imported 9.0.299 Beta.01
authorIan Beckwith <ianb@erislabs.net>
Fri, 17 Jun 2011 19:28:05 +0000 (20:28 +0100)
committerIan Beckwith <ianb@erislabs.net>
Fri, 17 Jun 2011 19:28:05 +0000 (20:28 +0100)
68 files changed:
COPYING.TXT
ck_crp.c
ck_ssl.c
ck_ssl.h
ckaaaa.txt [deleted file]
ckc211.txt [deleted file]
ckc299.txt [new file with mode: 0644]
ckcasc.h
ckcbwr.txt [deleted file]
ckccfg.txt [deleted file]
ckcdeb.h
ckcfn2.c
ckcfn3.c
ckcfns.c
ckcftp.c
ckcker.h
ckclib.c
ckclib.h
ckcmai.c
ckcnet.c
ckcnet.h
ckcplm.txt [deleted file]
ckcpro.c [new file with mode: 0644]
ckcpro.w
ckcsig.h
ckctel.c
ckctel.h
ckcuni.c
ckcuni.h
ckcxla.h
ckermit.ini [deleted file]
ckermit70.txt [deleted file]
ckermit80.txt [deleted file]
ckermod.ini [deleted file]
ckuat2.h
ckuath.c
ckuath.h
ckubwr.txt [deleted file]
ckucmd.c
ckucmd.h
ckucns.c
ckucon.c
ckudia.c
ckufio.c
ckuins.txt [deleted file]
ckuker.nr
ckupty.c
ckupty.h
ckuscr.c
ckusig.c
ckusig.h
ckutio.c
ckututor.txt [deleted file]
ckuus2.c
ckuus3.c
ckuus4.c
ckuus5.c
ckuus6.c
ckuus7.c
ckuusr.c
ckuusr.h
ckuusx.c
ckuusy.c
ckuver.h
ckuxla.c
ckuxla.h
ckwart.c
makefile

index da5d39e..9e8180a 100644 (file)
-THE C-KERMIT 7.0 AND 8.0 LICENSE
-
-  Last update: Thu May  1 13:52:15 2003
-
-This is the new C-Kermit 7.0 and 8.0 license.  The intention is to allow
-C-Kermit to be distributed with "free" operating systems such as GNU/Linux,
-FreeBSD, NetBSD, OpenBSD, The Hurd, etc, even when the distributions
-themselves (such as Red Hat or Caldera) might be sold and/or might include
-applications that are not free, and yet still require a license to include
-C-Kermit in or with "non-free" products such as commercial OS's, commercial
-software packages, embedded systems, and hardware (other than general-purpose
-computers preloaded with "free" operating systems), since these licenses
-furnish a large portion of the Kermit Project's funding.
-
-There have been some questions about the provision in Clause (A) that:
-
-                                                                  The
-    C-Kermit source code may not be changed without the consent of the
-    Kermit Project, which will not be unreasonably withheld (this is
-    simply a matter of keeping a consistent and supportable code base).
-
-The intention of this clause is primarily to make sure that anybody who
-makes modifications sends them back to us, since we are the ones have to
-support C-Kermit, and so we can carry them through to future releases (so
-you don't have to make the same changes again and again).
-
-Secondarily it is to protect Columbia University in the unlikely event of
-modifications made with deliberate intent to offend or cause damage.
-
-Any redistributor of C-Kermit under Clause (A) below should rest assured
-there is no intention of preventing them from constructing a distribution in
-the appropriate format (RPM or whatever) for their product or from issuing
-any patches required for their products; we simply want to be informed so we
-can maintain a consistent code base and a solid, supportable software
-package.  We are happy to work with any redistributor an any issues that
-concern them.  If you have questions, send them to kermit@columbia.edu.
-
-Note: All changes to this file since 1 January 2000 (the C-Kermit 7.0
-release date) are above; the license itself has not changed, except to
-update the most recent copyright date.
-
-(Begin)
-
-Copyright (C) 1985, 2003,
-  The Trustees of Columbia University in the City of New York.
-  All rights reserved.
-
-PERMISSIONS:
-
-The C-Kermit software may be obtained directly from the Kermit Project at
-Columbia University (or from any source explicitly licensed by the Kermit
-Project or implicitly licensed by Clause (A) below) by any individual for
-his or her OWN USE, and by any company or other organization for its own
-INTERNAL DISTRIBUTION and use, including installation on servers that are
-accessed by customers or clients, WITHOUT EXPLICIT LICENSE.
-
-Conditions for REDISTRIBUTION are as follows:
-
-(A) The C-Kermit software, in source and/or binary form, may be
-    included WITHOUT EXPLICIT LICENSE in distributions of OPERATING
-    SYSTEMS that have OSI (Open Source Initiative, www.opensource.org)
-    approved licenses, even if non-Open-Source applications (but not
-    operating systems) are included in the same distribution.  Such
-    distributions include, but are not limited to, CD-ROM, FTP site,
-    Web site, or preinstalled software on a new GENERAL-PURPOSE
-    computer, as long as the primary character of the distribution is
-    an Open Source operating system with accompanying utilities.  The
-    C-Kermit source code may not be changed without the consent of the
-    Kermit Project, which will not be unreasonably withheld (this is
-    simply a matter of keeping a consistent and supportable code base).
-
-(B) Inclusion of C-Kermit software in whole or in part, in any form, in
-    or with any product not covered by Clause (A), or its distribution
-    by any commercial enterprise to its actual or potential customers
-    or clients except as in Clause (A), requires a license from the
-    Kermit Project, Columbia University; contact kermit@columbia.edu.
-
-The name of Columbia University may not be used to endorse or promote
-products derived from or including the C-Kermit software without specific
-prior written permission.
-
-DISCLAIMER:
-
-  THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE
-  TRUSTEES OF COLUMBIA UNIVERSITY IN THE CITY OF NEW YORK AS TO ITS
-  FITNESS FOR ANY PURPOSE, AND WITHOUT WARRANTY BY THE TRUSTEES OF
-  COLUMBIA UNIVERSITY IN THE CITY OF NEW YORK OF ANY KIND, EITHER
-  EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
-  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-  THE TRUSTEES OF COLUMBIA UNIVERSITY IN THE CITY OF NEW YORK SHALL NOT
-  BE LIABLE FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL,
-  OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT OF OR
-  IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN IF IT HAS BEEN OR IS
-  HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.  YOU SHALL
-  INDEMNIFY AND HOLD HARMLESS THE TRUSTEES OF COLUMBIA UNIVERSITY IN
-  THE CITY OF NEW YORK, ITS EMPLOYEES AND AGENTS FROM AND AGAINST ANY
-  AND ALL CLAIMS, DEMANDS, LOSS, DAMAGE OR EXPENSE (INCLUDING
-  ATTORNEYS' FEES) ARISING OUT OF YOUR USE OF THIS SOFTWARE.
-
-The above copyright notice, permissions notice, and disclaimer may not be
-removed, altered, or obscured and shall be included in all copies of the
-C-Kermit software.  The Trustees of Columbia University in the City of
-New York reserve the right to revoke this permission if any of the terms
-of use set forth above are breached.
-
-(End)
+THE C-KERMIT 9.0 LICENSE
+
+  Thu Jun  2 12:37:40 2011
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+ + Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+ + Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in
+   the documentation and/or other materials provided with the
+   distribution.
+ + Neither the name of the <ORGANIZATION> nor the names of its
+   contributors may be used to endorse or promote products derived
+   from this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
index c35afd0..ec99cdf 100644 (file)
--- a/ck_crp.c
+++ b/ck_crp.c
@@ -1,8 +1,8 @@
-char *ckcrpv = "Encryption Engine, 8.0.114,  9 Oct 2003";
+char *ckcrpv = "Encryption Engine, 9.0.117, 19 Mar 2010";
 /*
   C K _ C R P . C  -  Cryptography for C-Kermit"
 
-  Copyright (C) 1998, 2004,
+  Copyright (C) 1998, 2010,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -88,6 +88,10 @@ static char * tmpstring = NULL;
 #endif /* CAST_EXPORT_ENCRYPTION */
 #endif /* CAST_OR_EXPORT */
 
+#ifdef MACOSX
+#undef LIBDES
+#endif /* MACOSX */
+
 #ifdef CRYPT_DLL
 int cmd_quoting = 0;
 
@@ -118,7 +122,7 @@ telopt(opt) int opt; {
 #endif /* TELOPT_MACRO */
 
 static int (*p_ttol)(char *,int)=NULL;
-static int (*p_dodebug)(int,char *,char *,long)=NULL;
+static int (*p_dodebug)(int,char *,char *,CK_OFF_T)=NULL;
 static int (*p_dohexdump)(char *,char *,int)=NULL;
 static void (*p_tn_debug)(char *)=NULL;
 static int (*p_vscrnprintf)(char *, ...)=NULL;
@@ -152,7 +156,7 @@ ttol(char * s, int n)
 }
 
 int
-dodebug(int flag, char * s1, char * s2, long n)
+dodebug(int flag, char * s1, char * s2, CK_OFF_T n)
 {
     if ( p_dodebug )
         return(p_dodebug(flag,s1,s2,n));
@@ -279,6 +283,14 @@ extern krb5_context k5_context;
 #endif /* CRYPT_DLL */
 
 #ifdef LIBDES
+#ifdef MACOSX
+#define des_new_random_key            ck_des_new_random_key
+#define des_set_random_generator_seed ck_des_set_random_generator_seed
+#define des_key_sched                 ck_des_key_sched
+#define des_ecb_encrypt               ck_des_ecb_encrypt
+#define des_string_to_key             ck_des_string_to_key
+#define des_fixup_key_parity          ck_des_fixup_key_parity
+#endif /* MACOSX */
 #ifndef UNIX
 #define des_new_random_key            des_random_key
 #define des_set_random_generator_seed des_random_seed
@@ -359,6 +371,7 @@ Block key;
 
 #ifdef UNIX
 #ifdef LIBDES
+#ifndef MACOSX
 /* These functions are not part of Eric Young's DES library */
 /* _unix_time_gmt_unixsec                                  */
 /* _des_set_random_generator_seed                          */
@@ -402,6 +415,7 @@ des_new_random_key(Block B)
     return(rc);
 }
 
+#endif /* MACOSX */
 #endif /* LIBDES */
 #endif /* UNIX */
 #endif /* CK_DES */
@@ -798,7 +812,7 @@ decrypt_ks_hack(buf,cnt) unsigned char *buf; int cnt;
         buf[len] = decrypt_input(buf[len]);
 
 #ifdef DEBUG
-    hexdump("decrypt ks hack", buf, cnt);
+    ckhexdump("decrypt ks hack", buf, cnt);
 #endif
     return 1;
 }
@@ -1057,7 +1071,10 @@ encrypt_support(_typelist, _cnt) unsigned char * _typelist; int _cnt;
     remote_supports_decrypt = 0;
 
     while (cnt-- > 0) {
+       debug(F101,"XXX cnt","",cnt);
         type = *typelist++;
+       debug(F101,"XXX type","",type);
+       debug(F101,"XXX ENCTYPE_ANY","",ENCTYPE_ANY);
         if ( EncryptType == ENCTYPE_ANY ||
              EncryptType == type ) {
 #ifdef DEBUG
@@ -1075,13 +1092,16 @@ encrypt_support(_typelist, _cnt) unsigned char * _typelist; int _cnt;
             }
         }
     }
+    debug(F101,"XXX use_type","",use_type);
     if (use_type) {
         ep = findencryption(use_type);
         if (!ep) {
             debug(F111,"encrypt_support","findencryption == NULL",use_type);
             return(-1);
         }
+       debug(F100,"XXX ep not NULL","",0);
         type = ep->start ? (*ep->start)(DIR_ENCRYPT, 0) : 0;
+       debug(F101,"XXX new type","",type);
 #ifdef DEBUG
         if (encrypt_debug_mode) {
             sprintf(dbgbuf, ">>>(*ep->start)() %s returned %d (%s)\n",
@@ -1497,7 +1517,7 @@ encrypt_send_keyid(dir, keyid, keylen, saveit)
         sprintf(tn_msg,"TELNET SENT SB %s %s ",
                  TELOPT(TELOPT_ENCRYPTION),
                  (dir == DIR_ENCRYPT) ? "ENC-KEYID" : "DEC-KEYID"); /* safe */
-        tn_hex(tn_msg,TN_MSG_LEN,&str_keyid[4],strp-str_keyid-2-4);
+        tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&str_keyid[4],strp-str_keyid-2-4);
         ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
         debug(F100,tn_msg,"",0);
         if (tn_deb || debses) tn_debug(tn_msg);
@@ -1598,7 +1618,7 @@ encrypt_start_output(type) int type;
             int i;
             sprintf(tn_msg,"TELNET SENT SB %s START ",
                      TELOPT(TELOPT_ENCRYPTION));                /* safe */
-            tn_hex(tn_msg,TN_MSG_LEN,&str_start[4],p-str_start-2-4);
+            tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&str_start[4],p-str_start-2-4);
             ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
             debug(F100,tn_msg,"",0);
             if (tn_deb || debses) tn_debug(tn_msg);
@@ -1721,7 +1741,7 @@ encrypt_send_request_start()
         int i;
         sprintf(tn_msg,"TELNET SENT SB %s REQUEST-START ",
                  TELOPT(TELOPT_ENCRYPTION));                    /* safe */
-        tn_hex(tn_msg,TN_MSG_LEN,&str_start[4],p-str_start-2-4);
+        tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&str_start[4],p-str_start-2-4);
         ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
         debug(F100,tn_msg,"",0);
         if (tn_deb || debses) tn_debug(tn_msg);
@@ -2132,8 +2152,9 @@ fb64_start(fbp, dir, server)
             sprintf(tn_msg,
                      "TELNET SENT SB %s IS %s FB64_IV ",
                      TELOPT(fbp->fb_feed[2]),
-                     enctype_names[fbp->fb_feed[4]]);                   /* safe */
-            tn_hex(tn_msg,TN_MSG_LEN,&fbp->fb_feed[6],(p-fbp->fb_feed)-2-6);
+                     enctype_names[fbp->fb_feed[4]]); /* safe */
+            tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&fbp->fb_feed[6],
+               (p-fbp->fb_feed)-2-6);
             ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
             debug(F100,tn_msg,"",0);
             if (tn_deb || debses) tn_debug(tn_msg);
@@ -2220,8 +2241,9 @@ fb64_is(data, cnt, fbp)
             sprintf(tn_msg,
                      "TELNET SENT SB %s REPLY %s FB64_IV_OK ",
                      TELOPT(fbp->fb_feed[2]),
-                     enctype_names[fbp->fb_feed[4]]);           /* safe */
-            tn_hex(tn_msg,TN_MSG_LEN,&fbp->fb_feed[6],(p-fbp->fb_feed)-2-6);
+                     enctype_names[fbp->fb_feed[4]]); /* safe */
+            tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&fbp->fb_feed[6],
+               (p-fbp->fb_feed)-2-6);
             ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
             debug(F100,tn_msg,"",0);
             if (tn_deb || debses) tn_debug(tn_msg);
@@ -2262,8 +2284,9 @@ fb64_is(data, cnt, fbp)
             sprintf(tn_msg,
                      "TELNET SENT SB %s REPLY %s FB64_IV_BAD ",
                      TELOPT(fbp->fb_feed[2]),
-                     enctype_names[fbp->fb_feed[4]]);           /* safe */
-            tn_hex(tn_msg,TN_MSG_LEN,&fbp->fb_feed[6],(p-fbp->fb_feed)-2-6);
+                     enctype_names[fbp->fb_feed[4]]); /* safe */
+            tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&fbp->fb_feed[6],
+               (p-fbp->fb_feed)-2-6);
             ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
             debug(F100,tn_msg,"",0);
             if (tn_deb || debses) tn_debug(tn_msg);
@@ -2381,7 +2404,7 @@ fb64_session(key, server, fbp)
 
     if (!key || key->length < sizeof(Block)) {
         CHAR buf[80];
-        sprintf(buf,"Can't set DES session key (%d < %d)",
+        sprintf((char *)buf,"Can't set DES session key (%d < %d)",
                 key ? key->length : 0, sizeof(Block));          /* safe */
 #ifdef DEBUG
         if (encrypt_debug_mode)
@@ -2433,7 +2456,7 @@ fb64_session(key, server, fbp)
     }
 
     memset(fbp->krbdes_sched,0,sizeof(Schedule));
-    hexdump("fb64_session_key",fbp->krbdes_key,8);
+    ckhexdump("fb64_session_key",fbp->krbdes_key,8);
 
     rc = des_key_sched(fbp->krbdes_key, fbp->krbdes_sched);
     if ( rc == -1 ) {
@@ -2450,7 +2473,7 @@ fb64_session(key, server, fbp)
                "Key Schedule not created by encryption",0);
     }
 
-    hexdump("fb64_session_key schedule",fbp->krbdes_sched,8*16);
+    ckhexdump("fb64_session_key schedule",fbp->krbdes_sched,8*16);
 #endif /* MIT_CURRENT */
     /*
     * Now look to see if krbdes_start() was was waiting for
@@ -2588,7 +2611,7 @@ fb64_stream_iv(seed, stp)
 
     memset(stp->str_sched,0,sizeof(Schedule));
 
-    hexdump("fb64_stream_iv",stp->str_ikey,8);
+    ckhexdump("fb64_stream_iv",stp->str_ikey,8);
 
 #ifndef MIT_CURRENT
     rc = des_key_sched(stp->str_ikey, stp->str_sched);
@@ -2605,7 +2628,7 @@ fb64_stream_iv(seed, stp)
         debug(F110,"fb64_stream_iv",
                "Key Schedule not created by encryption",0);
     }
-    hexdump("fb64_stream_iv schedule",stp->str_sched,8*16);
+    ckhexdump("fb64_stream_iv schedule",stp->str_sched,8*16);
 #endif /* MIT_CURRENT */
 
     stp->str_index = sizeof(Block);
@@ -2631,7 +2654,7 @@ fb64_stream_key(key, stp)
 
     memset(stp->str_sched,0,sizeof(Schedule));
 
-    hexdump("fb64_stream_key",key,8);
+    ckhexdump("fb64_stream_key",key,8);
 
     rc = des_key_sched(key, stp->str_sched);
     if ( rc == -1 ) {
@@ -2647,7 +2670,7 @@ fb64_stream_key(key, stp)
         debug(F110,"fb64_stream_key",
                "Key Schedule not created by encryption",0);
     }
-    hexdump("fb64_stream_key schedule",stp->str_sched,8*16);
+    ckhexdump("fb64_stream_key schedule",stp->str_sched,8*16);
 #endif /* MIT_CURRENT */
 
     memcpy(stp->str_output, stp->str_iv, sizeof(Block));
@@ -2958,8 +2981,9 @@ des3_fb64_start(fbp, dir, server)
             sprintf(tn_msg,
                      "TELNET SENT SB %s IS %s FB64_IV ",
                      TELOPT(fbp->fb_feed[2]),
-                     enctype_names[fbp->fb_feed[4]]);           /* safe */
-            tn_hex(tn_msg,TN_MSG_LEN,&fbp->fb_feed[6],(p-fbp->fb_feed)-2-6);
+                     enctype_names[fbp->fb_feed[4]]); /* safe */
+            tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&fbp->fb_feed[6],
+               (p-fbp->fb_feed)-2-6);
             ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
             debug(F100,tn_msg,"",0);
             if (tn_deb || debses) tn_debug(tn_msg);
@@ -3046,8 +3070,9 @@ des3_fb64_is(data, cnt, fbp)
             sprintf(tn_msg,
                      "TELNET SENT SB %s REPLY %s FB64_IV_OK ",
                      TELOPT(fbp->fb_feed[2]),
-                     enctype_names[fbp->fb_feed[4]]);           /* safe */
-            tn_hex(tn_msg,TN_MSG_LEN,&fbp->fb_feed[6],(p-fbp->fb_feed)-2-6);
+                     enctype_names[fbp->fb_feed[4]]); /* safe */
+            tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&fbp->fb_feed[6],
+               (p-fbp->fb_feed)-2-6);
             ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
             debug(F100,tn_msg,"",0);
             if (tn_deb || debses) tn_debug(tn_msg);
@@ -3088,8 +3113,9 @@ des3_fb64_is(data, cnt, fbp)
             sprintf(tn_msg,
                      "TELNET SENT SB %s REPLY %s FB64_IV_BAD ",
                      TELOPT(fbp->fb_feed[2]),
-                     enctype_names[fbp->fb_feed[4]]);           /* safe */
-            tn_hex(tn_msg,TN_MSG_LEN,&fbp->fb_feed[6],(p-fbp->fb_feed)-2-6);
+                     enctype_names[fbp->fb_feed[4]]); /* safe */
+            tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&fbp->fb_feed[6],
+               (p-fbp->fb_feed)-2-6);
             ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
             debug(F100,tn_msg,"",0);
             if (tn_deb || debses) tn_debug(tn_msg);
@@ -3208,8 +3234,8 @@ des3_fb64_session(key, server, fbp)
     keys2use = key->length / sizeof(Block);
     if (!key || (key->type == SK_DES) || (keys2use < 2)) {
         CHAR buf[80];
-        sprintf(buf,"Can't set 3DES session key (%d < %d)",
-                key ? key->length : 0, 2 * sizeof(Block));      /* safe */
+        sprintf((char *)buf,"Can't set 3DES session key (%d < %d)",
+                key ? key->length : 0, 2 * (int)sizeof(Block));        /* safe */
 #ifdef DEBUG
         if (encrypt_debug_mode)
             printf("%s\r\n",buf);
@@ -3236,8 +3262,8 @@ des3_fb64_session(key, server, fbp)
                  (void *) (key->data + 2*sizeof(Block)), sizeof(Block));
         break;
     }
-    hexdump("des3_session_key key->data",key->data,sizeof(Block));
-    hexdump("des3_session_key fbp->krbdes_key[0]",
+    ckhexdump("des3_session_key key->data",key->data,sizeof(Block));
+    ckhexdump("des3_session_key fbp->krbdes_key[0]",
             fbp->krbdes_key[0],
             sizeof(Block)
             );
@@ -3316,7 +3342,7 @@ des3_fb64_session(key, server, fbp)
             debug(F110,"des3_fb64_stream_iv",
                    "Key Schedule not created by encryption",0);
         }
-        hexdump("des3_fb64_session_key schedule",fbp->krbdes_sched[i],8*16);
+        ckhexdump("des3_fb64_session_key schedule",fbp->krbdes_sched[i],8*16);
     }
     /*
     * Now look to see if krbdes_start() was was waiting for
@@ -3454,7 +3480,7 @@ des3_fb64_stream_iv(seed, stp)
     for ( i=0;i<3;i++ ) {
         memset(stp->str_sched[i],0,sizeof(Schedule));
 
-        hexdump("des3_fb64_stream_iv",stp->str_ikey[i],8);
+        ckhexdump("des3_fb64_stream_iv",stp->str_ikey[i],8);
 
         rc = des_key_sched(stp->str_ikey[i], stp->str_sched[i]);
         if ( rc == -1 ) {
@@ -3470,7 +3496,7 @@ des3_fb64_stream_iv(seed, stp)
             debug(F110,"des3_fb64_stream_iv",
                    "Key Schedule not created by encryption",0);
         }
-        hexdump("des3_fb64_stream_iv schedule",stp->str_sched[i],8*16);
+        ckhexdump("des3_fb64_stream_iv schedule",stp->str_sched[i],8*16);
     }
     stp->str_index = sizeof(Block);
 }
@@ -3487,7 +3513,7 @@ des3_fb64_stream_key(key, stp)
 
         memset(stp->str_sched[i],0,sizeof(Schedule));
 
-        hexdump("des3_fb64_stream_key",key[i],8);
+        ckhexdump("des3_fb64_stream_key",key[i],8);
 
         rc = des_key_sched(key[i], stp->str_sched[i]);
         if ( rc == -1 ) {
@@ -3503,7 +3529,7 @@ des3_fb64_stream_key(key, stp)
             debug(F110,"des3_fb64_stream_key",
                    "Key Schedule not created by encryption",0);
         }
-        hexdump("des3_fb64_stream_key schedule",stp->str_sched[i],8*16);
+        ckhexdump("des3_fb64_stream_key schedule",stp->str_sched[i],8*16);
     }
 
     memcpy(stp->str_output, stp->str_iv, sizeof(Block));
@@ -4298,7 +4324,7 @@ cast_fb64_session(key, server, fbp, fs)
 
     if (!key || key->length < klen) {
         CHAR buf[80];
-        sprintf(buf,"Can't set CAST session key (%d < %d)",
+        sprintf((char *)buf,"Can't set CAST session key (%d < %d)",
                 key ? key->length : 0, klen);                   /* safe */
 #ifdef DEBUG
         if (encrypt_debug_mode)
index 7b53770..561e056 100644 (file)
--- a/ck_ssl.c
+++ b/ck_ssl.c
@@ -1,8 +1,8 @@
-char *cksslv = "SSL/TLS support, 8.0.221, 26 Feb 2004";
+char *cksslv = "SSL/TLS support, 9.0.227, 04 Aug 2020";
 /*
   C K _ S S L . C --  OpenSSL Interface for C-Kermit
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2010,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -19,7 +19,7 @@ char *cksslv = "SSL/TLS support, 8.0.221, 26 Feb 2004";
   . Client certificate to user id routine
 
   Note: This code is written to be compatible with OpenSSL 0.9.6[abcdefgh]
-  and 0.9.7 beta 5.
+  and 0.9.7 beta 5 (and, presumably, later).
   It will also compile with version 0.9.5 although that is discouraged
   due to security weaknesses in that release.
 */
@@ -52,6 +52,8 @@ char * GetAppData(int);
 #endif
 #endif /* OS2 */
 
+extern int quiet;                      /* fdc - Mon Nov 28 11:44:15 2005 */
+
 static int ssl_installed = 1;
 #endif /* CK_SSL */
 int
@@ -153,6 +155,7 @@ SSL *ssl_con = NULL;
 int ssl_debug_flag = 0;
 int ssl_verbose_flag = 0;
 int ssl_only_flag = 0;
+int ssl_raw_flag = 0;
 int ssl_active_flag = 0;
 int ssl_verify_flag = SSL_VERIFY_PEER;
 int ssl_certsok_flag = 0;
@@ -173,6 +176,7 @@ char *ssl_rnd_file = NULL;
 SSL_CTX *tls_ctx = NULL;
 SSL *tls_con = NULL;
 int tls_only_flag = 0;
+int tls_raw_flag = 0;
 int tls_active_flag = 0;
 
 int ssl_initialized = 0;
@@ -188,6 +192,13 @@ extern char szHostName[], szUserNameRequested[], szUserNameAuthenticated[];
 
 _PROTOTYP(int X509_to_user,(X509 *, char *, int));
 
+static int verbosity = 0;              /* Message control */
+static VOID
+setverbosity() {
+    verbosity = ssl_verbose_flag;
+    if (quiet) verbosity = 0;
+}
+
 int
 #ifdef CK_ANSIC
 ssl_server_verify_callback(int ok, X509_STORE_CTX * ctx)
@@ -205,6 +216,8 @@ X509_STORE_CTX *ctx;
     if ( ssl_certsok_flag )
         return(1);
 
+    setverbosity();
+
     error=X509_STORE_CTX_get_error(ctx);
     depth=X509_STORE_CTX_get_error_depth(ctx);
     xs=X509_STORE_CTX_get_current_cert(ctx);
@@ -240,7 +253,7 @@ X509_STORE_CTX *ctx;
         goto return_time;
     }
 
-    if (ssl_verbose_flag && !inserver && depth != ssl_verify_depth) {
+    if (verbosity && !inserver && depth != ssl_verify_depth) {
         printf("[%d] Certificate Subject:\r\n%s\r\n",depth,subject);
         printf("[%d] Certificate Issuer:\r\n%s\r\n",depth,issuer);
         ssl_verify_depth = depth;
@@ -330,6 +343,8 @@ X509_STORE_CTX *ctx;
     int depth, error, len;
     X509 *xs;
 
+    setverbosity();
+
     xs=X509_STORE_CTX_get_current_cert(ctx);
     error=X509_STORE_CTX_get_error(ctx);
     depth=X509_STORE_CTX_get_error_depth(ctx);
@@ -396,7 +411,7 @@ X509_STORE_CTX *ctx;
     }
 #endif /* XN_FLAG_SEP_MULTILINE */
 
-    if (ssl_verbose_flag && depth != ssl_verify_depth) {
+    if (verbosity && depth != ssl_verify_depth) {
         printf("[%d] Certificate Subject:\r\n%s\r\n",depth,subject);
         printf("[%d] Certificate Issuer:\r\n%s\r\n",depth,issuer);
         ssl_verify_depth = depth;
@@ -697,6 +712,8 @@ int ret;
     if (inserver || !ssl_debug_flag)
         return;
 
+    setverbosity();
+
     switch ( where ) {
     case SSL_CB_CONNECT_LOOP:
         printf("SSL_connect:%s %s\r\n",
@@ -755,6 +772,8 @@ ssl_client_cert_callback(s, x509, pkey)
     EVP_PKEY ** pkey;
 #endif /* CK_ANSIC */
 {
+    setverbosity();
+
     if ( ssl_debug_flag ) {
         const char * cipher_list=SSL_get_cipher(s);
         printf("ssl_client_cert_callback called (%s)\r\n",
@@ -796,7 +815,6 @@ int keylength;
 #endif /* CK_ANSIC */
 {
     static RSA *rsa_tmp=NULL;
-    extern int quiet;
 
 #ifndef NO_RSA
     if (rsa_tmp == NULL)
@@ -994,7 +1012,6 @@ int keylength;
 {
     static DH *dh_tmp=NULL;
     BIO *bio=NULL;
-    extern int quiet;
 
 #ifndef NO_DH
     if (dh_tmp == NULL)
@@ -1028,6 +1045,9 @@ int keylength;
 static void
 ssl_display_comp(SSL * ssl)
 {
+    if ( quiet )                       /* fdc - Mon Nov 28 11:44:15 2005 */
+        return;
+
     if ( !ck_ssleay_is_installed() )
         return;
 
@@ -1056,6 +1076,9 @@ int verbose;
     const char *cipher_list;
     char buf[512]="";
 
+    if ( quiet )                       /* fdc - Mon Nov 28 11:44:15 2005 */
+        return(0);
+
     if ( !ck_ssleay_is_installed() )
         return(0);
 
@@ -1141,14 +1164,13 @@ int
 tls_load_certs(SSL_CTX * ctx, SSL * con, int server)
 {
     int rc = 1;
-    extern int quiet;
 
     if ( !ck_ssleay_is_installed() )
         return(0);
 
-    debug(F111,"tls_load_certs","SSL_CTX",ctx);
-    debug(F111,"tls_load_certs","SSL",con);
-    debug(F111,"tls_load_certs","server",server);
+    debug(F110,"tls_load_certs","SSL_CTX",0);
+    debug(F110,"tls_load_certs","SSL",0);
+    debug(F110,"tls_load_certs","server",0);
 
     if ( con ) {
         if (ssl_rsa_cert_file) {
@@ -1336,10 +1358,19 @@ ssl_once_init()
 #endif /* CK_ANSIC */
 {
     COMP_METHOD * cm;
+    char * s;
 
     if ( !ck_ssleay_is_installed() )
         return;
-
+/*
+  OpenSSL does not provide for ABI compatibility between releases prior
+  to version 1.0.0.  If the version does not match, it is not safe to
+  assume that any function you call takes the same parameters or does
+  the same thing with them.  Removing this test prior to the OpenSSL 1.0.0
+  release will result in an increase in unexplained or incorrect behaviors.
+  The test should be revised once OpenSSL 1.0.0 is released and we see what
+  its claims are as to ABI compatibility.
+*/
     debug(F111,"Kermit built for OpenSSL",OPENSSL_VERSION_TEXT,SSLEAY_VERSION_NUMBER);
 #ifndef OS2ONLY
     debug(F111,"OpenSSL Library",SSLeay_version(SSLEAY_VERSION),
@@ -1357,8 +1388,49 @@ ssl_once_init()
         ssl_installed = 0;
         debug(F111,"OpenSSL Version does not match.  Built with",
                SSLeay_version(SSLEAY_VERSION),SSLEAY_VERSION_NUMBER);
-        printf("?OpenSSL libraries do not match required version.");
-        printf("  SSL\\TLS support disabled\r\n\r\n");
+        printf("?OpenSSL libraries do not match required version:\r\n");
+        printf("  . C-Kermit built with %s\r\n",OPENSSL_VERSION_TEXT);
+        printf("  . Version found  %s\r\n",SSLeay_version(SSLEAY_VERSION));
+        printf("  OpenSSL versions prior to 1.0.0 must be the same.\r\n");    
+
+       s = "R";
+#ifdef SOLARIS
+       printf("  Set CD_LIBRARY_PATH for %s.\r\n",OPENSSL_VERSION_TEXT);
+       s = " Or r";
+#endif /* SOLARIS */
+
+#ifdef HPUX
+       printf("  Set SHLIB_PATH for %s.\r\n",OPENSSL_VERSION_TEXT);
+       s = " Or r";
+#endif /* HPUX */
+
+#ifdef AIX
+       printf("  Set LIBPATH for %s.\r\n",OPENSSL_VERSION_TEXT);
+       s = " Or r";
+#endif /* AIX */
+
+#ifdef LINUX
+       printf("  Set LD_LIBRARY_PATH for %s.\r\n",OPENSSL_VERSION_TEXT);
+       s = " Or r";
+#endif /* LINUX */
+
+        printf(" %sebuild C-Kermit from source on this computer to make \
+versions agree.\r\n",s);
+
+#ifdef KTARGET
+       {
+           char * s;
+           s = KTARGET;
+           if (!s) s = "";
+           if (!*s) s = "(unknown)";
+           printf("  C-Kermit makefile target: %s\r\n",s);
+       }
+#endif /* KTARGET */
+        printf("  Or if that is what you did then try to find out why\r\n");
+        printf("  the program loader (image activator) is choosing a\r\n");
+        printf("  different OpenSSL library than the one specified in \
+the build.\r\n\r\n");
+        printf("  All SSL/TLS features disabled.\r\n\r\n");
         bleep(BP_FAIL);
 #ifdef SSLDLL
         ck_ssl_unloaddll();
@@ -1369,8 +1441,8 @@ ssl_once_init()
 #endif /* OS2ONLY */
 
     /* init things so we will get meaningful error messages
-    * rather than numbers
-    */
+     * rather than numbers
+     */
     SSL_load_error_strings();
 
 #ifdef SSHBUILTIN
@@ -2383,8 +2455,12 @@ ssl_get_dNSName(ssl) SSL * ssl;
         for (i = 0; i < sk_GENERAL_NAME_num(ialt); i++) {
             gen = sk_GENERAL_NAME_value(ialt, i);
             if (gen->type == GEN_DNS) {
-                if(!gen->d.ia5 || !gen->d.ia5->length)
-                    break;
+                if (!gen->d.ia5 || !gen->d.ia5->length)
+                 break;
+                if (strlen(gen->d.ia5->data) != gen->d.ia5->length) {
+                    /* Ignoring IA5String containing null character */
+                    continue;
+                }
                 dns = malloc(gen->d.ia5->length + 1);
                 if (dns) {
                     memcpy(dns, gen->d.ia5->data, gen->d.ia5->length);
@@ -2402,21 +2478,32 @@ cleanup:
 }
 
 char *
-ssl_get_commonName(ssl) SSL * ssl;
-{
+ssl_get_commonName(ssl) SSL * ssl; {
     static char name[256];
+    int name_text_len;
     int err;
     X509 *server_cert;
 
+    name_text_len = 0;
     if (server_cert = SSL_get_peer_certificate(ssl)) {
-        err = X509_NAME_get_text_by_NID(X509_get_subject_name(server_cert),
-                NID_commonName, name, sizeof(name));
+        name_text_len =
+           X509_NAME_get_text_by_NID(X509_get_subject_name(server_cert),
+                                     NID_commonName, name, sizeof(name));
         X509_free(server_cert);
     }
+    if (name_text_len <= 0) {
+       /* Common Name was empty or not retrieved */
+        err = 0;
+    } else if (strlen(name) != name_text_len) {
+        /* Ignoring Common Name containing null character */
+       err = 0;
+    } else {
+       err = 1;
+    }
     if (err > 0)
-        return name;
+      return name;
     else
-        return NULL;
+      return NULL;
 }
 
 char *
@@ -2681,8 +2768,12 @@ tls_get_SAN_objs(SSL * ssl, int type)
              * with one and linked to the other we use this hack.
              */
             if ((gen->type | V_ASN1_CONTEXT_SPECIFIC) == (type | V_ASN1_CONTEXT_SPECIFIC)) {
-                if(!gen->d.ia5 || !gen->d.ia5->length)
-                    break;
+                if (!gen->d.ia5 || !gen->d.ia5->length)
+                 break;
+                if (strlen(gen->d.ia5->data) != gen->d.ia5->length) {
+                    /* Ignoring IA5String containing null character */
+                    continue;
+                }
                 objs[j] = malloc(gen->d.ia5->length + 1);
                 if (objs[j]) {
                     memcpy(objs[j], gen->d.ia5->data, gen->d.ia5->length);
@@ -2703,7 +2794,7 @@ eject:
 static int
 dNSName_cmp(const char *host, const char *dNSName)
 {
-    int c1 = 0, c2 = 0, num_comp, rv = -1;
+    int c1 = 1, c2 = 1, num_comp, rv = -1;
     char *p, *p1, *p2, *host_copy=NULL, *dNSName_copy=NULL;
 
     /* first we count the number of domain name components in both parameters.
@@ -2765,6 +2856,7 @@ show_hostname_warning(char *s1, char *s2)
 {
     char prefix[1024];
     int ok = 1;
+    setverbosity();
     ckmakxmsg(prefix,1024,
               "Warning: Hostname (\"", s1, 
               "\") does not match server's certificate (\"", s2, "\")",
@@ -2773,25 +2865,31 @@ show_hostname_warning(char *s1, char *s2)
         ok = uq_ok(prefix,
                     "Continue? (Y/N) ",
                     3, NULL, 0);
-    else if (ssl_verbose_flag)
+    else if (verbosity)
         printf(prefix);
     return(ok);
 }
 
+#ifndef OSF50
 #ifndef HPUX10
 #ifndef HPUX1100
 #ifndef SCO_OSR505
 #ifndef OpenBSD
 #ifndef FREEBSD4
+#ifndef NETBSD15
 #ifndef LINUX
 #ifndef AIX41
 #ifndef UW7
+#ifndef IRIX65
 #ifndef SOLARIS9
 #ifndef SOLARIS8
 #ifndef SOLARIS7
+#ifndef MACOSX
 #ifdef DEC_TCPIP
 #define inet_aton INET_ATON
 #endif /* DEC_TCPIP */
+
+#ifndef NO_DCL_INET_ATON
 static int
 inet_aton(char * ipaddress, struct in_addr * ia) {
     struct stringarray * q;
@@ -2811,17 +2909,23 @@ inet_aton(char * ipaddress, struct in_addr * ia) {
     }
     return(0);
 }
+#endif /* NO_DCL_INET_ATON */
+
+#endif /* MACOSX */
 #endif /* SOLARIS7 */
 #endif /* SOLARIS8 */
 #endif /* SOLARIS9 */
+#endif /* IRIX65 */
 #endif /* UW7 */
 #endif /* AIX41 */
 #endif /* LINUX */
+#endif /* NETBSD15 */
 #endif /* FREEBSD4 */
 #endif /* OpenBSD */
 #endif /* SCO_OSR505 */
 #endif /* HPUX1100 */
 #endif /* HPUX10 */
+#endif /* OSF50 */
 
 int
 ssl_check_server_name(SSL * ssl, char * hostname)
@@ -2833,7 +2937,8 @@ ssl_check_server_name(SSL * ssl, char * hostname)
     struct in_addr ia;
     int rv;
 
-    if (ssl_verbose_flag && !inserver) {
+    setverbosity();
+    if (verbosity && !inserver) {
         if (dNSName = tls_get_SAN_objs(ssl,GEN_DNS)) {
             int i = 0;
             for (i = 0; dNSName[i]; i++) {
@@ -3082,6 +3187,7 @@ ssl_reply(how,data,cnt) int how; unsigned char *data; int cnt;
 {
     char * str=NULL;
 
+    setverbosity();
     data += 4;                          /* Point to status byte */
     cnt  -= 4;
 
@@ -3094,7 +3200,7 @@ ssl_reply(how,data,cnt) int how; unsigned char *data; int cnt;
     case SSL_ACCEPT:
         if (tn_deb || debses)
             tn_debug("[SSL - handshake starting]");
-        else if ( ssl_verbose_flag )
+        else if ( verbosity )
             printf("[SSL - handshake starting]\r\n");
         debug(F110,"ssl_reply","[SSL - handshake starting]",0);
 
@@ -3103,7 +3209,7 @@ ssl_reply(how,data,cnt) int how; unsigned char *data; int cnt;
             if (ssl_dummy_flag) {
                 if (tn_deb || debses)
                     tn_debug("[SSL - Dummy Connected]");
-                else if ( ssl_verbose_flag ) {
+                else if ( verbosity ) {
                     printf("[SSL - Dummy Connected]\r\n");
                 }
                 debug(F110,"ssl_reply","[SSL - Dummy Connected]",0);
@@ -3120,7 +3226,7 @@ ssl_reply(how,data,cnt) int how; unsigned char *data; int cnt;
                     len = BIO_read(bio_err,ssl_err,SSL_ERR_BFSZ);
                     ssl_err[len < SSL_ERR_BFSZ ? len : SSL_ERR_BFSZ] = '\0';
                     printf(ssl_err);
-                } else if ( ssl_verbose_flag ) {
+                } else if ( verbosity ) {
                     printf("[SSL - FAILED]\r\n");
                     ERR_print_errors(bio_err);
                     len = BIO_read(bio_err,ssl_err,SSL_ERR_BFSZ);
@@ -3134,13 +3240,13 @@ ssl_reply(how,data,cnt) int how; unsigned char *data; int cnt;
             } else {
                 if (tn_deb || debses)
                     tn_debug("[SSL - OK]");
-                else if ( ssl_verbose_flag ) {
+                else if ( verbosity ) {
                     printf("[SSL - OK]\r\n");
                 }
                 debug(F110,"ssl_reply","[SSL - OK]",0);
 
                 ssl_active_flag = 1;
-                ssl_display_connect_details(ssl_con,0,ssl_verbose_flag);
+                ssl_display_connect_details(ssl_con,0,verbosity);
             }
         }
         auth_finished(AUTH_UNKNOWN);
@@ -3151,7 +3257,7 @@ ssl_reply(how,data,cnt) int how; unsigned char *data; int cnt;
         if (tn_deb || debses) {
             tn_debug(
                  "[SSL - failed to switch on SSL - trying plaintext login]");
-        } else if ( ssl_verbose_flag ) {
+        } else if ( verbosity ) {
             printf("[SSL - failed to switch on SSL]\r\n");
             printf("Trying plaintext login:\r\n");
         }
@@ -3175,6 +3281,7 @@ ssl_is(data,cnt) unsigned char *data; int cnt;
     if ((cnt -= 4) < 1)
         return AUTH_FAILURE;
 
+    setverbosity();
     data += 4;
     switch(*data++) {
     case SSL_START:
@@ -3187,7 +3294,7 @@ ssl_is(data,cnt) unsigned char *data; int cnt;
 
             if (tn_deb || debses)
                 tn_debug("[SSL - handshake starting]");
-            else if ( ssl_verbose_flag )
+            else if ( verbosity )
                 printf("[SSL - handshake starting]\r\n");
             debug(F110,"ssl_is","[SSL - handshake starting]",0);
 
@@ -3198,7 +3305,7 @@ ssl_is(data,cnt) unsigned char *data; int cnt;
             if (ssl_dummy_flag) {
                 if (tn_deb || debses)
                     tn_debug("[SSL - Dummy Connected]");
-                else if ( ssl_verbose_flag ) {
+                else if ( verbosity ) {
                     printf("[SSL - Dummy Connected]\r\n");
                 }
                 debug(F110,"ssl_is","[SSL - Dummy Connected]",0);
@@ -3217,7 +3324,7 @@ ssl_is(data,cnt) unsigned char *data; int cnt;
                     tn_debug(errbuf);
                 else if ( ssl_debug_flag )
                     printf("%s\r\n",errbuf);
-                else if ( ssl_verbose_flag )
+                else if ( verbosity )
                     printf("[SSL - SSL_accept error]\r\n");
 
                 debug(F110,"ssl_is",errbuf,0);
@@ -3229,12 +3336,12 @@ ssl_is(data,cnt) unsigned char *data; int cnt;
 
             if (tn_deb || debses)
                 tn_debug("[SSL - OK]");
-            else if ( ssl_verbose_flag ) {
+            else if ( verbosity ) {
                 printf("[SSL - OK]\r\n");
             }
             debug(F110,"ssl_is","[SSL - OK]",0);
             ssl_active_flag = 1;
-            ssl_display_connect_details(ssl_con,1,ssl_verbose_flag);
+            ssl_display_connect_details(ssl_con,1,verbosity);
 
             /* now check to see that we got exactly what we
             * wanted from the caller ... if a certificate is
@@ -3294,6 +3401,7 @@ ck_tn_tls_negotiate(VOID)
     if ( !ck_ssleay_is_installed() )
         return(-1);
 
+    setverbosity();
     if (sstelnet) {
         /* server starts the TLS stuff now ... */
         if (!tls_only_flag) {
@@ -3304,14 +3412,14 @@ ck_tn_tls_negotiate(VOID)
 
             if (tn_deb || debses)
                 tn_debug("[TLS - handshake starting]");
-            else if ( ssl_verbose_flag )
+            else if ( verbosity )
                 printf("[TLS - handshake starting]\r\n");
             debug(F110,"ck_tn_tls_negotiate","[TLS - handshake starting]",0);
 
             if (ssl_dummy_flag) {
                 if (tn_deb || debses)
                     tn_debug("[TLS - Dummy Connected]");
-                else if ( ssl_verbose_flag ) {
+                else if ( verbosity ) {
                     printf("[TLS - Dummy Connected]\r\n");
                 }
                 debug(F110,"ck_tn_tls_negotiate","[TLS - Dummy Connected]",0);
@@ -3330,7 +3438,7 @@ ck_tn_tls_negotiate(VOID)
                     tn_debug(errbuf);
                 else if ( ssl_debug_flag )
                     printf("%s\r\n",errbuf);
-                else if ( ssl_verbose_flag )
+                else if ( verbosity )
                     printf("[TLS - SSL_accept error]\r\n");
 
                 debug(F110,"ck_tn_tls_negotiate",errbuf,0);
@@ -3340,13 +3448,13 @@ ck_tn_tls_negotiate(VOID)
 
             if (tn_deb || debses)
                 tn_debug("[TLS - OK]");
-            else if ( ssl_verbose_flag ) {
+            else if ( verbosity ) {
                 printf("[TLS - OK]\r\n");
             }
 
             debug(F110,"ck_tn_tls_negotiate","[TLS - OK]",0);
             tls_active_flag = 1;
-            ssl_display_connect_details(tls_con,1,ssl_verbose_flag);
+            ssl_display_connect_details(tls_con,1,verbosity);
 
 
 #ifdef SSL_KRB5
@@ -3408,7 +3516,7 @@ ck_tn_tls_negotiate(VOID)
                                            NID_commonName,str,
                                            256
                                            );
-                if ( ssl_verbose_flag )
+                if ( verbosity )
                     printf("[TLS - commonName=%s]\r\n",str);
 
                 X509_NAME_get_text_by_NID(X509_get_subject_name(peer),
@@ -3420,7 +3528,7 @@ ck_tn_tls_negotiate(VOID)
                                            str,
                                            256
                                            );
-                if ( ssl_verbose_flag )
+                if ( verbosity )
                     printf("[TLS - uniqueIdentifier=%s]\r\n",str);
 
                 /* Try to determine user name */
@@ -3455,7 +3563,7 @@ ck_tn_tls_negotiate(VOID)
 
         if (tn_deb || debses)
             tn_debug("[TLS - handshake starting]");
-        else if ( ssl_verbose_flag )
+        else if ( verbosity )
             printf("[TLS - handshake starting]\r\n");
         debug(F110,"ck_tn_tls_negotiate","[TLS - handshake starting]",0);
 
@@ -3466,7 +3574,7 @@ ck_tn_tls_negotiate(VOID)
             if (ssl_dummy_flag) {
                 if (tn_deb || debses)
                     tn_debug("[TLS - Dummy Connected]");
-                else if ( ssl_verbose_flag ) {
+                else if ( verbosity ) {
                     printf("[TLS - Dummy Connected]\r\n");
                 }
                 debug(F110,"ck_tn_tls_negotiate","[TLS - Dummy Connected]",0);
@@ -3487,7 +3595,7 @@ ck_tn_tls_negotiate(VOID)
                     len = BIO_read(bio_err,ssl_err,SSL_ERR_BFSZ);
                     ssl_err[len < SSL_ERR_BFSZ ? len : SSL_ERR_BFSZ] = '\0';
                     printf(ssl_err);
-                } else if ( ssl_verbose_flag ) {
+                } else if ( verbosity ) {
                     printf("[TLS - FAILED]\r\n");
                     ERR_print_errors(bio_err);
                     len = BIO_read(bio_err,ssl_err,SSL_ERR_BFSZ);
@@ -3510,7 +3618,7 @@ ck_tn_tls_negotiate(VOID)
                     {
                         if (tn_deb || debses)
                             tn_debug("[TLS - FAILED]");
-                        else if ( ssl_verbose_flag )
+                        else if ( verbosity )
                             printf("[TLS - FAILED]\r\n");
                         debug(F110,"ck_tn_tls_negotiate","[TLS - FAILED]",0);
                         auth_finished(AUTH_REJECT);
@@ -3522,7 +3630,7 @@ ck_tn_tls_negotiate(VOID)
                         if (!ok) {
                             if (tn_deb || debses)
                                 tn_debug("[TLS - FAILED]");
-                            else if ( ssl_verbose_flag )
+                            else if ( verbosity )
                                 printf("[TLS - FAILED]\r\n");
                             debug(F110,
                                    "ck_tn_tls_negotiate","[TLS - FAILED]",0);
@@ -3533,7 +3641,7 @@ ck_tn_tls_negotiate(VOID)
                 } else if (ssl_check_server_name(tls_con, szHostName)) {
                     if (tn_deb || debses)
                         tn_debug("[TLS - FAILED]");
-                    else if ( ssl_verbose_flag )
+                    else if ( verbosity )
                         printf("[TLS - FAILED]\r\n");
                     debug(F110,
                            "ck_tn_tls_negotiate","[TLS - FAILED]",0);
@@ -3569,11 +3677,11 @@ ck_tn_tls_negotiate(VOID)
 
             if (tn_deb || debses)
                 tn_debug("[TLS - OK]");
-            else if ( ssl_verbose_flag )
+            else if ( verbosity )
                 printf("[TLS - OK]\r\n");
             debug(F110,"ck_tn_tls_negotiate","[TLS - OK]",0);
 
-            ssl_display_connect_details(tls_con,0,ssl_verbose_flag);
+            ssl_display_connect_details(tls_con,0,verbosity);
         }
         auth_finished(AUTH_REJECT);
     }
@@ -3593,6 +3701,7 @@ ck_ssl_incoming(fd) int fd;
 
     int timo = 2000;
 
+    setverbosity();
     if ( !ck_ssleay_is_installed() )
         return(-1);
 
@@ -3603,7 +3712,7 @@ ck_ssl_incoming(fd) int fd;
     if (tls_only_flag) {
         if (tn_deb || debses)
             tn_debug("[TLS - handshake starting]");
-        else if ( ssl_verbose_flag )
+        else if ( verbosity )
             printf("[TLS - handshake starting]\r\n");
         debug(F110,"ck_ssl_incoming","[TLS - handshake starting]",0);
 
@@ -3621,7 +3730,7 @@ ck_ssl_incoming(fd) int fd;
                 tn_debug(errbuf);
             else if ( ssl_debug_flag )
                 printf("%s\r\n",errbuf);
-            else if ( ssl_verbose_flag )
+            else if ( verbosity )
                 printf("[TLS - SSL_accept error]\r\n");
 
             debug(F110,"ck_ssl_incoming",errbuf,0);
@@ -3629,7 +3738,7 @@ ck_ssl_incoming(fd) int fd;
         } else {
             if (tn_deb || debses)
                 tn_debug("[TLS - OK]");
-            else if ( ssl_verbose_flag )
+            else if ( verbosity )
                 printf("[TLS - OK]\r\n");
             debug(F110,"ck_ssl_incoming","[TLS - OK]",0);
             tls_active_flag = 1;
@@ -3637,7 +3746,7 @@ ck_ssl_incoming(fd) int fd;
     } else if (ssl_only_flag) {
         if (tn_deb || debses)
             tn_debug("[SSL - handshake starting]");
-        else if ( ssl_verbose_flag )
+        else if ( verbosity )
             printf("[SSL - handshake starting]\r\n");
         debug(F110,"ck_ssl_incoming","[SSL - handshake starting]",0);
 
@@ -3655,7 +3764,7 @@ ck_ssl_incoming(fd) int fd;
                 tn_debug(errbuf);
             else if ( ssl_debug_flag )
                 printf("%s\r\n",errbuf);
-            else if ( ssl_verbose_flag )
+            else if ( verbosity )
                 printf("[SSL - SSL_accept error]\r\n");
 
             debug(F110,"ck_ssl_incoming",errbuf,0);
@@ -3663,7 +3772,7 @@ ck_ssl_incoming(fd) int fd;
         } else {
             if (tn_deb || debses)
                 tn_debug("[SSL - OK]");
-            else if ( ssl_verbose_flag )
+            else if ( verbosity )
             printf("[SSL - OK]\r\n");
             debug(F110,"ssl_is","[SSL - OK]",0);
             ssl_active_flag = 1;
@@ -3757,6 +3866,7 @@ ck_ssl_outgoing(fd) int fd;
 {
     int timo = 2000;
 
+    setverbosity();
     if ( !ck_ssleay_is_installed() )
         return(-1);
 
@@ -3774,7 +3884,7 @@ ck_ssl_outgoing(fd) int fd;
 #endif /* USE_CERT_CB */
         if (tn_deb || debses)
             tn_debug("[TLS - handshake starting]");
-        else if (ssl_verbose_flag)
+        else if (verbosity)
             printf("[TLS - handshake starting]\r\n");
         debug(F110,"ck_ssl_outgoing","[TLS - handshake starting]",0);
         if (SSL_connect(tls_con) <= 0) {
@@ -3790,7 +3900,7 @@ ck_ssl_outgoing(fd) int fd;
 
             if (tn_deb || debses)
                 tn_debug("[TLS - FAILED]");
-            else if ( ssl_verbose_flag )
+            else if ( verbosity )
                 printf("[TLS - FAILED]\r\n");
             debug(F110,"ck_ssl_outgoing","[TLS - FAILED]",0);
             netclos();
@@ -3806,7 +3916,7 @@ ck_ssl_outgoing(fd) int fd;
                     {
                         if (tn_deb || debses)
                             tn_debug("[TLS - FAILED]");
-                        else if ( ssl_verbose_flag )
+                        else if ( verbosity )
                             printf("[TLS - FAILED]\r\n");
                         debug(F110,"ck_tn_tls_negotiate","[TLS - FAILED]",0);
 
@@ -3820,7 +3930,7 @@ ck_ssl_outgoing(fd) int fd;
                         if (!ok) {
                             if (tn_deb || debses)
                                 tn_debug("[TLS - FAILED]");
-                            else if ( ssl_verbose_flag )
+                            else if ( verbosity )
                                 printf("[TLS - FAILED]\r\n");
                             debug(F110,
                                    "ck_tn_tls_negotiate","[TLS - FAILED]",0);
@@ -3831,7 +3941,7 @@ ck_ssl_outgoing(fd) int fd;
                 } else if (ssl_check_server_name(tls_con, szHostName)) {
                     if (tn_deb || debses)
                         tn_debug("[TLS - FAILED]");
-                    else if ( ssl_verbose_flag )
+                    else if ( verbosity )
                         printf("[TLS - FAILED]\r\n");
                     debug(F110,
                            "ck_tn_tls_negotiate","[TLS - FAILED]",0);
@@ -3839,12 +3949,12 @@ ck_ssl_outgoing(fd) int fd;
                     return -1;
                 }
             }
-
-            printf("[TLS - OK]\r\n");
             if (tn_deb || debses)
                 tn_debug("[TLS - OK]");
+            else if (!quiet)
+               printf("[TLS - OK]\r\n");
             debug(F110,"ck_ssl_outgoing","[TLS - OK]",0);
-            ssl_display_connect_details(tls_con,0,ssl_verbose_flag);
+            ssl_display_connect_details(tls_con,0,verbosity);
         }
     }
     /* if we are doing raw SSL then start it now ... */
@@ -3855,7 +3965,7 @@ ck_ssl_outgoing(fd) int fd;
 #endif /* USE_CERT_CB */
         if (tn_deb || debses)
             tn_debug("[SSL - handshake starting]");
-        else if ( ssl_verbose_flag )
+        else if ( verbosity )
             printf("[SSL - handshake starting]\r\n");
         debug(F110,"ck_ssl_outgoing","[SSL - handshake starting]",0);
         if (SSL_connect(ssl_con) <= 0) {
@@ -3868,7 +3978,7 @@ ck_ssl_outgoing(fd) int fd;
             }
             if (tn_deb || debses)
                 tn_debug("[SSL - FAILED]");
-            else if ( ssl_verbose_flag )
+            else if ( verbosity )
                 printf("[SSL - FAILED]\r\n");
             debug(F110,"ck_ssl_outgoing","[SSL - FAILED]",0);
             return(-1);
@@ -3884,7 +3994,7 @@ ck_ssl_outgoing(fd) int fd;
                     {
                         if (tn_deb || debses)
                             tn_debug("[SSL - FAILED]");
-                        else if ( ssl_verbose_flag )
+                        else if ( verbosity )
                             printf("[SSL - FAILED]\r\n");
                         debug(F110,"ck_tn_tls_negotiate","[SSL - FAILED]",0);
 
@@ -3898,7 +4008,7 @@ ck_ssl_outgoing(fd) int fd;
                         if (!ok) {
                             if (tn_deb || debses)
                                 tn_debug("[SSL - FAILED]");
-                            else if ( ssl_verbose_flag )
+                            else if ( verbosity )
                                 printf("[SSL - FAILED]\r\n");
                             debug(F110,
                                    "ck_tn_tls_negotiate","[SSL - FAILED]",0);
@@ -3909,19 +4019,19 @@ ck_ssl_outgoing(fd) int fd;
                 } else if (ssl_check_server_name(ssl_con, szHostName)) {
                     if (tn_deb || debses)
                         tn_debug("[SSL - FAILED]");
-                    else if ( ssl_verbose_flag )
+                    else if ( verbosity )
                         printf("[SSL - FAILED]\r\n");
                     debug(F110, "ck_tn_tls_negotiate","[SSL - FAILED]",0);
                     auth_finished(AUTH_REJECT);
                     return -1;
                 }
             }
-
-            printf("[SSL - OK]\r\n");
             if (tn_deb || debses)
                 tn_debug("[SSL - OK]");
+           else if (!quiet)
+               printf("[SSL - OK]\r\n");
             debug(F110,"ck_ssl_outgoing","[SSL - OK]",0);
-            ssl_display_connect_details(ssl_con,0,ssl_verbose_flag);
+            ssl_display_connect_details(ssl_con,0,verbosity);
         }
     }
     return(0);  /* success */
@@ -3936,6 +4046,8 @@ ck_ssl_http_client(fd, hostname) int fd; char * hostname;
     if ( !ck_ssleay_is_installed() )
         return(-1);
 
+    setverbosity();
+
     /* bind in the network descriptor */
     SSL_set_fd(tls_http_con,fd);
 
@@ -3949,7 +4061,7 @@ ck_ssl_http_client(fd, hostname) int fd; char * hostname;
 #endif /* USE_CERT_CB */
         if (tn_deb || debses)
             tn_debug("[TLS - handshake starting]");
-        else if (ssl_verbose_flag)
+        else if (verbosity)
             printf("[TLS - handshake starting]\r\n");
         debug(F110,"ck_ssl_outgoing","[TLS - handshake starting]",0);
         if (SSL_connect(tls_http_con) <= 0) {
@@ -3965,7 +4077,7 @@ ck_ssl_http_client(fd, hostname) int fd; char * hostname;
 
             if (tn_deb || debses)
                 tn_debug("[TLS - FAILED]");
-            else if ( ssl_verbose_flag )
+            else if ( verbosity )
                 printf("[TLS - FAILED]\r\n");
             debug(F110,"ck_ssl_http_client","[TLS - FAILED]",0);
             http_close();
@@ -3981,7 +4093,7 @@ ck_ssl_http_client(fd, hostname) int fd; char * hostname;
                     {
                         if (tn_deb || debses)
                             tn_debug("[TLS - FAILED]");
-                        else if ( ssl_verbose_flag )
+                        else if ( verbosity )
                             printf("[TLS - FAILED]\r\n");
                         debug(F110,"ck_tn_tls_negotiate","[TLS - FAILED]",0);
                         return -1;
@@ -3993,7 +4105,7 @@ ck_ssl_http_client(fd, hostname) int fd; char * hostname;
                         if (!ok) {
                             if (tn_deb || debses)
                                 tn_debug("[TLS - FAILED]");
-                            else if ( ssl_verbose_flag )
+                            else if ( verbosity )
                                 printf("[TLS - FAILED]\r\n");
                             debug(F110,
                                    "ck_tn_tls_negotiate","[TLS - FAILED]",0);
@@ -4003,7 +4115,7 @@ ck_ssl_http_client(fd, hostname) int fd; char * hostname;
                 } else if (ssl_check_server_name(tls_http_con, hostname)) {
                     if (tn_deb || debses)
                         tn_debug("[TLS - FAILED]");
-                    else if ( ssl_verbose_flag )
+                    else if ( verbosity )
                         printf("[TLS - FAILED]\r\n");
                     debug(F110,
                            "ck_tn_tls_negotiate","[TLS - FAILED]",0);
@@ -4015,7 +4127,7 @@ ck_ssl_http_client(fd, hostname) int fd; char * hostname;
             if (tn_deb || debses)
                 tn_debug("[TLS - OK]");
             debug(F110,"ck_ssl_outgoing","[TLS - OK]",0);
-            ssl_display_connect_details(tls_http_con,0,ssl_verbose_flag);
+            ssl_display_connect_details(tls_http_con,0,verbosity);
         }
     }
     return(0);  /* success */
@@ -4144,8 +4256,12 @@ X509_to_user(X509 *peer_cert, char *userid, int len)
     for (i = 0; i < sk_GENERAL_NAME_num(ialt); i++) {
         gen = sk_GENERAL_NAME_value(ialt, i);
         if (gen->type == GEN_DNS) {
-            if(!gen->d.ia5 || !gen->d.ia5->length)
-                break;
+            if (!gen->d.ia5 || !gen->d.ia5->length)
+             break;
+            if (strlen(gen->d.ia5->data) != gen->d.ia5->length) {
+                /* Ignoring IA5String containing null character */
+                continue;
+            }
             if ( gen->d.ia5->length + 1 > sizeof(email) ) {
                 goto cleanup;
             }
index b4dd8a3..97b6544 100644 (file)
--- a/ck_ssl.h
+++ b/ck_ssl.h
@@ -1,7 +1,7 @@
 /*
   C K _ S S L . H --  OpenSSL Interface Header for C-Kermit
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2005,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
  * definitions there is no reason to have it included by openssl/evp.h
  */
 #define OPENSSL_NO_MDC2
+#ifdef OPENSSL_100
+#define OPENSSL_098
+#endif /* OPENSSL_100 */
+#ifdef OPENSSL_098
+#define OPENSSL_097
+#endif /* OPENSSL_098 */
+#ifdef CK_DES
 #include <openssl/des.h>
+#endif /* CK_DES */
 #include <openssl/ssl.h>
 #include <openssl/x509v3.h>
 #include <openssl/rand.h>
@@ -94,6 +102,9 @@ extern int tls_active_flag;
 extern int x509_cert_valid;
 extern X509_STORE *crl_store;
 
+extern int ssl_raw_flag;
+extern int tls_raw_flag;
+
 #ifndef NOHTTP
 extern SSL_CTX *tls_http_ctx;
 extern SSL *tls_http_con;
@@ -128,6 +139,8 @@ _PROTOTYP(int ssl_verify_crl,(int, X509_STORE_CTX *));
 _PROTOTYP(int tls_is_krb5,(int));
 _PROTOTYP(int X509_userok,(X509 *,const char *));
 _PROTOTYP(int ck_X509_save_cert_to_user_store,(X509 *));
+/* SMS 2007/02/15 */
+_PROTOTYP(int ssl_check_server_name,(SSL * ssl, char * hostname));
 #ifdef OS2
 #include "ckosslc.h"
 #include "ckossl.h"
diff --git a/ckaaaa.txt b/ckaaaa.txt
deleted file mode 100644 (file)
index efa83a5..0000000
+++ /dev/null
@@ -1,385 +0,0 @@
-ckaaaa.txt                                                        10 Apr 2004
-
-                          C-KERMIT VERSION 8.0.211
-                             OVERVIEW OF FILES
-
-              Communications software for UNIX and (Open)VMS.
-
-                      And in former versions also for:
-                         Stratus VOS, AOS/VS, QNX,
-            Plan 9, OS-9, Apollo Aegis, and the Commodore Amiga.
-                     The Apple Macintosh, the Atari ST.
-
-                 The Kermit Project - Columbia University
-
-           http://www.columbia.edu/kermit/ - kermit@columbia.edu
-
-
-  Copyright (C) 1985, 2004,
-    Trustees of Columbia University in the City of New York.
-    All rights reserved.  See the C-Kermit COPYING.TXT file or the
-    copyright text in the ckcmai.c module for disclaimer and permissions.
-
-
-DOCUMENTATION
-
-  C-Kermit is documented in the book "Using C-Kermit", Second Edition, by
-  Frank da Cruz and Christine M. Gianone, Digital Press, ISBN 1-55558-164-1,
-  supplementated by Web-based updates for C-Kermit 7.0 and 8.0.
-
-PLATFORMS
-                   Security
-   Name            Included   Last Updated
-
-   Unix               Yes     8.0.211  10 Apr 2004
-   (Open)VMS          No      8.0.208  10 Apr 2004
-   Windows (K95)      Yes     8.0.208  14 Mar 2003  (K95 2.1)
-   OS/2 (K95)         Yes     8.0.208  14 Mar 2003  (K95 2.1)
-   DG AOS/VS          No      7.0.196   1 Jan 2000
-   Stratus VOS        No      7.0.196   1 Jan 2000
-   Bell Plan 9        No      7.0.196   1 Jan 2000
-   Microware OS-9     No      7.0.196   1 Jan 2000
-   Commodore Amiga    No      7.0.196   1 Jan 2000
-   Macintosh          No      5A(190)  16 Aug 1994  (Mac Kermit 0.991)
-   Atari ST           No      5A(189)  30 Jun 1993
-
-QUICK START FOR FTP USERS
-
-  If you have a Web browser, go to:
-
-    http://www.columbia.edu/kermit/ckermit.html
-
-  And take it from there.  Otherwise...
-
-  The definitive FTP source for Kermit software is kermit.columbia.edu.
-  Kermit software obtained from other FTP sites is not necessarily complete
-  or up to date, and may have been modified.
-
-C-Kermit for UNIX computers that have a C compiler and 'make' program:
-
-  Directory kermit/archives, binary mode, file cku211.tar.Z or cku211.tar.gz
-
-  This is a compressed tar archive of UNIX C-Kermit source code, makefile, and
-  other files.  It unpacks into its current directory, so download it into a
-  fresh directory.  Transfer in binary mode, uncompress (or gunzip), untar (tar
-  xvf cku211.tar), and then give the appropriate "make" command to build for
-  your UNIX system; read the comments in the makefile and ckuins.txt for
-  further info.
-
-C-Kermit for VMS:
-
-  If you have VMS UNZIP, get the file kermit/archives/ckv211.zip in binary
-  mode, unzip, and build with CKVKER.COM.
-
-Others:  In the kermit/f or kermit/test directories under the appropriate
-prefixes, explained below.
-
-
-INSTALLATION
-
-Installation procedures depend on the system.  Please read the CK?INS.TXT,
-if any, file for your system (?=U for UNIX, V for VMS, etc).  Please note
-the naming and placement for the initialization files:
-
-  CKERMIT.INI
-    The standard initialization file.  Please leave it as is unless you
-    know what you are doing and (if you are changing it or replacing it
-    for others to use) you are prepared to support it.  Rename this file
-    to .kermrc in UNIX, OS-9, BeBox, or Plan 9.  In Stratus VOS, rename
-    it ckermit.ini (lowercase).  On multiuser systems, it goes either in the
-    (or EACH) user's home (login) directory, or else in a common shared
-    place if C-Kermit has been configured to look in that place (see
-    ckccfg.txt for details).
-
-  CKERMOD.INI
-    A *sample* customization file.  On multiuser OS's, a copy of this file
-    goes in each user's home directory, and then each user edits it to suit
-    her needs and preferences; e.g. by defining macros for their common
-    connections.
-
-  DIALING DIRECTORIES
-    Dialing directory files can be system-wide, per-group, or per-user, or
-    any combination.  For example, there can be a corporate wide directory
-    shared by all users, a supplemental directory for each division or
-    department, and a personal directory for each user.  Simply be sure the
-    dialing directory files are identified a SET DIAL DIRECTORY command in
-    the user's (or the system-wide) C-Kermit initialization file, or in the
-    environment variable (logical name, symbol) K_DIAL_DIRECTORY.  (The
-    standard initialization file looks by default in the user's home or login
-    directory.)  When installing C-Kermit on multiuser platforms from which
-    users will dial out, you can also set environment variables for area
-    code, country code, and the various dialing prefixes as described on page
-    478 of "Using C-Kermit" (second edition), so users don't have to worry
-    about defining these items themselves.   Network directories and service
-    directories can also be set up in a similar manner.
-
-  DOCUMENTATION
-    In UNIX, the general C-Kermit man page (or one of the versions tailored
-    for a specific platform, like HP-UX or Solaris) should be installed in
-    the appropriate place.  In VMS, the VMS help topic (CKVKER.HLP) should
-    be installed as described in CKVINS.TXT.  Plain-text documentation such
-    as CKERMIT2.TXT should be put in whatever place people are accustomed
-    to looking.
-
-FILES AND FILE NAMING CONVENTIONS
-
-C-Kermit is a family of Kermit programs for many different computer systems.
-The program shares a common set of system-independent file transfer protocol
-modules, written in the C language.  System-dependent operations are collected
-into system-specific modules for each system.
-
-C-Kermit file names all start with the letters "CK", followed by a single
-letter indicating the subgroup.  When referring to these files in the UNIX,
-AOS/VS, or VOS environments, use lowercase letters, rather than the uppercase
-letters shown here.  Subgroups:
-
-  _: Security/Authentication/Encryption code, possibly regulated by law
-  a: General descriptive material and documentation
-  b: BOO file encoders and decoders (obsolete)
-  c: All platforms with C compilers
-  d: Data General AOS/VS
-  e: Reserved for "ckermit" files, like CKERMIT.INI, CKERMIT80.TXT
-  f: (reserved)
-  g: (reserved)
-  h: (reserved)
-  i: Commodore Amiga (Intuition)
-  j: (unused)
-  k: (unused)
-  l: Stratus VOS
-  m: Macintosh with Mac OS
-  n: Microsoft Windows NT
-  o: OS/2 and/or Microsoft Windows 95/98/ME/NT/2000/XP/...
-  p: Bell Labs Plan 9
-  q: (reserved)
-  r: DEC PDP-11 with RSTS/E (reserved)
-  s: Atari ST GEMDOS (last supported in version 5A(189))
-  t: DEC PDP-11 with RT-11 (reserved)
-  u: UNIX or environments with UNIX-like C libraries
-  v: VMS and OpenVMS
-  w: Wart (Lex-like preprocessor, used with all systems)
-  x: (reserved)
-  y: (reserved)
-  z: (reserved)
-  0-3: (reserved)
-  4: IBM AS/400 (reserved)
-  5-8: (reserved)
-  9: Microware OS-9
-
-Examples:
-
-  ckaaaa.txt - This file
-  ckufio.c   - File i/o for UNIX
-  ckstio.c   - Communications i/o for the Atari ST
-  makefile   - makefile for building UNIX C-Kermit
-  ckpker.mk  - makefile for building Plan 9 C-Kermit
-  ckvker.com - build procedure for VMS C-Kermit
-
-IMPORTANT FILES (use lowercase names on UNIX, VOS, or AOS/VS):
-
-  ckaaaa.txt  - This file (overview of the C-Kermit files).
-                For system-specific distributions, this will normally
-                be replaced by a system-specific READ.ME file.
-
-  ckermit70.txt - Updates: Supplement to "Using C-Kermit", 2nd Ed, for 7.0.
-  ckermit80.txt - Updates: Supplement to "Using C-Kermit", 2nd Ed, for 8.0.
-  ckututor.txt  - C-Kermit Tutorial for Unix (plain text)
-  ckcbwr.txt  - "Beware file" (limitations, known bugs, hints), general.
-  ckermit.ini - Standard initialization file (rename to .kermrc in UNIX, OS-9)
-  ckermod.ini - Sample customization file (rename to .mykermrc in UNIX, OS-9)
-
-The following can be found at the Kermit FTP site:
-
-  ckermit.kdd - Sample dialing directory file (rename to .kdd in UNIX, OS-9)
-  ckermit.knd - Sample dialing directory file (rename to .knd in UNIX, OS-9)
-  ckermit.ksd - Sample services directory file (rename to .ksd in UNIX, OS-9)
-  ckedemo.ksc - Demonstration macros from "Using C-Kermit"
-  ckepage.ksc - Ditto
-  ckevt.ksc   - Ditto
-
-UNIX-specific files:
-
-  ckuins.txt - UNIX-specific installation instructions.
-  ckubwr.txt - UNIX-specific beware file.
-  ckuker.nr  - "man page" for UNIX.
-
-VMS-specific files:
-
-  ckvins.txt - VMS-specific installation instructions.
-  ckvbwr.txt - VMS-specific beware file
-  ckvker.hlp - VMS C-Kermit HELP topic (needs updating).
-
-DG AOS/VS-specific files:
-
-  ckdins.txt - Data General AOS/VS C-Kermit installation instructions
-  ckdbwr.txt - AOS/VS "beware" file
-  ckd*.cli   - Procedures for building AOS/VS C-Kermit
-
-The following files are of interest mainly to programmers and historians
-(find them at the Kermit ftp site):
-
-  ckcker.ann - Release announcements.
-  ckccfg.txt - Configuration information (feature selection), general.
-  ckcplm.txt - Program logic manual (for programmers).
-  ckc211.txt - Program update history for edit 201-211.
-  ckc200.txt - Program update history for edit 198-200 (big)
-  ckc197.txt - Program update history for edit 195-197 (big)
-  ckc190.txt - Program update history for edits 189-190 (big).
-  ckc188.txt - Program update history, edits 179-188 (big).
-  ckc178.txt - Program edit history, 5A edits through 178 (very big).
-  ckcv4f.txt - Program edit history, version 4F.
-  ckcv4e.txt - Program edit history, version 4E.
-
-BINARIES
-
-If you have FTP access to kermit.columbia.edu (also known as
-kermit.cc.columbia.edu, ftp.cc.columbia.edu), you can also retrieve various
-C-Kermit binaries from the directory kermit/bin/ck*.*, or more conventiently
-from the web page:
-
-  http://www.columbia.edu/kermit/ck80binaries.html
-
-Test versions would be in kermit/test/bin/ck*.*.  Be sure to transfer these
-files in binary mode.  The READ.ME file in that directory explains what's
-what.
-
-SOURCE FILES
-
-The source files for the UNIX version (all UNIX versions) are available in
-kermit/archives/ckuNNN.tar.Z, approximately 1MB in size.  Transfer this file
-in binary mode.  This is a compressed tar archive.  There is also a gzip'd
-version, cku211.tar.gz.  To get the binary tar archive:
-
-  mkdir kermit                   (at shell prompt, make a Kermit directory)
-  cd kermit                      (make it your current directory)
-
-  ftp kermit.columbia.edu        (make an ftp connection)
-  user: anonymous                (log in as user "anonymous", lower case!)
-  password:                      (use your email id as a password)
-  cd kermit/archives             (go to the archives directory)
-  type binary                    (specify binary file transfer)
-  get cku211.tar.Z               (get the tar archive) (or get cku192.tar.gz)
-  bye                            (disconnect and exit from ftp)
-
-  uncompress cku211.tar.Z        (at the shell prompt, uncompress the archive)
-  tar xvf cku211.tar             (extract the files from the tar archive)
-  make xxx                       (build C-Kermit for your system)
-
-(where "xxx" is the makefile entry appropriate for your system.)
-
-All C-Kermit source and other text files are also kept separately in the
-kermit/f directory.  The files necessary to build a particular implementation
-of C-Kermit are listed in the appropriate makefile or equivalent:
-
-       UNIX: makefile (or rename ckuker.mak to makefile)
-   2.11 BSD: ckubs2.mak (rename to makefile), ckustr.sed
-     Plan 9: ckpker.mk  (rename to mkfile)
-  Macintosh: ckmker.mak (rename to kermit.make, use MPW C 3.2)
-        VMS: CKVKER.COM (DCL) (and optionally also CKVKER.MMS)
-             or CKVOLD.COM (for VMS 4.x)
-      Amiga: CKIKER.MAK (Aztec C) or CKISAS.MAK (SAS C)
-   Atari ST: CKSKER.MAK
-       OS-9: ck9ker.mak or ck9ker.gcc
-     AOS/VS: ckdmak.cli, ckdcc.cli, ckdlnk.cli
-Stratus VOS: cklmak.cm
-
-Minimal source files for building selected versions (these patterns get all
-the files you need, and in some cases maybe a few extra):
-
-   UNIX:   ck[cuw]*.[cwh]  (including QNX, Plan 9, and BeBox)
-   UNIX:   ck[cuw_]*.[cwh] (Unix with security modules)
-   VMS:    ck[cuwv]*.[cwh]
-   Mac:    ck[cuwm]*.[cwhr]
-   AOS/VS: ck[cuwd]*.[cwh]
-   VOS:    ck[cwhl]*.[cwh]
-   Amiga:  ck[cuwi]*.[cwh]
-   Atari:  ck[cuws]*.[cwh]
-   OS-9:   ck[cuw9]*.[cwha]
-
-For a detailed, specific source file list for this C-Kermit release, see the
-file ckcxxx.txt, where xxx is the current C-Kermit edit number, such as 211.
-
-Finally, here is a more detailed description of the C-Kermit file naming
-conventions.  A C-Kermit filename has the form:
-
-  CK<system><what>.<type>
-
-where:
-
-<system> is described earlier in this file;
-
-<type> is the file type (use lowercase on UNIX, VOS, or AOS/VS):
-
-  c:   C language source
-  h:   Header file for C language source
-  w:   Wart preprocessor source, converted by Wart (or Lex) to a C program
-  r:   Macintosh resource file (8-bit text)
-  a:   Assembler source
-
-  txt: Plain text.
-  nr:  Nroff/Troff text formatter source for UNIX "man page"
-  mss: Scribe text formatter source
-  ps:  Typeset material to be printed on a PostScript printer
-  hlp: A VMS Help topic
-
-  ini: Initialization file
-  ksc: A Kermit Script to be executed by the TAKE command
-  kdd: A Kermit Dialing Directory
-  knd: A Kermit Network Directory
-  ksd: A Kermit Services Directory
-
-  mak: A Makefile or other build procedure (often needs renaming)
-  com: (VMS only) a DCL command procedure
-  cli: (AOS/VS only) a command procedure
-  cmd: (OS/2 only) a Rexx command procedure
-
-  boo: "boo"-encoded executable program, decode with CKBUNB program.
-  hex: "hex"-encoded executable program, decode with CKVDEH program (VMS only).
-  hqx: BinHex'd Macintosh Kermit program, decode with BinHex version 4.0.
-  uue: A uuencoded binary file, decode with uudecode or (DG only) CKDECO.
-
-  def: An OS/2 linker definitions file.
-  sh:  A UNIX shell script.
-  sed: A UNIX sed (editor) script.
-  str: A file of character strings extracted from C-Kermit (BSD 2.1x only).
-
-<what> is mnemonic (up to 3 characters) for what's in the file:
-
-NOTE: After C-Kermit 6.0, text filetypes such as .DOC and .HLP were changed
-to .TXT to avoid confusion in Windows-based Web browsers, which would
-otherwise mistake them for Microsoft Word or Windows Help documents.
-
-  aaa: A "read-me" file, like this one
-  ins: Installation instructions or procedures
-  bwr: "Beware" file -- things to watch out for, hints and tips
-  plm: Program Logic Manual
-  ker: General C-Kermit definitions, information, documentation
-
-  nnn: Digits: C-Kermit edit number (e.g. cku211.tar.gz)
-  cmd: Command parsing
-  con: CONNECT command
-  cns: CONNECT command (UNIX only - version that uses select(), not fork())
-  deb: Debug/Transaction Log formats, Typedefs
-  dia: Modem/Dialer control
-  fio: System-depdendent File I/O
-  fns: Protocol support functions
-  fn2: More protocol support functions (and FN3, ...)
-  lib: Common library routines module
-  mai: Main program
-  net: Network i/o module
-  pro: Protocol
-  scr: SCRIPT command
-  tel: Telnet protocol module
-  tio: System-dependent communications i/o & control and interrupt handing
-  sig: Signal handling module
-  usr: Interactive/script user interface
-  us2: More user interface (mainly help text)
-  us3: Still more user interface (and USR4, USR5, USR6, USR7)
-  usx: Common user interface functions
-  usy: Command-line parsing
-  xla: Character set translation module
-  uni: Unicode support
-  pty: Pseudoterminal support
-  mdb: Malloc-debugging module (not included in real builds)
-  str: Strings module (only for 2.xBSD)
-
-(End of ckaaaa.txt)
diff --git a/ckc211.txt b/ckc211.txt
deleted file mode 100644 (file)
index 1886725..0000000
+++ /dev/null
@@ -1,3595 +0,0 @@
-C-KERMIT CHANGE LOG (Changes since 8.0.200 of 12 Dec 2001)
-
-Chronological order: Go to the bottom to find the newest edits.
-
----8.0.200---
-
-Known bugs (+ = fixed after release):
-
- + 1. tilde_expand() can call getcwd() with NULL arg.
- + 2. getexedir() called too early (fatal in combination with (1)).
- + 3. Kermit "get blah" where blah is a symlink; server refuses to send it.
-      Should not do this if GET not recursive.
- ? 4. Dave Sneddon's report about VMS fore/background confusion.
- + 5. FTP GET path/file doesn't work - path not stripped - but MGET works.
- + 6. IRIX 5.3 compilation problems (have patches from Marcus Herbert)
- X 7. Filename completion bug (see below) (deferred).
- + 8. QNX6 herald and other problems.
-
--------------
-
-Merged Jeff's changes, 20 Dec 2001:
-
- . Changed all occurrences of "ttnproto == NP_TELNET" to "IS_TELNET()" to
-   account for the difference between SSH and Telnet.  ckuscr.c,
-   ckuus[3457].c, ckcnet.h, ckcfns.c, ckudia.c, ckutio.c, ckucon.c, ckucns.c.
-
- . Moved SSH pty failure warnings.  ckuusr.c.
-
- . Security adjustments to FTP module, plus fix an error message.  ckcftp.c.
-
- . Adjustment of some security-related #ifdefs. ckcdeb.h, ckuus2.c, ckctel.c.
-
- . Guard against calling getpwnam() with a NULL arg in tilde_expand() ckufio.c.
- . Moved getexedir() call to later, where it's safe.  ckcmai.c.
-
-Added SSH ADD and many SSH SET commands from Jeff's spec.  Fixed SHOW SSH
-to not dump core if variables weren't set.  ckcker.h, ckuus[r3].c, 20 Dec 2001.
-
-C-Kermit in server mode, client says "get foo" where foo is a symlink.
-Server says "no files meet selection criteria" instead of sending the file.
-It should only refuse to follow symlinks if it's a recursive get.  Fixed
-in sgetinit(): ckcpro.w, 21 Dec 2001.
-
-More work on SSH and SET/SHOW SSH commands.  ckuus[r3].c, 21 Dec 2001.
-
-Undid Jeff's replacement of the SSH pseudoterminal allocation failure
-message, because now it comes out any time an SSH command has to be
-reparsed (in the non-SSHBUILTIN case).  ckuusr.c, 21 Dec 2001.
-
-More SSH and SET SSH command work back & forth with Jeff, plus Jeff added
-SET HOST /NET:SSH.  ckcmai.c, ckuus[r37].c, ckcdeb.h, ckuusr.h, 22 Dec 2001.
-
-Added SSH OPEN switches.  ckuusr.c, 22 Dec 2001.
-
-Added SSH CLEAR, HELP SSH, and HELP SET SSH.  ckuus[r2].c, 23 Dec 2001.
-
-From Jeff:
- . SET TCP commands now apply to SSH
- . SSH V2 REKEY and FORWRD-{LOCAL,REMOTE}-PORT  commands now implemented
- . Missing DLLs automatically disable appropriate authentication mechanisms.
-ckuusr.c ckcnet.c ckuus3.c ckcmai.c ckcnet.h ckuus4.c, 26 Dec 2001.
-
-From Jeff:
- . Remove SET SSH KEEPALIVES.
- . Add help text for SSH AGENT { ADD, DELETE, LIST }.
-ckuus[23].c, 28 Dec 2001.
-
-Added parsing for SSH AGENT { ADD, DELETE, LIST }.  ckuusr.c, 28 Dec 2001.
-
-From Jeff:
- . Fixed a crash that can happen when making an SSH connection.
- . Filled in SSH AGENT actions.
- . Changed default for strict host key check (to ASK) and help text.
- . uploaded new binaries include ~kermit/os2test/beta/ssh-agent.exe
- . Read man ssh-agent on ftp.kermit.columbia.edu for details on what it does.
-ckuus[r23].c, 28 Dec 2001.
-
-"ftp get path/filename" didn't work; the FTP client did not strip the path
-from the local copy of the filename when doing a GET, even though it did
-for MGET.  Diagnosis: in doftpget(), the "if (!getone && !skipthis)" statement
-lacked an "else" part for the getone case.  ckcftp.c, 28 Dec 2001.
-
-A while back Jeff reported that in FTP MGET, if you cancel a file with 'x',
-all the rest of the files arrive truncated to 0 bytes.  I tried this on both
-Unix and Windows and couldn't reproduce it.
-
-In the last-minute flurry to release C-Kermit 8.0, I thought I noticed the FTP
-client failing to update the fullscreen file-transfer display.  But it seems
-to work right, at least in Unix.  When downloading a big file with FTP, all
-the display fields are updated as expected.  But smaller files might go by too
-fast for the display to do anything.  HOWEVER, in K95 the file transfer
-display does not update itself until the end of the file, even if the file
-takes a long time to transfer.  This happens in both the Console and GUI
-versions.  A thread thing?  (Jeff says no.)  Yet the same display works fine
-on Telnet connections.
-
-In IRIX 5.3, the select()-based CONNECT module had to include <sys/time.h>
-or else it blew up with "struct timeval" unknown.  Since there already was
-a SYSTIMEH CFLAG, I added the #include within #ifdef SYSTIMEH..#endif and
-rebuilt with KFLAGS=-DSYSTIMEH, only to discover that the irix5* targets
-didn't bother to propogate KFLAGS.  Fixed in ckucns.c, makefile, 30 Dec 2001.
-
-Increased IRIX5x Olimit from 2400 to 3000 because of ckuus[34].c.  Added
--ansi, since (Marcus Herbert reported) we were not actually getting ANSI-C
-compilation even though CK_ANSIC was defined.  But now that we are, we get
-warnings in <netinet/tcp.h>, which is included by ckcnet.h:
-
-  bit-field 'th_off' type required to be int, unsigned int, or signed int.
-  (3.5.2.1(30))
-         u_char  th_off:4,
-         ------  ^
-Tough.  makefile, 30 Dec 2001.
-
-But adding -ansi to the IRIX 5x targets also make compilation bomb whenever we
-referenced fdopen() or popen(), which evidently don't have prototypes in any
-of the header files.  Luckily we already have CFLAGS for this occasion too:
-DCLFDOPEN and DCLPOPEN.  Added these to the irix51 target.  Also had to copy
-the fdopen()-popen() prototype section to ckuusx.c, which has a new reference
-to fdopen() in a workaround for the curses console buffering bug.  makefile,
-ckuusx.c, 30 Dec 2001.
-
-The QNX6 version did not receive a proper herald (it announced itself as
-"unknown version".  Reshuffled #ifdefs in ckuver.h, added display of QNX6
-and NEUTRINO symbols to ckuus5.c, 30 Dec 2001.
-
-Lucas Hart sent in a patch for the VMS problem.  Apparently it was even worse
-than Dave Sneddon had reported: 8.0 couldn't run at all under Batch.  ckvtio.c,
-31 Dec 2001.
-
-A major obstacle to the usability of the FTP client is that certain commands
-don't behave as FTP users expect: CD, DIR, DELETE, MKDIR, etc, which are local
-rather remote, and there are no LCD (etc), USER, or ACCOUNT commands.  We
-could fix this by adding an FTP command-language personality, but file
-management commands can also be remote or local on connections to Kermit
-servers too.  So:
-
-SET LOCUS { LOCAL, REMOTE, AUTO }
-  Sets the locus for unprefixed file management commands.
-  When LOCAL, a REMOTE (or R) prefix is required for
-  to send file management commands to a remote server (e.g. RCD, RDIR).
-  When REMOTE, an L prefix is required to issue local file management
-  commands (e.g. LCD, LDIR).  The word LOCAL can't be used as a prefix
-  since it is used for declaring local variables.
-
-This applies to all types of connections, and thus is orthogonal to SET
-GET-PUT-REMOTE, which selects between Kermit and FTP for remote file-transfer
-and management commands.
-
-The default LOCUS is AUTO, which means we switch to REMOTE whenever an FTP
-connection is made, and to LOCAL whenever a non-FTP connection is made,
-and switch back accordingly whenever a connnection is closed.
-
-Implementation (31 Dec 2001):
- . None of this is compiled if LOCUS is not defined.
- . Added XYLOCUS (SET LOCUS) and LOCUS definitions: ckuusr.h.
- . Override by defining NOLOCUS (which inhibits definition of LOCUS).
- . Added LOCUS to SET keyword table: ckuusr.c.
- . Added locus & autolocus variables: ckuusr.c.
- . Added SET LOCUS parsing and variable setting: ckuus3.c.
- . Added display of LOCUS setting to SHOW COMMAND: ckuus5.c.
- . Added automatic locus setting to setlin(): ckuus7.c.
- . Added automatic locus setting to ftpopen() and ftpclose(): ckcftp.c.
-
-How to catch all the places where a Kermit connection is closed?  Turns out
-we've done this before, when we added the connection log.  So I made
-dologend() take care of locus switching.  But dologend() was not compiled in
-if certain symbols were defined, such as NOLOCAL, or not defined, such as
-CKLOGDIAL.  So I (a) rearranged the #ifdefs so that even if these would
-otherwise have obliviated dologend(), now they leave a piece of it for
-locus-setting; (b) moved the prototype out of #ifdefs; and (c) took all calls
-to it out of #ifdefs.  ckcker.h, ckcfn2.c, ckcmai.c, ckucns.c, ckucon.c,
-ckuus[r347x].c, 31 Dec 2001.
-
-Added locus checking to the following commands: DIRECTORY, CD/CWD, CDUP,
-DELETE, PWD, MKDIR, RMDIR, RENAME.  ckuusr.c, 31 Dec 2001.
-
-Added LDIRECTORY, LCD/LCWD, LCDUP, LDELETE, LPWD, LMKDIR, LRMDIR,
-LRENAME.  ckuusr.[ch], 31 Dec 2001.
-
-Added USER and ACCOUNT commands, which are the same as FTP USER and FTP
-ACCOUNT.  ckuusr.[ch], ckcftp.c, 31 Dec 2001.
-
-Since automatic locus switching could be a big surprise for most people, I
-printed message any time it changed.  ckcftp.c, ckuus[37].c, 31 Dec 2001.
-
-Added help text for the new L commands and filled in missing HELP text for
-SET GET-PUT-REMOTE, CDUP, MKDIR, and RMDIR.  ckuus2.c, 31 Dec 2001.
-
-Changed help text of CD, DIR, etc, for LOCUS.  Changed the help text for
-RCD, RPWD, RDEL, RDIR, etc, to mention that they also work with FTP servers.
-Updated HELP REMOTE for this too.  ckuus2.c, 31 Dec 2001.
-
-Made sure code builds with NOLOCAL, NOLOGDIAL, and NOLOCUS (it does).
-
-The IKSD command, when given with a /USER: switch, sends the user ID to the
-IKSD.  But the SET HOST /USER: command does not, when making a connection to a
-Kermit service.  This makes it impossible to script IKSD interactions using
-only client commands.  Furthermore, even if you include a /PASSWORD switch
-with the IKSD command, it does not send the password.  I added code near the
-bottom of setlin() to do this.  If we have a connection to a Kermit service
-and a /USER: switch was given, then we attempt a REMOTE LOGIN.  If a
-/PASSWORD: switch was not given then if the username is "ftp" or "anonymous",
-we automatically supply a password of user@host; otherwise we prompt for a
-password.  If a /USER: switch was not given, it acts like before.  It all
-works, but it might not be the best way (or place) to do it.  setlin():
-ckuus7.c, 31 Dec 2001.
-
-  NOTE: The above change doesn't help with IKSD /USER:anonymous,
-  the server prompts for password anyway, not sure why.
-
-  NOTE 2: What about secure authentication?  We have to test to see
-  if user was already authenticated before sending the login packet.
-
-Added /opt/kermit and /opt/kermit/doc to info_dir[] list (for Solaris).
-ckuus5.c, 31 Dec 2001.
-
-From Jeff: new Help text for SET TERM FONT (K95 GUI).  ckuus2.c, 1 Jan 2002.
-
-More work on help text for file management commands -- e.g. we can't lump
-the L-commands together with the unprefixed ones; they need separate entries.
-Also: added missing HELP REMOTE PWD, improved the default case (in which
-help text had been omitted for a valid command).  ckuus2.c, 1 Jan 2002.
-
-It seems VMS C-Kermit was pretty much ignoring the -B (force background) and
--z (force foreground) command-line options.  Fixed in congm(): ckvtio.c,
-1 Jan 2002.
-
-Tested the SET LOCUS business with VMS C-Kermit, which does not have a
-built-in FTP client.  Of course in this case there is no automatic locus
-switching, but SET LOCUS REMOTE works nicely on IKSD connections.
-
-From Jeff:
- . #ifdef adjustments for LOCUS changes.
- . SSH KEY CREATE /TYPE:SRP.
- . Fix \v(serial) to not be 8N2 by default if speed is 0.
- . Don't let doexit() run if sysinit() hasn't been called first.
-ckuus[r247x].c, 2 Jan 2002.
-
-Made SET BACKGROUND { ON, OFF } do exactly the same as -B and -z options.
-ckuus3.c, 2 Jan 2002.
-
-Updated user-visible copyright dates to 2002 (but still need to do all the
-source-module comments).  ckcmai.c, ckuus[25].c, 2 Jan 2002.
-
-Rearranged #include <sys/time.h> in ckucns.c that was done for IRIX 5.3,
-to avoid conflicts in SV/68 R3v6.  3 Jan 2002.
-
-From Dave Sneddon: Code changes in VMS sysinit() and congm() to work around
-problems in batch, SPAWN'd, etc, and change CTTNAM from TT: to SYS$INPUT:.
-ckcdeb.h, ckvtio.c, 3 Jan 2002.
-
-From Jeff:
- . Fixed typo in definition of CTTNAM for VMS.  ckcdeb.h
- . Moved macro definitions for SSHBUILTIN from ckuus3.c to ckuusr.h
-   so they can be referenced in ckuus7.c
- . Added SSH functionality to SET HOST:
-     SET HOST /NET:SSH /CONNECT hostname [port] /switches
- . Fixed SET NET TYPE so it won't reject SSH if SSH is installed.
- . Changes to allow IKSD to continue functioning.  Somehow this minor change
-   to ckcmai.c got lost in one of the back and forth exchanges.
- . HELP TEXT for UCS2 kverb
- . Fix a problem in K95 where multiple threads could be attempting to
-   send a telnet negotiation simultaneously.
-ckcmai.c ckcdeb.h ckuus2.c ckuus3.c ckuusr.c ckuusr.h ckuus7.c ckctel.c
-ck_crp.c ckuat2.h ckuath.c, 4 Jan 2002.
-
-From Jeff:
-
-  Peter Runestig complaining that the Telnet Forward X code was corrupting
-  data.  This resulted in a very thorough examination of the telnet module
-  code and a discovery of some rather significant problems.  The root of the
-  problems is the lack of thread safety.  To correct this problem the
-  following was done.
-
-  All code (regardless of module) which outputs telnet commands is placed
-  into a mutex region to ensure that competing output threads do not result
-  in interleaving their output.  This could happen for instance when the
-  forward-x thread is forwarding data and the user changes the window size
-  or sends an AYT or BREAK.  Next the buffer used for input and output
-  processing were identical.  This means that output data could be treated
-  as input or vice versa.  Ugh....
-
-  I also spent some more time cleaning up setlin().  Mostly reorganizing the
-  code into single if (...) blocks so that breaking it up will be easier.
-
-ckctel.c ckuus7.c, 4 Jan 2002.
-
-Updated internal copyright notices.  All modules, 5 Jan 2002.
-
-From Jeff:
-  More of same, plus new makefile target and changes from Spike Gronim
-  for freebsd44+srp+openssl.
-ckcdeb.h ckcnet.c ckctel.c ckuus7.c ck_ssl.c makefile, 5 Jan 2002.
-
-Some minor updates and fixes to SSH and SET SSH help text.
-ckuus2.c, 6 Jan 2002.
-
-Added SET RGB-COLORS for GUI.  ckuusr.[ch], ckuus3.c, 6 Jan 2002.
-
-From Jeff: More Telnet changes, Debug semaphores for K95, etc: ckcdeb.h,
-ckuusr.h, ckuus[r35x].c, ckctel.[ch], ckuath.c, 7 Jan 2002.
-
-Added --xpos:n --ypos:n, SET GUI WINDOW POSITION x y, and changed SET
-RGB-COLORS to SET GUI RGBCOLOR.  Action needs to be filled in (in setguiwin()
-in ckuus3.c), and gui_xpos and gui_ypos need to be defined in cko???.c.
-ckuusr.h, ckuus[r3y].c, 7 Jan 2002.
-
-Added --fontname:name --fontsize:name (and facename as synonym for fontname).
-ckuusr.h, ckuus[7y].c, 7 Jan 2002.
-
-Moved GUI (not OS/2) SET TERM FONT code in ckuus7.c to its own routine,
-setguifont(), in ckuus3.c, and made GUI SET TERM FONT call this routine,
-and also made SET GUI FONT call the same routine.  ckuus[37].c, 7 Jan 2002.
-
-Added --termtype:, --height:, --width:, --user:.  Also added symbols for
---telnet:, --ssh:, --ftp:, --[remote-]charset, and --password:, but didn't
-fill them in.  --password: is probably not a good idea (but we allow it for
-FTP); the others involve a lot of code-shuffling and reconciliation, which
-I'll try to do when I get a chance (especially the connection ones, which
-can be done as part of the setlin() restructuring).  ckuusr.h, ckuusy.c,
-8 Jan 2002.
-
-Also I tried commenting out the #ifndef KUI..#endif's around SET TERMINAL
-CHARACTER-SET (easier said than done because a crucial #endif was mislabeled).
-Let's see if it compiles & works...  ckuus7.c, 8 Jan 2002
-
-Added FTP [ OPEN ] /NOINIT, meaning don't send REST, STRU, and MODE commands
-upon making an FTP connection.  This allows connection to servers that close
-the connection (or worse) when given these commands (e.g. Linux 2.4 TUX 2.0
-FTP server).  ckcftp.c, 8 Jan 2002.
-
-Looked at adding caller ID support for the ANSWER command:
-
- . SET ANSWER CALLER-ID { ON, OFF }
- . SET ANSWER RINGS <number>
- . \v(callid_xxx) xxx = { date, time, name, nmbr, mesg }
- . CKD_CID modem capability
- . Set CKD_CID for modems that have it.
- . A quick survey shows:
-   - USR V.90:      No (but Jeff says some USRs have it).
-   - V.250:         No
-   - Lucent Venus:  No
-   - USR:           #CID=1 (the ones that have it -- X2?)
-   - Diamond Supra: #CID=1
-   - Rockwell 56K:  #CID=1
-   - PCTEL:         #CID=1
-   - Zoltrix:       +VCID=1
-   - Conexant:      +VCID=1
- . Since there are different commands to enable caller ID reporting,
-   we need a new field in struct MDMINF.
- . SHOW MODEM and SHOW DIAL would need updating.
- . etc etc...
-
-This is all way too much for now so I just did the setting of the \v(callid_*)
-variables.  These are reset at the beginning of an ANSWER command, and then
-set by the ANSWER command if they come in; thus they persist from the time
-they are collected until another ANSWER command is given.  To take advantage
-of autoanswer, the user has to enable it in the modem (all the modems I found
-that support it have it disabled by default), and also has to set the number
-of rings to at least 2.  This can be done with (depending on the modem):
-
-  set modem command autoanswer on ATS0=2#CID=1\{13}
-  set modem command autoanswer on ATS0=2+VCID=1\{13}
-
-and undone with:
-
-  set modem command autoanswer on ATS0=1#CID=0\{13}
-  set modem command autoanswer on ATS0=1+VCID=0\{13}
-
-The variables can be accessed only after the call is answered.  Therefore the
-only way to refuse a call is to answer it, inspect the variables, and then
-hang it up if desired.  Future Kermit releases can do this more nicely (as
-sketched out above.)  Also while I was in the dialing code, I added result
-code VCON (= VOICE), used by several of the newer modems.  These changes are
-untested.  The SET ANSWER command is written but commented out.  ckuusr.h,
-ckcker.h, ckuus[r3].c, ckudia.c, 8 Jan 2002.
-
-From Jeff: fixes to --termtype:, --height:, --width:, --user:, and filling in
-of --rcharset:, which required extracting code from settrm() into a separate
-parse-method-independent remote character-set setting routine.  ckuus[7y].c,
-8 Jan 2002.
-
-From Jeff: More work on TERMINAL CHARACTER-SET code reorganization, and
-reinstatement of SET TERMINAL CHARACTER-SET in K95G.  Also, fix char/CHAR
-warnings in Telnet module.  ckuus7.c, ckctel.c, 9 Jan 2002.
-
-Made SET TERM CHARACTER-SET visible for all builds, including K95G, and filled
-in HELP text for it.  ckuus[27].c, 9 Jan 2002.
-
-Added help text for new extended options.  ckuusy.c, 9 Jan 2002.
-
-Commented out the return(-2) statement at the end of xgnbyte() to make the
-"Statement not reached" errors go away, after checking to make sure that there
-was no path that could fall through to the end.  I'm 99.99% sure there isn't,
-but that doesn't mean that some compilers might not still complain.  ckcfns.c,
-9 Jan 2002.
-
-From Jeff: fix typo in the K95 extended-option help text; add more
-semaphores to network i/o.  ckuusy.c, ckcnet.c, 10 Jan 2002.
-
-Undid ansiisms in set{lcl,rem}charset() declarations.  ckuus7.c, 10 Jan 2002.
-
-Removed a duplicated clause from the install target.  makefile, 10 Jan 2002.
-
-From Jeff: more semaphores.  ckcnet.c, 11 Jan 2002.
-
-Moved references to tmpusrid and tmpstring out of NOSPL #ifdefs -- they can
-be used with NOSPL.  setlin(): ckuus7.c, 13 Jan 2002.
-
-Made a dummy dologend() routine outside of #ifndef NOICP, so we don't have
-to enclose every reference to dologend in #ifdefs.  (I had added a bunch of
-calls to dologend() throughout the code to handle automatic LOCUS switching.)
-ckuus3.c, 13 Jan 2002.
-
-Moved "extern int nettype" outside of NOICP #ifdefs in ckuus4.c for NOICP
-builds.  13 Jan 2002.
-
-Moved a misplaced #ifdef in the VERSION command.  ckuusr.c, 13 Jan 2002.
-
-Did 81 different feature-selection builds on Linux (RH 7.0), all OK after the
-changes listed above for today.  13 Jan 2002.
-
-Added prototypes for set{rem,lcl}charset().  ckcxla.h, 13 Jan 2002.
-
-Added ckcxla.h to dependencies for ckuusy.c.  ckvker.com, 13 Jan 2002.
-
-Made a correction to the HELP SET LOCUS text and supplied a missing comma
-for HELP REMOTE.  ckuus2.c, 13 Jan 2002.
-
-Built OK on HP-UX 11.11 (K&R and ANSI), Solaris 8 (cc), Solaris 2.5.1 (gcc),
-SunOS 4.1.3 (cc and gcc), VMS 7.1 (DEC C, net and nonet), Unixware 7.1.1,
-Tru64 4.0G, HP-UX 10.20 (K&R), AIX 4.3.3, FreeBSD 2.2.8, Slackware 8.0, IRIX
-6.5.13f, IRIX 5.3 (??? Can't tell -- the computer ran out of swap space -- but
-it was OK a few days ago), VMS 5.5-2 (VAX C, UCX + nonet)...  HP-UX 9.05, ...
-
-Some corrections to comments in HP targets from PeterE.  makefile, 14 Jan 2002.
-
-Corrections to prototypes for set{rem,lcl}charset() (VOID, not void) from Jeff.
-ckcxla.h, 14 Jan 2002.
-
-Builds, cont'd...  SINIX 5.42, Red Hat Linux 5.2 on i386, SuSE 7.0 on S/390, 
-Red Hat 7.1 on IA64, QNX 4.25, HP-UX 5.21/WinTCP, ..., 
-
-Dell Coleman <dell@aleph.tum.com> noticed that in AIX, the COPY command always
-says "Source and destination are the same file" when the destination file
-doesn't exist.  This is because in AIX, realpath() fails with ENOENT (errno
-2).  The zfnqfp() code already accounts for this, but evidently not well
-enough.  So I did what I should have done long ago.  zfnqfp() was originally
-accomplished with do-it-yourself code.  Later I added support for realpath(),
-and partitioned the routine into mutually exclusive compile-time sections:
-#ifdef CKREALPATH realpath()... #else do-it-yourself... #endif.  But if
-realpath() failed, there was no recourse to the do-it-yourself code.  Today I
-replaced the #else with the #endif, so the do-it-yourself part is always
-included and is executed if the realpath() call fails.  Built and tested on
-AIX 4.3.3 and Solaris 2.5.1, as well as on Linux with and without the
-realpath() code included.  zfnqfp(): ckufio.c, 16 Jan 2002.
-
-Separated K95 and C-Kermit test version numbers, so C-Kermit can be RC.02
-while K95 is Beta.01.  ckcmai.c, 16 Jan 2002.
-
-Inhibited 0-length writes by conol() and conoll(), since they cause big
-trouble with the AIX 4.3.3 pty driver, e.g. when you have an SSH connection
-into AIX and run C-Kermit there.  ckutio.c, 16 Jan 2002.
-
-Suppressed "Switching LOCUS..." messages from FTP client when it was invoked
-from the command line.  ckcfns.c, 17 Jan 2002.
-
-Dave Sneddon noticed that FOPEN /APPEND gets "?Write access denied" in VMS
-if the file exists.  This is apparently because VMS zchko() does the wrong
-thing.  Commenting out the call zchko() in the VMS case gets past this but
-then the appended part of the file has different attributes than the orignal
-part, e.g.:
-
-  abc  <- original line (horizontal, normal)
-  d    <- appended line (vertical)
-  e
-  f
-
-VMS fopen() takes an optional 4th argument: a series of RMS keyword=value
-pairs.  Kermit doesn't give any.  Experimentation shows that appending to
-a Stream_LF works fine.  That'll be a restriction for now, until somebody
-sends in code to get the RMS attributes of the original file and feed them
-to fopen().  Also need code to fix VMS zhcko() to say whether it's OK to
-append to a file.  ckuus7.c, 17 Jan 2002.
-
-Somebody suggested I could get a working Kermit for Neutrino 2+ by doing the
-QNX6 build on Neutrino itself.  I verified that this can't be done -- at least
-not by me -- since Netutrino 2+ doesn't have a compiler, and we already know
-the version cross-built for it on QNX4 doesn't work.  17 Jan 2002.
-
-From Jeff: SET SSH GSSAPI KEY-EXCHANGE { ON, OFF } parsing, SHOW SSH.
-ckuus3.c, 18 Jan 2002.
-
-PeterE suggested that SET ESCAPE allow 8-bit escape characters because of the
-difficulty in entering Ctrl-\ on European keyboards and the hardship (e.g. to
-EMACS and VI users) of sacrificing another C0 control character.  Like
-everything these days, this turns out to be rather a bigger deal than it would
-seem.  The SET ESCAPE parser calls setcc(), which accepts control characters
-in various formats (literal, ^X notation, or numbers), and gives an error
-return if the value is not 0-31 or 127.  This is changed easily enough to also
-allow numbers between 128 and 255.  But who else calls setcc()?  The commands
-for setting Kermit packet start and end characters.  No big deal, this gives
-people a bit more flexibility in case they need it, but it won't be
-documented.  setcc(): ckuus7.c, 18 Jan 2002.
-
-Since code to display the escape character is scattered all over the place,
-and some of it indexes into an array based on the character value (which would
-now dump core if the escape character was > 128), I put the code in one place,
-a new shoesc() routine in ckuusx.c (which needs to be outside #ifndef NOICP,
-since the CONNECT modules use it even in command-line only builds).  Also
-discovered that this code was indexing into the nm[] array with tt_escape to
-get "enabled" or "disabled", which is no longer appropriate, so fixed this
-too.  ckuusr.h, ckuus[5x].c, 18 Jan 2002.
-
-Made SHOW ESCAPE, SHOW TERM, and the various CONNECT modules call shoesc(),
-and updated HELP SET ESC.  ckuus[25].c, ckucns.c, ck[cuvd9]con.c, 18 Jan 2002.
-
-After all that, it occurred to me that this is a really bad idea for K95,
-with all the confusion about Console code pages, OEM code pages, Windows
-code pages, and Unicode.  But I tried "echo \161" at the K95 prompt and got
-the expected 8-bit character in both the Console version and the GUI, so
-maybe it's OK after all.
-
-Removed the automatic IKSD login code from setlin() since it complicates
-interactive anonymous login.  ckuus7.c, 20 Jan 2002.
-
-An #ifdef clause from Matthew Clarke to avoid "redeclaration of free" error
-when building a curses version of C-Kermit for AIX 2.2.1 on RT PC.  ckuusx.c,
-22 Jan 2002.
-
-Took care of one detail I omitted when adding the 8-bit escape character:
-not stripping the 8th bit before comparing the keyboard char with the escape
-char.  ck[uv]con.c, ckucns.c, 24 Jan 2002.
-
-Started to go through Jeff's changes of the last week but he had run trim -t
-on them, which untabifies, so the diffs were huge.  Retabifying Jeff's files
-only makes matters worse.  So instead of comparing each old and new source
-file in EMACS windows with M-X Compare-Windows like I usually do (which can't
-be told to ignore whitespace), I had to work from the diff -c -b listings.
-In ascending order of size of diffs:
-
-ckcker.h: Add I_AM_SSHSUB definition.
-ckuusr.h: XXLINK and VN_PERSONAL, etc, definitions.
-ckuusy.c: Support for "I Am SSHSUB" invocation.
-ckuus5.c: Support for new K95 directory structure.
-ckcmai.c: Init endianness earlier (K95 TYPE was broken), "I Am SSHSUB" support.
-ckuus7.c: Security #ifdefs, SSH OPEN /PASSWORD, SSHSUB support
-ckcftp.c: <-- SAVE TIL LAST
-ckuus6.c: Add LINK command for K95 on NT.
-ckuus4.c: Support for new K95 directory structure; SSHSUB support
-ckuus3.c: Support for new K95 directory structure; some SSH changes
-ckuus2.c: Changes to SSH related help text, add HELP LINK text
-ckuusr.c: LINK command, SSH OPEN /PASSWORD: /SUBSYSTEM: switches,
-  Pattern-management fixes.
-ckctel.c, ck_ssl.c, ckuath.c, ckcnet.c:
- Took Jeff's without looking.
-ckuusx.c, ckucns.c, ckucon.c, ckwart.c:
-  My changes from weeks ago that were never picked up.
-
-Built OK on Solaris with gcc and on SunOS with (K&R non-ANSI) cc.
-31 Jan 2002.
-
-Meanwhile, Jeff had made various changes in response to Jaya Natarajan at IBM,
-whose basic complaint was that numerous failure conditions were not being
-detected if the fullscreen file-transfer display was active.  Jeff found that
-this was because big blocks of code were skipped in that case and changed the
-code not to do that, which fixed the reported problems.  But later Jaya said
-that "ftp mget file1 file2" acted like "ftp mget *", so it seemed that Jeff's
-fixes broke file selection.  After taking Jeff's fixes for ckcftp.c, however,
-I still could not reproduce the problem.  ckcftp.c, 31 Jan 2002.  <-- Later,
-it turned out the problem was with IBM's custom FTP server.
-
-Fixed updates that I missed yesterday in ckcftp.c, ckuusr.c.  Moved misplaced
-#ifdef in ckuusy.c breaking nonet builds.  Added #ifdefs to sysinit() for
-nonet builds in ckutio.c.  Ran through build-in-many-configurations script
-in Linux, all builds OK.  1 Feb 2002.
-
-Moved shoesc() definition outside of NOXFER to fix NOXFER builds.
-ckuusx.c, 1 Feb 2002.
-
-Added MYCUSTOM definition alongside KERMRC and changed KERMCL to be the
-same as CKMAXPATH, instead of some random hardwired number.  ckuusr.h,
-1 Feb 2002.
-
-Changed ckcdeb.h to define DIRSEP and ISDIRSEP(), and put #ifndef
-[IS]DIRSEP..#endif around all [IS]DIRSEP definitions in ck[udso]fio.c, so we
-can finally put away the many repeated #ifdef chains when we get around to it.
-1 Feb 2002.
-
-Make VMS zkermini() return 1 on success, 0 on failure, rather than 0 always.
-ckvfio.c, 1 Feb 2002.
-
-Added code to doinit(), just before it goes to execute the init file.  If the
-init file name we are about to open is empty or fails zchki(), substitute the
-customization filename.  For now this code is in #ifdef USE_CUSTOM..#endif,
-which is not defined by default.  It does the trick in Unix and VMS.  Also
-included code from Jeff for K95, but this needs verification and testing.
-Also used DIRSEP and ISDIRSEP() throughout doinit() instead of the long #ifdef
-chains.  ckuus5.c, 1 Feb 2002.
-
-Moved shoesc() prototype from ckuusr.h to ckcker.h so modules that need it
-don't have to include ckuusr.h just for this one thing (example: ckvcon.c).
-1 Feb 2002.
-
-Defined USE_CUSTOM by default, except if NOCUSTOM is defined.  ckuusr.h,
-1 Feb 2002.
-
-Fixed kermit-sshsub code to really enter server mode, and to print
-"KERMIT READY TO SERVE..." so scripts can wait for it.  Also bumped the
-C-Kermit test ID to RC.03 and the K95 one to Beta.02.  ckcpro.w, ckcmai.c,
-2 Feb 2002.
-
-I was thinking about adding SET COMMAND BUFFER-SIZE to let people allocate
-as big a buffer as they wanted at runtime, mainly for defining huge macros.
-Moved the SCMD_blah definitions from ckuusr.h to ckuus3.c, since they aren't
-used anywhere else.  But stopped there since the rest turns out to be a rather
-big deal.  ckuusr.h, ckuus3.c, 2 Feb 2002.
-
-From Jeff, 3 Feb 2002:
- . Fix an out-of-order modem name in the SET MODEM TYPE table: ckudia.c.
- . Use SET LOGIN USER and PASSWORD if present. ckcftp.c.
-
-Cody Gould noticed that array declarations had become case sensitive, and
-upper case didn't work.  Diagnosis: misplaced case conversion in xarray().
-Fixed in ckuus5.c, 4 Feb 2002.
-
-SHOW VAR dumps core on \v(sexpression) or \v(svalue) -- failure to check for
-NULL pointer.  I wonder why this didn't happen before (answer: because I was
-doing it on SunOS; now I'm doing it on Solaris).  ckuus4.c, 6 Feb 2002.
-
-I've had several requests for "show var name name name...".  I added this to
-doshow(), such that SHOW VAR works exactly as it did before (if you don't give
-it an arg, it lists all variables; if you give it an arg, it appends "*" to it
-and lists all matching variables) but now you can also give more than one arg
-and it works the same way with each one as it did before if you gave it a
-single item (i.e., "*" is appended, so "show var os cmd" shows all variables
-whose names begin with "os" or "cmd".  You can also freely use pattern
-notation, including anchors.  Hmmm, no, actually it's different in that now
-each includes an implied * before AND after, so "show var version" shows all
-variables whose name contain "version" rather than all variables whose names
-start with it.  ckuus5.c, 6 Feb 2002.
-
-Cody Gould reported that WRITE FILE blah blah \fexec(anything) ... got a
-spurious "File or Log not open" error.  This turns out to be a rather
-pervasive problem -- whenever you use \fexec() it calls the parser recursively
-and this can run roughshod over global variables, such as our innocent little
-x, y, and s.  The fix in this case was to put x and y on the stack.  The same
-thing probably needs doing in about 10,000 other places.  Too bad C isn't
-Algol.  ckuusr.c, 6 Feb 2002.
-
-Minor fix to SHO VAR -- the "^" anchor wasn't working (e.g. "show var ^os").
-ckuus5.c, 6 Feb 2002.
-
-Fixes from Jeff for FTP file-transfer character-set translation in K95 and
-in WIKSD, plus updated K95 SSH help text.  ckcftp.c, ckcfns.c, ckuus2.c,
-7 Feb 2002.
-
-Server has its date set in the past.  Client says "remote dir".  Server sends
-A packet containing old date.  If client has FILE COLLISION UPDATE, it
-rejects the directory listing.  Changed gattr() to only reject real files
-(introduced by F packet), not X-packet material like directory listings.
-ckcfn3.c, 7 Feb 2002.
-
-Up-down arrow keys for command recall.  People have been asking for it for
-years but now it's actually important because of PDAs that don't have Ctrl
-keys.  Would have been trivial except that we use getchar() rather than
-coninc() for reading from the keyboard in Unix so conchk() doesn't help.  In
-fact there are lots of other places where conchk() is used this way and works
-only by accident.  The only reason we never noticed a problem before is that
-characters don't usually arrive from the keyboard that fast.  But when an
-arrow key sends "ESC [ A" all once, the stdin buffer gets some extra stuff in
-it, which getchar() will return next time, but which coninc()/conchk() will
-never see.  So I added a new cmdconchk() routine which, if the keyboard is
-being read with getchar() rather than coninc(), looks at the stdin buffer.
-Unfortunately, however, there is no API for this, nor is there any standard
-way to access the stdin buffer directly.  So first I did it for Solaris.  Then
-to make it portable requires a survey of the headers for every platform.  I
-found four major variations:
-
-  stdin->_r:
-    {Free,Open,Net}BSD, BSDI
-  stdin->_cnt:
-    SunOS, Solaris, HP-UX 5-6, AIX, VMS, SINIX, IRIX 5.3-6.5, DGUX
-    4.2BSD, 4.3BSD, OSF/1..Tru64, QNX4, Unixware 1.0-2.1.0
-  stdin->__cnt:
-    HP-UX 7-11, SCO: OSR5.0.6a, Unixware 2.1.3-7.x, OU8, UNIX 3.2v4.x
-  Subtract read from end pointer (_IO_file_flags defined):
-    Linux (tested on RH 5.2 thru 7.1)
-
-The Linux method is new and different to account for multibyte characters.
-All the others assume character == byte.
-
-For docs: ANSI only, 7-bit only; both application and cursor modes are
-accepted.  Only up and down arrow are handled; left and right arrows cause
-a beep.  ckucmd.c, 8 Feb 2002.
-
-Build-all: Discovered that changing CTTNAM from TT: to SYS$INPUT: in VMS
-(which was done on 3 Jan 2002 to work around problems starting Kermit in
-batch, spawn'd, etc) breaks Kermit on VMS 5.5/VAX (concb() fails with "lacks
-sufficient privilege"; if you enable all privs Kermit starts but then spews
-out a constant stream of BEL characters).  If you put dftty back to "TT:",
-everything is fine -- I have no idea why, so I used #ifdef VMSV70 to decide,
-which is totally crude.  Next I had to find where the boundary really is: VAX
-vs Alpha?  VAX C vs DEC C?  Or between VMS releases?  Built on:
- . VMS 6.2 Alpha (DEC C) - OK with TT:
- . VMS 6.2 Alpha (DEC C) - OK with SYS$INPUT: <-- keep this one
- . VMS 7.1 VAX   (DEC C)
-So the final condition is #ifdef VMSV60.  ckvker.com, ckvtio.c, ckuus5.c.
-
-QNX 6 needed some attention too:
- . Whoever did the makefile target made the default port "/dev/ser1".
- . Arrow keys...
-But I gave up on getting arrow keys to work -- it should be just like *BSD,
-but for some reason gcc complains that struct FILE has no _r member, even
-though it does (getchar uses it).
-
-Checked stdio.h on Mac OS X and it looks like the *BSDs.
-
---- C-Kermit 8.0.201 ---
-
-Removed -g from solaris2xg+krb5+krb4+openssl+shadow makefile target -- it
-was producing a 15MB binary!  makefile, 14 Feb 2002.
-
-Fixed a couple thinkos in "make install": $(DESTDIR) should not have been
-included in the tests for whether INFODIR or SRCDIR were desired.  makefile,
-14 Feb 2002.
-
-(tarball refreshed 16 Feb 2002)
-
---- C-Kermit 8.0.201 ---
-
-From Jeff: Better seeding of \frandom(): ckcmai.c, ckuus4.c, 18 Feb 2002.
-
-From Jeff: Make arrow keys work in WIKSD, but now also unconditionally
-compile arrow-key code in all versions.  ckucmd.c, 18 Feb 2002.
-
-From Jeff: ckuath.c, ck_ssl.c, ckcnet.c (didn't look).  18 Feb 2002.
-
-Added ORIENTATION command, that lists the various important directories, and
-\flongpathname() and \fshortpathname(), which do path format conversions in
-Windows, and are just synonynyms for \fpathname() elsewhere.  The new functions
-need building and testing in Windows.  ckuusr.h, ckuus[r24].c, 18 Feb 2002.
-
-Changed PWD for Windows only to show both short and long paths (but only if
-they are different; otherwise it behaves as before).  ckuusr.c, 18 Feb 2002.
-
-Changed default Windows prompt to show long pathname. ckuus5.c, 18 Feb 2002.
-
-Updated INTRO command to mention FTP, HTTP, and SSH.  ckuus2.c, 18 Feb 2002.
-
-From Jeff: fixes for typos in GetLongPathName() code: ckuus[r4].c, 22 Feb 2002.
-
-From Jeff: net/auth updates: ckcnet.c, ckuath.c, 22 Feb 2002.
-
-Added -DUSE_FILE__CNT to NCR MPRAS targets, George Gilmer: makefile,
-24 Feb 2002.
-
-From Jeff: Add support for GetLongPathName() in Win95 and NT: ckcdeb.h,
-ckuus[r4].c, 24 Feb 2002.
-
-From Jeff: More fixes for FTP SIGINT, plus fix [M]PUT /MOVE.  ckcftp.c,
-24 Feb 2002.
-
-Fixed an unguarded reference to inserver, gtword(): ckucmd.c, 24 Feb 2002.
-
-Adapted RETRIEVE for use with FTP connections; this one was missed when
-adapting GET, REGET, MOVE, etc.  ckuus6.c, ckcftp.c, 24 Feb 2002.
-
-Added special COPYRIGHT command text for the free version of WIKSD.
-ckcmai.c, ckuusr.c, 24 Feb 2002.
-
-C-Kermit, when in CONNECT mode and given the <Esc-Char>U sequence, would
-unconditionally close the connection if it was a network connection.  This
-is bad when Telnetting to a modem server.  I added to code to prevent this
-in the RFC2117 TELNET COMPORT case but I'm not sure how to exend this to the
-general case (or whether it would be a good idea).  ckucns.c, 24 Feb 2002.
-
-During file transfer, chktimo() calls ttgspd() for every packet, which clearly
-doesn't make sense on network connections, especially since on Telnet COMPORT
-connections it results in a network speed query for every packet.  Rearranged
-the code so this happens only on true serial-port connections.  ckcfn2.c,
-24 Feb 2002.
-
-From Jeff: Fix reversed ANSI/non-ANSI function declarations clauses in
-ckcftp.c, 26 Feb 2002.
-
-Changed Unix CONNECT module to call kstart() only when it has a chance of
-doing anything (i.e. a Kermit packet has been partially detected, or the
-packet start character just came in), rather than unconditionally on every
-incoming character.  ckucns.c, 8 Mar 2002.
-
-FTP PUT /SERVER-RENAME:, /RENAME-TO:, /MOVE-TO: were sticky.  Patch: In
-ckcftp.c, near the top of doftpput(), add the lines marked with "+":
-
-    makestr(&filefile,NULL);            /* No filename list file yet. */
-+   makestr(&srv_renam,NULL);          /* Clear /SERVER-RENAME: */
-+   makestr(&snd_rename,NULL);         /*  PUT /RENAME */
-+   makestr(&snd_move,NULL);           /*  PUT /MOVE */
-    putpath[0] = NUL;                   /* Initialize for syncdir(). */
-
-ckcftp.c, 26 Mar 2002.
-
-\fday() and \fnday() were broken for dates prior to 17 Nov 1858.  Fixed in
-fneval(): ckuus4.c, 28 Mar 2002.
-
-From Jeff:
- . New calling convenion for demoscrn(): ckucmd.c, ckuusx.c
- . Fix for host-initiated 80/132 col screen mode change.  ckuus7.c.
- . New \v(desktop) variable: K95 user desktop directory, ckuusr.h, ckuus4.c
- . New \v(rfc2717_signature) var: Telnet Com Port, ckuusr.h, ckuus4.c
- . Uncomment "not-reached" return(-2) in xgnbyte(): ckcfns.c
- . New dates: ckcmai.c.
- . Telnet Com Port fixes: ckutio.c
- . SET PRINTER fixes for K95: ckuus3.c
- . Session limit adjustments: ckuus3.c
- . New directory layout for K95 (TAKE, ORIENT): ckuusr.c
- . Fixes for Telnet Com Port, recycling SSH connections: ckuusr.c
-
-From me, not picked up by Jeff previously:
- . kstart() speedup: ckucns.c.
-
-1 Apr 2002.
-
----K95 1.1.21---
-
-From Jeff, 4 Apr 2002:
- . More fixes for Telnet Com Port: ckuus4.c, ckudia.c, ckutio.c, ckcnet.c:
-   . network connections will check for carrier detect if SET
-     CARRIER-WATCH is ON.   This could have a potential conflict if
-     the option is negotiated and the carrier is off, but the site
-     requires login.
-   . modem hangup message generated since the dial module did not
-     believe that network modems could be reset with a DTR drop.
- . Version number adjustments: 8.0.203, 1.1.99: ckcmai.c.
- . Security: ck_ssl.[ch], ckuath.c.
-
----C-Kermit 8.0.203---
-
-From Jeff, 6 Apr 2002:
- . Fix typo in HELP REMOTE HOST: ckuus2.c.
- . More Telnet Com Port fixes: ckctel.c, ckcnet.c, ckudia.c, ckutio.c
-
-From Jeff, 9 Apr 2002:
- . Fix autodownload problem: ckcfn[2s].c.
-
-Chiaki Ishikawa reported that in Linux (two different kinds), if you choose
-hardware parity, CONNECT, then escape back, the speed can change.  I tracked
-this down to the following statement in ttvt():
-
-       tttvt.c_cflag &= ~(IGNPAR);     /* Don't discard incoming bytes */
-
-Somehow execution of this statement corrupted the speed words of the termios
-struct, which are entirely separate words that are nowhere near the c_cflag
-member.  Anyway, the statement is wrong; it should be:
-
-       tttvt.c_cflag |= IGNPAR;        /* Don't discard incoming bytes */
-
-Fixing it cured the problem; don't ask me why.  ckutio.c, 9 Apr 2002.
-
-From Jeff:
-  fixes the problem reported by robi@hastdeer.com.au.  The request to
-  enter server mode was received while we were entering server mode.
-  But the server was waiting for the response to REQ_STOP sent to the
-  client.  Therefore, we weren't quite in server mode yet and the
-  request to enter server mode was rejected.  A check for the sstate
-  value solves the problem.  ckctel.c, 10 Apr 2002.
-
-Chiaki Ishikawa (CI) discovered the real cause for the speed changing problem.
-I was setting the IGNPAR bit in the wrong flag word: it should have been
-c_iflag instead of c_oflag, silly me.  Fixed in ttvt() and ttpkt(): ckutio.c.
-I also did a thorough census of all the termio[s] flags to ensure each was
-applied to the right flag word -- they were, IGNPAR in the HWPARITY case was
-the only mistake.  CI also discovered that the speed words in the Linux
-termios struct are not used at all -- the speeds are encoded in an
-undocumented field of c_cflag, which explains the problem.  10 Apr 2002.
-
-Any use of \{nnn} character notation in a macro definition, loop, or other
-braced block caused an "unbalanced braces" parse error.  The backslash in this
-case is not quoting the open brace; it's introducing a balanced braced
-quantity.  Special-cased in getncm(): ckuus5.c, 12 Apr 2002.
-
-The semantics of "if defined \v(xxx)" were changed in 8.0 to avoid obnoxious
-error messages when xxx was not a built-in variable (see notes of 19 Nov
-2000), such that "if defined \v(xxx)" would always succeed if there were such
-a variable, even if it had no value.  The behavior that is documented in the
-book (and also in ckermit70.html) and that we had in versions 6 and 7, was
-that IF DEFINED \v(xxx) would fail if \v(xxx) was defined but had an empty
-value OR if it was not defined, and would succeed only if it was defined and
-had a value.  Fixed in boolexp(): ckuus6.c, 12 Apr 2002.
-
-What about \function()s?  IF DEF \fblah() presently succeeds if the function
-exists; you don't even have to give arguments.  I think this behavior is more
-useful than if I required valid arguments and then evaluated the function --
-you can do that anyway with 'if not eq "\fxxx(a,b)" "" ...'  Of course this
-argument applies to "if def \v(xxx)" too, except that the current behavior is
-consistent with the 7.0 behavior, so there is no need for a change.
-
-Kent Martin discovered that if a macro contains a LOCAL statement for a
-variable whose name is the same as, or a unique left substring of, the macro's
-name, then undefining the local variable makes the macro disappear:
-
-  define DateDiff {
-    echo {DateDiff(\%1) executing...}
-  }
-  define Kent {
-    do DateDiff {2}
-    local date
-    assign date {}
-    do DateDiff {3}  <-- This fails (A)
-  }
-  do DateDiff {1}
-  do Kent
-  do DateDiff {4}    <-- So does this (B)
-
-The first part of the problem is that "assign date {}" called delmac with
-exact=0, so delmac evidently deleted first macro whose name started with
-"date" -- and since the only one was DateDiff, that's the one that was
-deleted.  Fixing this (change "delmac(vnp,0)" to "delmac(vnp,1)" in dodef())
-got us past A.  The second part was making the same fix to the delmac()
-call in popclvl().  ckuus[56].c, 13 Apr 2002.
-
-The INPUT command ignored the parity setting, thus SET PARITY EVEN,
-INPUT 10 "login:" didn't work.  Fixed in doinput(): ckuus4.c.  Also fixed a
-bogus #ifdef COMMENT section that messed up the block structure of the module
-and therefore EMACS's indenting.  18 Apr 2002.
-
-Added sco32v500net+ssl and Added sco32v505net+ssl targets, from Scott Rochford
-at Dell (not sure yet if they work).  Makefile, 19 Apr 2002.
-
-From Jeff, 22 Apr 2002:
- . Added "darkgray" color and made "dgray" an invisible synonym: ckuus3.c.
- . Fix carrier sense on Telnet Com Port immediately after dial: ckudia.c.
- . Change krb5_des_blah() arg list: ckutio.c.
- . Fix ttgmdm() for Telnet Com Port: ckutio.c.
- . Fix tthang() return code: ckutio.c.
- . Add aix43gcc+openssl target: makefile.
-
-From Jeff, 25 Apr 2002:
- . Fix SET GUI keyword table: ckuus[37].c.
- . A final fix to Telnet Com Port: ckctel.c, ckcnet.c.
-
-From Jeff, 26 Apr 2002:
- . Another final fix to Telnet Com Port: ckctel.c, ckudia.c.
-
-From Jeff, 27 Apr 2002:
- . separate the wait mechanism for TELNET SB COMPORT synchronous messages
-   from the asynchronous TELNET SB COMPORT MODEMSTATUS messages: ckctel.[ch]
- . fix debug messages in Certificate verify functions: ck_ssl.c, ckcftp.c.a
-
-Frank, 27 Apr 2002:
- . Fixed VMS zgetfs() to fail when file doesn't exist: ckvfio.c.
- . Fixed UNIX zgetfs() to check for null or empty arg: ckufio.c.
- . Added #include <time.h> for time() call: ckcmai.c.
- . Add casts to args in tn_wait() calls: ckctel.c.
-
-SINIX-P 5.42 (Pyramid architecture) makefile target from Igor Sobrado.
-makefile (no source-code changes), 1 May 2002.
-
-From Jeff, 5 May 2002,
- . Fix some "unknown host" messages: ckcftp.c.
- . Add more casts to tnc_wait() calls: ckudia.c.
- . Improvements to SHOW SSH, SHOW GUI: ckuus3.c.
- . Fixes to SET COMMAND { WIDTH, HEIGHT }: ckuus3.c.
- . Updates to ck_ssl.[ch], ckctel.c, ckcnet.c.
-
-Fixed the erroneous setting of ssh_cas during switch parsing rather than
-after cmcfm() in setlin(): ckuus7.c, 5 May 2002.
-
-setlin() decomposition (2300 lines), Part One: 
-
- . Copied a big chunk from the end of setlin(), beginning with net directory
-   lookup, but only the network-specific and common parts, to a new routine,
-   cx_net(), 900 lines.
-
- . Extracted many repetitious lines of error-message code from cx_net()
-   to a new routine, cx_fail().  Error messages are stored in slmsg, and
-   also printed but only if we were not called from a GUI dialog (and
-   QUIET wasn't set, etc etc).  Any adjutments in this policy can now be
-   made in one place.
-
- . I put a call to cx_net() in setlin() just before all the code it replaced.
-   It works for TELNET and SET HOST /TELNET.
-
- . Built with mkwatsol-k5k4ssl; after a couple fixes it builds OK and makes
-   Kerberized connections OK.
-
- . Copied the serial-port and common parts of the setlin() post-cmcfm()
-   code to another new routine, cx_serial(), about 275 lines.  Fixed
-   messages not to come out when called from GUI dialog, etc.  Inserted
-   a call to cx_serial() at the appropriate spot in setlin().  Tested
-   serial connections on watsun with "set line /dev/ttyh6", works OK.
-
- . Removed all the code from setlin() that was copied to cx_*().  This slims
-   setlin() down to 1120 lines.  Tested regular Telnet, Kerberized Telnet, and
-   serial connections again, all OK.  The Unix version of the SSH command is
-   OK too.
-
-setlin() deconstruction, Part Two:
-
-Now that we have the common network and serial connection pieces moved out of
-setlin(), we still need to move out the little code snippets for each network
-type that take place between command confirmation and the common code we just
-replaced.   As far as I can tell, this needs doing only for SSH.  The code
-labeled "Stash everything" copied to cx_ssh() but I didn't remove the original
-code since I can't test this.  I think I'm done -- maybe I'm overlooking
-something but I don't know what...  First we need to test the heck out of it
-in all command-line versions (K95 and C-Kermit).  Then to use this from
-the GUI, see the calling sequences for cx_serial(), cx_net(), and cx_ssh():
-
- . For serial or TAPI connections, the GUI should call cx_serial().
- . For SSH connections, it should call cx_ssh() and then cx_net().
- . For all other network connections, just calls cx_net().
-
-ckuus7.c, Cinco de Mayo de 2002.
-
-New ckuus7.c from Jeff, 8 May 2002.  Merge cx_ssh() into cx_net().  Also: I
-had made line[] an automatic variable, since the global line[] buffer is used
-by almost every parsing routine in C-Kermit to hold string fields between
-parsing and execution but Jeff says he found that some code somewhere depended
-on line[] containing the hostname after setlin() was finished.
-
-From Jeff, 10 May 2002:
- . Fix SET SSH STRICT-HOST-CHECKING parse: ckuus3.c.
- . Add prototypes for cx_net() and cx_serial(): ckuusr.h.
- . Add ANSI versions of cx_net() and cx_serial() declarations and supply a
-   missing parameter in the cx_serial() invocation, change SSHCMD cx_net()
-   invocation to new form.
-
-From Jeff, 16 May 2002:
- . ANSI strictness changes: ck_ssl.[ch]
- . New DIALER command: ckuusr.[ch]
- . Correction to how -0 turns off autodownload: ckuusy.c
- . Prototypes for GUI menu action functions: ckuusr.h.
- . Replace setting of GUI-action variables by function calls: ckuus[3457x].c
- . Fix FTP -z switch parsing: ckcftp.c.
- . Fix SET HOST testing of setlin() return code: ckuus3.c
-
-From Jeff, 18 May 2002:
- . Allow half-size GUI fonts: ckuus[35y].c.
-
-Fixed setguifont() to parse fractional font sizes and round to nearest half
-point.  ckuus3.c, 18 May 2002.
-
-For GUI, wrote front ends for getyesno(), readtext(), and readpass():
-
- . uq_ok() prints text and gets Yes/No, OK/Cancel, or just OK response.
-   This replaces getyesno() and can also be used for alert or help boxes.
-
- . uq_txt() prints text and gets a single text response.  Replaces
-   readtext() and readpass().
-
- . uq_mtxt() is like uq_txt() but allows multiple text fields.  Replaces
-   any combination of readtext() and readpass().
-
-Obviously the #ifdef KUI portions of the uq_blah() routines need filling in.
-ckuusr.h, ckuus3.c, 18 May 2002.
-
-Converted selected getyesno() calls to uq_ok(): ckcftp.c, ckuus3.c, ckuus6.c.
-Some were not converted because it was inappropriate, e.g. DELETE /ASK; others
-because they're in Jeff's code.  The most interesting conversions are in the
-DIAL command when DIAL CONFIRMATION is ON.  Here there is a dialog for each
-phone number asking if it's OK (ug_ok()) and if not, asking for a replacement
-(uq_txt()); seems to work fine in C-Kermit.  All the candidates for uq_mtxt()
-are in Jeff's code.  18 May 2002.
-
-From Jeff: Convert remaining getyesno/readtext/readpass calls to uq_blah()
-so they can be GUI dialogs.  ckuus[37].c, ckcftp.c, ckuath.c, ck_ssl.c,
-21 May 2002.
-
-Added KCD command = CD to symbolic directory name (EXEDIR, COMMON, APPDATA,
-TMPDIR, etc etc).  ckuusr.h, ckuus[r25].c, 21 May 2002.
-
-From Jeff, 28 May 2002:
- . --title: commandline option: ckuusr.h, ckuusy.c
- . Fix some #includes, move some declarations: ckcfns.c
- . Change K95 version from Dev.00 to Beta.01
- . ASK[Q] /GUI: ckuus6.c.
- . Various GUI screen updates and #ifdefs: ckuus7.c
- . Add missing cx_net() calls to new setlin() for file SuperLAT..: ckuus7.c
- . Updated uq_*() routines for GUI dialogs: ckuus3.c.
-
-Added GETOK switches (/TIMEOUT for all; /POPUP and /GUI for K95G):
-ckuus6.c, 29 May 2002.
-
-Added HELP SET GUI text.  ckuus2.c, 29 May 2002.
-
-From Jeff:
- . Another K95-specific #include for ckcfns.c.
- . More items for K95G Actions menu.
- . Change K95G Locus switching to call setlocus() rather than set variable.
- . Ditto for several other variables now settable from Actions menu.
- . Fix SET HOST /NET:SSH status code so IF SUCCESS works.
- . Fix SHOW SSH port-forwarding.
-ckcfns.c, ckuus[r367].c, ckcftp.c, ckcmai.c, 30 May 2002.
-
-Changed SET LOCUS to have a new value, ASK, corresponding to new autolocus
-value of 2, K95G only.  Changed setlocus() to not do anything if the new and
-old loci are the same, otherwise to invoke a GUI dialog in K95G if autolocus
-is 2, and also to handle any text messages.  Changed SHOW COMMAND to show ASK
-value for SET LOCUS.  Rewrote HELP SET LOCUS.  ckuusr.[ch], ckuus[23].c,
-ckcftp.c, 30 May 2002.
-
-Add a missing space to Locus popup, and fix Jeff's version of the code to
-compile in C-Kermit.  ckuusr.c, 31 May 2002.
-
-From Jeff, for K95 GUI, 6 June 2002:
- . Force some GUI popups to be in foreground: ckuus3.c.
- . Fix SHOW TERM font display: ckuus5.c.
- . Update K95 version numbers and date (4 June 2002): ckcmai.c.
- . Add note about encrypted private keys vs scripts to HELP SET AUTH: ckuus2.c.
- . Fix SET HOST for DECnet: ckuus7.c.
-
---- K95 2.0 ---
-
-From Jeff, 7 June 2002:
- . Fix some #ifdefs for Unix builds (locus, dial, etc): ckuus7.c
- . Add gui_resize_scale_font() prototype: ckuus3.c
- . Add some missing SET GUI commands: ckuus3.c
- . Update version numbers: ckcmai.c
-
---- K95 2.0.1 ---
-
-From Jeff, 11 June 2002:
- . Conditionalize Locus-switching popup text for GUI/Console: ckuusr.c.
- . Fix the SRP_installed_as_server() function.  The new API returns TRUE even
-   if the SRP config and password files cannot be found.  Went back to the old
-   API.  This bug affects C-Kermit 8 when built with SRP as well as 1.1.21
-   through 2.0.1.  Since iksdnt.exe has not been shipped yet I fixed it and
-   uploaded a new non-beta build of it.  ckuath.c.
-
-From Jeff, 12 June 2002:
- . Fix SSH AGENT ADD: ckuusr.c.
- . Fix --facename: option to not fail if name unknown: ckuusy.c.
- . Fixes for OpenSSL 0.9.7 and OpenBSD 3.1: ck_ssl.c.
- . Fix SET AUTH TLS VERIFY NO to prevent a dialog but still a warning if
-   SET AUTH TLS VERBOSE ON is set: ck_ssl.c.
- . Fix FTP code to verify the hostname as specified by the user and not
-   the hostname discovered by the reverse DNS lookup.  For example,
-     FTP OPEN kermit.columbia.edu
-   should produce a dialog because that name is not in the certificate
-   even though ftp.kermit.columbia.edu (the reverse DNS name) is:  ckcftp.c.
-
-Add support for Solaris 9 and NetBSD 1.6.  makefile, ckuver.h, ckcdeb.h,
-13 Jun 2002.
-
-Discovered that Solaris 9 wants to hide the members of struct FILE, and
-enforces this for 64-bit builds.  They offer some functions like __fbufsize()
-to get the info, but not the info we need for reading escape sequences (the
-_cnt member).  Let's hear it for political correctness.  Created new solaris9g
-(32-bit) and solaris9g64 (64-bit) targets.  Sorry, no arrow keys in 64-bit
-mode.  Also no more direct access to sys_errlist[]; must use strerror().
-makefile, ckucmd.c, 13 Jun 2002.
-
-Added solaris9g+openssl+zlib+pam+shadow, which in turn required adding
-solaris2xg32+openssl+zlib+pam+shadow, needed for gcc 3.1 in which you have
-to specify 32-bit.  Fails for some mysterious reason in link step
-(can't find libssl.so.0.9.6 even though it's there).  makefile, 13 Jun 2002.
-
-Solaris 8 empty socket problems again -- tthang() times out, subsequent
-tcsetattr() calls do horrible things.  Added a bandaid to ttclos(): don't
-call tcsetattr() any more if hangup timed out.  ckutio.c, 14 June 2002.
-
-Gerry B reported the bandaid got us bit farther but Kermit still disappears.
-Added code to reassert the alarm signal handler, since it is likely that
-Solaris has become stricter about this since last time I looked.  (Later
-Gerry reported back that this did the trick -- C-Kermit now exits normally
-and releases the lockfile).  ttclos(): ckutio.c, 17 Jun 2002.
-
-If you use Kermit to copy a file to a destination file that already exists and
-is longer than the source file, the destination file is not truncated.  I had
-mistakenly assumed that setting O_CREAT in the open() call in zcopy() would
-create a new copy of the file.  Fixed by also setting O_TRUNC.  ckufio.c,
-17 Jun 2002.
-
-Updated HELP INPUT and MINPUT text to explain 0 and -1 timeout values, and
-HELP DIAL to explain about entering CONNECT mode automatically.  ckuus2.c,
-17 Jun 2002.
-
-Got rid of client-side "Press the X or E key to cancel" message when giving
-a REMOTE command if QUIET is set or if XFER DISPLAY is NONE.  ckuus7.c,
-17 Jun 2002.
-
-From Jeff 25 Jun 2002:
- . Add SUN terminal type: ckuusr.h, ckuus[57].c.
- . Add GUI file transfer display: ckcker.h, ckuus[47x].c.
- . Changes to allow C-Kermit to build with OpenSSL 0.9.7.  Current
-   C-Kermit code is designed to compile with 0.9.6 and earlier.  To
-   compile with 0.9.7 you must specify -DOPENSSL_097.  This avoids
-   missing symbols in the DES library.  The functions in OpenSSL were
-   renamed in 0.9.7 to avoid link time conflicts with Kerberos 4.
-   ckufio.c ck_crp.c ckuath.c ck_ssl.h ck_ssl.c, makefile.
-
-From Jeff 26 Jun 2002:
- . apparently the SSL Passphrase Callback function was not converted
-   from readpass() to uq_txt()
- . FTP Authentication failure errors were not being reported to the
-   user.  So a failure would appear to be a successful completion
-   unless FTP DEBUG was ON.  Now the message is reported unless
-   the QUIET flag is set.
-ck_ssl.c, ckcftp.c.
-
-SET TRANSFER MODE MANUAL didn't work for FTP; fixed in putfile() and getfile():
-ckcftp.c, 1 Jul 2002.
-
-Changed debug log for FTP to log "FTP SENT" and "FTP RECD" for protocol
-messages, just like we do for Telnet, to make it easy to grep them out of
-the log.  ckcftp.c, 1 Jul 2002.
-
-In FTP MGET /UPDATE, equal times spuriously caused download.  doftpget() was
-misinterpreting chkmodtime()'s return code.  ckcftp.c, 3 Jul 2002.
-
-In FTP MGET /RECOVER, recovery is skipped if the local file is newer than
-the remote.  This would seem to make sense, but when a download is
-interrupted, the partial file never gets the date of the remote file, so
-the partial file is always newer, and recovery never works.  Fixed in
-recvrequest() by commenting out the date check.  ckcftp.c, 3 Jul 2002.
-
-A better way to fix the previous problem is to always set the file date from
-the server and then only allow /RECOVER to work when the dates are equal.
-But that's not possible because MDTM is not implemented universally, and it
-conflicts with how Kermit currently works, namely that FTP DATES are OFF by
-default.  Also, checking dates prevents [M]GET /RECOVER from working with
-files that were incompletely downloaded by some other FTP client.
-
-In FTP MGET /RECOVER <wildcard> <wildcard> ..., the first file in each group
-is always downloaded.  Diagnosis: Kermit sends "TYPE A" prior to NLST (as it
-must).  Then when it sends its first SIZE command, it's still in ASCII mode,
-so the server sends the "ASCII size" rather than the binary size, which does
-not agree with the size of the local file (which was downloaded in binary
-mode), so recovery is always attempted even when the files are identical.  The
-TYPE A command is sent by initconn().  After the remote_files() call, we have
-to change the type back to the prevailing type before sending the first SIZE
-command.  Fixed in cmdlinget() and doftpget(): ckcftp.c, 3 Jul 2002.
-
-In FTP MGET /EXCEPT:<pattern> used with SET XFER DISPLAY brief, files that
-are skipped just say ERROR instead of saying why they were skipped.  Fixed
-in doftpget(): ckcftp.c, 3 Jul 2002.
-
-Added EXIT to top-level HELP text.  ckuus2.c, 13 Jul 2002.
-
-Strip braces in REINPUT n {string}.  ckuusr.c, 13 Jul 2002.
-
-Added /QUIET switch to ASK-class commands.  This means not to print any error
-messages when an ASK-class command times out waiting for a response.  Made
-sure that when a timeout occurs, the command fails.  Also made sure the
-c-Kermit prompt doesn't write over the ASK prompt if ASK times out.  Also
-fixed ASK, when it times out, not to return -9, which it did in one case,
-which causes a command-stack dump.  ckuus[267].c, ckucmd.c, 13 Jul 2002.
-
-Fixed SET FILE INCOMPLETE help text, which said that both KEEP and AUTO were
-the default.  ckuus2.c, 13 Jul 2002.
-
-If you SET FTP DEB ON and then turn it OFF, the MGET temp file is still kept.
-Fixed by getting rid of ftp_knf variable and using ftp_deb to control whether
-temp file is deleted (ftp_knf was being set from ftp_deb anyway, but then
-wasn't being reset by SET FTP DEB OFF).  ckcftp.c, 13 Jul 2002.
-
-If an FTP transfer was in progress but the FTP connection drops and automatic
-locus switching is enabled, the locus does not change; thus (for example) a
-subsequent DELETE command makes Kermit send a REMOTE DELETE packet on stdout.
-Fixed in lostpeer(): ckcftp.c, 13 Jul 2002.
-
-For docs: FTP CD with no arg might not be accepted by the server; e.g. the
-Kermit FTP server says "501 Invalid number of arguments".
-
-The FTP module never handled SET INCOMPLETE.  Fixed in doftprecv2().  ckcftp.c,
-13 Jul 2002.
-
-When FTP DATES is ON, we set an incoming file's date only if the file was
-received successfully.  Changed the code to set the file's date even if it was
-received only partially (assuming we can get the date from server).  ckcftp.c,
-13 Jul 2002.
-
-Suppose we were doing FTP MGET /UPDATE from a server directory of 100,000
-files.  Kermit would send a SIZE command for every file unconditionally.  On
-some connections, e.g. to the Red Hat Rawhide server, each one could take up
-to 30 seconds.  That would be 3 million seconds = 34 days.  Don't send a SIZE
-command during the selection phase unless a /SMALLER or /LARGER selector was
-given.  Once the file is selected, send a SIZE command only if one hadn't been
-sent for that file already.  ckcftp.c, 13 Jul 2002.
-
-Made [M]GET and [M]PUT /UPDATE switch imply FTP DATES ON, since they didn't
-work unless it was.  ckcftp.c, 13 Jul 2002.
-
-Added FTP [M]GET /DATES-DIFFER, which is like /UPDATE except it selects files
-that are newer or older, rather than only newer.  This allows updates from
-sources where files might be rolled back to earlier versions.  It's a bit
-dangerous if you use it without knowing what it's for, since it allows older
-files to overwrite newer ones.  (Code is also in place for [M]PUT
-/DATES-DIFFER, and it works, but I commented it out because it's either
-useless or dangerous since when uploading, you can't set the the file dates
-when they are arrive on the server.)  ckcftp.c, 13 Jul 2002.
-
-Changed chkmodtime() to remember if MDTM fails on a particular connection
-because it's an unknown command (500, 502, or 202), and if so, not to ask
-again.  ckcftp.c, 13 Jul 2002.
-
-With this last change, I think it's safe to change the default for FTP DATES
-from OFF to ON.  ckcftp.c, 13 Jul 2002. 
-
-Increased max number of /EXCEPT: patterns from 8 to 64 for file transfer (not
-necessarily for other things).  This is now a compile-time symbol NSNDEXCEPT.
-ckcker.h, ckcmai.c, ckclib.c, ckcfns.c, ckcftp.c, ckuus[rx].c.  13 Jul 2002.
-
-Fixed FTP MGET to not send SIZE command when there is a name collision and
-FILE COLLISION is DISCARD, even if /SMALLER or /LARGER were also specified.
-ckcftp.c, 15 Jul 2002.
-
-MGET fails if no files were transferred, even if the reason is that no files
-met the selection critieria: /COLLISION:DISCARD, /UPDATE, /SMALLER, etc.
-Changed MGET to succeed in that case.  domget(): ckcftp.c, 16 Jul 2002.
-
-Big problems with canceling MGET; Ctrl-C cancels the current file, but we
-don't break out of the file loop, we just go on to the next file.  Worse, if
-we're executing a command file that has a series of MGETs, Ctrl-C doesn't
-break us out of the command file.  Fixed by making failftprecv() and
-failftprecv2() "chain" to the main SIGINT handler, trap().  This is fine in
-Unix, but I'd be really surprised if it works in K95 so I put it in #ifndef
-OS2.  Ditto for MPUT: Added the same treatment to failftpsend() and
-failftpsend2().  Ditto for cmdcancel().  To adapt to K95, search for "TEST ME
-IN K95" (5 places).  ckcftp.c, 16 Jul 2002.
-Fixed previous fix to account for the fact that failftpblah() can be called
-not only upon Ctrl-C, but also if transfer interrupted with X or Z.
-ckcftp.c, 16 Jul 2002.
-
-Yesterday's fixes revealed another problem: Interrupt MGET with Ctrl-C, start
-another MGET, and the file list is total garbage.  Diagnosis: secure_getc()
-and secure_getbyte() use internal static buffer pointers.  The only way they
-ever get reset is when the data connection is closed by the server, so if you
-interrupt a GET, the pointers are not reset and the next network read (e.g. of
-an NLST response) returns whatever junk was lying around in the old buffer.
-ckcftp.c, 17 Jul 2002.
-
-FTP MGET temp file is kept only if FTP DEBUG is ON.  Changed FTP module to
-also keep it if the regular debug log is active.  ckcftp.c, 17 Jul 2002.
-
-Fixed version test in ckermit.ini: should be 6 digits, not 5.  17 Jul 2002.
-
-Changed C-Kermit version number to 8.0.205 so scripts can test for the
-recent changes.  ckcmai.c, 18 Jul 2002.
-
----8.0.205---
-
-SET FILE COLLISION UPDATE would unset FTP DATES due to a typo in the recent
-changes.  ckcftp.c, 21 Jul 2002.
-
-FTP [M]GET /DATES-DIFFER really should have been a collision option.  Added
-this option (implemented for FTP only) to both SET FTP COLLISION and the
-FTP [M]GET /COLLISION: table, so this way if you have lots of [M]GETs, you
-don't have to put /DATES-DIFFER on each one.  ckcker.h, ckcftp.c, 21 Jul 2002.
-
-"FTP MGET a* b* c*" would fail to get any c*'s if no b*'s existed.
-ckcftp.c, 21 Jul 2002.
-
-From Jeff, 22 Jul 2002:
- . Beginnings of Ann Arbor Ambassador terminal emulation for K95;
-   ckuus[57].c, ckuusr.h.
- . Bump K95 version number to 2.0.2: ckcmai.c
-
-Added -DCK_PAM -DCK_SHADOW to all Solaris targets, 2.6 and above.  makefile,
-23 Jul 2002.
-
-Discovered that CK_SCRIPTS path search for TAKE files was #ifdef'd out
-except for K95.  Fixed in ckuusr.c, 25 Jul 2002.
-
-From Jeff: changes to support K95 italics: ckuus[57].c,  25 Jul 2002.
-
-Fixed path search for TAKE to not search the CK_SCRIPTS path if the filespec
-contains any directory or path parts.  Added a new function to check for
-this:  int hasnopath(filespec) in ckucmd.c: 26 Jul 2002.
-
-Update HP-UX build instructions from PeterE: makefile, 26 Jul 2002.
-
-Commented out "const" from struct pam_message declarations because it
-causes "initialization type mismatch" warnings.  ckufio.c, 26 Jul 2002.
-
-Suppose you have a network directory containing a listing for host "foo":
-
-  foo tcp/ip foo.bar.com
-
-Then in K95 you give a command "set host /network-type:ssh foo".  This
-results in the directory lookup replacing the "ssh" network type with TCP/IP,
-and making a Telnet connection.  Fix attempted at about line 8625 of ckuus7.c
-in cx_net(); needs testing in K95.  26 Jul 2002.
-
-FTP Password: prompt in Unix was not allowing editing.  The code looked right;
-I put in some debugging and suddenly it worked.  Took out the debugging and
-it still worked.  Maybe I dreamed it.  Anyway, I fixed the "FTP SENT" debug
-log entry to not record the password, and removed a redundant section above
-to log the same thing, but prior to any charset conversion.  ckcftp.c,
-27 Jul 2002.
-
-From Jeff, 28 Jul 2002:
- . Fix typo in initxlist(): ckcmai.c.
- . Fix typo in Friday's set-host fix: ckuus7.c.
- . Move parsing of --height/width command-line args after prescan(): ckuusy.c.
-
-Added invisible top-level SITE and PASSIVE commands for FTP as a convenience
-for habituated FTP client users.  ckuusr.[ch], ckcftp.c, 28 Jul 2002.
-
-A while back a user asked if it was possible to MGET a bunch of files from
-an FTP server and have them all appended to each other upon arrival.  The
-obvious way to do this would have been:
-
-  mget /collision:append /as-name:bigfile *.*
-
-But to make this work, I had to get rid of the "as-name must contain
-variables" check in the MGET parser.  doftpget(): ckcftp.c, 28 Jul 2002.  
-
-Verified that it was possible to do the same thing (GET a bunch of files
-and append them all into one result file) with Kermit protocol.  It works
-fine but in this case there is no /COLLISION switch; you have to SET FILE
-COLLISION APPEND first.  30 Jul 2002.
-
-Changed COPY /APPEND to allow wild source to single destination file, e.g.
-"copy /append *.* bigfile".  ckuus6.c, 30 Jul 2002.
-
-From Mark Berryman: a replacement for zchkpath(), the VMS routine that checks
-whether a file is in the current directory; the old one (that I wrote) was
-a hack that only worked sometimes.  Martin Vorlaender verified Mark's code in
-the situation where mine was breaking (server running in captive account).
-ckvfio.c, 30 Jul 2002.
-
-PeterE reported a problem with SWITCH case labels that start with '#':
-The problem is that the SWITCH variable contents in this case happens to be
-a comment, e.g.:
-
-  CMD(M)[_forward # Stand: 24.07.2002<CR>]
-
-so the GOTO target is null.  The solution would be for SWITCH to put the GOTO
-(_FORWARD) target in quotes.  But GOTO does not strip quotes or braces from
-around its target.  Fixed in ckuusr.c, 30 Jul 2002.
-
-Fixed the SWITCH macro definition to put the _FORWARD target in quotes.
-ckuus5.c, 30 Jul 2002.
-
-PeterE also reported that an empty SWITCH case label did not work.  There's no
-particular reason why it should, but after a brief look, it wasn't that hard
-so I did it.  It required commenting out the check for empty labels and fixing
-the comparison in dogoto().  Now it's possible to read lines from a file and
-use each line as a SWITCH variable, with patterns as case labels, including an
-empty label to match empty lines, #* labels to match comment lines, etc.
-ckuus[r6].c, 30 Jul 2002.
-
-PeterE also reported the value of \%* acquiring a trailing blank when
-referenced inside a SWITCH statment.  This happens because \%* is formed using
-\fjoin() on the \&_[] array based on its dimension, and at some point the
-dimension is spuriously increased by one.  As a workaround, I made \fjoin()
-ignore trailing empty \&_[] array elements and oddly enough this also fixed
-the growing dimensions problem.  The many script torture tests reveal no ill
-effects, so it seems like a keeper.  ckuus4.c, 30 Jul 2002.
-
-Some of Peter's sample scripts made C-Kermit 8.0.201 dump core, but no more.
-
-Fixed "delete xxx" to print an error message and fail if if xxx does not exist.
-Ditto for when xxx is a directory.  ckuus6.c, 30 Jul 2002.
-
-Patches to SSL modules from Jeff based on yesterday's advisory.  ck_ssl.[ch],
-31 Jul 2002.
-
-Fixed some typos affecting the filename collision action during command-line
-FTP [M]GET.  ckcftp.c, 31 Jul 2002.
-
-Fixed SHOW FTP to handle FTP COLLISION DATES-DIFFER.  ckcftp.c, 31 Jul 2002.
-
-A while back someone pointed out that SET CONTROL UNPREFIX ALL and SET
-PREFIXING NONE gave different results.  Fixed them to use the same code.
-Also made "set prefixing none" visible.  ckuus3.c, 4 Aug 2002.
-
-Added SET CD HOME <path>, to let the user specify which directory is intended
-when "CD" or "KCD" is given by itself.  This is because in Windows, some
-applications set up their own HOME environment variable that isn't necessarily
-where the user wants "cd" to go, but redefining HOME can interfere with the
-application (example: Windows EMACS).  SET CD HOME was done by adding a myhome
-variable, initially a NULL pointer, and then changing homepath() to use it if
-it is set.  zhome() is not affected.  Also the homepath() prototype had been
-missing from header files.  ckcmai.c, ckuusr.h, ckuus[2345].c, 4 Aug 2002.
-
-PeterE got another core dump with his SWITCH statement.  Found a place where
-an out-of-bounds array reference could occur if the switch variable was
-empty.  ckuus6.c, 5 Aug 2002.
-
-PeterE noticed that if the switch variable contained a comma, spurious matches
-could occur with the label pattern.  The real problem turns out to be what
-happens when the SWITCH variable doesn't match any of the case labels and
-there is no DEFAULT label.  Fixed by having dogoto() in the SWITCH (_FORWARD)
-case pop the command stack before returning failure, i.e. by moving the
-"if (stopflg) return(0);" statement down a few lines.  ckuus6.c, 5 Aug 2002.
-
-PeterE noticed that a SWITCH case label of :* did not match an empty SWITCH
-variable.  Fixed in doswitch(): ckuus6.c, 6 Aug 2002.
-
-In testing the previous fix, I found it only worked sometimes.  Inspection
-of the debug log showed that a statement like:
-
-  if (y == -3) s = "{}";
-
-was assigning "{" rather than "{}" to s.  Replacing the string constant by a
-buffer containing the same string fixed it.  The reason (guessed correctly by
-PeterE) was the following sequence:
-
-  y = cmfld("Variable name","",&s,xxstring);
-  if (y == -3) s = "{}";
-  len = ckstrncpy(tmpbuf,brstrip(s),TMPBUFSIZ);
-
-brstrip() (by design and as documented) affects the string in place.  But in
-this case the string is a constant, not data in a buffer, so all further uses
-of "{}" get the wrong string (at least in optimized builds).  The only real
-cure is to change brstrip() to make a copy of its argument if it has to do
-anything to it.  This will slow down some scripts, but it's too risky to
-leave it as it was.  ckclib.c, 6 Aug 2002.
-
-The previous change required an audit of the C-Kermit code to make sure that
-no references to brstrip() depended the result buffer being persistent, or the
-result pointer indicating a position in the source buffer.  Oops, it turns out
-that thousands of places rely on brstrip() working in place.  Therefore the
-change had to be undone.  There's no good way to write a dummy-proof brstrip();
-programmers either have be sure they're not calling it with a pointer to a
-string constant, or else they have to copy the result back to the right place
-each time.  Better to leave it as it was and audit the code to fix any calls
-that refer to string constants (turns out there were only two).  Restored the
-original fix to doswitch() (replacing the string constant by a buffer holding
-the same string), plus minor fixes to ckcftp.c, ckuus[r36].c, 6 Aug 2002.
-
-We need file dialogs in several situations in the K95 GUI.  I added a "user
-query" routine for this, uq_file(), in ckuus3.c, filling it in only for Unix.
-Then I added code to call it from rcvfil() when (a) it's an autodownload, and
-(b) SET TERM AUTODOWNLOAD is ASK (I just added this option; it needs to be set
-to see it in action -- maybe it should be the default for KUI, in which case
-initialize "int autodl = ?" to TAD_ASK in ckcmai.c).  Works fine, except of
-course it interferes with the file-transfer display, but that won't be a
-problem in K95G.  ckuusr.h, ckuus[37].c, ckcfns.c, ckucns.c, 6 Aug 2002.
-
-Another place we need a file dialog is when Kermit is a URL interpreter.  The
-problem is: how can we let the user decide whether Kermit should ask?  There
-really isn't any way.  Either it always asks or it never does.  In this case I
-think it makes sense to always ask if it's KUI, otherwise never.  I added the
-code for ftp: URLs to to doftprecv2(), which I tested successfully in Unix
-before putting it into #ifdef KUI..#endif.  Also added code for http[s] to
-ckuusy.c in #ifdef KUI..#endif, not tested.
-
-Still need this added for K95G Actions->Capture.  The clearest example is the
-FTP one.  Just search for KUI in the FTP module.
-
-Some minor adjustments to yesterday's work, mainly just comments, plus
-generate the full pathname for the default file.  ckuus3.c, ckcftp.c,
-7 Aug 2002.
-
-Note: for some reason cmofi() is not supplying the default value if user
-enters an empty name... (but that won't affect the Windows version).
-
-Added /USER: and /PASSWORD: switches to SET TCP { HTTP-PROXY, SOCKS-SERVER }.
-ckuus3.c, 7 Aug 2002.
-
-New 'uninstall' target from PeterE, works by having the 'install' target
-write an UNINSTALL shell script.  makefile, 8 Aug 2002.
-
-Added some debugging statements to the VMS communications i/o module to try
-to track down a problem that occurs when the controlling terminal is a LAT
-device.  ckvtio.c, 10 Aug 2002.
-
-Fixed the non-K95 uq_file() to respect the given default name, but still show
-the fully qualified absolute pathname for the default in the dialog.  The
-reason to not use the fully qualifed name as the default in the cmxxx() calls
-is that this can easily result in a whole directory tree being created due to
-directory aliases, symlinks, etc.  So when you get a file by referring to its
-URL (e.g. ftp://kermit.columbia.edu/kermit/READ.ME), uq_file() converts the
-READ.ME part to (e.g.) /home/fdc/tmp/READ.ME but gives just "READ.ME" as the
-default when parsing the name.  This way the user knows where it will go and
-gets an opportunity to change it, and if the default is accepted, it goes into
-the current directory.  uq_file(): ckuus3.c, 10 Aug 2002.
-
-Found the spot for calling uq_file() for kermit:// URL downloads.  Added
-prefatory text to filename prompts for Kermit and FTP downloads.  ckcfns.c,
-ckcftp.c, 10 Aug 2002.
-
-Now with kermit:// or ftp:// URL downloads there's no way to disable the
-prompting.  I could easily make SET TERMINAL AUTODOWNLOAD ASK cover these
-cases too (even though "terminal" has nothing to do with FTP or URL
-downloads).  OK, I did this, but now prompting is disabled by default.
-ckcftp.c, ckcfns.c.  10 Aug 2002.
-
-Enabled file prompting (adl_ask) by default in K95G, disabled it by default
-everywhere else.  So now FTP and Kermit URL downloads as well as terminal-mode
-Kermit (but not Zmodem) downloads are prompted for if TERMINAL AUTODOWNLOAD is
-ASK, which is it by default only in K95G.  But this will happen only if
-uq_file() is filled in for K95G; otherwise everything should work as before.
-ckcmai.c, 10 Aug 2002.
-
-Notes:
- . Need a better command to control this.
- . FTP URL downloads are almost instantaneous, whereas Kermit URL downloads
-   take a really long time to set up (logging in takes at least 10 seconds).
-
-From Jeff, 13 Aug 2002:
- . Increase K95 version to 2.1.0: ckcmai.c.
- . SET TCP { HTTP-PROXY, SOCKS-SERVER } /USER: /PASSWORD: actions: ckuus3.c.
-
-From PeterE: a new install target that's only about half as a big as the
-previous one, yet still generates an UNINSTALL script.  makefile, 13 Aug 2002.
-
-Vace wanted to be able to give the FTP client an offset for the server time,
-in case the server's time (or timezone) is set incorrectly.  I added this by
-building on all the date/time parsing/arithmetic code -- notably delta times
--- that was done for C-Kermit 8.0.  The new command is SET FTP
-SERVER-TIME-OFFSET delta-time; shows up in SHOW FTP and HELP SET FTP.
-ckcftp.c, 13 Aug 2002.
-
-Fixed HELP ASK and HELP GETOK text.  ckuus2.c, 14 Aug 2002.
-
-Fixed GETOK to accept /GUI switch even in K95.EXE and C-Kermit, just like ASK
-does (in which case, it just ignores it).  ckuus6.c, 14 Aug 2002.
-
-SET XFER CHAR TRANSPARENT no longer disables character-set translation because
-file-scanning turns it back on.  The "new way" to disable character-set
-translation is SET XFER TRANSLATION OFF.  This needlessly confuses users who
-expect the old way to still work.  So I fixed SET XFER CHAR TRANSPARENT to set
-XFER TRANSLATION OFF, and SET XFER CHAR anything-else to set it back ON.
-ckuus3.c, 15 Aug 2002.
-
-Fixed SET TERM AUTODOWNLOAD { ON, OFF } to turn off the ASK flag (adl_ask).
-ckuus7.c, 16 Aug 2002.
-
-Added FEAT query to FTP client from draft-ietf-ftpext-mlst-13.txt.  FEAT is
-sent along with REST 0, MODE S, and STRU F if /NOINIT is not included in the
-FTP OPEN command.  Parsing the FEAT result is handled by turning the "auth"
-argument to getreply() into a function code: GRF_AUTH to parse AUTH reply;
-GRF_FEAT to parse FEAT reply.  For GRF_FEAT, getreply() fills in a flag array,
-sfttab[] (server feature table); sfttab[0] > 0 means server responded to the
-FEAT query, in which case individual elements are set > 0 for each supported
-feature.  ckcftp.c, 18 Aug 2002.
-
-If server sends a feature list, display it if FTP DEBUG is on, then set mdtmok
-and sizeok (the flags that say whether it's OK to send MDTM and SIZE commands)
-accordingly.  If user gives an [M]PUT /RECOVER command and server has
-announced it doesn't support REST, print a warning but try anyway (maybe
-change this later).  Responses about other features that we use such as AUTH
-and PBSZ are ignored for now -- i.e. we try them anyway.  And of course
-responses for features we don't care about (LANG, TVFS, PROT) are ignored.
-ckcftp.c, 18 Aug 2002.
-
-If the server says it supports MLST, use MLSD instead of NLST to get the file
-list.  This is done in remote_files() with some simple string-twiddling.  Then
-replace the relevant (but not all) SIZE commands with code to first check if
-we already got the size from the MLSD response and use that instead rather
-than asking again.  Same deal for MDTM.  ckcftp.c, 18 Aug 2002.
-
-Checked that this works when giving pathnames in the MGET filespec.  Checked
-to make sure everything works as before with servers that don't support FEAT
-or MLSD.  Checked to make sure FTP OPEN blah /NOINIT worked with servers that
-do support FEAT and MLSD.  Checked that FTP CHECK works.  It's all OK.
-
-Tested only with Ipswitch server; need to find and test with others.
-
-The stack of temp files needed for MGET /RECURSIVE is annoying because what
-if we run out of file descriptors...  But the spec doesn't provide a way to
-request a recursive listing.
-
-Supplied a missing comma in HELP SET CD text.  ckuus2.c, 19 Aug 2002.
-
-Generalized parsing of MLST/MLSD file facts and values.  Got file type from
-server and had MGET skip non-regular files.  ckcftp.c, 19 Aug 2002.
-
-Kirk Turner-Rustin <ktrustin@owu.edu> reported that if Unix C-Kermit has a SET
-HOST PTY connection (e.g. SSH) open, local window size changes are not
-propogated through the connection to the host.  I imagine that must be because
-the SIGWINCH signal is caught by Kermit and its children don't see it; maybe
-if I pass it along to the child fork, all will be OK.  Began by exporting
-"slavepid" from the pty module and changing its name to pty_fork_pid.  Moved
-the SIGWINCH handler, winchh(), from ckctel.c to ckutio.c.  Armed it from Unix
-sysinit() so it's always armed.  This way window changes affect Unix C-Kermit
-no matter what mode it's in: tt_rows, tt_cols, cmd_rows, and cmd_cols are all
-kept in sync.  Then if we're not in remote mode (i.e. we have a ttyfd), we
-call tn_snaws() and rlog_snaws() (which should be ok since they return right
-away if the appropriate kind of connection is not open) and then if
-(pty_fork_pid > -1), a SIGWINCH signal is sent to it.  ckupty.c, ckctel.c,
-ckutio.c, 20 Aug 2002.
-
-All this works fine except the PTY part; in other words, the original problem
-is not fixed.  The "kill(pty_fork_pid,SIGWINCH)" call executes without error
-but has no effect because the size of the PTY never changed.  To make this
-work I had to add an ioctl() to change the size of the PTY before sending it
-the SIGWINCH.  Compiles and works ok on Linux and Solaris; Kirk also confirmed
-it for AIX 4.3.3.  ckutio.c, 20 Aug 2002.
-
-Fixed xlookup() to work for uppercase keywords.  ckucmd.c, 20 Aug 2002.
-
-Fixed FTP parsefeat() and parsefacts() to use xlookup() instead of lookup(),
-since abbreviated keywords are not allowed.  ckcftp.c, 20 Aug 2002.
-
-Adjusted some lines from yesterday's window-size code for platforms I hadn't
-tried yet.  ckutio.c, 21 Aug 2002.
-
-EXIT from K95 when it has an FTP connection open and it pops up the
-Locus dialog.  Made it not do this if it knows it's in the act of EXITing.
-ckuus[rx].c, 22 Aug 2002.
-
-In K95, FTP GET in ASCII mode results in a file with Unix line terminators
-even though the protocol is correct:
-
-  RETR smjulie.txt
-  150 Opening ASCII mode data connection for smjulie.txt (1878 bytes).
-
-The source file is a regular Unix text file with LF at the end of each line.
-It's incredible that nobody noticed this before.  It only came to light when
-somebody tried to open a downloaded text file with Notepad, which doesn't
-handle Unix-format files (Wordpad and Emacs have no problems with them).  The
-problem was in doftprecv2() in the FTT_ASC section.  There was no conditional
-code for Unix vs Windows.  In all cases, the code discarded incoming CR's in
-ASCII mode.  I put the CR-discarding code in #ifdef UNIX..#endif.  ckcftp.c,
-22 Aug 2002.
-
-Removed super-verbose debugging from gtword(): ckucmd.c, 23 Aug 2002.
-
-Gregory Bond reported a problem with "if defined \$(BLAH) ..." inside of a
-SWITCH statement.  It wasn't really the SWITCH that was doing it, it was the
-fact that he had enclosed the SWITCH case in braces, which made it an
-"immediate macro" (XXMACRO).  The XXMACRO code parsed the macro definition
-(the part inside the braces) with cmtxt(...,xxstring), which should have been
-cmtxt(...,NULL) to defer the evaluation of the interior of the macro until it
-was executed.  This is better illustrated with the following example:
-
-  { echo START, for \%i 1 3 1 { echo \%i }, echo STOP }
-
-which totally fell on its face prior to the fix.  Also fixed ?-help for
-immediate macros, which was broken too.  ckuusr.c, 23 Aug 2002.
-
-RFC959 says STOU does not take an argument.  But every FTP server I've
-encountered but one accepts the arg and constructs the unique name from it,
-which is better than making up a totally random name for the file, which is
-what RFC959 calls for.  Especially because there is no way for the client to
-find out the name chosen by the server (because RFC 959 and 1123 are
-contradictory, plus no servers follow either one of them for this anyway).  So
-we try STOU with the argument first, which works with most servers, and if it
-fails, we retry it without the arg, for the benefit of the one picky server
-that is not "liberal in what it accepts" UNLESS the first STOU got a 502 code
-("not implemented") which means STOU is not accepted, period (which happens
-with ProFTPD).  ckcftp.c, 25 Aug 2002.
-
-Added SET FTP ANONYMOUS-PASSWORD (plus help text and show value).  ckcftp.c,
-25 Aug 2002.
-
-Made FTP command "not available" if NOFTP is defined.  ckuusr.c, 25 Aug 2002.
-
-Forced client to send a TYPE command upon initial connection, since given
-the variable quality of FTP servers, it's not safe to assume the server is
-in ASCII or any other particular mode.  ckcftp.c, 25 Aug 2002.
-
-SET FTP CHARACTER-SET-TRANSLATION ON is completely broken in K95, although it
-works fine in C-Kermit.  Furthermore it is broken in both the GUI and Console
-versions, so it's not a Unicode vs OEM console-character-set issue.
-
-Added Concurrent PowerMAX OS target from Tom Horsley.  makefile, ckuver.h,
-27 Aug 2002.
-
-Minor fixes to FTP module from Jeff.  ckcftp.c, 27 Aug 2002.
-
-New Makefile target for Mac OS X 10.2, needs -DNDSYSERRLIST added, from
-William Bader.  2 Sep 2002.
-
-SET OPT DIR /DOTFILES didn't work for server listings.  A few years ago when
-I front-ended zxpand() with nzxpand(), I missed a couple places where
-traverse() needed to refer to xmatchdot (nzxpand's argument flag) rather than
-global matchdot.  Fixed in traverse(): ckufio.c, 2 Sep 2002.
-
-From Jeff, 4 Sep 2002:
- . setautodl(x) -> setautodl(x,y): ckuusr.h, ckuus[7y].c
- . Add another parameter to popup_readblah(): ckuus6.c
- . Sort out some confusion in scanfile() where a parameter was also used as a
-   local flag.  ckuusx.c.
- . Protect restoring of saved terminal idle parameters with a flag that says
-   they were actually saved.  ckuusr.c.
- . Rework uq_text() and uq_mtxt().  ckuus3.c.
- . Fix FTP charset translation for little-endian hardware: ckcftp.c.
-
-The latter still doesn't work in Linux:
-
-  (/home/fdc/kermit/) C-Kermit>set ftp server-character-set latin1-iso
-  (/home/fdc/kermit/) C-Kermit>set file character-set utf8
-  (/home/fdc/kermit/) C-Kermit>get latin1.txt
-
-Results in "????????: file not found".  But it works fine on the Sun.
-
-Jeff's patch removed a little-endian byte-swap (LEBS) from doftpsend2().  But
-the real problem was that LEBS was not being done consistently throughout the
-module.  There were similar xgnbyte()/xpnbyte() loops elsewhere in the code,
-and all of them needed to work the same way.  Undoing Jeff's fix and then
-adding the LEBS to the loop in getreply() makes downloads work right, but the
-messages are still messed up (they come out in Chinese :-)  Begin by moving all
-byte-swapping operations that occur in ckcftp.c itself into a new function,
-bytswap().  It's either right to do it all the time, or to do it never; this
-way we can turn it on and off in one place.
-
-xp/gnbyte() include behavior that depends on what Kermit is doing: W_SEND,
-etc.  xpnbyte() tests W_KERMIT, which is a combination of W_SEND, W_RECV, etc.
-Defined a new symbol W_XFER, which is like W_KERMIT but includes W_FTP.  These
-are all the "whats" in which character sets might need to be converted.
-Changed the W_KERMIT reference in xpnbyte() to W_XFER.  Fixed the inderminate
-"what" state after an FTP command by moving "what = W_COMMAND;" from before
-the main parse loop to inside it (this didn't matter before the addition of
-FTP but now it does).  ckcker.h, ckcftp.c, ckuus5.c, 6 Sep 2002.
-
-Finally I changed xlatec() to be consistent with all the other xgnbyte() /
-xpnbyte() usage throughout the FTP module and, poof, everything worked in
-Linux (and still works on the Sun).  We still need some work in Windows (where
-the file character-set is not necessarily the console character set for
-messages) but we can tackle that next.  ckcftp.c, 6 Sep 2002.
-
-Checking yesterday's work:
-
-Kermit file transfers with charset translation work fine in both directions.
-
-FTP GET with charset translation works fine on both BE and LE
-
-Fixed a typo in yesterday's changes that made FTP PUT with charset translation
-always upload 0-length files.  ckcftp.c, 7 Sep 2002.
-
-FTP PUT (after the typo was fixed) with charset translation works fine on BE,
-but on LE the message comes out in Chinese and the resulting file gets ? or
-nothing for all for the accented letters:
-
-      FTP...  Kermit 
-      Up  Dn  Up  Dn  Term
-  BE  OK  OK  OK  OK   xx
-  LE  no  OK  OK  OK   xx
-
-xx = C-Kermit CONNECT mode with translation doesn't seem to do anything, not
-only in today's code, but also in the 8.0 release version: "set term char
-latin1 utf8" -- SHOW CHAR shows the right stuff, but no translation is done.
-Ditto for the 7.0 release.  That can't be right...
-
-But one problem at a time -- what's wrong with LE FTP uploads?  Note that
-XLATE works on the same machine, so it's obviously confusion in xgnbyte()
-about "what".  Suppose we make xgnbyte() ALWAYS return bytes in BE order.
-This makes sense because xgnbyte() is almost always used to feed xpnbyte(),
-and xpnbyte() requires its bytes to come in BE order.  This means that all
-code that uses xgnbyte()/xpnbyte() loops can be simplifed, which I did for
-the FTP module.  ckcfns.c, ckcftp.c, 7 Sep 2002.
-
-Of course Kermit protocol uses xgnbyte() too, but only for filling
-packets, and packets never contain UCS2 and even if they did, it would have
-to be big-endian, so no changes needed for getpkt().  Now we have:
-
-      FTP...  Kermit 
-      Up  Dn  Up  Dn
-  BE  OK  OK  OK  OK
-  LE  OK  OK  OK  OK
-
-Now let's look at the remaining xgnbyte() calls in the rest of the code:
-
-ckuus4.c:
-  xlate() uses it of course.  I simplified the general-case loop.
-  Works OK on both Sun and Linux.
-
-ckuus6.c:
-  typegetline() uses it.  I commented out the byte swap.  Seems OK.
-
-Built and tested on Linux, Solaris, and SunOS.  I'm sure I must have broken
-something, but the main things are better than they were.  Kermit and FTP
-transfers need testing in K95, as well as the TYPE command (there's a bunch of
-special K95 code in there).  C-Kermit charset translation during CONNECT is
-still broken, or else I forgot how to use it, but that's a separate issue
-since xgnbyte()/xpnbyte() are not involved.  And we still need to do something
-in FTP getreply() for K95 to convert messages to the console character set for
-display, rather than the file character set (should be trivial).  Also there's
-still a lot of extra debugging and commented-out junk in ckcftp.c to be
-cleaned up after more testing.
-
-During yesterday's testing, I noticed that REMOTE SET { FILE, XFER }
-CHARACTER-SET didn't work.  The server accepted these commands but they didn't
-seem to do anything.  In fact, they did work, but they were undone later by
-code in sfile() that restored the global settings in case they had been
-temporarily overridden by autoswitching or whatever.  The solution is to
-"unsave" the saved values whenever a global setting is performed explicitly.
-Tested successfully against Sun and Linux servers.  Also the server end of
-REMOTE SET needed updating for Unicode.  ckcfn[s3].c, ckuus3.c, 8 Sep 2002.
-
-Cleaned commented-out cruft and extra debugging from ckcftp.c.  8 Sep 2002.
-
-Kermit autodownload with ASK file dialog: if user supplied an absolute
-pathname, it was treated like a relative one.  Fixed the invocation of
-uq_file() in rcvfil() to temporarily override the RECEIVE PATHNAMES setting.
-ckcfns.c, 10 Sep 2002.
-
-Added SET TERMINAL ROLL KEYSTROKES { SEND, RESTORE-AND-SEND, IGNORE }, parse
-only.  Needs implementation (search for tt_rkeys and rollkeytab in ckuus7.c).
-ckuusr.h, ckuus[27].c, 10 Sep 2002.
-
-If FILE INCOMPLETE is DISCARD and a file is being received by IKSD but IKSD
-gets a Telnet LOGOUT command, the partial file is not deleted.  In fact this
-happens any time doexit() is called for any reason during file reception,
-e.g. because of SIGHUP.  Added code to doclean() to check if a download
-output file was open, and if so, to delete it after closing it if keep==0.
-ckuusx.c, 10 Sep 2002.
-
-Added a brief one-line message after remote-mode file transfer saying
-what (or how many) file(s) were transferred, where they went, and whether
-the transfer was successful -- kind of an automatic WHERE command, useful
-with autodownloads so you know what happened.  ckcpro.w, 11 Sep 2002.
-
-The Unix and VMS C-Kermit CONNECT modules have botched remote-charset to
-local-UTF8 translation ever since the Unicode was first added in v7.0.  Fixed
-in ckucns.c, ckucon.c, ckvcon.c, 11 Sep 2002.
-
-On to pattern-matching...  The matchdot business should apply only for (Unix)
-filename matching, not for general string matching.  Fixed in ckmatch():
-ckclib.c, 11 Sep 2002.
-
-A bigger problem occurs in filename matching.  Somehow the dirsep == fence
-business interferes with matching {foo,bar,baz} segments.  For example, I have
-a filename "foo" and I want to match it with the pattern "{foo,bar}".  Somehow
-the segment pattern becomes "*/foo" and doesn't match the string.  Where does
-the '/' get tacked on?  I don't even know how to explain this, but the short
-story was that ckmatch(), under certain circumstances, would back up to before
-the beginning of the filename string, which just happened to contain a "/"
-(and before that a ".") because of who was calling it.  Obviously this is not
-how to write a pattern matching function...  Ensuring that it never backs up
-beyond the beginning of a string fixed the immediate problem and does not seem
-to have broken any other matching scenarios (I have 150 of them in my test
-script).  ckclib.c, 11 Sep 2002.
-
-There's still a problem though.  Suppose the a client sends "dir {{.*,*}}" to
-a server.  This asks for a directory listing of all files that begin with
-dot as well as all files.  Still doesn't work because we don't normally show
-dot-files, but in this case it SHOULD work because ".*" was explicitly
-requested.  Staring at the ckmatch() code revealed how to fix this, and I did,
-but that was only half the problem.  The other half was that the list of
-files being fed to ckmatch() did not include the dotfiles in the first place.
-The cure here is to change nzxpand() to prescan the pattern to see if it
-includes a leading dot, and if so to set the "xmatchdot" flag itself, even
-if it wasn't set by the caller.  ckclib.c, ckufio.c, 11 Sep 2002.
-
-Now that {foo,bar,...} patterns work better, I added a quick hack to the
-DIRECTORY command to allow multiple filespecs to be given, in which case we
-combine them into a {file1,file2,...} pattern before calling nzxpand().  Works
-fine but it's a hack because you don't get file lists upon "?" in the second
-and subsequent filespec fields, but I doubt anyone will notice.  So now,
-finally, people can do "dir .* *" like they do in Unix (except with ls) to get
-a listing of all files in a directory without having to know about or use the
-/DOTFILES switch.  This was NOT done for the server end of RDIR because of
-ambiguity of spaces as separators versus filename characters.)  domydir():
-ckuus6.c, ckuus[r2].c, 11 Sep 2002.
-
-Added a CONTINUE command.  In a script, this does whatever CONTINUE did before
-(e.g. in a FOR or WHILE loop).  At the prompt, it calls popclvl(), which gives
-a more natural way to continue a script that has "shelled out" to the prompt.
-ckuusr.[ch], 11 Sep 2002.
-
-Added help text for CONTINUE.  ckuus2.c, 12 Sep 2002.
-
-From Jeff, 16 Sep 2002:
- . SET TERM ROLL KEYSTROKES for K95: ckuusr.h, ckuus7.c
- . Remove the doexit() call from the Telnet TELOPT_LOGOUT handler: ckctel.c
-
-Fixed an FTP debug message to be consistent with Kermit ones.
-ckcftp.c, 16 Sep 2002.
-
-Added SET/SHOW TRANSFER REPORT to turn the post-transfer report off and on.
-ckuusr.h, ckuus[234].c, 16 Sep 2002.
-
-Fixed Solaris (and maybe some other SVORPOSIX builds) to find out their full
-hostname rather than just short form (e.g. watsol.cc.columbia.edu rather than
-just watsol).  ckhost(): ckuusx.c, 16 Sep 2002.
-
-"cat somefile | kermit -Ts -" is supposed to send stdin in text mode, but
-K95's file transfer display reports BINARY.  Looked at C-Kermit code; it seems
-fine.  Looked at packet and debug logs; C-Kermit was indeed sending in text
-mode and announcing it correctly.  K95 gattr() is doing the right thing:
-
-  gattr file type[AMJ]=3
-  gattr attribute A=text=0
-  gattr sets tcharset TC_TRANSP[A]
-
-Same thing happens when C-Kermit is receiving.  Yet when I send an actual
-file, rather than stdin, it's received in text mode.  The only difference is
-that stdin does not have a Length attribute in its A-packet, so in this case
-the receiver skips any calls to screen() that show the length or percent done.
-Aha, so maybe it's just a display problem -- scrft() is not being called to
-repaint the file type if the size was not known.  Fixed in opena() by
-removing the IF clause from "if (fsize > -1L) xxscreen(SCR_FS,0,fsize,"");".
-ckcfn3.c, 18 Sep 2002.
-
-K95 user has a listfile containing some regular filenames and then some
-filenames that include paths and has all kinds of problems with MGET /LISTFILE
-(pieces of different names concatenated to each other, etc).  Setting up the
-same scenario here, I don't see the same problems but I do see "Refused: Name"
-when we go to get a path/name file.  This happens because (a) we had already
-got a top-level file with a certain name, (b) a file in a subdirectory has the
-same name, (c) we are stripping the path before calling zchki(), and (d)
-FTP COLLISION is set to DISCARD.  How do we make FTP not strip the path?
-
-This is an interesting question...  The answer depends on where the user
-wants the file to go.  Normally if you tell an FTP client to "get foo/bar",
-you want the file "bar" to be downloaded to the current directory.
-
-Anyway, it turns out the FTP module uses paths locally during MGET only if
-/RECURSIVE was specified.  So:
-
-  mget /listfile:blah /recursive
-
-should have made this work, but it didn't because in the /LISTFILE case,
-we have effectively turned an MGET into a series of GETs, where the code to
-check whether to strip the path didn't check the recursive flag because how
-could a GET (as opposed to an MGET) be recursive?  Adding this exception to
-the if-condition got us a bit farther but now when we try to open the output
-file in doftprecv2(), zopeno() fails because the name contains a dirsep.
-We have to call zmkdir() first but that wasn't happening because some other
-flag wasn't set right in this case.  Finally zmkdir was called, but with
-the wrong string.  After fixing that, it works.  Now we should be able
-to use /RECURSIVE to force the pathname to be used on the local end.
-ckcftp.c, 19 Sep 2002.
-
-Checked FTP filename conversion issues.  FTP FILENAMES AUTO is supposed to
-mean LITERAL if "wearealike" OR server is UNIX or Windows, otherwise
-CONVERTED, but there were places where this rule was not applied consistently,
-fixed now.  ckcftp.c, 21 Sep 2002.
-
-Added SET FTP DISPLAY, which is like SET TRANSFER DISPLAY but applies only to
-FTP, mainly because I tended to type it all the time.  Now if you have dual
-sessions, each session can have its own transfer display style.  ckcftp.c,
-ckuusr.h, ckuus[347].c, 21 Sep 2002.
-
-Back to FTP MLSD.  We're supposed to match the pattern locally, not rely on
-the server to filter its list according to the client's pattern.  Thus we must
-also allow an empty argument to MGET and must not send a filespec with MLSD.
-Actually this is tricky -- how is the client supposed to know whether to send
-a filespec.  For example, if the user's command is "mget foo*bar", and the
-server supports MLSD, then what should the client do?  The client does not
-know the wildcard syntax on the server, so for all the client knows, this
-might be a valid directory name, in which case it should be sent.  On the
-other hand, the user might intend it as a wildcard, in which case it should
-NOT be sent.  But the FTP client can't read the user's mind.  This is another
-serious flaw in the Elz/Hethmon draft.  Anyway, I got the local matching
-business working for MLSD as long as the user's MGET arg is really a pattern
-and not a directory name.  To be continued...  ckcftp.c, 21 Sep 2002.
-
-Added FTP { ENABLE, DISABLE } { FEAT, MLST }.  If we always send FEAT, we
-usually get a complaint.  If we send FEAT and MLST is negotiated, there is a
-good chance it is misimplemented or will have undesirable side effects, such
-as sending huge file lists.  NOTE: /NOINIT on the FTP OPEN command also
-disables both of these.  ckcftp.c, 22 Sep 2002.
-
-Fixed mkstemp() code in FTP remote_files().  mktemp() does not open the file,
-mkstemp() does open it; previously we had been opening it again and never
-closing the first instance so every MGET would create another open file
-descriptor.  ckcftp.c, 22 Sep 2002.
-
-Added debug messages for temp-file creation and lines read from the temp file.
-ckcftp.c, 22 Sep 2002.
-
-Eliminated sending of some extraneous TYPE commands, but there's still room
-for improvement.  ckcftp.c, 22 Sep 2002.
-
-Moved definition of build date to top of ckcmai.c.  22 Sep 2002.
-
-Added recursion to MGET with MLSD...  It's all done in remote_files().
-Temp-file pointers are on a stack (max size 128).  When parsing MLSD lines
-from the temp file and we see "type=dir", we create the local directory by
-calling zmkdir(), change to the remote by sending CWD, increment the depth,
-and call ourselves.  When reading from a temp file, upon EOF we close and
-dispose of the temp file, return -3 if currently at top level, otherwise we
-free the tmpfile name, decrement the depth, send CDUP to the server, "cd .."
-locally, and go back and read the next line from the previous but now current
-temp file.  Conceptually simple but needed hours of debugging -- what must
-be static, what must be on the stack...  Seems OK now but still needs some
-heavy testing.  ckcftp.c, 22 Sep 2002.
-
-Added FTP { ENABLE, DISABLE } { SIZE, MDTM } and add help text for FTP
-ENABLE and DISABLE.  ckcftp.c, 23 Sep 2002.
-
-Don't allow restart if SIZE disabled.  ckcftp.c, 23 Sep 2002.
-
-Make sure all implicit SIZE commands are surpressed if SIZE disabled.
-ckcftp.c, 23 Sep 2002.
-
-If an explicit FTP MODTIME command is sent when MDTM is DISABLED, and it
-succeeds, re-ENABLE MDTM.  Ditto for SIZE.  ckcftp.c, 23 Sep 2002.
-
-If an explicit FTP FEATURES command is sent during an FTP session, redo the
-features database from it.  ckcftp.c, 23 Sep 2002.
-
-After further discussion with Robert Elz, I realized I had to expose the
-underlying MGET mechanisms to the user; the draft isn't going to change, and
-the new spec will result in undesirable effects if the client tries to "do the
-right thing" by magic in all situations; thus the user must have some new
-controls:
-
-  MGET [ /MLST, /NLST, /MATCH:xxx ] [ filespec [ filespec [ ... ] ] ]
-
-These switches let the user force the use of MLSD or NLST when there's a
-choice, and to force local use of a pattern rather than sending it to the
-server, and even to send a directory name to the server at the same time as
-specifying a pattern for local matching, and of course by default we try to do
-the right thing in all scenarios.  Symbols only; not coded yet.  ckuusr.h,
-23 Sep 2002.
-
-Added the three new switches to MGET, plus /MLST is an invisible synonym for
-/MLSD.  If /NLST or /MLSD is given it, it forces the corresponding FTP protocol
-directive.  ckcftp.c, 25 Sep 2002.
-
-Now for the tricky part: now we have two separate concepts for what to send to
-the server: a filename or wildcard to be interpreted by the server (NLST only)
-or a directory from which to get a list of all the files (NLST or MLSD),
-possibly together with a pattern to be used by the client to match filenames
-returned by the server.  This required giving remote_files() an additional
-argument.  Now it uses "pattern" (if any) strictly for local pattern matching
-(because now it is the /MATCH: switch argument, not the MGET filespec), and
-"arg" (the MGET filespec) is what it sends to the server, maybe (see the
-comments in the code for the actual details); either or both these can be
-null.  ckcftp.c, 25 Sep 2002.
-
-Discovered that "mget foo", where foo is a directory name, never worked.
-Fixed in remote_files(): ckcftp.c, 25 Sep 2002.
-
-Going through every combination of NLST, MLSD, /MATCH:, and MGET arg and
-debugging each case until OK...  Then also with the panix.com NetBSD server
-(lukemftpd 1.0) which also supports MLSD....  11 test cases all debugged and
-tested OK.  ckcftp.c, 26 Sep 2002.
-
-Added /NODOTFILES switch to FTP MGET, to control what happens with dot-files
-if the server includes their names in the list (as lukemftpd does).  There's
-no point in adding a /DOTFILES switch because what could it possibly do?
-ckcftp.c, 26 Sep 2002.
-
-Changed a bunch of "skipthis++" to "continue" in doftpget(), to avoid
-error messages when skipping files that user said she wanted to skip.
-ckcftp.c, 26 Sep 2002.
-
-Added help text for the new MGET switches.  ckcftp.c, 26 Sep 2002.
-
-Don't switch LOCUS when making an FTP connection until logged in.
-ckcftp.c, 26 Sep 2002.
-
-Fixed LDIR to run Kermit's built-in DIRECTORY code rather than the external
-directory program.  ckuusr.c, 26 Sep 2002.
-
-Protect iswild() against NULL args.  ckufio.c, 26 Sep 2002.
-
-From Jeff: SET GUI WINDOW RUN-MODE { MAXIMIZE, MINIMIZE, RESTORE },
-plus variables for GUI Window X position, GUI Window Y position, GUI
-Window X resolution, GUI Window Y resolution, GUI Window Run mode.
-ckuusr.h, ckuus[24].c, 27 Sep 2002.
-
-From Ronan Flood: updated FreeBSD 1.0 makefile entry, plus an #ifdef to protect
-sysconf() calls.  makefile, ckutio.c, 28 Sep 2002.
-
-Change ftp_auth() to return(0) if an AUTH command gets a 500 response, so it
-doesn't keep sending other kinds of AUTH commands.  ckcftp.c, 29 Sep 2002.
-
-Changes from Jeff to yesterday's changes.  ckcftp.c, 30 Sep 2002.
-
-From Jeff: SSH command-line personality.  Uses same command line as the Telnet
-personality.  ckcker.h, ckcmai.c, ckuus[4y].c, 3 Oct 2002.
-
-From Jeff, 7 Oct 2002:
- . SET PRINTER CHARACTER-SET.  ckuxla.c, ckuusr.h, ckuus[25].c
- . Promotion of K95 to Beta.01.  ckcmai.c
- . Promotion of SET GUI { MENUBAR, TOOLBAR } to visible.  ckuus3.c
-
-Changed the URL parser as follows: if the username and/or password fields are
-present but empty, as in:
-
-           ftp://@ftp.xyzcorp.com/somepath
-  or:      ftp://:@ftp.xyzcorp.com/somepath
-  but not: ftp://:ftp.xyzcorp.com/somepath
-
-the pointer for these items becomes a pointer to an empty string, rather than
-a NULL pointer.  Then when we go to open the connection, if the username
-string pointer points to an empty string, we prompt for the username (and/or
-password).  ckuusy.c 9 Oct 2002.
-
-Jason Heskett reported an interesting bug involving a core dump when an
-ON_EXIT macro is defined that executes another macro.  Sometimes.  He was able
-to send a short command file that always crashed.  Diagnosis: ON_EXIT, when it
-is called, pokes itself out of the macro table by setting its own entry in the
-macro name list to an empty string.  But this interferes with any macro
-lookups that are done while executing ON_EXIT's body and also evidently some
-code is not happy with empty macro names...  To fix: replace "on_exit" with
-"on_exxx", so the replacement keyword is (a) nonempty, and (b) doesn't wreck
-the alphabetical sorting of the table.  ckuusx.c, 9 Oct 2002.
-
-Added makefile targets for FreeBSD 4.6 and 5.0.  Built and tested on 4.6;
-don't know about 5.0.  ckuver.h, makefile, 9 Oct 2002.
-
-Added targets for AIX 5.2 and 5.3; totally untested.  ckuver.h, makefile,
-9 Oct 2002.
-
-Built current source on Unixware 7.1.3 (make uw7); it's fine.  9 Oct 2002.
-
-Promoted C-Kermit to 8.0.206 Beta.01 in hopes of a simultaneous release
-with K95 2.1.  ckcmai.c, 9 Oct 2002.
-
-From Jeff: Change KERMITFONT definitions to use the new (Unicode 3.1) code
-points for the terminal graphics characters (such as VT100 horizontal scan
-lines), rather than private-use codes.  ckcuni.c, 10 Oct 2002.
-
-Jason Heskett also complained that REMOTE CD would print the name of the new
-directory returned by the server even if he SET QUIET ON.  This is a tricky
-one.  Which server replies should the QUIET settings apply to?  If I give a
-REMOTE DIRECTORY command, it means I want to see the directory listing,
-period.  But if I give a REMOTE CD command, I get an "unsolicited" response
-message that SET QUIET ON should suppress.  Adding message suppression to 
-rcv_shortreply() is close, but not totally right; for example, it also
-suppresses the response to REMOTE PWD, which is not helpful.  The only right
-way to do this is to suppress for REMOTE CD only, which can be done only by
-setting a (new) global flag, rcdactive.  ckuus[r57].c, ckcpro.w, 10 Oct 2002.
-
-Ditto for REMOTE LOGIN response message ("Logged in").  ckuus7.c, 11 Oct 2002.
-
-From Jeff: SET GUI WINDOW FONT { NAME, SIZE }. ckuusr.h, ckuus4.c, 11 Oct 2002.
-
-Quick preliminary 8.0.206 build-all:
-
- OK SunOS 4.1.3
- OK Solaris 2.5.1
- OK Solaris 9
- OK AIX 4.3.3
- OK HP-UX 10.20
- OK VMS 7.1 Alpha + TCP/IP
- OK VMS 7.1 Alpha nonet
- OK VMS 5.5 VAX + TCP/IP
- OK VMS 5.5 VAX nonet
- OK Unixware 7.1.3
- OK FreeBSD 3.1
- OK FreeBSD 4.6
- OK NetBSD 1.5.2 MVME (Gerry B)
- OK Sinix 5.42
-
-Sinix build got stuck on ckuusr.c even though we're not optimizing on Sinix
-any more.  Rebooting the machine fixed it.
-
-Fixed some #ifdefs for VMS in new incomplete-file deletion code in doclean().
-ckuusx.c, 11 Oct 2002.
-
-Moved uq_blah() prototypes from ckuusr.h to ckcker.h because these routines
-are called in modules that don't (and shouldn't have to) include ckuusr.h.
-11 Oct 2002.
-
-Jeff verified secure builds on Linux and Solaris.
-
-Custom-build workout: 80 different feature-selection combinations:
- . Fixed yesterday's change for NOSPL: ckcfns.c.
- . Fixed conflict between NORECALL and USE_ARROWKEYS: ckucmd.c.
- . Moved setseslog() from ckuus5.c to ckuusx.c to avoid link-time foulups.
- . Fixed an unguarded reference to zmkdir() in ckcftp.c.
- . Protected rmsg() by #ifndef NOXFER: ckuus7.c.
- . Protected initxlist() by #ifndef NOXFER: ckcmai.c.
- . Fixed unguarded references to g_url struct in xx_ftp(): ckuusy.c.
- . Fixed unguarded references to tt_snaws() in winchh(): ckutio.c.
-
---- 8.0.206 Beta.01 11 Oct 2002 ---
-
-From Jeff, 16 Oct 2002:
- . Fix K95 RMDIR: ckcfn3.c.
- . Makefile targets for Red Hat 7.2, 7.3, 8.0: ckuver.h, makefile.
- . Added \v(log_xxx) for each kind of log for PeterE: ckuusr.h, ckuus4.c.
- . Added SET TERM ATTRIBUTE DIM { ON, OFF }: ckuus[27].c.
- . Change "const" to "CONST" in some PAM declarations.  ckufio.c.
-
-Added SET MATCH { DOTFILE, FIFO } { ON, OFF }.  A FIFO special file is a named
-pipe, used for interprocess communication.  It must be opened at both ends, so
-it's silly to match them by default; opening a FIFO and attempting to read
-will block forever unless somebody is writing into the other end.  Made the
-MATCH FIFO default OFF in all cases.  The dotfile default is the same as
-always (OFF for UNIX, ON elsewhere); SET MATCH DOTFILE is simply a more
-untuitive and findable command than SET WILD KERMIT /MATCH-DOT-FILES.  Note
-that SET MATCH DOTFILE undoes SET OPTIONS DIRECTORY /[NO]DOTFILES, and vice
-versa.  ckcmai.c, ckuusr.h, ckuus[23].c, ckufio.c. 17 Oct 2002.
-
-Added client and server end of REMOTE SET MATCH { DOTFILE, FIFO } { ON, OFF }.
-The new protocol codes are 330 and 331, respectively.  ckuus[367].c, ckcfns.c,
-17 Oct 2002.
-
-Adjusted the "match dot if pattern starts with dot" heuristic in nzxpand()
-to not kick in if the filespec is "./foo".  This probably needs more work.
-ckufio.c, 17 Oct 2002.
-
-Fixed typo in transcribing Jeff's ckcfn3.c code from yesterday.  18 Oct 2002.
-
-Moved some help text out of #ifdef ANYSSH that had nothing to do with SSH.
-(Idea for a new EMACS feature: M-X list-ifdef-environment.)
-ckuus2.c, 18 Oct 2002.
-
-Removed "set file { permission, protection }" keywords, which led nowhere.
-ckuus7.c, 18 Oct 2002.
-
-Added -DSV68 to all SV/68 targets.  Make ckgetfqhostname() just return its
-argument in SV/68; it dumps core otherwise.  In case this happens anywhere
-else, add -DNOCKGETFQHOST to CFLAGS.  makefile, ckcnet.c, 18 Oct 2002.
-
-For PeterE, added SET { SEND, RECEIVE } PERMISSIONS { ON, OFF } so incoming and
-outbound permission attributes can be set separately. ckuus[27].c, 18 Oct 2002.
-
-Changed SHOW ATTRIBUTES to show In and Out permissions separately.
-ckuus5.c, 18 Oct 2002.
-
-Fixed REDO to display the command it's redoing and to add it to the bottom
-of the recall buffer.  ckuusr.c, 18 Oct 2002.
-
-Discovered that DATE SATURDAY dumps core...  Apparently it always did; this
-case was not included in the date-time torture test script.  The crash happens
-because the DATE parsing code doesn't check for a NULL date-converion
-error-message pointer.  Fixed in ckuusr.c, 18 Oct 2002.
-
-The reason DATE SATURDAY got a date-conversion error was that this path thru
-the code left a result pointer unset.  Fixed in cmcvtdate(): ckucmd.c,
-19 Oct 2002.
-
-DATE SUNDAY +1DAY returned incorrect results (for any day-of-week name, any
-delta time), even though DATE TODAY +1DAY worked fine.  Fixed in cmcvtdate():
-ckucmd.c, 19 Oct 2002.
-
-SET TAKE ECHO ON counted each line twice when GOTO was active.  Fixed in
-dogoto(): ckuus6.c, 19 Oct 2002.
-
-Jeff noticed:
-"KERMIT READY TO GET...
- RCVD: (2 files) Last: [/amd/prost/p/kd/jaltman/.src/ckonet.c] (OK)
-the last file attempted may have been ckonet.c but it certainly was
-not the last file received" (similarly for sending).  Fixed by having two
-pointers for each name; a preliminary pointer, which is set for each file at
-the beginning of the transfer (when we have all the needed info), and a final
-one that is set from the preliminary one only after the file was transferred
-successfully.  This corrects not only the automatic "wheremessage" at the end
-of a remote-mode transfer, but also the WHERE and SHOW FILE command results.
-ckuusx.c, ckcfn[s3].c, ckcpro.w, 19 Oct 2002.
-
-From Jeff: Improve ORIENTATION message for K95 to say which directories are
-for which INI files.  ckuusr.c, 23 Oct 2002.
-
-Removed Beta designation from herald.  ckcmai.c, 23 Oct 2002.
-
-Put final dates and ID strings in Unix and VMS build procedures.
-Makefile, ckvker.com, 23 Oct 2002.
-
-Build-all...  #ifdef adjustments: ckcfns.c...  83 different feature-set
-combinations build OK on Linux.  23 Oct 2002.
-
-From Jeff: SET WIN95 HORIZONTAL-SCAN-LINE-SUBSTITUTIONS.  ckuusr.h, ckuus7.c,
-24 Oct 2002.
-
-Fixed Heath-19 graphic character-set table to use new Unicode 3.1 values
-if WIN95 HORIZ OFF.  ckcuni.c, 24 Oct 2002.
-
-Changed tx_usub() to return Unicode 3.1 values if WIN95 HORIZ OFF.
-ckcuni.c, 24 Oct 2002. <-- No backed off on this.
-
-Some problems during build-all:
-
- . VMS 7.1 TGV 4.2: If I make a Telnet connection with it, then try to send
-   a file (itself. wermit.exe) over the connection, the connection drops
-   after about 20%, the thermometer zooms out to 100% and SUCCESS is reported.
-   This doesn't happen with UCX.
-
- . VMS 7.3 TGV 4.3: ckcmai.c won't compile because of a complaint about the
-   declaration of select() (which ckcmai.c doesn't use) in
-   SYS$COMMON:[SYSLIB]DECC$RTLDEF.TLB.  Ditto in VMS 7.2 TGV 4.3.
-   Adding NOSELECT to CFLAGS doesn't help.  I don't think the VMS version
-   even uses select().  But the TGV 4.3 builds were OK in 8.0.201, so what
-   changed?  I don't see anything in ckcnet.h that would have done it.
-
-It builds OK with VMS 7.1 / TGV 4.2 but sending files on Telnet connections
-fails in a strange way: the connection drops, but the thermomoter goes to 100%
-and success is reported.  I don't know why the connection is dropping (s_errno
-is 32 == "broken pipe"), but the spurious success indication is because of
-a double failure in sdata(): (1) The packet-sending loop index could go
-negative without breaking the loop when streaming; (2) if spack() fails,
-sdata() should return -2, not -1 (which means EOF).  Also if any ttchk() in
-sdata() returns < 0, sdata should return -2.  I fixed this code (which has
-been this way for YEARS) and now VMS C-Kermit properly fails when it gets
-the spack() error, but ttchk() in this case still doesn't think the connection
-is lost, but that must be our new problem with MultiNet.  ckcfns.c,
-27 Oct 2002.
-
-The compilation failure in ckcmai.c is a clue...  The problem was that I added
-#ifdef VMS / #include <time.h> / #endif to shut up complaints about the time()
-call.  Evidently something in VMS <time.h> gives MultiNet a bad case of
-indigestion; removing it fixes the compilation and the result works fine.  The
-transmission failures in the other case seem to be a coincidence -- something
-to do with the U of Arizona (probably some obscure VMS quota on my IDs there,
-or some kind of network connection throttling), since it doesn't happen
-anywhere else.  ckcmai.c, 27 Oct 2002.
-
-Changed four occurrences of "void" to "VOID" in ckcftp.c, 27 Oct 2002.
-
-Defined NOCKFQHOSTNAME for HPUXPRE65.  Might also need this for HP-UX 7
-and maybe 8.  ckcnet.c, 27 Oct 2002.
-
-From Jeff: PAM_CONST definition to clear up warnings caused by different
-vendors' definitions of PAM structs.  ckufio.c, 28 Oct 2002.
-
-Unixware 2.1.0 build bombs immediately with "UX:make: ERROR: line too long"
-(which line?)  Not worth chopping up the makefile to fix but in a pinch it
-could be done.  2.1.3 builds OK.
-
-Did another 20-some platform builds, bringing the total to 83, plus a final
-runthrough of the build-with-84-different-feature-set-combinations script on
-Linux.  Should be good to go!
-
---- 8.0.206 24 Oct 2002 ---
-
-Finally got access to Linux on IA64 again.  Builds OK but dumps core
-immediately on startup.  Adding -DNOCKGETFQHOST was necessary but not
-sufficient.  In this case, the very call to ckgetfqhostname() from ckhost()
-(which is in ckuusx.c) was dumping core; thus I had to move the definition of
-NOCKGETFQHOST from ckcnet.c to ckcdeb.h, add an #ifdef __ia64__ clause to it,
-and protect the call to ckgetfqhostname() with it.  Obviously there has to be
-a better fix but this will have to for now.  ckcnet.c, ckuusx.c, ckcdeb.h,
-31 Oct 2002.
-
-Link step fails in Mandrake 9.0 with undefined references to res_search,
-dn_expand, and crypt.  Turns out the linux makefile target tests for the
-existence of libcrypt.a and libresolv.a, but in Mandrake 9.0 they exist
-only as *.so.  Changed linux target to look for both.  makefile, 1 Nov 2002.
-
-Vace reported that "ftp mget a b c" would get ALL files from the server's
-directory if c did not exist.  Diagnosis: off-by-one error in counting MGET
-args processed.  Naturally fixing this bug revealed another (this time
-cosmetic) one, which resulted in spurious error messages when hitting MGET
-args that have no match on the server.  Fixed in ckcftp.c, 1 Nov 2002.
-
-Rebuilt about 60 of the most important Unix binaries to pick up the fixes
-31 Oct - 1 Nov 2002, and refreshed the FTP site with new sources, tarballs,
-ZIP files, etc.  Sat Nov  2 19:11:30 2002
-
-From Martin Vorlaender and Jeff, SSL/TLS support for VMS:
-ckuusr.h, ckuath.h, ckcnet.c, ckctel.c, ckuath.c, 10 Nov 2002.
-
-Added PASV as invisible synonym for PASSIVE.  ckcftp.c, 10 Nov 2002.
-
---- 8.0.206 24 Oct 2002 #2 ---
-
-More work on SSL in VMS: Jeff + Martin Vorlaender: ck_ssl.c ckcmai.c ckcnet.c
-ckctel.c ckuath.h ckvcon.c ckvtio.c ckvker.com 10-15 Nov 2002.
-
-Discovered that ckvfio.c would not compile on VMS 6.1 with UCX 4.1 because 
-<conv$routines.h> was missing, which is explicitly included.  Enclosed the
-#include in #ifdef NOCONVROUTINES..#endif and rebuilt with
-@[users.fdc.src]ckvker.com "" "" "NOCONVROUTINES".  16 Nov 2002.
-
-Fixed the "ftp mget */data/*" problem with two small changes to doftpget():
-ckcftp.c, 16 Nov 2002.  Placed a copy of ckcftp.patch in ~kermit/f.
-
-From Lucas Hart: Fixes for VAX C 2.x and CMU TCP/IP.  "Can't guarantee that
-the revised CKVOLD will work for all combinations of more recent
-VMS/compiler/TCPIP releases, but I've tested it for compatibility on our AXP
-VMS 6.2, UCX 4.0, DECC 5.6, your AXP VMS 7.1, DEC TCPIP 5.1, DECC 6.0 as well
-as with VAX VMS 5.4, VAX C 3.2, CMU12 and VAX VMS 4.7, VAX C 2.4."  ckvfio.c,
-ckvtio.c, ckuus5.c, ckvker.com, ckvold.com, 17 Nov 2002.
-
-From Jeff: More work on VMS SSL.  Now it actually works, even in CONNECT mode,
-except it hangs when it gets an error alert or the remote closes the
-connection.  ckcnet.c. ckvtio.c, 17 Nov 2002.
-
-NOTE: Lucas's changes should go into the 8.0.206 source code but it's too
-late since ckvtio.c (upon which he based his changes) is already full of
-SSL code.
-
-MGET in K95 in totally broken FOR SOME PEOPLE (mainly me) if the TMP (or TEMP)
-value is too long.  It works fine if you set these to C:\TMP.  Diagnosis: (1)
-we were malloc'ing only 16 bytes for the temp file name (I think this was my
-fault -- I was only looking at the "ckXXXXXX" part and forgetting that this
-was appended to the TMP path); (2) the Windows version of mktemp() wants you
-to use the value pointed to by the pointer it returns, rather than assuming
-the mktemp() arg will be modified in place.  The code was changed to malloc a
-longer string and to use the return value from mktemp() (if any) rather than
-assuming that mktemp() modified its argument string (in K95 only -- not sure
-about Unix platforms; the man pages differ on this, but at least this way if
-some mktemp() version does NOT alter its argument, we still have a usable
-filename (like /tmp/ckXXXXXX)).  Of course this won't be good for recursive
-MLSD downloads, but we can always issue patches for the Unix version later if
-needed.  The Linux and BSD versions use mkstemp() anyway.  There is, however,
-a danger of a memory leak in the Unix version if the user has defined a TMPDIR
-or CK_TMP environment variable whose value is longer than 9 bytes.  All this
-is highly unlikely so we should be OK.  ckcftp.c, 17 Nov 2002.
-
---- K95 2.1.1 and updated ck[uv]206.{tar,zip} but not C-Kermit binaries ---
-
-From Jeff: Fixes for Telnet Com Port Control, update to a newer release of
-OpenSSL: ck_ssl.c ck_ssl.h ckcdeb.h ckcftp.c ckcmai.c ckcnet.c ckctel.c
-ckuath.c ckuath.h ckucns.c ckuus4.c ckuus5.c ckuusr.c ckuusr.h ckvcon.c
-ckvfio.c ckvker.com ckvtio.c ckvvms.h, 25 Nov 2002.
-
---- K95 2.1.2 and C-Kermit 8.0 CDROM ---
-
-From Jeff, 28 Nov 2002:
- . Updated SSL modules: ck_ssl.[ch].
- . Fixed cipher-list display in SHOW AUTH & FTP ssl_auth(): ckuus7.c. ckcftp.c
- . Some minor tn_wait() fixes: ckctel.c.
- . Preliminary SSL support for VMS CONNECT: ckvcon.c.
-
-Bumped C-Kermit edit number to 207.
-
-From Jeff, 29 Nov 2002: "[C-Kermit was dumping core on SCO OSR5 Telnet Com Port
-connections because] the SCO compiler treats all characters as signed.  This
-was causing 'sprintf(buf,"02x ",ch);' to produce strings such as "ffffffc2"
-instead of "c2" for values between 128 and 255.  This wrote beyond the end of
-a buffer and blew away the stack.  Having fixed this I also noticed that
-conect() did not properly check for carrier when TN CPC was negotiated.  This
-has now been fixed as well."  ckucns.c, ckucon.c, ckctel.c, 29 Nov 2002.
-
-From Jeff, 30 Nov 2002: Fix SSL for VMS and also carry forward the CPC fixes
-to VMS.  ckcnet.c, ckvtio.c, ckvcon.c, 30 Nov 2002.
-
-Changed copyright dates that are displayed (but not yet all the internal
-ones) from 2002 to 2003.  ckcmai.c, 3 Jan 2003.
-
-Fixed the FTP module's brief-format transaction log, which had the status
-inverted: OK for FAILED and v.v.  ckcftp.c 3 Jan 2003.
-
-From Jeff, 4 Jan 2003:
- . Make /MOVE-TO:xxx convert xxx to full pathname: ckuus[r67].c,
- . Make SHOW OPTIONS ALL show both kinds of options: ckuus2.c.
- . More command-line personalities: ckcmai.c, ckuusy.c.
- . New NOSCROLL command for K95: ckuusr.[ch], ckuus2.c.
- . New lockdown and other command-line options: ckuusr.h, ckuusy.c.
- . SSL interface updated to OpenSSL 0.9.7: ck_ssl.c.
- . SET TERM LINE-SPACING and CURSOR xxx NOBLINK: ckuus[27]c.
- . Expanded SHOW GUI command: ckuus3.c
- . New SHOW TABS code: ckuus5.c.
-
-Updated SUPPORT (BUG), NEWS, and INTRO texts.  ckuus[26].c. 5 Jan 2003.
-
-Fixed FTP module to suppress "'FEAT': Command not understood" message
-unless FTP DEBUG is ON.  ckcftp.c, 6 Jan 2003.
-
-Got a report that C-Kermit dumps core on Solaris when executing a certain
-script.  Seems to be related to changing vnambuf[] in zzstring() from an
-automatic array to a malloc'd buffer (see notes from 29 Jun 2000).  Changed
-it to an automatic buffer except for K95.  ckuus4.c, 6 Jan 2003.
-
-Nope, that's not it.  It evidently happens only after FTP PUT has been used.
-Fixed solaris9g makefile target to include -funsigned-char and built a new
-binary.  Determined that building with gcc and -funsigned-char makes no
-difference.  makefile, 7 Jan 2003.
-
-I did a preliminary audit, looking at the items in the left column: if used in
-a given routine, are there any obvious mistakes:
-
-                       1        2          3           4              5
-                   doftpput->putfile->sendrequest->doftpsend2->secure_write
-malloc                OK       OK         OK          OK             OK
-makestr               OK       OK        OK          OK             OK
-automatic arrays      OK       OK        OK          OK             OK
-[ck]str[n]cpy         OK       OK        OK          OK             OK
-[ck]str[n]cat         OK       OK        OK          OK             OK
-sprintf               OK       OK        OK          OK             OK
-nzltor                OK       OK        OK          OK             OK
-zfnqfp                OK       OK        OK          OK             OK
-memcpy                OK       OK        OK          OK             OK
-bcopy                 OK       OK        OK          OK             OK
-
-secure_write sends the data directly on clear-text connections.  On secure
-connections, it calls secure_putbuf(), which calls secure_putbyte(), but we
-aren't using those, so secure_write() is the end of the call chain for FTP
-PUT.  doftpsend2 has buf[] as an automatic array, which it reads file data
-into using zxin (binary mode only), but this looks OK.  Still, I changed it
-read 1 less than the buffer size (fread) just in case.  Also there was one
-debug() statement that referred to an automatic array (fullname[]) before it
-was initialized (but not used in this case), which I fixed.  ckcftp.c,
-7 Jan 2003.
-
-FTP GET /RECURSIVE somepath/somefile still didn't work, despite what the
-notes of 19 Sep 2001 say.  There are so many paths through the code,
-depending on switch values, GET vs MGET, etc, that a crucial spot was missed.
-Fixed in doftpget(): ckcftp.c, 7 Jan 2003.
-
-Back to the core dump...  after two days of full-time debugging, I found the
-culprit: the buffer-full test in the zzout() macro should have been ">="
-rather than just ">", thus Kermit wrote 1 byte past the end of the malloc'd
-FTP PUT output buffer, ucbuf.  Why did it never happen in K95?  Because, since
-it's a secure build, FUDGE_FACTOR is defined there.  But it's not defined in
-Solaris or other clear-text builds.  Although the crash wouldn't happen in
-secure builds, the 1-byte leak might have caused errors in the data transfer.
-In non-Solaris clear-text builds, like Linux, I suspect that malloc() tends
-add something for safety (especially given the man page statement that it
-allocates "at least" what you asked for).  Another reason the problem escaped
-notice is that zzout() is used only for text-mode PUTs (and then only when
-there is no character-set translation), but most transfers these days are
-binary and/or downloads.  Anyway, in the course of debugging, a lot of small
-cleanups were done: sizeof(blah) for all arrays was replaced by the same
-symbolic size that was used to allocate the array, numeric array sizes were
-replaced with symbolic ones, etc.  The real fix is one character long.
-ckcftp.c, 9 Jan 2003.
-
-Got a report that "mget /recursive */somedir/*" downloaded the files into
-the current directory, rather than re-creating the remote directory structure.
-Fixed in doftpget(): ckcftp.c, 10 Jan 2003.
-
-Unix C-Kermit did not allow file transfer if started under inetd and accessed
-via Internet raw socket (or whatever).  Diagnosis: isatty() and friends would
-fail causing ttopen() to fail.  Fixed by adding escape clauses for "-l 0"
-situations (i.e. Kermit invoked with an already-open file descriptor) at the
-appropriate places.  ckcmai.c, ckutio.c, 14 Jan 2003.
-
-From Jeff for K95 2.1.3
- . Add test for startflags & 128 to trap() for ignoring BREAK.
- . Fix for SHOW TRANSMIT.
-
---- K95 2.1.3 ---
-
-FTP USER, FTP ACCOUNT, plus the various prompts and switches for FTP username,
-password, and account all neglected to strip quotes, and in most cases quotes
-are necessary to specify a username that contains spaces.  ckcftp.c,
-15 Jan 2003.
-
-FTP MPUT f1 f2 f3... gets a parse error if any of the fn's do not match an
-existing file.  This is bad for scripts.  In doftpput(), cmfdb() looks for
-keywords (switches) or CMIFI.  When it hits CMIFI, it exits from the initial
-parse loop and then does additional cmifi()s in a loop until done.  The most
-obvious fix is to parse each field with cmfdb(CMIFI,CMFLD), i.e. fall back to
-CMFLD if CMIFI doesn't match anything.  Then if CMFLD was used, we don't add
-the filespec to the list.  This is a rather big change but it seems to work.
-No error messages or failures happen for non-matching fields, but an error
-message is printed (and the MPUT command fails) if none of the fields match
-any files.  This fix got in too late for 2.1.3; workaround: use C-Shell
-like wildcard list (ftp mput "{*.abc,foo.*}").  ckcftp.c, 16 Jan 2003.
-
-GREP did not pass its pattern through the expander, thus variables could
-not be used for patterns.  This must have been an oversight -- I can't find
-anything in my notes about it.  Fixed in dogrep(): ckuus6.c, 24 Jan 2003.
-
-New makefile target for HP-UX 11.xx with OpenSSL from Tapani Tarvainen.
-makefile, 31 Jan 2003.
-
-From Jeff:
- . Avoid core dump when dereferencing tnc_get_signature(): ckuus4.c.
- . Bump version numbers to 8.0.208, 2.1.4: ckcmai.c.
-
-Added /NOLOGIN to FTP [OPEN].  ckcftp.c, 10 Feb 2003.
-
-Don't dump core if FTP DEBUG is ON and FTP OPEN does not include a service.
-openftp(): ckcftp.c, 10 Feb 2003.
-
-HELP PATTERN text incorrectly identified commands and functions with
-floating and anchored patterns.  The corrected lists are:
-Floating: GREP, TYPE /MATCH:, /EXCEPT: patterns, \farraylook(),
-Anchored: IF MATCH, file-matching wildcards, \fsearch(), \frsearch()
-ckuus2.c, 10 Feb 2003.     
-
-INPUT n \fpattern(xxx) did not work for case-independent comparisons.
-Fixed in doinput(): ckuus4.c, 10 Feb 2003.
-
-It seems \fpattern() didn't work with MINPUT at all.  There was no code to
-handle \fpattern() in the MINPUT parse loop, so it never worked.  The code
-had to be totally rewritten to use cmfld() in a loop, rather than cmtxt()
-and then cksplit().  Furthermore, whenever any of the fields was an
-\fjoin(), this had to be split.  ckuusr.c, 10 Feb 2003.
-
-Macro replacement via \m() and \fdefinition() does not work as advertised
-(i.e. case sensitively) for associative array elements; e.g. \m(xxx<abc>) is
-treated the same as \m(xxx<ABC>), contrary to section 7.10.10 of the C-Kermit
-7.0 update notes, and to the fact that the two really do exist separately.
-Fixed by adding a static function isaarray(s) which succeeds if s is an
-associative array reference and fails otherwise, and then having \m()
-and \fdef() call mxxlook() (case-sensitive lookup) if isaarray(), otherwise
-(as before) mxlook()).  ckuus4.c, 11 Feb 2003.
-
-Fixed FTP OPEN to allow the /USER switch to override SET FTP AUTOLOGIN OFF,
-just as /NOLOGIN overrides SET FTP AUTOLOGIN ON.  ckcftp.c, 11 Feb 2003.
-
-In K95, "set key \1234 \27H" (any SET KEY command in which the first char of
-the definition was backslash, and the ONLY character after the backslash
-quantity was an uppercase letter, that letter would be lowercased).  Diagnosis:
-xlookup() poking its argument (see notes from July 2000).  Jeff sent a fix.
-ckucmd.c, 15 Feb 2003.
-
-Ran my S-Expression torture test to make sure Sexps still worked.  They do,
-except the bitwise & and | operators were broken, e.g. (& 7 2) and (| 1 2 4)
-get "Invalid operand" errors.  Jeff's code had added an early failure return
-from the lookup loop when when a single-byte keyword matched a keyword that
-started with the same byte but was more than one byte long.  So "&" would hit
-"&&" and fail instead of continuing its search (xlookup tables aren't sorted
-so there can be no early return).  Fixed in xlookup(): ckucmd.c, 16 Feb 2003.
-
-Got rid of "krbmit" target from makefile.  It's still there, but we don't
-use it any more.  All secure targets now use "xermit", and produce a binary
-called wermit, just like the regular ones do (except the old ckucon.c ones).
-Non-secure targets, since they don't define any of the security symbols,
-wind up compiling and linking to (mostly) empty security modules.  makefile,
-15 Feb 2003.
-
-Added \fcvtdate(xxx,3) to format its result in MDTM format (yyyymmddhhmmss,
-all numeric, no spaces or punctuation).  Of course these numeric strings
-are too big to be 32-bit numbers and are useless for arithmetic, but they're
-useful for lexical comparison, etc.  ckuus[24].c, 16 Feb 2003.
-
-The following FTP commands did not set FAILURE when they failed: RMDIR,
-CD, CDUP, Fixed in the corresponding doftpblah() routines.  ckcftp.c,
-16 Feb 2003.
-
-RENAME would sometimes not print an error message when it failed, e.g. in K95
-when the destination file already existed.  ckuus6.c, 17 Feb 2003.
-
-Fixed COPY error messages, which did not come out in standard format when
-/LIST was not included.  ckuus6.c, 17 Feb 2003.
-
-Fixed #ifdefs in ck_crp.c to allow nonsecure builds on old platforms like
-System V/68 R3.  19 Feb 2003.
-
-Similar treatment for ck_ssl.c.  20 Feb 2003.
-
-From Jeff, 21 Feb 2003:
- . AIX53 and AIX52 symbols for ckcdeb.h, makefile.
- . New gcc targets for various AIX 4.x/5.x versions: makefile.
- . Copyright date updates: ck_crp.c, ck_ssl.c.
- . ENABLE/DISABLE QUERY broken because keyword table out of order: ckuusr.c.
- . Fixed the use of HTTP proxies for HTTP [RE]OPEN for Unix: ckcnet.c.
-
-Also for K95 only: Allow file transfer when K95 is invoked on the remote end
-of a connection to a Pragma Systems Terminal Server connection; automatically
-SET EXIT HANGUP OFF when invoked with open port handle ("k95 -l nnnn").
-
-"cd a*" failed even when "a*" matched only one directory.  Fixed in cmifi():
-ckucmd.c, 21 Feb 2003.
-
-In the Unix version, replace "extern int errno;" with "#include <errno.h>"
-if __GLIBC__ is defined, since glibc now defines a thread-specific errno.
-ckcdeb.h, 26 Feb 2003.
-
-Added #ifdefs to skip compilation of ckuath.c in nonsecure builds.  Tested
-by building both secure and regular versions in Linux.  ckuath.c, 26 Feb 2003.
-
-Ran the build-in-84-different-configurations script on Linux to make sure it
-still builds with all different combinations of feature selection options.
-All OK.  26 Feb 2003.
-
-Built on VMS.  Needed to add a prototype for mxxlook*() to ckuusr.h; built
-OK otherwise.  26 Feb 2003.
-
-From Jeff: More #ifdef shuffling for nonsecure builds: ckuath.c, ck_ssl.c,
-27 Feb 2003.
-
-Added code to ensure \v(download) ends in a directory separator in Unix,
-Windows, and OS/2.  ckuus7.c, 27 Feb 2003.
-
-Added code to K95 zfnqfp() to tack on directory separator when returning
-a directory name.  ckofio.c, 27 Feb 2003.
-
-Somehow an old copy of ckuath.c popped to replace the new one.  Put the new
-one back.  28 Feb 2003.
-
-From Jeff: Fix typo in my K95 zfnqfp() code from yesterday; fixes for handling
-UNCs uniformly, no matter which way their slashes are leaning.  ckofio.c,
-28 Feb 2003.
-
-At Jeff Mezei's suggestion, separate text and binary mode open sequences
-for VMS session log.  ckvfio.c, 28 Feb 2003.
-
-Added freebsd48 target for FreeBSD 4.8.  makefile, 1 Mar 2003.
-
-Changed Mac OS X entries to include -DUSE_STRERROR.  makefile, 2 Mar 2003.
-
-Fixed GETOK /GUI to evaluate its text argument.  ckuus6.c, 3 Mar 2003.
-
-Jeff fixed the K95 Dialer QUICK dialog to (a) allow templates, and (b) have
-a Save-As option.  3 Mar 2003.
-
-Jeff fixed a problem with the Xmodem-CRC checksum being crunched whenever
-there was a retransmission.  7 Mar 2003.
-
-Added target/banner for Tru64 5.1B.  makefile, ckuver.h, 5 Mar 2003.
-
-In Unix, the zcopy() routine (used by the COPY command) reset the user's umask
-to 0 for the remainder of the Kermit process lifetime.  The bug was in
-ckufio.c 8.0.194, 24 Oct 2002, and is fixed in ckufio.c 8.0.195, 6 Mar 2003.
-Of course this happened after building 155 C-Kermit 8.0.208 binaries.  (But
-before officially releasing 8.0.208.)
-
-In the VMS version, changed:
-
-        while ((n--) && xx_inc(2) > -1) ;
-to:
-        while ((n--) && xx_inc(2) >= 0) ;
-
-to suppress the "...is being compared with a relational operator to a constant
-whose value is not greater than zero" warning.  ckvtio.c, 7 Mar 2002.
-
-Added a debug call to dologend in hopes of catching overzealous Locus
-switching, which seems to happen only in K95.  ckuus3.c, 7 Mar 2002.
-
-Rebuilt binaries for some of the more current Unix releases: AIX 4.3.3-5.1,
-Solaris 7-9 , Red Hat 7.0-8.0, Slackware 8.1, Freebsd 4.7-4.8, NetBSD 1.6,
-OpenBSD 3.2, Unixware 7.1.3, Open Unix 8, OSR5.0.6a, etc.  A Unix binary with
-COPY umask fix shows a 6 Mar 2003 date for "UNIX File support" in SHOW
-VERSIONS; a binary without the fix shows 24 Oct 2002.
-
-C-Kermit 8.0.208 dated 14 March 2003 released on 10 March 2003.
-
----8.0.208---
-
-From Jeff 13 Mar 2003:
- . Updated SSL module allows importation of tickets from host.
- . freebsd50+openssl target: makefile.
- . FTP PUT /PERMISSIONS error message for K95: ckcftp.c.
-Fixed MINPUT to strip quotes or braces from around targets (this was broken
-on Feb 10th).  Thanks to Jason Heskett for discovering and reporting this
-(killer) bug.  ckuusr.c, 14 Mar 2003.
-
-Changed version number to 209 Dev.00.  ckcmai.c, 14 Mar 2003.
-
-While debugging the alphapage script, I found that the command "minput 8 \6\13
-\21\13 \13\27\4\13 \30\13" gets "?Not confirmed" in 8.0.208 and 8.0.209, but
-not in 206 and earlier.  This problem too was introduced on Feb 10th by
-changing MINPUT parsing from cmtxt() followed by cksplit() to cmfld() in a
-loop.  cmfld() uses setatm() to return its result and of course setatm()
-breaks on \13.  Changing setatm() not to do this would break everything else.
-But cmfld() has no arguments that let us tell it to do anything different in
-this case.  Changing the API would be a disaster.  The only solution is to add
-an "MINPUT ACTIVE" (minputactive) global variable that tells cmfld() to tell
-setatm() not to break on CR.  Now MINPUT with braced targets containing CR
-and/or LF works in 209, 206, and 201 (but not 208).  ckucmd.c, ckuusr.c,
-ckuus5.c, 15 Mar 2003.
-
-MINPUT n \fjoin(&a) works OK if all the members of \&a[] are text strings, but
-if they are strings of control chars (as above), they don't get separated by
-the spaces.  For example in:
-
-  dcl \&a[] = "\4\5" "\6\7" xxx
-  minput 10 \fjoin(&a)
-
-MINPUT gets two targets: "aaa" and "\4\5 \6\7 xxx".  The bug was in the
-cksplit() call in the \fjoin() case of MINPUT: it needed to specify an
-include set consisting of all the control characters except NUL.  ckuusr.c,
-16 Mar 2003.
-
-But there's still a problem:
-
-  dcl \&a[] = "\4\5\13\10" "\6\7" "xxx"
-
-creates an array whose first member is "^D^E (one doublequote included).  But
-if braces are used instead, there's no problem.  Same deal as MINPUT: cmfld()
-breaks on CR or LF, thus the end quote is lost.  If I set minputactive for
-DECLARE initializers too, that fixes it.  Is there any reason not to do this?
-Can't think of any (famous last words)...  ckuusr.c, 16 Mar 2003.
-
-Since it has multiple applications, changed the flag's name from minputactive
-to keepallchars.  ckucmd.c, ckuus[r5].c, 16 Mar 2003.
-
-\v(exedir) wasn't being set correctly (it included the program name as well
-as the directory).  Fixed in getexedir(): ckuus4.c, 16 Mar 2003.
-
-SET CARRIER-WATCH <Esc> "auto matic" (spurious space in supplied keyword).
-Cosmetic only; it still worked.  Fixed in setdcd(): ckuus3.c, 16 Mar 2003.
-
-"directory a b c" listed too many files -- all files whose names END WITH a,
-b, or c, rather than the files whose names WERE a, b, or c.  Diagnosis: The
-filespec is changed into a pattern: {a,b,c}, which is the correct form.  It is
-passed to nzxpand(), which goes through the directory getting filenames and
-sending each one to ckmatch() with the given pattern.  ckmatch() receives the
-correct pattern but then prepends a "*" -- that's not right.  It's not just
-in filename matching either.  The following succeeds when it shouldn't:
-
-  if match xxxxc {{a,b,c}} <command>
-
-Changing ckmatch() to not prepend the "*" to each segment fixes the command
-above but breaks lots of others.  Running through the "match" torture-test
-script shows the problem occurs only when the {a,b,c} list is the entire
-pattern, and not embedded within a larger pattern.  Testing for this case
-fixed the problem.  ckmatch(): ckclib.c, 16 Mar 2003.
-
-Fixed FTP MODTIME to not print anything if QUIET ON.  ckcftp.c, 16 Mar 2003.
-
-Picked up a new ckuath.c from Jeff, not sure what the changes are. 16 Mar 2003.
-
-Did a few regular and secure builds to make sure I didn't wreck anything.
-
-Changed version number to 209 (final).  ckcmai.c, 16 Mar 2003.
-
-Jason Heskett found another bug: if you define a macro FOO inside the
-definition of another macro BAR, and FOO's definition includes an odd number
-of doublequotes (such as 1), FOO's definition absorbs the rest of BAR's
-definition.  Example:
-
-  def TEST {
-    .foo = {X"}
-    sho mac foo
-  }
-  do test
-  sho mac foo
-
-Results in:
-
-  foo = {X"}, sho mac foo
-
-Diagnosis: the TEST definition becomes:
-
-  def TEST .foo = {X"}, sho mac foo
-
-and the macro reader is erroneously treating the doublequote as an open
-quote, and then automatically closes the quote at the end of the definition.
-The error is that a doublequote should be significant only at the beginning of
-a field.  But the macro reader isn't a command parser; it doesn't know what
-a field is -- it's just looking for commas and skipping over quoted ones.
-First we have to fix an oversight: SET COMMAND DOUBLEQUOTING OFF should have
-worked here, but it wasn't tested in this case.  Fixed in getncm(): ckuus5.c,
-17 Mar 2003.
-
-There are only certain cases where it makes sense to treat doublequotes as
-signicant:
-
- . An open quote must be at the beginning or preceded by a space.
- . A close quote is only at the end or else followed by a space.
-
-This too was fixed in getncm(): ckuus5.c, 17 Mar 2003.
-
-A fix from Jeff SSL/TLS FTP data decoding.  ckcftp.c, 18 Mar 2003.
-
-Tried building C-Kermit on a Cray Y-MP with UNICOS 9.0.  "int suspend",
-declared in ckcmai.c and used in many modules, conflicts with:
-
-  unistd.h:extern int suspend __((int _Category, int _Id));
-
-The "=Dsuspend=xsuspend" trick doesn't work for this; there is no way around
-the conflict other than to rename the variable: ckcmai.c, ckutio.c,
-ckuus[35xy].c.  26 Mar 2003.  VMS and K95 not affected.
-
-OK that gets us past ckcmai.c...  Then in ckutio.c I had to add a new #ifdef
-around the LFDEVNO setting, because the Cray didn't have mkdev.h.  Could not
-find a Cray-specific manifest symbol, so I made a new makefile target (cray9)
-that sets this symbol.  Having done this I have no idea what kind of lockfile
-would be created, but I also doubt if anybody dials out from a Cray.  The
-binary should run a C90, J90, or Y-MP.  makefile, 26 Mar 2003.
-
-Added a target for SCO OSR5.0.7.  makefile, ckuver.h, 30 Mar 2003.
-
-Changed since 208:
-makefile ckuver.h ckcmai.c ckclib.c ckcftp.c ckucmd.c ckuus*.c ckutio.c.
-
----8.0.209---
-
-From Mark Sapiro, a fix for the March 17th doubleqote fix, getncm(): ckuus5.c,
-4 Apr 2003.
-
-From Jeff, 29 Apr 2003:
- . Corrected target for HP-UX 11.00 + OpenSSL: makefile, 
- . Do not allow WILL AUTH before WONT START_TLS: ckctel.h ckctel.c
- . Add hooks for SFTP and SET/SHOW SFTP: ckcdeb.h ckuusr.h ckuusr.c ckuus3.c
- . Add SKERMIT ckuusr.h ckuusr.c
- . Add ADM-5 terminal emulation: ckuus7.c, ckuus5.c
- . Uncomment and update HELP SET SSH V2 AUTO-REKEY: ckuus2.c
- . Enable IF TERMINAL-MACRO and IF STARTED-FROM-DIALER for C-Kermit: ckuus6.c
- . Fix conflicting NOSCROLL keyword definition: ckuusr.h
- . Set ttname when I_AM_SSH: ckuusy.c
- . Add extended arg parsing for SSH, Rlogin, Telnet: ckuusy.c, ckuus4.c
- . Security updates: ckuath.c, ck_ssl.c
- . Change K95 version number to 2.2.0: ckcmai.c
- . Save K95 term i/o state before executing keyboard macro: ckuus4.c
- . Add tests for SSH Subsystem active during INPUT/OUTPUT/CONNECT: ckuus[45].c
- . Enable K95 SET SSH V2 AUTO-REKEY: ckuus3.c
-
-SFTP and SET SFTP subcommands are implemented up to the case statements.
-
-Files of mine that Jeff hadn't picked up:
-  ckuver.h ckcftp.c ckutio.c ckuusx.c (just minor changes for last build-all)
-
-On 4 Jan 2003, SET RECEIVE MOVE-TO was changed to convert is argument to an
-absolute path, which made it impossible to specify a relative path, then
-move to different directories and have it apply relatively to each directory.
-Changed this as follows:
-
- . Parser uses cmtxt() rather than cmdir() so it won't fail at parse time.
- . If path is absolute, we fail at parse time if directory doesn't exist.
- . In reof() we run the the path through xxstring (again, in case deferred
-   evaluation of variables is desired) and then, if not null, use it.
- . If the directory doesn't exist, rename() fails and reof() returns -4,
-   resulting in a protocol error (this is not a change).  We do NOT create
-   the directory on the fly. 
-
-I also fixed SET SEND/RECEIVE RENAME-TO to parse with cmtxt() rather than
-cmdir(), since it's parsing a text template, not a directory name, e.g.
-"set receive rename-to file-\v(time)-v(date)-\v(pid)".  This was totally
-broken, since when I don't know.  We don't call xxstring() in this parse, so
-evaluation is always deferred -- I'd better not change this.  ckuus7.c,
-ckcfns.c, 1 May 2003.
-
-From Jeff, Sat May  3 14:15:23 2003:
- . Pick up the right isascii definition for K95: ckctel.c
- . malloc...  ckuath.c (new safe malloc routines for K95)
- . Add author listing: ckuus5.c
- . SSH Heartbeat support (K95 only): ckuus[23].c
- . Prescan --height and --width to avoid window resizing at startup: ckuusy.c
- . Add checks for fatal() or doexit() called from sysinit(): ckuusx.c
- . Move some K95-specific definitions to ckoker.h: ckcdeb.h
- . Add support for ON_CD macro in zchdir(): ckufio.c
- . Add a command to let FTP client authenticate with SSLv2: ckcftp.c
- . Fix parsing of FTP file facts like "UNIX.mode": ckcftp.c
-
-ON_CD will need some explaining (to be done).  It's implemented for Unix,
-VMS, WIndows, and OS/2.
-
-The FTP file facts fix came from first exposure to the new OpenBSD FTP
-server: ftp://ftp7.usa.openbsd.org/pub/os/OpenBSD/3.3/i386/
-The period in "UNIX.mode" caused an erroneous word break, adding junk to
-the filename.
-
-About the malloc changes, Jeff says "K95 is not behaving well in low memory
-environments.  I'm not sure that C-Kermit does much better.  The program does
-not crash but it certainly does not behave the way the user expects it to.
-I'm beginning to think that any malloc() error should be treated as fatal."
-
-Not visible in these changes because it's in K95-specific modules: Jeff made
-SET ATTRIBUTES OFF and SET ATTRIBUTES DATE OFF apply to XYZMODEM transfers.
-
-From Jeff, 11 May 2003:
- . Add support for SSH Keepalive to relevant SET command (K95): ckuus3.c
- . Reduce max overlapped i/o requests from 30 to 7 (K95): ckuus7.c
- . Don't call sysinit() in fatal(): ckuusx.c.
- . Some new conditionalizations for SSL module: ck_ssl.c
-
-The doublequote-parsing fixes from March and April broke the SWITCH statement,
-which is implemented by internally defining, then executing, a macro.  If I
-drop back to the old dumb handling of doublequotes, everything is fixed except
-the problem of March 17th.  But can we really expect getncm() to pre-guess
-what the parser is going to do?  getncm()'s only job is to find command
-boundaries, which are represented by commas.  Commas, however, is needed IN
-commands too.  We take a comma literally if it is quoted with \, or is inside
-a matched pair of braces, parens, or doublequotes.  It is not unreasonable to
-require a doublequote in a macro definition to be prefixed by \ when it is to
-be taken literally.  The proper response to Jason Heskett's complaint of March
-17th should have been to leave the code alone and recommand an appropriate
-form of quoting:
-
-  def TEST {
-      .foo = {X\"}
-      sho mac foo
-  }
-
-And this is what I have done.  Another reason for sticking with the old method
-is that it's explainable.  The "improved" method, even if it worked, would be
-be impossible to explain.  Btw, in testing this I noticed that the switch-test
-script made 8.0.201 dump core.  Today's version is fine.  The problem with
-quoted strings inside of IF {...} clauses and FOR and WHILE loops is fixed
-too.  Perhaps "unbroken" would be a better word.  ckuus5.c, 11 May 2003.
-
-Vace discovered that FTP MGET /EXCEPT:{... (with an unterminated /EXCEPT list)
-could crash Kermit.  Fixed in ckcftp.c, 11 May 2003.
-
-CONTINUE should not affect SUCCESS/FAILURE status.  ckuusr.c, 11 May 2003.
-
-Fixed an oversight that goes back 15 years.  While \{123} is allowed for
-decimal codes, \x{12} and \o{123} were never handled.  ckucmd.c, 11 May 2003.
-
-Added support for Red Hat <baudboy.h> and /usr/sbin/lockdev.  Supposedly this
-allows Kermit to be installed without setuid or setgid bits and still be able
-to lock and use the serial device.  Compiles and starts, but not tested.
-ckcdeb.h, makefile, ckutio.c, ckuus5.c, 16 May 2003.
-
-From Jeff: FTP ASCII send data to host when FTP /SSL was in use was broken.
-ftp_dpl is set to Clear when FTP /SSL is in use.  This was causing the data to
-be written to the socket with send() instead of the OpenSSL routines.
-ckcftp.c, ckuath.c, 21 May 2003.
-
-From Jeff: Stuff for Kerberos 524: ckcdeb.h.  Fixes for FTP; "FTP ASCII send
-data did not properly compute the end of line translations.  On Unix (and
-similar platforms) the end of line was correct for no character sets but
-incorrect when character sets were specified.  On Windows/OS2, the end of line
-was correct when character sets were specified and incorrect when they were
-not.  On MAC, both were broken.  Also, FTP Send Byte counts were incorrect
-when character sets were specified."  ckcftp.c.  17 Jun 2003.
-
-From Jeff: fixes to HTTP /AGENT: and /USER: switch action: ckcnet.c ckuus3.c
-ck_crp.c ckcftp.c ckuus2.c ckuusy.c ckuusr.c ckcnet.h, 21 Jun 2003.
-
-From Jeff: Fix SET DIALER BACKSPACE so it can override a previous SET KEY
-(e.g. from INI file): ckuus7.c.  Some SSL/TLS updates: ck_ssl.c.  HTTP support
-for VMS and other VMS improvements (e.g. a way to not have to hardwire the
-C-Kerit version number into the build script) from Martin Vorlaender:
-ckcnet.h, ckuus[r3].c, ckcdeb.h, ckvtio.c, ckcnet.c, ckvker.com.  Built on
-Solaris (gcc/ansi) and SunOS (cc/k&r).  The new VMS script tests the VMS
-version and includes HTTP support only for VMS 6.2 or later.  2 Jul 2003.
-
-Tried to build on our last VMS system but it seems to be dead.  Looks like a
-head crash (makes really loud noises, boot says DKA0 not recognized) (fooey, I
-just paid good money to renew the VMS license).  Tried building at another
-site with:
-
-  Process Software MultiNet V4.3 Rev A-X,
-  Compaq AlphaServer ES40, OpenVMS AXP V7.3
-  Compaq C V6.4-008 on OpenVMS Alpha V7.3
-
-Had to make a few corrections to ckvker.com.  But still, compilation of
-ckcnet.c bombs, indicating that the SELECT definition somehow got lost
-somewhere since the 209 release (i.e. no SELECT type is defined so it falls
-thru to "SELECT is required for this code").  But I don't see anything in
-ckcdeb.h or ckcnet.[ch] that would explain this.  Not ckvker.com either
-(putting the old one back gives the same result).  OK, I give up, maybe it's
-just that I haven't tried building it on MultiNet recently.  What about UCX?
-Aha, builds fine there except for warnings about mlook, dodo, and parser in
-ckvfio.c (because of ON_CD) -- I suppose I have #include <ckucmd.h>... (done)
-Anyhow it builds OK and the HTTP code is active and almost works (HTTP OPEN
-works; HTTP GET seems to succeed but creates an empty file every time).  Tried
-building under MultiNet at another installation; same bad result.
-
-OK so why won't it build for MultiNet?  Comparing ckcnet.c with the 209
-version, not a single #ifdef or #include is changed.  Tried building with
-p3="NOHTTP" -- builds OK, aha.  Where's the problem?  Not ckcnet.h...
-Not ckcdeb.h...  OK I give up, will revisit this next time I get time to
-do anything with the code.
-
-Later Jeff said "Martin did not implement VMS networking for the HTTP code.
-All he did was activate the #define HTTP which happens to work because his
-connections are using SSL/TLS connections.  http_inc(), http_tol(), etc have
-no support for VMS networking regardless of whether it is UCX or MULTINET.
-The vast majority of HTTP connections are not secured by SSL/TLS.  It makes no
-sense to support HTTP on VMS until someone is willing to either do the work or
-pay have the work done to implement VMS networking in that code base."  So the
-fix is to not enable HTTP for VMS after all.  Removed the CKHTTP definition
-for VMS from ckcdeb.h, 6 Jul 2003.
-
-Fixed ckvfio.c to #include <ckuusr.h> (instead of <ckucmd.h>) to pick up 
-missing prototypes.  6 Jul 2003.
-
-From Arthur Marsh: solaris2xg+openssl+zlib+srp+pam+shadow and the corresponding
-Solaris 7 target.  makefile, 6 Jul 2003.
-
-Remove duplicate #includes for <sys/stat.h>, <errno.h>, and <ctype.h> from
-ckcftp.c.  6 Jul 2003.
-
-Add -DUSE_MEMCPY to Motorola SV/68 targets because of shuffled #includes in 
-ckcftp.c.  8 Jul 2003.
-
-From Jeff: Fix problems mixing SSL and SRP without Kerberos.  Plus a few minor
-#define comment changes and a reshuffling of #defines in ckcdeb.h to allow me
-to build on X86 Windows without Kerberos.  ckcdeb.h, ck_crp.c, ckuath.c,
-10 Jul 2003.
-
-From Jeff: updated ckuat2.h and ckuath.c, 29 Jul 2003.
-
-Mats Peterson noticed that a very small Latin-1 file would be incorrectly
-identified as UCS-2 by scanfile().  Fixed in ckuusx.c, 29 Jul 2003.
-
-Fixed ACCESS macro definition to account for the fact that FIND is now a
-built-in command.  ckermit.ini, 30 Jul 2003.
-
-From Jeff: Fix for typo in urlparse() (svc/hos): ckuusy.c, 18 Aug 2003.
-
-From Jeff: Redhat9 makefile targets (needed for for OpenSSL 0.9.7):
-makefile, 19 Aug 2003.
-
-GREP /NOLIST and /COUNT did too much magic, with some undesirable fallout:
-"GREP /NOLIST /COUNT:x args" printed "file:count" for each file.  "GREP
-/COUNT:x /NOLIST args" did not print "file:count", but neither did it set the
-count variable.  Removed the magic.  Also one of the GREP switches,
-/LINENUMBERS, was out of order.  Fixed in ckuus6.c, 20 Aug 2003.
-
-From Jeff: "Reorganizing code to enable building with different subsets of
-options; a few typos corrected as well."  ckcdeb.h, ckuver.h (for RH9),
-ckcnet.c, ckuus7.c, ckuus3.c: 24 Aug 2003.
-
-Scanfile misidentified a big PDF file as text because the first 800K of it
-*was* text (most other PDF files were correctly tagged as binary).  Fixed
-by adding a check for the PDF signature at the beginning of the file.
-scanfile(): ckuusx.c, 25 Aug 2003.
-
-Ditto for PostScript files, but conservatively.  Signature at beginning of
-file must begin with "%!PS-Ado".  If it's just "%!" (or something nonstandard
-like "%%Creator: Windows PSCRIPT") we do a regular scan.  Also added "*.ps"
-to all binary filename patterns.  ckuusx.c, 4 Sep 2003.
-
-Ditto (but within #ifndef NOPCLSCAN) for PCL (<ESC>E) and PJL (<ESC>%) files,
-but no binpatterns (note: ".PCL" is the extension for TOPS-20 EXEC scripts).
-ckuusx.c, 4 Sep 2003.
-
-Added comments about OpenSSL 0.9.7 to all linux+openssl targets.
-makefile, 4 Sep 2003.
-
-From Jeff: Added - #define ALLOW_KRB_3DES_ENCRYPT.  When this symbol is defined
-at compilation Kermit will allow non-DES session keys to be used during Telnet
-Auth.  These session keys can then be used for Telnet Encrypt.  The reason
-this is not compiled on by default is that the MIT Kerberos Telnet does not
-follow the RFC for constructing keys for ENCRYPT DES when the keys are longer
-than 8 bytes in length.  ckuath.c, ckuus5.c, 4 Sep 2003.
-
-"ftp mget a b c" succeeded if one or more of the files did not exist, even
-with "set ftp error-action proceed".  This is because the server's NLST file
-list does not include any files that don't exist, so the client never even
-tries to get them.  Fortunately, the way the code is structured, this one was
-easy to fix.  ckcftp.c, 14 Sep 2003.
-
-From Jeff: Corrected code in ckcnet.c to ensure that Reverse DNS Lookups are
-not performed if tcp_rdns is OFF.  Fixed ck_krb5_getrealm() to actually return
-the realm of the credentials cache and not the default realm specified in the
-krb5.conf file.  Previously krb5_cc_get_principal() was not being called.
-Fixed ck_krb5_is_tgt_valid() to test the TGT in the current ccache and not the
-TGT constructed from the default realm.  ckcnet.c, ckuath.c, 14 Sep 2003.
-
-Marco Bernardi noticed that IF DIRECTORY could produce a false positive if
-the argument directory had previously been referenced but then removed.  This
-is because of the clever isdir() cache that was added to speed up recursion
-through big directory trees.  Changed IF DIRECTORY to make a second check
-(definitive but more expensive) if isdir() succeeds, and changed the
-directory-deleting routine, ckmkdir(), to flush the directory cache (UNIX
-only -- this also should be done in K95 but it's not critical).  This was
-done by adding a routine, clrdircache() to ckufio.c, which sets prevstat
-to -1 and prevpath[0] to NUL.  ckcfn3.c, ckuus6.c, ckufio.c, 18 Sep 2003.
-
-Marco reported the second fix still didn't work for him (even though it did
-for me).  Rather than try to figure out why, I concluded that the directory
-cache is just not safe: a directory found a second ago might have been deleted
-or renamed not only by Kermit but by some other process.  Why did I add this
-in the first place?  The log says:
-
-  Some debug logs showed that isdir() is often called twice in a row on the
-  same file.  Rather than try to sort out clients, I added a 1-element cache
-  to Unix isdir().  ckufio.c, 24 Apr 2000.
-
-Experimentation with DIR and DIR /RECURSIVE does not show this happening at
-all.  So I #ifdef'd out the directory cache (see #ifdef ISDIRCACHE in ckufio.c;
-ISDIRCACHE is not defined) and backed off the previous changes: ckufio.c,
-ckcfn3.c, ckuus6.c, 28 Sep 2003.
-
-From Jeff: Replace the compile time ALLOW_KRB_3DES_ENCRYPT with a run-time
-command SET TELNET BUG AUTH-KRB5-DES which defaults to ON: ckctel.[ch],
-ckuus[234].c, ck_crp.c, ckuath.c.  4 Oct 2003.
-
-Allow DIAL RETRIES to be any positive number, and catch negative ones.
-Also added code to check for atoi() errors (e.g. truncation).  At least on
-some platforms (e.g. Solaris) atoi() is supposed to set errno, but it
-doesn't.  ckuus3.c, ckucmd.c, 4 Oct 2003.
-
-Added /DEFAULT: to ASK-class commands (ASK, ASKQ, GETOK):
-
- . For popups: no way to send defaults to popup_readtext() or popup_readpass().
- . For GUI ASK[Q], pass default to gui_txt_dialog().
- . For GUI GETOK, convert "yes" "ok" or "no" default to number for uq_ok().
- . For Text GETOK, add default to cmkey().
- . For Text ASK[Q], add default to cmtxt().
- . For GETC, GETKEY, and READ: no changes.
-
-GETOK, ASK, and ASKQ with /TIMEOUT: no longer fail when the timer goes off
-if a /DEFAULT was supplied.  The GUI functions (uq_blah) don't seem to
-support timeouts.  Only the text version has been tested.  ckuus[26].c,
-4 Oct 2003.
-
-From Jeff: add /DEFAULT: for popups.  ckuus6.c. 6 Oct 2003.
-
-Change SET DIAL INTERVAL to be like SET DIAL RETRIES.  ckuus[34].c, 6 Oct 2003.
-
-Added target for HP-UX 10/11 + OpenSSL built with gcc, from Chris Cheney.
-Makefile, 12 Oct 2003.
-
-From Jeff, 6 Nov 2003:
- . #ifdef adjustments: ckcftp.c, ckcdeb.h
- . Fix spurious consumption of first byte(s) on Telnet connection: ckctel.c
- . Another HP PJL test for scanfile: ckuusx.c.
- . K95: Recognize DG4xx protected fields in DG2xx emulation: ckuus7.c.
- . Add SSLeay version display to SHOW AUTH command: ckuus7.c
- . Improved SET MOUSE CLEAR help text: ckuus2.c.
- . Improved Kverbs help text: ckuus2.c (+ new IBM-3151 Kverbs).
- . Some changes to ck_ssl.c, ckuath.c.
-
-From PeterE, 10 Nov 2003:
- . Improved HP-UX 10/11 makefile targets for OpenSSL.
- . #ifdef fix for OpenSSL on HP-UX: ck_ssl.c.
-
-Another new makefile from PeterE with improved and integrated HP-UX targets.
-12 Nov 2003.
-
-A couple fixes to the solaris9g+krb5+krb4+openssl+shadow+pam+zlib target
-from Jeff.  Added a solaris9g+openssl+shadow+pam+zlib target.  makefile,
-21 Nov 2003.
-
-From Jeff, 30 Nov 2003:
- . Fix SEND /MOVE-TO: ckuusr.c.
- . Fix K95 SET TITLE to allow quotes/braces around text: ckuus7.c.
- . Improved "set term autodownload ?" response: ckuus5.c.
- . Fix SHOW FEATURES to specify the protocol for encryption: ckuus5.c
- . Make {SEND, RECEIVE} {MOVE-TO, RENAME-TO} work for XYZMODEM (K95 only).
-
-From Jeff: 7 Jan 2004:
- . At one point Frank started to add a timer parameter to the
-   uq_txt() function but he only did it for the non-ANSI
-   compilers.  I added it for the ANSI compilers, fixed the
-   prototypes and provided a default value easily changed
-   DEFAULT_UQ_TIMEOUT: ckcker.h, ckuus[36].c, ck_ssl.c, ckcftp.c, ckuath.c.
- . Fixed SET TERMINAL DEBUG ON (typo in variable name): ckuus7.c.
- . Fixed BEEP INFORMATION; previously it made no sound, now uses
-   MB_ICONQUESTION.  ckuusx.c.
-
-From Ian Beckwith <ian@nessie.mcc.ac.uk> (Debianization), 7 Jan 2004:
- . Search dir/ckermit for docs, as well as dir/kermit in cmdini(): ckuus5.c.
- . New linux+krb5+krb4+openssl+shadow+pam target (kitchen sink minus SRP,
-   which Debian does not distribute): makefile.
- ? Mangles the DESTDIR support in makefile to install into a staging area:
-   makefile (I didn't take this one yet).
-
-Updated copyright notices for 2004, all modules.  7 Jan 2004.
-
-Added INPUT /NOMATCH, allowing INPUT to be used for a fixed amount of time
-without attempting to match any text or patterns, so it's no longer
-necessary to "input 600 STRING_THAT_WILL_NEVER_COME".  If /NOMATCH is
-included, INPUT succeeds if the timeout expires, with \v(instatus) = 1
-(meaning "timed out"); fails upon interruption or i/o error.  ckuusr.h,
-ckuus[r24].c, 7 Jan 2004.
-
-Added SET INPUT SCALE-FACTOR <float>.  This scales all INPUT timeouts by the
-given factor, allowing time-sensitive scripts to be adjusted to changing
-conditions such as congested networks or different-speed modems without
-having to change each INPUT-class command.  This affects only those timeouts
-that are given in seconds, not as wall-clock times.  Although the scale
-factor can have a fractional part, the INPUT timeout is still an integer.
-Added this to SHOW INPUT, and added a \v(inscale) variable for it.
-ckuusr.h, ckuus[r257].c, 7 Jan 2004.
-
-undef \%a, \fverify(abc,\%a) returns 0, which makes it look as if \%a is a
-string composed of a's, b's, and/or c's, when in fact it contains nothing.
-Changed \fverify() to return -1 in this case.  ckuus4.c, 12 Jan 2004.
-
-\fcode(xxx) returned an empty string if its argument string was empty.  This
-makes it unsafe to use in arithmetic or boolean expressions.  Changed it to
-return 0 if its argument was missing, null, or empty.  ckuus4.c, 12 Jan 2004.
-
-Updated \verify() and \fcode() help text.  ckuus2.c, 12 Jan 2004.
-
-While setting up IKSD, Ian Beckwith noticed that including the --initfile:
-option caused Kermit to start parsing its own Copyright string as if it were
-the command line, and eventually crash.  I couldn't reproduce on Solaris /
-Sparc but I could in Linux / i386 (what Ian is using) -- a change from Jeff
-on 28 Apr 2003 set the command-line arg pointer to a literal empty string in
-prescan() about line 1740 of of ckuus4.c; the pointer is incremented next
-time thru the loop, resulting in random memory being referenced.  Fixed by
-setting the pointer to NULL instead of "".  ckuus4.c, 12 Jan 2004.
-
-declare \&a[999999999999999] would dump core on some platforms.  atoi()
-or whatever would truncate the dimension to maxint.  When we add 1 to the
-result, we get a negative number, which is used as an index, loop test, etc.
-Fixed both dodcl() and dclarray() to check for (n+1 < 0).  ckuus[r5].c,
-12 Jan 2004.
-
-Unix zchki() would fail on /dev/tty, which is unreasonable.  This prevented
-FOPEN /READ from reading from the terminal.  zchki() already allowed for
-/dev/null, so I added /dev/tty to the list of specials.  Ditto for FOPEN
-/WRITE and zchko().  ckufio.c 13 Jan 2004.
-
-Added untabify() routine to ckclib.[ch], 13 Jan 2004.
-Added FREAD /TRIM and /UNTABIFY.  ckuus[27].c, 13 Jan 2004.
-Added \funtabify().  ckuusr.h, ckuus[24].c, 13 Jan 2004.
-
-Dat Nguyen noticed that (setq u 'p') followed by (u) dumped core.  This was
-caused by an over-clever optimization that skipped mallocs for short
-literals, but then went on later to try to free one that hadn't been
-malloc'd.  Fixed in dosexp(): ckuus3.c, 14 Jan 2004.
-
-Catch another copyright date.  ckuus5.c, 14 Jan 2004.
-
-Fixed SWITCH to work even when SET COMMAND DOUBLEQUOTE OFF (from Mark
-Sapiro).  ckuus5.c, 15 Jan 2004.
-
-Changed version to 8.0.211 so scripts can test for recently added features.
-ckcmai.c, 15 Jan 2004.
-
-Fixed a glitch in K95 "help set port".  ckuus2.c, 20 Jan 2004.
-
-Fix from Jeff: Connections to a TLS-aware protocol which require a reconnect
-upon certificate verification failure could not reconnect if the connection
-was initiated from the command line or via a URL.  ckctel.c ckcmai.c
-ckuusr.c ckuus7.c ckuusy.c, 20 Jan 2004.
-
-From Alex Lewin: makefile target and #ifdef for Mac OS X 10.3 (Panther):
-makefile, ckcnet.c, 7 Feb 2004.
-
-Added KFLAGS to sco32v507 targets to make PTY and SSH commands work.  The
-same flags could probably also be added to earlier OSR5 targets but they
-have not been tested there.  makefile, 7 Feb 2004.
-
-Checked a complaint that "LOCAL &a" did not make array \&a[] local.  Indeed
-it did not, and can not.  You have to use the full syntax in the LOCAL
-command, "LOCAL \&a[]", or else it doesn't know it's not a macro named &a.
-7 Feb 2004.
-
-Fixed some confusion in creating IKSD database file and temp-file names.
-I was calling zfnqfp() without remembering that the path member of the
-returned struct included the filename, so to get just the directory name,
-I needed to strip the filename from the right.  ckuusy.c, 2 Mar 2004.
-
-New ckuath.c, ck_ssl.c from Jeff.  2 Mar 2004.
-
-Updated Jeff's affiliation in VERSION command text.  ckuusr.c, 2 Mar 2004.
-
-Designation changed from Dev.00 to Beta.01.  ckcmai.c, 2 Mar 2004.
-
-Fixed zrename() syslogging -- it had success and failure reversed.
-Beta.02: ckufio.c, 4 Mar 2004.
-
-Problem: when accessing IKSD via a kermit:// or iksd:// URL, and a user ID
-is given but no password, doxarg() set the password to "" instead of leaving
-it NULL, but all the tests in dourl() are for NULL.  Fixed in doxarg():
-ckuusy.c, 5 Mar 2004.
-
-The logic in dourl() about which macro to construct (login and connect,
-login and get directory listing, or login and fetch a file) was a bit off,
-so all three cases were not handled.  ckcmai.c, 5 Mar 2004.
-
-Trial Beta builds:
- . HP-UX B.11.11 PA-RISC
- . HP-UX B.11.23 IA64
- . Tru64 4.0G Alpha
- . Tru64 5.1B Alpha
- . Debian 3.0 i386
- . Red Hat ES 2.1 i386
- . Slackware 9.1 i386
- . VMS 7.3-1 Alpha + UCX 5.3
- . VMS 7.3-1 Alpha no TCP/IP
- . VMS 7.3 Alpha MultiNet 4.3 A-X
- . SCO UnixWare 7.1.4 i386
- . SCO OSR5.0.7 i386
- . Solaris 9 Sparc
-
-Fixed compiler warning in doxarg() caused by typo (NULL instead of NUL) in
-the 5 March doxarg() edit.  ckuusy.c, 9 Mar 2004.
-
-IKSD (kermit://) command-line URLs did not work right if the client had
-already preauthenticated with Kerberos or somesuch because they tried to log
-in again with REMOTE LOGIN.  The macros constructed in doxarg() needed to
-check \v(authstate) before attempting REMOTE LOGIN.  ckcmai.c, 10 Mar 2004.
-
-Added ckuker.nr to x.sh (ckdaily upload) and updated ckuker.nr with current
-version number and dates.  10 Mar 2004.
-
-Replaced hardwired references to /usr/local in makefile with $(prefix)
-(which defaults to /usr/local, but can be overridden on the command line),
-suggested by Nelson Beebe for use with Configure.  10 Mar 2004.
-
-From Nelson Beebe: In the Kermit makefile in the install target commands,
-line 981 reads:
-
-        cp $(BINARY) $(DESTDIR)$(BINDIR)/kermit || exit 1;\
-
-Could you please add this line before it:
-
-        rm -f $(DESTDIR)$(BINDIR)/kermit;\
-
-Some sites (mine included) keep multiple versions of software around,
-with hard links between $(prefix)/progname and $(prefix)/progname-x.y.z.
-Failure to remove the $(prefix)/progname at "make install" time then
-replaces the old $(prefix)/progname-x.y.z with the new one, destroying
-an old version that the site wanted to be preserved.  makefile, 10 Mar 2004.
-
-Minor syntax and typo fixes (mostly prototypes): ckcdeb.h, ckcfns.c,
-ckclib.c, ckufio.c, ckuusr.h, ckuusx.c, 10 Mar 2004.  (I still have a few
-more to do.)
-
-Added CC=$(CC) CC2=$(CC2) to many (but not all) makefile targets that
-reference other makefile targets.  On some platforms (notably AIX, Solaris,
-SunOS) there are specific targets for different compilers, so I skipped
-those.  makefile, 10 Mar 2004.
-
-Added error checking to kermit:// URL macros, so they don't plow ahead
-after the connection is closed.  ckcmai.c, 11 Mar 2004.
-
-Added FreeBSD 4.9 and 5.1 targets (only the herald is affected).
-makefile, ckuver.h, 11 Mar 2004.
-
-Added "LIBS=-lcrypt" to bsd44 targets since nowadays crypt is almost always
-unbundled from libc.  Also added explanatory notes.  makefile, 11 Mar 2004.
-
-Changed MANDIR to default to $(manroot)/man/man1, and manroot to default
-to $(prefix).  More adding of CC=$(CC) clauses: {Free,Net,Open}BSD, 4.4BSD.
-makefile, 11 Mar 2004.
-
-Miscellaneous cleanups: ckuusx.c, ckcnet.c, ckufio.c, 11 Mar 2004.
-
-Corrected the check in the linux target to see if /usr/include/crypt.h
-exists, and if so to define HAVE_CRYPT_H, which is used in ckcdeb.h to
-#include <crypt.h> to get the prototype for crypt() and prevent bogus
-conversions on its return type on 64-bit platforms (the previous test wasn't
-quite right and the resulting symbol wasn't spelled right).  makefile,
-12 Mar 2004.
-
-From Jeff, 14 Mar 2004:
- . Initialize localuidbuf[] in tn_snenv(): ckctel.c.
- . Remove remote-mode checks in hupok() for K95G only (why?): ckuus3.c.
- . Add help text for new K95-only TYPE /GUI switches: ckuus2.c.
- . TYPE /GUI parsing, ...: ckuusr.c.
- . TYPE /GUI action, dotype(): ckuus6.c
- . Change Jeff's affiliation: most modules.
-
-20 Mar 2004: Looked into adding long file support, i.e. handling files more
-than 2GB (or 4GB) long.  Discovered very quickly this would be a major
-project.  Each platform has a different API, or environment, or transition
-plan, or whatever -- a nightmare to handle in portable code.  At the very
-least we'll need to convert a lot of Kermit variables from long or unsigned
-long to some new Kermit type, which in turn is #defined or typedef'd
-appropriately for each platform (to off_t or size_t or whatever).  Then we
-have to worry about the details of open() vs fopen(); printf() formats (%lld
-vs %Ld vs %"PRId64"...), platforms like HP-UX where you might have to use
-different APIs for different file systems on the same computer, etc.  We'll
-need to confront this soon, but let's get a good stable 8.0.211 release out
-first!  Meanwhile, for future reference, here are a few articles:
-
-General: http://freshmeat.net/articles/view/709/
-Linux:   http://www.ece.utexas.edu/~luo/linux_lfs.html
-HP-UX:   http://devrsrc1.external.hp.com/STK/partner/lg_files.pdf
-Solaris: http://wwws.sun.com/software/whitepapers/wp-largefiles/largefiles.pdf
-
-Looked into FTP timeouts.  It appears I can just call empty() (which is
-nothing more than a front end for select()) with the desired timeout before
-any kind of network read.  If it returns <= 0, we have a timeout.  This is
-not quite the same as using alarm() / signal() around a recv() (which could
-get stuck) but alarm() / signal() are not not used in the FTP module and are
-not naturally portable to Windows, but select() is already in use in the FTP
-module for both Unix and Windows.  This form of timeout could be used
-portably for both command response and data reads.  What about writes to the
-command or data socket?  They can get stuck for hours and hours without
-returning too, but the select() approach won't help here -- we need the
-actual send() or recv() to time out, or be wrapped in an alarm()/signal()
-kind of mechanism.  But if we can do that for sends, we can also do it for
-receives.  Better check with Jeff before I start programming anything.
-20 Mar 2004.
-
-Later: Decided to postpone the above two projects (ditto IPv6) until after
-8.0.211 is released because both will have major impacts on portability.
-Grumble: all i/o APIs should have been designed from the beginning with a
-timeout parameter.  To this day, hardly any have this feature.
-
-3-4 Apr 2004: More 8.0.211 Beta.02+ test builds:
-
- . FreeBSD 3.3
- . FreeBSD 4.4
- . Linux Debian 2.1
- . Linux RH 6.1
- . Linux RH 7.1
- . Linux RH 7.2
- . Linux RH 9 (with 84 different combinations of feature selection)
- . Linux SuSE 6.4
- . Linux SuSE 7.0
- . NetBSD 1.4.1
- . NetBSD 1.5.2
- . OpenBSD 2.5
- . OpenBSD 3.0
- . QNX 4.25
- . SCO UnixWare 2.1.3
- . SCO UnixWare 7.1.4
- . SCO OpenServer 5.0.7
- . SCO XENIX 2.3.4 (no TCP)
-
-Changes needed: None.
-
-Problem: SCO XENIX 2.3.4 network build failed in the FTP module with
-header-file syntax and conflicting-definitions trouble.  I'm not going to
-try to fix it; 8.0.209 built OK with FTP, so we'll just keep that one
-available.
-
-Got access to VMS 8.1 on IA64.  Building the nonet version of C-Kermit
-required minor modifications to ckvvms.h, ckv[ft]io.c, and ckvcon.c, to
-account for a third architecture.  Also to SHOW FEATURES in ckuus5.c.  Once
-that was done, the UCX 5.5 version built OK too.  Starts OK, makes Telnet
-connection OK, sends files.  Has some obvious glitches though -- "stat"
-after a file transfer reports 0 elapsed time (in fact it was 00:09:48) and
-1219174400 cps (when in fact it was 10364).  This doesn't happen on the
-Alpha.  Btw, the IA64 binary is twice as big as the Alpha one.  Changed
-to Beta.03.  5 Apr 2004.
-
-Fixed the ckdaily script to include the makefile and man page in the Zip
-file (they were not included because the Zip file was intended mainly for
-VMS users, but some Unix users prefer Zip to tar.gz).  6 Apr 2004.
-
-Traced problems in VMS/IA64 statistics report to rftimer()/gftimer() in
-ckvtio.c, which use sys$ and lib$ calls to figure elapsed time.  These work
-on VAX and Alpha but not IA64.  Sent a report to the chief engineer of the
-IA64 VMS port; he says it's probably a bug in VMS 8.1 (which is not a real
-release); he'll make sure it's fixed in 8.2.  As an experiment, tried
-swapping in the Unix versions of these routines (which call gettimeofday()
-etc).  They seem work just fine (it hung a couple times but I think that's
-because the underlying system hung too; trying it later on a new connection,
-it was fine; however I noticed a BIG discrepancy in throughput between
-sending and receiving).  Moved definitions for VMS64BIT and VMSI64 to
-ckcdeb.h so all modules can use them and added them to the SHOW FEATURES
-display.  Added VMSV80 definition to build procedure.  Beta.03+.  ckcdeb.h,
-ckcuus5.c, ckcvvms.h, ckvtio.c, ckvker.com, 6 Apr 2004.
-
-While doing the build-all, I noticed the VMS version did not build with
-Multinet or older UCX versions, always with the same errors -- undeclared
-variables, undefined symbols, all TCP/IP related.  This didn't happen a
-couple weeks ago...  Somehow the order of #includes was messed up --
-ckuusr.h depended on symbols that are defined in ckcnet.h, but ckcnet.h
-was being included after ckuusr.h...  this was compounded by two missing
-commas in ckvker.com.  11 Apr 2004.
-
-Removed Beta designation, released as 8.0.211, 10 Apr 2004.
-
----8.0.211---
-
-I had somehow lost the edit to ckutio.c that changed the UUCP lockfile for
-Mac OS X from /var/spool/uucp to /var/spool/lock.  So I slipped it in and
-re-uploaded version 8.0.211.  You can tell the difference because SHOW
-VERSIONS has a 17 Apr 2004 for the Communications I/O module.  Also the 10.3
-executable now has a designer banner: "Mac OS X 10.3".  makefile, ckuver.h,
-ckutio.c, ckuus[45].c, 17 Apr 2004.
-
-***********************
diff --git a/ckc299.txt b/ckc299.txt
new file mode 100644 (file)
index 0000000..fc7c6a9
--- /dev/null
@@ -0,0 +1,7696 @@
+C-KERMIT CHANGE LOG (Changes since 8.0.207 / K95 2.1.3 January 2003)
+
+  Chronological order.
+  Go to the bottom to find the newest edits.
+
+  F. da Cruz, The Kermit Project, Columbia University, NYC.
+
+FTP USER, FTP ACCOUNT, plus the various prompts and switches for FTP username,
+password, and account all neglected to strip quotes, and in most cases quotes
+are necessary to specify a username that contains spaces.  ckcftp.c,
+15 Jan 2003.
+
+FTP MPUT f1 f2 f3... gets a parse error if any of the fn's do not match an
+existing file.  This is bad for scripts.  In doftpput(), cmfdb() looks for
+keywords (switches) or CMIFI.  When it hits CMIFI, it exits from the initial
+parse loop and then does additional cmifi()s in a loop until done.  The most
+obvious fix is to parse each field with cmfdb(CMIFI,CMFLD), i.e. fall back to
+CMFLD if CMIFI doesn't match anything.  Then if CMFLD was used, we don't add
+the filespec to the list.  This is a rather big change but it seems to work.
+No error messages or failures happen for non-matching fields, but an error
+message is printed (and the MPUT command fails) if none of the fields match
+any files.  This fix got in too late for 2.1.3; workaround: use C-Shell
+like wildcard list (ftp mput "{*.abc,foo.*}").  ckcftp.c, 16 Jan 2003.
+
+GREP did not pass its pattern through the expander, thus variables could
+not be used for patterns.  This must have been an oversight -- I can't find
+anything in my notes about it.  Fixed in dogrep(): ckuus6.c, 24 Jan 2003.
+
+New makefile target for HP-UX 11.xx with OpenSSL from Tapani Tarvainen.
+makefile, 31 Jan 2003.
+
+From Jeff:
+ . Avoid core dump when dereferencing tnc_get_signature(): ckuus4.c.
+ . Bump version numbers to 8.0.208, 2.1.4: ckcmai.c.
+
+Added /NOLOGIN to FTP [OPEN].  ckcftp.c, 10 Feb 2003.
+
+Don't dump core if FTP DEBUG is ON and FTP OPEN does not include a service.
+openftp(): ckcftp.c, 10 Feb 2003.
+
+HELP PATTERN text incorrectly identified commands and functions with
+floating and anchored patterns.  The corrected lists are:
+Floating: GREP, TYPE /MATCH:, /EXCEPT: patterns, \farraylook(),
+Anchored: IF MATCH, file-matching wildcards, \fsearch(), \frsearch()
+ckuus2.c, 10 Feb 2003.     
+
+INPUT n \fpattern(xxx) did not work for case-independent comparisons.
+Fixed in doinput(): ckuus4.c, 10 Feb 2003.
+
+It seems \fpattern() didn't work with MINPUT at all.  There was no code to
+handle \fpattern() in the MINPUT parse loop, so it never worked.  The code
+had to be totally rewritten to use cmfld() in a loop, rather than cmtxt()
+and then cksplit().  Furthermore, whenever any of the fields was an
+\fjoin(), this had to be split.  ckuusr.c, 10 Feb 2003.
+
+Macro replacement via \m() and \fdefinition() does not work as advertised
+(i.e. case sensitively) for associative array elements; e.g. \m(xxx<abc>) is
+treated the same as \m(xxx<ABC>), contrary to section 7.10.10 of the C-Kermit
+7.0 update notes, and to the fact that the two really do exist separately.
+Fixed by adding a static function isaarray(s) which succeeds if s is an
+associative array reference and fails otherwise, and then having \m()
+and \fdef() call mxxlook() (case-sensitive lookup) if isaarray(), otherwise
+(as before) mxlook()).  ckuus4.c, 11 Feb 2003.
+
+Fixed FTP OPEN to allow the /USER switch to override SET FTP AUTOLOGIN OFF,
+just as /NOLOGIN overrides SET FTP AUTOLOGIN ON.  ckcftp.c, 11 Feb 2003.
+
+In K95, "set key \1234 \27H" (any SET KEY command in which the first char of
+the definition was backslash, and the ONLY character after the backslash
+quantity was an uppercase letter, that letter would be lowercased).  Diagnosis:
+xlookup() poking its argument (see notes from July 2000).  Jeff sent a fix.
+ckucmd.c, 15 Feb 2003.
+
+Ran my S-Expression torture test to make sure Sexps still worked.  They do,
+except the bitwise & and | operators were broken, e.g. (& 7 2) and (| 1 2 4)
+get "Invalid operand" errors.  Jeff's code had added an early failure return
+from the lookup loop when when a single-byte keyword matched a keyword that
+started with the same byte but was more than one byte long.  So "&" would hit
+"&&" and fail instead of continuing its search (xlookup tables aren't sorted
+so there can be no early return).  Fixed in xlookup(): ckucmd.c, 16 Feb 2003.
+
+Got rid of "krbmit" target from makefile.  It's still there, but we don't
+use it any more.  All secure targets now use "xermit", and produce a binary
+called wermit, just like the regular ones do (except the old ckucon.c ones).
+Non-secure targets, since they don't define any of the security symbols,
+wind up compiling and linking to (mostly) empty security modules.  makefile,
+15 Feb 2003.
+
+Added \fcvtdate(xxx,3) to format its result in MDTM format (yyyymmddhhmmss,
+all numeric, no spaces or punctuation).  Of course these numeric strings
+are too big to be 32-bit numbers and are useless for arithmetic, but they're
+useful for lexical comparison, etc.  ckuus[24].c, 16 Feb 2003.
+
+The following FTP commands did not set FAILURE when they failed: RMDIR,
+CD, CDUP, Fixed in the corresponding doftpblah() routines.  ckcftp.c,
+16 Feb 2003.
+
+RENAME would sometimes not print an error message when it failed, e.g. in K95
+when the destination file already existed.  ckuus6.c, 17 Feb 2003.
+
+Fixed COPY error messages, which did not come out in standard format when
+/LIST was not included.  ckuus6.c, 17 Feb 2003.
+
+Fixed #ifdefs in ck_crp.c to allow nonsecure builds on old platforms like
+System V/68 R3.  19 Feb 2003.
+
+Similar treatment for ck_ssl.c.  20 Feb 2003.
+
+From Jeff, 21 Feb 2003:
+ . AIX53 and AIX52 symbols for ckcdeb.h, makefile.
+ . New gcc targets for various AIX 4.x/5.x versions: makefile.
+ . Copyright date updates: ck_crp.c, ck_ssl.c.
+ . ENABLE/DISABLE QUERY broken because keyword table out of order: ckuusr.c.
+ . Fixed the use of HTTP proxies for HTTP [RE]OPEN for Unix: ckcnet.c.
+
+Also for K95 only: Allow file transfer when K95 is invoked on the remote end
+of a connection to a Pragma Systems Terminal Server connection; automatically
+SET EXIT HANGUP OFF when invoked with open port handle ("k95 -l nnnn").
+
+"cd a*" failed even when "a*" matched only one directory.  Fixed in cmifi():
+ckucmd.c, 21 Feb 2003.
+
+In the Unix version, replace "extern int errno;" with "#include <errno.h>"
+if __GLIBC__ is defined, since glibc now defines a thread-specific errno.
+ckcdeb.h, 26 Feb 2003.
+
+Added #ifdefs to skip compilation of ckuath.c in nonsecure builds.  Tested
+by building both secure and regular versions in Linux.  ckuath.c, 26 Feb 2003.
+
+Ran the build-in-84-different-configurations script on Linux to make sure it
+still builds with all different combinations of feature selection options.
+All OK.  26 Feb 2003.
+
+Built on VMS.  Needed to add a prototype for mxxlook*() to ckuusr.h; built
+OK otherwise.  26 Feb 2003.
+
+From Jeff: More #ifdef shuffling for nonsecure builds: ckuath.c, ck_ssl.c,
+27 Feb 2003.
+
+Added code to ensure \v(download) ends in a directory separator in Unix,
+Windows, and OS/2.  ckuus7.c, 27 Feb 2003.
+
+Added code to K95 zfnqfp() to tack on directory separator when returning
+a directory name.  ckofio.c, 27 Feb 2003.
+
+Somehow an old copy of ckuath.c popped to replace the new one.  Put the new
+one back.  28 Feb 2003.
+
+From Jeff: Fix typo in my K95 zfnqfp() code from yesterday; fixes for handling
+UNCs uniformly, no matter which way their slashes are leaning.  ckofio.c,
+28 Feb 2003.
+
+At Jeff Mezei's suggestion, separate text and binary mode open sequences
+for VMS session log.  ckvfio.c, 28 Feb 2003.
+
+Added freebsd48 target for FreeBSD 4.8.  makefile, 1 Mar 2003.
+
+Changed Mac OS X entries to include -DUSE_STRERROR.  makefile, 2 Mar 2003.
+
+Fixed GETOK /GUI to evaluate its text argument.  ckuus6.c, 3 Mar 2003.
+
+Jeff fixed the K95 Dialer QUICK dialog to (a) allow templates, and (b) have
+a Save-As option.  3 Mar 2003.
+
+Jeff fixed a problem with the Xmodem-CRC checksum being crunched whenever
+there was a retransmission.  7 Mar 2003.
+
+Added target/banner for Tru64 5.1B.  makefile, ckuver.h, 5 Mar 2003.
+
+In Unix, the zcopy() routine (used by the COPY command) reset the user's umask
+to 0 for the remainder of the Kermit process lifetime.  The bug was in
+ckufio.c 8.0.194, 24 Oct 2002, and is fixed in ckufio.c 8.0.195, 6 Mar 2003.
+Of course this happened after building 155 C-Kermit 8.0.208 binaries.  (But
+before officially releasing 8.0.208.)
+
+In the VMS version, changed:
+
+        while ((n--) && xx_inc(2) > -1) ;
+to:
+        while ((n--) && xx_inc(2) >= 0) ;
+
+to suppress the "...is being compared with a relational operator to a constant
+whose value is not greater than zero" warning.  ckvtio.c, 7 Mar 2002.
+
+Added a debug call to dologend in hopes of catching overzealous Locus
+switching, which seems to happen only in K95.  ckuus3.c, 7 Mar 2002.
+
+Rebuilt binaries for some of the more current Unix releases: AIX 4.3.3-5.1,
+Solaris 7-9 , Red Hat 7.0-8.0, Slackware 8.1, Freebsd 4.7-4.8, NetBSD 1.6,
+OpenBSD 3.2, Unixware 7.1.3, Open Unix 8, OSR5.0.6a, etc.  A Unix binary with
+COPY umask fix shows a 6 Mar 2003 date for "UNIX File support" in SHOW
+VERSIONS; a binary without the fix shows 24 Oct 2002.
+
+C-Kermit 8.0.208 dated 14 March 2003 released on 10 March 2003.
+
+---8.0.208---
+
+From Jeff 13 Mar 2003:
+ . Updated SSL module allows importation of tickets from host.
+ . freebsd50+openssl target: makefile.
+ . FTP PUT /PERMISSIONS error message for K95: ckcftp.c.
+Fixed MINPUT to strip quotes or braces from around targets (this was broken
+on Feb 10th).  Thanks to Jason Heskett for discovering and reporting this
+(killer) bug.  ckuusr.c, 14 Mar 2003.
+
+Changed version number to 209 Dev.00.  ckcmai.c, 14 Mar 2003.
+
+While debugging the alphapage script, I found that the command "minput 8 \6\13
+\21\13 \13\27\4\13 \30\13" gets "?Not confirmed" in 8.0.208 and 8.0.209, but
+not in 206 and earlier.  This problem too was introduced on Feb 10th by
+changing MINPUT parsing from cmtxt() followed by cksplit() to cmfld() in a
+loop.  cmfld() uses setatm() to return its result and of course setatm()
+breaks on \13.  Changing setatm() not to do this would break everything else.
+But cmfld() has no arguments that let us tell it to do anything different in
+this case.  Changing the API would be a disaster.  The only solution is to add
+an "MINPUT ACTIVE" (minputactive) global variable that tells cmfld() to tell
+setatm() not to break on CR.  Now MINPUT with braced targets containing CR
+and/or LF works in 209, 206, and 201 (but not 208).  ckucmd.c, ckuusr.c,
+ckuus5.c, 15 Mar 2003.
+
+MINPUT n \fjoin(&a) works OK if all the members of \&a[] are text strings, but
+if they are strings of control chars (as above), they don't get separated by
+the spaces.  For example in:
+
+  dcl \&a[] = "\4\5" "\6\7" xxx
+  minput 10 \fjoin(&a)
+
+MINPUT gets two targets: "aaa" and "\4\5 \6\7 xxx".  The bug was in the
+cksplit() call in the \fjoin() case of MINPUT: it needed to specify an
+include set consisting of all the control characters except NUL.  ckuusr.c,
+16 Mar 2003.
+
+But there's still a problem:
+
+  dcl \&a[] = "\4\5\13\10" "\6\7" "xxx"
+
+creates an array whose first member is "^D^E (one doublequote included).  But
+if braces are used instead, there's no problem.  Same deal as MINPUT: cmfld()
+breaks on CR or LF, thus the end quote is lost.  If I set minputactive for
+DECLARE initializers too, that fixes it.  Is there any reason not to do this?
+Can't think of any (famous last words)...  ckuusr.c, 16 Mar 2003.
+
+Since it has multiple applications, changed the flag's name from minputactive
+to keepallchars.  ckucmd.c, ckuus[r5].c, 16 Mar 2003.
+
+\v(exedir) wasn't being set correctly (it included the program name as well
+as the directory).  Fixed in getexedir(): ckuus4.c, 16 Mar 2003.
+
+SET CARRIER-WATCH <Esc> "auto matic" (spurious space in supplied keyword).
+Cosmetic only; it still worked.  Fixed in setdcd(): ckuus3.c, 16 Mar 2003.
+
+"directory a b c" listed too many files -- all files whose names END WITH a,
+b, or c, rather than the files whose names WERE a, b, or c.  Diagnosis: The
+filespec is changed into a pattern: {a,b,c}, which is the correct form.  It is
+passed to nzxpand(), which goes through the directory getting filenames and
+sending each one to ckmatch() with the given pattern.  ckmatch() receives the
+correct pattern but then prepends a "*" -- that's not right.  It's not just
+in filename matching either.  The following succeeds when it shouldn't:
+
+  if match xxxxc {{a,b,c}} <command>
+
+Changing ckmatch() to not prepend the "*" to each segment fixes the command
+above but breaks lots of others.  Running through the "match" torture-test
+script shows the problem occurs only when the {a,b,c} list is the entire
+pattern, and not embedded within a larger pattern.  Testing for this case
+fixed the problem.  ckmatch(): ckclib.c, 16 Mar 2003.
+
+Fixed FTP MODTIME to not print anything if QUIET ON.  ckcftp.c, 16 Mar 2003.
+
+Picked up a new ckuath.c from Jeff, not sure what the changes are. 16 Mar 2003.
+
+Did a few regular and secure builds to make sure I didn't wreck anything.
+
+Changed version number to 209 (final).  ckcmai.c, 16 Mar 2003.
+
+Jason Heskett found another bug: if you define a macro FOO inside the
+definition of another macro BAR, and FOO's definition includes an odd number
+of doublequotes (such as 1), FOO's definition absorbs the rest of BAR's
+definition.  Example:
+
+  def TEST {
+    .foo = {X"}
+    sho mac foo
+  }
+  do test
+  sho mac foo
+
+Results in:
+
+  foo = {X"}, sho mac foo
+
+Diagnosis: the TEST definition becomes:
+
+  def TEST .foo = {X"}, sho mac foo
+
+and the macro reader is erroneously treating the doublequote as an open
+quote, and then automatically closes the quote at the end of the definition.
+The error is that a doublequote should be significant only at the beginning of
+a field.  But the macro reader isn't a command parser; it doesn't know what
+a field is -- it's just looking for commas and skipping over quoted ones.
+First we have to fix an oversight: SET COMMAND DOUBLEQUOTING OFF should have
+worked here, but it wasn't tested in this case.  Fixed in getncm(): ckuus5.c,
+17 Mar 2003.
+
+There are only certain cases where it makes sense to treat doublequotes as
+signicant:
+
+ . An open quote must be at the beginning or preceded by a space.
+ . A close quote is only at the end or else followed by a space.
+
+This too was fixed in getncm(): ckuus5.c, 17 Mar 2003.
+
+A fix from Jeff SSL/TLS FTP data decoding.  ckcftp.c, 18 Mar 2003.
+
+Tried building C-Kermit on a Cray Y-MP with UNICOS 9.0.  "int suspend",
+declared in ckcmai.c and used in many modules, conflicts with:
+
+  unistd.h:extern int suspend __((int _Category, int _Id));
+
+The "=Dsuspend=xsuspend" trick doesn't work for this; there is no way around
+the conflict other than to rename the variable: ckcmai.c, ckutio.c,
+ckuus[35xy].c.  26 Mar 2003.  VMS and K95 not affected.
+
+OK that gets us past ckcmai.c...  Then in ckutio.c I had to add a new #ifdef
+around the LFDEVNO setting, because the Cray didn't have mkdev.h.  Could not
+find a Cray-specific manifest symbol, so I made a new makefile target (cray9)
+that sets this symbol.  Having done this I have no idea what kind of lockfile
+would be created, but I also doubt if anybody dials out from a Cray.  The
+binary should run a C90, J90, or Y-MP.  makefile, 26 Mar 2003.
+
+Added a target for SCO OSR5.0.7.  makefile, ckuver.h, 30 Mar 2003.
+
+Changed since 208:
+makefile ckuver.h ckcmai.c ckclib.c ckcftp.c ckucmd.c ckuus*.c ckutio.c.
+
+---8.0.209---
+
+From Mark Sapiro, a fix for the March 17th doubleqote fix, getncm(): ckuus5.c,
+4 Apr 2003.
+
+From Jeff, 29 Apr 2003:
+ . Corrected target for HP-UX 11.00 + OpenSSL: makefile, 
+ . Do not allow WILL AUTH before WONT START_TLS: ckctel.h ckctel.c
+ . Add hooks for SFTP and SET/SHOW SFTP: ckcdeb.h ckuusr.h ckuusr.c ckuus3.c
+ . Add SKERMIT ckuusr.h ckuusr.c
+ . Add ADM-5 terminal emulation: ckuus7.c, ckuus5.c
+ . Uncomment and update HELP SET SSH V2 AUTO-REKEY: ckuus2.c
+ . Enable IF TERMINAL-MACRO and IF STARTED-FROM-DIALER for C-Kermit: ckuus6.c
+ . Fix conflicting NOSCROLL keyword definition: ckuusr.h
+ . Set ttname when I_AM_SSH: ckuusy.c
+ . Add extended arg parsing for SSH, Rlogin, Telnet: ckuusy.c, ckuus4.c
+ . Security updates: ckuath.c, ck_ssl.c
+ . Change K95 version number to 2.2.0: ckcmai.c
+ . Save K95 term i/o state before executing keyboard macro: ckuus4.c
+ . Add tests for SSH Subsystem active during INPUT/OUTPUT/CONNECT: ckuus[45].c
+ . Enable K95 SET SSH V2 AUTO-REKEY: ckuus3.c
+
+SFTP and SET SFTP subcommands are implemented up to the case statements.
+
+Files of mine that Jeff hadn't picked up:
+  ckuver.h ckcftp.c ckutio.c ckuusx.c (just minor changes for last build-all)
+
+On 4 Jan 2003, SET RECEIVE MOVE-TO was changed to convert is argument to an
+absolute path, which made it impossible to specify a relative path, then
+move to different directories and have it apply relatively to each directory.
+Changed this as follows:
+
+ . Parser uses cmtxt() rather than cmdir() so it won't fail at parse time.
+ . If path is absolute, we fail at parse time if directory doesn't exist.
+ . In reof() we run the the path through xxstring (again, in case deferred
+   evaluation of variables is desired) and then, if not null, use it.
+ . If the directory doesn't exist, rename() fails and reof() returns -4,
+   resulting in a protocol error (this is not a change).  We do NOT create
+   the directory on the fly. 
+
+I also fixed SET SEND/RECEIVE RENAME-TO to parse with cmtxt() rather than
+cmdir(), since it's parsing a text template, not a directory name, e.g.
+"set receive rename-to file-\v(time)-v(date)-\v(pid)".  This was totally
+broken, since when I don't know.  We don't call xxstring() in this parse, so
+evaluation is always deferred -- I'd better not change this.  ckuus7.c,
+ckcfns.c, 1 May 2003.
+
+From Jeff, Sat May  3 14:15:23 2003:
+ . Pick up the right isascii definition for K95: ckctel.c
+ . malloc...  ckuath.c (new safe malloc routines for K95)
+ . Add author listing: ckuus5.c
+ . SSH Heartbeat support (K95 only): ckuus[23].c
+ . Prescan --height and --width to avoid window resizing at startup: ckuusy.c
+ . Add checks for fatal() or doexit() called from sysinit(): ckuusx.c
+ . Move some K95-specific definitions to ckoker.h: ckcdeb.h
+ . Add support for ON_CD macro in zchdir(): ckufio.c
+ . Add a command to let FTP client authenticate with SSLv2: ckcftp.c
+ . Fix parsing of FTP file facts like "UNIX.mode": ckcftp.c
+
+ON_CD will need some explaining (to be done).  It's implemented for Unix,
+VMS, WIndows, and OS/2.
+
+The FTP file facts fix came from first exposure to the new OpenBSD FTP
+server: ftp://ftp7.usa.openbsd.org/pub/os/OpenBSD/3.3/i386/
+The period in "UNIX.mode" caused an erroneous word break, adding junk to
+the filename.
+
+About the malloc changes, Jeff says "K95 is not behaving well in low memory
+environments.  I'm not sure that C-Kermit does much better.  The program does
+not crash but it certainly does not behave the way the user expects it to.
+I'm beginning to think that any malloc() error should be treated as fatal."
+
+Not visible in these changes because it's in K95-specific modules: Jeff made
+SET ATTRIBUTES OFF and SET ATTRIBUTES DATE OFF apply to XYZMODEM transfers.
+
+From Jeff, 11 May 2003:
+ . Add support for SSH Keepalive to relevant SET command (K95): ckuus3.c
+ . Reduce max overlapped i/o requests from 30 to 7 (K95): ckuus7.c
+ . Don't call sysinit() in fatal(): ckuusx.c.
+ . Some new conditionalizations for SSL module: ck_ssl.c
+
+The doublequote-parsing fixes from March and April broke the SWITCH statement,
+which is implemented by internally defining, then executing, a macro.  If I
+drop back to the old dumb handling of doublequotes, everything is fixed except
+the problem of March 17th.  But can we really expect getncm() to pre-guess
+what the parser is going to do?  getncm()'s only job is to find command
+boundaries, which are represented by commas.  Commas, however, is needed IN
+commands too.  We take a comma literally if it is quoted with \, or is inside
+a matched pair of braces, parens, or doublequotes.  It is not unreasonable to
+require a doublequote in a macro definition to be prefixed by \ when it is to
+be taken literally.  The proper response to Jason Heskett's complaint of March
+17th should have been to leave the code alone and recommand an appropriate
+form of quoting:
+
+  def TEST {
+      .foo = {X\"}
+      sho mac foo
+  }
+
+And this is what I have done.  Another reason for sticking with the old method
+is that it's explainable.  The "improved" method, even if it worked, would be
+be impossible to explain.  Btw, in testing this I noticed that the switch-test
+script made 8.0.201 dump core.  Today's version is fine.  The problem with
+quoted strings inside of IF {...} clauses and FOR and WHILE loops is fixed
+too.  Perhaps "unbroken" would be a better word.  ckuus5.c, 11 May 2003.
+
+Vace discovered that FTP MGET /EXCEPT:{... (with an unterminated /EXCEPT list)
+could crash Kermit.  Fixed in ckcftp.c, 11 May 2003.
+
+CONTINUE should not affect SUCCESS/FAILURE status.  ckuusr.c, 11 May 2003.
+
+Fixed an oversight that goes back 15 years.  While \{123} is allowed for
+decimal codes, \x{12} and \o{123} were never handled.  ckucmd.c, 11 May 2003.
+
+Added support for Red Hat <baudboy.h> and /usr/sbin/lockdev.  Supposedly this
+allows Kermit to be installed without setuid or setgid bits and still be able
+to lock and use the serial device.  Compiles and starts, but not tested.
+ckcdeb.h, makefile, ckutio.c, ckuus5.c, 16 May 2003.
+
+From Jeff: FTP ASCII send data to host when FTP /SSL was in use was broken.
+ftp_dpl is set to Clear when FTP /SSL is in use.  This was causing the data to
+be written to the socket with send() instead of the OpenSSL routines.
+ckcftp.c, ckuath.c, 21 May 2003.
+
+From Jeff: Stuff for Kerberos 524: ckcdeb.h.  Fixes for FTP; "FTP ASCII send
+data did not properly compute the end of line translations.  On Unix (and
+similar platforms) the end of line was correct for no character sets but
+incorrect when character sets were specified.  On Windows/OS2, the end of line
+was correct when character sets were specified and incorrect when they were
+not.  On MAC, both were broken.  Also, FTP Send Byte counts were incorrect
+when character sets were specified."  ckcftp.c.  17 Jun 2003.
+
+From Jeff: fixes to HTTP /AGENT: and /USER: switch action: ckcnet.c ckuus3.c
+ck_crp.c ckcftp.c ckuus2.c ckuusy.c ckuusr.c ckcnet.h, 21 Jun 2003.
+
+From Jeff: Fix SET DIALER BACKSPACE so it can override a previous SET KEY
+(e.g. from INI file): ckuus7.c.  Some SSL/TLS updates: ck_ssl.c.  HTTP support
+for VMS and other VMS improvements (e.g. a way to not have to hardwire the
+C-Kermit version number into the build script) from Martin Vorlaender:
+ckcnet.h, ckuus[r3].c, ckcdeb.h, ckvtio.c, ckcnet.c, ckvker.com.  Built on
+Solaris (gcc/ansi) and SunOS (cc/k&r).  The new VMS script tests the VMS
+version and includes HTTP support only for VMS 6.2 or later.  2 Jul 2003.
+
+Tried to build on our last VMS system but it seems to be dead.  Looks like a
+head crash (makes really loud noises, boot says DKA0 not recognized) (fooey, I
+just paid good money to renew the VMS license).  Tried building at another
+site with:
+
+  Process Software MultiNet V4.3 Rev A-X,
+  Compaq AlphaServer ES40, OpenVMS AXP V7.3
+  Compaq C V6.4-008 on OpenVMS Alpha V7.3
+
+Had to make a few corrections to ckvker.com.  But still, compilation of
+ckcnet.c bombs, indicating that the SELECT definition somehow got lost
+somewhere since the 209 release (i.e. no SELECT type is defined so it falls
+thru to "SELECT is required for this code").  But I don't see anything in
+ckcdeb.h or ckcnet.[ch] that would explain this.  Not ckvker.com either
+(putting the old one back gives the same result).  OK, I give up, maybe it's
+just that I haven't tried building it on MultiNet recently.  What about UCX?
+Aha, builds fine there except for warnings about mlook, dodo, and parser in
+ckvfio.c (because of ON_CD) -- I suppose I have #include <ckucmd.h>... (done)
+Anyhow it builds OK and the HTTP code is active and almost works (HTTP OPEN
+works; HTTP GET seems to succeed but creates an empty file every time).  Tried
+building under MultiNet at another installation; same bad result.
+
+OK so why won't it build for MultiNet?  Comparing ckcnet.c with the 209
+version, not a single #ifdef or #include is changed.  Tried building with
+p3="NOHTTP" -- builds OK, aha.  Where's the problem?  Not ckcnet.h...
+Not ckcdeb.h...  OK I give up, will revisit this next time I get time to
+do anything with the code.
+
+Later Jeff said "Martin did not implement VMS networking for the HTTP code.
+All he did was activate the #define HTTP which happens to work because his
+connections are using SSL/TLS connections.  http_inc(), http_tol(), etc have
+no support for VMS networking regardless of whether it is UCX or MULTINET.
+The vast majority of HTTP connections are not secured by SSL/TLS.  It makes no
+sense to support HTTP on VMS until someone is willing to either do the work or
+pay have the work done to implement VMS networking in that code base."  So the
+fix is to not enable HTTP for VMS after all.  Removed the CKHTTP definition
+for VMS from ckcdeb.h, 6 Jul 2003.
+
+Fixed ckvfio.c to #include <ckuusr.h> (instead of <ckucmd.h>) to pick up 
+missing prototypes.  6 Jul 2003.
+
+From Arthur Marsh: solaris2xg+openssl+zlib+srp+pam+shadow and the corresponding
+Solaris 7 target.  makefile, 6 Jul 2003.
+
+Remove duplicate #includes for <sys/stat.h>, <errno.h>, and <ctype.h> from
+ckcftp.c.  6 Jul 2003.
+
+Add -DUSE_MEMCPY to Motorola SV/68 targets because of shuffled #includes in 
+ckcftp.c.  8 Jul 2003.
+
+From Jeff: Fix problems mixing SSL and SRP without Kerberos.  Plus a few minor
+#define comment changes and a reshuffling of #defines in ckcdeb.h to allow me
+to build on X86 Windows without Kerberos.  ckcdeb.h, ck_crp.c, ckuath.c,
+10 Jul 2003.
+
+From Jeff: updated ckuat2.h and ckuath.c, 29 Jul 2003.
+
+Mats Peterson noticed that a very small Latin-1 file would be incorrectly
+identified as UCS-2 by scanfile().  Fixed in ckuusx.c, 29 Jul 2003.
+
+Fixed ACCESS macro definition to account for the fact that FIND is now a
+built-in command.  ckermit.ini, 30 Jul 2003.
+
+From Jeff: Fix for typo in urlparse() (svc/hos): ckuusy.c, 18 Aug 2003.
+
+From Jeff: Redhat9 makefile targets (needed for for OpenSSL 0.9.7):
+makefile, 19 Aug 2003.
+
+GREP /NOLIST and /COUNT did too much magic, with some undesirable fallout:
+"GREP /NOLIST /COUNT:x args" printed "file:count" for each file.  "GREP
+/COUNT:x /NOLIST args" did not print "file:count", but neither did it set the
+count variable.  Removed the magic.  Also one of the GREP switches,
+/LINENUMBERS, was out of order.  Fixed in ckuus6.c, 20 Aug 2003.
+
+From Jeff: "Reorganizing code to enable building with different subsets of
+options; a few typos corrected as well."  ckcdeb.h, ckuver.h (for RH9),
+ckcnet.c, ckuus7.c, ckuus3.c: 24 Aug 2003.
+
+Scanfile misidentified a big PDF file as text because the first 800K of it
+*was* text (most other PDF files were correctly tagged as binary).  Fixed
+by adding a check for the PDF signature at the beginning of the file.
+scanfile(): ckuusx.c, 25 Aug 2003.
+
+Ditto for PostScript files, but conservatively.  Signature at beginning of
+file must begin with "%!PS-Ado".  If it's just "%!" (or something nonstandard
+like "%%Creator: Windows PSCRIPT") we do a regular scan.  Also added "*.ps"
+to all binary filename patterns.  ckuusx.c, 4 Sep 2003.
+
+Ditto (but within #ifndef NOPCLSCAN) for PCL (<ESC>E) and PJL (<ESC>%) files,
+but no binpatterns (note: ".PCL" is the extension for TOPS-20 EXEC scripts).
+ckuusx.c, 4 Sep 2003.
+
+Added comments about OpenSSL 0.9.7 to all linux+openssl targets.
+makefile, 4 Sep 2003.
+
+From Jeff: Added - #define ALLOW_KRB_3DES_ENCRYPT.  When this symbol is defined
+at compilation Kermit will allow non-DES session keys to be used during Telnet
+Auth.  These session keys can then be used for Telnet Encrypt.  The reason
+this is not compiled on by default is that the MIT Kerberos Telnet does not
+follow the RFC for constructing keys for ENCRYPT DES when the keys are longer
+than 8 bytes in length.  ckuath.c, ckuus5.c, 4 Sep 2003.
+
+"ftp mget a b c" succeeded if one or more of the files did not exist, even
+with "set ftp error-action proceed".  This is because the server's NLST file
+list does not include any files that don't exist, so the client never even
+tries to get them.  Fortunately, the way the code is structured, this one was
+easy to fix.  ckcftp.c, 14 Sep 2003.
+
+From Jeff: Corrected code in ckcnet.c to ensure that Reverse DNS Lookups are
+not performed if tcp_rdns is OFF.  Fixed ck_krb5_getrealm() to actually return
+the realm of the credentials cache and not the default realm specified in the
+krb5.conf file.  Previously krb5_cc_get_principal() was not being called.
+Fixed ck_krb5_is_tgt_valid() to test the TGT in the current ccache and not the
+TGT constructed from the default realm.  ckcnet.c, ckuath.c, 14 Sep 2003.
+
+Marco Bernardi noticed that IF DIRECTORY could produce a false positive if
+the argument directory had previously been referenced but then removed.  This
+is because of the clever isdir() cache that was added to speed up recursion
+through big directory trees.  Changed IF DIRECTORY to make a second check
+(definitive but more expensive) if isdir() succeeds, and changed the
+directory-deleting routine, ckmkdir(), to flush the directory cache (UNIX
+only -- this also should be done in K95 but it's not critical).  This was
+done by adding a routine, clrdircache() to ckufio.c, which sets prevstat
+to -1 and prevpath[0] to NUL.  ckcfn3.c, ckuus6.c, ckufio.c, 18 Sep 2003.
+
+Marco reported the second fix still didn't work for him (even though it did
+for me).  Rather than try to figure out why, I concluded that the directory
+cache is just not safe: a directory found a second ago might have been deleted
+or renamed not only by Kermit but by some other process.  Why did I add this
+in the first place?  The log says:
+
+  Some debug logs showed that isdir() is often called twice in a row on the
+  same file.  Rather than try to sort out clients, I added a 1-element cache
+  to Unix isdir().  ckufio.c, 24 Apr 2000.
+
+Experimentation with DIR and DIR /RECURSIVE does not show this happening at
+all.  So I #ifdef'd out the directory cache (see #ifdef ISDIRCACHE in ckufio.c;
+ISDIRCACHE is not defined) and backed off the previous changes: ckufio.c,
+ckcfn3.c, ckuus6.c, 28 Sep 2003.
+
+From Jeff: Replace the compile time ALLOW_KRB_3DES_ENCRYPT with a run-time
+command SET TELNET BUG AUTH-KRB5-DES which defaults to ON: ckctel.[ch],
+ckuus[234].c, ck_crp.c, ckuath.c.  4 Oct 2003.
+
+Allow DIAL RETRIES to be any positive number, and catch negative ones.
+Also added code to check for atoi() errors (e.g. truncation).  At least on
+some platforms (e.g. Solaris) atoi() is supposed to set errno, but it
+doesn't.  ckuus3.c, ckucmd.c, 4 Oct 2003.
+
+Added /DEFAULT: to ASK-class commands (ASK, ASKQ, GETOK):
+
+ . For popups: no way to send defaults to popup_readtext() or popup_readpass().
+ . For GUI ASK[Q], pass default to gui_txt_dialog().
+ . For GUI GETOK, convert "yes" "ok" or "no" default to number for uq_ok().
+ . For Text GETOK, add default to cmkey().
+ . For Text ASK[Q], add default to cmtxt().
+ . For GETC, GETKEY, and READ: no changes.
+
+GETOK, ASK, and ASKQ with /TIMEOUT: no longer fail when the timer goes off
+if a /DEFAULT was supplied.  The GUI functions (uq_blah) don't seem to
+support timeouts.  Only the text version has been tested.  ckuus[26].c,
+4 Oct 2003.
+
+From Jeff: add /DEFAULT: for popups.  ckuus6.c. 6 Oct 2003.
+
+Change SET DIAL INTERVAL to be like SET DIAL RETRIES.  ckuus[34].c, 6 Oct 2003.
+
+Added target for HP-UX 10/11 + OpenSSL built with gcc, from Chris Cheney.
+Makefile, 12 Oct 2003.
+
+From Jeff, 6 Nov 2003:
+ . #ifdef adjustments: ckcftp.c, ckcdeb.h
+ . Fix spurious consumption of first byte(s) on Telnet connection: ckctel.c
+ . Another HP PJL test for scanfile: ckuusx.c.
+ . K95: Recognize DG4xx protected fields in DG2xx emulation: ckuus7.c.
+ . Add SSLeay version display to SHOW AUTH command: ckuus7.c
+ . Improved SET MOUSE CLEAR help text: ckuus2.c.
+ . Improved Kverbs help text: ckuus2.c (+ new IBM-3151 Kverbs).
+ . Some changes to ck_ssl.c, ckuath.c.
+
+From PeterE, 10 Nov 2003:
+ . Improved HP-UX 10/11 makefile targets for OpenSSL.
+ . #ifdef fix for OpenSSL on HP-UX: ck_ssl.c.
+
+Another new makefile from PeterE with improved and integrated HP-UX targets.
+12 Nov 2003.
+
+A couple fixes to the solaris9g+krb5+krb4+openssl+shadow+pam+zlib target
+from Jeff.  Added a solaris9g+openssl+shadow+pam+zlib target.  makefile,
+21 Nov 2003.
+
+From Jeff, 30 Nov 2003:
+ . Fix SEND /MOVE-TO: ckuusr.c.
+ . Fix K95 SET TITLE to allow quotes/braces around text: ckuus7.c.
+ . Improved "set term autodownload ?" response: ckuus5.c.
+ . Fix SHOW FEATURES to specify the protocol for encryption: ckuus5.c
+ . Make {SEND, RECEIVE} {MOVE-TO, RENAME-TO} work for XYZMODEM (K95 only).
+
+From Jeff: 7 Jan 2004:
+ . At one point Frank started to add a timer parameter to the
+   uq_txt() function but he only did it for the non-ANSI
+   compilers.  I added it for the ANSI compilers, fixed the
+   prototypes and provided a default value easily changed
+   DEFAULT_UQ_TIMEOUT: ckcker.h, ckuus[36].c, ck_ssl.c, ckcftp.c, ckuath.c.
+ . Fixed SET TERMINAL DEBUG ON (typo in variable name): ckuus7.c.
+ . Fixed BEEP INFORMATION; previously it made no sound, now uses
+   MB_ICONQUESTION.  ckuusx.c.
+
+From Ian Beckwith <ian@nessie.mcc.ac.uk> (Debianization), 7 Jan 2004:
+ . Search dir/ckermit for docs, as well as dir/kermit in cmdini(): ckuus5.c.
+ . New linux+krb5+krb4+openssl+shadow+pam target (kitchen sink minus SRP,
+   which Debian does not distribute): makefile.
+ ? Mangles the DESTDIR support in makefile to install into a staging area:
+   makefile (I didn't take this one yet).
+
+Updated copyright notices for 2004, all modules.  7 Jan 2004.
+
+Added INPUT /NOMATCH, allowing INPUT to be used for a fixed amount of time
+without attempting to match any text or patterns, so it's no longer
+necessary to "input 600 STRING_THAT_WILL_NEVER_COME".  If /NOMATCH is
+included, INPUT succeeds if the timeout expires, with \v(instatus) = 1
+(meaning "timed out"); fails upon interruption or i/o error.  ckuusr.h,
+ckuus[r24].c, 7 Jan 2004.
+
+Added SET INPUT SCALE-FACTOR <float>.  This scales all INPUT timeouts by the
+given factor, allowing time-sensitive scripts to be adjusted to changing
+conditions such as congested networks or different-speed modems without
+having to change each INPUT-class command.  This affects only those timeouts
+that are given in seconds, not as wall-clock times.  Although the scale
+factor can have a fractional part, the INPUT timeout is still an integer.
+Added this to SHOW INPUT, and added a \v(inscale) variable for it.
+ckuusr.h, ckuus[r257].c, 7 Jan 2004.
+
+undef \%a, \fverify(abc,\%a) returns 0, which makes it look as if \%a is a
+string composed of a's, b's, and/or c's, when in fact it contains nothing.
+Changed \fverify() to return -1 in this case.  ckuus4.c, 12 Jan 2004.
+
+\fcode(xxx) returned an empty string if its argument string was empty.  This
+makes it unsafe to use in arithmetic or boolean expressions.  Changed it to
+return 0 if its argument was missing, null, or empty.  ckuus4.c, 12 Jan 2004.
+
+Updated \verify() and \fcode() help text.  ckuus2.c, 12 Jan 2004.
+
+While setting up IKSD, Ian Beckwith noticed that including the --initfile:
+option caused Kermit to start parsing its own Copyright string as if it were
+the command line, and eventually crash.  I couldn't reproduce on Solaris /
+Sparc but I could in Linux / i386 (what Ian is using) -- a change from Jeff
+on 28 Apr 2003 set the command-line arg pointer to a literal empty string in
+prescan() about line 1740 of of ckuus4.c; the pointer is incremented next
+time thru the loop, resulting in random memory being referenced.  Fixed by
+setting the pointer to NULL instead of "".  ckuus4.c, 12 Jan 2004.
+
+declare \&a[999999999999999] would dump core on some platforms.  atoi()
+or whatever would truncate the dimension to maxint.  When we add 1 to the
+result, we get a negative number, which is used as an index, loop test, etc.
+Fixed both dodcl() and dclarray() to check for (n+1 < 0).  ckuus[r5].c,
+12 Jan 2004.
+
+Unix zchki() would fail on /dev/tty, which is unreasonable.  This prevented
+FOPEN /READ from reading from the terminal.  zchki() already allowed for
+/dev/null, so I added /dev/tty to the list of specials.  Ditto for FOPEN
+/WRITE and zchko().  ckufio.c 13 Jan 2004.
+
+Added untabify() routine to ckclib.[ch], 13 Jan 2004.
+Added FREAD /TRIM and /UNTABIFY.  ckuus[27].c, 13 Jan 2004.
+Added \funtabify().  ckuusr.h, ckuus[24].c, 13 Jan 2004.
+
+Dat Nguyen noticed that (setq u 'p') followed by (u) dumped core.  This was
+caused by an over-clever optimization that skipped mallocs for short
+literals, but then went on later to try to free one that hadn't been
+malloc'd.  Fixed in dosexp(): ckuus3.c, 14 Jan 2004.
+
+Catch another copyright date.  ckuus5.c, 14 Jan 2004.
+
+Fixed SWITCH to work even when SET COMMAND DOUBLEQUOTE OFF (from Mark
+Sapiro).  ckuus5.c, 15 Jan 2004.
+
+Changed version to 8.0.211 so scripts can test for recently added features.
+ckcmai.c, 15 Jan 2004.
+
+Fixed a glitch in K95 "help set port".  ckuus2.c, 20 Jan 2004.
+
+Fix from Jeff: Connections to a TLS-aware protocol which require a reconnect
+upon certificate verification failure could not reconnect if the connection
+was initiated from the command line or via a URL.  ckctel.c ckcmai.c
+ckuusr.c ckuus7.c ckuusy.c, 20 Jan 2004.
+
+From Alex Lewin: makefile target and #ifdef for Mac OS X 10.3 (Panther):
+makefile, ckcnet.c, 7 Feb 2004.
+
+Added KFLAGS to sco32v507 targets to make PTY and SSH commands work.  The
+same flags could probably also be added to earlier OSR5 targets but they
+have not been tested there.  makefile, 7 Feb 2004.
+
+Checked a complaint that "LOCAL &a" did not make array \&a[] local.  Indeed
+it did not, and can not.  You have to use the full syntax in the LOCAL
+command, "LOCAL \&a[]", or else it doesn't know it's not a macro named &a.
+7 Feb 2004.
+
+Fixed some confusion in creating IKSD database file and temp-file names.
+I was calling zfnqfp() without remembering that the path member of the
+returned struct included the filename, so to get just the directory name,
+I needed to strip the filename from the right.  ckuusy.c, 2 Mar 2004.
+
+New ckuath.c, ck_ssl.c from Jeff.  2 Mar 2004.
+
+Updated Jeff's affiliation in VERSION command text.  ckuusr.c, 2 Mar 2004.
+
+Designation changed from Dev.00 to Beta.01.  ckcmai.c, 2 Mar 2004.
+
+Fixed zrename() syslogging -- it had success and failure reversed.
+Beta.02: ckufio.c, 4 Mar 2004.
+
+Problem: when accessing IKSD via a kermit:// or iksd:// URL, and a user ID
+is given but no password, doxarg() set the password to "" instead of leaving
+it NULL, but all the tests in dourl() are for NULL.  Fixed in doxarg():
+ckuusy.c, 5 Mar 2004.
+
+The logic in dourl() about which macro to construct (login and connect,
+login and get directory listing, or login and fetch a file) was a bit off,
+so all three cases were not handled.  ckcmai.c, 5 Mar 2004.
+
+Trial Beta builds:
+ . HP-UX B.11.11 PA-RISC
+ . HP-UX B.11.23 IA64
+ . Tru64 4.0G Alpha
+ . Tru64 5.1B Alpha
+ . Debian 3.0 i386
+ . Red Hat ES 2.1 i386
+ . Slackware 9.1 i386
+ . VMS 7.3-1 Alpha + UCX 5.3
+ . VMS 7.3-1 Alpha no TCP/IP
+ . VMS 7.3 Alpha MultiNet 4.3 A-X
+ . SCO UnixWare 7.1.4 i386
+ . SCO OSR5.0.7 i386
+ . Solaris 9 Sparc
+
+Fixed compiler warning in doxarg() caused by typo (NULL instead of NUL) in
+the 5 March doxarg() edit.  ckuusy.c, 9 Mar 2004.
+
+IKSD (kermit://) command-line URLs did not work right if the client had
+already preauthenticated with Kerberos or somesuch because they tried to log
+in again with REMOTE LOGIN.  The macros constructed in doxarg() needed to
+check \v(authstate) before attempting REMOTE LOGIN.  ckcmai.c, 10 Mar 2004.
+
+Added ckuker.nr to x.sh (ckdaily upload) and updated ckuker.nr with current
+version number and dates.  10 Mar 2004.
+
+Replaced hardwired references to /usr/local in makefile with $(prefix)
+(which defaults to /usr/local, but can be overridden on the command line),
+suggested by Nelson Beebe for use with Configure.  10 Mar 2004.
+
+From Nelson Beebe: In the Kermit makefile in the install target commands,
+line 981 reads:
+
+        cp $(BINARY) $(DESTDIR)$(BINDIR)/kermit || exit 1;\
+
+Could you please add this line before it:
+
+        rm -f $(DESTDIR)$(BINDIR)/kermit;\
+
+Some sites (mine included) keep multiple versions of software around,
+with hard links between $(prefix)/progname and $(prefix)/progname-x.y.z.
+Failure to remove the $(prefix)/progname at "make install" time then
+replaces the old $(prefix)/progname-x.y.z with the new one, destroying
+an old version that the site wanted to be preserved.  makefile, 10 Mar 2004.
+
+Minor syntax and typo fixes (mostly prototypes): ckcdeb.h, ckcfns.c,
+ckclib.c, ckufio.c, ckuusr.h, ckuusx.c, 10 Mar 2004.  (I still have a few
+more to do.)
+
+Added CC=$(CC) CC2=$(CC2) to many (but not all) makefile targets that
+reference other makefile targets.  On some platforms (notably AIX, Solaris,
+SunOS) there are specific targets for different compilers, so I skipped
+those.  makefile, 10 Mar 2004.
+
+Added error checking to kermit:// URL macros, so they don't plow ahead
+after the connection is closed.  ckcmai.c, 11 Mar 2004.
+
+Added FreeBSD 4.9 and 5.1 targets (only the herald is affected).
+makefile, ckuver.h, 11 Mar 2004.
+
+Added "LIBS=-lcrypt" to bsd44 targets since nowadays crypt is almost always
+unbundled from libc.  Also added explanatory notes.  makefile, 11 Mar 2004.
+
+Changed MANDIR to default to $(manroot)/man/man1, and manroot to default
+to $(prefix).  More adding of CC=$(CC) clauses: {Free,Net,Open}BSD, 4.4BSD.
+makefile, 11 Mar 2004.
+
+Miscellaneous cleanups: ckuusx.c, ckcnet.c, ckufio.c, 11 Mar 2004.
+
+Corrected the check in the linux target to see if /usr/include/crypt.h
+exists, and if so to define HAVE_CRYPT_H, which is used in ckcdeb.h to
+#include <crypt.h> to get the prototype for crypt() and prevent bogus
+conversions on its return type on 64-bit platforms (the previous test wasn't
+quite right and the resulting symbol wasn't spelled right).  makefile,
+12 Mar 2004.
+
+From Jeff, 14 Mar 2004:
+ . Initialize localuidbuf[] in tn_snenv(): ckctel.c.
+ . Remove remote-mode checks in hupok() for K95G only (why?): ckuus3.c.
+ . Add help text for new K95-only TYPE /GUI switches: ckuus2.c.
+ . TYPE /GUI parsing, ...: ckuusr.c.
+ . TYPE /GUI action, dotype(): ckuus6.c
+ . Change Jeff's affiliation: most modules.
+
+20 Mar 2004: Looked into adding long file support, i.e. handling files more
+than 2GB (or 4GB) long.  Discovered very quickly this would be a major
+project.  Each platform has a different API, or environment, or transition
+plan, or whatever -- a nightmare to handle in portable code.  At the very
+least we'll need to convert a lot of Kermit variables from long or unsigned
+long to some new Kermit type, which in turn is #defined or typedef'd
+appropriately for each platform (to off_t or size_t or whatever).  Then we
+have to worry about the details of open() vs fopen(); printf() formats (%lld
+vs %Ld vs %"PRId64"...), platforms like HP-UX where you might have to use
+different APIs for different file systems on the same computer, etc.  We'll
+need to confront this soon, but let's get a good stable 8.0.211 release out
+first!  Meanwhile, for future reference, here are a few articles:
+
+General: http://freshmeat.net/articles/view/709/
+Linux:   http://www.ece.utexas.edu/~luo/linux_lfs.html
+HP-UX:   http://devrsrc1.external.hp.com/STK/partner/lg_files.pdf
+Solaris: http://wwws.sun.com/software/whitepapers/wp-largefiles/largefiles.pdf
+
+Looked into FTP timeouts.  It appears I can just call empty() (which is
+nothing more than a front end for select()) with the desired timeout before
+any kind of network read.  If it returns <= 0, we have a timeout.  This is
+not quite the same as using alarm() / signal() around a recv() (which could
+get stuck) but alarm() / signal() are not not used in the FTP module and are
+not naturally portable to Windows, but select() is already in use in the FTP
+module for both Unix and Windows.  This form of timeout could be used
+portably for both command response and data reads.  What about writes to the
+command or data socket?  They can get stuck for hours and hours without
+returning too, but the select() approach won't help here -- we need the
+actual send() or recv() to time out, or be wrapped in an alarm()/signal()
+kind of mechanism.  But if we can do that for sends, we can also do it for
+receives.  Better check with Jeff before I start programming anything.
+20 Mar 2004.
+
+Later: Decided to postpone the above two projects (ditto IPv6) until after
+8.0.211 is released because both will have major impacts on portability.
+Grumble: all i/o APIs should have been designed from the beginning with a
+timeout parameter.  To this day, hardly any have this feature.
+
+3-4 Apr 2004: More 8.0.211 Beta.02+ test builds:
+
+ . FreeBSD 3.3
+ . FreeBSD 4.4
+ . Linux Debian 2.1
+ . Linux RH 6.1
+ . Linux RH 7.1
+ . Linux RH 7.2
+ . Linux RH 9 (with 84 different combinations of feature selection)
+ . Linux SuSE 6.4
+ . Linux SuSE 7.0
+ . NetBSD 1.4.1
+ . NetBSD 1.5.2
+ . OpenBSD 2.5
+ . OpenBSD 3.0
+ . QNX 4.25
+ . SCO UnixWare 2.1.3
+ . SCO UnixWare 7.1.4
+ . SCO OpenServer 5.0.7
+ . SCO XENIX 2.3.4 (no TCP)
+
+Changes needed: None.
+
+Problem: SCO XENIX 2.3.4 network build failed in the FTP module with
+header-file syntax and conflicting-definitions trouble.  I'm not going to
+try to fix it; 8.0.209 built OK with FTP, so we'll just keep that one
+available.
+
+Got access to VMS 8.1 on IA64.  Building the nonet version of C-Kermit
+required minor modifications to ckvvms.h, ckv[ft]io.c, and ckvcon.c, to
+account for a third architecture.  Also to SHOW FEATURES in ckuus5.c.  Once
+that was done, the UCX 5.5 version built OK too.  Starts OK, makes Telnet
+connection OK, sends files.  Has some obvious glitches though -- "stat"
+after a file transfer reports 0 elapsed time (in fact it was 00:09:48) and
+1219174400 cps (when in fact it was 10364).  This doesn't happen on the
+Alpha.  Btw, the IA64 binary is twice as big as the Alpha one.  Changed
+to Beta.03.  5 Apr 2004.
+
+Fixed the ckdaily script to include the makefile and man page in the Zip
+file (they were not included because the Zip file was intended mainly for
+VMS users, but some Unix users prefer Zip to tar.gz).  6 Apr 2004.
+
+Traced problems in VMS/IA64 statistics report to rftimer()/gftimer() in
+ckvtio.c, which use sys$ and lib$ calls to figure elapsed time.  These work
+on VAX and Alpha but not IA64.  Sent a report to the chief engineer of the
+IA64 VMS port; he says it's probably a bug in VMS 8.1 (which is not a real
+release); he'll make sure it's fixed in 8.2.  As an experiment, tried
+swapping in the Unix versions of these routines (which call gettimeofday()
+etc).  They seem work just fine (it hung a couple times but I think that's
+because the underlying system hung too; trying it later on a new connection,
+it was fine; however I noticed a BIG discrepancy in throughput between
+sending and receiving).  Moved definitions for VMS64BIT and VMSI64 to
+ckcdeb.h so all modules can use them and added them to the SHOW FEATURES
+display.  Added VMSV80 definition to build procedure.  Beta.03+.  ckcdeb.h,
+ckcuus5.c, ckcvvms.h, ckvtio.c, ckvker.com, 6 Apr 2004.
+
+While doing the build-all, I noticed the VMS version did not build with
+Multinet or older UCX versions, always with the same errors -- undeclared
+variables, undefined symbols, all TCP/IP related.  This didn't happen a
+couple weeks ago...  Somehow the order of #includes was messed up --
+ckuusr.h depended on symbols that are defined in ckcnet.h, but ckcnet.h
+was being included after ckuusr.h...  this was compounded by two missing
+commas in ckvker.com.  11 Apr 2004.
+
+Removed Beta designation, released as 8.0.211, 10 Apr 2004.
+
+I had somehow lost the edit to ckutio.c that changed the UUCP lockfile for
+Mac OS X from /var/spool/uucp to /var/spool/lock.  So I slipped it in and
+re-uploaded version 8.0.211.  You can tell the difference because SHOW
+VERSIONS has 17 Apr 2004 for the Communications I/O module.  Also the 10.3
+executable now has a designer banner: "Mac OS X 10.3".  makefile, ckuver.h,
+ckutio.c, ckuus[45].c, 17 Apr 2004.
+
+---8.0.211---
+
+Removed "wermit" from "make clean" (how did it get there?).  makefile.
+
+From Jeff, applied 10 May 2004.
+ . Rearrange #ifdefs that define OS/2-only features. ckcdeb.h.
+ . Fix two strncat()s that should have been ckstrncat()s.  ckuus7.c.
+ . Fix two strncat()s that should have been ckstrncat()s.  ckuus4.c.
+ . Fix one strncat(). ckcfns.c.
+ . SET FTP CHAR ON used backwards byte order when output to screen.  ckcfns.c.
+ . Fix two strncat()s.  ckuus3.c.
+ . Add SET NETWORK TYPE NAMED-PIPE for K95.  ckuus3.c.
+ . Add "No active connections" message to hupok().  ckuus3.c.
+ . Fix many strncat()s.  ckcnet.c.
+ . Fix some strncat()s.  ckcftp.c
+ . Make FTP port unsigned short for 16383 < port < 65536.  ckcftp.c.
+ . Improvements to FTP USER command.  ckcftp.c.
+ . Fix FEAT parsing to allow for various forms of whitespace.  ckcftp.c.
+
+S-Expression (AND FOO BAR) would not short-circuit if FOO's value was 0,
+even though short-circuiting code has been there since Day 1.  Similarly for
+(OR BAR FOO).  Turns out the first operand was a special case that bypassed
+the short-circuit check.  Fixed in dosexp(): ckuus3.c, 10 May 2004.
+
+Red Hat 7.3 (and maybe others) <baudboy.h> referenced open() without first
+ensuring it was declared.  The declaration is in <fcntl.h>, which is after
+<baudboy.h> in ckutio.c series of #includes.  Made a special case for this.
+ckutio.c (see comments), 10 May 2004.
+
+If the local Kermit's parity is set to SPACE and then a file arrives via
+autodownload, automatic parity detection improperly switches it to NONE.
+Fixed in rpack() by switching parity automatically only if parchk() returns
+> 0 (rather than > -1), since NONE and SPACE are indistinguishable.  A
+bigger problem still remains: autodownload does not work at all if the
+sender is using actual parity bits (even, odd, or mark) and the receiver's
+parity is NONE.  ckcfn2.c, 10 May 2004.
+
+When a DIAL MACRO is defined and the phone number is comprised of more than
+one "word" (i.e. contains spaces), the dial macro loses the second and
+subsequent words after the first call. Fixed in xdial() by inserting quotes
+around phone number before passing it to xdial(). ckuus6.c, 10 May 2004.
+
+DIAL MACRO fix was not right; the quotes were kept as part of the phone
+number and sent to the modem.  dodo() pokes its argument to separate the
+macro argument string into its component arguments.  xdial() is called
+repeatedly on the same string, so after the first time, a NUL has been
+deposited after the first word of the telephone number.  The fix is to have
+xdial() create a pokeable copy of its argument string before calling
+dodo(dial-macro,args...).  It might seem odd that dodo pokes its argument,
+but making copies would be would be prohibitive in space and time.
+ckuus6.c, 23 May 2004.
+
+FTP CD did not strip braces or quotes from around its argument.  Fixed in
+doftprmt(): ckcftp.c, 23 May 2004.
+
+Added client side of REMOTE MESSAGE/RMESSAGE/RMSG: ckuus[r27].c, 23 May 2004.
+
+Server side of REMOTE MESSAGE: ckcpro.w, 23 May 2004.
+
+From Dave Sneddon: an updated CKVKER.COM containing a fix where the
+COMPAQ_SSL symbol was not defined but later referenced which generated an
+undefined symbol error.  ckvker.com, 5 Jan 2005.
+
+From Andy Tanenbaum (28 May 2005):
+ . Fix an errant prototype in ckcker.h and ckucmd.h - () instead of (void).
+ . Add support for MINIX 3.0.  makefile, ckutio.c, ckufio.c, ckuver.h.
+
+Fixed messed-up sndhlp() call which apparently had been jiggered to
+compensate for the bad prototype which has now been fixed, ckcpro.w,
+12 Jun 2005.
+
+From Jeff (12 June 2005):
+ . Security updates.  ck_ssl.c, ck_crp.c, ckuath.c.
+ . Fix bug in K95 SET PRINTER CHARACTER-SET. ckuus3.c.
+ . Add printer character-set to K95 SHOW PRINTER display. ckuus5,c
+ . Add SET MSKERMIT FILE-RENAMING to K95. ckuus7.c, ckuusr.h.
+ . Add help for K95 SET MSKERMIT.  ckuus2.c.
+ . Add SET GUI CLOSE to K95.  ckuusr.h, ckuus2.c, ckuus3.c
+ . Add help text for K95 SET GUI MENUBAR and TOOLBAR.  ckuus2.c.
+ . Add --noclose command-line option for K95.  ckuusy.c
+ . Add PAM support for Mac OS X.  ckufio.c.
+ . Add GSSAPI support for Mac OS X.  ckcftp.c.
+ . Pick up more URL options.  ckcker.h, ckuusy.c.
+ . Fix bug in delta-time calculation across year boundary.  ckucmd.c.
+ . Add Secure Endpoints to copyright notices.  ckcmai.c.
+ . Fix FTP HELP to override unverbose setting.  ckcftp.c.
+ . Fix assorted minor typos.
+
+From Matthias Kurz: automatic herald generation for NetBSD 2.0 and later,
+"make netbsd2".  ckuver.h, makefile, 12 Jun 2005.
+
+Added SET TERMINAL LF-DISPLAY, like CR-DISPLAY but for linefeed rather than
+carriage return.  ckuusr.h, ckuus[257x].c, 12 Jun 2005.
+
+Made a command-line option --unbuffered to do what the -DNONOSETBUF
+compile-time option does, i.e. force unbuffered console i/o.  Unix only.
+ckuusr.h, ckuusy.c, ckutio.c, 12 Jun 2005.
+
+Fixed getiact() (which displays TERM IDLE-ACTION setting) to display
+space as \{32}.  ckuus7.c, 12 Jun 2005.
+
+Added LMV as a synonym for LRENAME, which is itself a synonym for LOCAL
+RENAME.  ckuusr.c, 12 Jun 2005.
+
+Put HELP SET TERMINAL DG-UNIX-MODE text where it belonged.  ckuus2.c,
+12 Jun 2005.
+
+Added IF LINK (Unix only) to test if a filename is a symlink.  Uses the most
+simpleminded possible method, calls readlink() to see if it succeeds or fails.
+No other method is dependable across different Unixes.  This code should be
+portable because I already use readlink() elsewhere within exactly the same
+#ifdefs.  ckufio.c, ckuus2.c, ckuus6.c, 12 Jun 2005.
+
+Fixed a bug in which \fdir() wouldn't work when its argument was the nonwild
+name of a directory file.  zxpand(): ckufio.c, 12 Jun 2005.
+
+Made \fdirectory() a synonym for \fdirectories().  Made \fdir() an
+acceptable abbreviation for these, even though it clashes with \fdirname(),
+which still works as before.  ckuus4.c, 12 Jun 2005.
+
+Added the long-needed \flopx() function, to return rightmost pieces of
+strings, such as file extensions.  \fstripx() and \flopx() are the
+orthogonal functions we need to pick filenames apart from the right:
+\stripx(foo.tar.gz) = foo.tar; flopx(foo.tar.gz) = gz.  ckuusr.h, ckuusr.c,
+ckuus2.c, 12 Jun 2005.
+
+Removed reference to defunct fax number, ckcmai.c, 12 Jun 2005.
+
+Added -DHAVE_PTMX to linux+krb5+openssl+zlib+shadow+pam.  From Timothy Folks.
+makefile, 12 Jun 2005.
+
+Built on Solaris 9 and NetBSD 2.0.
+
+From Jeff: New build target for Mac OS X 10.3 with Kerberos 5 and SSL.
+makefile, 14 Jun 2005.
+
+Fixed error in ckuver.h NetBSD #ifdefs.  15 Jun 2005.
+
+Fixed SET TERMINAL IDLE-ACTION OUTPUT to work as documented, namely if the
+output string is empty, to send a NUL.  Previously there was no way to make
+it send a NUL.  ckuus7.c, 15 Jun 2005.
+
+Suppose (in Unix, for example) a filename contains wildcard characters, such
+as {abc}.txt.  When referring to such a file (e.g. in a SEND command), these
+characters can be quoted, e.g. \{abc\}.txt.  But if the file list has been
+obtained programmatically, e.g. stored in an array, there is no way, short
+of tedious, complicated, and error-prone string processing, to reference the
+file.  For this we need a way to disable wildcard processing.  I added { ON,
+OFF } choices for the SET WILD and SHOW FILE commands: ckuusr.h, ckuus[234].c.
+{ ON, OFF } turns wildcarding off and on without affecting the { KERMIT,
+SHELL } agent choice; it does this by setting a new and separate global
+variable, wildena.  Added semantics to ckufio.c.  Crude but effective.  It
+might have been more Unixlike to add Yet Another form of quoting but we
+have enough of that already (later maybe I'll add a \function() for this).
+Needs to be propogated to Windows and VMS.  15 Jun 2005.
+
+Improved and fixed typos in HELP WILDCARD and HELP PATTERN.  ckuus2.c,
+15 Jun 2005.
+
+The GREP command, and probably anything else that uses ckmatch() for pattern
+matching, failed on patterns like */[0-3]*.html.  The [a-b] handler, when
+failing to match at the current position, neglected to back up the pattern
+and try again on the remainder of the string.  I also fixed another case, in
+which matching a literal string a*b?c against the pattern a[*?]*[?*]c caused
+ckmatch() to recurse until it blew up.  ckclib.c, 16 Jun 2005.
+
+Added builds and designer banner for Solaris 10.  makefile, ckuver.h,
+27 Jun 2005.
+
+Defined CKHTTP for NetBSD, the HTTP code builds and works fine there.
+ckcdeb.h, 2 Jul 2005.
+
+Added #ifndef OSF40..#endif around definition of inet_aton() in ck_ssl()
+to allow building in Tru64.  Added tru64-51b+openssl to makefile.
+15 Jul 2005.
+
+HTTP GET would fail if the URL contained any metacharacters, no matter how
+much you quoted them.  Although it uses cmfld() to parse the (partial) URL,
+it then uses cmofi() to get the output filename, which by default is the
+"filename" from the URL, which might be something like "rankem.asp?id=1639".
+cmofi() refuses to accept unquoted metacharacters in "filenames" and that's
+what happens in this case if the output filename is not specified.  Worked
+around this by disabling wildcard processing around HTTP GET using the new
+"wildena" variable from June 15th.  ckuusr.c, 18 Jul 2005.
+
+Fixed the June 16th fix to the pattern matcher.  I fixed a real problem, but
+I made an unrelated optimization that introduced new ones.  ckclib.c,
+18 Jul 2005.
+
+Added missing help text for \fb64encode() and \fb64decode().  ckuus2.c,
+18 Jul 2005.
+
+Changed SET WILD OFF help text to warn that this setting prevents the
+creation of backup files (later I'll have to see if something more useful
+can be done about this).  ckuus2.c, 18 Jul 2005.
+
+Built OK on Mac OS X 10.4.2 using macosx103 target (but with some
+"signedness" warnings in ckcnet.c and ckcftp.c).  Built on Unixware 7.1.4
+with uw7 target.  27-28 Jul 2005. 
+
+Added -DCKHTTP to Mac OS X 10.3-.4 KFLAGS.  Makefile, 4 Aug 2005.
+
+Built on BSDI 4.3.1.  Added -DCKHTTP.  
+
+Compact substring notation extended to accept not only start:length but also
+start-end notation.  Thus \s(foo[12:18]) means the substring of foo starting
+at position 12 of length 18, and tne new \s(foo[12-18]) means the substring
+of foo starting at position 12 and ending with position 18.  Ditto for
+\:(\%a), etc.  ckuus4.c, 9 Aug 2005.
+
+See correspondence with Mark Sapiro, Nov 2003 and Sep 2004, about certain
+variations on IF syntax having been broken by the introduction of "immediate
+macros" circa 1999.  It seems the problem -- variables not being expanded --
+always occurs in the ELSE part when (a) the IF condition is false; (b) the
+ELSE command is "standalone", i.e. expressed as a separate command after the
+IF command (original C-Kermit 5A syntax), and (c) its command list is a block.
+This would suggest the problem is in the XXELS parser.
+
+Going back to 1999, I find this:
+  Fixed a problem Jim Whitby noticed with quoting in ELSE statements.  This
+  problem was introduced when I unified IF and XIF, and occurs only when
+  ELSE begins on a line, followed by a { command list } rather than a single
+  command.  The solution (gross) was to make a special version of pushcmd()
+  (called pushqcmd()) for this situation, which doubles backslashes while
+  copying, BUT ONLY IF it's a command list (i.e. starts with "{"); otherwise
+  we break lots of other stuff.  Result passes Jim's test and still passes
+  ckedemo.ksc and iftest.ksc.  ckucmd.c, ckuus6.c, 27 Sep 99.
+
+I undid this change and it made no difference to all the other IF
+constructions (in fact, it fixed an urelated one that was broken, so now
+iftest scores 54 out of 54, instead of 53).  However, it does not fix the
+ELSE problem; in fact it pushes it all the way in the other direction:
+
+  The opposite occurs any time you try to execute an immediate macro inside a
+  macro or any other { block }: not only is the variable evaluated, it is
+  evaluated into nothing.  It looks like this happens only in immediate
+  macros, i.e. *commands* that start with '{'.  So maybe we really have two
+  isolated problems, that can each be fixed.
+
+The situation is illustrated by this simple script:
+
+  def xx {
+      if false { echo \%1, echo \%2 }
+      else { echo \%3, echo \%4 }
+  }
+  xx one two three four
+
+With pushqcmd() it echoes the variable names literally; with pushcmd() it 
+echoes empty lines.  Since ELSE, when its argument is a block, dispatches
+to the immediate-macro handler, it seems we have unified the two problems,
+so fixing one should fix the other.
+
+The problem is that we define a new temporary macro and then call dodo() to
+execute it.  But if the definition contains macro arguments, we have added a
+new level of macro invocation, thus wiping out the current level of args.
+The cure is to expand the variables in the immediate macro in the current
+context, before executing it.  This means simply changing the cmtxt() call
+that reads the immediate macro to specify xxsting as its processing
+function, rather than NULL, which is used for real macros to defer their
+argument evaluation until after the macro entered.  ckuusr.c, 11 Aug 2005.
+
+Added a new makefile target, macosx10.4, for Mac OS X 10.4.  This one uses
+an undocumented trick to get the otherwise unavailable-except-by-clicking
+Mac OS X version number (in this case 10.4.2) and stuff it into the HERALD
+string.  makefile, 11 Aug 2005.
+
+Built OK on Solaris 9, Solaris 10 (with a few implicit declaration warnings
+in ckuusx.c), Mac OS X 10.4.2 (with some warnings in ckcnet.c and ckcftp.c),
+Mac OS X 10.3.9 (also using the macos10.4 entry, which gets the right
+version number, and gets no warnings at all), RH Enterprise Linux AS4 on AMD
+x86_64, Tru64 Unix 4.0F, SCO UnixWare 7.1.4
+
+For docs and/or scriptlib:  Unix C-Kermit can be a stdin/out filter.  The
+trick is to use the ASK, ASKQ, or GETC command for input, specifying no
+prompt, and ECHO or XECHO for output, e.g.:
+
+while true {
+    ask line
+    if fail exit 0
+    echo \freverse(\m(line))
+}
+exit 0
+
+FOPEN didn't do anything with the channel number if the open failed, so any
+subsequent command that tried to reference it would get a parse error it was
+undefined or non-numeric, not very helpful.  Changed FOPEN to set the
+channel number to -1 if the file can't be opened.  Now subsequent operations
+on the channel fail with "Channel -1: File not open".  I also added two
+magic channel numbers: -8 means that any FILE command (besides OPEN and
+STATUS) on that channel is a noop that succeeds silently; -9 is a noop that
+fails silently.  So now it's possible to simply set a channel number to one
+of these values to disable i/o to certain file without getting lots of error
+messages.  dofile(): ckuus7.c, 12 Aug 2005.
+
+Added automatic herald construction for UnixWare 7.  makefile, 12 Aug 2005.
+
+Unix isdir() never allowed for arguments that started with tilde, so gave
+incorrect results for ~/tmp/ or ~fdc.  The problem was mainly invisible
+since most commands that parsed file or directory names used cmifi(), cmdir(),
+etc, which did the conversions themselves.  But IF DIRECTORY was an exception,
+since its operand had to be treated as just text, and then tested after it
+was parsed.  ckufio.c, 13 Aug 2005.
+
+Fixed the following:
+"ckuusx.c", line 8959: warning: implicit function declaration: ckgetpeer
+"ckufio.c", line 1869: warning: implicit function declaration: ttwait
+"ckufio.c", line 2941: warning: implicit function declaration: mlook
+"ckufio.c", line 2943: warning: implicit function declaration: dodo
+"ckufio.c", line 2944: warning: implicit function declaration: parser
+"ckcftp.c", line 2625: warning: implicit function declaration: delta2sec
+"ckcftp.c", line 4071: warning: no explicit type given for parameter: prm
+"ckcftp.c", line 8389: warning: no explicit type given for parameter: brief
+ckuusx.c, ckufio.c, ckcftp.c, ckucmd.h.  13 Aug 2005.
+
+Unbuffered stdout code has never worked because the setbuf(stdout,NULL) call
+has to occur before the stdout has been used.  The reason it's needed is
+that some Kermit code writes to stderr (which is unbuffered) and other code
+writes to stdout, and therefore typescripts can come out jumbled.  Robert
+Simmons <robertls@nortel.com> provided the needed clue when he insisted it
+worked only when executed at the very beginning of main().  So I moved the
+code to that spot.  But since now we also want to make unbuffered a runtime
+(command-line) option, I had to do a clunky by-hand pre-prescan inline in
+main() to look thru argv[], even before prescan() was called.  ckcmai.c,
+ckutio.c, ckuusy.c, 13 Aug 2005.  (Now that this works, it might be a good
+idea to remove all use of stderr from Kermit.)
+
+Managed, after some finagling, to build a 64-bit version on Solaris 10 at
+Utah Math with Sun cc.  (Can't make any gcc builds at all, 32- or 64-bit,
+they all blow up in <sys/siginfo.h>.)  New target: solaris10_64.  makefile,
+15 Aug 2005.
+
+The 64-bit Solaris 10 version compiles and links OK and transfers files in
+remote mode.  It can make FTP connections and use them, but Telnet connections
+always fail with "network unreachable".  This is with all default libs and
+include files.  Nelson has a separate set in /usr/local, which he references
+explicitly in all his 64-bit builds, but using these makes no difference.
+Some data type is wrong in ckcnet.c.  But telnet works fine in 64-bit Linux
+and Tru64 builds.  Debug logs trace the difference to netopen() (of course),
+the spot where we test the results of inet_addr(), which is already marked
+suspicious for 64-bit builds.  It seems that inet_addr() is of type in_addr_t,
+which in turn is u_int32, i.e. an unsigned 32-bit int.  Yet the man page says
+that failure is indicated by returning -1.  I guess this doesn't matter in
+32-bit builds, but in the 64-bit world, the test for failure didn't work
+right.  I made a Solaris-specific workaround, and checked that it works in
+both 32-bit and 64-builds.  I really hate typedefs.  ckcnet.c, 15 Aug 2005.
+
+Changed the plain-text version (as opposed to the popup or GUI version - the
+GUI version, at least, already does this) of ASKQ to echo keystrokes
+asterisks rather than simply not echo anything, so it's easier to see what
+you're doing, the effects of editing, etc.  Experimental; for now, there's
+no way to disable this.  Not sure if there needs to be.  Anyway, to get this
+working required a fair amount of cleaning up of gtword(), which was echoing
+different ways in different places.  ckuus6.c, ckucmd.c, 15 Aug 2005.
+
+Added a solaris9_64 target for building a 64-bit version on Solaris 9 with
+Sun cc.  Verified, using the DIR command and \fsize() function on a 4.4GB
+file, that the Solaris 64-bit version of Kermit gets the size correctly, and
+that it can copy such a file (thus its fopen/fread/fwrite/fclose interface
+works right).  Initiated a large-file transfer between here and Utah over
+SSH and verified that it puts the correct file size in the A packet when
+sending; the right quantites are shown on the file transfer display (file
+size CPS, percent done, etc).  But even at 5Mb/sec, it takes a good while to
+transfer 4.4GB, more than 2 hours (not streaming; 30 window slots, 4K
+packets, maybe it would go faster with streaming)...  After an hour or so,
+it filled up the partition and gave up (gracefully) before it reached the
+2GB frontier (drained its pending packets, closed the partial file).
+Restarted at 12:54, this time with streaming and 8K packets (the speed
+wasn't significantly different).  This time it transferred 95% of the file
+(4187660288 bytes) before failing because the disk filled up.  Went to Utah
+and started a transfer between two Solaris 10/Sparc hosts; this goes about 8
+times faster.  The transfer completed successfully after 17m41s.  All fields
+in the f.t. display looked right the whole time.  Then I verified various
+other 64-bit combinations transferring the same 4.4GB file:
+
+        To................
+  From  Sol  Amd  i64  Tru      
+  Sol   OK   OK   OK   OK      Sol = Solaris 10 / Sparc
+  Amd   OK                     Amd = AMD x86_64 RH Enterprise Linux AS4
+  i64   OK                     i64 = Intel IA64, RH 2.1AS
+  Tru                          Tru = Tru64 Unix 4.0F Alpha
+
+(The other combinations are difficult to test for logistical reasons.)
+
+Tried sending the same long file with Kermit's FTP client.  It chugged along
+for a while until I stopped it; it would have taken hours to complete.
+There is no indication that it wouldn't have worked, assuming the FTP server
+could also handle long files, which who knows.  Anyway, Kermit showed all
+the right data on the display screen.  17 Aug 2005.
+
+On AMD x86_64 and IA64 native 64-bit Linux builds, the pty routines did not
+work at all.  ptsname() dumped core.  If I commented out ptsname(), then the
+next thing dumped core.  The same code works on the other 64-bit builds.
+Poking around, I see that this version of Linux has an openpty() function,
+which I could try using instead of the current API -- grantpty(), etc.  Then
+I see that openpty() is already coded into Kermit's pty module,
+conditionalized under HAVE_OPENPTY, which has never before been defined for
+any build.  I added a test to the makefile linux target (look for the
+openpty() prototype in <pty.h>, if found define HAVE_OPENPTY as a CFLAG and
+also add -lutil to LNKFLAGS).  Works fine on the problem builds, and also
+on previously working 32-bit builds.  makefile, 17 Aug 2005.
+
+Fixed a bug in the ASKQ echo asterisks code, which made the VMS version of
+C-Kermit always echo asterisks.  Turns out that some code in the main parse
+loop to reset command-specific flags was in the wrong place, which had other
+effects too, for example ASKQ temporarily turns off debug logging as a
+security measure, but the code to turn it back on was skipped in most cases.
+Some other side effects related to the DIRECTORY and CD commands might have
+been possible but I haven't seen them.  ckuus[56].c, 23 Aug 2005.
+
+Problem reported when sending a file to VMS when the name in the F packet
+starts with a device specification and does not include a directory field,
+and PATHNAMES are RELATIVE.  Example: dsk:foo.bar becomes f_oo.bar.  The
+code assumes that if there is a device field, it is followed by a directory
+field, and it inserts a dot after the '[', which in this case is not there.
+Later the dot becomes '_' because of the only-one-dot rule.  Solution: only
+insert the dot if there really is an opening bracket.  nzrtol(): ckvfio.c,
+23 Aug 2005.
+
+A report on the newsgroup complains that C-Kermit and K95 servers were
+sending REMOTE DIR listings with only #J line terminators, rather than #M#J.
+Yet all the other REMOTE xxx responses arrived with #M#J.  snddir() was
+neglecting to switch to text mode.  ckcfns.c, 26 Aug 2005.
+
+Back to long files.  What happens if 32-bit Kermit is sent a long file?
+It gets an A-packet that looks like this:
+
+  ^A_"A."U1""B8#120050815 18:28:03!'42920641*4395073536,#775-!7@ )CP
+
+The 32-bit receiver reacts like so:
+
+  gattr length[4395073536]=100106240
+
+the first number being the string from the A-packet, the second being the
+value of the long int it was converted to by atol().  Clearly not equal in
+this case.  When this happens Kermit should reject the file instead of
+accepting it and then getting a horrible error a long time later.  Added
+code to gattr() to convert the result of atol() back to a string and compare
+it with the original string; if they're not equal, reject the file on the
+assumption that the only reason this could happen is overflow.  Also some
+other code in case the sender sends the only LENGTHK attribute.  Now files
+whose lengths are too big for a long int are rejected right away, provided
+the sender sends the length in an A packet ahead of the file itself.  If
+this new code should ever cause a problem, it can be bypassed with SET
+ATTRIBUTE LENGTH OFF.  ckcfn3.c, 26 Aug 2005.
+
+As I recall from when I was testing this a few weeks ago, when the too-big
+length is not caught at A-packet time, the transfer fails more or less
+gracefully when the first attempt is made to write past the limit.  I went
+to doublecheck this by sending a big file from the 64-bit Solaris10 version
+to a 32-bit Mac OS X version that does not have today's code.  The Mac
+thinks the incoming file is 2GB long when it's really 4GB+.  But in this
+case, something new happens!  Although the percent done and transfer rate go
+negative, the file keeps coming.  It would seem that Mac OS X lets us create
+long files without using any special APIs.  The transfer runs to completion.
+Mac OS X Kermit says SUCCESS (but gets the byte count and cps wrong, of
+course).  But then a STATUS command says FAILURE.  The file was, however,
+transferred successfully; it is exactly the same length and compares byte
+for byte with the original.  This tells me that in the Mac OS X version --
+and how many others like it??? -- today's rejection code should not be
+enabled.  Meanwhile I put today's new code in #ifndef NOCHECKOVERFLOW..#endif,
+and defined this symbol in the Mac OS X 10.4 target.  Over time, I'll have
+to find out what other platforms have this characteristic.  And of course
+I'll also have to do something about file-transfer display, statistics, and
+status.  makefile, ckcfn3.c, 26 Aug 2005.
+
+From now on I'm going to bump the Dev.xx number each time I upload a new
+ckdaily.  This one will be Dev.02.  ckckmai.c, 26 Aug 2005.
+
+Got rid of all the extraneous FreeBSD 4 and 5 build targets.  Now there's
+one (freebsd) for all FreeBSD 4.1 and later.  makefile, 27 Aug 2005.
+
+Mac OS X 10.4 (Tiger) is a 64-bit OS.  Building C-Kermit 0n 10.4.2 without
+any special switches stilll gives a 32-bit executable.  Ditto building with
+-mpowerpc64.  Further investigation turned up a tip sheet on MySQL that says
+you have to include all of these: -mpowerpc64 -mcpu=G5 -mtune=G5 -arch
+ppc64.  That did the trick.  New makefile target: macosx10.4_64.  But the
+10.4.2 system I tried did not have 64-bit [n]curses or resolv libs, so this
+build has no -DNOCURSES -DNO_DNS_SRV.  makefile, 27 Aug 2005.
+
+Created a symbol CK_64BIT to indicate true 64-bit builds at compile time.
+Added 64-bit announcement to the startup herald and the VERSION text.
+ckcdeb.h, ckuus[r5].c, 27 Aug 2005.
+
+Added a built-in variable \v(bits) to indicate the size of the build
+(16, 32, 64, or whatever else sizeof() might report).  ckuusr.h, ckuus4.c,
+27 Aug 2005.
+
+Got rid of all the warnings in 64-bit Mac OS X about args to getsockopt(),
+getsockname(), and getpeername(), and the comparisons on the return value
+of inet_addr().  ckcnet.[ch], 27 Aug 2005.
+
+Now to check the effects on other builds...
+  Linux on AMD64: ok.
+  Linux on IA64: ok.
+  Linux on i386: ok.
+  Mac OS X 10.3.9 32-bit: ok.
+  Solaris 10 64-bit: ok.
+  Solaris 9 32-bit: ok.
+  Tru64 4.0F: ok.
+  FreeBSD 4.11: ok.
+  FreeBSD 5.4 ia64 (64-bit): ok.
+  FreeBSD 5.4 i386 (32-bit): ok.
+
+The Tru64 5.1B build totally blew up because they have their own unique
+sockopt/etc length-argument data type (int!), so I had to roll back on using
+socklen_t for this in all 64-bit builds.  Checked to make sure it still
+builds on Tru64 4.0F after this change (it does).  ckcnet.h, 27 Aug 2005.
+
+The HP-UX 11i/ia64 build comes out to be 32-bit but thinks it's 64-bit.
+CK_64BIT is set because __ia64 is defined.  So how do I actually make a
+64-bit HP-UX build?  I tried adding +DD64 to CFLAGS, and this generates
+64-bit object files but linking fails to find the needed 64-bit libs
+(e.g. -lm).  For now I added an exception for HPUX to the CK_64BIT
+definition section.  ckcdeb.h, 27 Aug 2005.
+
+Took the time to verify my recollection about the "graceful failure" on a
+regular Pentium Linux system when receiving a too-big file...  OK, it's not
+exactly graceful.  It gets a "File size limit exceeded" error; the message
+is printed in the middle of the file-transfer display, apparently not by
+Kermit, and Kermit exits immediately.  Looks like a trap...  Yup.  "File
+size limit exceeded" is SIGXFSZ (25).  What happens if we set it to SIG_IGN?
+Just the right thing: The receiver gets "Error writing data" at 2147483647
+bytes, sends E-packet to sender with this message, and recovers with total
+grace (drains packet buffers, returns to prompt).  ckutio.c, 27 Aug 2005.
+
+Backed off from rejecting a file because its announced size overflows a
+long.  Now instead, I set the file size to -2 (a negative size means the
+size is unknown, but we have always used -1 for this; -2 means "unknown and
+probably too big").  In this case, the f-t display says:
+
+  File Size: POSSIBLY EXCEEDS LOCAL FILE SIZE LIMIT
+
+then the user can interrupt it with X or whatever, or can let it run and
+see if maybe (as in the case of Mac OS X) it will be accepted anyway.  This
+way, we skip all the bogus calculations of percent done, time remaining, etc.
+ckcfn3.c, ckuusx.c, 27 Aug 2005.
+
+Discovered that VMS C-Kermit on Alpha and IA64 is a 32-bit application;
+sizeof(long) == sizeof(char *) == 4.  Tried adding /POINTER_SIZE=64 to VMS
+DECC builds on Alpha and IA64, but the results aren't great.  Tons of
+warnings about pointer size mismatches between Kermit pointers and RMS ones,
+and the executable doesn't run.  It appears that access to long files
+would require a lot of hacking, similar to what's needed for 32-bit Linux.
+
+--- Dev.02: 27 Aug 2005 ---
+
+From Jeff, 28 Aug 2005.
+ . Fix SSH GLOBAL-KNOWN-HOSTS-FILE / USER-KNOWN-HOSTS-FILE parsing, ckuus3.c.
+ . Pick up K95STARTFLAGS from environment, ckuus4.c.
+ . Fix some typos in command-line processing (-q), ckuus4.c.
+ . Be sure to suppress herald if started with -q, ckuus7.c.
+ . Fix ssh command-line switches, ckuusy.c.
+
+Eric Smutz complained that HTTP POST was adding an extraneous blank line,
+which prevented his application from successfully posting.  RFC 2616 states
+(in Section 4.1):
+
+   In the interest of robustness, servers SHOULD ignore any empty
+   line(s) received where a Request-Line is expected. In other words, if
+   the server is reading the protocol stream at the beginning of a
+   message and receives a CRLF first, it should ignore the CRLF.
+
+   Certain buggy HTTP/1.0 client implementations generate extra CRLF's
+   after a POST request. To restate what is explicitly forbidden by the
+   BNF, an HTTP/1.1 client MUST NOT preface or follow a request with an
+   extra CRLF.
+
+This seems pretty clear.  One section of code in http_post() (just above the
+postopen: label) was appending a CRLF to a buffer whose last already was
+terminated by CRLF, and then appended a second CRLF; thus two empty lines.
+I removed the second one.  ckcnet.c, 28 Aug 2005.
+
+I looked into the 64-bitness of NetBSD, it seems to be like Linux and
+FreeBSD on 64-bit hardware, i.e. you just build it there and it works, at
+least on Alpha and AMD64, going back to NetBSD 1.4 or 1.5.  But I don't have
+access to any of these for verification and documentation on the Web is
+scanty.
+
+Checked PeterE's complaint again of warnings in ckutio.c about parameter
+list of get[ug]id() and gete[ug]id().  When I "make hpux1100o" on HP-UX
+11.11 (PA-RISC), there are definitely no warnings.  He says the same thing
+happens on 10.xx, but I don't have access to that any more.  I also did
+"make hpux1100o" on HP-UX 11.23 (11i v2) (PA-RISC), also no warnings.
+(Except in both cases, a warning about a comment within a comment in
+/usr/include/sys/ptyio.h).  On HP-UX 11i v2 on Itanium, however, there are
+TONS of warnings, mostly of the "variable set but never used" kind.  Also
+"dollar sign used in identifier".  Tracking this last one down, I see it's
+complaining about code that's in #ifdefs for other platforms, such as
+Apollo Aegis.  Is "aegis" defined in HP-UX 11i v2/IA64?  No!  (It would show
+up in SHOW FEATURES if it was.)  Some phase of the compiler is complaining
+about code that it should be skipping (and that, in fact, it *is* skipping
+it because the build is successful).  It's as if cc is running lint for me
+but not telling lint which macros are defined and which are not.
+
+Verified that 64-bit linking fails in the same way for HP-UX 11i v2 on both
+IA64 and PA-RISC.  Sent a query to HP.
+
+Compiling ckcnet.c and ckcftp.c got the familiar sockopt-related warnings on
+HP-UX 11i v2; turns out it is just like Tru64 Unix in using an int for the
+length argument.  Added another special case and the warnings went away.
+ckcnet.h, 28 Aug 2005.
+
+Added some stuff to SHOW FEATURES to see what kinds of macros are exposed
+(e.g. INT_MAX, LONG_MAX, LLONG_MAX, etc) and also show sizeof(long long) and
+sizeof(off_t).  Building this code all over the place will give me an idea
+of how widespread these data types are, and to what extent I can tell
+whether they are available from clues in the header files.  (At first
+glance, it appears that I'm not picking up <limits.h>, but adding an
+#include for it is just asking for trouble.)  No complaints about long long
+or off_t from Solaris 9 or recent Linuxes.  ckuus5.c, 28 Aug 2005.
+
+Fixed a warning in HP-UX 10 and 11 stemming from some old-style prototypes
+in ckutio.c for get[re][gu]id().  ckutio.c, 29 Aug 2005.
+
+Updated minix3 target from Andy Tanenbaum.  makefile, 29 Aug 2005.
+
+PeterE confirms that "long long" and off_t are available in all HP-UX 10 and
+11, and in HP-UX 9 on PA-RISC but not Motorola.  30 Aug 2005.
+
+Got 64-bit builds to work on HP-UX.  According to my notes, John Bigg of HP
+said (in 1999) that HP-UX 10.30 and later require PA-RISC 1.1, and do not
+work on PA-RISC 1.0.  But is PA 1.0 64-bit or what?  Today, Alex McKale of
+HP said "The 64-bit binaries will work on all machines that have the same or
+later release of HP-UX (excluding PA-RISC 1.1 machines)".  Still need
+clarification...  Maybe it's that all IA64 builds can be 64-bit but I need
+dual builds for PA-RISC.  Meanwhile I started transfer of a 4GB+ file from
+Solaris to HP-UX 11i but it exceeded some quota on the HP long before it
+approached the 2G point.  It failed cleanly and up until then it was working
+fine (numbers, stats, etc).  30 Aug 2005.
+
+Support of large files in 32-bit builds began in 10.20.  64-bit application
+support began in 11.00, but not all machines that run 11.00 support 64 bits.
+About long files, see HP /usr/share/doc/lg_files.txt.
+
+PeterE found that certain patterns can still make Kermit loop; example:
+
+  if match T01011-00856-21-632-073 *[abc] { echo GOOD } else { echo BAD }
+  if match T01011-00856-21-632-073 *[a-z] { echo GOOD } else { echo BAD }
+
+The minimum offending pattern is * followed immediately by an [xxx]
+construction, followed by anything else, including nothing.  Previous
+versions of Kermit handled this one correctly, without looping (but failed
+certain matches that should have succeeded).  The new section of code I
+added on 15 June, upon failure to match, advances the string pointer and
+backs up the pattern to the previous pattern, and starts again
+(recursively).  However, there needed to be a corresponding check at entry
+for an empty target string.  ckmatch(): ckclib.c, 12 Sep 2005.
+
+PeterE discovered that "kermit -y filethatdoesnotexit" gives an erroneous
+error message that names the user's customization, rather than the name
+given on the command line.  doinit(): ckuus5.c, 12 Sep 2005.
+
+FREAD does not get an error if it tries to read a record or file or piece of
+file that is too big for its buffer.  In particular, FREAD /SIZE:xxx seems
+to succeed even if less than xxx was read.  It should fail unless, perhaps,
+it successfully read up to the end of the file.  Furthermore, if xxx is
+bigger than the file buffer size, it should complain.  The buffer is
+line[LINBUFSIZ], 32K.  The lack of failure was due to code in dofile() that
+adjusted the given size silently if it was greater than the buffer size,
+which I removed, and also added a check when parsing the /SIZE: switch.
+dofile(): ckuus7.c, 12 Sep 2005.
+
+That still didn't help with FREAD /SIZE:n returning less than n bytes, even
+when they were available.  That's because the underlying routine, z_in(),
+didn't check fread()'s return code, which is the number of bytes read.
+If fread() has smaller buffers, it needs to be called in a loop.  z_in():
+ckuus7.c, 12 Sep 2005.
+
+Flen() fails on strings of length 8192 or more.  The limitation is in the
+callers of zzstring, which seem to be specifying an 8K buffer, in this case
+fneval().  The operable symbols are FNVALL (max length of value returned by
+a function) and MAXARGLEN (maximum length of an argument to a function).  I
+changed both of these for BIGBUFOK builds to be CMDBL.  Buffers can never be
+infinite, there has to be a limit.  It's important to make everything work
+consistently within that limit, and to make something useful happen when the
+limit is exceeded.  At this point, I can probably also increase the limits
+for modern 32-bit systems, and certainly for 64-bit ones.  Also there's no
+point in worrying about 16-bit platforms any more; earlier C-Kermit versions
+can still be used on them if necessary. ckuusr.h, 12 Sep 2005.
+
+Special #ifdefs for finding resolv.h and nameser.h in MINIX3 from Andy
+Tanenbaum.  ckcnet.c, 20 Sep 2005.
+
+PeterE noticed that ckmatch(), even though it works pretty well now, does a
+lot of extra and unnecessary recursion after determining the string and
+pattern do not match, at least when the pattern is of the form *[abc].
+After several false starts I was able reduce this effect to a minor level
+(but not eliminate it all together) by changing a while loop into a do loop.
+ckmatch(): ckclib.c, 15 Oct 2005.
+
+Added -DNOLONGLONG to HP-UX 8.00 and earlier builds, and to Motorola-based
+HP-UX 9.00 builds.  This is simply to inhibit the test for whether "long
+long" is supported by the compiler, since when it isn't, the module
+containing the test won't compile.  makefile, ckuus5.c, 16 Oct 2005.
+
+Making ASKQ always echo askterisks is a bad idea, because when it doesn't
+echo, it's the perfect way to read silently from stdin, e.g. in a CGI script
+(INPUT can also be used for this but it's not as straightforward).  So I put
+the default for ASKQ back to no echoing, then gave ASKQ its own switch
+table, which is the same as for ASK with the addition of an /ECHO:x switch,
+which tells what character to echo.  ckucmd.c, ckuus[26].c, 17 Oct 2005.
+
+Fixed a bug in FTP GET /COMMAND filename commandname; it always dumped core
+dereferencing a null string (the nonexistent local asname).  ckcftp.c,
+17 Oct 2005.
+
+For docs: if you don't like the funny business that happens when you type
+an IF command at the prompt, use XIF instead and it won't happen.  Also note
+that commands like "if xxx { echo blah } else { echo blah blah }" don't
+work when typed at the prompt; you have to use XIF for this. 
+
+Back to ckmatch()...  Under certain conditions (e.g. patterns like *[abc])
+failure to match would not stop the recursion because the string and pattern
+arguments are on the stack, as they must be, so there was no way for level
+n-1 to know that level n had detected a definitive nonmatch and that no
+further attempts at matching were required.  The right way to handle this is
+to recode the whole thing as coroutines, the cheap way out is with a global
+static flag.  Works perfectly, in the sense that the match.ksc test results
+are identical to what they were before and the extra backing up and
+recursion are eliminated.  (The Oct 15th fix wasn't really a fix, it broke
+a couple of cases.)  ckclib.c, 20 Oct 2005.
+
+ckuus7.c(2987): warning #267: the format string requires additional arguments
+(in PURGE command); fixed 20 Oct 2005.
+
+From Andy Tanenbaum, final changes for MINIX3: #ifdef out the inline
+definitions for gettimeofday() and readlink().  ckutio.c, 23 Oct 2005.
+
+From Jeff: struct gss_trials initializers changed from gss_mech_krb5 to
+ck_gss_mech_krb5.  ckcftp.c, 23 Oct 2005.
+
+From Jeff: some improvements to K95 GUI SHOW TERMINAL.  ckuus5.c, 23 Oct 2005.
+
+Found and corrected some misplaced #ifdefs in shofeat(), ckuus5.c, 23 Oct 2005.
+
+--- Dev.03 ---
+
+Fixed a compiler warning in a debug() statement in zzstring() by adding
+parens.  ckuus4.c, 24 Oct 2005.
+
+Added -DNOLONGLONG to sv68r3v6 target, makefile, 25 Oct 2005.
+
+New makefile targets for HP-UX from PeterE to handle the 'long long'
+situation.   26 Oct 2005.
+
+From Jeff: changes to support OpenSSL 0.9.8, ck_ssl.h.  ckcasc.h has had
+short names defined for ASCII control characters for 20-some years but now
+they are causing conflicts, so EM becomes XEM (also for OpenSSL 0.9.8).
+Changed K95's default terminal type from VT320 to VT220 because VT320
+termcaps/terminfos are disappearing from Unix hosts: ckuus7.c.  Reorganize
+the data-types section of SHOW FEATURES to add more macro tests for integral
+sizes and to provide for the proper printf formatting in order to allow the
+sizes to be output ("You are going to need to be careful because %llx is not
+supported on all platforms.  On Windows, it is the same as %lx, 32 bits"):
+ckuus5.c, 26 Oct 2005.
+
+Defined NOLONGLONG ckcdeb.h for various old platforms where we know we are
+never going to need 64-bit ints (even if they support a long long datatype,
+chances are pretty slim they supported 64-bit file sizes).  ckcdeb.h,
+26 Oct 2005.
+
+PeterE noticed that GOTO targets can only be 50 characters long.  This was
+by design, a long time ago, on the assumption that nobody would make longer
+labels.  But in SWITCH statements, case labels can be variables that expand
+to anything at all.  If we chop them off at 50, we might execute the wrong
+case.  Changed the maximum label size to be 8K, and added code to dogoto()
+to check when a label or target is too long and fail, to prevent spurious
+GOTO or SWITCH results.  ckuusr.h, ckuus[r6].c, 26 Oct 2005.
+
+Testing revealed there was still a problem with SWITCH case labels that were
+variables that expanded into long strings.  Turns out that I was being
+too clever when I decided that, if the SWITCH macro was n1 characters long
+and the case-label search target was n2 characters long, I only had to
+search the first n1-n2+1 characters of the macro definition.  That was true
+before I allowed case labels to be variables, but not any more!  Fixed in
+dogoto(): ckuus5.c, 26 Oct 2005.
+
+--- Dev.04 ---
+
+Dev.04 didn't actually contain Jeff's data-type changes to shofeat(),
+I think I saved the wrong buffer in EMACS...  Fixed now.  27 Oct 2005.
+
+PeterE corrected a typo in the HP-UX 7.00 makefile target.  27 Oct 2005.
+
+PeterE had been reporting problems stress-testing the new SWITCH code, but
+only on HP-UX 9, primarily stack overrun.  Turns out to be the HP-UX 9
+optimizing compiler's fault.  No optimization, no problems.
+
+PeterE found that even when dogoto() detects a string that is too long
+and fails, this does not stop SWITCH from producing a result, which can not
+possibly be trusted.  Changed the part of dogoto() that handles this to
+not just fail, but also to exit the script immediately and return to top
+level.  ckuus6.c, 28 Oct 2005.
+
+An idea popped into my head after having typed too many commands like "dir
+ck[cuw]*.[cwh]" to check the list of matching files, and then having to
+retype the same filespec in a SEND command: Why not unleash some unused
+control character such as Ctrl-K to spit out the most recently entered input
+filespec?  It was easy, just a few lines in cmifi2() and gtword(), plus a
+couple declarations.  To see all the changes, search for "lastfile" (all the
+new code is protected by #ifndef NOLASTFILE).  ckucmd.c, 28 Oct 2005.
+
+I added a new variable \v(lastfilespec) that expands to the same last
+filespec, for use in scripts.  ckuusr.h, ckuus4.c, 28 Oct 2005.
+
+The Unix version of C-Kermit failed to put anything in the session log if
+SET TERMINAL DEBUG ON.  Rearranged the pertinent clause so logging happens
+independent of TERMINAL DEBUG.  For now, since the user who noticed this
+wanted debug format to go into the session log, that's what I do.  The
+alternative would be to just log the raw incoming stream as usual, or to add
+Yet Another SET Command to choose.  ckucns.c, 11 Nov 2005.
+
+Fixed HELP INTRO text.  ckuus2.c, 11 Nov 2005.
+
+Added NOLONGLONG for SV68.  ckcdeb.h, 11 Nov 2005.
+
+--- Dev.05 ---
+
+Added a debug() statement in FTP secure_getbyte() to see what's going on
+with Muhamad Taufiq Tajuddin's 205-byte-per-second FTP/SSL downloads.
+
+--- Dev.06 ---
+
+Result: nothing, SSL_get_error() does not report any errors.  Suggested
+testing SSL_read()'s return code, if 0 don't update the screen.
+
+Created a new data type CK_OFF_T in ckcdeb.h that will eventually resolve
+to whatever each platform uses for file sizes and offsets.  ckcdeb.h,
+17 Nov 2005.
+
+Made a new library routine ckfstoa() that converts a file size or offset to
+a string.  This is to solve the problem with having to use different
+printf() formats for different representations of file size (int, long, long
+long, off_t, signed, unsigned, etc).  Replaced a few printf("%l",size) with
+printf("%s",ckfstoa(size)) with the expected results.  This is just a start,
+the definitions will need adjustment for many platforms, variables need to
+be redeclared, and all the offending printf's (and printw's) will have to
+hunted down and converted.  ckclib.[ch], ckuus4.c, 17 Nov 2005.
+
+Built a minimal version on Linux with:
+make linux "KFLAGS=-DNOLOCAL -DNOICP -DNOCSETS -DNODEBUG"
+Worked fine, result was 260K on i686.  21 Nov 2005.
+
+Discovered that Kermit's date parser, contrary to the documentation, failed
+to handle strings like "Wed, 13 Feb 2002 17:43:02 -0800 (PST)", which are
+commonly found in email.  This was because of an overzealous and misguided
+check in the code; once removed, all was well.  ckucmd.c, 26 Nov 2005.
+
+Added a new format code 4 to \fcvtdate() to emit asctime() format, used in
+BSD-format email message envelopes (i.e. the "From " line).  shuffledate(),
+ckucmd.c, ckuus[24].c, 26 Nov 2005.
+
+Added a new function \femailaddress().  Given a From: or Sender: header line
+from an RFC2822-format email address, extracts and returns the actual email
+address, such as kermit@columbia.edu.  ckuusr.h, ckuus[42].c, 26 Nov 2005.
+
+Using the new functions, I wrote a script to fetch mail from a POP3 server
+over a TLS connection.  But the line-at-a-time input (needed for changing
+line terminators and byte-stuffing text lines that start with "From ") is
+slow, 17 sec to read 29 messages totaling 175K.
+
+Added INPUT /CLEAR so INPUT can be started with a clean buffer without
+requiring a sepearate CLEAR INPUT command.  ckuusr.h, ckuus[r24].c,
+27 Nov 2005.
+
+One thing that INPUT was never able to do well was read and save the
+complete incoming data stream.  That's because, while waiting for its
+target, the buffer might overflow wrap around.  Yet there was never a way to
+tell it to stop when its buffer fills up and let me save it.  I added a
+/NOWRAP switch that does this.  If the buffer fills up before any other
+completion criterion is met, INPUT returns failure, but with \v(instatus)
+set to 6 (the next available instatus value).  Thus a program that wants to
+read and save (say) an email message from a POP server, which could be any
+length at all, and which terminates with <CRLF>.<CRLF> could do this:
+
+  set flag off
+  while open connection {
+      input /nowrap 10 \13\10.\13\10 # Wait for <CRLF>.<CRLF>
+      if success {
+          frwrite /string \%o {\freplace(\v(input),\13\10.\13\10,\13\10)}
+          set flag on
+          break
+      } else if ( == \v(instatus) 6 || == \v(instatus) 1 ) {
+          frwrite /string \%o {\v(input)}
+          continue
+      }
+      break
+  }
+  if flag (handle success)
+
+Note carefully the braces around the FWRITE text; without them, trailing
+spaces would be lost.
+
+Previously the only way to INPUT an entire data stream without losing
+anything (assuming it was ordinary lines of text that were not "too long"),
+was line-by-line:
+
+  while open connection {
+      input /clear 10 \13\10
+      if fail break
+      if eq "\v(input)" "$ \13\10" break
+      fwrite /string \%o {\freplace(\v(input),\13\10,\10)}
+  }
+
+The new code is 3 times faster using the default INPUT buffer length of 4K.
+Raising it to 16K makes it 3.6 times faster (not worth it).  Changing the
+POP3 script to use INPUT /NOWRAP makes it about twice as fast (it does more;
+it has to do all the byte-stuffing and unstuffing).  27 Nov 2005.
+
+Changed ssl_display_xxx() to just return if SET QUIET ON.  Otherwise there
+is no way to suppress the messages.  Also protected a previously unprotected
+printf("[SSL - OK]\r\n"); by if ( ssl_verbose_flag ).  ck_ssl.c,
+28 Nov 2005.
+
+Discovered that FOPEN /APPEND doesn't work if the file doesn't exist.  It
+uses cmiofi() which is a super-hokey front end to cmifi2().  I had code to
+call it but for some reason it was commented out, with a note to the effect
+it didn't work.  I uncommented it but that didn't help much.  So I wrote an
+entirely new cmiofi() that works exactly as it should, using chained FDBs,
+_CMIFI to _CMOFI (I think the original cmiofi() predated chained FDBs).
+ckuus7.c, ckucmd.c, 29 Nov 2005.
+
+Getting rid of the awful hacks required to call cmiofi() meant I also had to
+change the EDIT command, which is the only other place where it's used.
+Unfortunately now it's no longer possible to give EDIT without a filename
+(to just start an empty editor) but I doubt anyone will notice.  ckuusr.c,
+29 Nov 2005.
+
+IF KERBANG didn't always work right.  If a kerbang script TAKEs another
+kerbang script, the second one should have IF KERBANG false, but it didn't.
+Added a check for \v(cmdlevel) == 1.  Now you can write a wrapper that runs
+a kerbang script in a loop, and the latter can use IF KERBANG to know
+whether to EXIT (if called at top level) or END (if called by another
+script, thus allowing -- in this case -- the loop to continue).  ckuus6.c,
+29 Nov 2005.
+
+Changed \flop() and flopx() functions to take a third argument, a number
+signifying at which occurrence of the break character to lop, so:
+
+  \flopx(sesame.cc.columbia.edu) = edu
+  \flopx(sesame.cc.columbia.edu,,2) = columbia.edu
+
+ckuus[24].c, 1 Dec 2005.
+
+Built OK on VMS 7.2-1 with MultiNet 4.4.  Built with and without OpenSSL on
+Linux OK, ditto Solaris 9.  Built OK on RH Linux AS4 on X86_64 (64-bit);
+"show var fsize" (using new ckfstoa()) works OK there.  Also Mac OS X 10.3.9
+(32-bit), Tru64 UNIX 4.0F (64-bit), HP-UX 11iv2 (64-bit) (picky new compiler
+spews out tons of useless warnings), FreeBSD 6.0 on ia64 (64-bit).
+
+--- Dev.07 ---
+
+Changed "make netbsd" to be a synonym for "make netbsd2" because the
+original netbsd target was ancient.  Renamed it to netbsd-old.  makefile,
+3 Dec 2005.
+
+Updated INPUT and MINPUT help text.  ckuus2.c, 3 Dec 2005.
+
+Discovered that on a SET PORT /SSL connection, Kermit treats incoming
+0xff data bytes (e.g. sent from the POP server) as IACs and goes into Telnet
+negotiations.  Jeff says "You will need to implement NP_SSLRAW and NP_TLSRAW
+that do the same as NP_TCPRAW but negotiate SSL or TLS as appropriate."
+This was not as easy as it sounded, because apparently a lot of the Telnet
+code is used by SSL and TLS even when Telnet protocol is not being executed.
+I wound up doing this as follows: I added /SSL-RAW and /TLS-RAW to the
+switch table.  Rather than disable Telnet, they do exactly what the /SSL and
+/TLS switches do, but also set a special flag.  This flag is checked in only
+two place: netclos() (to prevent Kermit from sending TELNET LOGOUT when
+closing the connection), and tn_doop() (to prevent Kermit from reacting to
+incoming IACs; it makes tn_doop() return(3), which means "quoted IAC", which
+causes the caller to keep the IAC as data).  ckcnet.h, ckctel.h, ckctel.c,
+ckuus7.c, 4 Dec 2005.
+
+The INPUT command did not account for tn_doop() returning 3.  Fixed in
+doinput(), ckuus4.c, 4 Dec 2005.
+
+Added another debug() statement in FTP secure_getbyte() to see what's going on
+with Muhamad Taufiq Tajuddin's 205-byte-per-second FTP/SSL downloads, plus
+new code to test SSL_read()'s return code (byte count); if 0 don't update
+the screen.  ckcftp.c, 4 Dec 2005.
+
+--- Dev.08 ---
+
+Fixed a typo in the non-ANSIC definition of ckfstoa().  ckclib.c, 7 Dec 2005.
+
+Our Ctrl-C trap (the ON_CTRLC macro) wasn't working for kerbang files.
+Rearranged some code to make it work.  ckcmai.c, 8 Dec 2005.
+
+Started converting code to use CK_OFF_T for file sizes and offsets, and
+all [s]printf's to replace "%ld" or whatever with "%s", and the size
+variable with a call to ckfstoa().  Since I haven't actually changed the
+definition of CK_OFF_T from what all the size variables were to begin
+with (i.e. long), it shouldn't do any harm.  So far just ckcfn3.c
+10 Dec 2005.
+
+An updated HP-UX 9.xx makefile target from PeterE to fix a core dump that
+happens on that platform due to insufficient resources.  14 Dec 2005.
+
+Added debug() statements to http_blah() routines to tell whether the
+connection is "chunked".  There seems to be a bad performance problem.
+ckcnet.c, 14 Dec 2005.
+
+PeterE complained about ugly DIRECTORY error message, ?No files match -
+"{blah}".  The braces are used internally in case the user typed more than
+one filespec.  I changed the error message to remove them.  Ditto DELETE.
+ckuus6.c, 15 Dec 2005.
+
+The problem with HTTP downloads is that Kermit always does single-character
+read() or socket_read() calls (or the SSL equivalent); see http_inc().  I
+added buffering code for non-SSL connections only but it's gross because it
+has to swap ttyfd and httpfd before calling nettchk().  I tried making a
+nettchk() clone that accepts a file descriptor as an argument but it didn't
+work because too many other routines that are invoked directly or implicitly
+by nettchk() (such as in_chk()) are still hardwired to use ttyfd.  HTTP GETs
+are now 20 times faster on the local network (the improvement is less
+dramatic over a clogged Internet).  ckcnet.[ch], 15 Dec 2005.
+
+--- Dev.09 ---
+
+HTTP file-descriptor swapping is not thread safe.  Doing it right, of
+course, is a big deal, so for now I just don't define HTTP_BUFFERING for
+Windows.  ckcnet.c, 15 Dec 2005.
+
+Noticed that HTTP not included in FreeBSD and OpenBSD builds.  Fixed in
+ckcdeb.h, 22 Dec 2005.
+
+Fleshed out 32/64-bit data type definitions and changed struct zattr
+(file attribute structure) members length and lengthk to have the new
+CK_OFF_T type.  Changed final arguments of debug() and tlog() to be the new
+LONGLONG type.  ckcdeb.h, 22 Dec 2005.
+
+Changed ckfstoa() to return a signed number in string form, rather than an
+unsigned one.  That's because off_t is signed (thank goodness).  Added the
+inverse function, ckatofs() so we can convert file sizes and offsets back
+and forth between binary number and string.  ckclib.c, 22 Dec 2005.
+
+Changed Attribute Packet reader to convert incoming file size attribute
+with ckatofs() rather than atol().  ckcfn3.c, 22 Dec 2005.
+
+Converted debug(), tlog(), ckscreen(), etc, to handle potentially "long long"
+arguments by making their "n" argument CK_OFF_T.  ckuusx.c, ckcdeb.h,
+22 Dec 2005.
+
+Converted the rest of the source files to use CK_OFF_T for all file size
+and offset and byte-count related variables, and converted all references to
+these variables in printfs to go through ckfstoa().  Then I built it on
+Linux/i386 with:
+
+  make linux "KFLAGS=-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
+
+which makes off_t be 64 bits and magically makes all the regular file APIs
+use 64-bit sizes and offsets without changing the API calls in the source
+code.  It's going to be a lot of work to get through all the kinks but I was
+able to send a long file, do directory listings of long files, do
+\fsize(longfile), etc.  When it sends a file, the length is shown correctly
+in the A packet.  If the receiver does not support big numbers, it receives
+the file OK anyway, without showing the size, the thermometer, or percent
+done (and then will get an error when the file keeps coming after the 2G
+mark).  Kermit 95 actually refuses long files for "Size", but only if the
+announced is less than 2^63 bytes.  When today's Linux version receives a
+file, it shows the length correctly in the file-transfer display, as well as
+percent done, thermometer, etc.  Also built this version on true 64-bit
+Linux, and it worked fine.  Many files changed, 22 Dec 2005.
+
+For the record, this API is specified in X/Open's Single UNIX Specification
+Version 2, which is branded as UNIX 98.  It is called Large File Support, or
+LFS, and was developed at the Large File Summit.
+
+It looks like the operative feature-test macro in glibc for transitional
+large file support is __USE_LARGEFILE64.  So if this is defined, we can also
+supply _LARGEFILE_SOURCE and _FILE_OFFSET_BITS=64 automatically for 32-bit
+Linux builds.  But there's a Catch-22, you don't know if this is defined
+until you read the header files, but you have to define _LARGEFILE_SOURCE
+and _FILE_OFFSET_BITS before you read the header files.  Maybe it's good
+enough to grep through <features.h> for __USE_LARGEFILE64.  makefile,
+23 Dec 2005.
+
+Checked this on true 64-bit Linux.  The same symbols are defined in CFLAGS,
+but they do no harm; it builds without complaint and works fine.  24 Dec 2005.
+
+Built it on Red Hat Linux 6.1 from 1999.  This picked up the long file
+support too.  Guess 6.1 isn't old enough to not have it!  Kermit seems to
+work OK on regular files but I don't have enough disk space to create a long
+file, and my bigfile.c program (which creates a long file containing only 1
+byte) doesn't work ("fseeko: invalid argument").  It looks like parts of
+this API were visible in Linux before they were actually working.
+24 Dec 2005.
+
+Converted all fseek() and ftell() to macros that expand to fseek() and ftell()
+or fseeko() and ftello() depending on whether _LARGEFILE_SOURCE is defined.
+ckufio.c, ckuus7.c, ckuusx.c, 24 Dec 2005.
+
+Made a CK_OFF_T version of cmnum().  It would be a very big deal to just
+change cmnum() to return a new type, so another idea is to rename cmnum() to
+something else, cmnumw(), change its result argument to CK_OFF_T, and then
+make a stub cmnum() to call it to get an int, then call cmnumw() explicitly
+any time we need a big number.  ckucmd.c, 24 Dec 2005.
+
+Calling cmnumw() directly requires changes to each routine that uses it.
+The INCREMENT and DECREMENT commands, for example, required changes to
+doincr(), varval(), and incvar(), and all references to them.  ckuusr.[ch],
+ckuus[56].c, 24 Dec 2005.
+
+Calling cmnumw() in chained FDBs required defining a new function code,
+_CMNUW, adding a new member to the OFDB struct for returning wide results,
+and adding a new case to cmfdb().  ckucmd.[ch], 24 Dec 2005.
+
+Changed FSEEK and FCOUNT to use the new chained FDB interface, now we can
+seek and look past 2GB.  ckuus7.c, 24 Dec 2005.
+
+Next come switches, which store their results in a struct stringint.  This
+struct was defined in each module where it was used (ckuus[r367].c, ckcftp.c).
+I moved the definition to ckuusr.h and added a wval member, which can be
+referenced by any switch-parsing code that calls cmnumw().  24 Dec 2005.
+
+Changed SEND /CALIBRATE:n to allow big values of n.  This makes it possible
+to test the protocol aspects of long-file transfer without actually having a
+long file handy.  ckuusr.c, 24 Dec 2005.
+
+SEND /SMALLER-THAN:n, SEND /LARGER-THAN:n, and and SEND /START:n also now
+allow large values of n.  ckuusr.c, 24 Dec 2005.
+
+Changed the algebraic expression evaluator to use wide values.
+ckuus5.c, 24 Dec 2005.
+
+Fixed ckfstoa() to handle the case when n is negative and (0 - n) is also
+negative, which happens for numbers 2^(n-1) or greater, where n is the
+number of bits in the word size we're dealing with, e.g. 64, in which case
+2^63 has its sign bit set so seems to be negative.  In such cases, ckfstoa()
+returns "OVERFLOW" instead of a numeric string.  We'll have to see how this
+plays out but I think it's better to cause a parse error and stop things
+dead than to return a spurious number.  ckclib.c, 24 Dec 2005.
+
+Converted the S-Expression handler to use wide integers. ckuus3.c, 24 Dec 2005.
+
+Took all the LONGLONG stuff out of ckcdeb.h, we don't need it.
+
+All of these changes result in 64-bit arithmetic (more or less) on 32-bit
+Linux, as well as on true 64-bit platforms.
+
+Rebuilt today's code on Solaris 9 in the 32-bit and 64-bit worlds, on Red
+Hat 6.1, Red Hat AS4.2.  I haven't bothered trying a 32/64 hybrid build for
+Solaris, since I can build a pure 64-bit version there.  Quick tests show
+the large-number arithmetic works OK in all cases except, of course, on pure
+32-bit builds (unfortunately I can't find a running Linux system old enough
+to verify this for Linux, but it's true for other 32-bit platforms).
+24 Dec 2005.
+
+Tried building a hybrid version on Solaris 9 after all since the LFS API is
+ostensibly the same as for Linux:
+
+ make solaris9 "KFLAGS=-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
+
+It built smoothly and the resulting binary is 2.5MB compared to 3.4MB for
+the 100% 64-bit version.  Looks like a keeper.  For now, added solaris9lfs
+and solaris10lfs entries to the makefile but if these work on PCs we can
+make these the regular entries for Solaris 9 and 10.  27 Dec 2005.
+
+Built on Mac OS X 10.4 with the regular target.  It seems that in that case,
+off_t is 64 bits anyway.  Noticed that a lot of stuff didn't work, like
+exponentiation in S-Expressions.  Tried building it as above, which worked,
+and now CK_OFF_T is 64 bits instead of 32, but (^ 2 30) is still 2.0.  In
+fact 2-to-the-any-power is 2.0.  It seems that the Mac OS X version did not
+have FNFLOAT defined.  It also seems that every test in dosexp() like:
+
+  if (result != fpresult) fpflag++;
+
+should have been protected by #ifdef FNFLOAT..#endif /* FNFLOAT */ -- a
+double-ended break, as they say in the nuclear power industry.  ckuus3.c,
+27 Dec 2005.
+
+Added GREP /EXCEPT:pattern.  ckuus[26].c, 27 Dec 2005.
+
+Fixed a problem with uninitialized pv[].wval (switch-parsing parameter-value)
+members that showed up on certain platforms or with certain compilers.  Now
+the Mac OS X 10.4 version works.  ckuus[r367].c, ckcftp.c, 28 Dec 2005.
+
+Built on Unixware 7.1.1, a pure 32-bit build, seems fine.  Rebuilt on Red
+Hat AS 4.2 just to make sure I didn't break anything, it's OK.  No testing
+on HP-UX, etc, because HP testdrive file sytem is full, can't upload anything.
+29 Dec 2005.
+
+Commented out the SHOW FEATURES section that displays constants like
+INT_MAX, CHAR_MAX, etc, because printing each value in the appropriate
+format is too tricky, and we don't need them anyway.  ckuus5.c, 29 Dec 2005.
+
+Updated ckvfio.c to use CK_OFF_T for the relevant variables.  Built and
+tested on VMS/Alpha 7.2: file transfer in remote mode; making a Telnet
+connection and then local-mode file transfer; S-Expressions, all OK.  Also
+built a no-net version OK.  29 Dec 2005.
+
+Built and tested on Red Hat AS4 AMD X86_64, used it to upload new sources to
+FreeBSD 4.11.  Built on FreeBSD 4.11/i386.  Here's another one where off_t
+is 64 bits, even though long is 32 bits.  But it seems to work ok, not sure
+why, when CK_OFF_T is 32 bits.  There is no _LARGEFILE_SOURCE stuff in the
+header files.  29 Dec 2005.
+
+Built on Mac OS X 10.3.9 using the new macosx10.4 target to pick up LFS.
+Works fine.
+
+Built on Red Hat Linux 4WS on IA64 (64-bit).  Now this one is odd, stat()
+fails on big files.  It happens also if I use the "linuxnolfs" target, which
+does not define _USE_LARGEFILE or _FILE_OFFSET_BITS=64.  DIRECTORY BIGFILE
+shows the size as -1, but if "log debug", it says "no files match", i.e.
+different behavior, observer effect.  I hate when that happens.
+
+Let's see if that's an anomoly...  Built on Tru64 Unix 4.0F (64-bit Alpha).
+It sees long files just fine.  Rebuilt and checked on x86_64 again... fine.
+OK, let's not worry about IA64 yet.
+
+Another small fix to the HP-UX 9.0 target from PeterE.  makefile, 29 Dec 2005.
+
+---Dev.10---
+
+Code adjustments from Jeff, mainly to the SSL and TLS Raw mode code from
+several weeks ago, plus changing some data types in the security code to
+CK_OFF_T, plus a different data type for CK_OFF_T for K95 because Windows
+size_T isn't signed.  This presumably will allow large-number arithmetic but
+it will not give large file access because that will require replacing all C
+library file i/o calls (esp. in ckofio.c) with native Windows APIs.  Build
+on Solaris 9 with and without SSL and on Linux RH AS4.2 with and without
+SSL.  ck_crp.c, ck_ssl.c, ck_ssl.h, ckcdeb.h, ckcftp.c, ckcmai.c, ckcnet.c,
+ckcnet.h, ckctel.c, ckuat2.h, ckuus4.c, ckuus7.c, ckuusr.c, 30 Dec 2005.
+
+It was reported that WRITE SESSION always returned a failure status, even
+when it succeeded.  The problem was that Unix versions of zsout() and
+zsoutl(), for the session log only, were using write() and returning
+write()'s return code, which is different from what zsout() and zsoutl() are
+documented to return.  Also plugged a couple potential holes in zsoutx()
+that I noticed while I was in the neighborhood.  ckufio.c, 30 Dec 2005.
+
+Added FSEEK /FIND:pattern.  This form of FSEEK accepts all the other
+switches and arguments and performs the desired seek.  Then, if the seek was
+successful, it starts from that point and reads through the file, line by
+line, searching for the first line that contains the given string or matches
+the given (unanchored) pattern and, if found, sets the file pointer to the
+beginning of that line.  Useful, e.g., for very long timestamped logs, where
+you want to start processing at a certain date or time; searching for a
+particular string is much faster than doing date comparisons on each line.
+ckuus[27].c, 30 Dec 2005.
+
+It was annoying me that FILE STATUS (FSTATUS) required a channel number to
+be given even if only one file was open, so I supplied the correct default
+in that case.  ckuus7.c, 30 Dec 2005.
+
+INPUT /NOWRAP, added recently, is used for efficiently copying the INPUT
+stream intact, but it's not good for matching because if the INPUT target is
+broken between the end of the previous buffer and the beginning of the next
+one, the context is lost and the match does not occur.  I thought of several
+ways around this, but they all involve saving a huge amount of context --
+old input buffers, the arrays of target strings and corresponding match
+positions, etc.  The alternative is fairly simple but it's not transparent
+to the user.  Here's what I did in a POP script:
+
+    .eom := "\13\10.\13\10"
+    set flag off                           # FLAG ON = success
+    while ( open connection && not flag ) {
+        .oldinput := \fright(\v(input),8)  # Save tail of previous INPUT buffer
+        input /clear /nowrap 4 \m(eom)     # Get new INPUT buffer
+        if success {                       # INPUT matched - good
+            .s := {\freplace(\v(input),\m(eom),\13\10)}
+            set flag on
+        } else {                           # No match
+            .s := \v(input)                # Check if target crossed the border
+            .oldinput := \m(oldinput)\fsubstr(\v(input),1,8)
+            if \findex(\m(eom),\m(oldinput)) set flag on
+        }
+        ...
+    }
+
+I think this will be easier to explain than any dangerous and grotesque
+magic I might put into doinput() itself.  For now, added a few words about
+this to HELP INPUT.  ckuus2.c, 30 Dec 2005.
+
+Back to the pattern matcher.  Noticed that "IF MATCH index.html [a-hj-z]*"
+succeeded when it should have failed.  In ckmatch(), the clist section
+needed one more clause: it can't float the pattern if an asterisk does not
+occur in the pattern before the clist.  This change fixes the problem
+without breaking any other cases that weren't already broken, most of which
+involve slists, i.e. {string,string,string,...}.  ckclib.c, 30 Dec 2005.
+
+Tried FSEEK /FIND: on a largish file (over 100,000 lines), using it to seek
+to a line near the end.  It took 0.756 seconds, compared with Unix grep,
+which did the same thing in 0.151 sec.  That's because C-Kermit is using
+ckmatch().  But if the search target is not a pattern, it should be a bit
+faster to use ckindex().  Yup, 0.554 sec, a 36% improvement.  Can't expect
+to compete with grep, though; it's highly tuned for its single purpose.
+ckclib.[ch], ckuus7.c, 1 Jan 2006.
+
+Updated visible copyright dates to 2006: ckcmai.c, ckuus2.c, ckuus5.c,
+1 Jan 2006.
+
+Noticed that NetBSD 2.0.3 has 64-bit off_t, and that _LARGEFILE_SOURCE is
+mentioned in <stdio.h>.  Tried building Kermit with _LARGEFILE_SOURCE added
+to CFLAGS, it's good.  Added it to the netbsd target.  makefile, 1 Jan 2006.
+
+Fixed typo, #ifdef CK_NOLONGLONG in ckuus5.c should have been #ifndef
+CK_LONGLONG (which, it turns out, we don't use anyway).  2 Jan 2005.
+
+Observed that FreeBSD 4.x has a 64-bit off_t, but does not use the
+_LARGEFILE_SOURCE convention.  Reasoning that all versions of FreeBSD have
+off_t (I was able to check back to FreeBSD 3.3), I simply #define CK_OFF_T
+to be off_t in ckcdeb.h within #ifdef __FreeBSD__ .. #endif.  Another one
+down.  This can be done for any platform that is guaranteed to have off_t.
+Turns out FreeBSD 3.3 has 64-bit off_t too.  2 Jan 2005.
+
+OpenBSD, same as FreeBSD.  Also, added OS-version-getting thing to makefile
+target for the program herald, as in the other BSDs.  Built on OpenBSD 2.5
+from 1998, it has 64-bit off_t too.  ckcdeb.h, makefile, 2 Jan 2005.
+
+Dumping the command stack every time there's an error is really too much.
+I added SET COMMAND ERROR-DISPLAY {0,1,2,3} to set the verbosity level of
+error messages.  Only level 3 dumps the stack.  ckuus[235].c, 2 Jan 2005.
+
+Built on HP-UX 11.11 with _LARGEFILE_SOURCE and _FILE_OFFSET_BITS=64.  The
+result works fine as far as I can tell.  It sees big files, it can open
+them, seek to positions past the 2^31 boundary.  It can send large files.
+It can do large-number arithmetic (^ 2 62).  The only problem is that during
+compilation, every single modules warns:
+
+  cc: "/usr/include/sys/socket.h", line 504: warning 562: Redeclaration of
+  "sendfile" with a different storage class specifier: "sendfile" will have
+  internal linkage.
+  cc: "/usr/include/sys/socket.h", line 505: warning 562: Redeclaration of
+  "sendpath" with a different storage class specifier: "sendpath" will have
+  internal linkage.
+
+These warnings should be perfectly harmless since they are not coming from
+C-Kermit code, nor does C-Kermit use either one of those functions.  These
+warnings don't come out in HP-UX 11i v2, but on that one we get tons and tons
+of picky compiler warnings (variables set but not used, defined but not
+referenced, etc).  A couple, however, turned out to be valid; one case of
+"expression has no effect", and two of "string format incompatible with
+data type" (I missed a couple file-size printfs).
+
+There were also numerous warnings about signedness mismatch or sign
+conversion of constants like IAC (0xff).  Does the HP-UX Optimizing Compiler
+have a compiler flag to make all chars unsigned?  Yes, +uc, but the man page
+says "Be careful when using this option.  Your application may have problems
+interfacing with HP-UX system libraries and other libraries that do not use
+this option".  Sigh, better not use it.
+
+After reviewing "HP-UX Large Files White Paper Version 1.4" and HP's
+"Writing Portable Code" documents, I added -D_LARGEFILE_SOURCE
+-D_FILE_OFFSET_BITS=64 to the hpux1000 target, which is the basis for all
+HP-UX 10.00 and later builds.  Large files are available in HP-UX 10.20 and
+later.  10.00 and 10.10 were not real releases, and anyway these flags
+should be harmless there unless the large-file implementation was only
+partly done.  Built OK on both PA-RISC and IA64, optimized and plain.
+makefile, 4 Jan 2006.
+
+Built on FreeBSD 6.0 on IA64.  All OK except I got a warning about the
+argument passed to time() in logwtmp() in ckufio.c.  This section had
+already been partially fixed; thus I put the improved version into
+#ifdef CK_64BIT, which is our newly available symbol that should be
+automatically defined for any true 64-bit build.  ckufio.c, 4 Jan 2006.
+
+Finally got around to testing Jeff's changes to SSL/TLS RAW mode from
+December 30th against our POP server.  It didn't work, couldn't log in.
+Tried backing off the ckctel.c changes first; that allowed login and
+communication, but it did not suppress activation of Telnet protocol
+whenever a 0xff byte arrived.  Backed off the rest of the changes and now
+all is OK again.  ckctel.c, ckcnet.c, ckuus7.c, 9 Jan 2006.
+
+Built on NetBSD 1.4.1 (1999), found that it did not like the large file
+assumption -- fseeko() and ftello() do not exist; added a clause to the
+netbsd target to check for fseeko and not define _LARGEFILE_SOURCE if not
+found.  Oddly enough, off_t is 64 bits anyway, but it doesn't look like the
+APIs are half-done.  For example, stat() uses off_t (64 bits) for the file
+length, but fseek() uses long (32 bits) and there is no 64-bit analog.
+Anyway the new netbsd target works on both 1.4.1 and 1.5.2 (no large files)
+and on 2.0.3 (large files).  makefile, 9 Jan 2006.
+
+Built on QNX-32 4.25, which has no large file support.  Got a few strange
+compiler (WatCom) warnings, but it built and runs OK.  Noticed that file
+transfers into QNX over a Telnet connection can't use streaming, but that's
+nothing new to this version; same thing happens with C-Kermit 7.0.  9 Jan 2006.
+
+Built on IRIX 6.5.  I didn't bother with large files there because it does
+not support the _LARGEFILE_SOURCE interface; you have to change all the APIs
+at the source level from blah() to blah64().  Seems to work fine as a 32-bit
+app even though its off_t is 64 bits.  Tried a pure 64-bit IRIX 6.5 build
+but it dies in ckcnet.c when it hits SOCKOPT_T and GSOCKNAME_T with "The
+identifier 'socklen_t' is undefined".
+
+Looks like I no longer have access to SCO OSR5.
+
+Made a pure 32-bit build on SCO UnixWare 7.1.4, all OK.  Found that this
+version also supports LFS, added it to the uw7 target.  makefile, 9 Jan 2006.
+
+--- Dev.11 ---
+
+Evidently the HP-UX bundled (non-ANSI non-optimizing) compiler doesn't like
+long integers in switch expressions.  Changed three examples of these in the
+S-expression code.  ckuus3.c, 10 Jan 2006.
+
+A section of tstats() where GFTIMER isn't defined (e.g. on Motorola
+sv68r3v6) was garbled.  Fixed in ckcfn2.c, 10 Jan 2006.
+
+A fix for setting 921600 bps on Linux from Paul Fulghum, Microgate Systems Ltd.
+ttgspd(): ckutio.c, 11 Jan 2006.
+
+Noticed that when I changed the compact substring notation code back on
+August 9th, I broke the ability to use arithmetic expressions within the
+brackets, which explains some rather odd behavior I saw with some of my
+scripts.  Looking more deeply into this, I also see that all the parsers I
+have been using up to now for this, as well as for array bounds pairs, have
+been inadequate because they never allowed for nested constructions, such as
+a member of a bounds pair that itself was an array element, possibly with
+another array element as a subscript.  I wrote a new routine for this,
+called boundspair(), which is like arraybounds() except it accepts an extra
+argument, an array of characters that can serve as bounds-pair delimiters,
+and it returns the pair separator that was encountered in another new
+argument.  For the alternative substring notation for [startpos-endpos] I
+had to change the delimiter from '-' to '_' because '-' can be used in
+arithmetic but '_' is not a recognized operator.  This is so I can parse,
+e.g. [a:b] or [a_b] in the same context, and then find out which form was
+used, e.g. \s(line[9:12]) or \s(line[9_12]); the first string is 4 bytes
+long, the second is 12.  Everything seems to be OK now.  \s(line[10]) gives
+everything starting at 10, but \s(line[10:0]) gives the null string.  Bad
+syntax in the bounds pairs results in a null string; missing pieces of the
+bounds pair result in defaults that should be compatible with previous
+behavior.  ckuus[45].c, ckuusr.h, 13 Jan 2005.
+
+Changed arraybounds() to call boundsdpair().  This was a rather drastic
+change, not strictly necessary, but I think I got all the kinks out.
+ckuus5.c, 13 Jan 2005.
+
+Changes from PeterE to the makefile for HP-UX 6 and 7, to accommodate bigger
+symbol tables, etc.  19 Jan 2005.
+
+Determined that SCO OSR5.0.6 (and earlier) do(es) not support large files.
+Don't know about 5.0.7.  30 Jan 2005.
+
+Created a new build target for SCO OSR6.0.0.  Gets the exact 6.x.x version
+dynamically.  Supports large files and big-number arithmetic via CK_OFF_T.
+The sockopt() family of functions changed the data types of some of their
+arguments since OSR5.  It was already possible to define SOCKOPT_T and
+GSOCKNAME_T from the command line but I had to add code to also allow this
+for GPEERNAME_T too.  ckcnet.c, makefile, 30 Jan 2005.
+
+Apparently, ever since C-Kermit 7.0 was released, it has never been possible
+to use a variable for the as-name in a RECEIVE command in Kermit 95.  This
+is because evaluation of the as-name field was deferred until after we could
+check whether it might be a directory name (which, in Windows, could start
+with a backslash).   This little bit of magic was not a good idea, magic
+hardly ever is.  I changed the code to evaluate both as-name fields in the
+normal way.  If they want to receive to a directory called "\%1", they'll
+just have to spell it differently.  The workaround is to turn the whole
+command into a macro and evaluate it before executing it, e.g.:
+
+  assign xx receive /as-name:\%1
+  do xx
+
+ckuus6.c, 1 Feb 2006.
+
+Built OK on FreeBSD 6.1 on AMD64.  Adjusted some copyrights and date stamps.
+ckcmai.c, makefile, 8 Feb 2006.
+
+--- Dev.12 ---
+
+Fixed a signed/unsigned char warning in the new boundspair() calling code
+in the compact substring notation handler.  ckuus4.c, 9 Feb 2006.
+
+Removed a spurious extra linux+openssl label from the makefile, added
+solaris10g_64 synonym.  9 Feb 2006.
+
+Satisfied myself that LFS is OK on Solaris 10 i386, and I'm going to assume
+it's also OK on Solaris 9.  Made LFS standard for all Solaris 9 and 10
+builds (including the secure ones) except the explicitly 64-bit ones, and
+made the provisional solarisXXlfs targets into synonyms.  makefile, 9 Feb 2006.
+
+--- Dev.13 ---
+
+Further attempts at SSL/TLS message suppression when QUIET is ON.
+ck_ssl.c, 16 Feb 2006.
+
+From J.Scott Kasten: (quote...) I just uploaded a patch to /kermit/incoming.
+The file name is "jsk-patch-for-cku211.diff".  I have also included the
+patch as ASCII text in this email below.  This patch may be applied to the
+cku211.tar.gz source code via:
+  cd cku211, patch -p1 <../jsk-patch-for-cku211.diff
+The patch adds 4 new build targets:
+  netbsdwoc - a stripped no curses target for iksd used.
+  netbsdse  - security enhanced target with srp, ssl, and zlib.
+  irix65gcc - build on SGI Irix 6.5 platform using gcc.
+  irix65se  - security enhanced target with srp, ssl, and zlib.
+The patch fixes one build target:
+  irix64gcc - The "-s" option is not supported by gcc under Irix.
+I thank all of you in the Kermit Project for such a fine utility.  I
+recently had to get a 16 MB file overseas across a spotty communications
+link to repair a computer remotely.  Kermit was the only thing that could do
+the job, so I wanted to contribute these patches back to the mainstream to
+say thanks.  This digitally signed email is a binding contract that
+officially assigns the rights to the source code patch (shown below) that I
+developed to the Kermit Project at Columbia University. (...end quote)
+ck_ssl.c, makefile, 23 Feb 2006.
+
+Changed the new NetBSD target names to be consistent with the conventions
+used in most other targets:
+
+  netbsdwoc -> netbsdnc
+  netbsdse  -> netbsd+ssl+srp+zlib
+  irix65se  -> irix65+ssl+srp+zlib
+
+and removed old, now superfluous, NetBSD targets (old-netbsd, netbst15,
+netbst16), leaving synonym labels in their place.  Also updated (crudely)
+the Linux target variations (curses instead of nocurses, no curses at all)
+to be (appropriately modified) copies of the current linux target.  It would
+be nicer to combine them, but this gets the job done.  makefile, 23 Feb 2006.
+
+--- Dev.14 ---
+
+Fixed the HELP command when used with tokens like @, ^, #, and ;.  The first
+two had been omitted from the table.  The second two required a new path
+into the guts of the parser, since comments are normally stripped at a very
+low level.  ckuus[r2].c, ckucmd.c, 24 Feb 2006.
+
+Built on AIX 5.1 ("make aix51") without incident.  Then I tried:
+
+ make aix51 "KFLAGS=-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
+
+This had no effect.  I found the relevant document ath the IBM website.  It
+says to use -D_LARGE_FILES instead.  I added this to the AIX 4.2 target
+since (a) IBM says large files are supported by AIX 4.2 and later, and (b)
+all Kermit AIX targets past 4.2 use the 4.2 one.  Plus a clause to make
+sure CK_OFF_T is defined appropriately.  ckcdeb.h, makefile, 6 Mar 2006.
+
+Added a 32-bit aix51+openssl target.  Builds OK, works fine (tested against
+our SSL POP server).  Tried I tried adding -D_LARGE_FILES.  It seems to work
+fine, so we'll keep it.  Cleaned up the other aix5blah entries a bit also.
+makefile, 6 Mar 2006.
+
+Fixes from J. Scott Kasten to the IRIX 6.4 and 6.5 makefile targets.  They
+were badly wrong.  makefile, 6 Mar 2006.
+
+The reason Kermit was looping on directories in IRIX was a classic
+"double-ended break".  The makefile targets failed to define DIRENT so
+Kermit was open/read on directories rather than opendir()/readdir().  But
+then it was also failing to account for the fact that read() would return -1
+on error.  The makefile fix adds -DDIRENT, and the read() case in traverse()
+now properly terminates its loop on error.  ckufio.c, 6 Mar 2006.
+
+--- Dev.14 ---
+
+In response to a complaint that C-Kermit would not build on HP-UX 11 with
+OpenSSL, I tried it myself on both 11.11/PA-RISC and 11i v2/Itanium.  It built
+OK on both but I had to add a new target (hpux1000o+openssl-nozlib) for no
+Zlib since these boxes did not have it installed.  makefile, 9 Mar 2006.
+
+Added OpenSSL version number display to SHOW FEATURES.  ckuus5.c, 9 Mar 2006.
+
+Gavin Graham noticed that FTP [M]GET /DELETE /MOVE-TO: was rejected with
+"?Sorry, /DELETE conflicts with /MOVE or /RENAME".  This check belongs in the
+PUT code but not in the GET code.  Commented it out and tested the result.
+The combination is now accepted but then Kermit refuses the incoming file as
+if it had been given a /SMALLER-THAN: or /LARGER-THAN: switch, which it didn't
+happen.  Turns out there was one more place where I wasn't initializing the
+new "wide int" member of the switch-parsing pv[] struct.  Once this was fixed,
+the /MOVE-TO part still didn't work.  Turned out the /DELETE case was part of
+a long if-else-if-else- chain, which effectively made /DELETE and /MOVE-TO: or
+/RENAME-TO: mutually exclusive.  Fixed this, now it works fine.  ckcftp.c,
+13 Mar 2006.
+
+Got access to AIX 5.3, built there, all OK, including large files. 13 Mar 2006.
+
+--- Dev.16 ---
+
+Patches from Mark Sapiro to suppress getsockopt() and getsockname() warnings
+in Mac OS X.  ckcnet.[ch], 18 Mar 2006.
+
+In response to a complaint from Clarence Dold, tried "make redhat9" (which
+is the rather dated target that tried to include all forms of security) on
+RH Linux AS4.3, it failed miserably.  I made a new makefile target, removing
+Kerberos IV and got a lot farther.  But then in ckcftp.c, the following
+struct definition:
+
+  struct {
+      CONST gss_OID_desc * CONST * mech_type;
+      char *service_name;
+  } gss_trials[] = {
+      { &ck_gss_mech_krb5, "ftp" },
+      { &ck_gss_mech_krb5, "host" },
+  };
+
+refers to a variable, ck_gss_mech_krb5, that is not defined anywhere.  Up
+above, however, is a static definition for gss_mech_krb5, so I changed the
+struct definition to match.  Next, in ckuath.c, the compiler could not find
+the com_err.h file.  Turns out in Linux this is in a subdirectory, et, so we
+have to add a -I clause to the makefile target for this.  Made a target for
+Linux+SSL only.  Made a target for Linux+Krb5 only; this required moving an
+#ifdef in ckuus7.c to prevent an unguarded reference to SSLEAY_VERSION.
+New targets: linux+krb5+ssl, linux+krb5, linux+krb5.  ckcftp.c, ckuus7.c,
+makefile, 27 Mar 2006.  
+
+New targets of HP-UX 10/11 with OpenSSL from PeterE.  makefile, 27 Mar 2006.
+
+Added large file/integer support to SHOW FEATURES.  ckuus5.c, 27 Mar 2006.
+
+Built OK on Solaris 9 and 10 with gcc (someone was complaining that this
+didn't work, but that was 8.0.211).
+
+Started build on a Sun 3/80 mc68030 with NetBSD 2.0 and gcc 3.3.3.  But it
+died with an assembler error in ckcfn2.c (compiler bug).  27 Mar 2006.
+
+--- Dev.17 ---
+
+NebBSD 2.0 build completed by turning off optimization on ckcfn2.c
+("KFLAGS=-O0").  Result supports 64-bit ints and, presumably, large files.
+uname -p = "m68k", -m = "sun3". 29 Mar 2006.
+
+Corrected an omission in applying PeterE's updates to the HP-UX targets.
+makefile, 28 Mar 2006.
+
+solaris2xg+krb5+krb4+openssl+shadow:
+
+Tried resurrecting the solaris2xg+krb5+krb4+openssl+shadow target.  It asks
+to link with libdes but there is no libdes.  Removed -ldes from the target,
+now at least it builds and runs wart.  The compilation blows up in ckcftp.c
+for missing header files:
+
+  ckcftp.c:462: kerberosIV/krb.h: No such file or directory
+  ckcftp.c:500: gssapi/gssapi_generic.h: No such file or directory
+  ckcftp.c:501: gssapi/gssapi_krb5.h: No such file or directory
+
+Got a bit farther by adding appropriate -I's and -L's to KFLAGS but it still
+dies compiling (or linking?) ckcftp.c, but it doesn't say exactly why.  OK,
+deferred.
+
+Added SET SEXPRESSION TRUNCATE-ALL-RESULTS { ON, OFF }.  This can be used
+for force integer arithmetic in any kind of calculation that requires it,
+such as date calculations.  This is a global setting, not on any kind of
+stack.  Also, updated SHOW SEXP and added HELP SET SEXP which wasn't there
+before.  ckuus[23].c, 30 Mar 2006.
+
+To make the RENAME command a bit more useful, need to add some switches.
+But it shares a switch table, qvswtab[], with some other commands.  Broke
+this off into its own switch table.  ckuus6.c, 17 Apr 2006.
+
+Added RENAME switch values that can be used in the same table with the DELETE
+switch values, which are shared by many commands.  ckuusr.h, 17 Apr 2006.
+
+Discovered that the RENAME command could be entered without any arguments
+and it would still succeed.  Fixed in dorenam(): ckuus6.c, 17 Apr 2006.
+
+Added parsing for RENAME /UPPER:option (to uppercase the file name(s)),
+/LOWER:option (to lowercase), and /REPLACE:{{s1}{s2}} (to do string
+replacement on the filename(s)), but not the semantics.  When any of these
+switches is given, the target ("to") name is not parsed; they act on the
+source name.  The /LOWER: switch takes keyword args to specify whether it
+should act only only files that have all UPPER case latters, or on ALL files
+(i.e., including files with mixed-case names); similarly for the /UPPER:
+switch.  There is some creative parsing allowing these to be given with or
+without a colon and keyword argument, which works fine except if you include
+the colon but no argument, execute the command (which works fine), and then
+recall the command.  I haven't yet decided about the interaction among these
+switches.  Clearly if /UPPER is given after /LOWER, it overrides.  But if
+/UPPER (or /LOWER) is given with /REPLACE, what should happen?  ckuus6.c,
+17 Apr 2006.
+
+Filled in actions for RENAME /UPPER: and /LOWER: for the single file case,
+and tested all combinations of switch values and filename configurations.
+Once that was OK, moved the code out into a separate routine, renameone(),
+and then called it from both the single-file case and the multifile case.
+ckuus6.c, 19 Apr 2006.
+
+Added RENAME /SIMULATE.  Filled in the code for string replacement, needs
+testing.  ckuus6.c, 20 Apr 2006.
+
+Changed /REPLACE options to allow a negative number to specify an occurrence
+from the right, so -1 means the last occurrence, -2 means the next-to-last,
+etc.  ckuus6.c, 24 Apr 2006.
+
+Added RENAME /COLLISION:{OVERWRITE,PROCEED,FAIL}.  This is implemented but
+not tested.  ckuus6.c, 24 Apr 2006.
+
+Worked on RENAME /COLLISION:FAIL.  I decided it was less than useful to ...
+
+Added SET RENAME { COLLISION, LIST } to let user change default collision
+and listing actions.  ckuusr.[ch], ckuus[36].c, 25 Apr 2006.
+
+Experimented with parsing for /CONVERT:cset1:cset2.  The problem here is
+that there is no straightforward way for a switch to have multiple
+arguments.  Or is there...?  If I parse cset1 with cmswi() rather than
+cmkey(), it almost works; the only problem is that the character-set
+keywords don't have CM_ARG set, so they don't know to stop on, and ignore, a
+colon.  If I make a copy of the table and set CM_ARG in the flags field for
+each keyword, it works fine: if I Tab in the first name, it fills itself
+out, supplies a colon, and waits for the second name.  So in the code, the
+first time that RENAME /CONVERT is invoked, I put code to copy fcstab[] and
+set CM_ARG in each flags field.  Works fine, and now we know how to make a
+switch that takes multiple arguments.  ckuus6.c, 24 Apr 2006.
+
+I thought I had a function to convert the character set of a string but I
+don't, so actually implementing /CONVERT: will be difficult.
+
+Actually the parsing wasn't that easy either.  It works OK interactively,
+but not in a TAKE file.  To make a long story short, I had to change
+gtword() and cmkey2() to not require "/" at the beginning of a switch, and
+then to parse arguments-that-are-followed-by-other-arguments as if they were
+switches, so that they can end with colon rather than space.  This might
+seem dangerous, but switches always have "/" at the beginning, so the check
+is superfluous.  ckucmd.c, 26 Apr 2006.
+
+Back to /CONVERT...  Once I was able to get the code to call cvtstring() I
+was able to debug it (at first it was skipping every second character).  And
+now we have a general-purpose string-translating function we can call from
+anywhere.  Requires that C-Kermit be built with Unicode support.
+ckuus6.c, 26 Apr 2006.
+
+Added SHOW RENAME.  ckuusr.h, ckuus[r5].c, 26 Apr 2006.
+
+Conditionalized some Unix/Windows assumptions in renameone() so the code
+could work in VMS.  ckuus6.c, 2 May 2006.
+
+Added RENAME /FIXSPACES to change all spaces in the filename(s) to
+underscore or any other character or string that is given.  This is just a
+special case of RENAME /REPLACE:{{ }{x}} with easier syntax.
+ckuusr.h, ckuus6.c, 2 May 2006.
+
+Added an "all-but" control to the /REPLACE options:
+/REPLACE:{{.}{_}{~1}} means replace all but the first (this one works);
+/REPLACE:{{.}{_}{~-1}} means replace all but the last (this one not yet).
+ckuus6.c, 2 May 2006.
+
+Filled in the second one ("all but" the given occurrence).  The algorithm is
+simply to reverse the three strings and then use the same code as we use in
+the left-right-case, and then unreverse the result.  At first I used
+yystring() for this but yikes, what a bad design!  So I made a better
+string-reversal routine, gnirts(), for this (luckily yystring() is only used
+in one place, for which its design is appropriate). ckuus6.c, 3-4 May 2006.
+
+Added code to handle the case where the file being renamed includes a path
+specification.  In this case we separate the path, apply the renaming
+functions to the filename only, and then at the end rejoin the original
+filename with the path, and join the new name with same path or, if a
+destination directory was given, with that.  ckuus6.c, 4 May 2006.
+
+Added HELP SET RENAME and updated HELP RENAME.  ckuus2.c, 4 May 2006.
+
+"Tom Violin" (Tom Hansen) noticed that the first time you FOPEN a file,
+Kermit's memory consumption goes way up.  In fact there's a warning to that
+effect in the code, where, upon first open, a potentially big array of
+potentially big structs is allocated.  I rewrote the code to allocate each
+array member (struct ckz_file) as needed, i.e. when a file is opened, and to
+free it when the file is closed (or the open fails).  This was actually
+quite a lot of work, which is why I didn't do it the first time around:
+every single "."  had to be changed to "->".  Every check for a valid
+channel first had to check if the channel's struct was allocated and every
+other reference to z_file[i]->anything had to be prechecked that z_file[i]
+was not a NULL pointer.  Also I made some improvements to FILE STATUS, and I
+fixed FILE CLOSE to default the channel number if only one channel was open,
+as I did for FILE STATUS a while back.  ckuus7.c, Cinco de mayo 2006.
+
+Ran my old BUILDS script that builds C-Kermit with about 100 different
+combinations of feature-selection switches.  Fixed a few small glitches so
+now they all build OK (except can't do NOANSI builds any more on recent
+Linuxes because of varargs()).  ckuus3.c, ckuus5.c, ckuus6.c, ckuus7.c,
+ckucmd.c, ckcfns.c, 6 May 2006.
+
+Fixed RENAME /LOWER and /UPPER, when given with no colon or agrument, to
+default to ALL.  ckuus6.c, 13 May 2006.
+
+Built on VMS 7.2-1, tested new RENAME command there; seems to be OK.
+13 May 2006.
+
+--- Dev.18 ---
+
+I wanted to test large files against RESEND but I don't have access to any
+system that can run C-Kermit and that also has enough space for a large
+file.  I created a "fake" large file on Linux (3G hole plus 1 byte), and
+sent it over a localhost connection, and interrupted it repeatedly and then
+initiated a RESEND at the sender.  In each case, it picked up where it left
+off.  But before the 2G boundary was crossed the disk filled up.
+Inconclusive.  14 May 2006.
+
+PeterE got a warning in the new FILE OPEN code when building in HP-UX 9.
+I added a cast, built on HP-UX 11, no more complaint.  However there
+are warnings about internal vs external bindings of sendpath and sendfile
+in every module.  Too bad, these are not Kermit tokens, it's a conflict in
+HP's header files.  Marc Sapiro doesn't see them; probably it's something
+on the HP testdrive site.  ckuus7.c, 17 May 2006.
+
+Fixed the tru64-51b+openssl target -- the terminating doublequote of KFLAGS
+was missing -- and also the osf target, which failed to import the LIBS
+definition from whatever other target invoked it.  Now the SSL build goes OK
+on Tru64 5.1B.  Replaced x.tar.z in the download areas without declaring a
+new Dev number.  The new one has a makefile with today's date.  Software
+engineering at its best!  makefile, 18 May 2006.
+
+Scott Kasten noted that the estimated-time-remaining calculation would go
+bonkers on LFS systems when RESENDing a large file.  It looks like the
+shocps() and shoetl() functions escaped the CK_OFF_T conversion.  I made
+what seemed to be the right adjustments, and then was lucky enough to find a
+computer that had enough free disk space for me to send a large file,
+interrupt it several times, resend it, all seems to be OK.  28 May 2006.
+Later Scott verified these changes independently for Linux, but the problems
+in IRIX remain.
+
+Patches from Scott Kasten for large files on IRIX 6.5: ckcdeb.h, makefile,
+12 Jun 2006.
+
+--- Dev.19 ---
+
+Added a new function for dealing with JPGs and GIFs:
+
+\fpicture(filename,&a)
+  returns 0 if file not recognized or can't be opened;
+  returns 1 if landscape, 2 if portrait or square.
+  If array given, element 1 is width, element 2 is height.
+
+ckuusr.h, ckuus4.c, 19 Jun 2006.
+
+Scott Kasten reports that the FTP client can transfer large files OK, at
+least in Linux, but has trouble with recovery:
+
+ . Kermit takes a very long time to start the transfer, sometimes over
+   30 minutes.  Suspect the ftp server is counting the bytes in a long file?
+   Or maybe it's a text-mode transfer and it's counting the lines?  Probably
+   in response to Kermit's SIZE command.
+
+ . The size shown in the FT display is wrong by a random amount.  And of
+   course so are the progress bar, percent done, and time remaining.
+
+ . The file, however, is transferred correctly.  REGET works correctly too.
+
+I tried setting up a test scenario locally but our Solaris FTP server does
+not support large files:
+
+  FTP SENT [SIZE BIGFILE]
+  FTP RCVD [550 BIGFILE: not a plain file.]
+  FTP SENT [PASV]
+  FTP RCVD [227 Entering Passive Mode (128,59,48,24,246,37)]
+  FTP SENT [RETR BIGFILE]
+  FTP RCVD [550 BIGFILE: Value too large for defined data type.]
+
+Created the same 3GB on a Tru64 Unix system that allows FTP access.  Made
+the connection from C-Kermit on Solaris (32-bit with LFS):
+
+  16:46:12.908 FTP SENT [SIZE BIGFILE]
+  16:46:12.947 FTP RCVD [213 3000000001]
+
+Note that it takes less than half a second to get the reply.  Now I start
+the download and then interrupt it at about 2%:
+
+  16:46:12.979 FTP SENT [TYPE I]
+  16:46:13.174 FTP RCVD [200 Type set to I.]
+  16:46:13.226 FTP SENT [PASV]
+  16:46:13.262 FTP RCVD [227 Entering Passive Mode (15,170,178,171,11,37)]
+  16:46:13.299 FTP SENT [RETR BIGFILE]
+  16:46:13.337 FTP RCVD [150 Opening BINARY mode data connection for BIGFILE..]
+  16:47:24.895 FTP RCVD [426 Transfer aborted. Data connection closed.]
+  16:47:24.934 FTP RCVD [226 Abort successful]
+  16:47:24.991 FTP SENT [MDTM BIGFILE]
+  16:47:25.028 FTP RCVD [213 20060706204458]
+
+Now I do a REGET:
+
+  16:51:55.321 FTP SENT [PASV]
+  16:51:55.357 FTP RCVD [227 Entering Passive Mode (15,170,178,171,11,43)]
+  16:51:55.394 FTP SENT [REST 122736640]
+  16:51:55.430 FTP RCVD [350 Restarting at 122736640. Send STORE or RETRIEVE..]
+  16:51:55.431 FTP SENT [RETR BIGFILE]
+  16:51:55.469 FTP RCVD [150 Opening BINARY mode data connection for BIGFILE..]
+
+This worked perfectly, as far as I can tell; the FT display picked up in the
+right place; the thermometer, percent done, and estimated time remaining
+were the same as when we left off last time.  I did the same thing several
+more times, everything was OK.  It would have taken a really long time to
+let this run to completion, but I think this demonstrates that Scott's
+symptoms are server-dependent.  No changes.  6 July 2006.
+
+Checked current code on VMS 8.2-1 on IA64 / UCX 5.5, builds fine.
+No changes.  Updated listing at HP.  6 July 2006.
+
+Checked FTP GET of large file in ASCII mode against Tru64 FTP server.  It
+was fine, and there was no delay in the server's response to our SIZE command
+(as there would be if it were scanning the entire file to count how many
+bytes would be required to send it in text mode).  7 Jul 2006.
+
+Tested FTP PUT big file against Tru64, OK.  Ditto FTP RESEND big file:
+
+  C-Kermit>resend BIGFILE
+   PUT BIGFILE (binary) (3000000001 bytes)---> PASV
+  227 Entering Passive Mode (15,170,178,171,13,186)
+  ---> SIZE BIGFILE
+  213 343211280
+  ---> MDTM BIGFILE
+  213 20060707141243
+  ---> APPE BIGFILE
+  150 Opening BINARY mode data connection for BIGFILE (128.59.59.56,45470).
+
+Made REPUT a synonym for RESEND.  ckuusr.c, 7 Jul 2006.
+
+Added FTP REPUT and FTP RESEND since previously there was no FTP-prefixed
+command for recovering uploads, only the regular RESEND command, which might
+not have been obvious to people.  ckcftp.c, 7 Jul 2006.
+
+Added help text for FTP RESEND and REPUT and amended RESEND help text.
+ckcftp.c, ckuus2.c, 7 Jul 2006.
+
+Changed name of \fpicture() to \fpictureinfo() and added help text.  By the
+way, ImageMagick can do this too: identify -format "%w %h" dscf0520.jpg.
+The advantage of having it in Kermit is that not everybody has ImageMagick.
+ckuus[24].c, 7 Jul 2006.
+
+Changed the numeric comparisons = < > <= >= != to allow long integers by
+changing the data type to CK_OFF_T, etc.  ckuus6.c, 7 Jul 2006.
+
+Noticed that \fkeywordvalue(foo=this is a string) only kept the first word.
+Fixed it to keep the whole definition.  Also added \fkwvalue() as a briefer
+synomym.  ckuus4.c, 7 Jul 2006
+
+Sometimes we want to check if a file's status before we've FOPEN'd it, in
+which case the channel variable is likely to be empty and \f_status(\%c)
+would get an error.  Making the obvious change didn't fix this, however.  It
+turns out that the function evaluator failed to adjust argn (argument count)
+when trailing arguments were empty, and argn was being used in this case,
+and probably others, to test whether an argument existed.  I added code to
+adjust argn to reflect the number of aruments up to and including the
+rightmost non-empty one.  ckuus4.c, 7 Jul 2006.
+
+Fixed \fstripb() to not dump core if second argument is missing.
+ckuus4.c, 7 Jul 2006.
+
+Discovered that it was not obvious what pattern to use to match strings
+enclosed in square brackets.  "if match [abc] \[*\]" didn't work.  Neither
+did various other tricks like NCRs for the brackets.  However, "if match
+[abc] \\[*\\]" does work.  Trying to fix this would no doubt break 100 other
+things, so let's call it a feature.  7 Jul 2006.
+
+Added \fgetpidinfo(n) to return info about a process ID; for now it simply
+returns 1 if the process is alive and 0 if not (or -1 if the argument is
+bad or missing or on any kind of error).  ckuusr.h, ckuus[24].c, 7 Jul 2006.
+
+The "where-did-my-file-go" message seemed to be ending with a LF rather
+than CRLF, probably because the terminal modes had not yet been restored,
+leaving the next prompt hanging below it, rather than on the left margin,
+if C-Kermit exited immediately after the transfer.  Fixed by changing
+all \n's to \r\n's in wheremsg(): ckcpro.w, 8 Jul 2006.
+
+Added \v(lastkwval) so we can retrieve programmatically the keyword most
+recently processed by \fkeywordval().  ckuusr.h, ckuus4.c, 9 Jul 2006.
+
+--- Dev.20 ---
+
+Added #ifdef SV68, #include <unistd.h>, #endif because Unix System V/68 on
+Motorola choked on the SEEK_CUR reference without it.  ckuus4.c, 10 Jul 2006.
+
+Make \fkeywordval(xxx) undefine xxx (i.e. when a keyword is given with no
+value).  This way command-line keywords will always override preexisting
+default definitions, whether they have a value or not, which makes it easier
+to parse command lines like "foo=bar blah xx=yy".  ckuus[24].c, 12 Jul 2006.
+
+On 29 Nov 2005 I changed IF KERBANG to solve a problem (see entry for that
+date), but introduced a new one; namely that you can't have (e.g.)  a FATAL
+macro that uses IF KERBANG to decide whether to EXIT all the way or STOP
+back to the prompt.  Changed it again, this time to require not that the
+command level be 1, but that the command *file* level be 0 (i.e. that we are
+in the top-level command file, irrespective of the command or macro level,
+but not in a subfile).  ckuus6.c, 12 Jul 2006.
+
+It is unhelpful when Kermit gets a syntax error in the middle of a big
+compound statement block (e.g. FOR or WHILE loop) and dumps out the whole
+thing in an error message.  I changed the two places where this can happen
+to call a new routine that, instead of dumping out the entire cmdbuf,
+checks its length first and if it's more than a line long, truncates it
+and adds an ellipsis.  ckuus6.c, 12 Jul 2006.
+
+The new RENAME command didn't give very good error messages, e.g. if the
+filespec didn't match any files.  Fixed in dorenam(): ckuus6.c, 12 Jul 2006.
+
+Fixed DIR /TOP to work if the /TOP:n argument was omitted, defaulting
+to 10.  domydir(): ckuus6.c, 12 Jul 2006.
+
+Added DIR /COUNT:v to count the number of files that match the given
+criteria and store result in the variable v.  ckuusr.h, ckuus[r26].c,
+24 Aug 2006.
+
+Added HDIRECTORY as an invisible synonym for DIR /SORT:SIZE /REVERSE.
+Can be used with other switches, of course, so (e.g.) HD /TOP shows the
+ten biggest files.  ckuusr.h, ckuus[r26].c, 24 Aug 2006.
+
+DIR /FOLLOWLINKS and /NOFOLLOWLINKS always did the same thing; the switch
+was ignored, a symlink is always followed.  Fixed in ckuus6.c, 24 Aug 2006.
+
+Added DIR /NOLINKS, which means don't show or count symlinks at all.
+ckuusr.h, ckuus[r26].c, 24 Aug 2006.
+
+Build on Solaris 9 and NetBSD 3.0, 24 Aug 2006.
+
+Added a missing definition for LOCK_DIR in the Linux HAVE_BAUDBOY case,
+suggested by Gerry Belanger.  ckutio.c, 6 Oct 2006.
+
+Suggested by Jim Crapuchettes: \v(dialmessage) is the text string
+corresponding to \v(dialstatus).  ckuusr.h, ckuus4.c, 6 Oct 2006.
+
+Soewono Effendi sent code for exit sequence to leave DTR on; this amounted
+to unsetting HPUCL in c_cflag.  I did it a simpler way, hopefully portable
+to all Unixes, but who knows at this late date.  The code is inside
+#ifndef CK_NOHUPCL..#endif in case it causes trouble.  It is executed if
+SET EXIT HANGUP is OFF and a serial port was open at the time Kermit exits
+(or closes it explicitly).  ttclos(): ckutio.c, 6 Oct 2006.
+
+Built on Solaris9/Sparc; FreeBSD 6.2/AMD64; NetBSD 3.0/i386; HP-UX 11i v2;
+SCO OSR6.00.
+
+--- Dev.21 ---
+
+Added netbsd+openssl target to makefile.  Built OK (NetBSD 3.0, OpenSSL
+0.9.7d) except with some warnings in ck_crp.c.  Connects and logs in OK to a
+secure site.  10 Oct 2006.
+
+Added a debug statement to ftp_hookup() to record the TCP port that was used.
+ckcftp.c, 11 Oct 2006.
+
+Built with OpenSSL 0.9.7l on Solaris 9.  Built with OpenSSL 0.9.8d on
+Solaris 9; connects and logs in to a secure site.  11 Oct 2006.
+
+The new RENAME command didn't work if both the source and destination names
+included directory segments, e.g. "rename /tmp/foo ~/bar" (see notes of
+4 May 2006).  This was fixed in renameone() by a special case in which
+the second argument is given but it is a filename, not a directory name.
+ckuus6.c, 11 Oct 2006.
+
+Fixed unguarded reference to dialmsg[] for \fdialmessage(), noticed by
+Gerry Belanger.  ckuus4.c, 12 Oct 2006.
+
+Added a TOUCH command that does what UNIX touch does: creates the file if it
+does not exist, updates the timestamp if it does.  If a wildcard is given,
+it operates only on existing files.  It shares the DIRECTORY command parser,
+so all the same file selection switches can be given.  ckuusr.[ch],
+ckuus[26].c, 12 Oct 2006.
+
+PeterE noticed that if you FOPEN a file, do some seeks or reads, then FCLOSE
+it, then FOPEN it again (or open a different one), some of the old
+information is still there (e.g. current line number).  This is an artifact
+of the changes of May 4th.  Now the file closing and opening routines are a
+bit more careful about scrubbing and initializing the file info struct.
+ckuus7.c, 12 Oct 2006.
+
+--- Dev.22 ---
+
+Built OK on Red Hat Linux AS4 with both "make linux" and "make linuxnc". 
+15 Oct 2006.
+
+DIRECTORY /BRIEF ignored file selection switches and always listed all
+files.  This was because of how I cleverly called filhelp() (the routine
+that lists matching files when ? is typed in a filename field) and, of
+course, filhelp() doesn't know anything about the DIRECTORY command's file
+selections.  Changed filhelp() to accept all the args needed for passing
+along to fileselect(), renamed it to xfilhelp(), and made a filhelp() stub
+that chains to xfilhelp() with null selections.  ckcker.h, ckucmd.[ch],
+ckuus6.c, 29 Nov 2006.
+
+SHOW CONNECTION for an SSH connection said the connection type was "NET"
+rather than "SSH".  Fixed in dolognet(): ckuus3.c, 29 Nov 2006.
+
+SHOW CONNECTION didn't show the TCP port number.  This command works by
+parsing the current connection log entry string, which doesn't have a field
+for this, but which sometimes shows the port number as part of the hostname
+(but more often not).  Added code to dolognet() to log the TCP port number,
+if known.  This involved adding a gettcpport() function to ckcnet.c.
+ckcnet.[ch], ckuus3.c, 29 Nov 2006.
+
+This was impossible: def \%1 upper, echo \f\%1(abc) -- i.e. to "compose" a
+function name.  Fixed in zzstring().  But note that it's still not possible
+to do this: def \%1 \fupper, echo \%1(abc) -- because at the point where
+"\fupper" is encountered, which is automatically fed to fneval(), the
+argument list hasn't been read yet.  ckuus4.c, 29 Nov 2006.
+
+The meaningless Lisp command (=) would cause Kermit to hang.  Due to some
+idiosyncracy in the parser, it would see this as ((=) and would go into
+"wait for the closing paren" mode.  There was already a hack in the code to
+compensate for this, but it didn't work.  I fixed the hack but I don't
+understand the real problem.  Anyway, comparing Kermit with real (Franz)
+Lisp I discovered that comparison operators do not require two arguments, as
+Kermit has been doing, although they do require at least one.  I changed
+Kermit to not require two, so now all the comparison predicates behave
+exactly like Franz Lisp, including getting an error if there are no args).
+ckuus[r3].c, 29 Nov 2006.
+
+From to-do list: Make a way to inhibit pattern matching in SWITCH labels.
+It's already there; just quote the wildcard characters; the only trick is
+that for some reason (such as that SWITCH is really an internally defined
+macro), a double quote is needed:
+
+  switch \%1 {
+    :a\\*z, echo literally "a*z", break
+    :abcxyz, echo literally "abcxyz", break
+    :a*z, echo a...z, break
+    :default, echo NO MATCH
+  }
+
+In first case, the asterisk is taken literally; in the third it's a
+metacharacter and the label matches any string that starts with 'a' and
+ends with 'z'.
+
+Array initializion would quit early if any initializers were undefined,
+e.g. "decl \&a[] = \%a \%b \%c" would stop at the first element if \%b
+was not defined, even though \%c might be defined.  Fixed in dodcl():
+ckuusr.c, 30 Nov 2006.
+
+DIR /ARRAY:a filespec, when the filespec does not match any files,
+terminates with the array undeclared.  It would be better to return a
+declared but empty array (\&a[0] = 0).  The code is already there to do
+that, but isn't working.  And yet "declare \&a[0]" does indeed create a
+0-element array ("show array" shows a dimension of 0).  Turns out there were
+two problems; one was the careless recycling of a local variable ("array"),
+resulting in failure to create \&a[] (but not any other array).  Fixed in
+domydir(): ckuus6.c, 30 Nov 2006.
+
+The other problem was that dclarray(), when called with an array name and a
+dimension of zero, does two different things depending on whether the array
+already existed.  There is still a fair amount of confusion about whether a
+dimension of 0 indicates an array with 1 element (as it should) or a
+nonexistent array.  We call dclarray() with a size of 0 to undeclare an
+array but we also need to able able to declare an array with only element 0.
+I changed dclarray() to treat a negative dimension as a command to destroy
+the array, and 0 or positive as a command to create the array with the given
+dimension.  ckuus[r56].c, 30 Nov 2006.
+
+Next problem: when chkarray() returns 0, this should not be interpreted to
+mean the array does not exist.  Looks like the only place this happened was
+in \fcontents(); fixed in ckuus4.c, 30 Nov 2006.
+
+If we include file selectors with DIR /ARRAY:&a and some of the files that
+match the given filespec but don't fit the selectors, the array's dimension
+is bigger than its number of elements.  Added code at the end of domydir()
+to resize the array so \fdim() returns the number of filenames in the array,
+and also made sure that element 0 contains that number too.  ckuus6.c,
+30 Nov 2006.
+
+This would be a nice elegant way to loop over a bunch of files, if it worked:
+
+  for \%i 1 \ffiles(*) 1 { rename \fnextfile() xxx_\flpad(\%i,3,0) }
+
+But in this loop, Kermit skips every other file (beginning with the first)
+and then runs out of files halfway through the loop.  Why?  Because in
+commands like RENAME and DELETE, the filename parser is in a chained FDB
+with the switch parser.  First the switch parser, cmswi(), gets its hands on
+\fnextfile(), passing it through the evaluator and thus getting the first
+filename, which it then sees is not a switch, so now the field is parsed by
+the next parser in the chain, cmifi(), which causes \fnextfile() to be 
+executed again.  In fact, the FOR loop has nothing to do with; the same
+thing happens like this:
+
+  void \ffiles(*)
+  delete \fnextfile()
+
+This deletes not the first file, but the second one.  Obviously users can be
+told not to refer to \fnextfile() in chained-fdb fields:
+
+  for \%i 1 \ffiles(*) 1 { .f := \fnextfile(), delete \m(f) }
+
+but this is hardly intuitive.  I had some clever ideas of how to make
+\fnextfile() work as expected in this context but it's way too much magic.
+Better to simply document that \fnextfile() is "deprecated" and the array
+format should be used:
+
+  for \%i 1 \ffiles(*,&a) 1 { delete \&a[\%i] }
+
+The difference is, an array element doesn't change every time it's referred to!
+
+Added a /PRESERVE switch to the COPY command to preserve the timestamp and
+permissions of the file.  I did this using the Kermit APIs so it should work
+for any version of C-Kermit or K95.  ckuus[26].c, 30 Nov 2006.
+
+Added COPY /OVERWRITE:{ALWAYS,NEVER,OLDER,NEWER} to control name collisions
+when copying across directories.  ckuus[26].c, 1 Dec 2006.
+
+--- Dev.23 ---
+
+Fixed a bug in SET TELNET PROMPT-FOR-USERID, SET AUTH KERBEROS[45] PROMPT,
+and SET AUTH SRP PROMPT in which the user's string was compared with a
+literal (s == ""), reported by Pavol Rusnak.  Worse, empty strings (if the
+test succeeded) were turned into null pointers, and then fed to strlen().
+Fixed in ckuus3.c, 5 Dec 2006.
+
+Added an optional 4th argument to \findex(), \frindex(), \fsearch(), and
+\frsearch(): the desired occurrence number of the searched-for string.
+\frsearch() was a bit tricky.  ckuus[24].c, 7 Dec 2006.
+
+Added \fcount(s1,s2) to tell the number of occurrences of s1 in s2.
+ckuus[24].c, 8 Dec 2006.
+
+Added \ffunction(s1) to tell if a given built-in function is available.
+ckuus[24].c, 8 Dec 2006.
+
+Changed RENAME /COLLISION:PROCEED to be /COLLISION:SKIP, which is clearer.
+ckuus[26].c, 8 Dec 2006.
+
+For communication protocols: INPUT /COUNT:n to read exactly n characters
+without any matching.  Can be used, for example, with CONTENT_LENGTH in CGI
+scripts; NUL characters are counted but not collected.  ckuusr.[ch],
+ckuus4.c, 8 Dec 2006.
+
+There was a bad bug in the date-parsing routines; it's been there for years.
+If a date string includes a timezone, e.g. "Sat, 9 Dec 2006 19:26:23 EST",
+and converting to GMT changes the date, the variables for day, month, and
+year (which are used later) were not updated, and the final result was a day
+off.  Fixed in cmcvtdate(): ckucmd.c, 10 Dec 2006.
+
+Built OK with SSL/TLS.  Tested with the POP script, found that I broke INPUT
+when adding the /COUNT feature; there was a path through the code that could
+leave the "anychar" variable unset and therefore random.  Fixed in
+doinput().  The POP script, which does not use /COUNT, works again and so
+does a new CGI script, which does use /COUNT.  ckuus4.c, 10 Dec 2006.
+
+Supplied a missing comma in the help-text array for HELP SET TERMINAL, which
+resulted in bad formatting in K95 around SET SNI-FIRMWARE-VERSIONS.
+ckuus2.c, 10 Dec 2006.
+
+Made "help locus" a synonym for "help set locus".  ckuusr.[ch], ckuus2.c,
+11 Dec 2006.
+
+This morning the Columbia FTP server was malfunctioning in a perfect way
+for me to implement and test an FTP timeout mechanism.  The server would
+close the data connection after sending the file, but the client never saw
+the close and was stuck forever in a recv().  I added code to do a select()
+on the data connection prior to entering the recv(), with a timeout on the
+select() that the user can establish with SET FTP TIMEOUT.  Built and tested
+on Solaris 9, clear-text FTP.  Also built cleanly for FTPS and tested
+against a server that does not hang; I don't have access to an FTPS server
+that would tickle the timeout code.  ckcftp.c, 11 Dec 2006.
+
+--- Dev.24 ---
+
+Fixed a bug in the INPUT /COUNT: parser: the array of search strings was
+never initialized, which didn't matter before, but with /COUNT:, if the
+first element was not a NULL pointer, we'd treat it as a search string, and
+then if it happened to match something in the input stream, the operation
+would stop before the count was exhausted.  Fixed by (a) initializing the
+array, and (b) ignoring any search strings if /COUNT: was given.  ckuusr.c,
+13 Dec 2006.
+
+Removed a debug() statement from zsattr() that suddenly started making some
+version of gcc complain, reported by Gerry Belanger.  ckufio.c, 13 Dec 2006.
+
+--- Dev.25 ---
+
+Some casts for the 3 interior args of the new select() call in ckcftp.c
+for HP-UX 9.  14 Dec 2006.
+
+Changed \fkeywordvalue() to accept a string rather than a single word
+as its second argument, so that more than one separator could be specified,
+and to return -1 on error, 0 if it found nothing, 1 if given a kewyord but
+no value, and 2 if there was a keyword and a value.  dokwval(): ckuus[24].c,
+14 Dec 2006.
+
+Checked FTP timeout on command channel with FTP DIRECTORY of a big directory
+using a path into our ftp server that preserves the hanging behavior.  The
+timeout was actually working, but the failure condition wasn't propogating
+back to the user, and there was no error message.  Fixed in doftprecv2() and
+failftprecv2(): ckcftp.c, 15 Dec 2006.
+
+Added the obvious timeout checks for FTP uploads, but I have no way to test
+the code since our misbehaving FTP server does not hang when receiving
+files, only when sending them.  But uploads work both with and without a
+timeout set, so at least no harm is done.  ckcftp.c, 17 Dec 2006.
+
+When downloading with FILE DESTINATION NOWHERE (= /CALIBRATE), Kermit still
+checked the size of the incoming file and refused it if there wasn't enough
+free disk space, on platforms (such as VMS) where zchkspa()) actually works;
+reported by Bob Gezelter.  ckcfn3.c, 18 Dec 2006.
+
+Built on Mac OS X 10.4.8 and NetBSD 3.1_RC3, all OK.  19 Dec 2006.
+
+--- Dev.26 ---
+
+Built on VMS 7.3-2/Alpha.  Had to squelch a couple compiler warnings by
+changing some ints in the new \fpictureinfo() code from unsigned to signed,
+and fix a typo in the prototype for the new gettcpport() function.
+ckcnet.h, ckuus4.c, 22 Dec 2006.
+
+--- Dev.27 ---
+
+Parameterized pty routines and all references to them for file descriptor,
+rather than to use global ttyfd, thus allowing ptys to be created for
+different purposes.  Tested on Solaris 9 and Mac OS X 10.4.8, with "set host
+/connect /pty emacs" (fine in both cases), and (more to the point) "set host
+/connect /pty kermit" -- here we make a connection from one Kermit process
+to another and transfer a file; works fine and wasn't especially slow either;
+a good sign.  ckcdeb.h, ckutio.c, ckupty.c, 22 Dec 2006.
+
+Created a new version of ttruncmd() called ttyptycmd(), which works by
+calling do_pty() to get a pty to run the command on, and then in a loop,
+reads from the pty and writes to the net and reads from the net and writes
+to the pty, using select() to which of those it should do on each pass.
+First cut just uses single-byte reads and writes.  Tested using Kermit
+itself as an external protocol.  Works but slowly: 6000cps.  Zmodem doesn't
+work at all.  ckutio.c, 24 Dec 2006.
+
+Changed single-character read() and write() to buffered reads and writes,
+with ttxin() and ttol() used for network i/o.  Using Kermit as the external
+protocol, this gives 450Kcps (about 1/3 normal on this connection).  
+
+But now there's a problem: the loop doesn't know when to stop.  How does it
+know when the process that is running on the pty has exited?  With single
+character read()'s that are executed unconditionally when select() says the
+pty has data waiting, as in the first pass, I get EIO if there actually
+isn't any, and can exit the loop.  But now, to avoid blocking, I call
+in_chk() to see how much data is waiting, and I don't try to read anything
+if it says nothing is waiting.  If the process associated with the pty file
+descriptor has terminated, in_chk() would presumably get some kind of error,
+but it doesn't.  I changed do_pty to return the pid of the fork where it
+execs its command so we can check the pid with kill(pid,0) when in_chk() of
+the pty says 0, but this doesn't help either; it seems like the process is
+not exiting, but of course it is.
+
+I could not find any legitimate way to test when the pty fork terminated.
+Select() always says the pty file descriptor was ready, no matter what.
+Select() never reports an exception on the pty file descriptor;
+in_chk(ptyfd) returns 0 and not an error.  read(ptyfd,...) gets 0 but not an
+error.  fcntl(ptyfd,...) doesn't get an error.  Finally I tried
+write(ptyfd,c,0) and this indeed gets EIO (i/o error).  With this, using
+Kermit as the external protocol works fine in Solaris but I tend to think
+this trick will not be very portable (it isn't).  24 Dec 2006.
+
+Made ttptycmd() use a more intelligent buffering scheme, fixed a few things
+about how I was setting up the select() call that should address some of
+yesterday's problems.  Still doesn't work but it's progress.  A: 25 Dec 2006.
+
+Debugging yesterday's code...  Still, the error conditions are never set,
+we never detect when the pty closes.  In Solaris, if select() says ptyfd is
+ready to read but in_chk() says there are no characters there, we can treat
+this as a loop-exit condition.  But in NetBSD, in_chk() always says 0 when
+used on a pty (but works OK on a serial or net connection).
+
+Realized I could not use in_chk() on the pty because there is too much
+baggage with the communication path -- myread(), etc etc) -- so I replaced
+this with a simple ioctl(ptyfd,FIONREAD,&n).  This works fine in Solaris but
+always returns 0 in NetBSD, despite what the man page says (i.e. that this
+function can be used on any file descriptor).
+
+OK, let's see.... select() does not return useful results.  It says
+characters are waiting on ptyfd when they are not, and it never detects the
+closure of the pty.....  Well of course not, because we are the ones who
+have to close it.  Just because the process has stopped doesn't mean the pty
+is closed.  So we're back to square one, how do we know when to close it?
+ckupty.c seems to keep the process ID in a global variable, pty_fork_pid
+(which is not the same as the pid now returned by do_pty(), which is
+useless, but I don't understand why).  But it doesn't matter because when we
+kill(pty_fork_pid,0), we still get no error of any kind, even after we know
+the process has exited.  I am completely flummoxed.  select() lies, and even
+if it didn't, there is simply no completion criterion.  In the loop,
+select() always says that the pty is ready to read.  To be continued.
+26 Dec 2006.
+
+Back to Square One, single-byte reads and writes.
+
+ . This works for both ripple and Kermit.
+ . Doesn't work for Zmodem but we'll deal with that later.
+ . In this case FD_ISSET(ptyfd) is still true after pty closes.
+
+But the ensuing read() gets EIO so we know the pty is gone.  That means the
+same thing should happen in the buffered version, no?  Yes; I went back to
+the buffered version and replaced all the other nonworking tests by a
+blocking read of 1 byte on the pty and this detects the termination.  Now:
+
+ . ripple works perfectly (of course it's only one-way).
+ . Kermit fails
+
+Let's call the remote, forked, redirected, external Kermit A and its
+local partner B.  A sends its S-packet, B receives it OK and Acks.
+A apparently does not receive the ACK in time, so sends the S again, but OK.
+followed immediately by the F.  B Acks the F.  A sends the A, B Acks it.
+But now A sends a piece of the previous F packet and the the first piece
+of a D packet.
+
+Clearly the buffering is messed up.  Sure enough, there was an extraneous
+statement incrementing a read pointer in a write section.  Removing that
+cleared up the problems with Kermit, now we can send and receive substantial
+files efficiently in remote mode.  Zmodem seems to work too, except that at
+the beginning a bunch of "**B0800000000022d"'s are stuffed into Kermit's
+command buffer, so after the transfer we get some error messages.
+
+In local mode, over a Telnet connection, Kermit works fine.  Zmodem works
+OK too except it doesn't finish right, so at the very end rz on the far end
+is still waiting for something; if I cancel out of it with ^X^X^X^X^X, it
+deletes the file.  So there still is something wrong with the termination
+test.
+
+Also you don't see anything on your screen when running Kermit or Zmodem
+this way.  That's to be expected, since they are using stdio for the
+transfer, so they can't also be displaying progress or other messages.
+
+Built this on NetBSD again...  Seems to work this time, but has trouble
+finishing, like Zmodem.  Hmmm, on closer examination, it turns out that
+since in_chk() always returns 0 on the ptyfd, we fall into our new
+single-byte read code, so it's really slow, like 10K cps on a connection
+where 1M is the norm.  27 Dec 2006.
+
+Switched the pty from buffer peeking (FIONREAD) and blocking reads to to
+nonblocking reads (O_NONBLOCK / O_NDELAY).  Works just fine on NetBSD except
+now we no longer get EIO at the end when trying to read from the pty process
+that has exited.  In fact, we're back to square one again.  not ioctl(), not
+fcntl(), not select(), not even read() gets an i/o error after the pty
+process exits.  But in NetBSD, we have to use nonblocking reads because ...
+Hmmmm, maybe switch the fd between blocking and nonblocking for the test...
+Nope, NetBSD seems to be hopeless (later, Ed Ravin confirmed that similar
+problems have been observed with other applications that try to do this).
+
+Switching to Linux, I see that yesterday's Solaris code (blocking reads)
+works exactly the same way on Linux.
+
+Tried today's O_NDELAY method on Solaris.  It works perfectly.  And then I
+moved this one to Linux and it works perfectly there too.  Except in both
+cases we have the wierd thing with Zmodem at the end, but I think that's
+because rz/sz don't use standard i/o.  On NetBSD, it still hangs at the end.
+
+Turns out that testing the pid works in NetBSD, even though it didn't in
+Solaris.  Turns out read() gets an i/o error in Solaris and Linux but not
+in NetBSD.  So checking the read result first, and then checking the pid
+if read() got zero bytes catches all three.  28 Dec 2006.
+
+Now the question of return code.  In the original ttruncmd() function, we do
+a fork() and a wait().  When the external protocol program finishes, wait()
+gives us its return code and we can pass it on through \v(pexitstat) as well
+ttruncmd's own return code.  But ttptycmd() has to interact with the pty
+continuously, so it can't just sit back and wait() for it.  Instead we have
+to detect when the process has exited and then call waitpid() on the fork
+pid, before shutting down the pty.  Tested on Solaris using Kermit as the
+external protocol and then inducing failure, or letting it run to
+completion.  FAILURE and SUCCESS set appropriately in each case.  Tested
+with Zmodem too, works OK except for the aforementioned cosmetic glitch at
+the end.  Tested on NetBSD, all OK.
+
+To make K5 connection to Panix from Spam:
+
+ set telnet debug on
+ authenticate K5 init /realm:PANIX.COM /password:xxxxx
+ set host shell.panix.com 23 /k5login
+
+Good...  Now I try to send a file from Spam to Panix over the K5 connection
+using Kermit itself as the external protocol.  It fails.  Inspection of the
+debug log on the far side shows that the S-Packet was received correctly,
+good!  This means we are reading the clear-text S-Packet from the external
+Kermit program, and that ttol() is encrypting appropriately.
+
+The remote Kermit sends the Ack and goes to read the next packet: ttinl()
+calls myfillbuf() and:
+
+  SVORPOSIX myfillbuf calling read()
+  SVORPOSIX myfillbuf=0                <-- read returns 0
+  SVORPOSIX myfillbuf ttcarr=2
+  SVORPOSIX myfillbuf errno=0          <-- and reports no error
+  HEXDUMP: mygetbuf read (-3 bytes)
+  mygetbuf errno=0
+  ttinl myread failure, n=-3
+  ttinl myread errno=0
+  ttinl non-EINTR -3[closing]
+
+This happens because myfillbuf() deliberately returns -3 when read() gets 0
+bytes.  I don't understand why this happens but the real problem is yet to
+come.  The local Kermit (the one that has made the secure connection and is
+running the external protocol through ttptycmd()) eventually figures out
+that the transfer failed and when we reconnect, we get total garbage -- the
+encryption either stopped happening, or got out of sync.
+
+Looking at the local debug log, ttol() is doing its job, converting the
+initial "kermit -r\13" from plaintext to cyphertext, as shown by the
+hexdumps.  Then it enters ttptycmd()...  Hmmmm, wait, how can it send the
+"kermit -r" before it starts the external protocol?  Never mind, worry about
+that later...  Anyway, ttptycmd() says:
+
+  ttptycmd loop top have_pty=1
+  ttptycmd loop top have_net=1
+  ttptycmd FD_SET ptyfd in
+  ttptycmd FD_SET ttyfd in
+  ttptycmd nfds=5
+  ttptycmd select=1
+  ttptycmd FD_ISSET ttyfd in
+  ...
+  ttptycmd in_chk(ttyfd) n=11
+  ttptycmd ttxin n=11
+
+ttxin() asks for 11 bytes, myfillbuf() gets 11 bytes, and hexdump() shows
+the cyphertext, there doesn't seem to be any decrypting going on.  Hmmm, it
+looks like the regular code calls ttinc() in a loop, rather than ttxin().
+Maybe ttxin() doesn't have decryption hooks.  No, that's not it, the code is
+there, but the Kermit packet reader does not use ttxin(), it uses ttinl().
+But of course we can't use that for external protocols because it's designed
+only to read Kermit packets.  Substituting a loop of ttinc()s for the ttxin()
+call fixes things (and stangely enough, it seems to be faster).  And now we
+have our first external protocol transfer over a secure connection (external
+Kermit program, Linux over Kerberos 5 to NetBSD).  Zmodem worked too for a
+short file but "something happens" with longer ones.  29 Dec 2006.
+
+New makefile target for Linux with Kerberos 5, linux+krb5, that doesn't
+include anything extra from SSL or other security methods (but apparently it
+is still necessary to include -DOPENSSL_097 in order to get the right names
+for the DES routines?).  Ditto netbsd+krb5 for NetBSD, except in this case
+-DOPENSSL_097 is not necessary.  makefile, 30 Dec 2006.
+
+Note to myself: On Panix:
+
+  export LD_LIBRARY_PATH=/usr/local/kerblib
+  make netbsd+krb5 "K5LIB=-L/usr/local/kerblib" "K5INC=-I/usr/local/include"
+
+Can't telnet-k5 from newly built Kermit on NetBSD; partway through the
+negotiations, just after "TELNET RCVD SB ENCRYPTION SUPPORT DES_CFB64
+DES_OFB64 IAC SE" it dumps core.  The last two lines in debug.log after
+this are:
+
+  tn_sb[len]=5
+  encrypt_support[cnt]=2
+
+Rebuilding with -DOPENSSL_097 doesn't change anything.  Ed Ravin said they
+have two different Kerberos installations, Heimdahl and MIT; maybe some
+mixup between the two explains the problem (Jeff concurs). The core dump
+occurs in ck_crp: encrypt_support():
+
+   debug(F100,"XXX ep not NULL","",0);
+   type = ep->start ? (*ep->start)(DIR_ENCRYPT, 0) : 0; <-- Here
+   debug(F101,"XXX new type","",type);
+
+Anyway, I can log in with Kerberos 5 to Panix OK from Columbia (sesame)
+using 8.0.201.  So let's try to resurrect the Solaris version with everything:
+
+  solaris9g+krb5+krb4+openssl+shadow+pam+zlib
+
+I hunted around to find where the current library and header file
+directories were...  Last time I tried this (March 2006) it bombed, not
+finding libdes.  Instead we have /opt/kerberos5125/lib/libdes425.a.  Made a
+new cu-specific target that includes this; now we get farther; it blows up
+in ckcftp.c with tons of errors and warnings, which we can worry about
+later.  Building again with -DNOFTP, it gets to ckuath.c (the first security
+module) and:
+
+  ckuath.c:151:18: error: krb5.h: No such file or directory
+  ckuath.c:152:21: error: profile.h: No such file or directory
+  ckuath.c:153:21: error: com_err.h: No such file or directory
+  ckuath.c:176:28: error: kerberosIV/krb.h: No such file or directory
+  In file included from /opt/openssl-0.9.8d/include/openssl/des.h:101,
+                  from ckuath.c:219:
+
+Found krb5.h in /opt/kerberos5125/include/krb5.h, added a -I for this
+directory ...  Now we get lots of warnings in ckuath.c, but it completes OK,
+then we wind up bombing out in ck_crp.c; I don't know why -- there are all
+the same warnings (related to argument passing to DES functions), but no
+errors.  I have no clue.
+
+Tried to resurrect the solaris2x+krb4 target; this required changing -lkrb
+to -lkrb4 and -ldes to -ldes425.  Lots of warnings in ckutio.c, ckcnet.c,
+ckctel.c, then it bombs out in ckcftp.c because it can't find krb.h.  I
+found it, adjusted the -I flags, but now it bombs because krb.h itself
+#includes <kerberosIV/des.h>, which of course it can't find because the
+brackets mean it's looking in /usr/include/kerberosIV/, which, of course,
+the sys folks have removed.  Giving up on Solaris again.  Later, Jeff said
+"Solaris does not publicly export the krb5 libraries.  You need to build
+the MIT Kerberos libraries separately and link to them."  30 December 2006.
+
+Changed copyright date to 2007.  ckcmai.c, 1 Jan 2007.
+
+With Ed Ravin's help, successfully built C-Kermit with Kerberos 5 and
+OpenSSL (netbsd+krb5+openssl+zlib), but it does not make K5 connections; it
+gets hung up in the Telnet negotiations.  3 Jan 2007.
+
+Downloaded MIT Kerberos 5 v1.4.4 to Solaris 9, 54MB worth.  This is just so
+I can build a Kerberized C-Kermit for testing ttyptycmd().  Ran the
+configure program, got a few warnings but it didn't fail (should it?)  Did
+"make install", specifying a private directory but it failed immediately
+with "cannot stat libkrb5support.so.0.0: No such file or directory".
+OK, I tried.  3 Jan 2007.
+
+Made a new makefile target for Mac OS X, macosx10.4+krb5+ssl, ran it on Mac
+OS X 10.4.8.  It bombs out in ckcftp.c with: ckcftp.c:551: error: static
+declaration of 'gss_mech_krb5' follows non-static declaration
+/usr/include/gssapi/gssapi_krb5.h:76: error: previous declaration of
+'gss_mech_krb5' was here".  Ditto for gss_mech_krb5_old, gss_nt_krb5_name,
+and gss_nt_krb5_principal.  Tried again with -DNOFTP.  We get lots of
+warnings in the network modules, but they complete.  But ck_ssl.c bombed
+with a conflict between its own declarations of encrypt_output and
+decrypt_input and the ones in ckuat2.h; removed the prototypes from the
+latter (as Jeff advised) it built OK and it works OK too.  Built with FTP
+too, but with link-time warnings about the aformentioned gss_* symbols.
+#ifdef'd them out (gss_mech_krb5, gss_mech_krb5_old, gss_mech_name, and
+gss_mech_principal) for MACOSX, where these symbols are exported by the
+library.  Now it all compiles and links OK, and runs OK too.  3 Jan 2007.
+
+Spent a day hunting around for a version of Zmodem that would build and
+execute on Mac OS X, finally found one.  Now at last I could try a Zmodem
+external-protocol transfer over a secure connection.  But phooey, C-Kermit's
+pty support didn't work on this box.  Kermit finds master /dev/ptypa OK,
+then in ptyint_void_association() tries to open /dev/tty but gets ERRNO=6
+"device not configured" (which is apparently OK, because the same thing
+happens on other platforms where this works), then tries to open slave
+/dev/ttypa and gets ERRNO=13 "permission denied" because, indeed, I don't
+have r/w permission on the device.  Left a message.  4 Jan 2007.
+
+Changed TRANSMIT /BINARY output buffer size from 252 to 508 to avoid
+TCP fragmentation.  Need to add a SET command for this later.
+ckuus4.c, 5 Jan 2007.
+
+Found another Mac where the ptys weren't protected against me, make a K5
+connection and transferred a largish file with Zmodem with zero glitches,
+except it was kind of slow, 84K cps.  Well, we're doing single-character
+reads on the net (ttinc()'s instead of ttxin()).  Hmmm, but then I did it
+again and got 2.2Mcps.  Success was reported, but it actually didn't work;
+it only sent the first quarter of the file....  Oh well, at least now we
+have a testbed.  5 Jan 2007.
+
+Tried again, saw that the file is actually transferred instantly but then
+we're not picking up the protocol at the end.  Theory: after the transfer
+finishes, we come back to the prompt on the remote host, which means we have
+something to read from the net and write to the pty, but the pty has already
+exited.  AFTER THE PTY IS GONE, WE DO NOT WANT TO READ FROM THE NET ANY
+MORE.  Adding this test makes Kermit succeed right away when sending the
+same largish file, with a transfer rate of 4M cps, that's better.  But the
+rz program on the far end is evidently not receiving the goodbye handshake
+from the receiver, because it sits there foreever in its *B09002402009418
+mode until I ^X^X^X^X^X out of it, at which point it deletes the file it
+already received, not very helpful.  In the code, I read from the pty if the
+pty is open and there is room in the buffer.  This means that when we get to
+the end, either there is no room in the buffer (unlikely) or the last bit
+sent by sz before exiting was cut off when the fork closed.  Why do we get
+in this fix only with Zmodem and not with Kermit?
+
+In Mac OS X, after sz exits, we get ERRNO=5 if we try to write to the pty,
+but we still get no errors after that if we try to read from it.  Still,
+prior to this we did more than 20 unproductive nonblocking reads from the
+pty (no error, no bytes) without incident; there did not seem to be anything
+waiting.  In fact, the last thing we read from the pty were the text
+messages that are issued at the end of the transfer: "rz 3.73 1-30-03
+finished."  After which it pauses a second and spits out a message about
+UNREGISTERED COPY.
+
+Figured out how to build lrzsz, in hopes that the previous problems were
+with rzsz and crzsz's fiddling with file descriptors, but I get the same
+behavior.  Which is good, I guess, because if I can fix one, I fix them all.
+Or not...  Testing lrz by itself (not under C-Kermit), I see that it doesn't
+work at all with Kermit's own Zmodem implementation.
+
+OK, here's one problem: at the end of the transfer, the Omen Zmodems print
+stuff like "Please read the license agreement", Kermit dutifully reads this
+from the pty and sends it to the host, the host shell says "Please: command
+not found", issues its prompt again, which Kermit reads, feeds to the pty,
+and apparently the pty echoes it, so we send it back to the host, and there
+ensues an infinite loop of getty babble until the pty closes.  Now, there
+ought to be a way to make the external protocol shut up, like Kermit's
+-q(uiet) flag, but these are unregistered versions so you can't shut up the
+messages.  In fact, the transfer works, but the getty babble at the end
+ruins the experience.  Now I'm beginning to wonder how any of these programs
+ever worked as external protocols.  Hmmm, now that I try it, I see the
+same thing happens the old way, when using ttruncmd() rather than ttptycmd().
+
+Reading the crzsz documentation I see it says that messages come out on
+stderr.  OK, that's progress.  In ckupty.c I try redirecting 2 to /dev/null.
+Well good, this filters out the messages from csz, but we still get getty
+babble on the prompt.  In the debug log, we read the last bunch of stuff
+from net, 618 bytes of Zmodem stuff...   Now what happens?
+
+Zmodem on the remote exits, the host prints its prompt.  Kermit, of course,
+reads the prompt from the net, now come to the bottom of the loop and we
+have 7 bytes to write to the pty, and no error condition, so we continue the
+loop.  select() says that the pty is ready for writing.  We write the 7
+bytes and and get no error.  Loop again, this time select() says the pty has
+data waiting.  Sure enough we get the prompt back, and send it to the net,
+and thus begins the getty babble.  There are two causes for this:
+
+  1. crzsz does not exit immediately; it sleeps for 10 seconds after
+     printing its nag message.
+
+  2. During this interval the pty seems to be echoing what is sent to it.
+     csz is not echoing; I checked.  Anyway, removing the pause doesn't
+     seem to make a difference.
+
+ttptycmd() needs to:
+
+ . TELL the pty module to redirect stderr to /dev/null
+ . SET PTY TO NOECHO (master or slave?)
+
+Tried setting the pty to noecho:
+
+  termbuf.c_lflag &= ~(ECHO|ECHOE|ECHOK);
+
+and this seemed to stop the getty babble.  After the file transfer, I read
+back the prompt from the host shell, I write the prompt bytes to the pty;
+there is no error.  And now select() simply hangs forever (or times out if
+a timeout is set).  The question here is: why didn't writing to the pty
+produce an error?  And, because we never detect the pty has exited, we can't
+set a good return code.  5 Jan 2007.
+
+Moved pty fork testing to a separate routine, pty_get_status(), and 
+added a call to it from the place where we time out, in case the fork
+terminated; then we can get and return its status.  6 Jan 2007.
+
+Added calls to pty_get_status() to every place where we suspect a pty error,
+tried again with lrzsz, crzsz, and regular rzsz.  All three work, but in
+each case waitpid() indicates that the sz program gave exit code 1 (failure).
+ckutio.c, 7 Jan 2007.
+
+Changing the subject...  On my test system, every time I execute ttptycmd(),
+I get "permission denied" on /dev/ttyp3.  Then I run it again and get to
+ttyp4 which is OK.  I wanted to skip past any pty for which I lack
+permission and try the next without raising an error.  Added debugging code:
+
+  16:25:23.524 pty_getpty() pty master open error[/dev/ptyp0]=5
+  16:25:23.524 pty_getpty() pty master open error[/dev/ptyp1]=5
+  16:25:23.524 pty_getpty() pty master open error[/dev/ptyp2]=5
+  16:25:23.524 pty_getpty() found pty master[/dev/ptyp3]
+  16:25:23.524 pty_getpty() slavebuf [2][/dev/ttyp3]
+
+So it already was skipping past open errors; ttyp3 was opened successfully.
+The problem is that ptyp3 is rw-rw-rw-, but the corresponding master,
+ttyp3, is rw--r----.  It seems the code assumes that if the master can be
+opened, then so can the corresponding slave.  Unfortunately, the code is
+not structured to allow us to skip ahead to the next master if the slave
+can't be opened.  7 Jan 2007.
+
+Spent a couple hours trying to rearrange the code in the pty module to skip
+past inaccessible slaves but it was a rabbit hole, not worth it, backed off.
+8 Jan 2008.
+
+Tried an upload over a secure connection using lsz.  Unexpectedly, this time
+it worked; not only was the file (about 0.5MB) transferred correctly, but
+Kermit detected the fork's termination and got the pid's exit status, and,
+for the first time, correctly reported a successful transfer.  I have no
+idea why this works today and not yesterday.  More tests; it works most of
+the time.  It works with csz and with regular sz too.
+
+(days later...)
+
+ckucns.c seems to do the right thing; it recognize the ZSTART string,
+activates the Zmodem-Receive APC, and returns.  doconect() sees the APC and
+begins to execute it.  The RECEIVE command results in a call to the GET
+command parser, doxget() (IS THAT RIGHT?), then comes a ttflui(), which
+throws away a bunch of stuff.  Finally we get to ttptycmd(), we get a pty
+and run lrz in it, select() says stuff is waiting from the pty, but read
+returns 0, errno 0.  Skipping the ttflui() in doxget() if the protocol was
+not Kermit didn't seem to make difference.  ckuus6.c, 8 Jan 2007.
+
+The problem is that in this case, reads from the pty never get anything (no
+data, no error), write always gets an error.  It's as if the pty was not
+being set up right, or we're using the wrong file descriptor.  And if we
+skip the autodownload?  Same thing.
+
+OK, putting downloads aside for a moment, let's get uploads working as well
+as possible.  At this point we have the odd situation (at least in this
+configuration) that the upload succeeds, but now for some reason we are
+unable to read the exit status from the process, even though this was
+working before, so ttptycmd() returns 0 (failure), yet Kermit reports
+success.
+
+Well, it turns out that kill(pty_fork_pid,0) was gumming up the works.
+If we use only waitpid() all is well, I think.  waitpid() with WNOHANG
+returns -1 with status -1 errno 0 if the pid has not exited, and it returns
+the pid and status > -1 if the process has exited.  Fixed pty_get_status()
+to do it this way.  ckutio.c, 7 Jan 2007.
+
+Let's move this from Mac OS to NetBSD and see how it works.  Well, the file
+transfer was just fine, but then I used some sexps to calculate the elapsed
+time and transfer rate, and Kermit hung in dosexp().  Fine, ignoring that...
+The debug log shows that ttptycmd() gets the pty OK, master and slave, the
+i/o goes smoothly, and waitpid() does its job perfectly.  Solaris, same
+deal; ttruncmd() goes smoothly, but then the sexps afterward get "Arithmetic
+exception".  Turns out there was a BAD bug in dosexp() that allowed an
+integer division by 0 to occur under certain circumstances; it's always been
+there.  Fixed in dosexp(): ckuus3.c, 8 Jan 2007.
+
+After noticing a few problems running the pop.ksc script in production over
+the past year, rewrote \femailaddress() to be more reliable and a lot
+simpler.  ckuus4.c, 9 Jan 2007.
+
+Back to ttptycmd()...  When we left off, we could send but not receive.  Set
+up a test case using Kermit as the external protocol for receiving a short
+file.  If I SET STREAMING OFF and use short packets, it actually does work,
+so it's not a complete failure to function, but apparently a lack of flow
+control for the pty.  Began by completing the parameterization of the pty
+module, so it can be called for interactive use (fc 0) or for running
+protocols (1).  Confirmed that everything works at least as well as before
+(e.g. "set host /pty emacs" vs external protocols).  ckcdeb.h, ckutio.c,
+ckupty.c, 9 Jan 2007.
+
+Found in HP-UX "man 7 pty" a description of ioctl(fd,TIOCTTY,fc) which is
+exactly what we want: fc 0 turns off all termio processing and guarantees an
+ininterrupted, unmolested, flow-controlled stream of bytes in both
+directions.  This function also exists in Linux, but not in Solaris, NetBSD,
+or Mac OS X (TIOCNOTTY is not what we want, it does something else entirely).
+
+Another possibility is TIOCREMOTE, which "causes input to the pseudoterminal
+to be flow controlled and not input edited, regardless of the terminal
+mode".  This one exists in at least HPUX, NetBSD, Solaris, and Mac OS X.
+
+Solaris: builds OK, but at runtime we get ENOTTY ("Inappropriate ioctl for
+device").  By the time this happens, it's hard to tell from the code whether
+the fd we're using is for the master or the slave; TIOCREMOTE can be used
+only on the master.  Close inspection shows that I am indeed doing that;
+ptyfd as seen by ttptycmd() is truly the master, i.e. the /dev/ptyXX device,
+not the /dev/ttyXX device (the slave fd can't be seen at all, as it exists
+only in a separate fork).  OK, so now we know that TIOCREMOTE can't be used
+on Solaris.
+
+NetBSD: Somehow, whether as a result of today's fiddling or the phase of the
+moon, the code in pty_open_slave() that tries to open /dev/tty started
+failing on NetBSD ("Device not configured").  Changing it to be run only if
+fc == 0 (which doesn't seem to hurt anything), once again I get ENOTTY on
+the TIOCREMOTE ioctl.  Zmodem works but Kermit totally fails (the fork exits
+immediately with an exit code of 0, even though it didn't do anything).
+
+Mac OS X: Exactly the same sequence and results as NetBSD.
+
+Linux:  It did not execute the new ioctl at all; apparently the TIOC symbols
+are hidden or not exported or something.
+
+Where we stand:
+ . Downloads don't work
+ . Uploads got slow again
+ . Kermit doesn't work at all as an external protocol
+
+Actually if I take the debugging out it goes fast, but it doesn't finish.
+
+All today's work on ttptycmd() looks like a dead end.  To roll back to
+yesterday:
+
+  cp ckutio.c-20070108 ckutio.c
+  cp ckupty.c-20070108 ckupty.c
+  cp ckupty.h-20070108 ckupty.h
+
+or to continue with today's:
+
+  cp ckutio.c-20070109 ckutio.c
+  cp ckupty.c-20070109 ckupty.c
+  cp ckupty.h-20070109 ckupty.h
+
+Comparing Monday's and Tuesday's pty-related code, the differences are:
+ 1. Passing of function code to and among pty modules.
+ 2. Skipping the TIOCSCTTY ioctl and the open("/dev/tty") test.
+ 3. Attempting to put pty in TIOCTTY or TIOCREMOTE mode.
+
+Commenting out 2 and 3 should put us back where we were on Monday if the
+parameterization was done right.  And with this, on Solaris, downloading
+with Kermit external protocol works but slowly, 8K cps, with or without
+debugging.  Debug log does not show any obvious bottlenecks; select() takes
+anywhere between no time at all and 0.1 seconds to return.  If I increase
+the pty-net buffer size from 1K to 4K, the rate goes up to 55K cps.  If I
+make it 8K I get 136K cps.  With 16K I get 346K cps.  32K: 395K cps -- this
+last one isn't worth the doubling.  But at 24K I get 490K cps, sometimes
+twice that.  Let's stick with 24K for now.  Downloading with Zmodem (rzsz)
+works at the same rate, but now we're back to seeing the getty babble
+(Several "**B0800000000022d") at the end. 10 Jan 2007.
+
+Moving to Mac OS X, everything works the same as on Solaris, except I don't
+get the Zmodem getty babble there, not even with Omen rzsz.  Tested sends
+in both remote and local mode, the latter over a secure Kerberos 5 Telnet
+connection, using C-Kermit, rzsz, lrzsz, and crzsz, all good.  10 Jan 2007.
+
+Now we're back where we were yesterday morning, but with better throughput.
+The big issue then was receiving files.  But yikes, now it works!  Not only
+that, I got a transfer rate of 2.1M cps.  That's using Kermit protocol,
+streaming, and big (4K) packets.  Which didn't work before.  Not a fluke
+either, I uploaded bigger and bigger files up to 6MB, they all went
+smoothly, at rates between 1 and 2 MBps.  10 Jan 2007.
+
+Not so great in Zmodem land, however.  If I start the external-protocol
+receiver on the far end, escape back and start a Zmodem send... nothing.
+If I leave the remote C-Kermit at its prompt (where it supposed to recognize
+the Zmodem start string), still nothing.  On the other hand, if I do it
+with a script instead of by hand:
+
+  def xx output take blah\13, send /proto:zmodem \%1
+  
+it works, at least intermittently.  But that's in remote mode.  We won't be
+using this in remote mode.  In local mode, where we have a secure connection
+to another computer, it seems we can read from the pty and write to the net,
+but we time out waiting to read from the net; nothing arrives.  Well, we
+know that i/o works both ways, so there is some kind of screwup with the
+Zmodem protocol start itself.  Increasing the (still hardwired timeout) from
+5 to 22sec and driving the whole process with a script so as to avoid
+autodownload as well as manual dexterity effects...  It just sits there
+forever, way longer than 22 sec.  ^C'ing out, I see that sz was indeed
+started on the far end and the protocol was executing.  But it looks like
+the receiver (the one running under ttptycmd()) is getting trashed packets,
+because (a) it seems to be sending the same thing over and over again, and
+(b) sometimes it waits as long as 10 seconds before anything arrives from
+the remote.  Maybe I was too impatient; I interrupted it after 4 minutes but
+it seems to have been making some progress.  Whenever there was data
+available to read from the net, it was always 65 bytes, and it was not
+actually the same data over and over.  This is using lrz as the external
+protocol.  crz gets a bit farther.  In this case we read up to 24K at a
+gulp, but the amount varies a lot.  It looks like we took in about 1.2MB of
+Zmodem protocol data, but were only able to output the first 20K of the
+file.  Clearly there were lots of errors.  In the end, the crz exits with
+status 1 (failure).
+
+Anyway it looks like we're back at needing to find a way to accomplish
+something like TIOCREMOTE on the pty, which is where we came in.  10 Jan 2007.
+
+Without any way to make the pty transparent and flow controlled, it would
+seem to make sense to write to the pty in smaller chunks than we do to the
+net.  I left the read-from-pty-write-to-net buffer at 24K and changed the
+read-from-net-write-to-pty buffer to 48 bytes.
+
+Upload using lsz worked but took about 3 minutes.  Actually it didn't work.
+On the local end it seemed to work, but the file did not appear on the
+remote end.  Tried this several times, each time with different results,
+adding more debugging each time.  The problem this time was that the pty
+read could get EWOULDBLOCK.  Changed the code to not treat this as an error,
+now Zmodem uploads are solid again except I never got EWOULDBLOCK again
+either, even though I repeated the same upload about 1000 times (with
+throughput of over 2MBps even with debugging on), so the test for it has
+not been exercised.
+
+OK, uploads still work.  Back to downloading...  The very first pty read
+gets 0 bytes, followed by the fork test that shows that it exited with
+exit status 2. 
+
+Next we try starting sz with some different options on the far end:
+
+ -q: quiet (no messages):
+     for some reason this gets totally stuck.
+     it looks as if this option is misdocumented;
+     sz seems to be sending the letter C (as in Xmodem 1K or whatever)
+
+ -e: escape (all control chars):
+     first attempt to read pty finds the process gone with exit status 2.
+
+ -k: send 1k blocks:
+     this one didn't stop immediately.  It reads 48 bytes from net, writes
+     48 to the pty with no error.  Then reads 21 bytes from the pty, writes
+     them to the net OK.  Then reads 48 bytes from net, writes them to pty OK,
+     reads 21 from pty, writes to net OK, etc etc...  It appears to have
+     worked but (final read from pty returned 0, fork test showed lrz exited
+     with status 0), but only 754 bytes were received from the net when the
+     file is 420K...
+
+Well this only goes to show that the faster we shove stuff into the pty, the
+worse it gets.  Zmodem downloads won't work unless we can make the pty
+transparent and flow-controlled.  So to summarize today's developments:
+
+ . separated in/out buffer sizes
+ . handled EWOULDBLOCK
+ . found out that sz options don't help much
+
+11 Jan 2007.
+
+Next day.  This has got to be the most delicate code ever, it's like
+Whack-A-Mole, fix A and B pops up.  Even without touching it, something that
+worked perfectly a 2:00 doesn't work at all an hour later.  Maybe I could
+have used pipes instead of ptys, but pipes have problems of their own.
+There has to be a way to do this.  The telnet server, the SSH server, etc --
+they all run on ptys, and we can upload files to them with Kermit.  Why?
+Because Kermit puts its terminal into all the right modes using the
+time-honored methods of ttpkt() and ttvt().  Perhaps all we need is a copy
+of ttpkt() that operates on the pty.
+
+On that theory, let's go back to Kermit as the external protocol.
+It's important to suppress all messages and displays.  With that,
+uploads work fine, no hitches.
+
+Downloads:  We fail right away.  The debug log shows the Kermit program that
+we are starting in the pty says:
+
+  "" - Invalid command-line option, type "kermit -h" for help.
+
+But of course we are not giving it an invalid command-line option.
+Switching to gkermit for the external protocol, now we see that no matter
+command-line options we use, we read 0d 0d 0a from the pty and then the
+next time we go to read from the pty we get 0 bytes and waitpid() says the
+program has exited with status 1.
+
+Why should downloading be different from uploading?  ttptycmd has no idea,
+it does everything the same.  The only difference would seem to be which
+side sends first, but even that tends to get washed out by each program's
+startup messages.
+
+Downloading with Kermit worked 2 days ago, what's different now?  The buffer
+sizes.  Putting the net-to-pty back up to 24K (from 48 bytes)...  Now it
+works again.
+
+Conclusion: Kermit conditions the pty correctly, Zmodem does not.  Therefore
+ttruncmd() must duplicate what ttpkt() does.
+
+Or not.  Because rz works fine on ssh/telnet ptys too.  But not on our pty.
+lrz exits immediately with status code 2 = 01000 but there are no clues in
+the lrz.c source code, I don't even see this exit status set anywhere.
+Unredirecting stderr, I see that the error is "lrz: garbage on command line".
+
+Why do both Kermit and Zmodem sometimes think they are receiving an invalid
+command line?  If I could capture the garbage...
+
+Side trip #1: ("pty.log",O_WRONLY) gives "no such file or directory".
+Changed this to ("pty.log",O_CREAT,0644) and now it doesn't get an error,
+and it creates the file, but not with 0644 permissions, and with nothing
+written in it.  How come nothing works?
+
+Fine, the debug log shows that ttptycmd() receives the correct string
+(e.g. "lrz -v").  It passes it to do_pty() correctly, and do_pty() passes it
+to exec_cmd(), which runs cksplit() on it, coming up (in this case) with
+"lrz" and "-v", which is right, and then:
+
+    args = q->a_head + 1;
+    execvp(args[0],args);
+
+execvp() wants the args array to have a null element at the end.  cksplit()
+does indeed do that, or at least the code is there.  Added code to exec_cmd()
+to verify the argument list and that it is null-terminated.  So far it is.
+
+Anyway, we have traffic between the Zmodem partners, but no joy.
+Commenting out the bit that redirects stderr, now I can see it on my screen
+in real time:
+
+  lrz waiting to receive.Retry 0: Bad CRC
+  Retry 0: Got ERROR
+  Retry 0: TIMEOUT
+  Retry 0: TIMEOUT
+  Retry 0: TIMEOUT
+  Retry 0: TIMEOUT
+
+etc etc, forever.  Trying sz -e on the far end, I get:
+
+  Retry 0: Bad CRC
+  Retry 0: Garbage count exceeded
+  Retry 0: Garbage count exceeded
+  Retry 0: Garbage count exceeded
+  Retry 0: Garbage count exceeded
+  Retry 0: Garbage count exceeded
+  Retry 0: Garbage count exceeded
+  Retry 0: Garbage count exceeded
+  ...
+  Retry 0: Got ERROR
+  Retry 0: Bad CRC
+  Retry 0: Got ERROR
+  Retry 0: Got ERROR
+  lrz: xxufio.c removed.
+
+So apparently it's not a matter of escaping.  Trying some other stuff, I
+caught the command-line problem in the act:
+
+  lrz: garbage on commandline
+  Try `lrz --help' for more information.
+
+Debug log shows:
+
+  cksplit result[lrz]=1
+  cksplit result[-v]=2
+  exec_cmd arg[lrz]=0
+  exec_cmd arg[-v]=1
+  exec_cmd arg[]=2
+
+An empty string at the end instead of a null pointer.  I really do not see
+any way that could happen, but rather than dig into cksplit() again after
+all these years I added a test for this in exec_cmd(), which, of course
+after adding it, never encountered this behavior again.
+
+Fiddled with pty buffer size again.  Made it 512 bytes instead of 24K.
+Zmodem downloads are the same (Rety 0: TIMEOUT, over and over).  But I don't
+see what the problem is -- every time we receive n bytes from the net, we
+write n bytes successfully to the pty and there are no errors.  But it also
+looks like the remote sender is sending the file header over and over
+because it's not receiving an acknowledgment.  If we're not losing data,
+then maybe it's a transparency problem.
+
+Tried uncommenting the TIOCblah stuff I commented out before.  Now instead
+of only timeouts I get:
+
+  lrz waiting to receive.Retry 0: Bad CRC
+  Retry 0: Got ERROR
+  Retry 0: Bad CRC
+  Retry 0: Got ERROR
+  Retry 0: Bad CRC
+  Retry 0: Got ERROR
+  Retry 0: TIMEOUT
+
+which is odd because the TIOCREMOTE ioctl failed with errno 14, EFAULT,
+bad address, which should indicate it had no effect.  We're still receiving
+data from the remote in tiny chunks (from 12 to 65 bytes), apparently the
+same stuff (file header), and writing them to the pty successfully but
+nothing...
+
+Looked at cloning ttpkt() for the pty, but these stupid routines use global
+tty mode structs so it's not going to be easy.
+
+Well, we got exactly nowhere today, but I think I'll leave stderr as it is
+so users will see some feedback; no reason not to.
+
+WHY DO KERMIT DOWNLOADS WORK AND ZMODEM NOT?
+
+Is it 8-bit transparency?  Up til now I've been testing with text files.
+If I try to download a binary what happens?  Fails after 99 seconds.  Packet
+log from the far end shows that as soon as the first packet containing 8-bit
+data is sent, everything stops.  At least I got one of these:
+
+  17:23:56.475 exec_cmd arg[gkermit]=0
+  17:23:56.475 exec_cmd arg[-qr]=1
+  17:23:56.475 exec_cmd arg[]=2
+  17:23:56.475 exec_cmd SUBSTITUTING NULL=2  <-- the code I just added
+
+Doing this again shows the same thing on the near end.  All the 7-bit-only
+packets are sent and acknowledged OK.  Three 8-bit data packets arrive and
+nothing else happens after that.  This is with G-Kermit.
+
+The same thing happens with C-Kermit receiving.  But if I change C-Kermit's
+.kermrc to turn off streaming and use a short packet length:
+
+The transfer works, even though it's sending 8-bit bytes.  So the problem is
+not 8-bit data after all, per se.  Facts:
+
+ . Kermit can receive streaming transfers of 7-bit files.
+ . Kermit can not receive streaming transfers of 8-bit files.
+ . Kermit can receive nonstreaming transfers of 8-bit files with short packets.
+ . Kermit can receive nonstreaming transfers of 8-bit files with 1K packets.
+ . Kermit can receive nonstreaming transfers of 8-bit files with 4K packets.
+
+So it's the combination of streaming and 8-bit data?  12 Jan 2007.
+
+As a test I made a new routine pty_make_raw() that does cfmakeraw() (a
+nonportable "POSIX-like" function known to be used on ptys in applications
+that do approximately what we're attempting).  Results:
+
+ Solaris: errno 25 - inappropriate ioctl for device.
+
+This happens even when we try to get the terminal modes with tcgetattr(),
+which is completely nuts.  We pass it the file descriptor of the pty master,
+which is supposed to work.  But in Mac OS X, there are no errors.  But
+downloads still don't work; lots of errors but the pattern is different.
+Using a very small buffer:
+
+  Retry 0: Bad CRC
+  Retry 0: Garbage count exceeded
+  Retry 0: Garbage count exceeded
+  Retry 0: Got TIMEOUT
+  Retry 0: TIMEOUT
+  Retry 0: Bad CRC
+  Retry 0: Bad CRC
+  Retry 0: Garbage count exceeded
+  Retry 0: Garbage count exceeded
+  Retry 0: TIMEOUT
+  Retry 0: Got ERROR
+  Retry 0: TIMEOUT
+  Retry 0: Garbage count exceeded
+  Retry 0: Garbage count exceeded
+  Retry 0: Bad CRC
+
+Using a bigger buffer:
+
+  Retry 0: Garbage count exceeded
+  Retry 0: Garbage count exceeded
+  Retry 0: Garbage count exceeded
+  Retry 0: Garbage count exceeded
+  Retry 0: Garbage count exceeded
+  Retry 0: Garbage count exceeded
+  (several screensful)
+
+Various other combinations... Nothing seems to work.
+
+Insight: telnetd does exactly what we want to do, sort of.
+But it uses TIOCPKT, so every time it reads from pty, it receives
+one control byte and then the data bytes, which would complicate our
+buffering scheme considerably.  Anyway the TIOCPKT ioctl() fails on
+Mac OS X with 14 "Bad address".
+
+Also see: snoopserver.c (found in Google).  It seems to do things in a
+slightly different way -- it sets stdout to raw and then dups it to the
+slave side of the pty?
+
+Maybe it's a mistake to use the ckupty.c routines.  They are designed for
+creating and accessing an interactive session.  Maybe just copy one of the
+other programs.
+
+18 Jan 2007.  Tried going back to blocking rather than nonblocking reads
+to see if it would make a difference, after all the other changes.  Nope.
+OK, let's look at some of these other programs...
+
+snoopserver.c.  I don't know exactly what this is or where it's from or what
+platform it runs on and there are no comments to speak of, but it does
+approximately what ttptycmd() does.  To get a pty it uses openpty():
+
+  if (openpty(&pty, &tty, NULL, NULL, NULL) == -1)
+
+then creates a fork.  In the fork, it closes the pty (master) and
+manipulates the modes of the tty (slave), dups tty to be stdio, and then
+doex execv() on the command.  Meanwhile the upper fork closes the tty
+(slave), gets the attributes of stdin, using atexit() to have them
+automatically restored on exit.  Then it sets stdin to raw mode and enters
+the select() loop on stdin, the pty master, and the net.  It uses regular
+blocking reads.  It does not use TIOCPKT or anything like it.
+
+openpty() is supported on: Linux, Mac OS X, NetBSD, FreeBSD, ...
+openpty() is NOT supported on: Solaris, HP-UX, ...
+
+ 1. Try copying the pty code, but keep everything else the same.
+
+I did this; it compiles and starts OK, upper fork (ttptycmd) debug log shows
+no errors, but nothing happens.  Logs show that the Kermit program that is
+started in the subfork seems to die as soon as it reaches eof on its init
+file.  The good news, at least, is that select() doesn't report report that
+the pty is ready to be read.  Clearly the file descriptors aren't being
+assigned as expected, or as before.
+  
+In ckupty.c getptyslave() dup2's the slave fd to 0 and 1.  The new code
+does exactly the same thing.  Debug log makes it look like the forked kermit
+is not receiving its command line.  But now I'm not even sure that the
+forked kermit started at all.  ps from another terminal doesn't show it.
+
+19 Jan 2007: Noticed that in snoopserver, the select() calls use standard
+input and output file descriptors, rather than the pty master.  Made that
+change...  In doing that I had to look at every file descriptor in every
+line of code and discovered a couple mistakes, fixed them, put back the
+original code but with the fixes, tried it, but no change; can upload OK but
+still can't download with Zmodem without lots of errors and ultimate
+failure.  Going back to the alternative version and trying to get the the
+file descriptors sorted out, now it appears that the external Kermit program
+never even starts in the lower fork.  After a bit more fiddling I sort that
+out, but now when the lower Kermit program goes to open "/dev/tty" it gets
+errno 6 "Device not configured".  Forcing it to use stdio with "-l 0", it
+gets past this and actually sends its first packet.  But the Kermit on top
+reads nothing from the pty.
+
+Next, I change the pty fd from STDIN_FILENO and STDOUT_FILENO to slavefd.
+No difference.  Next I comment out the dup2() calls.  This time I get some
+action.  The transfer starts, but only one packet comes.  Log shows that
+the lower Kermit sends its S packet.  The upper Kermit receives the ACK
+but the lower Kermit never gets it.  The write to the pty succeeds, no
+error.  Different combinations give different results.  If write to master
+and read from the slave, I get packets in both directions but tons of
+errors....  This happens only if I comment out the dup2()'s.
+
+25 Jan 2007: After leaving it sit for a while, and realizing that what I'm
+trying to do has to be possible because so much other software does the same
+thing (e.g. Telnet servers), I put things back to how they were originally
+-- the upper fork (Kermit) uses the master and the lower fork the slave.
+The upper fork puts the master in raw mode, the lower fork puts the slave in
+raw mode.  The lower fork dup2's the slave fd to stdin/out.  Send file in
+remote mode using external Kermit: works OK but select() times out at the
+end.  This means that the self-contained pty code in ttptycmd() is sorted
+out -- all the file descriptors go to the right place, etc, and now we can
+use this routine as a testbed, rather than the original ckupty.c-based one.
+
+But send with lsz, csz, and regular rz: Nothing happens, times out after 0
+bytes of i/o.  Once again, Kermit works, Zmodem doesn't.  The reason for
+running Zmodem in a pty is so its i/o will work as it does on a terminal,
+no matter how it may fiddle the file descriptors.  So why don't we see a
+single byte come out?
+
+Commenting out pty_make_raw(), I get a successful Zmodem send using lsz.
+csz manages to get the filename across, but then gets stuck.  regular sz, on
+the other hand, works perfectly.  Testing csz by itself (not under Kermit),
+I see it fails in exactly the same way ("Got phony ZEOF", etc).  OK, forget
+crzsz.
+
+OK, let's move to local mode over a Kerberized Telnet connection...
+Uploading (sending) with external Kermit protocol... works.
+Downloading (receiving) with external Kermit protocol... works.
+Uploading with sz... works.
+Downloading with lrz...  Gets tons of errors and fails.
+
+Running pty_make_raw() on the slave but not on the master: no difference.
+Running pty_make_raw() on the master but not on the slave: no difference.
+
+Back where we started...  Either:
+
+ . Zmodem is overdriving the pty, no matter what modes we put it in.  
+ . It's a transparency problem.
+
+Theoretically we should be able to test these by using different sz switches:
+  -q:    quiet (should always use this)
+  -e:    escape all control characters
+  -B n:  Buffer n bytes (rather than whole file)
+  -L n:  Packet length
+  -l n:  Frame length (>= packet length)
+  -w n:  Window size
+  -4:    4K blocksize (doesn't help)
+
+-q by itself doesn't help.
+-q -e, this one worked but still got about 100 errors and was very slow.
+-q -e -l 200 -L 100, failed fast and bad.
+-q -e -w 1.  Failed quickly.
+-q -e -w 1 -B 100.  Eventually failed.
+-q -w 1, Eventually failed.
+-q -l 1024, this gets much more errors, definitely need -e.
+-q -e -l 1024, got pretty far before failing.
+-q -e -w 1 -l 1024, also got pretty far before failing.
+-q -e, this one got farthest of all, about 48K, before getting errors.
+
+In the latter combinations that work somewhat better, we always get up to
+16K, or 32K, or 48K, before the errors start coming out and piling up.
+Sometimes the errors are recoverable and we receive as much as 300K
+successfully before giving up.
+
+Now that we have data flowing pretty well (but not well enough), tried
+reinstating pty_make_raw(), but it hurt more than helped.
+
+As a sanity check, I tried transferring from the same host over the same
+kind of connection (Kerberized Telnet) directly to K95's built-in Zmodem
+protocol, and that worked fine.  So the problem is definitely in the pty.
+Or more precisely, where Kermit writes incoming net data to the pty master.
+
+26 Jan 2007: Tried changing the size of the net-to-pty buffer from 24K to
+1K.  Result: total failure.  Set both buffers to 1K.  Still total failure.
+Set both to 4K: now we get about 45K of data, then failure.  Put them both
+back to 24K, still fails totally -- the same code that worked pretty well
+yesterday.  Actually, no downloads work, not even Kermit, not even of
+text files.
+
+27 Jan 2007: Since I have not been able to find a way to make ptys work for
+this, I made a third copy of this routine, this time using pipes instead of
+ptys.  The disadvantage here is that if the external protocol does not use
+stdio, the pipes won't work, but one thing a time...
+
+Inferior Kermit starts in lower fork, but when it tries to send its first
+packet it gets errno=9 EBADF, Bad File Descriptor.  Substituting G-Kermit as
+the external protocol, which is simpler, reveals that the problem is that
+the external protocol gets errors when it tries to manipulate the its stdio
+file descriptors with ioctls, etc; these are not valid for a pipe.  The pipe
+mechanism itself works.  If I take out the test for ttpkt() failing in
+gkermit, the file transfer works OK.  Trying Zmodem... Sending works OK;
+receiving works a lot better than with ptys (it got 360K into the file
+before failing).  Making the buffers smaller, doesn't help.
+
+I'm starting to wonder if the problem might be in my buffering code, rather
+than in the pty or pipe interface...  Try making a version that does
+single-character reads and writes.
+
+This one reads the first packet from the lower Kermit and sends it.  It is
+recognized by the other Kermit, which sends an ACK.  We see the ^A of the
+ACK, but then select() times out on the next character -- OF COURSE: because
+at a lower level, it has already been read.  We have to check the myread
+buffer, and then call select() only if it's empty.  Making this change:
+
+ . SEND with G-Kermit works (but very slowly).
+ . SEND with lsz works but gets a lot of errors, eventually succeeds.
+
+Let's work our way back...  With the same changes to the buffered pipe version:
+
+ . SEND with G-Kermit/streaming works (fast).
+ . SEND with lsz works too (fast), but we get gubbish at the end.
+ . RECEIVE with Kermit fails because "/dev/tty is not a terminal device".
+ . RECEIVE with rsz... lots of errors ("garbage count exceeded") but succeeded.
+
+But maybe now we're seeing pipe artifacts, so going back one more step to
+the version that gets its own pty and starts its own fork:
+
+ . SEND with G-Kermit/Streaming works (fast) but select() times out at the end.
+
+Another breakthrough: Moved the write pieces to below the read pieces.  This
+is what was preventing the buffer reset code from working -- with the writes
+done before the reads, we never catch up and can never reset the buffers.
+
+ . SEND with G-Kermit/streaming works (fast) (but there's a pause at the end)
+ . SEND with lsz works (fast) (but there's a pause at the end)
+ . RECEIVE with rsz... lots of errors ("garbage count exceeded") and fails.
+ . RECEIVE with Kermit -- nothing happens (it thinks it succeeded), then we
+     reconnect, terminal sees S packet and goes into autodownload
+
+From the log it looks like ttpkt() fails in the lower Kermit.  Switching
+this with the hacked G-Kermit...  it gets "transmission error on reliable
+link".  Tried again with real Kermit below, this time with "-l 0" and not
+streaming.  This was actually working, but slowly, I don't see any NAKs in
+the packet log, but then select() timed out.
+
+28 Jan 2007: Restored both the calls to pty_make_raw():
+
+ . SEND with C-Kermit streaming works, but slow (54Kcps)
+ . Ditto, but with debugging off -- hangs forever.
+ . Ditto, but using G-Kermit instead of C-Kermit -- also hangs forever.
+
+Backed off on calling pty_make_raw().  Same thing.
+Reduced size of net-to-pty buffer.  Same thing.
+
+15 Feb 2007...  Decided to give up on this and publish it as is, in hopes
+that somebody with more experience with ptys can make it work, because I'm
+just going in circles.  So today I just have to get the code into shape so
+people could choose among the three alternative routines.  The second one,
+yttyptycmd(), is the one that uses openpty(), which is not portable, so it
+can be enabled only for Mac OS X, NetBSD, FreeBSD, and Linux, or by also
+defining HAVE_OPENTPY at compile time.  Anyway, if you build Kermit in the
+normal way, you get the regular behavior -- ttruncmd() is used to execute
+external protocols.  If you build it with -DXTTPTYCMD, you get the first
+version of ttptycmd(); with -DYTTPTYCMD the second, and with -DZTTPTYCMD the
+third.
+
+(Then some interruptions, then...)
+
+From Jeff, fix hostname comparison in X.509 certificate checking to work
+right in the case of names that contain no periods.  dNSName_cmp(): cl_ssl.c,
+21 Feb 2007.
+
+John Dunlap noticed some strange behavior when transferring files between
+home base and the EM-APEX oceanographic floats via satellite... long story,
+but every so often the transfer would get stuck for a long time, and it
+happened only when C-Kermit was sending a file and received two or more
+packets (Ack or Nak) back to back from the float.  Years ago I added some
+lookahead code to ttinl() to clear the input buffer of any interpacket junk
+so that, in the windowing case, we wouldn't be tricked next time around into
+thinking a packet was waiting to be read when there wasn't.  The code, which
+has been there for a while, was a bit fractured; luckily, it would be
+executed only when the debug log was active so it didn't have much effect.
+The problem was that if the SOP came immediately after the EOP, it could be
+missed because the loop read the next character before checking the current
+one.  Fixed by rearranging the loop.  Also I changed it so it would execute
+in all cases, not only when the debug log was active.  Also, cleaned up a
+bunch of confusing #ifdefs and removed some chunks that had been commented
+out for years, decades maybe.  ttinl(): ckutio.c, 21-22 Feb 2007.
+
+Added NOW keyword info to HELP DATE, plus a tip about how to convert to UTC;
+suggested by Arthur Marsh.  ckuus2.c, 22 Feb 2007.
+
+When an FTP client sends NLST to the server and no matching files are found,
+the server is supposed to respond with an error message on the control
+channel and nothing on the data channel.  However it seems that at least one
+server sends the error message back on the data channel, as if it were a
+filename ("/bin/ls: blah: No such file or directory"), and on the control
+channel there is no error indication ("226 ASCII Transfer complete").  At
+this point remote_files() has a listfile and, if a match pattern was given,
+it looks through list to see if any of the lines match the given filename,
+e.g. "blah".  This makes FTP CHECK give false positives.  The problem
+(diagnosed by Jeff) is that the match pattern was not given in this case, so
+it takes some random default action, resulting in the spurious success
+return.  Fixed by using the user's string as the pattern.  Not tested,
+however, since I don't have access to a server that behaves this way.
+ckcftp.c, 22 Feb 2007.
+
+If an external-protocol file transfer fails, don't print Kermit-specific
+hints.  ckuus5.c, 22 Feb 2007.
+
+One more time with ttinl().  Got rid of the "csave" junk, which never could
+have worked (which is no doubt why it was in a debugging section).  The
+problem was that saving the beginning of the next packet locally did not
+synchronize with the buffer clearing (ttflui()) done at a higher level,
+between calls to ttinl().  So now, the lookahead code, if it finds the
+beginning an as-yet unread packet, puts it back at the head of the input
+queue.  This way, if the protocol engine clears the input buffer, it will
+get the whole packet, not just the part after the SOH.  ckutio.c, 24 Feb 2007.
+
+From Steven M Schweda, Saint Paul, MN: adaptation of large file support to
+VMS (it was already possible to transfer large files in VMS C-Kermit but the
+file-transfer display and statistics were wrong).  And a minimal adaptation
+of the FTP client to VMS -- no RMS, no special VMS file stuff, Stream_LF and
+binary files only, developed and tested only with UCX.  SSL/TLS is
+supported.  The source-code changes are minimal; most have nothing to do
+with VMS, but with header files, prototypes, and data types (e.g. ftp_port
+int rather than short, various signed/unsigned conflicts) to shut up
+compiler warnings.  Some of these could be dangerous in terms of
+portability; I've marked them with /* SMS 2007/02/15 */.  ckcfns.c,
+ckcnet.h, ck_ssl.h, ckuus3.c, ckuus4.c, ckvfio.c, ckcftp.c, ckvker.mms
+(which was rewritten to actually reflect the source module dependencies),
+ckvker.com (also heavily modified).  ckvker.com (the "makefile" for VMS
+C-Kermit) now indludes "F" and "I" option flags for the large File and
+Internal ftp features, plus better handling of Vax/Alpha/IA64 distinction.
+26 Feb 2007.
+
+Changed NetBSD targets to include -DHAVE_OPENPTY and -lutil, so they
+can use openpty().  makefile, 26 Feb 2007.
+
+Built on Solaris without and with SSL OK.
+Built on NetBSD with Kerberos 5, OK.
+Built on Mac OS X 10.4, regular version, OK.
+Built on Mac OS X 10.4 with SSL and Kerberos 5, OK.
+
+On VMS 7.2-1/Alpha with MultiNet 4.4A-X...
+
+'CC' 'CCOPT' KSP:ckuus3
+%DCL-W-TKNOVF, command element is too long - shorten
+ \CKUUS4.OBJ "'CC' 'CCOPT' KSP:ckuus4" "KSP:ckuus4.c KSP:ckcsym.h KSP:ckcdeb.h
+ KSP:ckclib.h" "KSP:ckcasc.h KSP:ckcker.h KSP:ckcnet.h KSP:ckvioc.h"
+"KSP:ckctel.h KSP:ckuusr.h KSP:ckucmd.h KSP:ckuver.h" "KSP:ckcxla.h
+ KSP:ckuxla.h KSP:ckcuni.h KSP:ckuath.h"
+
+The new rule for ckuus4.c was too long.  I removed one file from the
+dependency list (ckcxla.h, which will probably never change again) and that
+made it OK.  Built Nonet and Net versions OK, but this is without the new
+stuff.
+
+"make f" (large-file support) on VMS 7.2-1...
+'CC' 'CCOPT' KSP:ckuus4
+                    if (CKFSEEK(fp,(CK_OFF_T)j,SEEK_CUR) != 0) {
+........................^
+%CC-I-IMPLICITFUNC, In this statement, the identifier "fseeko" is implicitly
+declared as a function.
+
+Ditto for ftello and fseeko in various other places, and then fseeko and
+ftello come up up undefined at link time.
+
+The rule for ckcftp in "make i" (Internal FTP support) had the same problem.
+I removed ckcxla.h from its dependency list too, but "utime" comes up
+undeclared at compile time and undefined at link time.
+
+Verdict: neither one of the two new features can be used in VMS 7.2 or
+earlier, but the code still builds OK if you don't ask for them.
+
+VMS 8.3 on IA64...  Can't build anything:
+%MMS-F-BADTARG, Specified target (WERMIT) does not exist in description file
+
+27 Feb 2007: Changed CKVKER.COM to keep all its dependencies but use a
+shorter logical name (Steven M Schweda).  The problem on VMS 8.3 is that MMS
+now supports case-sensitive file systems, and so it can't find anything.
+Workaround: bypass MMS (include "m" in P1).  With this, "@ckvker.com ifm"
+builds OK on HP Testdrive, but I can't test the new features since outbound
+connections are not allowed there.  As for fseeko(), ftello(), and utime(),
+they simply are not availble prior to VMS 7.3.  It would probably be a good
+idea to test for this in CKVKER.COM, but actually it is possible to install
+newer C's and CRTLs on older VMS versions, so don't stand in their way.
+
+28 Feb 2007: With additional chages from SMS, and then some further
+adjustments, I was able to build the FTP version on VMS 7.2-1.  First I
+tested it with GET of a binary file, but it transferred it in text mode.
+After a few more attempts with PUT and GET, it crashed with "floating/decimal
+divide by zero" in ckscreen, ckuusx.c line 27859.  Of course, that's the
+listing line, not the source line, and I don't have a listing.
+
+To get a listing, I deleted CKUUSX.OBJ and then did:
+
+  $ make i "" "" "/LIST"
+
+Surprisingly, it recompiled everything.
+
+Anyway, the divide by zero happened in a section of code where the divisor
+was not checked, but it was a section of code we should not have been
+executing at all, since the file-transfer display was fullscreen, and this
+was in the "brief" section.  Anyway, I added the needed check.  Again, it
+recompiles everything.  Maybe there's no MMS on grumpy -- right, there isn't.
+
+ANYWAY... Try to GET a binary file like this:
+
+  binary
+  ---> TYPE I
+  200 Type set to I.
+  get gkermit
+  ---> TYPE A
+  200 Type set to A.
+  ---> SIZE gkermit
+  550 gkermit: file too large for SIZE.
+  GET gkermit (text) (-1 bytes)---> TYPE A
+
+Anyway... "get /binary gkermit" downloads it, seemingly correctly (the byte
+count is right).
+
+But "put /binary gkermit.;1" results in a 0-length GKERMIT file being sent.
+Here's the debug log:
+
+FTP PUT gnfile[DISK$MSA4:[C.FDC.NET]gkermit.;1]=1
+ftp putfile flg[DISK$MSA4:[C.FDC.NET]gkermit.;1]=0
+zltor fncnv[DISK$MSA4:[C.FDC.NET]gkermit.;1]=-1
+FTP PUT nzltor[GKERMIT]
+zfnqfp 1[DISK$MSA4:[C.FDC.NET]gkermit.;1]=675
+zfnqfp 2[DISK$MSA4:[C.FDC.NET]GKERMIT.;1]=31
+zfnqfp 3[DISK$MSA4:[C.FDC.NET]GKERMIT.;1]=31
+zrelnam result 2[gkermit.;1]
+ftp sendrequest restart[DISK$MSA4:[C.FDC.NET]gkermit.;1]=0
+openi name[DISK$MSA4:[C.FDC.NET]gkermit.;1]
+openi sndsrc=-1
+openi file number=2
+zopeni[DISK$MSA4:[C.FDC.NET]gkermit.;1]=2
+zopeni fp=0
+chkfn=2
+chkfn return=0
+zopeni fixed file format - using blk I/O
+zopeni binary flag at open=1
+zopeni ifile_bmode=1
+zopeni binary=1
+zopeni RMS operations completed ok
+openi zopeni 1[DISK$MSA4:[C.FDC.NET]gkermit.;1]=1
+ftpcmd cmd[PASV]
+FTP SENT [PASV]
+FTP RCVD [227 Entering Passive Mode (166,84,1,2,233,216)]
+initconn connect ok
+FTP SENT [STOR GKERMIT]
+FTP RCVD [150 Opening BINARY mode data connection for 'GKERMIT'.]
+doftpsend2 ftpcode[STOR]=150
+
+  Here is where the file is supposed to be read and sent but there is nothing
+  in the log between the "doftpsend2 ftpcode" line and the following line.
+
+rftimer status=1
+gftimer status 1=1
+gftimer status 2=1409025
+gftimer status 3=1409025
+gftimer s[0.000000]
+zclose n=2
+chkfn=2
+chkfn return=1
+zclose ZIFILE RMS operations completed ok
+ftp getreply lcs=0
+ftp getreply rcs=-1
+ftp getreply fc=0
+FTP RCVD [226 Transfer complete.]
+ftp getreply[226 Transfer complete.]=2
+doftpsend2 ok=0
+
+Everything is OK up until we go to send the file, then it behaves as if we
+got EOF immediately and so closes the data connection, and reports success;
+an empty copy of the file is left on the far end.
+
+Starting over with a text file....  PUT LOGIN.COM gets another divide by
+zero.  But it happened in the code I just fixed, which is impossible.  Swell.
+I recompiled everything and this time the upload worked, and downloading it
+again worked too.
+
+But a binary file still can't be uploaded.  Trying to upload a text file
+after doing this seems to succeed (reports the right number of bytes sent)
+but nothing appears on the far side.
+
+SUMMARY:
+
+  To download a text file: GET /ASCII blah.txt    (/ASCII is optional)
+  To download a binary file: GET /BINARY blah.bin (/BINARY is required)
+  To upload a text file: PUT blah.txt             (/ASCII switch not needed)
+  To upload a binary file: PUT /BINARY blah.bin   (doesn't work)
+
+Problems:
+  . Why doesn't BINARY "stick"?
+  . Why don't binary uploads work?
+
+The culprit seems to be the VMS version of zxin().  In the FTP module,
+zxin() is called only when sending binary files.  In VMS, zxin() is just
+a front end for C-Library fread().  It probably needs to do just do
+zminchar() in a loop, like binary mode does, but calling zzout instead
+of xxout.  Or something like that.  FINISH THIS TOMORROW (debug on grumpy).
+
+2 Mar 2007: New logs from John Dunlap.
+
+ema-1636-log-0175.dbg: C-Kermit uploads a short file. It receives an Ack for
+the Z packet it just sent, tailgated by the beginning of a Nak for the next
+packet.  When the second SOH is encountered, it is put back in the myread
+queue.  Then the protocol engine, to which we return the Ack, says, "I have
+the packet I wanted so I'm clearing the buffer", and away go the first two
+bytes of the Nak from the myread buffer.  Then, having just received the Ack
+of our Z packet, we send our B, and go to read the reply.  in_chk finds 0 in
+the myread buffer (which we just cleared) and 6 waiting to be read from the
+comms channel, which it does, obtaining the remaining 6 bytes of the Nak,
+which it properly discards.  (The reason this is proper is that, having
+already received the Ack for the last packet it sent, no Ack or Nak that
+arrives subsequently -- in the non-windowing case -- could possibly affect
+what it does next.)  Since it hasn't yet found a good packet, it keeps
+reading, and now it finds the Ack to the B, as soon as it showed up.  This
+is how it's supposed to work.  No time was lost because of anything that
+C-Kermit did.
+
+ema-1636-log-0174.dbg: C-Kermit uploads a short file. It sends Data packet
+#3 and receives the Ack followed immediately by the first 3 bytes of a Nak
+for packet 4.  When it gets to the SOH of the second packet, it pushes it
+back in the queue.  Again, input() flushes the input buffer (myread queue
+and device buffer).  C-Kermit detects EOF on the file it is sending, and
+sends the Z packet.  Then it reads the remaining bytes of the Nak,
+which it discards, and then it finds the Ack for Z which comes in 23 seconds
+later, sends the B, gets a Nak for the B, sends the B again, gets the Ack
+for the B 4 seconds later, and done.  Again, it's working right and losing
+no time.
+
+The question remains: what would happen if the protocol engine did not clear
+the buffer?  Would ttinl() retrieve all packets in sequence even when they
+come back to back?  To test this, I had C-Kermit send a file using 30 window
+slots and observed the stream of Acks in the reverse direction:
+
+  HEXDUMP: mygetbuf read (16 bytes)
+  01 25 23 59 2f 52 39 0d | 01 25 24 59 2b 26 31 0d  .%#Y/R9. .%$Y+&1.
+  ttinl lookahead my_count=9
+  ttinl lookahead removed=^M
+  ttinl lookahead pushback SOP=^A
+  HEXDUMP: ttinl got (7 bytes)
+  01 25 23 59 2f 52 39    |                          .%#Y/R9
+  RECEIVE BUFFERS:
+  buffer inuse address length data type seq flag retries
+     0     1     29212 9667     0   Y    3     0
+  [\ 1%#Y]
+  ...
+  in_chk my_count=8
+  ...
+  ttinl lookahead my_count=1
+  ttinl lookahead removed=^M
+  HEXDUMP: ttinl got (7 bytes)
+  01 25 24 59 2b 26 31    |                          .%$Y+&1
+  RECEIVE BUFFERS:
+  buffer inuse address length data type seq flag retries
+     0     1     29212 9667     0   Y    4     0
+  [\ 1%$Y]
+
+Here we can see that the pushed-back SOH was properly retrieved next time
+around, and the tailgating Ack was not lost.  This scenario repeats itself
+212 times in the log, and there are no screwups.
+
+Back to VMS FTP...  The problem with sending binary files is that zxin()
+uses C-Library fopen()/fread() instead of RMS, so it can't access the input
+file, which was opened by zopeni(), which is totally RMS-ified in VMS
+C-Kermit.  For VMS only, I replaced the zxin() loop by a zminchar() loop
+like the one used in text mode, except without the character set or
+record-format conversion.  Tested by PUT /BINARY of some binary files, which
+worked fine.  ckcftp.c, 2 Mar 2007.
+
+Next problem...  VMS C-Kermit ftp client sending binary files in text mode.
+Variation 1: We just send the file.  zopeni() is supposed to detect that
+it's a binary file and automatically set the mode.  And it does:
+
+  zopeni fixed file format - using blk I/O
+  zopeni binary flag at open=0
+  zopeni ifile_bmode=1
+  zopeni binary=0
+  zopeni autoswitch from TEXT to BINARY
+  zopeni RMS operations completed ok
+
+but then in gnfile():
+
+  if (!server || (server && ((whatru & WMI_FLAG) == 0)))
+    binary = gnf_binary;       /* Restore prevailing transfer mode */
+
+Well, since VMS sets text/binary mode automatically when sending files,
+this code can (and should) be skipped in VMS.  gnfile(): ckcfns.c, 2 Mar 2007.
+
+Variation 2: BINARY or SET FILE TYPE BINARY doesn't force binary mode.  But
+SET FTP TYPE BINARY does.  But BINARY does indeed call doftptyp() so what's
+the problem?  We do indeed set ftp_typ to 1 but it gets reset somewhere
+before we call zopeni().  But then zopeni() puts it back to 1.  Tracing
+through a transfer, it looks like all of this works right, it's only that
+the file transfer display says TEXT when the transfer is really in binary
+mode.  This is because screen() is called before openi().  I wonder if we
+can call scrft() from the ftp module...  No, that would be too easy.  OK,
+sendrequest calls openi() and sets the file mode; putfile() calls
+screen(SCR_FN), which prints the transfer mode.  But putfile calls
+sendrequest() after it puts up the screen that says the file type.  So it
+looks like sendrequest() has to call screen(SCR_FN) again if it changes the
+file type.  OK, that did it.  ckuusx.c, ckcftp.c, 2 Mar 2007.
+
+The BINARY and TEXT (ASCII) commands do not inhibit automatic type switching
+in VMS.  They don't in Unix either.  They never have.  Should they?  I think
+so, otherwise what good are they?  Plus we want the Kermit FTP client to
+behave like the others.  I added code for this but it doesn't work, due to
+the layers and layers of text/binary detection and switching and
+if-this-but-then-if-that...  Anyway, no harm done.  The normal rule is:
+when you PUT a file, Kermit figures out on a per-file basis whether to use
+text or binary mode unless you include a /TEXT (/ASCII) or /BINARY switch
+in the PUT (or MPUT) command.  ckuus[r3].c, ckcftp.c, 2 Mar 2007.
+
+Wed Mar 7 16:21:13 2007 WROTE SHORT TEST PROGRAM for ttruncmd (the openpty
+version) on Mac OS X.  On dulce: ~/kermit/ttpty.c / ttpty.sh.  It starts the
+external protocol in the lower fork.  The command to run is a command-line
+argument.  Sending and receiving files with Kermit works OK.  But again, the
+standalone program totally fails when I use sz or lsz as the external
+protocol.  So it looks like we can rule out any environmental effects of
+running the code inside C-Kermit.
+
+Mon Mar 12 16:52:20 2007: Put some effort into making ttpty.c more useful;
+added a debug log.  Found that for some reason, at least on Mac OS X,
+select() always timed out at the the end.  I added a SIGCHLD alarm and that
+seems to handle the fork exit condition very nicely.  Now we can send (say)
+a 3MB file at good speed on Ethernet (1Mcps) considering the debugging, etc,
+and it terminates instantly.  But when sending a file into ttptycmd (with
+"gkermit -r"), things go wrong at the end -- the Z packet is never
+acknowledged.  This is reproducible.  Maybe this is a good lead....  The log
+shows that select() timed out, even though the gkermit fork had not yet
+exited (or finished).  It looks like gkermit sent the Ack, ttpty.c read it
+from the pty and sent it out the net:
+
+  0003: read pty=8                <-- read Ack from pty
+  0003: loop top have_pty=1
+  0003: loop top have_net=1
+  0003: FD_SET pty_in
+  0003: FD_SET ttyfd in
+  0003: FD_SET ttyfd out=8
+  0003: nfds=5
+  0003: select=1
+  0003: FD_ISSET ttyfd out
+  0003: write net=8               <-- send ack to net
+  0003: loop top have_pty=1
+  0003: loop top have_net=1
+  0003: FD_SET pty_in
+  0003: FD_SET ttyfd in
+  0003: nfds=5
+  0009: select=0
+  0009: select timeout - have_pty=1
+
+But Ack never arrived.  This is a streaming transfer.  But nope, streaming
+is not the problem.  If I disable streaming ("gkermit -Sr"), we hang in in
+the middle of sending the data.  If I use small packets, we don't hang:
+1000 is OK, 2000 is not.  In fact, the cutoff is 1024.  OK, TBC...
+
+Wed 14 Mar 2007: Receiving a file thru ttpty "gkermit -e 1200 -Srd"
+produces a debug log that shows that gkermit gets a lot of EAGAIN errors
+when it tries to read from its stdin.  In fact, it takes 6 tries (read()
+calls) to read the S packet (27 bytes).  Then when the first data packet
+arrives (1200 bytes), read() never returns even one single byte.  The
+timeout interval is 15 seconds and it times out repeatedly.  Added a
+primitive hex dump to the ttpty debug log for each read/write (showing only
+the first 24 characters and the last character, so it fits on one line).
+Tried uploading a file.  The S, F, and A packets (short) are received and
+Ack'd OK, but then ttpty select() times out, never receiving even one byte
+from the D packet.  Clearly, when the pty driver receives a burst of > 1K
+bytes, stops working.  As before, if I limit the packets to < 1K, it works
+fine.
+
+Can I send an 8-bit binary file?  Nope.  ttpty reads the binary data just
+fine from the net and writes it exactly as it was received to the pty, but
+the first time we write an 8-bit byte, we never hear back from the PTY
+again.  But the log shows that when the initial 7-bit packets from the pty,
+it looks like the PTY is not in rawmode, because these packets end with ^J
+rather than ^M.  Calling pty_make_raw() on the masterfd and slavefd
+explicitly, however, doesn't change anything.  It doesn't matter if I do
+this in the lower fork or the upper fork.  So maybe it's the actual
+semantics of pty_make_raw() that are wrong.
+
+Thu 15 Mar 2007: Went thru all the terminal mode flags in Mac OS X; didn't
+help.  Changed hex dump to show whole packet.  Put hex dump routine in a
+private copy of G-Kermit.  Tried to transfer an 8-bit file, logging both
+ttpty and gkermit.  Compared what ttpty received on stdin with what it sent
+to the pty (same) and what was received by G-Kermit (same).  Then I realized
+that my little test program was not putting its controlling terminal into
+raw mode; when I did that, I could upload binary files (streaming, 2MB/sec).
+And with Zmodem too (with rz; lrz doesn't work for some reason).  Looking
+back at the original in ckutio.c, I see that ttptycmd() never called
+ttpkt().  Maybe that was the trouble all along.  (Yup, but maybe not the
+whole trouble.)
+
+Moving back to C-Kermit and the original ttptycmd() routine, adding the call
+to ttpkt(), and stripping out a lot of cruft, and moving the pty_make_raw()
+code to ckupty.c, Kermit uploads and downloads (streaming) work fine in
+Solaris.  Zmodem sends a file, but then the transfer hangs at the very end,
+as if the signoff protocol were lost.  This happens on Solaris.  If I move
+back to Mac OS X, everything works just fine.  Then, making a Kerberized
+connection from the Mac to NetBSD, I can send files from the Mac with both
+Zmodem and Kermit.  Receiving...  Kermit OK.  Zmodem...  Nope.  "rz:
+Persistent CRC or other ERROR" (and created a 265MB debug.log!)
+
+Fri 16 Mar 2007: ttptycmd() was for sending files with Zmodem across
+encrypted connections.  But it occurred to me that it's necessary for
+clear-text connections too; e.g. Telnet, where 0xff has to be doubled.  Of
+course Zmodem doesn't do that itself, so there's no way Zmodem external
+protocol could work when executed over a Telnet connection, and in fact
+it doesn't.  I wonder why I ever thought it did.
+
+Wed 21 Mar 2007: Back to where we left off a week ago.  Trying C-Kermit's
+ttptycmd() on the Mac again, in remote mode:
+
+ . G-Kermit send txt (kst): OK  832Kcps  
+ . G-Kermit recv txt (kr):  OK  425Kcps  
+ . G-Kermit send bin (ksb): OK 1000Kcps  
+ . G-Kermit recv bin (kr):  OK  188Kcps  
+
+And Zmodem:
+
+ . sz txt (zst): OK  563Kcps  
+ . sz bin (zsb): OK  714Kcps  
+ . rz txt (zr):  OK  863Kcps  
+ . rz bin (zr):  OK  198Kcps  
+
+So in remote mode, everything works.  Now let's try a clear-text Telnet
+connection...
+
+ . G-Kermit send txt (kst): OK  841Kcps
+ . G-Kermit recv txt (krt): OK  391Kcps
+ . G-Kermit send bin (ksb): OK  811Kcps
+ . G-Kermit recv bin (krb): OK  171Kcps
+
+And Zmodem over the same clear-text telnet connection:
+
+ . sz txt (zst): OK  91Kcps (*)
+
+Kermit is sending sz messages like "sz 3.73 1-30-03 finished." to the
+host, which tries to execute them, after the transfer is finished.
+Of course "sz" is a command, but:
+
+  sz: cannot open 3.73: No such file or directory
+  sz: cannot open 1-30-03: No such file or directory
+  sz: cannot open finished.: No such file or directory
+
+Did I lose that code that dis-redirects stderr when I went back to using the
+pty code from the ckupty module?  No, it's there and it's being executed.
+Apparently the copy of sz I have is writing its "finished" message to stdout
+because "sz blah 2> /dev/null" does not suppress it.  Starting again with
+lsz instead of sz:
+
+ . sz txt (lzst): OK  413Kcps
+ . sz bin (lzsb): OK  FAILED (*)
+ . rz txt (lzrt): OK  
+ . rz bin (lzrb): OK
+
+(*) Sigh.  Using lsz, we get "garbage count exceeded" errors and eventual
+failure.  But using regular sz, we get the extraneous message that starts
+sz on the far tend, and the resulting getty babble.
+
+But even without changing the code, it will work one minute, and then fail
+consistently the next.  For example, I was able to send files with sz
+successfully over and over, but with the getty babble at the end.  Then,
+after trying lsz and then going back to sz, every attempt at sending a file
+quits with "Got ZCAN".  The difference has to be that Kermit always does at
+least some minimal encoding of C0/C1 control characters such NUL and DEL and
+IAC, and I doubt that Zmodem does.
+
+http://zssh.sourceforge.net/ says:
+
+  If file transfer is initiated but never completes (ie a line like :
+
+     Bytes Sent:      0/    513   BPS:0        ETA 00:00  Retry 0: Got ZCAN
+
+   can be seen, but transfer never completes), chances are the pty/tty on one
+   of the systems are not 8-bit clean.  (Linux is 8-bit clean, NetBSD is not).
+   Using the -e (escape) option of rz should solve this problem.
+
+It doesn't, at least not with lrz.  And yes, the receiving end happens to be
+NetBSD.  But it looks like the zssh people have been down this road too.
+
+But with rz and sz, it worked.  Once.  Twice.  Three times.  But of course,
+with the getty babble at the end.  This can be taken care of by doing:
+
+  rz -eq ; cat > foo
+
+which puts "sz 3.73 1-30-03 finished" and any other messages in foo (but you
+have to type ^D to finish the cat).  Using this method I was also able to
+send an 8K binary file that contained a test pattern of all 256 possible byte
+values.  Then I tried a 3MB binary executable.  All OK.  So here we go again:
+
+ . sz txt (zst): OK
+ . sz bin (zsb): OK
+ . rz txt (zrt): 
+ . rz bin (zrb): 
+
+Downloading fails about halfway through a fairly large file.  I tried an
+even bigger file, guaranteed to be 100% ASCII; same thing -- halfway
+through: "rz: Persistent CRC or other ERROR".  But it worked with a smaller
+version of the same file (82K versus 2MB).  Tried again with the bigger
+version, it failed in exactly the same way at exactly the same spot: byte
+number 1048320.  But this is just ASCII text so it can't be a transparency
+problem.  Substituting another plain ASCII file of the same size but totally
+different contents, it doesn't fail (2.36MB).  Back to the previous file, it
+fails again, but in a different spot (832960).  So it's not totally
+deterministic.
+
+To round things out, I tried downloading the binary test-pattern file; it's
+only 8K.  This failed.
+
+  -4, --try-4k                go up to 4K blocksize
+  -B, --bufsize N             buffer N bytes (N==auto: buffer whole file)
+  -e, --escape                escape all control characters (Z)
+  -E, --rename                force receiver to rename files it already has
+  -L, --packetlen N           limit subpacket length to N bytes (Z)
+  -l, --framelen N            limit frame length to N bytes (l>=L) (Z)
+
+Tried again with "sz -L 256 -B 256 -4aeq".  Doesn't change anything.
+
+NOTE: Mac OS X rz 3.73 1-30-03 does not support -e.
+NetBSD rz 0.12.20 does support -e.
+
+Thu 22 Mar 2007: It occurs to me that ttpkt() might still be a problem;
+maybe it's the network connection and not the pty that is not transparent
+enough.  To test this theory I did "stty raw ; stty -a" and then copied all
+of the flag values into ttpkt in the BSD44ORPOSIX section:
+
+ . rz txt (zrt): OK (2.36MB file, worked 2 out of 3 times)
+ . rz bin (zrb): "rz: Persistent CRC or other ERROR"
+
+A little more fiddling with the flags and I got the 8K binary test pattern
+to SEEM to download OK (in the sense that rz gave a 0 return code) but the
+file itself was truncated, always at 224.  If I changed the test pattern
+file to not include any bytes with value 224 (0xe0) or 255 (0xff), the
+download worked.  So we have a transparency problem somewhere.  The debug
+log shows that all byte values are being received from the network correctly
+so the problem has to occur when we try to feed them to the pty.
+
+But no amount of twiddling with the termios flags seems to let these
+characters pass through.  Of course, since they are not in the C0 or C1
+control range, "sz -e" doesn't quote them (which it does by prefixing with
+Ctrl-X and then adding 0x40 to the byte value so (e.g.) NUL becomes ^X@.
+Note that 255 does not cause problems because it coincides with the IAC
+character; the remote Telnet server doubles outbound IACs, and Kermit's
+ttinc() undoubles them automatically (as the log shows).
+
+Trying to send a different file (a C-Kermit binary) shows that 255 is the
+real killer; the file is truncated where the first one appears (at about
+6K), even though some 224's precede it.  Going back to the remote-mode test,
+I see the same thing happens with the binary test-pattern file, if I send it
+from K95 direct to rz-under-C-Kermit-in-remote-mode.  So it has nothing to
+do with C-Kermit having a network connection.  Yet if I send the same file
+direct from K95 to rz, it goes OK and the result is not truncated, so it's
+not Zmodem either.  The data arrives to C-Kermit intact, so the failure is
+definitely in writing it to the rz process through the slave and master ptys.
+
+BUT if I send the same file from K95 to rz-under-ttpty, that works.  What's
+the difference?  Suppose I just transplant ttpty literally into C-Kermit...
+It makes no difference.  When receiving the test-pattern, it truncates it
+in exactly the same place.
+
+Well, all this is on Mac OS X.  What if I move it to a different platform?
+OK, building on Solaris and following the exact same procedure, ttptycmd()
+doesn't even use the network connection.  I think that's because rzsz on
+Solaris is hardwired to use the controlling terminal and can't be
+redirected, even in a pty?
+
+Moved to NetBSD.
+
+ . sz txt (zst): Failed ("Got ZCAN")
+ . sz bin (zsb): 
+ . rz txt (zrt): OK
+ . rz bin (zrb): 
+
+Well, this is a big mess.  Sending doesn't work (or sometimes it does but
+reports that it didn't).  Receiving...  well, actually it's the same thing;
+the file is completely transferred but then the final protocol handshake is
+lost.  The local C-Kermit returns to its prompt, but rz is still running:
+
+  Retry 0: Got TIMEOUT
+  Retry 0: TIMEOUT
+  Retry 0: Got TIMEOUT
+  Retry 0: TIMEOUT
+  Retry 0: Got TIMEOUT
+  Retry 0: TIMEOUT
+  Retry 0: Got TIMEOUT
+  Retry 0: TIMEOUT
+  Retry 0: Got TIMEOUT
+  Retry 0: TIMEOUT
+  Retry 0: Got TIMEOUT
+
+I don't see how that is even possible.  Even after I exit from Kermit the
+messages keep coming, even though ps doesn't show the rz process anywhere.
+Looking at the code, I see a place where end_pty() was still commented out
+from the ttpty.c episode, I uncommented it.  But still:
+
+ . sz txt (zst): Fails ("Got ZCAN")
+ . sz bin (zsb): Fails instantly (but with no diagnostic)
+ . rz txt (zrt): OK
+ . rz bin (zrb): Fails with tons of "Bad CRC", "Gargage Count exceeded"
+
+Conclusion for the day: I think this is hopeless.  Even if I can get it to
+work somewhere, the results depend on the exact Zmodem software, how it uses
+stdin/out vs stderr versus getting its own nonredirectable file descriptor,
+versus the Zmodem version on the other end and which options are available
+on each, versus the pty and select() quirks on each platform, and on and on.
+It will be so hard to explain and to set up that nobody would ever use it.
+It would be better to just implement Zmodem internally.
+
+Fri 23 Mar 2007: Went back to the small test program, ttpty.c.  Tried
+setting both the master and the slave pty to rawmode, even though I have
+never seen any other software that did this.  I had it receive the binary
+test pattern file; it worked.  I made a bigger test-pattern file, 3MB,
+containing single, double, and triple copies of each byte in byte order and
+in random order, this one was accepted too.
+
+So it would seem that the ckupty.c module is something to avoid after all.
+It's full of stuff I don't understand and probably should not undo.  So
+changing C-Kermit's ttptycmd() to manage its own pty again, using openpty()
+(which is not portable), I got it all to work in remote mode: Kermit
+text/binary up/down and Zmodem text/binary up/down.  But in local mode on
+the client side of a Telnet connection...
+
+  zst: OK, but we still get the getty babble at the end that starts sz.
+  zsb: OK, ditto.  This is with the 3MB test-pattern file.
+  zrt: Not OK -- "Persistent CRC or other ERROR"
+  zrb: Not OK -- got the cutoff at 224 again "Persistent CRC or other ERROR"
+
+It's close.  But actually this was still with USE_CKUPTY_C defined.  When I
+undefined it, it was back to being totally broken.  Start over.  (Check the
+new cfmakeraw() code.)
+
+Tue 27 Mar 2007: Starting over.  Back to ttpty.c.  Let's verify, VERY
+CAREFULLY, that it really does work, using the most stressful of the four
+tests: sending the big (3.2768MB) binary test pattern from K95 into rz
+through ttpty, logging everything.  ttpty definitely receives the big file
+smoothly with no errors or hiccups when I have it set to use the master side
+of the pty for i/o.  The application program (Zmodem in this case) runs on
+the slave, and the network and/or control program communicates with the
+master.  This implies that Zmodem controls the terminal modes of the slave,
+and ttpty should be concerned with those of the master.  Doing it this way
+in ttpty confirms this.
+
+Fine.  But if I tell ttpty to SEND a file with sz, nothing happens.  Ditto
+with lsz.  Select times out waiting for input from the pty.  But if I
+manually tell K95 to RECEIVE /PROTOCOL:ZMODEM it works OK.  Somehow sz's
+initial B000000 string is being swallowed somewhere, and it's waiting for
+a reply from the receiver.  sigh...  But "ttpty gkermit -s filename" works
+fine.  What's the difference?  It has nothing to do with stdout vs stderr;
+sz is not writing to stderr at all.  Is it some timing thing between the
+forks?  Aha.  It's that I change the modes of the pty master in one fork
+while sz is already starting in the other fork.
+
+OK, good, now for the first time we have Kermit and Zmodem both able to
+upload and download a large worst-case binary test-pattern file... in
+remote mode.  Now taking today's lessons and fitting them back into
+C-Kermit so I can try it local mode...
+
+Using G-Kermit as the external protocol, first in remote mode...  All good:
+text/binary up/down.  The "halting problem" is solved by SIGCHLD, which
+catches fork termination instantly and lets ttptycmd() know there is no more
+pty.  Zmodem:
+
+  zst: OK
+  zsb: OK
+  zrt: OK
+  zrb: OK
+
+That's a first.  Next, repeat in local mode, in which C-Kermit is the client
+and has made a Telnet connection to another host over a secure (Kerberos V)
+connection:
+
+  kst: OK     zst: ...
+  ksb: OK
+  krt: OK  
+  krb: OK
+  
+It seems we can never end a day on a high note.  Somehow I seem to have
+broken regular internal Kermit protocol transfers over encrypted connections
+-- the en/decryption engine loses sync.  But they still work OK over a
+clear-text Telnet connection.
+
+Today's code in ~/80/dulce.tar (27 Mar 2007).
+
+Added makefile target solaris10g+openssl.  Gathered all the standard CFLAGS
+for Solaris into cdcdeb.h so they don't have to be included in every single
+makefile target for Solaris.  On local Solaris 10 host OpenSSL is in
+/opt/openssl-0.9.8e/.  Tried the new makefile target, works OK.  Also made
+solaris10+openssl for Sun CC, but couldn't test it because I can't find any
+Solaris 10 host that has Sun CC.  Built with gcc at another site that has
+OpenSSL 0.9.8f-dev, all OK.  ckcdeb.h, makefile, 24 Jun 2007.
+
+It occurs to me that Kermit transfers on secure connections might have been
+broken by the changes I made back in February to ttinl() for John Dunlap.
+Here, for the first time, we invoke myunrd() to push a byte back into the
+input queue, and there is also some funny business with "csave", which
+changed, and which an old comment notes that it has to be treated specially
+when encrypting.  So it could be that the broken Kermit transfer has nothing
+to do with the work on external protocols, and that putting back the
+previous ttinl() will fix it.  But now I can't seem to make a Kerberized
+connection from Panix to Panix, even though I can make one from Columbia to
+Panix.  This means I have to build a Kerberized binary from the current
+source code on either Solaris or Mac OS X.  Trying Solaris
+first... [~/solaris9k5/mk5.sh] This didn't work the first time due to
+undefined krb5_init_ets, which is referenced if MIT_CURRENT is not defined
+(it should be for Kerberos 5 1.05 and later and we have 1.42 here), tried
+again with -DMIT_CURRENT=1...  Nope, that one totally blew up in ck_crp.c.
+Later, Jeff says krb5_init_ets is a no-op in Kerberos 1.4.x and later,
+so I added an #ifdef (NO_KRB5_INIT_ETS) for skipping it; now it builds and
+runs OK.  ckuath.c, makefile, 9 Jul 2007.
+
+Meanwhile, using C-Kermit on Mac OS X, which makes the Kerberized connection
+just fine, but still has the problem transferring files over it.  Packet log
+shows:
+
+  s-00-01-^A9 Sz/ @-#Y3~Z! z0___F"U1@A^M 
+  r-00-01-^A9 Y~/ @-#Y3~^>J)0___J"U1@I
+  s-01-01-^A(!Fx.x)(V^M
+  r-xx-08-<timeout>
+  S-01-08-^A(!Fx.x)(V^M
+  r-xx-08-<timeout>
+  S-01-08-^A(!Fx.x)(V^M
+  r-xx-16-<timeout>
+
+Note that S packet is sent, received, and Ack'd OK.  The F packet is sent but
+is never Ack'd.  Tried this several times and noticed that it's just
+receiving that is screwed up, not sending.  After ^C'ing out of the
+transfer, I can still type commands, and they are executed on the far end,
+but the results coming back are gibberish.  Mon Jul 9 16:08:22 2007 (come
+back to this later... substitute Dev.27 ttinl for current one and see if
+the problem goes away, and if so, conditionalize the new code for clear-text
+connections).
+
+Built C-Kermit with Kerberos 5 on Solaris with a version of ckutio.c that
+uses the old ttinl() and transferred a file OK over a Kerberized connection.
+So now it's just a matter of reconciling the old and new ttinl.  The easiest
+way to do this is to have new ttinl() chain to old ttinl() if the connection
+is encrypted, which is what I did and it works fine.  At some point the two
+versions of ttinl() should be reconciled.  ckutio.c, 12 Aug 2007.
+
+There was a function, islink(), used in only one place (ckuus6.c) that had
+the same name as a commonly used scalar variable, and it was missing a
+prototype.  Changed its name to isalink() and added the prototype (Unix
+only), ckuus6.c, ckufio.c, ckcdeb.h. 12 Aug 2007.
+
+Revisiting the ASCII and BINARY top-level commands, which are supposed to
+be like in other FTP clients, but don't seem to have any effect.  I added a
+new routine to the FTP module, doftpglobaltype(), that sets the global,
+sticky, permanent transfer mode (ASCII or BINARY) (TENEX could be added to
+if anybody asks).  These commands (now that they work) are different from
+SET FTP TYPE { ASCII, BINARY }, which set the *default* transfer mode when
+automatic switching fails for a given file.  ckuusr.c, ckcftp.c, 12 Aug 2007.
+ (notify: Matt <mlist@cmcflex.com>)
+
+Even though the code hasn't changed, suddenly we're getting:
+
+  "ckuusx.c", line 5682: warning: implicit function declaration: tgetent
+  "ckuusx.c", line 6183: warning: implicit function declaration: tgetstr
+  "ckuusx.c", line 6262: warning: implicit function declaration: tputs
+  "ckuusx.c", line 6266: warning: implicit function declaration: tgoto
+
+in ckuusx.c on Solaris 9.  <curses.h> is still in /usr/include, dated 2002.
+A quick search shows the missing functions are hiding in <term.h>, which
+until now was included only in Linux.  Added a USE_TERM_H clause.  No, that
+doesn't help, the prototypes are not selected at compile time; there are
+#ifdefs in that file that skip over these prototypes.  I had to put them in
+the code under #ifdef BUG999..#endif (I could have used a longer name like
+#ifdef ADD_PROTOTYPES_FOR_CURSES_FUNCTIONS, but that would not be portable).
+ckuusx.c, 12 Aug 2007.
+
+Also:
+
+  "ckuusx.c", line 9232: warning: implicit function declaration: creat
+
+This is called in the IKSD dababase code, used for getting a lockfile.
+creat() is a Unixism in code that is supposed to be portable.  But IKSD only
+runs on Unix and Windows, so I assume the Windows C library has a creat()
+function.  Anyway, suddenly the Solaris header files seem to have blocked
+whatever path previously existed to the creat() prototype (which is in
+<fcntl.h>), so I added an #include in the appropriate spot.  ckuusx.c,
+12 Aug 2007.
+
+Kermit functions for converting the number base -- \fradix(), \fhexify(),
+\unfhexify() -- did not work with big numbers; ckradix() was missed in the
+CK_OFF_T conversion.  Fixed in ckclib.c, 12 Aug 2007.
+
+Updated the help text for ASCII, BINARY, and SET FTP TYPE to clarify the
+semantics.  ckuus2.c, ckcftp.c, 12 Aug 2007.
+
+Error messages were printed upon failure to open any of the four log file,
+even with SET QUIET ON.  Fixed in ckuus4.c, 12 Aug 2007.
+
+Built OK on NetBSD 1.3_RC3.  Tried to build secure version but the libraries
+had disappeared.  13 Aug 2007.
+
+Built OK on Mac OS X 10.4.9.  Tried the secure version, macosx10.4+krb5+ssl.
+Here we get the usual pile of "pointer targets in passing argument 1 of
+(function name) differ in signedness", regarding security functions, but it
+built OK.  13 Aug 2007.
+
+Reconciling the two ttinl's...  On encrypted connections myread() returns
+encrypted bytes; ttinl() has to decrypt them; it wasn't doing this in the
+lookahead section so I fixed it.  The new code works on both encrypted and
+clear-text connections.  I removed the chaining to oldttinl(), and
+oldttinl() itself.  ckutio.c, 13 Aug 2007.
+
+  (Wouldn't it make more sense and be more efficient and less confusing
+  for myfillbuf() to do the decrypting?)
+
+When C-Kermit uses Zmodem as an external protocol, it doesn't seem to scan
+files before sending them to set text or binary mode appropriately.  It's
+that external protocols bypass Kermit's whole "get next file" mechanism; the
+(possibly wild) filespec is simply passed to the external protocol program.
+Changing this would be a very big deal.  But if only one file is being sent
+(the filespec is not wild) it's easy enough to check.  I added this to the
+external protocols section of the protocol module.  It can be overridden in
+any of the regular ways (/TEXT or /BINARY switch on SEND command, SET
+PATTERNS OFF, SET TRANSFER MODE MANUAL, etc).  ckcpro.w, 13 Aug 2007.
+
+[FTP SEND /RECURSIVE]
+Peter Crowley reported a problem with FTP recursive uploads getting the
+directory tree wrong when the previous pathname was a left substring of the
+new pathname (e.g. foo/bar/ and foo/bar2/).  The logic did not handle this
+case and created the bar2 directory as a subdirectory of bar, rather than as
+a parallel directory.  Fixed in syncdir() and tested with various edge cases.
+ckcftp.c 14 Aug 2007.
+
+  notify <peter.crowley@alumni.utexas.net>
+
+Added CD messages to FTP BRIEF display to track the ups and downs of
+recursive uploads.  ckcftp.c, 14 Aug 2007.
+
+The OUTPUT command gave a misleading error message ("Connection to xxx not
+open") when used on a serial port that was, indeed, open but was not
+presenting the Carrier signal, when CARRIER-WATCH was not OFF.  Added a new
+message for this, and some others.  ckuus5.c, 14 Aug 2007.
+
+Sending from the command line, e.g. kermit -s foo, did not give an
+informative error message if the file could not be found or opened.  Fixed
+in ckuusy.c, 14 Aug 2007.
+
+OK, back to ttptycmd....  It seems that back on March 27th, I got everything
+working but I thought that there was still something wrong with it because
+an unrelated problem so I put it aside.  The version of ttpty.c from that
+date worked OK, and it looks like I updated ckutio.c from it, but that
+version of ckutio.c was put aside.  Since then I have been working on the
+ckutio.c version that was NOT put aside and so now I have to reconcile the
+two:
+
+  ~/80/ttypty/20070327/ckutio.c
+  ~/80/ckutio.c
+
+As a first cut I did this simply by replacing the contents of the #ifdef
+CK_REDIR section of the latter with that of the former.  Of course in
+Solaris this comes up with openty() implicitly declared at compile time and
+unresolved at link time.  So the first task is to get HAVE_OPENPTY defined
+for platforms that have it and have the others use the ttruncmd().  For
+starters I put an #ifdef block in ckcdeb.h that defines HAVE_OPENPTY for
+Linux, FreeBSD, NetBSD, OpenBSD, and Mac OS X.  Ones that don't have
+openpty() include AIX, HP-UX, and Solaris.  Others like SCO I don't know but
+I doubt it.  The real solution is to get the ckupty.c module to work but one
+thing at a time...  This version is supposed work with secure builds on the
+openpty() platforms, and on the others like Solaris, if an external protocol
+is attempted on a secure (encrypted) connection, an error message is
+printed and the command fails.  ckutio.c, 14 Aug 2007.
+
+How to test?  Apparently I did all my testing on Panix before, and that's
+where all my Zmodem builds are, but now when I build a Kerberized version
+(which works if I do it on the right pool host), it won't make a local
+connection, and there is no other place I can connect to that has a
+Kerberized Telnet server.  I can, however, connect to Panix from here, using
+the same code, but on Mac OS X...
+
+Slight detour: Got access to AIX again (5.3.0.0).  Picky compiler, some
+things needed fixing....  Also it says "1506-507 (W) No licenses available.
+Contact your program supplier to add additional users. Compilation will
+proceed shortly" and of course it goes kind of slow.  For some reason, I
+can't do streaming transfers into AIX over a local network (to its SSH
+server), but windowed transfers are OK.  Anyway, noting that we've been
+using the same basic makefile target since AIX 4.2, changing nothing but the
+version herald, I made a new target, simply "aix", that picks up the AIX
+version automatically and sets the herald from it.  Ditto for aix+openssl,
+but on this host requires setting SSLINC and SSLLIB to /opt/ssl/include and
+/opt/ssl/lib.  Also the make program here was extremely sensitive to spacing
+so I had to make some minor edits to get the link step to work for the SSL
+version.  ckuusy.c, makefile, 14-15 Aug 2007.
+
+Got rid of the special Panix secure NetBSD target, replaced it with a
+regular one, which is invoked in the normal way by defining K5INC and K5LIB
+to point to to where the stuff is hidden.  Cleaned up and modernized the
+comments in the makefile a bit.  makefile 15 Aug 2007.
+
+Changed some data types and added some casts to ckctel.c to do away with
+tons of "pointer targets in passing argument 1 of 'xxx' differ in signedness"
+warnings.  15 Aug 2007.
+
+Set up Mac OS X as the testbed for ttptycmd(), with Panix as the remote
+partner over a Kerberos 5 connection.  The first test is to send a 300K
+text file with gkermit as the external protocol.  It worked fine, and the
+debug log showed all the right components were active (namely encryption and
+ttptycmd) [kermit/zmodem send/receive text/binary]:
+
+  Kermit    Zmodem
+  kst OK    zst OK
+  ksb OK    zsb OK
+  krt OK    zrt OK
+  krb OK    zrb Failed "rz: Persistent CRC or other ERROR"
+
+We've seen this before.  The problem is 0xff, Telnet IAC, as I proved to
+myself by constructing a 3MB file that contained every byte but 0xff in every
+mixture and order and transferring it successfully over the same connection.
+Presumably the Telnet server is doubling IACs, whereas of course rz is not
+undoubling, thus the CRC error.  This is progress.  15 Aug 2007.
+
+Log shows that indeed every IAC in the source file arrives doubled.  Adding
+code to remove the first IAC of every adjacent pair, a small test file with
+different-length runs of IACs transfers OK.  The 3MB all.bin file does not.
+
+Starting over...  I can receive a big text file with Zmodem OK.  The 3.2MB
+binary test pattern that contains no IACs failed after 1.8MB, but the part
+that it transferred was OK.  A second try, almost the whole thing arrived,
+it stopped just 584 bytes short of the end.  Could be that file size is a
+separate problem.  Making a new copy exactly 1MB long...  Well, that's
+interesting, this one too stopped just short of the end.  And again, the
+same thing.  When connecting back to the host, the last Zmodem packet can
+be seen on the screen; it's as if the local Zmodem exited before reading
+the last packet...  But OK, if I change the options on the remote sz
+sender to use small blocks, etc, then it works.
+
+Now, changing from the 1MB no-IAC-binary test pattern, to the 1MB all-values
+test pattern, we fail after 81K.  But the part that was transferred is
+correct.  Second try, same thing, but 57K.  Third: 40K.  Each time, upon
+connecting back, the session is completely dead.
+
+IF I HAVE TO undouble IACs for incoming files, don't I have to double them
+going out?  To send a block to net we just call ttol(), but ttol() doesn't
+do any doubling (because Kermit protocol always quotes 0xff).  To see what
+happens, I changed the ttol() call to ttoc() in a loop that doubles IACs.  I
+tested this by sending the full 3.2MB test pattern, which worked fine.
+
+For receiving, it's slow but it works OK with files that don't contain IACs
+(my concern was that IACs might appear in outbound files or in Zmodem
+protocol messages).  It receives the 1MB no-IAC test pattern, so there are
+no problems with protocol or timing.  But the full test pattern always gets
+cut off, but at different points, as before, with the remote session dead.
+Changing the Zmodem receiver from rz to lrz on the local end (since the
+sender on the remote end is lsz) does not change the behavior.
+
+Anyway, I went back and replaced the byte loop with something more
+efficient, and it goes about 20 times faster.  But this doesn't help either,
+it only makes it fail faster.  But aha, what if a doubled IAC is broken
+across successive pty reads -- we have to make the "previous character"
+memory persistent.  Well, that was a good insight, but it still didn't fix
+it.  The log shows the IAC handling code is working fine.
+
+What does sz say?  Capturing its stderr to a file... "Retry 1: Got ZCAN".
+Next time: "Retry 1: Got TIMEOUT".  Next time: Got ZCAN.
+
+Trying different Zmodem options...  apparently I don't need to use short
+blocks.  But I do need to use -e, probably because of Telnet NVT treatment
+of carriage return; without -e, there is a "persistent CRC error".  -O
+disables timeouts, but this makes no difference.
+
+OK, we still have two Big Problems:
+
+ 1. When a long file has no IACs, the final < 1K of the file is not received.
+ 2. When a long file has IACs, the transfer generally stops very early.
+
+Problem 1: the transfer consistently fails less than 1K from the end of the
+file.  Upon CONNECT back to the host, a big Zmodem packet is sitting there
+waiting to be read, which means ttptycmd()'s copy of rz is terminating
+early.  Can we catch it in the debug log?  Doing this takes forever and
+writes a GB to the disk...  And then the problem doesn't happen.  Also, I
+can receive a HUGE text file almost instantly with no errors at all.
+
+Switching to lrz on the receiving end, now I see the error messages, about
+300 lines like this:
+
+  Retry 0: Garbage count exceeded
+  Bytes received:  872352/1000000   BPS:85464  ETA 00:01  Retry 0: Bad CRC
+  Bytes received:  892448/1000000   BPS:86690  ETA 00:01  Retry 0: Bad CRC
+  Retry 0: Garbage count exceeded
+  Retry 0: Garbage count exceeded
+  Retry 0: Garbage count exceeded
+  Retry 0: Garbage count exceeded
+  Retry 0: Garbage count exceeded
+  Retry 0: Garbage count exceeded
+  Retry 0: Got ERROR
+  Bytes received:  898336/1000000   BPS:84293  ETA 00:01  Retry 0: Bad CRC
+  Retry 0: Garbage count exceeded
+  Retry 0: Garbage count exceeded
+  Bytes received:  900384/1000000   BPS:83751  ETA 00:01  Bad escape sequence
+  2fRe
+  try 0: Bad data subpacket
+  Bytes received:  941472/1000000   BPS:86191  ETA 00:00  Retry 0: Bad CRC
+  Retry 0: Garbage count exceeded
+
+Even when it succeeds, it gets these.  But if I receive a text file, no
+matter how big, no errors or retries or timeouts at all.  So it appears that
+there is only one problem: a big-time lack of transparency regarding 8-bit
+and/or control characters.  The odd thing is, it's not that the characters
+can't get through -- they all can -- but they seem to cause transitory
+blockages.  16 Aug 2007.
+
+Cleaned up the remaining pointer signedness warnings in ckutio.c, but this
+was a mistake, it broke Kerberos connections completely.  Undid the changes.
+ckutio.c, 17 Aug 2007.
+
+Changed all return() in the fork()==0 section of ttptycmd() to exit().
+ckutio.c, 17 Aug 2007.
+
+Tried explicitly setting the slave pty to rawmode.  Makes no difference.
+Tried using the Mac OS X (curses) raw() function, and also system("stty
+raw"); still no difference.  Tried doing all of these in different
+combinations and orders.  I found one combination that cuts the errors about
+in half, and the transfer of the no-IAC test pattern almost always succeeds
+(but it's slow).  Anyway, it doesn't help much with the test pattern that
+contains IACs.  Well, the code is more solid than it was before but
+functionally we have not advanced much if we can't download a binary file
+with Zmodem!  On the other hand, we can upload them, and we can transfer
+text files in both directions, which is an improvement over the previous
+situation, in which the entire session would hang due to loss of
+synchronization of the encryption stream.
+
+Tried adding -funsigned-char to CFLAGS of Mac OS X target.  It does not
+make the "signedness" warnings go away and it doesn't change the runtime
+symptoms.
+
+I tried a simpler version of pty_make_raw(), the one from Serg Iakovlev, but
+it was a total failure.  That's encouraging though, because it indicates
+that pty_make_raw() is the right place to be working.
+
+Then I made pty_make_raw() set or unset every single terminal flag
+explicitly.  This made no difference, but didn't hurt anything either.
+
+Then I made pty_make_raw() explicitly set all the c_cc[] characters to 0
+(but left c_cc[VMIN] as 1).  This made no difference either.
+
+I checked pty_make_raw() against ttpkt() and the only difference I found in
+the terminal flags is that ttpkt() sets IGNPAR thinking it means "ignore
+parity errors" when really it means "discard any character that has a parity
+error" (at least according to Iakovlev) -- exactly the opposite.  But I
+tried it both ways, no difference.  17 Aug 2007.
+
+I noticed that even Zmodem text receives can fail.  They don't get any
+errors, they just get cut off shortly before the end.  (But usually they
+succeed, and fast too, like 500K cps).
+
+What if I don't call pty_make_raw() at all on the slave pty?
+
+zrt: EESSSSSSSS: 80% good (E = stopped just before end but no other errors)
+
+zrb no-IAC test pattern, short blocks:
+ 1. S/5 (success with 5 screens of errors.
+ 2. S/7
+ 3. S/7
+ 4. S/6
+ 5. E/7 (failed just before end)
+ 6. S/7
+ 7. S/6
+ 8. S/6
+ 9. S/6
+10. S/4
+
+So, lots of errors, but it recovered 90% of the time.
+Next, same thing, but without requesting short blocks:
+
+ 1. E/5
+ 2. S/5
+ 3. E/4
+ 4. S/5
+ 5. S/5
+ 6. S/5
+ 7. X/0 (hard failure right away: "Got ZCAN"
+ 8. S/5
+ 9. S/5
+10. S/5
+
+So it doesn't look like short blocks make that much difference.  Now what if
+I turn off prefixing?  Bad CRC, fails immediately every time.  Putting back
+pty_make_raw(slave), it still fails hard.
+
+Tried a new strategy with pty_make_raw(): rather than modify existing flags,
+I set all flags to 0, and then turn on only those few that we need like CS8.
+Now we get only 2.5 screens of errors instead 4-7 and the transfer rate is
+higher for binary files (all of the previous ones were under 100K CPS, while
+for text files it was 400-500K CPS):
+
+ 1. S/2 195669 CPS
+ 2. S/2 194720
+ 3. E/3
+ 4. S/2 192550
+ 5. S/3 192325
+ 6. S/3 145066
+ 7. S/2 200689
+ 8. S/3 188948
+ 9. S/2 209461
+10. S/3 181991
+
+I noticed that there was no TIOCSTTY ioctl in the pty/fork setup sequence,
+which is recommended somewhere, so I tried that and it was a disaster; the
+entire session hung.  I took it back out.  18 Aug 2007.
+
+Tried some transfers over a clear-text (not encrypted) connection with the
+same results: smooth, fast transfer of a big text file (400K cps); rocky but
+successful transfer of the no-IAC binary pattern file (135K cps).  Switching
+back to ttruncmd(), the same binary file is received at 1.5M cps, and the
+no-IAC binary file totally fails after too many "Bad CRC"s; and we already
+know that any file that contains IACs will fail.  One might say that
+ttptycmd() is better in every respect than ttruncmd() except in speed
+(when it works).
+
+Let's see if ttyptycmd still works in remote mode (to local K95):
+ . sz / text works, but slowly.
+ . lsz / text works but some wierd errors are reported.
+ . lsz / binary / no IAC doesn't work at all (CRC-32 mismatch for a header;
+        Unexpected control character ignored: 13, etc).
+ . sz / binary / no IAC works OK but slow.
+ . sz / binary / full test pattern with IAC works OK but slow.
+ . Sending text into rz fails completely.
+
+What about ttruncmd() in remote mode?
+ . send /text works, fast.
+ . send /binary works, fast. 
+ . receive /text works, not so fast but not bad.
+ . receive /binary works, not so fast but not bad.
+
+So we use ttruncmd() for remote mode, and we use it for local mode
+serial-port and modem connections, and we use ttptycmd() on network
+connections because (a) they might be encrypted, and (b) even if they are
+not, they use some protocol that we have to handle, e.g. Telnet, Rlogin.
+19 Aug 2007.
+
+Discovered that Sending binary files no longer works.  Text is OK, binary
+transfers don't even start.  This happens on both encrypted and clear-text
+connections.  ttptycmd() is being used in both cases.  But oddly enough,
+receiving binary still works as before.  What did I break, and when?
+Oh, it was just the script, when I changed it from using sz to lsz.  Putting
+it back to sz makes it work, even with the full 3.2MB binary pattern with
+IACs.
+
+I backed off the changes I made to ckctel.c to suppress some warnings, in
+view of the fact that similar changes to ckutio.c broke things so badly.
+19 Aug 2007.
+
+If sz is not given the -e flag, it sends control characters bare, except ^P,
+^Q, ^S, and ^X.  ^X is the control prefix, so ^A is sent ^X followed by A.
+With -e, all C0 control chars are prefixed, but with ^X, which is, of
+course, a control character.  Interestingly, the C1 analogs of ^P, ^Q, ^S
+(but not ^X and, unfortunately, not IAC) are also prefixed.  -e makes no
+difference for 8-bit characters.
+
+If we have a Telnet connection and the server is in ASCII (NVT) mode, CR is
+always followed by LF or NUL.  Well, it seems the server is putting us
+(Kermit) in binary mode in this case, but staying in ASCII mode itself.
+Added code to handle NVT byte stuffing and unstuffing in each direction
+independently, according to the TRANSMIT_BINARY state in that direction.  I
+made a file containing just the bytes 0-31 and 127 and 128-159 and 255 (66
+bytes all together) and sending it from the host to C-Kermit, the local log
+shows that every control character was received correctly and all TELNET
+conversions were done right -- NUL removed after CR (and only after CR); IAC
+removed after IAC (and only after an IAC meant as a quote).  For the first
+time, I can receive the 1MB all-values test pattern, but there are still
+tons of (correctable) CRC errors, so the transfer rate is really awful, like
+about 5% of what we get with a text file (25Kcps instead of 500).
+
+Further experimentation shows that the fundamental transparency problem is
+fixed; we can receive short files (say, 1K or less) containing absolutely
+any byte values in any combination with no errors at all.  But once the file
+size reaches (say) 10K, we get CRC errors, like one every 2 or 3K of data.
+These are not deterministic.  In successive transfers of the same file, they
+come in different spots.  It's tempting to blame pty buffer overruns, but
+then text files would show the same behavior.  When a binary file size
+exceeds, say, 1MB, the chances of successful completion go way down,
+independent of whether my external protocol is rz or lrz.  I like lrz better
+because the error reports come out on the screen as the transfer is going
+on.  Trying to download a real-world binary file -- a 2.2MB C-Kermit
+executable -- I get 4500 error messages but the transfer evenually succeeds,
+with an effective throughput of 21Kcps.
+
+Actually it turns out that "sz -a somebigtextfile" (2.2MB) also gets a lot
+of CRC errors.  The -e flag (escape all control characters) makes the same
+big text file transfer with few or no errors.  It's not sure-fire.
+Sometimes no errors, sometimes one or two, and sometimes a fatal error that
+kills the transfer.
+
+With binary files... a 32K binary file seems to make it every time.  40K
+fails about 50% of the time.  48K fails 60% and every time it fails, it has
+created a partial file of exactly 32K (32768 bytes).  96K fails 9 out of 10
+times, when it fails, the partial file is always 0 bytes, or 32768, or
+65536, but that just means that rz's file output buffer is 32K.
+
+Why, then, do binary files cause trouble if it is not a solid transparency
+problem?  If a certain file can get through once, why can't it get through
+every time?  When a character arrives at the pty, the pty driver probably
+takes a different path through its code, checking the terminal flags that
+would affect that character.  I tried making Kermit's network read buffers
+very small but, surprisingly, this made things worse.  I also tried making
+them very much bigger, which didn't help either.  24K still seems to be the
+right size.
+
+So, is it that some characters take longer to process than others?  So long
+that data is lost due to lack of flow control between TCP and the pty?  One
+way to test this theory is to slow Zmodem down.  I tried "-l 32" which,
+according to the man page, tells sz to "wait for the receiver to acknowledge
+correct data every N (32 <= N <= 1024) characters.  This may be used to
+avoid network over-run when XOFF flow control is lacking."  Makes no
+difference.  I also tried the -w (Window) switch, ditto.  In fact there are
+all sorts of options to set the "window size", "packet length", "block
+size", and "frame length", but with no explanation of what these mean or how
+they are related.  If I crank everything down to minimum value:
+
+  lsz q -L 32 -l 32 -w 1
+
+I get 50% success with the 96K file instead of 10%.  Adding -e, oddly
+enough, made it worse.  I also tried setting the environment variable
+ZNULLS to different numbers like 512, no help there either.
+
+I tried making the read-from-net-write-to-pty buffer small (1K) but leaving
+the pty-to-net one big.  This improves chances of success, but it's
+intolerably slow (3Kcps when the connection is capable of 500K).
+
+I also changed the write-to-pty operation from a single write() call of
+possibly many K characters to a byte loop, one write() per byte.  Same
+result: success (but still about 300 recoverable errors), throughput 3Kcps.
+20 Aug 2007.
+
+With ttptycmd() configured to write to the pty in a byte loop, it is
+possible to delay each write.  Adding a 10msec delay per character results
+in a transfer that runs at about 20 cps and (for the 96K test file) would
+take about 80 minutes to complete.  And yet it still gets just as many
+errors.  So it's not a matter of timing either.  The errors come, on
+average, every file 388 bytes, but not at regular intervals.
+
+I tried the TIOCREMOTE ioctl on the pty master, as discussed somewhat
+obliquely in the Mac OS X "man pty" page; "This mode causes input to the
+pseudo terminal to be flow controlled and not input edited (regardless of
+the terminal mode)" -- sounds like just the ticket but it made no
+difference.  Actually, looking at a man page on another OS (Solaris), it
+says this is only for lines of text, EOLs are supplied, so that would mess
+up the protocol.  So remember: don't use this.
+
+Tried without O_NDELAY; the behavior was the same but the speed was much
+slower.
+
+Tried switching back to the ckupty.c routines on Mac OS X and found that it
+works now the same as with openpty(), except that I seem to get more getty
+babble at the end.  But this means I can run some tests on Solaris.  I moved
+the entire test environment from Mac OS X 10.4.9 to Solaris 9.  But it
+doesn't work at all.
+
+Trying to figure out the ckupty.c modules again.
+ . do_pty() calls pty_getpty() which returns in arg1 the fd of the pty master.
+ . Then it creates a pipe as a way to tell when the child dies
+ . Then it creates a fork:
+    - The parent does a blocking read from the pipe
+    - The child calls getptyslave() to get the pty slave
+      and writes one byte to the pipe
+      and then execs the command it's supposed to run
+Note that the file descriptor of the slave is known only to the lower fork.
+Therefore the lower fork is the one that has to set all the tty modes, etc.
+I took care of all that but the ckupty.c method doesn't work at all on
+Solaris.  But it works "fine" on Mac OS X (the 32K all-bytes test file
+transfers instantly with no errors, but the 96K one errors out).
+
+The problem on Solaris is that pty_make_raw() fails on the masterfd (but not
+on the slavefd) with errno 25 "ioctl inappropriate for device".  It doesn't
+matter whether I do it in ckupty.c or ckutio.c.  I found a web page on
+kde.org that says Solaris does not allow tcget/setattr() on a pty master.
+But the Sun "knowledge base" is not open to the public.  Well, presumably
+changes made to the slave are reflected in the master (comments in Solaris
+telnetd seem to confirm this...)  Let's come back to Solaris later.
+
+Moving to a Linux with lrzsz installed...  Built a Kerberos 5 version with
+USE_CKUPTY_C.  Like on Mac OS X, it transfers short files OK and chokes on
+longer ones.  Switched to openpty(), it behaves the same.  So the problems
+on Mac OS X are evidently not OS-specific, which is good I guess, since that
+means finding the way around them will apply to more than one platform.
+21 Aug 2007.
+
+Look into TIOCSCTTY again.  On System V based OS's, opening a pty acquires a
+controlling terminal automatically.  On BSD-based OS's, no; you have to use
+the TIOCSCTTY on the slave file descriptor to give it one.  I'm not sure why
+a controlling terminal would be needed, except that without one, the virtual
+device "/dev/tty" does not exist for the process that runs on the pty, and
+maybe the application that runs there (e.g. rzsz) checks for it.  On the
+downside, having a controlling terminal opens the process up to terminal
+interrupts like SIGINT and SIGQUIT.  Until now I have not been using this
+ioctl().  Results (in Linux):
+
+  With TIOCSCTTY: 96K all-bytes test: 11 screens of errors, then success
+  Without TIOCSCTTY: exactly the same.
+
+Tried the same thing with TIOCNOTTY instead of TIOCSCTTY, with exactly the
+same results (no effect whatsoever).
+
+There has to be a way to make this work, because Zmodem works through
+telnetd, which basically the same thing as ttptycmd(): a relay between the
+network and a pty.  ttptycmd() is like telnetd backwards.  Modern telnetds
+are not much help; they don't access ptys or the network directly, they go
+through "mux" devices so I can't see what they're doing to get transparency
+and flow control.  An old BSD telnetd uses packet mode but that would be a
+big deal...
+
+I tried ignoring various signals like SIGTTOU and SITSTP, since some Telnet
+clients do this.  No effect, no difference.  Anyway, in Linux the transfers
+almost always finish OK despite the many errors.  There is just some trick
+I'm missing to make the pty accept a stream of arbitrary bytes without
+hiccuping.
+
+What about Solaris, which uses ckupty.c?  In streams-based OS's, where line
+disciplines and whatnot are pushed on top of the pty, it looks like the pty
+module saves the file descriptor of the "bare" slave pty (as 'spty') before
+pushing things onto it, and then later uses spty rather than the regular
+slave pty file descriptor when getting/setting terminal modes.  I'm not sure
+what this is all about but it's definitely SysVish...  It happens if
+STREAMSPTY is defined, but I noticed that STREAMSPTY is never defined
+anywhere.  I tried defining it so we take an entirely different path through
+the code.  It made absolutely no difference.
+
+Then I noticed that HAVE_STREAMS is not defined for Solaris either.  Tried
+defining it, but the session didn't work at all, no i/o.  Removing the
+HAVE_STREAMS definition but keeping the STREAMSPTY defined, I rebuilt and
+tried "set host /connect /pty emacs".  I got an EMACS screen but could not
+type anything into it, which means that STREAMSPTY should not be defined
+either.  Removed the definition and "set host /pty" works again.  So what's
+the problem with ttptycmd()?
+
+In fact, ttptycmd() works on Solaris with Kermit as the external protocol,
+but not with Zmodem, not even with text files.  So again, there is no
+fundamental problem with the code or the logic, it's Just A Matter Of
+Transparency to control and/or 8-bit characters -- some trick I don't know
+about.
+
+Looking at the Solaris debug log...  I see that ckupty.c is calling
+init_termbuf() to set the tty modes of the master, not the slave, and
+set_termbuf() to set them, but you can't do that in Solaris, error 25.  This
+is in getptyslave().  Shouldn't getptyslave() be setting the tty modes of
+the slave, not the master?  I changed it to do this, but like all other
+changes, it made no difference.  I checked to make sure that after the change,
+"set host /pty /connect emacs" still worked and it did.
+
+And then what...  I had some code to redirect stderr in ckupty.c that was
+not being executing due to a typo.  When I fixed the typo, poof, Zmodem
+binary transfers started working, or working as well as they work in Linux
+and Mac OS X.  It turns out that if I don't redirect stderr, sz and rz
+just don't work.  But lsz and lrz do.  But if I do redirect it, I don't see
+the progress messages from lsz/lrz.  22 Aug 2007.
+
+Built on HP-UX 11i v3 (B.11.31 U ia64) with optimizing compiler, got tons of
+picky warnings, but it finished and linked and runs OK.  Many of the
+warnings were like this:
+
+  "ckucns.c", line 1606: warning #2068-D: integer conversion resulted in a
+  change of sign:   tnopt[0] = (CHAR) IAC;
+
+IAC is defined as 255 in ckctel.h.  If I define it as 0xff, I don't get the
+warnings.  I changed the definitions of all the Telnet commands to be in hex
+notation rather than decimal.  If cuts way down on the HP-UX warnings and
+doesn't seem to cause problems elsewhere.  ckctel.h, 23 Aug 2007.
+
+Now it looks like Solaris is working but then it hangs at the end.  It
+appears as if the ckupty.c module is blocking SIGCHLD.  Debug log shows that
+when the transfer is complete, we received IAC DM (Telnet Data Mark) after
+sz's last gasp and before the shell prompt is printed.  But calling
+tn_doop() in this case is a mistake because we are reading the number of
+bytes that we know are available in a counted loop, but tn_doop() would
+consume an unknown number of bytes and we would never know when to exit the
+loop.  Anyway, C-Kermit doesn't do anything with DM.  Skipping over
+tn_doop() (and not writing out the Telnet command bytes) fixes the hanging
+condition at the end, even though SIGCHLD is never raised.  ckutio.c,
+23 Aug 2007.
+
+Some tests, Solaris to NetBSD over K5.
+zst sends ascii.txt, a 2.36MB ascii text file (Kcps / Errors).
+zrt receives the same file:
+
+  zst 587/0 526/0 542/0 434/0 423/0
+  zrt 827/0 800/0 847/0 FAIL  610/0
+
+So text is good.  Binary not so good.  Here we transfer the 1MB all-bytes
+pattern file.  zrb receives it successfully, but with 1248 errors, at only
+15Kcps.  Sending the same file out always fails:
+
+  Begin 20070823 16:32:07: SEND BINARY all2.bin [sz]
+  Sending: all2.bin
+  Bytes Sent:   5600/1000000   BPS:12446    ETA 01:19   FAILURE
+  End 20070823 16:32:13
+  Elapsed time: 6.617992999999842
+  cps = 151103.2121067556
+  lsz: caught signal 1; exiting
+
+Decided to move to Linux but found that something is screwed up in Linux
+C-Kermit with tilde expansion:
+
+  send ~/testfiles/all.bin
+
+doesn't expand at all (but it did yesterday!).  The problem was in the
+ancient, ancient realuid/setuid handling code; real_uid() no longer works in
+Linux.  I worked around this in whoami() by setting ruid to getuid() if
+real_uid() returned a negative number.  Maybe dangerous, worry about it
+later.  ckufio.c, 23 Aug 2007.
+
+ANYWAY... after fixing that, I tested zsb on Linux, and it's broken there
+too, using openpty(), so it's nothing to do with ckupty.c.  After sending
+the first Zmodem data packet, it just hangs, nothing comes back.  In text
+mode it gets farther, but then the same thing happens.  Captured stderr from
+rz on the far end:
+
+  Bytes received:     608/1000000   BPS:21137  ETA 00:47  Retry 0: Bad CRC
+  Bytes received:     864/1000000   BPS:23540  ETA 00:42  Retry 0: Bad CRC
+  Bytes received:    1120/1000000   BPS:25003  ETA 00:39  Retry 0: Bad CRC
+  Bytes received:    5696/1000000   BPS:56988  ETA 00:17  Retry 0: Bad CRC
+  Bytes received:    9120/1000000   BPS:62227  ETA 00:15  Retry 0: Bad CRC
+  Bytes received:    9376/1000000   BPS:60766  ETA 00:16  Retry 0: Bad CRC
+  Bytes received:    9632/1000000   BPS:60361  ETA 00:16  Retry 0: Got TIMEOUT
+  Retry 0: Sender Canceled
+  Retry 0: Got ZCAN
+
+The local sz, however, doesn't give any error message.  ZCAN means: "other
+end canceled session by sending 5 ^X's" (or user typed them).  What actually
+happens is that ttptycmd()'s select() times out waiting for something from
+the Zmodem partner and ttptycmd() itself kills the sz fork with SIGHUP.
+When lsz receives SIGHUP it sends the ZCAN.  So the real problem is that
+after some point we're not receiving anything.
+
+I changed the timeout from 4 seconds to 30 seconds and now I see it just
+stops for long periods of time and then resumes.  The lrz log on the
+receiving end shows tons of timouts, CRC errors, and other errors.  The
+local log shows that lsz wound up sending ZCAN (2 x (10 x ^H, 10 x ^X)).
+
+Moving on to another problem...  Turns out Ctrl-C (SIGINT) is working right
+after all.  Since I'm using my test scripts like kerbang scripts, Ctrl-C
+exits through trap(), as it should, closing the connection and cleaning up.
+If I start Kermit and tell it to TAKE the script, then Ctrl-C brings me back
+to the prompt with the connection still open (as it should).  However, until
+now I haven't done anything about the fork or the ptys.  Added code to
+trap() to kill the fork and close the master pty.  ckuusx.c, 24 Aug 2007.
+
+Added code to try to break the deadlock.  If select() times out, but we have
+stuff to write either to the pty or the net, try to do it anyway, even
+though select() did not say we could.  But this doesn't help because when
+select() times out we don't have anything to write.  The problem is that
+after receiving that last packet from the remote rz, the local lsz doesn't
+seem to do anything, as if the lower fork wasn't running (and to confirm
+this hypothesis, sometimes I noticed that when I Ctrl-C'd out of this, the
+transfer would take off again).
+
+Backing up and testing with gkermit rather than zmodem:
+
+ kst ripple.txt [824K] OK
+ kst ascii.txt [1359K] OK
+ krt ripple.txt -- FAILED
+
+It seems that we can't handle streaming.  If I set up krt to disable
+streaming on receipt, it works OK.
+
+ krt ripple.txt [824K] OK
+ krb all2.bin  [1000K] OK
+
+So here we have no trouble sending but big trouble receiving unless we
+disable streaming.  Whereas with Zmodem we have trouble receiving.
+
+But this wasn't happening before, what changed?  Using C-Kermit on the far
+end to receive the file with debug log on, I see that it is sending 4K data
+packet after 4K data packet, with the local gkermit silent, as expected.
+About midway through the transfer, the local Kermit sends an error packet
+"Transmission error on reliable link".  Looking at G-Kermit's debug log...
+It receives the first five 4K data packets OK, but gets a CRC error on the
+fifth one, and sends the Error packet.  So it has received a stream of
+20-some thousand bytes OK and then messes up.  That number sounds a lot like
+ttptycmd()'s buffer size.  I changed the buffer sizes to be different:
+
+  Read from pty and write to net: 4K  
+  Read from net and write to pty: 1K
+
+This time it received the first 4K packet and failed on the second one.
+Then I increased the buffers to 98K each, expecting to receive lots more
+packets successfully but it bombed out on the 5th one.  But that's good, it
+confirms there's no logic error in the buffer management.  Just to make
+sure, though, let's set the buffer size smaller than the packet size and
+disable streaming.  In this case we get 4 good data packets and a CRC error
+on the 5th one and so we request retransmission, and the next 8 times it
+arrives it gets a different CRC error, but the 9th copy is OK.  Then the
+next packet comes and it gets a CRC error every time.  And this is nothing
+but plain ASCII text.
+
+Switching to remote mode:
+
+  REMOTE=1 kk kst
+
+(after tricking myself because it was using ttruncmd() for this...) I see
+that nothing works at all.  What did I break?  24 Aug 2007.
+
+Fixed ttptycmd() to restore console modes after a remote-mode transfer.
+ckutio.c, 25 Aug 2007.
+
+Noticed that error codes like ESRCH are not available in all modules.
+That's because of some complicated in #ifdefs in ckcdeb.h that wind up not
+always #including <errno.h>.  But I notice that ckutio.c includes it
+unconditionally with no ill effects, and so does ckvfio.c.  Does any version
+of Unix at all not have <errno.h>?  Added a catch-all clause to ckcdeb.h to
+#include <errno.h> (in UNIX only) if, after the other clauses, ESRCH was
+still not defined.  ckcdeb.h, 25 Aug 2007.
+
+Now back to debugging ttptycmd()...  Remote-mode transfers with ttptycmd()
+were broken in two places, maybe as long as 2 weeks ago (this would have
+affected non-network transfers too, which I can't test any more).
+The logic was missing in a couple places for the non-network and/or
+non-Telnet and/or non-encrypting connections (if statements with no else
+parts).  Fixed in ckutio.c, 25 Aug 2007.
+
+Testing remote mode:
+
+ kst OK   zst OK
+ ksb OK   zsb OK
+ krt OK   zrt OK
+ krb OK   zrb OK
+
+Functionally it all works but there are hitches with Zmodem as always.
+When sending to K95:
+
+ . If I send with lsz, there are hundreds of "Subpacket too long" errors,
+   and the transfer is very slow, but it succeeds.
+
+ . If I send with the 1994 Omen version of sz, transmission is instantaneous
+   and without errors, but then it hangs at the end.
+
+ . If I bypass C-Kermit and send direct from lsz or sz, both work fine.
+
+So clearly the ptys are getting in the way.  The hanging at the end would be
+caused by the sz process closing before its last output reached the master
+pty.  It would need to do some form of flushing and/or pausing at the end
+but there's nothing I can do about that; these programs were not designed to
+be used in this way.  Anyway, it only seems to happen with files longer than
+100K.
+
+For local mode, testing in Solaris over our Kerberos 5 connection again:
+
+ gkermit  lrzsz
+ kst OK   zst FAIL
+ ksb OK   zsb FAIL
+ krt OK   zrt OK but with errors
+ krb OK   zrb FAIL
+
+If I use Omen rzsz as the external protocol (e.g. with zst), it blocks
+redirection and it sends the file to my terminal, rather than over the
+connection.  This would probably be because it finds out the device name of
+the job's controlling terminal and opens it, to prevent redirection.  This
+is hard to prevent in Solaris because there is no TIOCSTTY ioctl().
+Supposedly the same thing is accomplished by closing and reopening the slave
+pty after doing setsid().  I added code to do this, but it made no
+difference.  (If I use lsz instead of sz, it is indeed redirected, but jams
+up after about 15K.)  ckupty.c, 27 Aug 2007.
+
+On Mac OS X with sz 3.73 1-30-03, however, the redirection works, so I
+assume it would also work in Linux, FreeBSD, NetBSD, etc, too.  Doing the
+full test suite on Mac OS X:
+
+ gkermit   lrzsz          rzsz
+  kst OK   zst FAIL (1)    OK
+  ksb OK   zsb FAIL (2)    OK
+  krt OK   zrt OK   (3)    OK for 100K file, fails for longer.
+  krb OK   zrb FAIL (4)    OK (1MB all-bytes test pattern)
+
+(1) 64K file OK every time; 100K file fails every time.
+(2) 10K file fails every time.
+(3) Succeeds with 800K file but gets a few recoverable errors.
+(4) Succeeds with 48K binary file with some errors, fails with longer ones.
+
+So actually it looks pretty good, it's just that lrzsz messes up.  When
+sending with lsz if I include -L 512 it sends the 100K test file with no
+errors, but still chokes on longer ones.
+
+Testing on Mac OS X again, but this time over a clear-text Telnet connection:
+
+ gkermit        lrzsz    rzsz
+  kst OK   zst  FAIL(1)   OK
+  ksb OK   zsb  FAIL(2)   OK
+  krt OK   zrt  OK(3)     OK
+  krb OK   zrb  FAIL(4)   OK 
+
+(1) Almost worked, finished 777K out of 824K without errors.
+(2) Got tons of errors, failed in first 30K out of 1000K.
+(3) OK for 100K file but fails for larger.
+(4) OK for 48K binary fail but fails for larger.
+
+Maybe see if we can do without the OPENPTY part.
+
+TOMORROW -- just clean up the code, add some SET / SHOW / HELP commands,
+document it, and move on.
+
+Note: In K95, SET WINDOW sets the Zmodem packet length, 32 - 1024, multiple
+of 64.
+
+SEE ~/80/external.txt
+
+Changed ftp port from int to unsigned int.  ckcftp.c, 30 Aug 2007.
+
+Tried again to build KRB4/KRB5/SSL/TLS version for Solaris 9.  Had to update
+the build procedure again, of course, because of new file and directory
+names, but ran into problems anyway because the
+cu-solaris9g+krb5+krb4+openssl+shadow+pam+zlib target was calling another
+target that did not know about the hardwired pathnames.  Integrated the two
+targets and tried building again.  It actually compiled ok (but with lots of
+warnings from the security modules), but failed at link time with
+krb5_init_ets not found; fixed that with an #ifdef NO_KRB5_INIT_ETS, now it
+builds OK but without the ftp client.  Tried building it WITH the FTP and
+that was OK too, no changes needed except to the build procedure.  12 Feb
+2008, that is: C-Kermit 8.0.212 : 20080212.
+
+Tried to build with -DCK_SRP and -lsrp but:
+
+  hash_supported                      ckcftp.o
+  hash_getdescbyname                  ckcftp.o
+  hash_getdescbyid                    ckcftp.o
+  cipher_getdescbyname                ckcftp.o
+  krypto_delete                       ckcftp.o
+  krypto_new                          ckcftp.o
+  cipher_supported                    ckcftp.o
+  krypto_msg_priv                     ckcftp.o
+  krypto_msg_safe                     ckcftp.o
+  hash_getlist                        ckcftp.o
+  cipher_getlist                      ckcftp.o
+  cipher_getdescbyid                  ckcftp.o
+
+Sent mail to Tom Wu and backed off for now.  makefile, 14 Feb 2008.
+(Tom Wu never answered; seems like SRP is defunct.)
+
+The ".blah = xxx" form of variable assignment only worked for variables
+names of length 22 or less, noticed and fixed by Wolfram Sang.  ckucmd.c,
+5 Mar 2008.
+
+In "set host /pty ssh ..." connections, the INPUT command suddenly stopped
+working.  This is in Solaris 9.  It happens with all 8.0.* versions of
+C-Kermit, so it's nothing to do with ttptycmd().  Added some debug()
+statements but they don't show anything.  Turns out there wasn't a problem
+after all.  Wed Mar 26 16:04:53 2008
+
+Changed cmifi() to not print "?No files match" (or whatever) if SET QUIET ON.
+ckucmd.c, 26 Mar 2008.
+
+Added \v(remoteip) for the IP address of the host we're connected to,
+and \v(inmessage) for INPUT status messages corresponding to \v(instatus).
+ckuusr.h, ckcmai.c, ckuus[24].c, 26 Mar 2008.
+
+Made \fkeywordval() strip braces/quotes from the right-hand side so we can
+handle things like:
+
+  password="stringwithspaceatend "
+
+ckuus4.c, 6 Aug 2008.
+
+Added invisible PUTENV command for UNIX only.  Value should not be enclosed
+in doublequotes.  Requires lge \v(buildid) 20080826.  ckuusr.[ch], 26 Aug 2008.
+
+Added SET VARIABLE-EVALUATION { RECURSIVE, SIMPLE }.  This is highly
+experimental, but also highly desirable if it works out.  SIMPLE inhibits
+the default recursive method of evaluating \%x and \&x[] variables, which
+is, quite frankly, nuts and makes programming in Kermit at best
+counterintuitive.  I made an exception in the case of array subscripts,
+because changing how they are evaluated could break a lot of scripts, and
+anyway there should never be any harm in evaluating them recursively because
+their final value is always (or should be) numeric, not some string that
+might contain backslashes.  The SET VAR setting is on the stack, just like
+SET QUIET (it follows the quiet/xquiet code in ckuus[356].c), so macros or
+command files that change it can't break the script that invokes them.
+Added \frecurse() to force recursive evaluation of a \%x or \&x[] variable
+regardless of the VARIABLE-EVALUATION setting.  Added \v(vareval) to allow
+programmatic setting to current setting.  Tested on Solaris 9 but should be
+totally portable.  ckuusr.[ch], ckuus[356].c, 11 Sep 2008.
+
+From Günter Knauf: 64-bit builds were failing on SuSE Linux because
+libresolv and libcrypt were in lib64 rather than lib; updated the tests in
+the linux makefile target to find them.  makefile, 12 Jan 2009.
+
+Tried building on Red Hat Enterprise Linux Server release 5.3 64-bit.
+There is no curses or ncurses.  "make linuxnc" compiled OK but collapsed at
+link time looking for crypt(), res_search(), and dn_expand().  Turned out
+the linuxnc (and linuxc) targets needed the same treatment as the Linux one
+for 64-bit Linuxes.  makefile, 3 Mar 2009.
+
+Consolidated the linux targets so we no longer need three separate ones for
+curses, ncurses, and no curses.  "make linux" works ok on computers with and
+without (n)curses.  "make linux+ssl", ditto.  "linux+krb5+ssl builds OK but
+needs -DNO_KRB5_INIT_ETS".  Makefile, 3 Mar 2009.
+
+Fixed copyright date announced in herald, ckuus5.c, 3 Mar 2009.
+
+Patch from Seth Therault to avoid deprecation warning for utmp references
+in ckufio.c in Mac OS X 10.5 (later, this became a consolidated makefile
+target that works automatically for at least Mac OS X 10.3.9 through
+10.5.6).  makefile, ckufio.c, 28 April 2009.
+
+zshcmd() (the function used by RUN and ! to run external commands) was not
+falling back as expected in Linux RHEL4/5 if SHELL was not defined in the
+environment.  Also in all Unix versions, there was no indication if a RUN/!
+command failed (other than the return code) because the specified shell
+didn't exist or was not executable (e.g. the SHELL environment variable was
+misdefined).  Now it prints the name of the offending shell and the reason
+it couldn't be executed (Not found, Permission denied, etc).  ckufio.c,
+28 April 2009.
+
+There is no easy way to get the last field of string; for example, the
+extension from a filename, which might have any number of fields.  In
+general we want to be able to get "word number n" counting from the right;
+\fword() lacks this ability.  Now if you give it a negative word number,
+that says to count from the right; for example \fword(one two three four
+five, -2) returns "four".  ckclib.c, ckuusr.c, 14 May 2009.
+
+Fixed a typo in the aix51+openssl (SSLLIBS should have been SSLLIB).
+From Jason Lehr.  makefile, 27 May 2009.
+
+Updated the linux+openssl+zlib+shadow+pam target to chain to the new main
+Linux target.  A bunch of other ones remain un-updated. makefile, 12 Jun 2009.
+
+Updates to the new Mac OS X 10.5 target from Seth Therault (which is
+supposed to work on all Mac OS 10-point-anything) to avoid warnings
+that came up on on Mac OS 10.4.11/Intel.  Once this one is proven we should
+be able to remove/consolidate lots of other ones.  makefile, 12 Jun 2009.
+
+C-Kermit disables SSL with the message "?OpenSSL libraries do not match
+required version." if the version of OpenSSL that Kermit was built with is
+not exactly the same as the version that is loaded dynamically at runtime.
+This is actually the proper behavior, since APIs are not guaranteed not to
+change between OpenSSL versions prior to 1.0.0.  Made the error message more
+informative.  ck_ssl.c, 26 Aug 2009, and again 28 Aug 2009.
+
+AIX 6.1 is out, it is really just a new name for AIX 5.4.  Added makefile
+targets, plus for the first I made AIX 4.2 and later figure out its version
+number in the makefile target so we don't have to keep adding new -DAIXnn
+sections to the code, and also get its hardware name (e.g. "powerpc") from
+uname at make time, rather than hardwiring "rs6000" as I did before.
+Consolidated all AIX 4.2 and later targets so now just "make aix" or "make
+aix+ssl" can be used.  Except not the gcc ones as they have some quirks so
+I'd rather not disturb them.  Tested this on AIX 5.3.
+makefile, 28 Aug 2009.
+
+From Kinjal Shah, a correction to the Linux makefile entry that allows it
+find the 64-bit curses or ncurses library.  makefile, 29 Aug 2009.
+
+Renamed aix4[23]: to oldaix4[23]: in makefile to fix the warning messages
+I didn't notice before.  I didn't want to remove them because they have
+some special things that might still be needed, if anybody still has these 
+AIX versions.  makefile, 29 Aug 2009.
+
+Built on RHEL 5.3 64-bit, regular and with OpenSSL 0.9.8e.  31 Aug 2009.
+
+Built on NetBSD 5.0.1/i386, regular and with OpenSSL 0.9.9-dev, 1 Sep 2009.
+
+Changed SSL message to mention LD_LIBRARY_PATH (Solaris), SHLIB_PATH (HP-UX),
+LIBPATH (AIX), or LD_LIBRARY_PATH (Linux).  ck_ssl.c, 3 Sep 2009
+
+Noticed that "make linux+openssl" fails to include -lutil a link time, which
+it needs for openpty().  That's because this target is obsolete.  I renamed
+it to be oldlinux+openssl and added linux+openssl as a synonym for
+linux+ssl.  makefile, 3 Sep 2009.
+
+Tested linux+openssl+zlib+shadow+pam, it's OK.  Also linux+krb5.  Also
+linux+krb5+ssl.  makefile, 3 Sep 2009.
+
+Tried building on Solaris 9 with OpenSSL 0.9.8k with
+solaris9g+openssl+shadow+pam+zlib, it failed like so:
+
+  ck_ssl.c:2875: error: conflicting types for 'inet_aton'
+  /usr/include/arpa/inet.h:52: previous declaration of 'inet_aton' was here
+  make[2]: [ck_ssl.o] Error 1
+  make[2]: Leaving directory hmt/sirius1/prv0/kd/fdc/solaris9ssl'
+  make[1]: [solaris2xg+openssl+zlib+pam+shadow] Error 2
+  make[1]: Leaving directory hmt/sirius1/prv0/kd/fdc/solaris9ssl'
+  make: [solaris9g+openssl+shadow+pam+zlib] Error 2
+
+The problem was caused by including an inet_aton() function ck_ssl.c for
+the benefit of platforms that don't have one in their libraries.  This is
+defeated by including NO_DCL_INET_ATON in KFLAGS.  I added this, but then
+I thought it would be a good idea to automatically sense the OpenSSL
+version so we can automatically set OPENSSL_097 or OPENSSL_098 rather than
+bombing out, so I added code to do that too, and also to set the Solaris
+version number: 9, 10, or 11.  The new entry is solaris9g+openssl.
+ckcdeb.h, makefile, 3 Sep 2009.
+
+Fixed a complaint in ckufio.c about implicit declaration of initgroups.
+ckufio.c, 4 Sep 2009.
+
+Built on Solaris 10 with gcc and Sun CC using new solaris{9,10,11} target
+that is like the new solaris{9,10,11}g one but without the gccisms.
+makefile, 4 Sep 2009.
+
+Changed solaris{9,10,11}g+ssl target to set only the SSL-specific things and
+then chain to the main solaris{9,10,11}g target.  Tested OK on Solaris 9 and
+10.  makefile, 4 Sep 2009.
+
+Created solaris{9,10,11}+ssl target that is exactly like the
+solaris{9,10,11}g+ssl except it chains to the solaris{9,10,11} target
+instead of the solaris{9,10,11}g one.  That is, it builds an SSL version of
+C-Kermit using Sun CC rather than gcc.  makefile, 4 Sep 2009.
+
+Tried building on HP-UX 10.20, bundled (non-ANSI) compiler ("make
+hpux1000").  This failed until I:
+
+ . Moved a struct inititialization out of setextern(), ckuus3.c.
+ . Removed an ANSIism from the declaration of sigchld_handler() in ckutio.c
+ . Added a cast to strcmp() in zvuser(), ckufio.c.
+
+Builds OK now.  Built OK with "hpux1000o" (the ANSI compiler) too.
+And with "hpux1000gcc".  Couldn't test "hpux1000o+openssl".  21 Sep 2009.
+
+The Sony Playstation 2 and 3 are 64-bit PowerPC platforms that can run Linux
+if it is installed as an "other OS" on its hard disk; and the Linux kernel
+since 2.6.21 supports the PS3 without any patching required.  Pawel Rogocz
+reported that "make linuxppc" (one of the old targets that has not yet been
+integrated into the main "linux" target) compiles OK on 2.6.29-ydl61.3
+(Yellow Dog Linux release 6.2 'Pyxis'), but fails at link time because
+'openpty' isn't found, because -lutil was not included, because that part
+was added only to the main linux target.  I asked him to try "make linux"
+and he sent back a transcript in which there were thousands of errors from
+the curses code ckuusx.c.  Later I tried it myself and it built without a
+hitch.  My theory is that between then and now, a missing piece of the
+ncurses library (/usr/include/ncursesw) was installed.  21 Sep 2009.
+
+HP-UX 9.05 on PA-RISC 9000/712 building with hpux0900 (bundled compiler):
+ . ckutio.c compilation failed with PENDIN and FLUSHO not defined in
+   pty_make_raw().  I dummied definitions for them to handle this situation
+   on this or any other platform where it might crop up.
+   ckutio.c, 24 Sep 2009.
+ . Ditto for the PTY module, + IMAXBEL.  ckupty.c, 24 Sep 2009.
+ . References to endusershell() were fatal in the bundled compiler.  Changed
+   the hpux0900 target to define NODCLENDUSERSHELL, and put a special case
+   in ckufio.c to not put a cast in front of the call if NODCLENDUSERSHELL
+   is defined.  Now it builds and links OK.  makefile, ckufio.c, 24 Sep 2009.
+
+HP-UX 9.05 on PA-RISC 9000/712 building with hpux0900o (optimizing compiler):
+ . Warnings in ckutio.c at line 14860 about arguments to select (pointers
+   are not assignment-compatible).  "man select" says arguments are ints.
+   Defining INTSELECT fixes these warnings but results in fatal errors later
+   around line 14881 and others in the area involving FD_SET.  This was too
+   involved so I put it back as it was.  24 Sep 2009.
+
+Built OK on Solaris 10 with Sun CC.  A couple warnings about implicit
+function declarations for curses routines because apparently they aren't
+declared in curses.h.  Tuff.  25 Sep 2009.
+
+Tried building on Solaris 10 with Sun CC and OpenSSL 0.9.8k, and this
+uncovered various loose ends in the solaris9+openssl target, which I fixed.
+makefile, 25 Sep 2005.
+
+Fixed four typos in printfs in ck_ssl.c, \% instead of just %.  25 Sep 2009.
+
+Squelched 20-some complaints about a character array being referred to
+directly instead of by a pointer, plus several other similar nits to get rid
+of all the compilation warnings on Solaris 10 with Sun C 5.8 Patch 121015-06
+2007/10/03.  ckctel.c, ckctel.h, 25 Sep 2009.
+
+Built the result on the same Solaris 10 system with gcc 4.2.4 using the
+new solari10g+openssl target, working out a few kinks here too.
+makefile, 25 Sep 2009.
+
+Made consolidated Solaris 9/10/11 64-bit targets for gcc, solaris9g64,
+solaris10g64, solaris11g64, tested on Solaris 10 Sparc. makefile, 25 Sep 2009.
+
+Made consolidated Solaris 9/10/11 64-bit targets for Sun cc: solaris9_64,
+solaris10_64, solaris11_64.  These simply set a couple flags and chain to
+the main solaris9 target.  makefile, 25 Sep 2009.
+
+Removed a bunch of old superfluous Solaris 9 and 10 targets: oldsolaris9,
+oldsolaris9lfs, solaris9g64 solaris9g_64, oldsolaris10 old solaris10lfs,
+oldsolaris10+openssl, oldsolaris10g+openssl, solaris10_64, oldsolaris10g,
+solaris10g_64, solaris10g64.  There are still plenty more to prune but it's
+a start.  makefile, 25 Sep 2009.
+
+Added or fixed some missing prototypes in ckctel.h:
+fwdx_send_xauth_to_xserver(), fwdx_parse_displayname.  25 Sep 2009.
+
+Improved the instructions for building secure versions in the makefile,
+using this example:
+
+  make solaris9+openssl "SSLINC=-I/opt/openssl-0.9.8k/include" \
+   "SSLLIB=-L/opt/openssl-0.9.8k/lib"
+
+makefile, http://kermit.columbia.edu/security.html, 25 Sep 2009.
+
+Built on HP-UX 11.11, 26 Sep 2009:
+ . make hpux1100 (ok)
+ . make hpux1100gcc (ok)
+ . make hpux1100o (gets a lot of warnings about sendpath and sendfile,
+    because they are also declared in <sys/socket.h>, but builds OK)
+ . make hpux1000gcc+openssl \
+    SSLINC=-I/opt/openssl/include SSLLIB=-L/opt/openssl/lib
+
+Note: sendpath and sendfile are not Kermit symbols.  The warnings are coming
+from socket.h: 'Redeclaration of "sendfile" with a different storage class
+specifier'.  This is nothing new; see notes of 2-4 Jan 2005.
+
+From Peter Eichhorn:
+ . Update to makefile to make current code build OK on HP-UX 8.00.
+ . Changes to format of some hints to make them more copy-and-pastable.
+makefile, ckuu5.c, 28 Sep 2009.
+
+From Peter Eichhorn: Changes to HP-UX 7.0 target to increase the switch table
+stack size, which was overflowing.  makefile, 30 Sep 2009
+
+HP-UX 6.5 (1989), "make hpux0650tcpc"... (8:19...)  Needed to not include
+arpa/inet.h (which doesn't exist) and not use host address lists (add
+-DNOHADDRLIST), which gets us past ckcnet.c, but in ckcftp.c we bomb out on
+FD_SETSIZE undefined.  Somehow we worked around this in ckcnet.c.  Patched
+in a definition in ckcftp.c, and also added -DINTSELECT to compiler flags.
+Compiles ok, bombs at link time on bcopy, bzero, FD_ZERO, FD_SET, FD_ISSET.
+Now it compiles and links OK but dumps core when started.  Added
+-DNOCKGETFQHOST, rebuilt from scratch (takes 35 minutes).  It starts OK, but
+it dumps core when given a "telnet xxx" command, where xxx is a hostname.
+However, it works OK if an IP address is used: "telnet 123.45.6.78".  It
+took all day to track this down, but now it's fixed (see the #ifdef HPUX6
+sections of ckcnet.c).  So now (for the first time, I think) we have both
+telnet and ftp in HP-UX 6.x, if anyone cares.  ckcnet.[ch], ckcftp.c,
+makefile, 2 Oct 2009.
+
+Changed default SET TERMINAL TYPE type for K95 from vt320 to vt220.  This is
+because Unix OS's such as Solaris have dropped vt320 as a terminal type.
+settrmtyp(), ckuus7.c, 5 Oct 2009.
+
+I moved the PUTENV command code, which was inline, to a function, doputenv().
+ckuus[r7].c, ckuusr.h, 5 Oct 2009.
+
+Changed the UNIX version of SET TERMINAL TYPE to take a value and then do
+the equivalent of "export TERM=value" by calling doputenv().  This sets
+\$(TERM) correctly and passes its value along to inferior processes.
+However, to make this take effect within Kermit itself (for the fullscreen
+file transfer display and for the SCREEN command, Ctrl-L, etc) I also had to
+reinitialize the curses database, which is tricky because normally if you
+feed it an unknown terminal name, it just exits.  ckuus7.c, 5 Oct 2009.
+
+Changed the little-known and little-used RESET command (which closes all
+open files) to also put command echoing back to normal in case it got
+messed up somehow (as in HP-UX 6.5, upon returning from PUSH).
+ckuusx.c, 5 Oct 2009.
+
+For Unix, increased string buffer sizes for wildcard expansion for all
+platforms that have BIGBUFOK defined from 500000 (0.5M) to 10000000 (10M)
+bytes, and for 64-bit builds to 2000000000 (2G) bytes.  No point making
+it bigger than that because malloc's argument is a size_t, which is an int.
+ckufio.c, 5 Oct 2009.
+
+Built on Mac OS X 10.4.11, required one minor adjustment to the makefile
+(-DNODCLINITGROUPS).  This was using the macosx10.5 target, which is
+supposed to be universal like the linux and netbsd targets, but not yet
+proven.  Also built a 64-bit version (-mpowerpc64 -mcpu=G5 -mtune=G5
+-arch ppc64); it compiles and links OK but won't start: "Bad CPU Type
+in executable".  Fix later...  makefile, 5 Oct 2009.
+
+Changes from Seth Theriault to suppress signed vs unsigned char warnings in
+Mac OS 10.5.8 from gcc4, and a new makefile target for Mac OS X (presumably
+10.3.9 or later) + Kerberos 5 and OpenSSL.  ckutio.c, ckuath.c, ckctel.c,
+ckcnet.c, ckcftp.c, ck_crp.c, makefile, 6 Oct 2009.
+
+  Later I had to back out of these, because although it made for a
+  clean build, in the resulting executable SSL connections didn't work.
+
+Tue Oct  6 17:23:27 2009
+FTP address resolution is broken, but ftp_hookup() hasn't changed.
+So... (see the #ifdef HPUX6 sections of ckcnet.c)  (I did, and I rolled
+back some of the changes from the other day, but it made no difference.)
+Putting back the ckcftp.c from a few weeks ago makes no difference.
+Putting back the ckcnet.c from a few weeks ago makes no difference.
+
+Added patches from Seth Theriault so macosx10.5+krb5+openssl would build
+on Mac OS X 10.3.9.  makefile, ckcftp.c, 7 Oct 2009.
+
+Built today's code on Linux RHEL4, NetBSD 5.0.1, Solaris 9, and Mac OS X
+10.4.11, both with and without SSL.  The NetBSD system has OpenSSL 0.9.9-dev.
+7 Oct 2009.
+
+In Mac OS X 10.6, the following symbols are unresolved at link time:
+_des_key_sched, _des_new_random_key, _des_ecb_encrypt,
+_des_init_random_number_generator, _des_fixup_key_parity.  This is
+with OpenSSL 0.9.8k.  But it doesn't happen on other platforms that
+have 0.9.8k.
+
+Added SET SESSION-LOG NULL-TERMINATED-TEXT.  This is for the benefit of a
+speech synthesizer that will speak a line of text only after receiving a
+NUL character.  A more general solution would be to define a filter or
+whatever, but who has time.  ckuus[23x].c, 7 Oct 2009.
+
+Consolidated Mac OS X targets, and removed experimental 64-bit ones, because
+they never could work in 10.5 and earlier because 64-bit libs are missing,
+and 10.6 and later are 64-bit automatically.  makefile, 8 Oct 2009.
+
+Built on Mac OS X 10.6.1.  It came out automatically as a 64-bit build
+because __LP64__ is defined somewhere that I can't find.  But this explains
+why the 0.9.8k on 10.6 comes up with missing symbols when the 0.9.8k lib
+10.5 (or on Solaris or on Linux) does not: it's a different library: "Mach-O
+64-bit dynamically linked shared library x86_64", rather than "Mach-O
+dynamically linked shared library ppc".  Probably the 64-bit version has
+some things #ifdef'd out.  Added -m32 to the CFLAGS and LNKFLAGS for the
+macosx+krb5+openssl targets, and it built OK one time.  But then the errors
+came back.  makefile, 8 Oct 2009.
+
+Updated C-Kermit installation for Mac OS X in ckuwr.html on the website.
+8 Oct 2009.
+
+Tried some things to get around the problem with OpenSSL in Mac OS X 10.6,
+to no avail.  Asked Jeff.  He said, "MacOS X no longer includes DES anywhere
+on the system.  Not for SSL, not for Kerberos, not for anything.  This will
+increasingly become the situation on new operating systems.  Windows 7 and
+2008 R2 will also ship with no DES."  Sure enough, the Mac OS X Server
+Upgrading and Migrating document for 10.6 says, "Mac OS X Server v10.6 does
+not support single DES encryption. It supports AES 128 and 256 encryption
+types. However, during a migration or upgrade from v10.4 to v10.6, servers
+that were Kerberized by the v10.5 Open Directory server will not use the AES
+128 or 256 encryption types. To use the AES 128 or 256 encryption types you
+must re-Kerberize all servers."  12 Oct 2009.
+
+DES and 3DES encryption can be excluding removing the -DCK_DES flag.  I
+removed this one and -DLIBDES (and -m32) and this makes a working 64-bit
+version.  Then I added code to the macosx+krb5+openssl target to use these
+flags if the Mac OS X version was 10.5 or less and leave them out for 10.6
+or later.  Tested on 10.4.11 and 10.6.1.  A better way to do it might have
+been "nm -gj libssl.dylib | grep des_", but that gives the same results on
+10.4 and 10.6.  Also, 10.6 still has /usr/include/ssl/des.h.
+makefile, 13 Oct 2009.
+
+Next issue:
+  In file included from ckutio.c:15674:
+  /usr/lib/gcc/i386-redhat-linux/3.4.6/include/varargs.h:4:2: #error "GCC no
+  longer implements <varargs.h>."
+  /usr/lib/gcc/i386-redhat-linux/3.4.6/include/varargs.h:5:2: #error "Revise
+  your code to use <stdarg.h>."
+
+The problem occurs when trying to force a non-ANSIC build with GCC.
+Changing the source file to include <stdarg.h> instead of <varargs.h>
+doesn't help because evidently <stdarg.h> requires an ANSI C compiler.
+Nothing can be done about this.  13 Oct 2009.
+
+Next issue: Can't compile ckcftp.c with -DNOCSETS or -DNOSPL; some
+#ifdef/#endif doesn't match up.  Sigh, this is the hardest kind of thing to
+debug.  There's 17,622 lines of code in this module and no tool that I know
+of.... Wait, I wrote one.  But it shows all the #if/#ifdef/#ifndef's and
+#endifs matching up just fine.  Backing off to ckcftp.c of a few days ago
+(before char / unsigned char casts were added), I see that it builds OK, so
+I backed off to that one, but put back the special case #ifdef for MACOSX103
+declaring CONST gss_OID_desc, and it builds OK (the other stuff was purely
+cosmetic, when will I learn?).  ckcftp.c, 13 Oct 2009.
+
+Protected cvtstring() and related functions with #ifdef NOCSETS..#endif,
+and ditto for the character-set conversion code in dorename().
+ckuus6.c, 13 Oct 2009.
+
+Fixed an #endif /* TNCODE */ that was a line too low in ttptycmd(),
+causing -DNONET builds to fail.  ckutio.c, 13 Oct 2009.
+
+There was a reference to doputenv() that wasn't guarded by #ifndef NOPUTENV,
+fixed in ckuus7.c, 13 Oct 2009.
+
+Moved doputenv() and settermtyp() out of an #ifdef NOLOCAL section because
+these are useful even when not making connections.  ckuus7.c, 13 Oct 2009.
+
+Moved havelfs declaration outside of #ifdef NOXFER because it was also used
+for other things.  ckcmai.c, 13 Oct 2009.
+
+COPY /PRESERVE depended on code from the Kermit protocol module, which
+is omitted in -DNOXFER builds.  Disabled COPY /PRESERVE in -DNOXFER
+builds.  ckuus6.c, 14 Oct 2009.
+
+SHOW PROTOCOL code for external protocols had to be #ifdef'd out for
+-DNOPUSH builds.  ckuus4.c, 14 Oct 2009.
+
+There was some confusion between "No XYZMODEM" and "No extermal protocols";
+cleared up in ckuus3.c, 14 Oct 2009.
+
+After all that, 86 different combinations of feature selections built OK on
+Linux.  And the Kerberized version (K5) works OK on Linux for Telnet and FTP.
+14 Oct 2009.
+
+Changed version number to 9.0.  All modules, 16 Oct 2009.
+
+Need to make LOG SESSION log to a tty.  Right now "log session
+/dev/ttyKeySerial1" says "Write permission denied" even though the device is
+crw-rw-rw-.  This happens in zchko(), which is called by cmofi().  The
+problem is that /dev/ is not writeable.  I added a Unix-only clause that
+attempts to open the file for write access using open(), in order to get a
+file descriptor, which then can be passed to isatty() to check if it's a
+tty, and if so, to allow access.  And then close it.  I tested this on Mac
+OS X as follows:
+
+  log session /dev/ttyKeySerial1
+  telnet somehost
+
+The Mac's serial port was connected to the serial port of another computer
+where Kermit displayed the incoming characters in CONNECT mode.  Glitches:
+
+ 1. The port has to be set up as desired in advance, outside of Kermit.
+ 2. log session /dev/ttyKeySerial1 will hang if any required modem signals
+    are not present when the port is opened.
+ 3. Bypasses lockfile mechanism - so we do this only if -DNOUUCP.
+
+For (2), I tried setting O_NDELAY / O_NONBLOCK, and this allowed zchko() to
+continue, but then it freezes in the subsequent fopen().  So I changed
+zopeno() to also check if the device is a serial port, and if so, to open()
+it with O_NDELAY / O_NONBLOCK, and then convert the file descriptor into a
+file pointer with fdopen().
+
+Now for the speaking device that needs lines to be terminated by NUL...
+
+  set session-log binary       <-- need to put these in SHOW LOG
+  set session-log null-padded      (and in HELP SET LOG)
+  set line /dev/ttyKeySerial1
+
+This part works.
+
+This feature is enabled only for -DNOUUCP builds because serial ports aren't
+like other Unix files; we would have to create a lockfile, but we can't do
+that...  actually, ttlock() takes a name as an argument, but ttunlck() does
+not, so there would be no way to remove the lock.  Anyway, there is only one
+API for configuring the port (speed, flow control, etc) and it only works
+with the SET LINE device, not any random file.  To fix this would require
+massive redesign and changes.  ckuus[23].c, ckufio.c, 19-20 Oct 2009.
+
+I made -DNOUUCP the default for Mac OS X, since everybody winds up building
+it that way anyhow.  To undo this, do "make macosx KFLAGS=-UNOUUCP".
+makefile, 21 Oct 2009.
+
+Changed SET SESSION-LOG TEXT to strip out ANSI escape sequences; 
+previously there wasn't that much difference between TEXT and BINARY logs.
+It's still not perfect; for example it doesn't delete characters that the
+user erased.  (Made sure this still builds with -DNOESCSEQ.)
+ckucns.c, 22 Oct 2009.
+
+Changed SHOW LOG to show the SET SESSION-LOG settings, as well as
+SET DEBUG, which was not shown before.  ckuus5.c, 22 Oct 2009.
+
+If a series of PUTENV commands is given, each new one undoes the previous
+one, so only the last definition is seen by the new fork (or by Kermit
+itself).  Turns out you can't feed automatic variables to putenv(); they
+have to be static, so to allow for multiple PUTENV commands Kermit has to
+maintain an array of static strings.  ckuus7.c, 6 Nov 2009.
+
+From Seth Theriault, a better way for the makefile to determine the
+Mac OS X version number; there's a program for this, sw_ver.  makefile,
+6 Nov 2009.
+
+Peter Eichhorn reported that file-transfer failure hints were not coming
+out since Dev.27.  The only change I made since then was to skip them if
+the file-transfer protocol was not Kermit.  I was using the wrong variable
+in the tests, 'proto' instead of 'protocol'.  ckuus5.c, 6 Nov 2009.
+
+Changed Mac OS X targets to correctly extract the Mac OS major version
+from uname -r in order to choose correctly between utmp and utmpx; this
+wasn't working in 10.6.1.  makefile, 6 Nov 2009.
+
+Fix from Seth T. for an oversight in the previous edit.  Also add
+MACOSX103 to "show features" display.  makefile, ckuus5.c, 10 Nov 2009.
+
+Added REJECT as a synonym for DISCARD in SET FILE COLLISION; it's more
+intuitive and more accurate.  ckuus[27].c, 15 Nov 2009.
+
+\fsplit() and \fword() always break on 8-bit characters unless you explicitly
+put every single 8-bit value into the include set, e.g. (for a TSV file):
+
+  undef include
+  for \%i 128 255 1 {
+      if == \%i 9 continue
+      .include := \m(include)\fchar(\%i)
+  }
+  .\%n := \fsplit(\m(line),&a,\9,\m(include))
+
+I changed cksplit() to treat all 8-bit bytes 128-255 as non-break characters
+by default.  It might have made more sense to do this for 160-255 (since
+128-159 are traditionaly C1 control characters) but thanks to Microsoft
+tradition is out the window.  To treat one or more 8-bit characters as break
+characters, put them in the break set.  This might break some scripts, but I
+doubt it because this flaw was so awful that if anyone had come up against
+they would have let me know.  ckclib.c, 16 Nov 2009.
+
+Changed the netbsd target to set -funsigned-char, since cc on NetBSD is
+actually gcc.  makefile, 16 Nov 2009.
+
+Changed macosx targets to get the CPU type from the HOSTTYPE environment
+variable.  Also added getenv("HOSTTYPE") as a last-resort method to set the
+\v(cpu) variable at runtime (maybe it should be the first resort?)...
+ckuus4.c, makefile, 16 Nov 2009.
+
+Made sure the solaris9_64 and solaris10 targets still work.  16 Nov 2009.
+
+Made sure the current source package builds OK on HP-UX 10.20...  Got a lot
+of "warning 6062: Optdriver: Exceeding compiler resource limits in xxx; some
+optimizations skipped. Use +Onolimit if override desired" but it builds OK.
+Tested long file transfer; works OK.  17 Nov 2009.
+
+Built on FreeBSD 7.2 with and without OpenSSL, all OK.  17 Nov 2009.
+
+Built on NetBSD 5.0.1 with and without OpenSSL, all OK, but netbsd+krb5
+fails with "can't find -lgssapi_krb5"; worked around this with
+"K5LIB=-L/usr/local/kerblib" (where the lib actually is on this host) but
+then it failed with "ckcftp.c:13868: error: 'gss_nt_service_name' undeclared".
+17 Nov 2009.
+
+I found a VMS 6.2 system... Takes a loooong time to build there.  In
+ckuusy.c, DEC C didn't like the prototypes and declarations of dorlgarg()
+and dotnarg() as static so I made them not static.  But that didn't help,
+now it fails at the very end, saying the final #ifdef is an invalid
+statement.  It looks like an #ifdef mismatch that affects only VMS.  I ran
+my #ifdef matcher, it turned up nothing.  I substituted a copy of ckuusy.c
+from 2007, it comes up with the same errors.  Then I substituted the copy
+from 8.0.211 from 2004, and this one compiled OK and, miraculously, the
+whole mess even linked OK and runs OK.  The Alpha binary is 2.84MB.  Now I
+have 4500 lines of code to compare....  I went through the two files line by
+line and I can't see a single thing wrong.  I gave up and tried building the
+TCP/IP version.  It builds fine except for ckuusy.c, with the utterly
+useless error message:
+
+  #endif /* NOCMDL */
+  ...................^
+  %CC-E-BADSTMT, Invalid statement.
+
+Indicating the last line in the file.  Just for the heck of it, I put
+another line after that one:
+
+  /* This is a test */
+
+and got:
+
+  /* This is a test */
+  ....................^
+  %CC-E-BADSTMT, Invalid statement.
+
+So it is not objecting to anything in the file.  Trying the old LISP trick,
+I put an extraneous closing bracket after that.  Success!  Honestly, I don't
+see anything wrong with file.  It's DEC C V5.3-006.  I suspect a C bug.
+I'll leave it like this for now until I get access to some other VMS
+versions.  Another clue is that when building the network version I get a
+horrible warning I never saw before from a module that hasn't been touched
+in a very long time (ckvrtl.c).  Also, in the network version, I note that
+the FTP code is not compiled in.  We have to try this again with some
+command-line switches, but it'll do for now.  ckuusy.c, 18 Nov 2009.
+
+---C-Kermit 9.0 Alpha.01---
+
+From Steven Schweda (SMS), the real solution for the VMS closing brace
+problem, it wasn't a DECC bug, it was a me bug.  ckuusy.c, 20 Nov 2009.
+
+Rediscovered the new VMS build options: f for Long Files, i for Internal
+FTP.  "make mnf" doesn't work on VMS 6.2, it looks like the VMS definition
+for CK_OFF_T got lost.  Same thing with "make mfi".  Come back to this later.
+
+From Gerry Belanger, a fix to INPUT /COUNT:n.  ckuus4.c, 26 Nov 2009.
+
+Added \fsqueeze(s), returns string s with leading and trailing whitespace
+removed, Tabs converted to Spaces, and multiple spaces converted to single
+spaces.  For now, ASCII only, no options.  ckuusr.h, ckuus[24].c, 27 Nov 2009.
+
+I wrote a Kermit script to read a big file of addresses on Solaris 9,
+\fsqueeze()ing each line.  After about 14000 lines, there was a malloc
+failure in getnct() (the command-file reader).  There's nothing wrong with
+\fsqueeze(), the failure is on a deeper level, because the same thing
+happens if I use \fupper() (which is structurally identical to \fsqueeze())
+in the same script.  The problem is not in getnct() either, because every
+malloc() is freed (I checked).  On the other hand, the same script (with
+\fupper() instead of \fsqueeze() completes OK in C-Kermit 8.0.201.  If I
+remove the function call (\fsqueeze() or \fupper()) from the script, it also
+runs OK in 9.0.  This seems to point the finger at fnevel(), which contains
+countless malloc's and free's.  But comparing fneval() between 8.0.211 and
+9.0, I don't see any difference that would explain this behavior -- nothing
+at all that involves malloc(), makstr(), or free().  Nor any pertinent
+change in the caller (zzstring) of fneval().  27 Nov 3009.
+
+Another problem is that when this happens, the error is not caught (e.g. by
+the IF FAIL statement after the command that contains the function call);
+instead, C-Kermit returns immediately to its prompt.  27 Nov 2009.
+
+It could simply be that some of the buffers we allocate are much bigger now.
+But again, I don't see much difference between 8.0.211 and 9.0; we were
+already allocating 32K command-related buffers (malloc() takes a size_t, and
+size_t is an int almost everywere).  I built the same source on NetBSD and
+ran the same script (with \fqueeze()), and it worked fine.  Let's worry
+about this later, if it comes up.  27 Nov 2009.
+
+Built OK on Silicon Graphics IRIX 6.5 R10000; regular build OK, SSL and
+Kerberos builds failed.  30 Nov 3009.
+
+Tried to build on Digital Unix 4.0F but it blew up in ckutio.c, apparently
+not recognizing any of the terminal struct symbols from termios.h.  Tried
+again with gcc, same thing.  Tried explicitly #including <sys/termios.h>
+within #ifdef TRU64, same thing.  What could have changed?  30 Nov 2009.
+
+Built OK on Linux RHEL5.4/Itanium-2, make linux.  The secure build
+required "FLAGS=-DNO_KRB5_INIT_ETS" and built OK.  30 Nov 2009.
+
+Built OK on Digital Unix 4.0F using "make osf" instead of "make tru64-40f".
+I don't know why the specific target doesn't work, but it's not worth
+chasing down.  2 Dec 2009.
+
+Built OK on MirBSD 10, despite a lot of gratuitous compiler warnings.  Built
+OK on MirBSD 10, OpenBSD 4.5, and Fedora 10.  3 Dec 2009.
+
+(Various other successful Unix builds in these weeks...)
+
+Built on VMS 7.2 and 8.3 with and without TCP/IP, no problems.  11 Jan 2010.
+
+Built on VMS 8.3 with "make fi" to include the FTP client and long-file
+support (mid Jan 2010).
+
+Built on VMS 8.3 with UXC 5.6 and HP SSL 1.3, which is OpenSSL 0.9.7e.
+It compiled and linked OK but when I tried to make an FTP SSL connection
+it crashed in SSL$LIBSSL_SHR, which is called from ssl_auth(), after having
+had TLS accepted as an authentication type, but before actually
+authenticating.  In Unix:
+
+ 19. ftp open ftp.somecompany.com /user:pge.com/test_quota /password:xxxxxx
+Connected to ftp.somecompany.com.
+220-Somecompany FTP v6.0 for WinSock ready...
+220 Welcome to the online storage FTP server.  Please check the main web
+site for system announcements and AUP. (O)
+---> AUTH TLS
+234 AUTH command OK. Initializing SSL connection.
+TLS accepted as authentication type
+SSL DEBUG ACTIVE
+=>START SSL/TLS connect on COMMAND
+
+In VMS:
+
+ 19. ftp open ftp.somecompany.com /user:pge.com/test_quota /password:xxxxxx
+Connected to ftp.somecompany.com.
+220 Somecompany FTP v6.0 for WinSock ready...
+---> AUTH TLS
+234 AUTH command OK. Initializing SSL connection.
+TLS accepted as authentication type
+SSL DEBUG ACTIVE
+%SYSTEM-F-ACCVIO, access violation, reason mask=04, virtual
+address=FFFFFFFF8001A120, PC=000000000068B118, PS=0000001B
+
+Note: The Unix version received the second 220 response, the VMS version did
+not.  That's odd, it's the same code...  25 Jan 2010.
+
+Added some essential details to the HELP FSEEK text.  ckuus2.c, 25 Jan 2010.
+
+Discovered that the result returned by \fsearch() is totally unreliable.
+This is probably too hard to fix.
+
+FSEEK did not pay attention to SET CASE, searches were always case sensitive.
+Fixed in ckuus7.c, 26 Jan 2010.
+
+FSEEK failed to find anything if the search pattern was matched in the first
+line of the file.  Fixed in ckuus7.c, 26 Jan 2010.
+
+\fword() and \fsplit()....  Another change, but not backwards-incompatible.
+One may now put the word ALL (just like that, all uppercase) as the include
+set (4th argument) to indicate that there will be no break characters other
+than those explicitly given in the break set, e.g. \fsplit(\m(xx),&a,:,ALL)
+breaks a line only on a colon (:), nothing else.  The original rules for
+cksplit() were more than a little counterintuitive: the default break set is
+all non alphanums, and the default include set is all alphanums, so if you
+wanted to parse (say) a CSV file, breaking only on comma, you had to think
+of all the characters you wanted to keep.  This way you just say ALL.
+ckclib.c, 26 Jan 2010.
+
+Speaking of CSV files... How can you put comma as a function argument when
+comma is the function-argument separator?  Use one of these forms:
+
+ \fsplit(\m(xx),&a,",",ALL)
+ \fsplit(\m(xx),&a,{,},ALL)
+ \fsplit(\m(xx),&a,\44,ALL)
+ \fsplit(\m(xx),&a,\fchar(44),ALL)
+
+From John Dunlap, U. of Washington Applied Physics Lab: 'When "stty -a <
+/dev/ttyS0 | grep crtscts" shows "crtscts" (not "-crtscts") and when using a
+three wire serial interface and when asking kermit to not use flow control
+(set flow none) then "ckutio.c1" (see attachments) fails while "ckutio.c"
+works.  The result of "diff -u ckutio.c1 ckutio.c" is attached as "diffs"'.
+ckutio.c, 26 Jan 2010.
+
+Changed the year from 2009 to 2010 in the modules I worked on today and in
+the heralds, etc.  ckckmai.c, ckuus5.c, ckutio.c, ckclib.c, ckuus7.c,
+26 Jan 2010.
+
+Built on Linux Fedora Core 3, regular and with OpenSSL 0.9.7a.  Built on
+Ubuntu 9.4 OK, but SSL and Kerberos builds failed due to not finding libs
+and/or header files.  I'm sure this could be fixed...  27 Jan 2010.
+
+Added SSL, KRB4, and KRB5 to the startup herald for versions that were
+built with SSL, Kerberos 4, or Kerberos 5.  Built OK on Fedora 3 with
+linux+krb5+ssl and new banner shows correctly.  ckuus5.c, 27 Jan 2010.
+
+Set NO_KRB5_INIT_ETS by default in ckuath.h since krb5_init_ets() is a no-op
+in Kerberos 1.4.x and later and in some installations it can't be found,
+which clobbers the build.  ckuath.h, 27 Jan 2010.
+
+Adapted to MINIX 3 1.5, the first version that has virtual memory according
+to Andy T, who should know.  On earlier versions (e.g. MINIX 3 1.2) any
+attempt to build C-Kermit causes the compiler to crash.  Now the compiler
+doesn't crash but it spews out countless warnings about old-fashioned
+function declarations that I don't get anywhere else.  The real problems
+came in ckutio.c where numerous symbols were undefined at compile time and
+the POSIX function tcgetpgrp() was not found at link time, even though there
+is a prototype for it in the MINIX header files, and there is no alternative
+(since POSIX doesn't let us use ioctl()).  Also note that there is some
+confusion over the compile-time symbols MINIX, MINIX2, MINIX3, and MINIX315.
+You would expect MINIX to mean "any version of MINIX" but in some parts of
+ckutio.c it means MINIX 1.0.  I sincerely doubt that C-Kermit 9.0 can be
+built on any version of Minix before 3.1.5 so I removed the confusion and
+made MINIX mean "any Minix".  It builds on 3.1.5 OK now, except for the FTP
+client.  This can probably be fixed but...  Modules changed: ckcdeb.h,
+ckuver.h, ckcmai.c, ckuus5.c, ckutio.c, 1 Feb 2010.
+
+Later.. Andy says MINIX does not support job control, so no program is ever
+in the background.  That settles that!  1 Feb 2010.
+
+Built OK on Minix, Linux, Mac OS X, Solaris 9, NetBSD 5.0.1...  1 Feb 2010.
+
+---C-Kermit 9.0 Alpha.02---
+
+From Christian Corti at Uni-Stuttgart.de: fixes to allow building on SunOS
+4.1, which once was my main development platform but which is long-gone from
+here.  ckupty.c, ckutio.c, 9 Feb 2010.  (He says it is also necessary to
+comment out the "struct winsize" and "struct ttysize" in sys/ioctl.h;
+otherwise there will be a conflict with sys/ttycom.h (included by termios.h)
+which also declares these structs. But you need both includes.')
+
+From John Dunlap, a fix for Kermit protocol fixed packet-timeout interval
+going to a unexpected value (missing else clause in two places).
+ckcfn2.c, 9 Feb 2010.
+
+Added an aixg target to build on AIX with gcc when gcc is not installed as
+cc, and also added CC=$(CC) CC2=$(CC) clauses to the aix and aix+ssl
+targets.  Wow, AIX really loses bigtime when receiving files through its ssh
+server.  Streaming can't be used, sliding windows recover from errors but
+there are tons of them using the default 4K packets; 500 works much better.
+Built with IBM cc and gcc, and also tested (successfully) the new aix+ibmssl
+target, in which the OpenSSL headers and libs are in a standard place.
+makefile, 9 Feb 2010.
+
+In ckupty.h, make the #include <sys/ioctl.h> be #ifndef SUNOS41.
+From Christian Corti.  10 Feb 2010.
+
+Built on VMS E8.4.  12 Feb 2010.
+
+Tried to build on a real VAX-11/785 but the machine seems to be seriously
+wedged.  12-15 Feb 2010.
+
+Added note to CKVKER.COM to the effect the the 'f' option has no effect
+on VAX architecture.  15 Feb 2010.
+
+Moved the #include "ckvrtl.h" in the FTP module to below the include for
+utime.h, because building the VMS version with the 'i' option (meaning
+"include internal ftp client") results in "struct utimbuf tp" erroring out
+because struct utimbuf is not defined yet (at least in some version of VMS
+with some version of C).  From Rob Brown, ckcftp.c, 20 Feb 2010.
+
+From Martin Vorlaender: new code in VMS C-Kermit build procedure to detect
+OpenSSL version automatically.  ckvker.com, 22 Feb 2010.
+
+Added code to INPUT command to strip ANSI escape sequences.  It's activated
+by SET SESSION-LOG TEXT.  ckuusr.h: added prototype for chkaes();
+ckucon.c, ckucns.c: made inesc[] and oldesc[] global instead of static; 
+ckuus4.c: doinput() code for skipping escape sequences.  1 Mar 2010.
+
+Peter Eichhorn complained that if you make an ssh connection with Kermit,
+then log out from the ssh host, and then use a "connect" command to
+make a new connection to the same host (which you can do with Telnet),
+Kermit says (e.g.):
+
+ DNS Lookup... Can't get address for ssh -e none somehostname
+ Sorry, can't open ssh -e none somehostname: Error 0
+
+I added code to detect and handle this case and it seems to work OK, even
+though it's kind of a hack.  ckuusr.[ch], ckuus7.c, 1 Mar 2010.
+
+There has never been a clean way to put debugging messages (ECHO commands)
+in a script which are executed only if debugging is desired and ignored
+otherwise.  You'd have to set a random variable and test it, or define a
+macro or whatever.  To make this more straightforward, I added SET DEBUG
+MESSAGE ON/OFF/STDERR, and added a new MESSAGE (syn: MSG) command for printing
+debugging messages to stdout if SET DEBUG MESSAGE is ON or to stderr if SET
+DEBUG MESSAGE is STDERR.  ckcmai.c, ckuus[r23].c, 12 Mar 2010.
+
+Also for debugging and error messages, I added \v(lastcommmand) so that
+the command that failed can be included in an IF FAIL or DEBUG error message.
+This works even for commands that have syntax errors.
+ckuusr.h, ckuus5.c, ckucmd.c, 12 Mar 2010.
+
+From SMS for VMS: 'Added/documented P3 options INTSELECT, OLDFIB, OLDIP.
+Disabled (commented out) automatic definition of NOSETTIME for VMS before
+V7.2 (vms_ver .lts. "VMS_V72").'  ckcdeb.h, ckcftp.c, ckcnet.c, ckuus[2567].c,
+ckvfio.c, ckvker.com, ckvrtl.[ch], 15 Mar 2010.
+
+Exposed inesc[] and oldesc[] for VMS, so new INPUT command escape-sequence
+stripping can work (really, chkaes() and related global variables should be
+moved out of ck[uvd]con.c/ckucns.c and into a common module; do that later).
+ckuusr.h, ckvcon.c, 15 Mar 2010.
+
+Built OK on Solaris9, Mac OS X 10.4.11, RHEL4 (32-bit), RHEL5 (64-bit),
+AIX 5.3, SCO OpenServr 6.0.0...  15 Mar 2010.
+
+Not so good on VMS, turns out I made a typo in one of the VMS updates
+(#ifndef OLDIP instead of #ifdef...).  ckcnet.c, 16 Mar 2010.
+
+More from SMS for VMS, 16 Mar 2010:
+ . Set MAXPATH correctly for VMS, ckcdeb.h.
+ . NAM -> NAML, QIO replaces system( "SET PROTECTION"), bugfixes in
+   cvtdir() and nzltor(), ...  (See comments): ckvfio.c, new ckvrms.h.
+   (The RMS code in ckvfio.c was almost totally rewritten)
+ . Moved "NAMX$*" (and related) macros to ckvrms.h, and renamed to
+   "NAMX_*" (and similar "$" -> "_"), moved "FIB_*" macros from ckvrtl.c.
+
+These changes are mainly to accommodate the ODS5 file system, which has
+longer and mixed-case filenames, and also to execute certain commands
+(e.g. for setting file protection, deleting directories) directly instead
+of using a system() command.
+
+Built OK on VMS 8.3 (with and without network support).  16 Mar 2010.
+
+Failed to build on VMS 6.2.  16 Mar 2010.
+
+FreeBSD 8.0 <libutil.h> has a hexdump() prototype that conflicts with the
+hexdump macro defined in ckcdeb.h.  Since the same thing is likely to happen
+elsewhere, I changed the Kermit macro to ckhexdump as well all references to
+it: ckcdeb.h, ckcftp.c, ckcnet.c, ckctel.c, ckuath.c, ckutio.c, 16 Mar 2010.
+
+Built OK on Digital Unix Tru-64 4.0E using "make osf", 16 Mar 2010.
+
+Tried again to build Digital Unix Tru64 4.0E using "make tru64-40e", but
+something prevents it from picking up the termios symbols and it blows up in
+ckutio.c, whereas this used to work in earlier C-Kermit versions.  This is
+the only Tru64 system I still have access to, so I can't tell if it's a
+local peculiarity or what.  Note that POSIX is not defined for this build.
+But if I define it, I get into trouble with "struct timeval".  Tried again
+with "KFLAGS=-DPOSIX -DNOTIMEVAL" but that doesn't help.  Tried "make
+dec-osf" and that worked OK but oddly enough it makes a Kermit with less
+features than "make osf".  16 Mar 2010.
+
+To go with MESSAGE and SET DEBUG MESSAGE, I added IF DEBUG, which is true
+if SET DEBUG MESSAGE is not OFF and false otherwise.  ckuusr.h, ckuus6.c,
+16 Mar 2010.
+
+From SMS: Corrections to my merging of SMS's changes, ckcftp.c, ckvrtl.h.
+Builds OK on VMS 6.2 now.  Also did an SSL build on VMS 8.3 with OpenSSL
+m0.9.7e and "OPENSSL_DISABLE_OLD_DES_SUPPORT" was included in P3
+automatically by Martin V's addition to ckvker.com.  17 Mar 2010.
+
+From SMS: #include <types.h> earlier for VMS in ckcdeb.h to pick up off_t
+before it is referenced.  This allows C-Kermit to compile on VMS/Alpha 6.2
+but linking fails on fseeko() and ftello() (and yet, a functional executable
+is created, and FSEEK works right).  Builds the same way with no problems at
+all on VMS 8.3 / Alpha.  In this case we get the full 64-bit arithmetic...
+Well, 62 bits:
+
+  ATLAS::C-Kermit>( ^ 2 63)
+   9223372036854775000.0
+  ATLAS::C-Kermit>( ^ 2 62)
+   4611686018427387904
+
+whereas on VMS 6.2 we get integers only up to (^ 2 30).  17 Mar 2010.
+
+Changed the VMS build procedure to enable large file support automatically
+for non-VAX and VMS 7.3 or greater.  No reason not to include this feature.
+Changed the sense of the F option to DISABLE large file support in the
+unlikely case that C-Kermit is being built on a suitable platform but the
+C library is older than VMS73_ACRTL-V0200, in which case fseeko() and
+ftello() will come up missing at link time.  ckvker.com, 18 Mar 2010.
+
+Changed VMS build procedure to include the FTP client in any network build
+by default.  Changed the sense of the I option to exclude the FTP client,
+in case anybody would want to do that.  ckvker.com, 18 Mar 2010.
+
+From SMS: updated dependencies in CKVKER.COM, fix the "don't reinclude me"
+clause in CKVRTL.H.  19 Mar 2010.
+
+Built OK on VMS 6.2 and 8.3 with and without networking.  Large file support
+included automatically in VMS 8.3  FTP client included automatically in both
+network builds.  19 Mar 2010.
+
+Changed hexdump() to ckhexdump() in ck_crp.c, which I missed before.
+19 Mar 2010.
+
+---C-Kermit 9.0 Alpha.03---
+
+In HP-UX with the bundled-non ANSI compiler, we get warnings about functions
+such as endusershell(), which are declared void in the header files.  But in
+non-ANSI builds we defind VOID to be int rather than void, so our prototypes
+are wrong.  I checked that HP-UX 9, 10, and 11 all have void datatype and
+changed the definition of VOID to void in those cases.  ckcdeb.h, 29 Mar 2010.
+
+Fixed a typo in a debug() statement in cksplit() that was causing some
+warnings.  ckclib.c, 29 Mar 2010.
+
+Ditto in tls_load_certs().  ck_ssl.c, 29 Mar 2010.
+
+"make hpux1000o+ssl" files with:
+/usr/ccs/bin/ld: Unsatisfied symbols:
+   __umoddi3 (code)
+   __udivdi3 (code)
+   __eprintf (code)
+
+It appears that OpenSSL (0.9.7c in this case) requires -lgcc.
+And indeed hpux1000gcc+ssl builds fine.  29 Mar 2010.
+
+There are various warnings in the SSL code in ckutio.c, ckcftp.c, and
+ckcnet.c about pointers not being assignment compatible, but I have learned
+from experience not to try to fix these (see notes from 6 Oct 2009).
+29 Mar 2010.
+
+connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)): In FTP,
+this doesn't work on RHEL5 / Mac OX X 6.1/2 64-bit.  But the connect() in
+Telnet works.  On Mac OS X 6.2 I tried changing the socket() call to be like
+the one in ckcnet.c for Telnet, but it made no difference.  On a RHEL5.4
+system on i386, FTP works fine, so it's not the Red Hat version.  On Digital
+Unix 4.0E 64-bit, same thing:
+
+  11:23:10.722 ftp_hookup[kermit.columbia.edu]=21
+  11:23:10.722 ftp hookup A[kermit.columbia.edu]
+  11:23:10.722 ftp hookup C[kermit.columbia.edu]
+  11:23:10.722 ftp hookup socket=4
+  11:23:10.722 ftp hookup HADDRLIST
+  11:23:10.723 ftp hookup connect failed=13
+  11:23:10.723 ftp hookup bad
+
+13 = Permission denied:
+
+  [EACCESS] Search permission is denied for a component of the path prefix;
+    or write access to the named socket is denied.
+
+On Gentoo Linux, also on Alpha, the errno is 51: Network is unreachable.
+Clearly some data type in the sockets structs is out of whack.
+
+The third connect() argument is "address length".  The address is a
+struct sockaddr.  About the third argument, RHEL5 "man connect" says:
+
+  The third argument of connect() is in reality an int (and this is what 
+  4.x BSD and libc4 and libc5 have).  Some POSIX confusion resulted in 
+  the present socklen_t, also used by glibc.  See also accept(2).
+
+Building on RHEL5 on x86_64, where size_t is 8 and socklen_t is 4, I get a
+warning:
+
+  ckcftp.c: In function 'ftp_hookup':
+  ckcftp.c:14667: warning:
+   comparison is always true due to limited range of data
+
+Referring to:
+
+  if (hisctladdr.sin_addr.s_addr != (unsigned long) -1)
+
+This seems to be the problem; if I remove the (unsigned long) cast (in two
+places), the problem goes away.  Actually what I should be comparing it with
+is INADDR_NONE, which is defined appropriately in some header file, e.g. as
+0xffffffff.  Also I define it explicitly as -1 if it is not defined in any
+header file (as is the case in Solaris 9).  Tested OK on 64-bit RHEL5,
+32-bit RHEL5, Digital Unix 4.0E 64-bit, Solaris 9 32-bit, Mac OS X 10.4.11
+32-bit, Mac OS X 10.6.3 64-bit, AIX 5.3, Gentoo Linux 2.6.31 on Alpha
+64-bit, NetBSD 5.0.1 32-bit....  ckcftp.c, 29 Mar 2010.
+
+---C-Kermit 9.0 Alpha.04---
+
+Yesterday's VOID redefinition caused problems for HP-UX in ckuusx.c, in the
+curses section where VOID is undef'd and not used to avoid a conflict with
+curses.h.  As a workaround I defined a new macro CKVOID with the same
+definition as VOID and used it in the offending section of ckuusx.  The real
+solution is to replace all references to VOID with CKVOID (since VOID is
+increasingly likely to cause conflicts), but a mass search and replace is
+not without risks.  ckcdeb.h, ckuusx.c, 30 Mar 2010.
+
+Changed VOID and CKVOID definition to be 'void' for all HP-UX (verified by
+PeterE back to HP-UX 6.5, 1989).  Still need to check this on HP-UX 5.21;
+if that's an exception it can be done in the makefile.  ckcdeb.h, 30 Mar 2010.
+
+The change I made to allow CONNECT to reestablish a previous SSH connection
+prevented a new SSH connection to a different host to be made.  Fixed in
+ckuus7.c, 30 Mar 2010.
+
+Fixed mistaken extern declarations of krb4_errno and krb5_errno as strings
+in nvlook(); they are ints. Built OK on Mac OS X 10.6.3. ckuus4.c, 30 Mar 2010.
+
+A fix to Trusted HP-UX makefile target from PeterE, to account for the
+equivalence of +openssl and +ssl as target suffixes.  30 Mar 2010.
+
+Added a new function \fcvtcsets(string,cset1,cset1) that converts a string
+from one character set to another.  The csets are File Character-Set names.
+ckuus4.c, 31 Mar 2010.
+
+Added a new function \fdecodehex(string,prefix) that decodes a string
+containing prefixed hex bytes.  Default prefix is %%, but any prefix of
+one of two chars (such as % or 0x) can be specified.  ckuusr.h, ckclib.h,
+ckclib.c, ckuusr.c, 31 Mar 2010.
+
+Richard Nolde reports that Kermit can't find -lpam on Fedora 12 because it's
+in /lib rather than /usr/lib.  RHEL5 has symlinks, FC12 should too.  Added a
+note to the makefile.  1 Apr 2010.
+
+Build on Solaris 11 for the first time.  Had to adjust ckuver.h to get the
+version herald right.  This was on a box that reported its architecture as
+i86pc.  1 Apr 2010.
+
+Added MIME character-set names as invisible synonyms in the file and
+terminal character-set tables, fcstab[] and tcstab[].  Note that not all the
+character sets known to Kermit are registered in MIME.  But at least now
+MIME-registered character sets can be referred to by their MIME names, e.g.
+ISO-8859-1, ISO646-ES, IBM437, WINDOWS-1252.  These are not listed if you
+type ? in a field that is parsing them, unless you type a letter first,
+e.g. "i?" lists ISO- and IBM set names.  Later maybe I'll make parallel
+tables, or keyword attribute bit that says whether a name is MIME or not.
+The real benefit of this change is that now Kermit can take its
+character-set names from external sources like email headers or web logs.
+ckuxla.c, 1 Apr 2010.
+
+Changed the IF command to accept a bare macro name its condition.  This will
+parse and execute correctly if the macro is defined and if it has a numeric
+value, or if it is not defined, in which case it evaluates to 0 (FALSE).  If
+it is defined but has a non-numeric value, a parse error occurs.  ckuus6.c,
+2 Apr 2010.
+
+Added \fstringtype() function.  Given a string argument, it tells whether
+the string is 7bit, 8bit, utf8, binary, etc.  ckuusr.h, ckuus[4x].c,
+2 Apr 2010.
+
+Did a few builds to make sure there were no booboos.  Solaris 9, NetBSD
+5.01, Linux RHEL4, HP-UX 10.20 (non-ANSI compiler and ANSI optimizing
+compiler), Mac OS X 10.4.11, SCO OSR 6.00.  5 Apr 2010.
+
+---C-Kermit 9.0 Alpha.05---
+
+Increased maximum variable name length from 4K to 16K. Verified that
+too-long names are caught and recovered from correctly.  ckuusr.h, 6 Apr 2010.
+
+Implemented a new \fsplit() option for parsing CSV files, which turns out to
+be a little complicated, because the separator is not just a comma, but a
+comma and all its surrounding spaces.  Also there are special quoting rules
+for fields with embedded commas and fields with embedded quotes.  ckclib.c,
+7 Apr 2010.
+
+---C-Kermit 9.0 Alpha.06---
+
+VMS changes from SMS.  They build OK, Kermit file transfers are still OK,
+but FTP text-mode GETs always hang on the 10th 8K network read.  Couldn't
+get a debug log this time.  ckcmai.c, ckvfio.c, ckvrms.h, ckvker.com.
+8 Apr 2010.
+
+Changing VNAML from 4K to 16K broke the build on HP-UX 9.  Put it back to
+4K.  9 Apr 2010.
+
+John Dunlap, running days-long stress tests between E-Kermit and C-Kermit,
+found a bug in the packet-reading and -decoding code: If a NAK packet
+arrives with its length field corrupted to indicate a bigger size, and there
+are enough bytes following in the pipeline, ttinl() will return a too-long
+packet (if there are not enough bytes waiting to be read, then ttinl() will
+properly time out).  In the bad case rpack() trusts the packet length, uses
+it as the basis for computation of the block-check length, which is then
+used to access memory that might not be there, causing (at least on John's
+Linux system) a segmentation fault.  John added the normal clause to check
+the result of the block-check calculation, and I changed ttinl() to always
+break on the eol character (normally carriage return), since this can never
+appear in a packet, even if we "set control unprefix all".  Also added a
+check to ttinl() to protect against length fields corrupted into illegal
+values.  ckcfn2.c, ckutio.c, 13 Apr 2010.
+
+From Lewis McCarthy:
+  Based on code inspection, C-Kermit appears to have an SSL-related security
+  vulnerability analogous to that identified as CVE-2009-3767 (see e.g.
+  http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2009-3767).
+
+  I'm attaching a patch for this issue relative to the revision of ck_ssl.c
+  obtained from a copy of http://www.columbia.edu/kermit/ftp/test/tar/x.zip
+  downloaded on 2010/07/30, which I believe is the latest.
+
+  When this flaw was first widely publicized at last year's Black Hat
+  conference, it was claimed that some public certificate authorities had
+  indeed issued certificates that could be used to exploit this class of
+  vulnerability. As far as I know they have not revealed specifically which
+  public CA(s) had been found issuing such certificates.
+  Some references: http://www.mseclab.com/?p=180
+  http://www.theregister.co.uk/2009/07/30/universal_ssl_certificate/
+
+Patches added to ck_ssl.c, 4 Aug 2010.
+
+Peter Eichhorn reported that "RENAME ../x ." didn't work.  This is a side
+effect of the changes of 2006 to the RENAME command, there was a little
+confusion in the renameone() routine; fixed in ckuus6.c, 4 Aug 2010.
+
+If only one file is FOPEN'd, FCLOSE given with no arguments would close it.
+Turns out to be a bad idea. Example: program with an input and output file,
+try to close the output file before it is opened by just typing FCLOSE; this
+can mess up the input file.   For safety FCLOSE has to require a channel
+number or ALL.  ckuus7.c, 4 Aug 2010.
+
+Added \fstrcmp(s1,s2,case,start,length), which has the advantage over IF
+EQU,LGT,LLT that case senstivity can be specified as a function arg, and
+also substrings can be specified.  ckuusr.h, ckuus[24].c, 5 Aug 2010.
+
+The CSV feature of Alpha.06 had a subtle flaw, namely that if the last item
+in a comma separated list was enclosed within doublequotes with a trailing
+space after the closing doublequote, a spurious empty final element would be
+created in the result array.  Fixed in cksplit(), ckclib.c, 5 Aug 2010.
+
+---Alpha.07---
+
+The CSV feature of \fsplit() splits a comma-separated list into an array.
+To turn the array back into a comma separated list, \fjoin(&a,\44,1) almost
+works, except for elements contain literal doublequotes, such as:
+
+  Mohammad "The Greatest" Ali
+
+This calls for making a symbolic CSV argument for \fjoin() like the one that
+was made for \fsplit(): \fjoin(&a,CSV).  Also \fjoin(&a,TSV) for
+Tab-separated list.  Thus if Kermit reads a record in CSV format, splits it
+into an array, and then joins the array back into a CSV record, the result
+will be equivalent to the original, according to the CSV definition.  It
+might not be identical, because if the result had extraneous spaces before
+or after the separating commas, these are discarded, but that does not
+affect the elements themselves.  Furthermore it is now possible to convert
+a comma-separated list into a tab-separated list, and vice versa (which is
+not a simple matter of changing commas to tabs or vice versa).  ckuus4.c,
+12 Aug 2010.
+
+From Joop Boonen 26 Juli 2010: "Added HAVE_LOCKDEV as openSuSE >= 11.3 uses
+lockdev but not baudboy.  They use ttylock directly.  The program code has
+been added so the the program works without a problem."  makefile, ckcdeb.h,
+ckutio.c, ckuus5.c, 23 Aug 2010.
+
+---Alpha.08---
+
+From Gary Mills at the U of Manitoba: convert Solaris version from BSD ptys
+to streams ptys because there are only 48 BSD-style ptys and he was running
+out.  No code changes needed, the only change necessary was to add the
+following flags to the makefile target:
+
+  -DHAVE_STREAMS -DHAVE_GRANTPT -DHAVE_PTSNAME
+  -DPUSH_PTEM -DPUSH_LDTERM -DPUSH_TTCOMPAT
+
+makefile, ckcmai.c, 21 Sep 2010.
+
+Testing this in Solaris 9 I see that the DES library disappeared.  Added
+code to the solaris9 targets (also used by Solaris 10 and 11) to check for
+this.  makefile, 21 Sep 2010.
+
+The Solaris target checked the OpenSSL version automatically to set the
+right flag, the Linux target didn't.  Put the OpenSSL-version testing code
+in the Linux target too.  makefile, 21 Sep 2010.
+
+A couple minor changes to the tru64-51b makefile targets from Steven Schweda
+but there still are some problems with the Tru64 Unix builds.
+makefile, 21 Sep 2010.
+
+---Alpha.09---
+
+\fcontents(\&a[3]) got an error if the array was declared but its dimension
+was less than 3, which is bad when dealing with (say) an array created
+dynamically by \fsplit(), which might or might not have a third element.
+In case it doesn't -- i.e. in case we are referring to an out of range
+element of any array that is declared -- we should just return a null
+string, as we do with other types of variables that are not defined.
+For that matter, ditto even if the array is not declared; what useful
+purpose is served by throwing an error in this case?
+ckuus4.c, 30 Dec 2010.
+
+cksplit() treats \ as a quoting character.  If the source string contains
+backslashes, they are swallowed (or, if doubled, one is kept).  That's not
+good for parsing external data, such as lines read from files, where there
+are no quoting rules.  This came up when parsing CSV files; as a workaround,
+I made \fsplit() treat backslash as an ordinary character for CSV and TSV
+splitting (a better solution might be yet another argument that specifies
+a quote character).  ckclib.c, 30 Dec 2010.
+
+Began converting C-Kermit to Open Source with the Simplified 3-Clause BSD
+license.  Updated the text for the INTRO, LICENSE, NEWS, and SUPPORT
+commands.  Fixed things so the copyright year to be displayed is defined in
+one place (ck_cryear in ckcmai.c), rather than hardwired into text strings
+all over the place.  COPYING.TXT, ckcmai.c, ckuus[256].c, 2 Jun 2011.
+
+When I added MIME synonyms for Kermit character-set names, I left a bogus
+entry in the tables ("windows-1251") that was in the wrong place
+alphabetically, thus preventing most references to file character-set names
+from working right.  Removed the bogus entry.  ckuxla.c, 2 Jun 2011.
+
+Most combinations work OK, but not translating Cyrillic text from UTF-8
+to Latin/Cyrillic, and probably the same would be true for any case of
+converting from UTF-8 or UCS-2 to anything else.  The problem was in
+xgnbyte(), which converts the input stream from the specified character to
+UCS2; it needed to make a special case for when the input file was already
+Unicode.  Believe it or not, this problem occurred at least as far back as
+8.0.201 (9.5 years ago) and nobody noticed.  So if the fix isn't perfect
+probably nobody will notice that either.  ckcfns.c, 3 Jun 2011.
+
+The SET BLOCK CHECK command did not parse all the items in its keyword
+list.  Fixed in ckuus3.c, 3 Jun 2011.
+
+For EM-APEX ocean floats project, where buoys in stormy waters have to
+transmit data through an earth satellite using non-error-correcting modems,
+John Dunlap ran exhaustive stress tests of Kermit protocol transfers through
+a simulated connection that injected errors and delays and identified a
+weakness in Kermit protocol when it is used under extremely bad conditions:
+If a data byte of the S packet (or its Ack) is corrupted and the 1-byte
+checksum is also corrupted in such a way that that the checksum matches the
+corrupted data, the two Kermit programs will disagree as to the negotiated
+parameters.  For example, if file Sender's RPT field is changed from '~' to
+'^', the receiver will decode the packet incorrectly.  Ditto for most of the
+other parameters.  The result is that a corrupted file is received but
+reported correct.  John suggested a new mode of operation in which the Type
+3 block check is used for all packets.  Such a mode can not be negotiated
+because the negotiation packet itself is assumed by all Kermit programs to
+have a 1-byte checksum.  Added SET BLOCK-CHECK 5 to the parser (with
+invisible synonym FORCE-3".  ckuus3.c, 3 Jun 2011.
+
+Added supporting code for SET BLOCK 5: ckcfn[23].c, ckcpro.w, ckcmai.c,
+ckuus3.c, 3 Jun 2011.
+
+Added code to skip the heuristic that S and I packets always have block
+check type 1.  File transfer OK between two C-Kermits with SET BLOCK 5.
+rpack(): ckcfn2.c, 5 Jun 2011.
+
+Made the file receiver put "5" in the block-check-type in its ACK to the
+S-Packet.  spar(): ckcfns.c, 5 Jun 2011.
+
+Now the question is: Can we make the file receiver automatically and safely
+recognize a three-byte block check on an incoming S or I packet?  It's
+tricky because the block check field is not self-identified, it's just the
+last "n" characters of string indicated by the length field, so correct
+decoding of the packet depends on stateful knowledge of "n".  How about this:
+rpack() already knows what type of packet it is, so if it's an S or I packet
+and the 8th byte of the data field is "5" and last 3 bytes, when interpreted
+as the CRC, match the packet contents, then we accept the packet and switch
+to BLOCK 5 mode.  
+
+On the other hand, if the "5" was put there by corruption, the CRC should
+catch the error.  In that case we NAK the packet and presumabely get a
+different version back.  There would be no reason to try to re-read the same
+packet with a different block check, because the "5" could not possibly be
+there legitimately unless it had a 3-byte CRC.  To be clear, this is
+cheating.  We read the packet contents before we know the packet is correct,
+then we check that it *is* correct.  I made the 4-line change to rpack()
+and it works OK in the absense of transmission errors.  ckcfn2.c, 3 Jun 2011.
+
+So the various combinations should work as desired:
+
+ . Sender and receiver both support and are told to SET BLOCK 5 ("SB5").
+ . Sender SB5, but receiver doesn't support it (errors out).
+ . Sender SB5, receiver supports it but wasn't told (auto-recognizes it).
+ . Receiver SB5 but sender no (errors out).
+
+Note in the last case, the receiver should NOT automatically fall back to
+standard behavior because if the user said SET BLOCK 5 that means every
+packet MUST be protected by CRC to prevent the I/S packets from being
+corrupted.
+
+Installed new HELP SET BLOCK-CHECK text.  ckuus2.c, 5 Jun 2011.
+
+Autodownload didn't work when the S or I packet had a 3-byte block check
+because kstart() checked it for a 1-byte checksum.  Fixed in kstart(),
+ckcfn2.c, 6 Jun 2011.  However, older Kermit versions and programs that
+claim to do "autodownload" will never recognize this type of packet.  No
+big deal since even if they did, the transfer would fail anyway.
+
+Added 'FORCE 3' to E-Kermit, called it EK 1.7.  The option is "-b 5".  Works
+OK for sending and receiving, both with and without the new option.  Also
+works with "-b 5" if you send an S packet to it with '5' in the BCT field.
+Changes were minimal, I have them all in ek17.diff.
+
+I could probably also make a new G-Kermit in about 10 minutes, but who cares
+about G-Kermit...  We already have two useful Kermit programs that
+interoperate with the new protocol.  6 Jun 2011.
+
+Replaced the very inadequate help texts for functions \fword() and
+\fsplit() with new ones.  ckuus2.c, 6 Jun 2011.
+
+There were a couple reports of file corruption that I was saving for later.
+Now that now is later I dug up the messages, files, and logs and it turns
+out that nobody had reported a reproducible case of Kermit corrupting a
+file.  There have been non-reproducible cases though, almost certainly due
+to corruption of the S or I packet or its ACK, which is why we now have SET
+BLOCK 5.  Even with BLOCK CHECK 5, there is no guarantee that the same thing
+won't happen, it is just far less likely.  Even if we added a 32-bit CRC or
+even 64-bit one, there would still be a small chance it could happen.
+
+7 Jun 2011:
+
+Corrected various #ifdefs (or lack of them) when building C-Kermit with
+different combinations of feature-selection options such as NOCSETS, NOICP,
+NOLOCAL, NOSPL, NOUNICODE, etc.  ckcfns.c ckcmai.c ckcxla.h ckuus2.c
+ckuus4.c ckuus5.c ckuus6.c ckuusr.c, 7 Jun 2011.  After running the script
+that does all these builds (84 of them) I ran it again to make sure that
+none of the changes broke builds that succeeded before the changes were made.
+
+Built OK on Solaris9 ("make solaris9")
+Ditto with Krb5 and OpenSSL 0.9.8q  ("make solaris9g+openssl+shadow+pam+zlib")
+
+Built OK on Mac OS X 10.4.11 ("make macosx").
+Also "make macosx+krb5+openssl.
+
+Built OK on Linux RHEL4 ("make linux").
+Built OK on Linux RHEL4 with OpenSSL 0.9.7a ("make linux+ssl").
+Built OK on Linux RHEL5 ("make linux").
+
+"make linux+ssl" fails on RHEL5 because of DES, even though the target
+tests for the presence or absence of the DES libraries.  In this case the
+libraries are there but they lack the functions des_ecb3_encrypt,
+des_random_seed, and des_set_odd_parity.  The build succeeds as:
+
+  make linux+ssl KFLAGS=-UCK_SSL
+
+Since DES is now considered harmful, Jeff Altman suggests that all OpenSSL
+builds, even for old versions, should omit it ("If you are building with
+openssl and no kerberos or srp, just disable DES.  Disabling DES will impact
+telnet and rlogin but it won't matter if you have no ability to negotiate a
+session key").
+
+From Ian Beckwith, patches for Debian Linux:
+ . Change all '-' to '\(hy' in man page (new pedantry): ckuker.nr.
+ . Make IKSD authentication (using PAM) ask for a password when an invalid
+   username has been given, to avoid disclosing which account names are valid:
+   ckufio.c, ckuus7.c.
+ . Fix spelling errors: ckcftp.c, ckuus2.c, ckuker.nr, ckcpro.w, ckuusr.h.
+ . Patch makefile to support install to a staging area with DESTDIR.
+ . Some other patches (mainly for typos) were for plain-text documentation
+   files that were generated from Web pages; I updated the web pages.
+
+A big corporate C-Kermit user has an application where a local C-Kermit
+makes a connection to a remote one, uploads some files, and then if the
+server has any new patch files for the local, it sends the patches and
+does a REMOTE HOST command to run the patch program.  This stopped working
+in C-Kermit 6.0 or 7.0 when I put a check to prevent it, because "it makes
+no sense to send REMOTE commands to the local end, because the results are
+sent back to the remote to be displayed on its screen but it has no screen".
+That may be true, but if the user needs to control the local from the
+remote, they should be able to.  I removed the checks.  This doesn't solve
+the problem of where the output goes; ideally it would go to the local
+screen but I don't see any elegant and simple way to make that change.
+However the output redirectors can still be used with the REMOTE command
+so the results can be captured to a remote file, which could then be sent.
+ckuus7.c, 7 Jun 2011.
+
+Changed SET VARIABLE-EVALUATION to SET COMMAND VARIABLE-EVALUATION, but left
+the former version available.  ckuusr.c, 9 Jun 2011.
+
+Documented the SET COMMAND VARIABLE-EVALUATION command, which I added in
+2008.  ck90.html, 9 Jun 2011.
+
+Renamed all old Mac OS X makefile targets to have the prefix "old" to avoid
+confusing them with the current targets, and made macosx10 a synonym for
+macosx, so those who used previous makefiles will get a current target
+without having to know the new name.  makefile, 9 Jun 2011.
+
+Added XMESSAGE, which is to MESSAGE as XECHO is ECHO: prints the text
+without a line terminator, so it can be continued by subsequent [X]MESSAGE
+commands.  ckuusr.[ch], 9 Jun 2011.
+
+Back to "make linux+ssl" on RHEL5...  I took the coward's way out and added
+code to the makefile target to check whether the build worked (somebody let
+me know if there is a better way to check), and if not to give a message
+suggesting they "make clean ; make linux+ssl KFLAGS=-UCK_DES".  makefile,
+9 Jun 2011.
+
+Noticed that \frecurse() would dump core if called with no arguments.
+Fixed in ckuus4.c, 9 Jun 2011.
+
+Added \q() as an alternative to the more verbose \fliteral() for quoting
+strings that contain characters (like \) that would otherwise be significant
+to Kermit.  It's more efficient because it isn't a function call, and 'q'
+is an intuitive letter to mean 'quote'.  It also works better than
+\fliteral() because functions treat commas and braces specially.  ckuus4.c,
+10 Jun 2011.
+
+Built OK on VMS 8.3 on Alpha, no net.  DEC C caught a couple glitches in the
+new code that gcc didn't catch, which I fixed.  ckuus[25].c, 10 Jun 2011.
+
+Built OK on VMS 8.3 on Alpha with Multinet 5.3.  The SSL build failed but
+I'm not going to worry about it.  10 Jun 2011.
+
+Built OK on NetBSD 5.1.  10 Jun 2011.
+
+Tried to resurrect my old "build-all" machine, an IBM Netfinity 3500 from
+1997 with 20-some mountable bootable hard disks with lots of 1990s OS's on
+them.  No dice.  I can see the BIOS but not the hard disks.  The
+configuration is still correct because it tries to boot from the mountable
+hard disk, but it fails (I tried six different ones).
+
+Tried to resurrect my old Siemens Nixdorf RM 200 MIPS machine.  Booted OK,
+headless even, but makes a hellish high-pitched whine, like a dentist drill.
+It's pretty slow too.  "make sinix542" (for SINIX 5.4.2) bombed at link
+time on no rdchk().  Fixed by #including <sys/filio.h>.  ckutio.c, 10 Jun 2011.
+
+Tried to resurrect my old SCO Xenix 2.3.4 machine, also headless.  Amazingly
+it still works; it can't use a monitor but I can Telnet to it.  Had to tweak
+some #ifdefs but I got a no-net version built successfully.  According to my
+notes, it hasn't been possible to build with TCP/IP since C-Kermit 8.0,
+but how many people ever had SCO Xenix 2.3.4 with TCP/IP anyway?  Anyway we
+still have the binaries for C-Kermit 7.0.  ckuus4.c, 10 Jun 2011.
+
+Built OK on AIX 5.3.  Built OK on Solaris 10.  11 Jun 2011.
+
+Tried harder to revive the build-all machine, now it sort of works, but not
+all of the bootable OS's work.  Built C-Kermit 9.0 OK on OpenBSD 3.0.  Built
+OK on QNX 4.25 but had to #ifdef references to IXANY in ckutio.c and ckupty.
+Built OK on NetBSD 1.5.1 (2000).  Tried "make netbsd+ssl" on this one, it's
+OpenSSL 0.9.5a 1 Apr 2000, but it bombs out in ckuath.c, no big deal.
+Another problem in NetBSD 1.5.2 is that even though off_t is 8, CK_OFF_T
+is 4.  Worth noting but not worth fixing unless someone else notices.
+13 Jun 2011.
+
+SuSE 7.0... boots OK but telnet server doesn't work.  Can telnet out but
+it's too flaky, connection drops if I try to transfer a file.
+
+OpenBSD 2.5 [1999] OK.  Red Hat 7.1 OK.  Red Hat 7.1 with OpenSSL 0.9.6
+not OK, same error as with 0.9.5a:
+
+ckuath.c
+In file included from ck_ssl.h:48,
+                 from ckuath.c:225:
+/usr/include/openssl/des.h:77: warning: redefinition of `Block'
+ckuat2.h:86: warning: `Block' previously declared here
+/usr/include/openssl/des.h:83: redefinition of `struct des_ks_struct'
+/usr/include/openssl/des.h:91: warning: redefinition of `Schedule'
+ckuat2.h:90: warning: `Schedule' previously declared here
+
+So it appears that OpenSSL support is broken for pre-0.9.7.  Tried
+building it again with -UCK_SSL (since the errors are originating from
+from des.h)...  But it still failed exactly the same way.  I found
+#includes for des.h in ckuath.c and and ck_ssl.h and #ifdef'd them out,
+but it still fails:
+
+In file included from /usr/include/openssl/evp.h:89,
+                 from /usr/include/openssl/x509.h:67,
+                 from /usr/include/openssl/ssl.h:69,
+                 from ck_ssl.h:51,
+                 from ckuath.c:227:
+/usr/include/openssl/des.h:77: warning: redefinition of `Block'
+ckuat2.h:86: warning: `Block' previously declared here
+/usr/include/openssl/des.h:83: redefinition of `struct des_ks_struct'
+/usr/include/openssl/des.h:91: warning: redefinition of `Schedule'
+ckuat2.h:90: warning: `Schedule' previously declared here
+
+Built OK on Debian 2.1.  13 Jun 2011.
+
+On FreeBSD 4.4, it blows up with:
+ckufio.c: In function vpass':
+ckufio.c:8201: conflicting types for 'initgroups'
+/usr/include/unistd.h:154: previous declaration of 'initgroups'
+ckufio.c:8201: warning: extern declaration of 'initgroups' doesn't match global
+one.  Fixed by defining NODCLINITGROUPS for FreeBSD in ckufio.c. It might not 
+be the right fix, but I don't have a lot of other FreeBSD versions to
+compare with.  Anyway now it builds OK on 4.4, and also on FreeBSD 3.3.
+ckufio.c, 13 Jun 2011.
+
+Tried to build on SCO Open Server 5.0.7 but it fails at link time because
+it can't find rdchk().  But it's supposed to be there!  Come back to this
+later...
+
+Red Hat 6.1             i386   32/64   linux          2332545
+Red Hat 7.1             i386   32/64   linux          2368528
+Red Hat EL4             i386   32/74   linux          2363067
+Red Hat EL5.6           i386    64     linux          2371279
+Solaris9                sparc  32/64   solaris9       2849896
+Solaris9+ssl            sparc  32/64   solaris9       5021764
+Solaris10               sparc  32/64   solaris10      2855776
+QNX                     i386    32     qnx32          2012323 
+NetBSD 1.5.1            i386   32/64   netbsd         2198055
+NetBSD 5.1              i386   32/64   netbsd         2159863
+OpenBSD 2.5             i386   32/64   openbsd        2236036
+Mac OS X 10.6.7         x86_64  64     macosx         2.7M
+Mac OS X 10.4.11        ppc    32/64   macosx         2496304
+Debian 2.1              i386   32/64   linux          2213221
+FreeBSD 4.4             i386   32/64   freebsd        2291333
+FreeBSD 3.3             i386   32/64   freebsd        2147370
+SINIX 5.42              mips    32     sinix542       3319325 (1995)
+SCO Unixware 2.1.3      i386    32     uw213          2242176
+SCO OSR6.0.0            i386   32/64   sco_osr600     2368300
+
+More builds, 14 June 2011:
+
+VMS 6.2                 alpha   32     make mn        2556928 No TCP/IP
+VMS 6.2                 alpha   32     make m         3112960 UCX 4.0
+Solaris 11              i386   32/64   solaris11      2823860
+Solaris 11              i386   32/64   solaris11+ssl  2993660 OpenSSL 0.9.8l
+NetBSD 5.1              i386   32/64   netbsd+krb5    2307855 Kerberos 5
+Linux Slackware 12.1.0  i386   32/65   linux          2175754
+Linux Fedora 14         i386   32/64   linux          2256514
+Linux Fedora 14         i386   32/64   linux+ssl      ....... OpenSSL 1.0.0d
+Linux Fedora 14         i386   32/64   linux+krb      2449614 (*)
+
+(*) make linux+krb5 "LIBS=$LIBS /lib/libk5crypto.so.3 /lib/libcom_err.so.2"
+
+Noticed that netbsd+ssl build on NetBSD 5.1 said "NetBSD 1.5" in its banner.
+Fixed by replacing the old hardwired target with the new "subroutinized"
+target a'la linux+ssl and adapting it to NetBSD.  makefile, 15 Jun 2011.
+
+Same deal for Kerberos 5, make a new netbsd+krb5 target and it builds ok,
+at least once one figures out where the Kerberos headers and libs are.
+makefile, 15 Jun 2011.
+
+Same deal for the netbsdnc target, now it simply defined NOCURSES and
+chains to the main netbsd target.  makefile, 15 Jun 2011.
+
+Tried to build with Kerberos 5 on Solaris, fails because the DES library
+no longer exists.  This one is beyond me, sorry.
+
+Made new targets for MirBSD, mirbsd and mirbsd+ssl, makefile 15 Jun 2011.
+
+In OpenSUSE 11.2 with OpenSSL 0.9.8r we bomb on undefined references from
+various DES library routines.  Builds OK without DES.
+
+Various linux+krb5 builds fail because can't find -lgssapi_krb5
+
+SSL builds with OpenSSL < 0.9.7 fail even though there is code to support
+the older SSL.
+
+Fixed some printf %ld vs int instances in the sizeofs section of SHOW FEATURES.
+ckuus5.c, 15 Jun 2011.
+
+Fixed the new linux+ssl target to actually use the SSLINC and SSLLIBS
+definitions, oops.  makefile, 15 Jun 2011.
+
+15 June 2011 builds (Beta.01):
+
+AIX 5.3                 ppc    32/64   aix+ssl        3283846 OpenSSL 0.9.8m
+NetBSD 5.1              i386   32/64   netbsd         2159863
+NetBSD 5.1              i386   32/64   netbsd+ssl     2350274 OpenSSL 0.9.9-dev
+NetBSD 5.1              i386   32/64   netbsd+krb5    2349627 MIT Krb5 1.6.3
+FreeBSD 8.2             i386   32/64   freebsd        2298414
+FreeBSD 8.2             i386   32/64   freebsd+ssl    2448961 OpenSSL 0.9.8q
+OpenBSD 4.7             i386   32/64   openbsd        2266132
+OpenBSD 4.7             i386   32/64   openbsd+ssl    2409263 OpenSSL 0.9.8k
+MirBSD 10               i386   32/64   mirbsd         2216601
+MirBSD 10               i386   32/64   mirbsd+ssl     2358318 OpenSSL 0.9.8r
+OpenSuse 11.2           x86_64  64     linux          2348468
+OpenSuse 11.2           x86_64  64     linux+ssl (*)  2546540 OpenSSL 0.9.8r
+RHEL 5.6                ia64    64     linux          4390687
+RHEL 5.6                ia64    64     linux+ssl (*)  4775007 OpenSSL 0.9.8e
+Ubuntu 9.10             i386   32/64   linux          2275523
+Ubuntu 9.10             i386   32/64   linux+ssl      2466708 OpenSSL 0.9.8r
+Gentoo 1.12.13          ppc    32/64   linux          2386597
+Gentoo 1.12.13          ppc64   64     linux          2749015
+Gentoo 1.12.13          ppc64   64     linux+ssl      3002150 OpenSSL 0.9.8r
+Gentoo 1.12.13          sparc  32/64   linux          2478382
+Gentoo 1.12.13          sparc  32/64   linux+ssl      2690499 OpenSSL 0.9.8r
+Solaris 9               sparc  32/64   solaris9       2849896
+Solaris 10              i386   32/64   solaris10      2837620
+IRIX 6.5                R10000 32/64   irix65         2869704
+
+* and KFLAGS=-UCK_DES
+
+Tried building on NetBSD 5.1 with Heimdal Kerberos using:
+
+make netbsd+krb5 \
+ "KFLAGS=-DHEIMDAL" \
+ "K5INC=-I/usr/include" \
+ "K5LIB=-L/usr/lib"
+
+It found all its headers OK, but it blew up in ckuath.c.  Small wonder,
+ckccfg.html says:
+
+HEIMDAL
+    Should be defined if Kerberos V support is provided by HEIMDAL. Support
+    for this option is not complete in C-Kermit 8.0. Anyone interested in
+    working on this should contact kermit-support. 
+
+'krb5-config --version' gives the MIT Kerberos 5 version number.
+
+Make a new netbsd+krb5+ssl target based on the combination of the new
+netbsd+ssl and netbsd+krb5 targets.  There were lots of warnings in the
+compilation but no errors, but it produced an executable that starts and
+does normal things but I have no idea if the SSL or Kerberos functions work.
+makefile, 16 Jun 2011.
+
+Changed the cu-solaris9-krb5 target to test for the presence of DES because
+DES isn't there, to see if this would allow a Kerberos build to proceed.
+And it worked, amazing.  At least the build completed, I have no way to test
+the Kerberos part.  makefile, 16 Jun 2011.
+
+Updated the solaris9+ssl target to do the DES testing.  makefile, 16 Jun 2011.
+
+Updated cu-solaris+krb5 target to test whether the GSSAPI library is called
+libgassapi or libgassapi_krb5.  makefile, 16 Jun 2011.
+
+Added lots of tests to the Linux Kerberos 5 entries, linux+krb5 and
+linux+krb5+ssl, because some have libk5crypto and some don't; some have
+libcom_err and some don't; and some have libgssapi_krb5 (e.g. RHEL5,
+OpenSuse 11.2) whereas others have libgssapi (Gentoo).
+
+16 June 2011 builds (Beta.01):
+
+NetBSD 5.1 i386   32/64  netbsd+krb5+ssl   2451757 OpenSSL 0.9.9 MIT Krb5 1.6.3
+Solaris 9  sparc  32/64  solaris9+krb5     2543036 MIT Kerberos 5 1.7.1
+Solaris 9  sparc  32/64  solaris9+ssl      5021544 OpenSSL 0.9.8q (gcc)
+Gentoo...  ppc    32/64  linux             2386597
+Gentoo...  ppc    32/64  linux+ssl         2593561 OpenSSL 0.9.8r 
+Gentoo...  ppc64   64    linux             2749015
+Gentoo...  ppc64   64    linux+ssl         3002150 OpenSSL 0.9.8r 
+RHEL5      x86_64  64    linux+krb5 (*)    2563878 MIT Kerberos 5 1.6.1
+RHEL5      x86_64  64    linux+krb5+ssl(*) 2563878 MIT Kerberos 5 1.6.1
+Fedora 14  i386   32/64  linux+krb5+ssl    2539891 MIT Krb5 + OpenSSL 0.9.8r
+
+* KFLAGS=-UCK_DES
+
+---------------------------------
+***************************
index c7c32cc..68cd2f7 100644 (file)
--- a/ckcasc.h
+++ b/ckcasc.h
@@ -6,7 +6,7 @@
   Author: Frank da Cruz (fdc@columbia.edu).
   Columbia University Academic Information Systems, New York City.
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2009,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -42,7 +42,7 @@
 #define SYN   22        /* SYN, Ctrl-V */
 #define ETB   23        /* Ctrl-W */
 #define CAN   24        /* CAN, Ctrl-X */
-#define EM    25        /* Ctrl-Y */
+#define XEM   25        /* Ctrl-Y (was EM but conflicts with OpenSSL) */
 #define SUB   26        /* SUB Ctrl-Z */
 #define ESC   27        /* Escape Ctrl-[ */
 #define XFS   28        /* Field Separator,  Ctrl-Backslash */
diff --git a/ckcbwr.txt b/ckcbwr.txt
deleted file mode 100644 (file)
index 5e70e65..0000000
+++ /dev/null
@@ -1,1467 +0,0 @@
-
-                      C-Kermit 8.0 General Hints and Tips
-
-     Frank da Cruz
-     [1]The Kermit Project, [2]Columbia University
-
-   As of: C-Kermit 8.0.211, 17 March 2003
-   This page last updated: Sat Apr 10 16:37:37 2004 (New York USA Time)
-
-     IF YOU ARE READING A PLAIN-TEXT version of this document, it is a
-     plain-text dump of a Web page. You can visit the original (and
-     possibly more up-to-date) Web page here:
-
-  [3]http://www.columbia.edu/kermit/ckcbwr.html
-
-   This document contains platform-independent C-Kermit hints and tips.
-   Also see the platform-specific C-Kermit hints and tips document for
-   your platform, for example:
-
-  [4]http://www.columbia.edu/kermit/ckubwr.html
-
-   for Unix. This document also applies to [5]Kermit 95 for Windows,
-   which is based on C-Kermit.
-
-   [ [6]C-Kermit ] [ [7]TUTORIAL ]
-    ________________________________________________________________________
-
-  CONTENTS
-
-   0. [8]PATCHES
-   1. [9]INCOMPATIBLE CHANGES
-   2. [10]THE C-KERMIT COMMAND PARSER
-   3. [11]MULTIPLE SESSIONS
-   4. [12]NETWORK CONNECTIONS
-   5. [13]MODEMS AND DIALING
-   6. [14]DIALING HINTS AND TIPS
-   7. [15]TERMINAL SERVERS
-   8. [16]TERMINAL EMULATION
-   9. [17]KEY MAPPING
-  10. [18]FILE TRANSFER
-  11. [19]SCRIPT PROGRAMMING
-    ________________________________________________________________________
-
-  0. PATCHES
-
-   [ [20]Top ] [ [21]Contents ] [ [22]Next ]
-
-   Source-level patches for C-Kermit 8.0.211:
-
-     (None)
-    ________________________________________________________________________
-
-  1. INCOMPATIBLE CHANGES
-
-   [ [23]Top ] [ [24]Contents ] [ [25]Next ]
-
-   These are not necessarily exhaustive lists.
-
-  1.1. C-Kermit 6.0
-
-   C-Kermit 6.0 was released 6 September 1996 and is completely
-   documented in [26]Using C-Kermit, 2nd Edition. The following
-   incompatible changes were made in C-Kermit 6.0:
-
-     * Unless you tell C-Kermit otherwise, if a serial or network
-       connection seems to be open, and you attempt to EXIT or to open a
-       new connection, C-Kermit warns you that an active connection
-       appears to be open and asks you if you really want to close it. If
-       you do not want these warnings, add SET EXIT WARNING OFF to your
-       customization file or script, or give this command at the prompt.
-     * The default for SET { SEND, RECEIVE } PATHNAMES was changed from
-       ON to OFF, to prevent unexpected creation of directories and
-       depositing of incoming files in places you might not know to look.
-     * The default for SET FILE INCOMPLETE was changed from DISCARD to
-       KEEP to allow for file transfer recovery.
-     * The default file-transfer block-check is now 3, rather than 1. If
-       the other Kermit does not support this, the two will drop back to
-       type 1 automatically unless the other Kermit fails to follow the
-       protocol specification.
-     * The default flow-control is now "auto" ("do the right thing for
-       each type of connection"), not Xon/Xoff.
-     * Backslash (\) is no longer a command continuation character. Only
-       - (hyphen, dash) may be used for this in C-Kermit 6.0 and later.
-     * Negative INPUT timeout now results in infinite wait, rather than 1
-       second.
-
-  1.2. C-Kermit 7.0
-
-   C-Kermit 7.0 was released 1 January 2000. Its new features are
-   documented in the C-Kermit 7.0 Supplement,
-   [27]http://www.columbia.edu/kermit/ckermit2.html. The following
-   incompatible changes were made in C-Kermit 7.0:
-     * The "multiline GET" command is gone. Now use either of the
-       following forms instead:
-  get remote-name local-name
-  get /as-name:local-name remote-name
-       If either name contains spaces, enclose it in braces (or, in
-       C-Kermit 8.0, doublequotes).
-     * To include multiple file specifications in a GET command, you must
-       now use MGET rather than GET:
-  mget file1 file2 file3 ...
-     * C-Kermit 7.0 and later use FAST Kermit protocol settings by
-       default. This includes "unprefixing" of certain control
-       characters. Because of this, file transfers that worked with
-       previous releases might not work in the new release especially
-       against a non-Kermit-Project Kermit protocol implementation (but
-       it is more likely that they will work, and much faster). If a
-       transfer fails, you'll get a context-sensitive hint suggesting
-       possible causes and cures. Usually SET PREFIXING ALL does the
-       trick.
-     * By default C-Kermit 7.0 and later send files in text or binary
-       mode by looking at each file to see which is the appropriate mode.
-       To restore the previous behavior, put SET TRANSFER MODE MANUAL and
-       the desired SET FILE TYPE (TEXT or BINARY) in your C-Kermit
-       initialization file.
-     * The RESEND and REGET commands automatically switch to binary mode;
-       previously if RESEND or REGET were attempted when FILE TYPE was
-       TEXT, these commands would fail immediately, with a message
-       telling you they work only when the FILE TYPE is BINARY. Now they
-       simply do this for you.
-     * SET PREFIXING CAUTIOUS and MINIMAL now both prefix linefeed (10
-       and 138) in case rlogin, ssh, or cu are "in the middle", since
-       otherwise <LF>~ might appear in Kermit packets, and this would
-       cause rlogin, ssh, or cu to disconnect, suspend,escape back, or
-       otherwise wreck the file transfer. Xon and Xoff are now always
-       prefixed too, even when Xon/Xoff flow control is not in effect,
-       since unprefixing them has proven dangerous on TCP/IP connections.
-     * In UNIX, VMS, Windows, and OS/2, the DIRECTORY command is built
-       into C-Kermit itself rather than implemented by running an
-       external command or program. The built-in command might not behave
-       the way the platform-specific external one did, but many options
-       are available for customization. Of course the underlying
-       platform-specific command can still be accessed with "!", "@", or
-       "RUN" wherever the installation does not forbid. In UNIX, the "ls"
-       command can be accessed directly as "ls" in C-Kermit.
-     * SEND ? prints a list of switches rather than a list of filenames.
-       If you want to see a list of filenames, use a (system-dependent)
-       construction such as SEND ./? (for UNIX, Windows, or OS/2), SEND
-       []? (VMS), etc.
-     * In UNIX, OS-9, and Kermit 95, the wildcard characters in previous
-       versions were * and ?. In C-Kermit 7.0 they are *, ?, [, ], {, and
-       }, with dash used inside []'s to denote ranges and comma used
-       inside {} to separate list elements. If you need to include any of
-       these characters literally in a filename, precede each one with
-       backslash (\).
-     * SET QUIET { ON, OFF } is now on the command stack, just like SET
-       INPUT CASE, SET COUNT, SET MACRO ERROR, etc, as described on p.458
-       of [28]Using C-Kermit, 2nd Edition. This allows any macro or
-       command file to SET QUIET ON or OFF without worrying about saving
-       and restoring the global QUIET value. For example, this lets you
-       write a script that tries SET LINE on lots of devices until it
-       finds one free without spewing out loads of error messages, and
-       also without disturbing the global QUIET setting, whatever it was.
-     * Because of the new "." operator (which introduces assignments),
-       macros whose names begin with "." can not be invoked "by name".
-       However, they still can be invoked with DO or \fexecute().
-     * The syntax of the EVALUATE command has changed. To restore the
-       previous syntax, use SET EVALUATE OLD.
-     * The \v(directory) variable now includes the trailing directory
-       separator; in previous releases it did not. This is to allow
-       constructions such as:
-  cd \v(dir)data.tmp
-       to work across platforms that might have different directory
-       notation, such as UNIX, Windows, and VMS.
-     * Prior to C-Kermit 7.0, the FLOW-CONTROL setting was global and
-       sticky. In C-Kermit 7.0, there is an array of default flow-control
-       values for each kind of connection, that are applied automatically
-       at SET LINE/PORT/HOST time. Thus a SET FLOW command given before
-       SET LINE/PORT/HOST is likely to be undone. Therefore SET FLOW can
-       be guaranteed to have the desired effect only if given after the
-       SET LINE/PORT/HOST command.
-     * Character-set translation works differently in the TRANSMIT
-       command when (a) the file character-set is not the same as the
-       local end of the terminal character-set, or (b) when the terminal
-       character-set is TRANSPARENT.
-
-  1.3. C-Kermit 8.0
-
-   The following incompatible changes were made in C-Kermit 8.0:
-     * C-Kermit now accepts doublequotes in most contexts where you
-       previously had to use braces to group multiple words into a single
-       field, or to force inclusion of leading or trailing blanks. This
-       might cause problems in contexts where you wanted the doublequote
-       characters to be taken literally. Consult [29]Section 5 of the
-       [30]C-Kermit 8.0 Update Notes for further information.
-     * Using the SET HOST command to make HTTP connections is no longer
-       supported. Instead, use the new [31]HTTP OPEN command.
-    ________________________________________________________________________
-
-  2. THE C-KERMIT COMMAND PARSER
-
-   [ [32]Top ] [ [33]Contents ] [ [34]Next ] [ [35]Previous ]
-
-   Various command-related limits are shown in the following table, in
-   which the sample values are for a "large memory model" build of
-   C-Kermit, typical for modern platforms (Linux, Solaris, AIX, VMS,
-   etc). You can see the values for your version of Kermit by giving the
-   SHOW FEATURES command. The maximum length for a Kermit command (CMDBL)
-   also determines the maximum length for a macro definition, since
-   DEFINE is itself a command. The maximum length for a variable name is
-   between 256 and 4096 characters, depending on the platform; for array
-   declarations and references, that includes the subscript.
-       ______________________________________________________________
-
-   Item Symbol Sample
-   Value Definition
-   Number of characters in a command CMDBL 32763 ckucmd.h
-   Number of chars in a field of a command    ATMBL 10238 ckucmd.h
-   Nesting level for command files MAXTAKE 54   ckuusr.h
-   Nesting level for macros MACLEVEL 128 ckuusr.h
-   Nesting level for FOR / WHILE loops FORDEPTH 32 ckuusr.h
-   Number of macros MAC_MAX 16384 ckuusr.h
-   Size of INPUT buffer INPBUFSIZ 4096 ckuusr.h
-   Maximum files to match a wildcard MAXWLD    102400 ckcdeb.h
-   Filespecs in MSEND command MSENDMAX 1024 ckuusr.h
-   Length for GOTO target label LBLSIZ 50 ckuusr.h
-   \fexecute() recursion depth limit CMDDEP 64 ckucmd.h
-       ______________________________________________________________
-
-   If you need to define a macro that is longer than CMDBL, you can break
-   the macro up into sub-macros or rewrite the macro as a command file.
-   In a pinch you can also redefine CMDBL and recompile C-Kermit. All of
-   these numbers represent tradeoffs: the bigger the number, the more
-   "powerful" Kermit in the corresponding area, but also the bigger the
-   program image and possibly disk footprint, and the longer it takes to
-   load and initialize.
-
-   In the interactive command parser:
-
-     * EMACS- or VI-style command line editing is not supported.
-     * Editing keys are hardwired (Ctrl-U, Ctrl-W, etc).
-
-   If you interrupt C-Kermit before it has issued its first prompt, it
-   will exit. This means that you cannot interrupt execution of the
-   initialization file, or of an "application file" (file whose name is
-   given as the first command-line argument), or of an alternative
-   initialization file ("-y filename"), and get to the prompt. There is,
-   however, one exception to this rule: you *can* interrupt commands --
-   including TAKE commands -- given in the '-C "command list"'
-   command-line argument and -- if there were no action commands among
-   the command-line arguments -- you will be returned to the C-Kermit
-   prompt. So, for example, if you want to start C-Kermit in such a way
-   that it executes a command file before issuing its first prompt, and
-   you also want to be able to interrupt the command file and get to the
-   prompt, include a TAKE command for the desired command in the -C
-   argument, for example:
-
-  kermit -C "take dial.scr"
-
-   At the command prompt, if you use the backslash (\) prefix to enter a
-   control character, space, or question mark into a command literally,
-   the backslash disappears and is replaced by the quoted character. If
-   it was a control character, it is shown as a circumflex (^). This
-   allows editing (backspace, delete, Ctrl-W) to work correctly even for
-   control characters.
-
-   Priot to C-Kermit 8.0, the only way to include a comma literally in a
-   macro definition -- as opposed to having it separate commands within
-   the definition -- is to enter its ASCII value (44) in backslash
-   notation, e.g.:
-
-  DEFINE ROWS RUN MODE CO80\{44}\%1
-
-   In C-Kermit 8.0 you can use constructions like this:
-
-  DEFINE ROWS RUN MODE "CO80,\%1"
-
-   If you quote special characters in a filename (e.g. in the SEND
-   command), filename completion may seem to work incorrectly. For
-   example, if you have a file whose name is a*b (the name really
-   contains an asterisk), and you type "send a\\*<ESC>", the "b" does not
-   appear, nor will Ctrl-R redisplay the completed name correctly. But
-   internally the file name is recognized anyway.
-
-   Question-mark help does not work during execution of an ASKQ command.
-   The question marks are simply accepted as text.
-
-   In OUTPUT commands only, \B sends a BREAK signal, \L sends a Long
-   BREAK signal, and \N sends a NUL (ASCII 0). BREAK and Long BREAK are
-   special signals, not characters, and NUL is a character that normally
-   cannot be included in a C string, since it is the C string terminator.
-   If you really want to output a backslash followed by a B, an L, or an
-   N (as is needed to configure certain modems, etc), double the
-   backslash, e.g. "output \\B". In C-Kermit 7.0 or later, you can disarm
-   and re-arm the special OUTPUT-command escapes (\B, \L, and \N) with
-   SET OUTPUT SPECIAL-ESCAPES { OFF, ON }.
-
-   When using the command-line processor ("kermit -l /dev/tty00 -b
-   19200", etc), note that in some cases the order of the command-line
-   options makes a difference, contrary to the expectation that order of
-   command-line options should not matter. For example, the -b option
-   must be given after the -l option if it is to affect the device
-   specified in the -l option.
-    ________________________________________________________________________
-
-  3. MULTIPLE SESSIONS
-
-   [ [36]Top ] [ [37]Contents ] [ [38]Next ] [ [39]Previous ]
-
-   C-Kermit 7.0 and earlier do not support multiple sessions. When you
-   SET LINE (or SET PORT, same thing) to a new device, or SET HOST to a
-   new host, the previous SET LINE device or network host connection is
-   closed, resulting in hangup of the modem or termination of the network
-   connection. In windowing environments like HP-VUE, NeXTSTEP, Windows,
-   OS/2, etc, you can run separate copies of Kermit in different windows
-   to achieve multiple sessions.
-
-   To achieve multiple sessions through a single serial port (e.g. when
-   dialing up), you can install SLIP or PPP on your computer and then use
-   C-Kermit's TCP/IP support over the SLIP or PPP connection, assuming
-   you also have TCP/IP networking installed on your computer.
-
-   C-Kermit 8.0 has the same restriction on SET LINE and SET HOST
-   sessions: only one regular session (dialout, Telnet, etc) can be open
-   at a time. However, version 8.0 adds two new kinds of sessions: FTP
-   and HTTP; one or both of these can be open at the same as a regular
-   session.
-    ________________________________________________________________________
-
-  4. NETWORK CONNECTIONS
-
-   [ [40]Top ] [ [41]Contents ] [ [42]Next ] [ [43]Previous ]
-
-  FTP Client Bugs
-
-   The Unix C-Kermit 8.0.206 FTP client had the following bugs at the
-   time most of the 8.0.206 binaries were built for the C-Kermit 8.0
-   CDROM:
-
-    1. FTP MGET fails when directory segments contain wildcards, as in
-       "ftp mget */data/*.dat". Work around by doing a separate MGET for
-       each source directory.
-    2. FTP MGET can fail or produce random side effects if you have a
-       TMPDIR or CK_TMP environment variable definition in effect, or a
-       SET TEMP-DIRECTORY value, longer than 7 characters. Work around by
-       giving a SET TEMP-DIRECTORY command with a short value, such as
-       "/tmp".
-
-   These two bugs are fixed in the source code that is included on the
-   CDROM, and also in Kermit 95 2.1.1. You can tell if a C-Kermit 8.0.206
-   binary has these fixes by typing SHOW VERSION; if it says "FTP Client,
-   8.0.200, 24 Oct 2002" it has the fixes; if the edit number is less
-   that 200, it doesn't, in which case can build a new binary from the
-   source code (or contact us and we'll try to get get one for you).
-
-  Making TCP/IP Connections Can Take a Long Time
-
-   The most frequently asked question in many newsgroups is "Why does it
-   take such a long time to make a Telnet connection to (or from) my
-   (e.g.) Linux PC?" (this applies to Kermit as well as to regular Telnet
-   clients):
-
-    1. Most Telnet servers perform reverse DNS lookups on the client for
-       security and/or logging reasons. If the Telnet client's host
-       cannot be found by the server's local DNS server, the DNS request
-       goes out to the Internet at large, and this can take quite some
-       time. The solution to this problem is to make sure that both
-       client and host are registered in DNS.
-    2. C-Kermit itself performs reverse DNS lookups unless you tell it
-       not to. This is to allow C-Kermit to let you know which host it is
-       actually connected to in case you have made a connection to a
-       "host pool" (multihomed host). You can disable C-Kermit's reverse
-       DNS lookup with SET TCP REVERSE-DNS-LOOKUP OFF.
-    3. C-Kermit 7.0 and later strictly enforce Telnet protocol rules. One
-       such rule is that certain negotiations must be responded to. If
-       C-Kermit sends a such a negotiation and the host does not respond,
-       C-Kermit waits a long time for the reply (in case the network is
-       congested or the host is slow), but eventually will time out. To
-       eliminate the waits (and therefore risk possible protocol
-       mismatches -- or worse -- between Telnet client and server), tell
-       C-Kermit to SET TELNET WAIT OFF (or include the /NOWAIT switch
-       with the TELNET command).
-
-  The Rlogin Client
-
-   In multiuser operating systems such as UNIX and VMS, TCP/IP Rlogin
-   connections are available only to privileged users, since "login" is a
-   privileged socket. Assuming you are allowed to use it in the first
-   place, it is likely to behave differently depending on what type of
-   host you are rlogging in to, due to technical reasons having to do
-   with conflicting interpretations of RFC793 (Out-Of-Band Data) and
-   Rlogin (RFC1122)... "Specifically, the TCP urgent pointer in BSD
-   points to the byte after the urgent data byte, and an RFC-compliant
-   TCP urgent pointer points to the urgent data byte. As a result, if an
-   application sends urgent data from a BSD-compatible implementation to
-   an [44]RFC-1122 compatible implementation then the receiver will read
-   the wrong urgent data byte (it will read the byte located after the
-   correct byte in the data stream as the urgent data byte)." Rlogin
-   requires the use of OOB data while Telnet does not. Therefore, it is
-   possible for Telnet to work between all systems while BSD and System V
-   TCP/IP implementations are almost always a bad mix.
-
-  The Telnet Client
-
-   On a TCP/IP TELNET connection, you should normally have PARITY set to
-   NONE and (except in VMS C-Kermit) FLOW-CONTROL also set to NONE. If
-   file transfer does not work with these settings (for example, because
-   the remote TELNET server only gives a 7-bit data path), use SET PARITY
-   SPACE. Do not use SET PARITY MARK, EVEN, or ODD on a TELNET connection
-   -- it interferes with TELNET protocol.
-
-   If echoing does not work right after connecting to a network host or
-   after dialing through a TCP/IP modem server, it probably means that
-   the TELNET server on the far end of the connection is executing the
-   TELNET protocol incorrectly. After initially connecting and
-   discovering incorrect echoing (characters are echoed twice, or not at
-   all), escape back, give the appropriate SET DUPLEX command (FULL or
-   HALF), and then CONNECT again. For a consistently misbehaving
-   connection, you can automate this process in a macro or TAKE file.
-
-   TELNET sessions are treated just like serial communications sessions
-   as far as "terminal bytesize" and "command bytesize" are concerned. If
-   you need to view and/or enter 8-bit characters during a TELNET
-   session, you must tell C-Kermit to SET TERMINAL BYTESIZE 8, SET
-   COMMAND BYTESIZE 8, and SET PARITY NONE.
-
-   If you SET TELNET DEBUG ON prior to making a connection, protocol
-   negotiations will be displayed on your screen. You can also capture
-   them in the debug log (along with everything else) and then extract
-   them easily, since all Telnet negotiations lines begin with
-   (uppercase) "TELNET".
-    ________________________________________________________________________
-
-  5. MODEMS AND DIALING
-
-   [ [45]Top ] [ [46]Contents ] [ [47]Next ] [ [48]Previous ]
-
-   External modems are recommended because:
-
-     * They don't need any special drivers.
-     * They are less likely to interfere with normal operation of your
-       computer.
-     * You can use the lights and speaker to troubleshoot dialing.
-     * You can share them among all types of computers.
-     * You can easily turn them off and on when power-cycling seems
-       warranted.
-     * They are more likely to have manuals.
-
-   Modems can be used by C-Kermit only when they are visible as or
-   through a regular serial port device. Certain modems can not be used
-   in this normal way on many kinds of computers: Winmodems, RPI modems,
-   Controllerless modems, the IBM Mwave, etc; all of these require
-   special drivers that perform some, most, or all of the modem's
-   functions in software. Such drivers are generally NOT available in
-   UNIX or other non-Windows (or non-OS/2, in the case of the Mwave)
-   platforms.
-
-   In order to dial a modem, C-Kermit must know its repertoire of
-   commands and responses. Each modem make and model is likely to have a
-   different repertoire. Since Kermit has no way of knowhing which kind
-   of modem will be dialed, normally you have to tell it with a SET MODEM
-   TYPE command, e.g.:
-
-  set modem type usrobotics
-  set line /dev/cua0
-  set speed 57600
-  dial 7654321
-
-   In the early days, there was a wide variety of modems and command
-   languages. Nowadays, almost every modem uses the Hayes AT command set
-   (but with some differences in the details) and its startup
-   configuration includes error correction, data compression, and
-   hardware (RTS/CTS) flow control. As long as C-Kermit is capable of
-   hardware flow control (as it is on many, but not all, the platforms
-   where it runs, since some operating systems don't support it), the
-   modem can be dailed immediately, without lengthy configuration
-   dialogs, and in fact this is what SET MODEM TYPE GENERIC-HIGH-SPEED
-   does. In C-Kermit 8.0, GENERIC-HIGH-SPEED has become the default modem
-   type, so now it is usually possible to SET LINE, SET SPEED, and DIAL
-   without having to identify your modem. If this doesn't work, of
-   course, then you might have to fall back to the tradiational method:
-   Give a SET MODEM TYPE for a specific modem first, then SET LINE, SET
-   SPEED, and DIAL.
-
-   An important change in C-Kermit 6.0 is that when you give a SET MODEM
-   TYPE command to tell Kermit what kind of modem you have, Kermit also
-   sets a number of other modem-related parameters automatically from its
-   internal modem database. Thus, the order in which you give
-   modem-related commands is significant, whereas in prior releases they
-   could be given in any order.
-
-   In particular, MODEM SPEED-MATCHING is set according to whether the
-   modem is known to be capable of speed buffering. SET MODEM TYPE
-   HAYES-2400 automatically turns SPEED-MATCHING ON, because when the
-   Hayes 2400 reports a particular speed in its CONNECT message, that
-   means its interface speed has changed to that speed, and C-Kermit's
-   must change accordingly if it is to continue communicating. This might
-   cause some confusion if you use "set modem type hayes" for dialing a
-   more advanced type of modem.
-
-   The new default for flow control is "auto", meaning "do the right
-   thing for each type of connection". So (for example) if your version
-   of C-Kermit supports SET FLOW RTS/CTS and your modem also supports
-   RTS/CTS, then Kermit automatically sets its flow control to RTS/CTS
-   and set modem's flow control to RTS/CTS too before attempting to use
-   the modem.
-
-   For these reasons, don't assume that "set modem type hayes" should be
-   used for all modems that uses the Hayes AT command set. "set modem
-   type hayes" really does mean Hayes 1200 or 2400, which in turn means
-   no hardware flow control, and no speed buffering. This choice will
-   rarely work with a modern high-speed modem.
-    ________________________________________________________________________
-
-  6. DIALING HINTS AND TIPS
-
-   [ [49]Top ] [ [50]Contents ] [ [51]Next ] [ [52]Previous ]
-
-   If you have a high-speed, error-correcting, data-compressing,
-   speed-buffering modem, you should fix the modem's interface speed as
-   high as possible, preferably (at least) four times higher than its
-   maximum connection (modulation) speed to allow compression to work at
-   full advantage. In this type of setup, you must also have an effective
-   means of flow control enabled between C-Kermit and the modem,
-   preferably hardware (RTS/CTS) flow control. On platforms that do not
-   support hardware flow control, it is usually possible to select
-   software flow control (Xon/Xoff), and C-Kermit will do its best to set
-   the modem for local Xon/Xoff flow control too (but then, of course,
-   Ctrl-S and Ctrl-Q characters can not be transmitted on the
-   connection).
-
-   If you are having trouble dialing your modem, SET DIAL DISPLAY ON to
-   watch the dialing interactions between C-Kermit and your modem.
-   Consult Chapters 3-4 of [53]Using C-Kermit (2nd Ed) for modem-dialing
-   troubleshooting instructions. The following sections offer some
-   addtional hints and tips.
-
-  6.1. Syntax
-
-   If you want to dial a number that starts with #, you'll need to quote
-   the "#" character (as \# or \{35}), since it is also a comment
-   introducer:
-
-  C-Kermit>dial #98765421-1-212-5551212   ; Looks like a comment
-  ?You must specify a number to dial
-  C-Kermit>dial \#98765421-1-212-5551212  ; Works OK
-  C-Kermit>dial =#98765421-1-212-5551212  ; This works too
-
-   When using a dialing directory, remember what happens if a name is not
-   found:
-
-  C-Kermit>dial xyzcorp
-  Lookup: "xyzcorp" - not found - dialing as given
-
-   This normally does no harm, but some modems might behave strangely
-   when given dial strings that contain certain letters. For example, a
-   certain German modem treats any dial string that contains the letter
-   "s" as a command to fetch a number from its internal list, and replies
-   OK to the ATD command, which is normally not a valid response except
-   for partial dialing. To avoid this situation, use:
-
-  lookup xyzcorp
-  if success dial
-
-  6.2. The Carrier Signal
-
-   Remember: In many C-Kermit implementations (depending on the
-   underlying operating system -- mostly Windows, OS/2, and
-   System-V-based UNIX versions, and in C-Kermit 7.0, also VMS), you
-   can't CONNECT to a modem and type the modem's dialing command (like
-   "ATDT7654321") manually, unless you first tell C-Kermit to:
-
-  SET CARRIER-WATCH OFF
-
-   This is because (in these implementations), the CONNECT command
-   requires the modem's Carrier Detect (CD) signal to be on, but the CD
-   signal doesn't come on until after dialing is complete. This
-   requirement is what allows C-Kermit to pop back to its prompt
-   automatically when the connection is hung up. See the description of
-   SET CARRIER-WATCH in "Using C-Kermit".
-
-   Similarly, if your dialed connection drops when CARRIER-WATCH is set
-   to AUTO or ON, you can't CONNECT back to the (now disconnected) screen
-   to see what might have happened unless you first SET CARRIER-WATCH
-   OFF. But sometimes not even SET CARRIER-WATCH OFF will help in this
-   situation: certain platforms (for example Unixware 2.1), once carrier
-   drops, won't let the application do i/o with the device any more. In
-   that case, if you want to use the device again, you have to CLOSE it
-   and OPEN it again. Or you can have Kermit do this for you
-   automatically by telling it to SET CLOSE-ON-DISCONNECT ON.
-
-  6.3. Dialing and Flow Control
-
-   Don't SET FLOW RTS/CTS if your modem is turned off, or if it is not
-   presenting the CTS signal. Otherwise, the serial device driver can get
-   stuck waiting for this signal to appear.
-
-   Most modern modems support RTS/CTS (if they support any hardware flow
-   control at all), but some computers use different RS-232 circuits for
-   the same purposes, e.g. DTR and CD, or DTR and CTS. In such cases, you
-   might be able to make your computer work with your modem by
-   appropriately cross-wiring the circuits in the cable connector, for
-   example the computer's DTR to the modem's RTS, and modem's CD to the
-   computer's CTS. HOWEVER, C-Kermit does not know you have done this. So
-   if you have (say) SET FLOW DTR/CD, C-Kermit will make no attempt to
-   tell the modem to use RTS/CTS. You probably did this yourself when you
-   configured the modem.
-
-  6.4. The Dial Timeout
-
-   If it takes your call longer to be completed than the timeout interval
-   that C-Kermit calculates, you can use the SET DIAL TIMEOUT command to
-   override C-Kermit's value. But beware: the modem has its own timeout
-   for completing the call. If it is a Hayes-like modem, C-Kermit adjusts
-   the modem's value too by setting register S7. But the maximum value
-   for S7 might be smaller than the time you need! In that case, C-Kermit
-   sets S7 to 0, 255, or other (modem-specific) value to signify "no
-   timeout". If Kermit attempts to set register S7 to a value higher than
-   your modem's maximum, the modem will say "ERROR" and you will get a
-   "Failure to initialize modem" error. In that case, use SET DIAL
-   TIMEOUT to override C-Kermit's calculation of the timeout value with
-   the highest value that is legal for your modem, e.g. 60.
-
-  6.5. Escape Sequence Guard Time
-
-   A "TIES" (Time-Independent Escape Sequence) modem does not require any
-   guard time around its escape sequence. The following text:
-
-  +++ATH0
-
-   if sent through a TIES modem, for example because you were uploading
-   this file through it, could pop the modem back into command mode and
-   make it hang up the connection. Later versions of the Telebit T1600
-   and T3000 (version LA3.01E firmware and later), and all WorldBlazers,
-   use TIES.
-
-   Although the probability of "+++" appearing in a Kermit packet is
-   markedly lower than with most other protocols (see the [54]File
-   Transfer section below), it can still happen under certain
-   circumstances. It can also happen when using C-Kermit's TRANSMIT
-   command. If you are using a Telebit TIES modem, you can change the
-   modem's escape sequence to an otherwise little-used control character
-   such as Ctrl-_ (Control-Underscore):
-
-  AT S2=31
-
-   A sequence of three consecutive Ctrl-_ characters will not appear in a
-   Kermit packet unless you go to extraordinary lengths to defeat more
-   than a few of Kermit's built-in safety mechanisms. And if you do this,
-   then you should also turn off the modem's escape-sequence recognition
-   altogether:
-
-  AT S48=0 S2=255
-
-   But when escape sequence recognition is turned off, "modem hangup"
-   (<pause>+++<pause>ATH0<CR>) will not work, so you should also SET
-   MODEM HANGUP RS232-SIGNAL (rather then MODEM-COMMAND).
-
-  6.6. Adaptive Dialing
-
-   Some modems have a feature called adaptive dialing. When they are told
-   to dial a number using Tone dialing, they check to make sure that
-   dialtone has gone away after dialing the first digit. If it has not,
-   the modem assumes the phone line does not accept Tone dialing and so
-   switches to Pulse. When dialing out from a PBX, there is almost always
-   a secondary dialtone. Typically you take the phone off-hook, get the
-   PBX dialtone, dial "9" to get an outside line, and then get the phone
-   company's dialtone. In a situation like this, you need to tell the
-   modem to expect the secondary dialtone. On Hayes and compatible
-   modems, this is done by putting a "W" in the dial string at the
-   appropriate place. For example, to dial 9 for an outside line, and
-   then 7654321, use ATDT9W7654321:
-
-  SET PBX-OUTSIDE-PREFIX 9W
-
-   (replace "9" with whatever your PBX's outside-line prefix is).
-
-  6.7. The Busy Signal
-
-   Some phone companies are eliminating the busy signal. Instead, they
-   issue a voice message such as "press 1 to automatically redial until
-   the number answers, or...". Obviously this is a disaster for modem
-   calls. If your service has this feature, there's nothing Kermit can do
-   about it. Your modem will respond with NO CARRIER (after a long time)
-   rather than BUSY (immediately), and Kermit will declare the call a
-   failure, rather than trying to redial the same number.
-
-  6.8. Hanging Up
-
-   There are two ways to hang up a modem: by turning off the serial
-   port's DTR signal (SET MODEM HANGUP-METHOD RS232-SIGNAL) or sending
-   the modem its escape sequence followed by its hangup command (SET
-   MODEM HANGUP-METHOD MODEM-COMMAND). If one doesn't work, try the
-   other. If the automatic hangup performed at the beginning of a DIAL
-   command causes trouble, then SET DIAL HANGUP OFF.
-
-   The HANGUP command has no effect when C-Kermit is in remote mode. This
-   is on purpose. If C-Kermit could hang up its own controlling terminal,
-   this would (a) most likely leave behind zombie processes, and (b) pose
-   a security risk.
-
-   If you DIAL a modem, disconnect, then SET HOST or TELNET, and then
-   HANGUP, Kermit sends the modem's hangup command, such as "+++ATHO".
-   There is no good way to avoid this, because this case can't reliably
-   be distinguished from the case in which the user does SET HOST
-   terminal-server, SET MODEM TYPE name, DIAL. In both cases we have a
-   valid modem type selected and we have a network connection. If you
-   want to DIAL and then later make a regular network connection, you
-   will have to SET MODEM TYPE NONE or SET DIAL HANGUP OFF to avoid this
-   phenomenon.
-    ________________________________________________________________________
-
-  7. TERMINAL SERVERS
-
-   [ [55]Top ] [ [56]Contents ] [ [57]Next ] [ [58]Previous ]
-
-   Watch out for terminal server's escape character -- usually a control
-   character such as Ctrl-Circumflex (Ctrl-^). Don't unprefix it in
-   Kermit!
-
-   Ciscos -- must often be told to "terminal download"... Cisco ASM
-   models don't have hardware flow control in both directions.
-
-   Many terminal servers only give you a 7-bit connection, so if you
-   can't make it 8-bit, tell Kermit to "set parity space".
-
-   The following story, regarding trouble transferring 8-bit files
-   through a reverse terminal server, was contributed by an Annex
-   terminal server user:
-
-     Using C-Kermit on an HP 9000 712/80 running the HP-UX 10.0
-     operating system. The HP was connected to a Xylogics Annex
-     MICRO-ELS-UX R7.1 8 port terminal server via ethernet. On the
-     second port of the terminal server is an AT&T Paradyne 3810 modem,
-     which is connected to a telephone line. There is a program which
-     runs on the HP to establish a Telnet connection between a serial
-     line on the Annex and a character special file on the HP (/dev
-     file). This is an Annex specific program called rtelnet (reverse
-     telnet) and is provided with the terminal server software. The
-     rtelnet utility runs on top of the pseudo-terminal facility
-     provided by UNIX. It creates host-originiated connections to
-     devices attached ot Annex serial ports. There are several command
-     line arguments to be specified with this program: the IP address of
-     the terminal server, the number of the port to attach to, and the
-     name of the pseudo-device to create. In addition to these there are
-     options to tell rtelnet how to operate on the connect: -b requests
-     negotiation for Telnet binary mode, -d turns on socket-leve
-     debugging, -f enables "connect on the fly" mode, -r removes the
-     device-name if it already exists, etc. The most important of these
-     to be specified when using 8 data bits and no parity, as we found
-     out, was the -t option. This creates a transparent TCP connection
-     to the terminal server. Again, what we assumed to be happening was
-     that the rtelnet program encountered a character sequence special
-     to itself and then "eating" those kermit packets. I think this is
-     all of the information I can give you on the configuration, short
-     of the values associated with the port on the terminal server.
-
-   How to DIAL from a TCP/IP reverse terminal server (modem server):
-
-    1. (only if necessary) SET TELNET ECHO REMOTE
-    2. SET HOST terminal-server-ip-name-or-address [ port ]
-    3. SET MODEM TYPE modem-type
-    4. (only if necessary) SET DIAL HANGUP OFF
-    5. (for troubleshooting) SET DIAL DISPLAY ON
-    6. DIAL phone-number
-
-   The order is important: SET HOST before SET MODEM TYPE. Since this is
-   a Telnet connection, serial-port related commands such as SET SPEED,
-   SET STOP-BITS, HANGUP (when MODEM HANGUP-METHOD is RS232), etc, have
-   no effect. However, in C-Kermit 8.0, if the modem server supports
-   [59]RFC-2217 Telnet Com-Port Control protocol, these commands do
-   indeed take effect at the server's serial port.
-    ________________________________________________________________________
-
-  8. TERMINAL EMULATION
-
-   [ [60]Top ] [ [61]Contents ] [ [62]Next ] [ [63]Previous ]
-
-   Except for the Windows, OS/2, and Macintosh versions, C-Kermit does
-   not emulate any kind of terminal. Rather, it acts as a
-   "semitransparent pipe", passing the characters you type during a
-   CONNECT session to the remote host, and sending the characters
-   received from the remote host to your screen. Whatever is controlling
-   your keyboard and screen provides the specific terminal emulation: a
-   real terminal, a PC running a terminal emulator, etc, or (in the case
-   of a self-contained workstation) your console driver, a terminal
-   window, xterm, etc.
-
-   Kermit is semitrantsparent rather than fully transparent in the
-   following ways:
-
-     * During a TELNET ("set host") session, C-Kermit itself executes the
-       TELNET protocol and performs TELNET negotiations. (But it does not
-       perform TN3270 protocol or any other type of 3270 terminal
-       emulation.)
-     * If you have changed your keyboard mapping using SET KEY, C-Kermit
-       replaces the characters you type with the characters or strings
-       they are mapped to.
-     * If you SET your TERMINAL CHARACTER-SET to anything but
-       TRANSPARENT, C-Kermit translates your keystrokes (after applying
-       any SET KEY definitions) before transmitting them, and translates
-       received characters before showing them on your screen.
-     * If your remote and/or local TERMINAL CHARACTER-SET is an ISO 646
-       7-bit national character set, such as German, French, Italian,
-       Swedish, etc, or Short KOI used for Cyrillic, C-Kermit's CONNECT
-       command automatically skips over ANSI escape sequences to avoid
-       translating their characters. Only ANSI/ISO standard
-       (VT100/200/300-like) 7-bit escape sequence formats are supported
-       for this purpose, no proprietary schemes like H-P, Televideo,
-       Tektronix, etc.
-     * If your version of C-Kermit includes SET TERMINAL APC command,
-       then C-Kermit's CONNECT command will handle APC escape sequences
-       if TERMINAL APC is not set to OFF (which is the default).
-
-   You can make C-Kermit fully transparent by starting it with the -0
-   (dash zero) command-line option.
-
-   If you are running C-Kermit under a console driver, or in a terminal
-   window, that emulates the VT100, and use C-Kermit to log in to a VMS
-   system, the console driver or terminal window (not Kermit) is supposed
-   to reply to the "what are you?" query (ESC Z) from the VAX. If it
-   doesn't, and you can't make it do so, then you can (a) live with the
-   "unknown terminal" problem; (b) tell VMS to SET TERMINAL/DEVICE=VT100;
-   (c) program a key using SET KEY to send the appropriate sequence and
-   then punch the key at the right time; or (d) use the VMSLOGIN macro
-   that is defined in CKERMIT.INI to do this for you automatically.
-
-   SET SESSION-LOG { TEXT, BINARY }, which is effective in UNIX and
-   AOS/VS but not other C-Kermit versions, removes CR, DEL, NUL, XON, and
-   XOFF characters (Using C-Kermit neglects to mention that XON and XOFF
-   are removed). The TEXT-mode setting is ineffective during SCRIPT
-   command execution, as well as on X.25 connections.
-    ________________________________________________________________________
-
-  9. KEY MAPPING
-
-   [ [64]Top ] [ [65]Contents ] [ [66]Next ] [ [67]Previous ]
-
-   Except in the terminal-emulating versions, C-Kermit's key mapping
-   facilities are limited to normal "ASCII" keys, and cannot be used with
-   function keys, arrow keys, arcane key combinations, etc. Since
-   C-Kermit runs on such a wide variety of hardware platforms (including,
-   for example, more than 360 different UNIX platforms), it is not
-   possible for C-Kermit to support every conceivable keyboard under
-   every release of every UNIX (or VMS, or ...) product on every
-   different kind of computer possibly under all manner of different
-   console drivers, even if it had the means to do so.
-
-   In technical terms, C-Kermit uses the read() function to read
-   keystrokes, and read() returns a single byte (value 0 through 255).
-   C-Kermit's SET KEY function applies to these single-byte codes.
-   "Extended function" keys, such as F-keys, arrow keys, etc, usually
-   return either a 2-byte "scan code" or else a character string (such as
-   an escape sequence like "<ESC> O p"). In both cases, C-Kermit has no
-   way to tell the difference between such multibyte key values, and the
-   corresponding series of single-byte key values. This could only be
-   done by accessing the keyboard at a much lower level in a highly
-   platform-dependent manner, probably requiring tens of thousands of
-   lines of code to support even a sampling of the most popular
-   workstation / OS combinations.
-
-   However, most workstation console drivers (terminal emulation windows,
-   etc) include their own key-mapping facility. For example in AIX, the
-   AIXterm program (in whose window you would run C-Kermit) allows
-   rebinding of the F1-F12 keys to arbitrary strings. The same is true of
-   Xterm and DECterm windows, etc. Consult the technical documentation
-   for your workstation or emulator. See sample Xterm (Xmodmap) mappings
-   in the [68]Unix C-Kermit Hints and Tips document.
-
-   The SET KEY command (except in Kermit 95) does not allow a key
-   definition to be (or contain) the NUL (\0) character.
-    ________________________________________________________________________
-
-  10. FILE TRANSFER
-
-   [ [69]Top ] [ [70]Contents ] [ [71]Next ] [ [72]Previous ]
-
-   C-Kermit 7.0 is the first release of C-Kermit to use fast (rather than
-   robust and therefore slow) protocol defaults: long packets, sliding
-   windows, control-character unprefixing, and streaming where possible.
-   This makes most transfers (partner willing) dramatically faster "out
-   of the box" but might break some combinations that worked before. If
-   transfers with C-Kermit 7.0 or later fail where transfers worked with
-   earlier C-Kermit versions, try the following (one at a time, in this
-   order):
-
-    1. SET PREFIXING ALL: Disables control-character unprefixing.
-    2. SET STREAMING OFF: Disables streaming.
-    3. CAUTIOUS: Selects medium but cautious protocol settings.
-    4. ROBUST: this command reverts to the most conservative protocol
-       settings.
-
-   Execution of multiple file transfers by C-Kermit from a command file
-   when in remote mode might exhibit long delays between each transfer.
-   To avoid this, just include the command "SET DELAY 0" in your command
-   file before any of the file-transfer commands.
-
-   File transfer failures can occur for all sorts of reasons, most of
-   them listed in Chapter 10 of [73]Using C-Kermit. The following
-   sections touch on some that aren't.
-
-   The [74]C-Kermit 7.0 Release Notes document SEND /COMMAND as taking an
-   argument, but it doesn't. Instead of SEND /COMMAND:{some command},
-   use:
-
-SEND /COMMAND [ other switches such as /AS-NAME: ] command [ arguments... ]
-
-  10.1. Laptops
-
-   Watch out for laptops and their assorted power-saver features; for
-   example, a built-in modem's "auto timeout delay" hanging up the
-   connection in the middle of a file transfer. Most modems, even if they
-   have this feature, do not have it enabled by default. But if you
-   experience otherwise inexplicable disconnections in the midst of your
-   Kermit sessions, check the modem manual for such things as "idle
-   timeout", "auto timeout", etc, and add the command to disable this
-   feature to Kermit's init string for this modem.
-
-  10.2. NFS
-
-   If uploading a large file to an NFS-mounted disk fails (or is
-   painfully slow), try uploading it to a local disk (e.g. /tmp on Unix)
-   and then copying to the NFS disk later.
-
-  10.3. Modems
-
-   If you are dialing out and find that downloads work but uploads don't,
-   try again with a lower serial-port speed. Case in point: dialing out
-   on a certain PC from Linux at 115200 bps using a USR Courier 56K
-   "V.Everything" external modem and RTS/CTS flow control. Downloads
-   worked flawlessly, uploads stopped dead after the first few packets
-   were sent. The modem lights showed constant retraining (ARQ light
-   blinks slowly), and the CTS light was off 95% of the time, allowing
-   nothing to get through. Reducing the serial port speed to 57600 bps
-   made the problems go away. Evidently the PC in question has a very
-   fast serial port, since dialing the same modem with a different PC at
-   115200 bps works without incident.
-
-  10.4. TCP/IP Connections
-
-   If you have trouble transferring files over a TCP/IP connection, tell
-   Kermit to SET PARITY SPACE and try again. If that doesn't work, also
-   try a shorter packet length or smaller window size (to compensate for
-   certain well-known broken Telnet servers), and/or SET RELIABLE OFF.
-
-  10.5. Multihop Connections
-
-   If you have a multihop connection, with the interior nodes in CONNECT
-   mode (Kermit, Telnet, Rlogin, or any other), you can expect (a) file
-   transfer to be slower, and (b) the connection to be less transparent
-   (to control characters, perhaps to the 8th bit) than a more direct
-   connection. C-Kermit 7.0 and later have a "-0" (dash-zero)
-   command-line option to make it 100% transparent in cases where it is
-   to be used in the middle.
-
-  10.6. Recovery
-
-   The recovery feature (RESEND command) that was added in version
-   5A(190) works only for binary-mode transfers. In order for this
-   feature to be useful at all, the default for SET FILE INCOMPLETE was
-   changed from DISCARD to KEEP. Otherwise an interrupted transfer would
-   leave no partial file behind unless you had remembered to change the
-   default. But now you have to pay closer attention to Kermit's messages
-   to know whether a transfer succeeded or failed -- previously, if it
-   failed, the file would not show up on the receiving end at all; in
-   5A(190) and later, you'll get a partial file which could easily be
-   mistaken for the complete file unless you change the default back to
-   DISCARD or read the screen messages, or keep a transaction log.
-
-  10.7. Filename Collisions
-
-   SET FILE COLLISION BACKUP is the default. This means:
-
-     * If you send the same file lots of times, there will be many backup
-       files. There is no automatic mechanism within Kermit to delete
-       them, no notion of a "version retention count", etc, but you can
-       use the PURGE command to clean them up.
-     * If a file arrives that has the same name as a directory, the file
-       transfer fails because Kermit will not rename a directory. Send
-       the file with another name, or use SET FILE COLLISION RENAME.
-     * If the directory lacks write permission, the file transfer fails
-       even if you have write access to the file that is being backed up;
-       in that case, switch to SET FILE COLLISION OVERWRITE or APPEND, or
-       send to a different directory.
-
-   SET FILE COLLISION UPDATE depends on the date/time stamp in the
-   attribute packet. However, this is recorded in local time, not
-   Universal Time (GMT), and there is no indication of time zone. The
-   time is expressed to the precision of 1 second, but some file systems
-   do not record with this precision -- for example, MS-DOS records the
-   file date/time only to the nearest 2 seconds. This might cause update
-   operations to send more files than necessary.
-
-   (This paragraph does NOT apply to UNIX, where, as of C-Kermit 7.0,
-   C-Kermit pipes incoming mail and print material directly the mail or
-   print program): When C-Kermit is receiving files from another Kermit
-   program that has been given the MAIL or REMOTE PRINT command, C-Kermit
-   follows the current filename collision action. This can be
-   disconcerting if the action was (for example) BACKUP, because the
-   existing file will be renamed, and the new file will be mailed (or
-   printed) and then deleted. Kermit cannot temporarily change to RENAME
-   because the file collision action occurs when the filename packet is
-   received, and the PRINT or MAIL disposition only comes later, in the
-   Attribute packet.
-
-   Watch out for SET FILE COLLISION RENAME, especially when used in
-   conjunction with recovery. Recall that this option (which is NOT the
-   default) renames the incoming file if a file already exists with the
-   same name (the default is to rename the previously existing file, and
-   store the incoming file with its own name). It is strongly recommended
-   that you do not use SET FILE COLLISION RENAME if you ever intend to
-   use the recovery feature:
-
-     * When the file is first received by C-Kermit, its name is changed
-       if another file already has the same name. When you RESEND the
-       same file after a failure, C-Kermit will probably try to append
-       the re-sent portion to the wrong file.
-     * Assuming that you get RESEND to work with FILE COLLISION RENAME,
-       C-Kermit, when receiving the remainder of the file during a RESEND
-       operation, will report back the wrong name. Nothing can be done
-       about this because the name is reported back before the receiving
-       Kermit program finds out that it is a recovery operation.
-
-   Also watch out for DISABLE DELETE, since this implicitly sets FILE
-   COLLISION to RENAME. And note tht DELETE is DISABLEd automatically any
-   time you Kermit is in local mode (i.e. it makes a connection). Also
-   note that for purposes of DISABLE and ENABLE, "set host *" connections
-   do not count as local mode even though, strictly speaking, they are.
-
-  10.8. DOS Pathnames
-
-   When referring to foreign MS-DOS, Windows, Atari ST, OS/2, or other
-   file specifications that contain backslash characters in a C-Kermit
-   command, you might have to double each backslash, for example:
-
-  C-Kermit>get c:\\directory\\foo.txt
-
-   This is because backslash is used in C-Kermit commands for introducing
-   special character codes, variables, functions, etc.
-
-  10.9. Cancellation
-
-   If attempting to cancel local-mode file reception at a very early
-   stage (i.e. before data packets are exchanged) with X or Z does not
-   work, use E or Ctrl-C instead, or wait until the first data packets
-   are sent.
-
-   If you cancel a transfer that is underway using X or Z, and a lot of
-   window slots are in use, it might take a while for the cancellation to
-   take effect, especially if you do this on the receiving end; that's
-   because a lot of packets might already be on their way to you. In that
-   case, just be patient and let Kermit "drain" them.
-
-   If C-Kermit is sending a file, remote-mode packet-mode breakout (three
-   consecutive Ctrl-C's by default) is not effective until after C-Kermit
-   sends its first packet. If C-Kermit is receiving a file or is in
-   server mode, it is effective right away. In the former case, the SET
-   DELAY value determines the earliest time at which you can break out of
-   packet mode.
-
-  10.10. Partner Peculiarities
-
-   When one or both partners is on an SCO operating system such as OSR5,
-   you might issue the command:
-
-mapchan -n
-
-   to disable character-set conversion by the terminal driver. Similarly
-   for AIX:
-
-setmaps -t NOMAP
-
-   When using C-Kermit to transfer files with the HP48SX calculator, you
-   must SET FLOW NONE. The HP48SX does not support flow control, and
-   evidently also becomes confused if you attempt to use it. You might
-   also need to use SET SEND PAUSE 100 (or other number). For greater
-   detail about transferring files the the HP-48, see:
-
-  [75]http://www.columbia.edu/kermit/hp48.html
-
-   Some communication programs have errors in their implementation of
-   Kermit attribute packets. If you get an error message from your
-   communication program like "Attribute error", tell C-Kermit to SET
-   ATTRIBUTES OFF. Better yet, switch to a real Kermit program.
-
-   Some communication software claims to implement Kermit sliding
-   windows, but does so incorrectly. If sliding window transfers fail,
-   set C-Kermit's window size to the smallest one that works, for
-   example, SET WINDOW 1.
-
-   For lots more detail about how to cope with defective Kermit partners,
-   see:
-
-     * [76]Coping with Faulty Kermit Implementations (C-Kermit 7.0 and
-       later).
-     * [77]Coping with Broken Kermit Partners (C-Kermit 8.0 and later).
-
-   The UNIX version of C-Kermit discards carriage returns when receiving
-   files in text mode. Thus, "bare" carriage returns (sometimes used to
-   achieve overstriking) are lost.
-    ________________________________________________________________________
-
-  11. SCRIPT PROGRAMMING
-
-   [ [78]Top ] [ [79]Contents ] [ [80]Previous ]
-
-  11.1. Comments Versus the SCRIPT Command
-
-   Remember that ";" and "#" introduce comments when (a) they are the
-   first character on the line, or (b) they are preceded by at least one
-   blank or tab within a line. Thus constructions like:
-
-  INPUT 5 ;
-  SCRIPT ~0 #--#--#
-
-   must be coded using backslash notation to keep the data from being
-   ignored:
-
-  INPUT 5 \59                   ; 59 is the decimal ASCII code for ";"
-  SCRIPT ~0 \35--#--#           ; 43 is the decimal ASCII code for "#"
-
-   or, more simply:
-
-  INPUT 5 \;                    ; Just quote the semicolon
-  SCRIPT ~0 \#--#--#            ; Just quote the "#"
-    ________________________________________________________________________
-
-  11.2. Alphabetic Case and the INPUT Command
-
-   INPUT and MINPUT caseless string comparisons do not work for non-ASCII
-   (international) characters. Workaround: SET INPUT CASE OBSERVE. Even
-   then, the "lexically less than" and "lexically greater than"
-   operations (IF LLT, IF LGT) probably won't work as expected. The same
-   is true for the case-conversion functions \Flower() and \Fupper().
-   C-Kermit does not know the collating sequence for different character
-   sets and languages. (On the other hand, it might work depending on
-   such items as how Kermit was linked, whether your operating supports
-   "locales", etc)
-    ________________________________________________________________________
-
-  11.3. NUL (0) Characters in C-Kermit Commands
-
-   You can't include a NUL character (\0) in C-Kermit command text
-   without terminating the character string in which it appears. For
-   example:
-
-  echo In these brackets [\0] is a NUL
-
-   will echo "In these brackets [". This applies to ECHO, INPUT, OUTPUT,
-   and all other commands (but you can represent NUL by "\N" in an OUTPUT
-   string). This is because C-language strings are terminated internally
-   by the NUL character, and it allows all of C-Kermit's string
-   comparison and manipulation functions to work in the normal "C" way.
-
-   To illustrate:
-
-  INPUT 5 \0
-
-   is equivalent to:
-
-  INPUT 5
-
-   and:
-
-  INPUT 5 ABC\0DEF
-
-   is equivalent to:
-
-  INPUT 5 ABC
-
-   INPUT operations discard and ignore NUL characters that arrive from
-   the communication device, meaning that they do not figure into
-   matching operations (e.g. A<NUL>B matches AB); they are not deposited
-   in the INPUT buffer (\v(input)); and they are not counted in
-   \v(incount), with two exceptions:
-
-    1. An arriving NUL character restarts the INPUT SILENCE timer.
-    2. An arriving NUL character terminates the INPUT command with the
-       SUCCESS condition if the INPUT command was given an empty search
-       string. In this case \v(incount) is set to 1.
-
-   Also, the \v(inchar) variable is null (completely empty) if the last
-   INPUT character was NUL. That is, there is no way to tell only by
-   looking at \v(inchar) the difference between a NUL that was INPUT and
-   no INPUT at all. If the INPUT command succeeded but \v(inchar) is
-   empty, then a NUL character was input. Also, \v(incount) will be set
-   to 1.
-
-   Here's a sample script fragment to read characters, possibly including
-   NUL, from the communication connection and write them to a file:
-
-  while true {
-      input 1                      ; read one byte
-      if fail break                ; timed out or connection closed
-      fwrite /char \%c \v(inchar)  ; record the byte
-  }
-
-   This works because when \v(inchar) is NUL, that's equivalent to FWRITE
-   /CHAR having no text argument at all, in which case it writes a NUL
-   character.
-
-   \v(incount) and \v(inchar) are NOT affected by the CLEAR command.
-    ________________________________________________________________________
-
-  11.4. \ffiles() and \fnextfile() Peculiarities
-
-   The following script program:
-
-  for \%i 1 \ffiles(oofa.*) 1 {
-      send \fnextfile()
-  }
-
-   did not work as expected in C-Kermit 6.0 and earlier but does work in
-   C-Kermit 7.0 and later.
-    ________________________________________________________________________
-
-  11.5. Commands That Have Only Local Effect
-
-   Certain settings are local to each command level, meaning that
-   subordinate command levels (macros or command files) can change them
-   without affecting their values at higher command levels. When a new
-   command level is invoked, the value is inherited from the previous
-   level. These settings are:
-
-  CASE
-  COUNT and \v(count)
-  INPUT CASE
-  INPUT TIMEOUT
-  MACRO ERROR
-  QUIET
-  TAKE ERROR
-
-   This arrangement allows CASE, TIMEOUT, and ERROR settings, which are
-   used to control automatic exit from a command file or macro upon
-   error, to be automatically restored when the command file or macro
-   exits.
-
-   The COUNT variable follows this rule too, which permits nested SET
-   COUNT / IF COUNT loops, as in this example in which the inner loop
-   counts down from the current COUNT value of the outer loop (try it):
-
-  DEFINE INNER WHILE COUNT { WRITE SCREEN {   Inner:}, SHOW COUNT }
-  SET COUNT 5
-  WHILE COUNT { WRITE SCREEN Outer:, SHOW COUNT, DO INNER }
-
-   Keep in mind that an inferior command level cannot manipulate the
-   COUNT value held by a higher level. For example:
-
-  DEFINE OOFA SHOW COUNT, IF COUNT GOTO LOOP
-  SET COUNT 5
-  :LOOP
-  OOFA
-  ECHO Done
-
-   results in an infinite loop; the COUNT value remains at 5 because it
-   is never decremented at the same level at which it was set.
-    ________________________________________________________________________
-
-  11.6. Literal Braces in Function Calls
-
-   Since braces are used in function calls to indicate grouping, there is
-   no way to pass literal braces to the function itself. Solution: Define
-   a variable containing the string that has braces. Example:
-
-  define \%a ab{cd
-  echo \fsubstring(\%a)
-  ab{cd
-
-   If the string is to start with a leading brace and end with a closing
-   brace, then double braces must appear around the string (which itself
-   is enclosed in braces):
-
-  define \%a {{{foo}}}
-  echo \fsubstring(\%a)
-  {foo}
-
-   This also works for any other kind of string:
-
-  define \%a {{ab{cd}}
-  echo \fsubstring(\%a)
-  ab{cd
-    ________________________________________________________________________
-
-  11.7. Defining Variables on the C-Kermit Command Line
-
-   To define variables on the C-Kermit command line, use the -C
-   command-line option with one or more DEFINE or ASSIGN commands. Note
-   that the C-Kermit command line must cope with the quoting rules of
-   your shell. Examples:
-
-  kermit -C "define \\%a foo, define phonenumber 7654321"
-
-   In this case we follow UNIX quoting rules by doubling the backslash.
-   Once C-Kermit starts, the \%a and \m(phonenumber) variables are
-   defined as indicated and can be used in the normal way.
-
-   In DOS or Windows or OS/2 the command would be:
-
-  kermit -C "define \%%a foo, define phonenumber 7654321"
-
-   Here we need to double the percent sign rather than the backslash
-   because of DOS shell quoting rules.
-    ________________________________________________________________________
-
-  11.8. Per-Character Echo Check with the OUTPUT Command
-
-   Sometimes the OUTPUT command must be used to send commands or data to
-   a device in "echoplex" mode, meaning that characters must be sent one
-   at a time, and the next character can not be sent until the echo from
-   the previous one has been received. For example, a certain PBX might
-   have this characteristic. Let's say a Kermit script is used to program
-   the PBX. If characters are sent too fast, they can be lost. It would
-   seem that the command:
-
-  SET OUTPUT PACING milliseconds
-
-   could be used to take care of this, but the pacing interval is
-   constant and must be set large enough to allow even the slowest echo
-   to finish. If the script is large (an actual example is 14,000 lines
-   long), this can cause it to take hours longer than it needs to.
-
-   Here is a macro you can use to OUTPUT a string in an Echoplex
-   environment:
-
-  define XOUTPUT {
-      local \%c \%i
-      set output pacing 0
-      for \%i 1 \flen(\%*) 1 {
-          asg \%c \fsubstr(\%*,\%i,1)
-          output \%c
-          input 2 \%c
-      }
-  }
-
-   C-Kermit 7.0 or later is required.
-
-   It sends one character at a time and then waits up to 2 seconds for
-   the character to be echoed back, but continues to the next character
-   as soon as the echo appears, so no time is wasted. You can add an IF
-   FAIL clause after the INPUT in case you want to do something special
-   about failure to detect an echo within the timeout period. Obviously
-   you can also change the 2-second limit, and adjust the script in any
-   other desired way.
-    ________________________________________________________________________
-
-  11.9. Scripted File Transfer
-
-   Sometimes a user complains that when she makes a connection by hand,
-   logs in, and transfers a file, there are no problems, but when she
-   scripts the the exact same sequence, the file transfer always fails
-   after a few packets. Here's a scenario where this can happen:
-
-    1. Upon logging in to the remote computer, it sends a "What Are You?"
-       escape sequence.
-    2. When you log in interactively, your terminal emulator sends the
-       response. This is invisible to you; you don't know it's happening.
-    3. When you script the login, and begin a file transfer immediately
-       upon logging in, the host still sends the "What Are You?"
-       sequence. Kermit's INPUT ECHO setting is ON by default, so the
-       escape sequence passes through to the terminal, and the terminal
-       sends its response. But by this time Kermit has already started
-       the file transfer.
-    4. By default, the local Kermit program examines the keyboard for
-       interruption characters between every packet. The "What Are You"
-       response is sitting in the keyboard buffer. Eventually Kermit will
-       read a character such as "c" that is a valid interruption
-       character, and the file transfer stops with "User cancelled".
-
-   The right way to handle this situation is to have your look for the
-   "What Are You?" sequence and send the response itself, as described in
-   Using C-Kermit, pp.429-431. Or you can work around it by telling the
-   local Kermit to "set input echo off" and/or "set transfer interruption
-   off".
-    ________________________________________________________________________
-
-  11.10. Other...
-
-   Escape sequences (or any strings that contain control characters)
-   can't be used as labels, GOTO targets, or SWITCH cases.
-
-   [ [81]Top ] [ [82]Contents ] [ [83]C-Kermit Home ] [ [84]C-Kermit 8.0
-   Overview ] [ [85]Kermit Home ]
-     _________________________________________________________________
-
-   C-Kermit 8.0 Unix Hints and Tips / [86]The Kermit Project /
-   [87]Columbia University / [88]kermit@columbia.edu / 10 April 2004
-
-References
-
-   1. http://www.columbia.edu/kermit/
-   2. http://www.columbia.edu/
-   3. http://www.columbia.edu/kermit/ckcbwr.html
-   4. http://www.columbia.edu/kermit/ckubwr.html
-   5. http://www.columbia.edu/kermit/k95.html
-   6. http://www.columbia.edu/kermit/ckermit.html
-   7. http://www.columbia.edu/kermit/ckututor.html
-   8. http://www.columbia.edu/kermit/ckcbwr.html#x0
-   9. http://www.columbia.edu/kermit/ckcbwr.html#x1
-  10. http://www.columbia.edu/kermit/ckcbwr.html#x2
-  11. http://www.columbia.edu/kermit/ckcbwr.html#x3
-  12. http://www.columbia.edu/kermit/ckcbwr.html#x4
-  13. http://www.columbia.edu/kermit/ckcbwr.html#x5
-  14. http://www.columbia.edu/kermit/ckcbwr.html#x6
-  15. http://www.columbia.edu/kermit/ckcbwr.html#x7
-  16. http://www.columbia.edu/kermit/ckcbwr.html#x8
-  17. http://www.columbia.edu/kermit/ckcbwr.html#x9
-  18. http://www.columbia.edu/kermit/ckcbwr.html#x10
-  19. http://www.columbia.edu/kermit/ckcbwr.html#x11
-  20. http://www.columbia.edu/kermit/ckcbwr.html#top
-  21. http://www.columbia.edu/kermit/ckcbwr.html#contents
-  22. http://www.columbia.edu/kermit/ckcbwr.html#x2
-  23. http://www.columbia.edu/kermit/ckcbwr.html#top
-  24. http://www.columbia.edu/kermit/ckcbwr.html#contents
-  25. http://www.columbia.edu/kermit/ckcbwr.html#x2
-  26. http://www.columbia.edu/kermit/ck60manual.html
-  27. http://www.columbia.edu/kermit/ckermit2.html
-  28. http://www.columbia.edu/kermit/ck60manual.html
-  29. http://www.columbia.edu/kermit/ckermit80.html#x5
-  30. http://www.columbia.edu/kermit/ckermit80.html
-  31. http://www.columbia.edu/kermit/ckermit80.html#x2.2
-  32. http://www.columbia.edu/kermit/ckcbwr.html#top
-  33. http://www.columbia.edu/kermit/ckcbwr.html#contents
-  34. http://www.columbia.edu/kermit/ckcbwr.html#x3
-  35. http://www.columbia.edu/kermit/ckcbwr.html#x1
-  36. http://www.columbia.edu/kermit/ckcbwr.html#top
-  37. http://www.columbia.edu/kermit/ckcbwr.html#contents
-  38. http://www.columbia.edu/kermit/ckcbwr.html#x4
-  39. http://www.columbia.edu/kermit/ckcbwr.html#x2
-  40. http://www.columbia.edu/kermit/ckcbwr.html#top
-  41. http://www.columbia.edu/kermit/ckcbwr.html#contents
-  42. http://www.columbia.edu/kermit/ckcbwr.html#x5
-  43. http://www.columbia.edu/kermit/ckcbwr.html#x3
-  44. ftp://ftp.isi.edu/in-notes/rfc1122.txt
-  45. http://www.columbia.edu/kermit/ckcbwr.html#top
-  46. http://www.columbia.edu/kermit/ckcbwr.html#contents
-  47. http://www.columbia.edu/kermit/ckcbwr.html#x6
-  48. http://www.columbia.edu/kermit/ckcbwr.html#x4
-  49. http://www.columbia.edu/kermit/ckcbwr.html#top
-  50. http://www.columbia.edu/kermit/ckcbwr.html#contents
-  51. http://www.columbia.edu/kermit/ckcbwr.html#x7
-  52. http://www.columbia.edu/kermit/ckcbwr.html#x5
-  53. http://www.columbia.edu/kermit/ck60manual.html
-  54. http://www.columbia.edu/kermit/ckcbwr.html#x10
-  55. http://www.columbia.edu/kermit/ckcbwr.html#top
-  56. http://www.columbia.edu/kermit/ckcbwr.html#contents
-  57. http://www.columbia.edu/kermit/ckcbwr.html#x8
-  58. http://www.columbia.edu/kermit/ckcbwr.html#x6
-  59. ftp://ftp.isi.edu/in-notes/rfc2217.txt
-  60. http://www.columbia.edu/kermit/ckcbwr.html#top
-  61. http://www.columbia.edu/kermit/ckcbwr.html#contents
-  62. http://www.columbia.edu/kermit/ckcbwr.html#x9
-  63. http://www.columbia.edu/kermit/ckcbwr.html#x7
-  64. http://www.columbia.edu/kermit/ckcbwr.html#top
-  65. http://www.columbia.edu/kermit/ckcbwr.html#contents
-  66. http://www.columbia.edu/kermit/ckcbwr.html#x10
-  67. http://www.columbia.edu/kermit/ckcbwr.html#x8
-  68. http://www.columbia.edu/kermit/ckubwr.html
-  69. http://www.columbia.edu/kermit/ckcbwr.html#top
-  70. http://www.columbia.edu/kermit/ckcbwr.html#contents
-  71. http://www.columbia.edu/kermit/ckcbwr.html#x11
-  72. http://www.columbia.edu/kermit/ckcbwr.html#x9
-  73. http://www.columbia.edu/kermit/ck60manual.html
-  74. http://www.columbia.edu/kermit/ckermi70.htm
-  75. http://www.columbia.edu/kermit/hp48.html
-  76. http://www.columbia.edu/kermit/ckermit70.html#x4.22
-  77. http://www.columbia.edu/kermit/ckermit80.html#x15
-  78. http://www.columbia.edu/kermit/ckcbwr.html#top
-  79. http://www.columbia.edu/kermit/ckcbwr.html#contents
-  80. http://www.columbia.edu/kermit/ckcbwr.html#x10
-  81. http://www.columbia.edu/kermit/ckcbwr.html#top
-  82. http://www.columbia.edu/kermit/ckcbwr.html#contents
-  83. http://www.columbia.edu/kermit/ckermit.html
-  84. http://www.columbia.edu/kermit/ck80.html
-  85. http://www.columbia.edu/kermit/index.html
-  86. http://www.columbia.edu/kermit/index.html
-  87. http://www.columbia.edu/
-  88. mailto:kermit@columbia.edu
diff --git a/ckccfg.txt b/ckccfg.txt
deleted file mode 100644 (file)
index 5870974..0000000
+++ /dev/null
@@ -1,1766 +0,0 @@
-
-                        C-Kermit Configuration Options
-
-     Frank da Cruz
-     [1]The Kermit Project
-     [2]Columbia University
-
-   As of: C-Kermit 8.0.211, 10 April 2004
-   This page last updated: Sun Apr 11 16:45:55 2004 (New York USA Time)
-
-     IF YOU ARE READING A PLAIN-TEXT version of this document, note that
-     this file is a plain-text dump of a Web page. You can visit the
-     original (and possibly more up-to-date) Web page here:
-
-  [3]http://www.columbia.edu/kermit/ckccfg.html
-
-   [ [4]C-Kermit Home ] [ [5]Kermit Home ]
-    ________________________________________________________________________
-
-  CONTENTS
-
-  1. [6]FILE TRANSFER
-  2. [7]SERIAL COMMUNICATION SPEEDS
-  3. [8]FULLSCREEN FILE TRANSFER DISPLAY
-  4. [9]CHARACTER SETS
-  5. [10]APC EXECUTION
-  6. [11]PROGRAM SIZE
-  7. [12]MODEM DIALING
-  8. [13]NETWORK SUPPORT
-  9. [14]EXCEPTION HANDLING
- 10. [15]SECURITY FEATURES
- 11. [16]ENABLING SELECT()
- 12. [17]I/O REDIRECTION
- 13. [18]FLOATING-POINT NUMBERS, TIMERS, AND ARITHMETIC
- 14. [19]SPECIAL CONFIGURATIONS
-  I. [20]SUMMARY OF COMPILE-TIME OPTIONS
-    ________________________________________________________________________
-
-  OVERVIEW
-
-   This document describes configuration options for C-Kermit (5A and
-   later). The major topics covered include program size (and how to
-   reduce it), how to include or exclude particular features, notes on
-   serial-port, modem, and network support, and a list of C-Kermit's
-   compile-time options.
-
-   For details about your particular operating system, also see the
-   system-specific installation instructions file, such as the
-   [21]C-Kermit Installation Instructions for Unix.
-
-   [ [22]C-Kermit Home ] [ [23]Kermit Home ]
-    ________________________________________________________________________
-
-  1. FILE TRANSFER
-
-   [ [24]Top ] [ [25]Contents ] [ [26]Next ] [ [27]Previous ]
-
-   Prior to version 7.0, C-Kermit was always built with the most
-   conservative Kermit file-transfer protocol defaults on every platform:
-   no control-character prefixing, 94-byte packets, and a window size of
-   1.
-
-   Starting in version 7.0, fast settings are the default. To override
-   these at compile time, include:
-
-  -DNOFAST
-
-   in the C compiler CFLAGS. Even with the fast defaults, C-Kermit
-   automatically drops down to whatever window and packet sizes requested
-   by the other Kermit, if these are smaller, when sending files (except
-   for control-character unprefixing, which is not negotiated, and which
-   is now set to CAUTIOUS rather than NONE at startup). C-Kermit's
-   settings prevail when it is receiving.
-
-   [ [28]C-Kermit Home ] [ [29]Kermit Home ]
-    ________________________________________________________________________
-
-  2. SERIAL COMMUNICATION SPEEDS
-
-   [ [30]Top ] [ [31]Contents ] [ [32]Next ] [ [33]Previous ]
-
-   As of 6 September 1997, a new simplified mechanism for obtaining the
-   list of legal serial interface speeds is in place:
-
-     * If the symbol TTSPDLIST is defined, the system-dependent routine
-       ttspdlist() is called at program initialization to obtain the
-       list.
-     * This symbol should be defined only for C-Kermit implementations
-       that have implemented the ttspdlist() function, typically in the
-       ck?tio.c module. See [34]ckutio.c for an example.
-     * TTSPDLIST is automatically defined in [35]ckcdeb.h for UNIX. Add
-       the appropriate #ifdefs for other platforms when the corresponding
-       ttspdlist() functions are filled in.
-     * If TTSPDLIST is (or normally would be) defined, the old code
-       (described below) can still be selected by defining NOTTSPDLIST.
-
-   The ttspdlist() function can obtain the speeds in any way that works.
-   For example, based simply on #ifdef Bnnnn..#endif (in UNIX). Although
-   it might be better to actually check each speed against the currently
-   selected hardware interface before allowing it in the array, there is
-   usually no passive and/or reliable and safe way to do this, and so
-   it's better to let some speeds into the array that might not work,
-   than it is to erroneously exclude others. Speeds that don't work are
-   caught when the SET SPEED command is actually given.
-
-   Note that this scheme does not necessarily rule out split speed
-   operation, but effectively it does in C-Kermit as presently
-   constituted since there are no commands to set input and output speed
-   separately (except the special case "set speed 75/1200").
-
-   Note that some platforms, notably AIX 4.2 and 4.3, implement high
-   serial speeds transparently to the application, e.g. by mapping 50 bps
-   to 57600 bps, and so on.
-
-   That's the whole deal. When TTSPDLIST is not defined, the following
-   applies:
-
-   Speeds are defined in two places: the SET SPEED keyword list in the
-   command parser (as of this writing, in the [36]ckuus3.c source file),
-   and in the system- dependent communications i/o module, ck?tio.c,
-   functions ttsspd() (set speed) and ttgspd() (get speed). The following
-   speeds are assumed to be available in all versions:
-
-  0, 110, 300, 600, 1200, 2400, 4800, 9600
-
-   If one or more of these speeds is not supported by your system, you'll
-   need to change the source code (this has never happened so far). Other
-   speeds that are not common to all systems have Kermit-specific
-   symbols:
-
-               Symbol       Symbol
-  Speed (bps)  to enable    to disable
-       50       BPS_50       NOB_50
-       75       BPS_75       NOB_75
-       75/1200  BPS_7512     NOB_7512
-      134.5     BPS_134      NOB_134
-      150       BPS_150      NOB_150
-      200       BPS_200      NOB_200
-     1800       BPS_1800     NOB_1800
-     3600       BPS_3600     NOB_3600
-     7200       BPS_7200     NOB_7200
-    14400       BPS_14K      NOB_14K
-    19200       BPS_19K      NOB_19K
-    28800       BPS_28K      NOB_28K
-    38400       BPS_38K      NOB_38K
-    57600       BPS_57K      NOB_57K
-    76800       BPS_76K      NOB_76K
-   115200       BPS_115K     NOB_155K
-   230400       BPS_230K     NOB_230K
-   460800       BPS_460K     NOB_460K
-   921600       BPS_921K     NOB_921K
-
-   The [37]ckcdeb.h header file contains default speed configurations for
-   the many systems that C-Kermit supports. You can override these
-   defaults by (a) editing ckcdeb.h, or (b) defining the appropriate
-   enabling and/or disabling symbols on the CC command line, for example:
-
-  -DBPS_14400 -DNOB_115200
-
-   or the "make" command line, e.g.:
-
-  make blah "KFLAGS=-DBPS_14400 -DNOB_115200"
-
-   Note: some speeds have no symbols defined for them, because they have
-   never been needed: 12.5bps, 45.5bps, 20000bps, etc. These can easily
-   be added if required (but they will work only if the OS supports
-   them).
-
-   IMPORTANT: Adding one of these flags at compile time does not
-   necessarily mean that you will be able to use that speed. A particular
-   speed is usable only if your underlying operating system supports it.
-   In particular, it needs to be defined in the appropriate system header
-   file (e.g. in UNIX, cd to /usr/include and grep for B9600 in *.h and
-   sys/*.h to find the header file that contains the definitions for the
-   supported speeds), and supported by the serial device driver, and of
-   course by the physical device itself.
-
-   ALSO IMPORTANT: The list of available speeds is independent of how
-   they are set. The many UNIXes, for example, offer a wide variety of
-   APIs that are BSD-based, SYSV-based, POSIX-based, and purely made up.
-   See the ttsspd(), ttgspd(), and ttspdlist() routines in [38]ckutio.c
-   for illustrations.
-
-   The latest entries in this horserace are the tcgetspeed() and
-   ttsetspeed() routines found in UnixWare 7. Unlike other methods, they
-   accept the entire range of integers (longs really) as speed values,
-   rather than certain codes, and return an error if the number is not,
-   in fact, a legal speed for the device/driver in question. In this
-   case, there is no way to build a list of legal speeds at compile time,
-   since no Bnnnn symbols are defined (except for "depracated, legacy"
-   interfaces like ioctl()) and so the legal speed list must be
-   enumerated in the code -- see ttspdlist() in [39]ckutio.c.
-
-   [ [40]C-Kermit Home ] [ [41]Kermit Home ]
-    ________________________________________________________________________
-
-  3. FULLSCREEN FILE TRANSFER DISPLAY
-
-   [ [42]Top ] [ [43]Contents ] [ [44]Next ] [ [45]Previous ]
-
-   New to edit 180 is support for an MS-DOS-Kermit-like local-mode full
-   screen file transfer display, accomplished using the curses library,
-   or something equivalent (for example, the Screen Manager on DEC VMS).
-   To enable this feature, include the following in your CFLAGS:
-
-  -DCK_CURSES
-
-   and then change your build procedure (if necessary) to include the
-   necessary libraries. For example, in Unix these are usually "curses"
-   or "ncurses" (and more recenlty, "ncursesw" and "slang"), perhaps also
-   "termcap", "termlib", or "tinfo":
-
-  "LIBS= -lcurses -ltermcap"
-  "LIBS= -lcurses -ltermlib"
-  "LIBS= -lncurses"
-  "LIBS= -ltermlib"
-  "LIBS= -ltinfo"
-
-   "man curses" for further information, and search through the Unix
-   [46]makefile for "CK_CURSES" to see many examples, and also see the
-   relevant sections of the [47]Unix C-Kermit Installation Instructions,
-   particularly Sections [48]4 and [49]9.2.
-
-   There might still be a complication. Some implementations of curses
-   reserve the right to alter the buffering on the output file without
-   restoring it afterwards, which can leave Kermit's command processing
-   in a mess when the prompt comes back after a fullscreen file transfer
-   display. The typical symptom is that characters you type at the prompt
-   after a local-mode file transfer (i.e. after seeing the curses
-   file-transfer display) do not echo until you press the Return (Enter)
-   key. If this happens to you, try adding
-
-  -DCK_NEWTERM
-
-   to your makefile target (see comments in screenc() in [50]ckuusx.c for
-   an explanation).
-
-   If that doesn't fix the problem, then use a bigger hammer and replace
-   -DCK_NEWTERM with:
-
-  -DNONOSETBUF
-
-   which tells Kermit to force stdout to be unbuffered so CBREAK mode can
-   work.
-
-   In SCO Xenix and SCO UNIX, there are two separate curses libraries,
-   one based on termcap and the other based on terminfo. The default
-   library, usually terminfo, is established when the development system
-   is installed. To manually select terminfo (at compile time):
-
-  compile -DM_TERMINFO and link -ltinfo
-
-   and to manually select termcap:
-
-  compile -DM_TERMCAP and link -ltcap -ltermlib
-
-   <curses.h> looks at M_TERMINFO and M_TERMCAP to decide which header
-   files to use. /usr/lib/libcurses.a is a link to either libtinfo.a or
-   libtcap.a. The C-Kermit compilation options must agree with the
-   version of the curses library that is actually installed.
-
-   NOTE: If you are doing an ANSI-C compilation and you get compile time
-   warnings like the following:
-
-  Warning: function not declared in ckuusx.c: wmove, printw, wclrtoeol,
-  wclear, wrefresh, endwin, etc...
-
-   it means that your <curses.h> file does not contain prototypes for
-   these functions. The warnings should be harmless.
-
-   New to edit 190 is the ability to refresh a messed-up full-screen
-   display, e.g. after receiving a broadcast message. This depends on the
-   curses package including the wrefresh() and clearok() functions and
-   the curscr variable. If your version has these, or has code to
-   simulate them, then add:
-
-  -DCK_WREFRESH
-
-   The curses and termcap libraries add considerable size to the program
-   image (e.g. about 20K on a SUN-4, 40K on a 386). On some small
-   systems, such as the AT&T 6300 PLUS, curses can push Kermit over the
-   edge... even though it compiles, loads, and runs correctly, its
-   increased size apparently makes it swap constantly, slowing it down to
-   a crawl, even when the curses display is not in use. Some new makefile
-   targets have been added to take care of this (e.g. sys3upcshcc), but
-   similar tricks might be necessary in other cases too.
-
-   On the curses file-transfer display, just below the "thermometer", is
-   a running display of the transfer rate, as a flat quotient of file
-   characters per elapsed seconds so far. You can change this to an
-   average that gives greater weight to recent history (0.25 *
-   instantaneous cps + 0.75 * historical cps) by adding -DCPS_WEIGHTED to
-   your CFLAGS (sorry folks, this one is not worth a SET command). You
-   can choose a second type of weighted average in which the weighting
-   smooths out progressively as the transfer progresses by adding
-   -DCPS_VINCE to -DCPS_WEIGHTED.
-
-   An alternative to curses is also available at compile time, but should
-   be selected if your version of Kermit is to be run in local mode only
-   in an ANSI terminal environment, for example on a desktop workstation
-   that has an ANSI console driver. To select this option in place of
-   curses, define the symbol MYCURSES:
-
-  -DMYCURSES
-
-   instead of CK_CURSES. The MYCURSES option uses built-in ANSI (VT100)
-   escape sequences, and depends upon your terminal or console driver to
-   interpret them correctly.
-
-   In some C-Kermit builds, we replace printf() via #define printf...
-   However, this can cause conflicts with the [n]curses header files.
-   Various hacks are required to get around this -- see [51]ckutio.c,
-   [52]ckufio.c, [53]ckuusx.c, [54]ckucmd.c, etc.
-
-   [ [55]C-Kermit Home ] [ [56]Kermit Home ]
-    ________________________________________________________________________
-
-  4. CHARACTER SETS
-
-   [ [57]Top ] [ [58]Contents ] [ [59]Next ] [ [60]Previous ]
-
-   Since version 5A, C-Kermit has included support for conversion of
-   character sets for Western European languages (i.e. languages that
-   originated in Western Europe, but are now also spoken in the Western
-   Hemisphere and other parts of the world), via ISO 8859-1 Latin
-   Alphabet 1, for Eastern European languages (ISO Latin-2), Hebrew (and
-   Yiddish), Greek, and Cyrillic-alphabet languages (ISO Latin/Cyrillic).
-   Many file (local) character sets are supported: ISO 646 7-bit national
-   sets, IBM code pages, Apple, DEC, DG, NeXT, etc.
-
-   To build Kermit with no character-set translation at all, include
-   -DNOCSETS in the CFLAGS. To build with no Latin-2, add -DNOLATIN2. To
-   build with no Cyrillic, add -DNOCYRIL. To omit Hebrew, add -DNOHEBREW.
-   If -DNOCSETS is *not* included, you'll always get LATIN1. To build
-   with no KANJI include -DNOKANJI. There is presently no way to include
-   Latin-2, Cyrillic, Hebrew, or Kanji without also including Latin-1.
-
-   [61]Unicode support was added in C-Kermit 7.0, and it adds a fair
-   amount of tables and code (and this is only a "Level 1" implementation
-   -- a higher level would also require building in the entire Unicode
-   database). On a PC with RH 5.2 Linux, building C-Kermit 7.0, we get
-   the following sizes:
-
-  NOCSETS NOUNICODE NOKANJI   Before    After                  
-   [   ]    [   ]    [   ]    1329014   (Full)
-   [   ]    [   ]    [ X ]    1325686   (Unicode but no Kanji)
-   [   ]    [ X ]    [   ]    1158837   (All charsets except Unicode)
-   [ X ]    [ x ]    [ x ]    1090845   (NOCSETS implies the other two)
-
-   Note, by the way, that NOKANJI without NOUNICODE only removes the
-   non-Unicode Kanji sets (Shift-JIS, EUC-JP, JIS-7, etc). Kanji is still
-   representable in UCS-2 and UTF-8.
-
-   [ [62]C-Kermit Home ] [ [63]Kermit Home ]
-    ________________________________________________________________________
-
-  5. APC EXECUTION
-
-   [ [64]Top ] [ [65]Contents ] [ [66]Next ] [ [67]Previous ]
-
-   The Kermit CONNECT and INPUT commands are coded to execute Application
-   Program Command escape sequences from the host:
-
-  <ESC>_<text><ESC>\
-
-   where <text> is a C-Kermit command, or a list of C-Kermit commands
-   separated by commas, up to about 1K in length.
-
-   To date, this feature has been included in the OS/2, Windows, VMS,
-   OS-9, and Unix versions, for which the symbol:
-
-  CK_APC
-
-   is defined automatically in [68]ckuusr.h. For OS/2, APC is enabled at
-   runtime by default, for UNIX it is disabled. It is controlled by the
-   SET TERMINAL APC command. Configuring APC capability into a version
-   that gets it by default (because CK_APC is defined in [69]ckuusr.h)
-   can be overridden by including:
-
-  -DNOAPC
-
-   on the CC command line.
-
-   C-Kermit's autodownload feature depends on the APC feature, so
-   deconfiguring APC also disables autodownload (it doesn't use APC
-   escape sequences, but uses the APC switching mechanism internally).
-
-   [ [70]C-Kermit Home ] [ [71]Kermit Home ]
-    ________________________________________________________________________
-
-  6. PROGRAM SIZE
-
-   [ [72]Top ] [ [73]Contents ] [ [74]Next ] [ [75]Previous ]
-
-   SECTION CONTENTS
-
-  6.1. [76]Feature Selection
-  6.2. [77]Changing Buffer Sizes
-  6.3. [78]Other Size-Related Items
-  6.4. [79]Space/Time Tradeoffs
-
-   (Also see [80]Section 4)
-
-   Each release of C-Kermit is larger than the last. On some computers
-   (usually old ones) the size of the program prevents it from being
-   successfully linked and loaded. On some others (also usually old
-   ones), it occupies so much memory that it is constantly swapping or
-   paging. In such cases, you can reduce C-Kermit's size in various ways,
-   outlined in this section. The following options can cut down on the
-   program's size at compile time by removing features or changing the
-   size of storage areas.
-
-   If you are reading this section because all you want is a small, fast,
-   quick-to-load Kermit file-transfer application for the remote end of
-   your connection, and the remote end is Unix based, take a look at
-   G-Kermit:
-
-  [81]http://www.columbia.edu/kermit/gkermit.html
-
-  6.1. Feature Selection
-
-   Features can be added or removed by defining symbols on the CC (C
-   compiler) command line. "-D" is the normal CC directive to define a
-   symbol so, for example, "-DNODEBUG" defines the symbol NODEBUG. Some C
-   compilers might use different syntax, e.g. "-d NODEBUG" or
-   "/DEFINE=NODEBUG". For C compilers that do not accept command-line
-   definitions, you can put the corresponding #define statements in the
-   file ckcsym.h, for example:
-
-  #define NODEBUG
-
-   The following table shows the savings achieved when building C-Kermit
-   8.0 (Beta.04) with selected feature-deselection switches on an
-   Intel-based PC with Red Hat Linux 7.0 and gcc 2.96. The sizes are for
-   non-security builds. The fully configured non-security build is
-   2127408 bytes.
-
-  Option      Size    Savings Effect
-  NOICP        545330   74.4% No Interactive Command Parser (command-line only)
-  NOLOCAL     1539994   27.6% No making connections.
-  NOXFER      1551108   27.1% No file transfer.
-  IKSDONLY    1566608   26.4% Internet Kermit Server only.
-  NOCSETS     1750097   17.7% No character-set conversion.
-  NOSPL       1800293   15.4% No Script Programming Language.
-  NONET       1808575   15.0% No making network connections.
-  NOUNICODE   1834426   13.8% No Unicode character-set conversion.
-  NOHELP      1837877   13.6% No built-in help text.
-  NODEBUG     1891669   11.1% No debug log.
-  NOFRILLS    1918966    9.8% No "frills".
-  NOFTP       1972496    7.3% No FTP client.
-  NODIAL      1984488    6.7% No automatic modem dialing.
-  NOPUSH      2070184    2.7% No shell access, running external programs, etc.
-  NOIKSD      2074129    2.5% No Internet Kermit Server capability.
-  NOHTTP      2082610    2.1% No HTTP client.
-  NOFLOAT     2091332    1.7% No floating-point arithmetic.
-  NOCHANNELIO 2095978    1.5% No FOPEN/FREAD/FWRITE/FCLOSE, etc.
-  MINIDIAL    2098035    1.4% No built-in support for many kinds of modems.
-  NOSERVER    2098987    1.3% No server mode.
-  NOSEXP      2105898    1.0% No S-Expressions.
-  NOPTY       2117743    0.5% No pseudoterminal support.
-  NORLOGIN    2121089    0.3% No RLOGIN connections.
-  NOOLDMODEMS 2124038    0.2% No built-in support for old kinds of modems.
-  NOSSH       2125696    0.1% No SSH command.
-
-   And here are a few combinations
-
-   Options Size Savings Effect
-   NODEBUG NOICP NOCSETS NOLOCAL 281641 86.7% No debug log, parser,
-   character sets, or making connections.
-   NOICP NOCSETS NOLOCAL 376468 82.3% No parser, character sets, or
-   making connections.
-   NOICP NOCSETS NONET 427510 79.9% No parser, character sets, or network
-   connections.
-   NOSPL NOCSETS 1423784 33.1% No script language, or character sets.
-
-   -DNOFRILLS removes various command synonyms; the following top-level
-   commands: CLEAR, DELETE, DISABLE, ENABLE, GETOK, MAIL, RENAME, TYPE,
-   WHO; and the following REMOTE commands: KERMIT, LOGIN, LOGOUT, PRINT,
-   TYPE, WHO.
-
-  6.2. Changing Buffer Sizes
-
-   Most modern computers have so much memory that (a) there is no need to
-   scrimp and save, and (b) C-Kermit, even when fully configured, is
-   relatively small by today's standards.
-
-   Two major factors affect Kermit's size: feature selection and buffer
-   sizes. Buffer sizes affect such things as the maximum length for a
-   Kermit packet, the maximum length for a command, for a macro, for the
-   name of a macro, etc. Big buffer sizes are used when the following
-   symbol is defined:
-
-  BIGBUFOK
-
-   as it is by default for most modern platforms (Linux, AIX 4 and 5,
-   HP-UX 10 and 11, Solaris, etc) in [82]ckuusr.h. If your build does not
-   get big buffers automatically (SHOW FEATURES tells you), you can
-   include them by rebuilding with BIGBUFOK defined; e.g. in Unix:
-
-  make xxxx KFLAGS=-DBIGBUFOK
-
-   where xxxx is the makefile target. On the other hand, if you want to
-   build without big buffers when they normally would be selected, use:
-
-  make xxxx KFLAGS=-DNOBIGBUF
-
-   There are options to control Kermit's packet buffer allocations. The
-   following symbols are defined in [83]ckcker.h in such a way that you
-   can override them by redefining them in CFLAGS:
-
-  -DMAXSP=xxxx - Maximum send-packet length.
-  -DMAXRP=xxxx - Maximum receive-packet length.
-  -DSBSIZ=xxxx - Total allocation for send-packet buffers.
-  -DRBSIZ=xxxx - Total allocation for receive-packet buffers.
-
-   The defaults depend on the platform.
-
-   Using dynamic allocation (-DDYNAMIC) reduces storage requirements for
-   the executable program on disk, and allows more and bigger packets at
-   runtime. This has proven safe over the years, and now most builds
-   (e.g. all Unix, VMS, Windows, and OS/2 ones) use dynamic memory
-   allocation by default. If it causes trouble, however, then omit the
-   -DDYNAMIC option from CFLAGS, or add -DNODYNAMIC.
-
-  6.3. Other Size-Related Items
-
-   To make Kermit compile and load successfully, you might have to change
-   your build procedure to:
-
-    a. Request a larger ("large" or "huge") compilation / code-generation
-       model. This is needed for 16-bit PC-based UNIX versions (most or
-       all of which fail to build C-Kermit 7.0 and later anyway). This is
-       typically done with a -M and/or -F switch (see your cc manual or
-       man page for details).
-    b. Some development systems support overlays. If the program is too
-       big to be built as is, check your loader manual ("man ld") to see
-       if an overlay feature is available. See the 2.10/2.11 BSD example
-       in the UNIX makefile. (Actually, as of version 7.0, C-Kermit is
-       too big to build, period, even with overlays, on 2.xx BSD).
-    c. Similarly, some small and/or segment-based architectures support
-       "code mapping", which is similar to overlays (PDP11-based VENIX
-       1.0, circa 1984, was an example). See the linker documentation on
-       the affected platform.
-
-   It is also possible to reduce the size of the executable program file
-   in several other ways:
-
-    a. Include the -O (optimize) compiler switch if it isn't already
-       included in your "make" entry (and if it works!). If your compiler
-       supports higher levels of optimization (e.g. -O2 or higher number,
-       -Onolimit (HP-UX), etc), try them; the greater the level of
-       optimization, the longer the compilation and more likely the
-       compiler will run out of memory. The the latter eventuality, some
-       compilers also provide command-line options to allocate more
-       memory for the optimizer, like "-Olimit number" in Ultrix.
-    b. If your platofrm supports shared libraries, change the make entry
-       to take advantage of this feature. The way to do this is, of
-       course, platform dependent; see the NeXT makefile target for an
-       example. some platforms (like Solaris) do it automatically and
-       give you no choice. But watch out: executables linked with shared
-       libraries are less portable than statically linked executables.
-    c. Strip the program image after building ("man strip" for further
-       info), or add -s to the LNKFLAGS (UNIX only). This strips the
-       program of its symbol table and relocation information.
-    d. Move character strings into a separate file. See the 2.11 BSD
-       target for an example.
-
-  6.4. Space/Time Tradeoffs
-
-   There are more than 6000 debug() statements in the program. If you
-   want to save both space (program size) and time (program execution
-   time), include -DNODEBUG in the compilation. If you want to include
-   debugging for tracking down problems, omit -DNODEBUG from the make
-   entry. But when you include debugging, you have two choices for how
-   it's done. One definition defines debug() to be a function call; this
-   is cheap in space but expensive in execution. The other defines debug
-   as "if (deblog)" and then the function call, to omit the function call
-   overhead when the debug log is not active. But this adds a lot of
-   space to the program. Both methods work, take your choice; IFDEBUG is
-   preferred if memory is not a constraint but the computer is likely to
-   be slow. The first method is the default, i.e. if nothing is done to
-   the CFLAGS or in [84]ckcdeb.h (but in some cases, e.g. VMS, it is). To
-   select the second method, include -DIFDEBUG in the compilation (and
-   don't include -DNODEBUG).
-
-   [ [85]C-Kermit Home ] [ [86]Kermit Home ]
-    ________________________________________________________________________
-
-  7. MODEM DIALING
-
-   [ [87]Top ] [ [88]Contents ] [ [89]Next ] [ [90]Previous ]
-
-   -DNODIAL removes automatic modem dialing completely, including the
-   entire [91]ckudia.c module, plus all commands that refer to dialing in
-   the various ckuus*.c modules.
-
-   -DMINIDIAL leaves the DIAL and related commands (SET/SHOW MODEM,
-   SET/SHOW DIAL) intact, but removes support for all types of modems
-   except CCITT, Hayes, Unknown, User-defined, Generic-high-speed, and
-   None (= Direct). The MINIDIAL option cuts the size of the dial module
-   approximately in half. Use this option if you have only Hayes or CCITT
-   modems and don't want to carry the baggage for the other types.
-
-   A compromise between full dialer support and MINIDIAL is obtained by
-   removing support for "old" modems -- all the strange non-Hayes
-   compatible 1200 and 2400 bps modems that C-Kermit has been carrying
-   around since 1985 or so. To remove support for these modems, add
-   -DNOOLDMODEMS to CFLAGS at compilation time.
-
-   Finally, if you keep support for old modems, you will notice that
-   their names appear on the "set modem ?" menu. That's because their
-   names are, by default, "visible". But the list is confusing to the
-   younger generation, who have only heard of modems from the
-   V.32bis-and-later era. If you want to be able to use old modems, but
-   don't want their names cluttering up menus, add this to CFLAGS:
-
-  -DM_OLD=1
-
-   [ [92]C-Kermit Home ] [ [93]Kermit Home ]
-    ________________________________________________________________________
-
-  8. NETWORK SUPPORT
-
-   [ [94]Top ] [ [95]Contents ] [ [96]Next ] [ [97]Previous ]
-
-   SECTION CONTENTS
-
-  8.1. [98]TCP/IP
-  8.2. [99]X.25
-  8.3. [100]Other Networks
-
-   C-Kermit supports not only serial-port and modem connections, but also
-   TCP/IP and X.25 network connections. Some versions support other
-   network types too like DECnet, LAT, NETBIOS, etc. If you define the
-   following symbol:
-
-  NONET
-
-   then all network support is compiled away.
-
-  8.1. TCP/IP
-
-   SUBSECTION CONTENTS
-
-  8.1.1. [101]Firewalls
-  8.1.2. [102]Compilation and Linking Problems
-  8.1.3. [103]Enabling Host Address Lists
-  8.1.4. [104]Enabling Telnet NAWS
-  8.1.5. [105]Enabling Incoming TCP/IP Connections
-  8.1.6. [106]Disabling SET TCP Options
-
-   C-Kermit's TCP/IP features require the Berkeley sockets library or
-   equivalent, generally available on any Unix system, as well as in
-   Windows 9x/NT, OS/2, VMS, AOS/VS, VOS, etc. The TCP/IP support
-   includes built-in TELNET, FTP, and HTTP protocol. To select TCP/IP
-   support, include -DTCPSOCKET in your makefile target's CFLAGS, or (in
-   VMS) the appropriate variant (e.g. -DWOLLONGONG, -DMULTINET,
-   -DEXCELAN, -DWINTCP, etc).
-
-   The VMS and/or early Unix third-party TCP/IP products are often
-   incompatible with each other, and sometimes with different versions of
-   themselves. For example, Wollongong reportedly put header files in
-   different directories for different UNIX versions:
-
-     * in.h can be in either /usr/include/sys or /user/include/netinet.
-     * telnet.h can be in either /usr/include/arpa or
-       /user/include/netinet.
-     * inet.h can be in either /usr/include/arpa or /user/include/sys.
-
-   In cases like this, use the -I cc command-line option when possible;
-   otherwise it's better to make links in the file system than it is to
-   hack up the C-Kermit source code. Suppose, for example, Kermit is
-   looking for telnet.h in /usr/include/arpa, but on your computer it is
-   in /usr/include/netinet. Do this (as root, or get the system
-   administrator to do it):
-
-  cd /usr/include/arpa
-  ln /usr/include/netinet/telnet.h telnet.h
-
-   ("man ln" for details about links.)
-
-   The network support for TCP/IP and X.25 is in the source files
-   [107]ckcnet.h, [108]ckctel.c, [109]ckctel.c, [110]ckctel.h,
-   [111]ckcftp.c, with miscellaneous SHOW commands, etc, in the various
-   ckuus*.c modules, plus code in the ck*con.c or ckucns.c (CONNECT
-   command) and several other modules to detect TELNET negotiations, etc.
-
-   Within the TCPSOCKET code, some socket-level controls are included if
-   TCPSOCKET is defined in the C-Kermit CFLAGS and SOL_SOCKET is defined
-   in in the system's TCP-related header files, such as <sys/socket.h>.
-   These are:
-
-  SET TCP KEEPALIVE
-  SET TCP LINGER
-  SET TCP RECVBUF
-  SET TCP SENDBUF
-
-   In addition, if TCP_NODELAY is defined, the following command is also
-   enabled:
-
-  SET TCP NODELAY (Nagle algorithm)
-
-   See the [112]C-Kermit user documentation for descriptions of these
-   commands.
-
-  8.1.1. Firewalls
-
-   There exist various types of firewalls, set up to separate users of an
-   internal TCP/IP network ("Intranet") from the great wide Internet, but
-   then to let selected users or services get through after all.
-
-   One firewall method is called SOCKS, in which a proxy server allows
-   users inside a firewall to access the outside world, based on a
-   permission list generally stored in a file. SOCKS is enabled in one of
-   two ways. First, the standard sockets library is modified to handle
-   the firewall, and then all the client applications are relinked (if
-   necessary, i.e. if the libraries are not dynamically loaded) with the
-   modified sockets library. The APIs are all the same, so the
-   applications do not need to be recoded or recompiled.
-
-   In the other method, the applications must be modified to call
-   replacement routines, such as Raccept() instead of accept(), Rbind()
-   instead of bind(), etc, and then linked with a separate SOCKS library.
-   This second method is accomplished (for SOCKS4) in C-Kermit by
-   including -DCK_SOCKS in your CFLAGS, and also adding:
-
-  -lsocks
-
-   to LIBS, or replacing -lsockets with -lsocks (depending on whether the
-   socks library also includes all the sockets entry points).
-
-   For SOCKS5, use -DCK_SOCKS5.
-
-   Explicit firewall support can, in general, not be a standard feature
-   or a feature that is selected at runtime, because the SOCKS library
-   tends to be different at each site -- local modifications abound.
-
-   The ideal situation occurs when firewalls are supported by the first
-   method, using dynamically linked sockets-replacement libraries; in
-   this case, all your TCP/IP client applications negotiate the firewall
-   transparently.
-
-  8.1.2. Compilation and Linking Problems
-
-   If you get a compilation error in [113]ckcnet.c, with a complaint like
-   "incompatible types in assignment", it probably has something to do
-   with the data type your system uses for the inet_addr() function,
-   which is declared (usually) in <arpa/inet.h>. Kermit uses "unsigned
-   long" unless the symbol INADDRX is defined, in which case "struct
-   inaddr" is used instead. Try adding -DINADDRX to CFLAGS in your make
-   entry, and if that fixes the problem, please send a report to
-   kermit@columbia.edu.
-
-   Compilation errors might also have to do with the data type used for
-   getsockopt() and setsockopt() option-length field. This is normally an
-   int, but sometimes it's a short, a long, or an unsigned any of those,
-   or a size_t. To fix the compilation problem, add -DSOCKOPT_T=xxx to
-   the CFLAGS in your makefile target, where xxx is the appropriate type
-   (use "man getsockopt" or grep through your system/network header files
-   to find the needed type).
-
-  8.1.3. Enabling Host Address Lists
-
-   When you give Kermit an IP host name, it calls the socket routine
-   gethostbyname() to resolve it. gethostbyname() returns a hostent
-   struct, which might or might not not include a list of addresses; if
-   it does, then if the first one fails, Kermit can try the second one,
-   and so on. However, this will only work if the symbol "h_addr" is a
-   macro defined as "h_addr_list[0]", usually in netdb.h. If it is, then
-   you can activate this feature by defining the following symbol in
-   CFLAGS:
-
-  HADDRLIST
-
-  8.1.4. Enabling Telnet NAWS
-
-   The Telnet Negotiation About Window Size (NAWS) option requires the
-   ability to find out the terminal screen's dimensions. E.g. in Unix, we
-   need something like ioctl(0, TIOCGWINSZ, ...). If your version of
-   Kermit was built with NAWS capability, SHOW VERSIONS includes CK_NAWS
-   among the compiler options. If it doesn't, you can add it by defining
-   CK_NAWS at compile time. Then, if the compiler or linker complain
-   about undefined or missing symbols, or there is no complaint but SHOW
-   TERMINAL fails to show reasonable "Rows =, Columns =" values, then
-   take a look at (or write) the appropriate ttgwsiz() routine. On the
-   other hand, if CK_NAWS is defined by default for your system (in
-   [114]ckcnet.h), but causes trouble, you can override this definition
-   by including the -DNONAWS switch on your CC command line, thus
-   disabling the NAWS feature.
-
-   This appears to be needed at least on the AT&T 3B2, where in
-   [115]ckutio.c, the routine ttgwsiz() finds that the TIOCGWINSZ symbol
-   is defined but lacks definitions for the corresponding winsize struct
-   and its members ws_col and ws_row.
-
-   The UNIX version of C-Kermit also traps SIGWINCH, so it can send a
-   NAWS to the Telnet server any time the local console terminal window
-   size changes, e.g. when you stretch it with a mouse. The
-   SIGWINCH-trapping code is enabled if SIGWINCH is defined (i.e. in
-   signal.h). If this code should cause problems, you can disable it
-   without disabling the NAWS feature altogether, by defining NOSIGWINCH
-   at compile time.
-
-  8.1.5. Enabling Incoming TCP/IP Connections
-
-   This feature lets you "set host * port" and wait for an incoming
-   connection on the given port. This feature is enabled automatically at
-   compile if TCPSOCKET is defined and SELECT is also defined. But watch
-   out, simply defining SELECT on the cc command line does not guarantee
-   successful compilation or linking (see [116]Section 11).
-
-   If you want to disable incoming TCP/IP connections, then build
-   C-Kermit with:
-
-  -DNOLISTEN
-
-  8.1.6. Disabling SET TCP Options
-
-   The main reason for this is because of header file / prototype
-   conflicts at compile time regardting get- / setsockopt(). If you can't
-   fix them (without breaking other builds), add the following in CFLAGS:
-
-  -DNOTCPOPTS
-
-  8.2. X.25
-
-   X.25 support requires (a) a Sun, (b) the SunLink product (libraries
-   and header files), and (c) an X.25 connection into your Sun. Similarly
-   (in C-Kermit 7.0 or later) Stratus VOS and IBM AIX.
-
-   In UNIX, special makefile targets sunos4x25 and sunos41x25 (for SUNOS
-   4.0 and 4.1, respectively), or aix41x25, are provided to build in this
-   feature, but they only work if conditions (a)-(c) are met. To request
-   this feature, include -DSUNX25 (or -DIBMX25) in CFLAGS.
-
-   SUNX25 (or -DIBMX25) and TCPSOCKET can be freely mixed and matched,
-   and selected by the user at runtime with the SET NETWORK TYPE command
-   or SET HOST switches.
-
-  8.3. Other Networks
-
-   Support for other networking methods -- NETBIOS, LAT, Named Pipes, etc
-   -- is included in ck*net.h and ck*net.c for implementations (such as
-   Windows or OS/2) where these methods are supported.
-
-   Provision is made in the organization of the modules, header files,
-   commands, etc, for addition of new network types such as DECnet, X.25
-   for other systems (HP-UX, VMS, etc), and so on. Send email to
-   [117]kermit@columbia.edu if you are willing and able to work on such a
-   project.
-
-   [ [118]C-Kermit Home ] [ [119]Kermit Home ]
-    ________________________________________________________________________
-
-  9. EXCEPTION HANDLING
-
-   [ [120]Top ] [ [121]Contents ] [ [122]Next ] [ [123]Previous ]
-
-   The C language setjmp/longjmp mechanism is used for handling
-   exceptions. The jump buffer is of type jmp_buf, which almost
-   everywhere is typedef'd as an array, in which case you should have no
-   trouble compiling the exception-handling code. However, if you are
-   building C-Kermit in/for an environment where jmp_buf is something
-   other than an array (e.g. a struct), then you'll have to define the
-   following symbol:
-
-  JBNOTARRAY
-
-   [ [124]C-Kermit Home ] [ [125]Kermit Home ]
-    ________________________________________________________________________
-
-  10. SECURITY FEATURES
-
-   [ [126]Top ] [ [127]Contents ] [ [128]Next ] [ [129]Previous ]
-
-   Security, in the sense of secure authentication and strong encryption,
-   can be built into versionf of C-Kermit for which the appropriate
-   libraries and header files are available (Kerberos IV, Kerberos V,
-   OpenSSL, SRP), as explained in great detail in the Kermit Security
-   Reference
-   . The following symbols govern C-Kermit's security features at build
-   time:
-
-   NO_AUTHENTICATION
-          Means do not configure any TELNET AUTHENTICATION support. It
-          implies NO_ENCRYPTION and undefines any of the auth and encrypt
-          types. It does not undefine CK_SSL even though builds with
-          CK_SSL cannot succeed without CK_AUTHENTICATION. (This will be
-          supported in a future release. It will be needed to allow
-          C-Kermit to be built only as an FTP client.)
-
-   NO_KERBEROS
-          Means do not compile in any KERBEROS support when
-          CK_AUTHENTICATION has been defined.
-
-   NO_SRP
-          Do not compile in any SRP support when CK_AUTHENTICATION has
-          been defined.
-
-   NO_SSL
-          Do not compile in any SSL/TLS support
-
-   NO_ENCRYPTION
-          Do not compile in any Telnet encryption support. It does not
-          affect the use of SSL/TLS
-
-   NOSSH
-          Do not compile in any SSH support whether internal or external
-
-   CK_AUTHENTICATION
-          Telnet AUTHENTICATION support. (Also, required if SSL/TLS
-          support is desired.) On most platforms this does not autodefine
-          any authentication mechanisms such as Kerberos V, Kerberos IV,
-          SRP, ... Those need to be defined separately.
-
-   CK_KERBEROS
-          Defined automatically when KRB4, KRB5, or KRB524 are defined.
-          Implies that some version of Kerberos is in use.
-
-   KRB4
-          Should be defined when Kerberos IV support is desired.
-
-   KRB5
-          Should be defined when Kerberos V support is desired.
-
-   KRB524
-          Should be defined if both Kerberos V and Kerberos IV are used
-          and the Kerberos IV support is provided by the MIT Kerberos IV
-          compatibility library in the current Kerberos 5 distribution.
-
-   KRB5_U2U
-          Should be defined if KRB5 is defined and Kerberos 5 User to
-          User mode is desired.
-
-   HEIMDAL
-          Should be defined if Kerberos V support is provided by HEIMDAL.
-          Support for this option is not complete in C-Kermit 8.0. Anyone
-          interested in working on this should contact kermit-support.
-
-   CK_SRP
-          Should be defined if SRP support is desired.
-
-   CK_ENCRYPTION
-          Should be defined if TELNET ENCRYPTION option support is
-          desired. This option does not define any particular encryption
-          types. That should be done by defining CK_DES or CK_CAST.
-
-   CK_DES
-          Should be defined if either DES or 3DES Telnet Encryption
-          option support is desired.
-
-   LIBDES
-          If CK_DES is defined and DES support is being provided by
-          either Eric Young's libdes.a or OpenSSL 0.9.6x or earlier, this
-          option must be defined. If it is not defined, it will be
-          assumed that DES support is provided by the MIT Kerberos IV
-          libraries.
-
-   CK_CAST
-          Should be defined if CAST Telnet Encryption option support is
-          desired
-
-   CK_SSL
-          Should be defined if SSL/TLS support (OpenSSL) is desired.
-
-   SSL_KRB5
-          If KRB5 is defined, and OpenSSL is built to support the
-          Kerberos 5 ciphers, then you should define SSL_KRB5
-
-   NOSSLKRB5
-          If you are using OpenSSL 0.9.7 or higher and do not wish to
-          build with support for Kerberos 5 TLS ciphers, this option must
-          be defined.
-
-   ZLIB
-          If you are using OpenSSL 0.9.6 or higher and it has been
-          compiled with support for ZLIB compression, this option should
-          be defined to enable Kermit to properly enable the use of
-          compression.
-
-   SSHCMD
-          Defined for C-Kermit to enable the use of external SSH clients
-          from the Kermit command language
-
-   SSHBUILTIN
-          Defined for Kermit implementations that have integrated SSH
-          support. Currently only Windows.
-
-   ANYSSH
-          Defined if either SSHCMD or SSHBUILTIN are defined.
-
-   CK_SNDLOC
-          Telnet Send Location support.
-
-   NOSNDLOC
-          Do not include Telnet Send Location support.
-
-   CK_XDISPLOC
-          Telnet X-Display Location support. Determines if the X-Display
-          location information is sent to the Telnet server either via
-          Telnet XDISPLOC or NEW-ENV options.
-
-   NOXDISPLOC
-          Do not include Telnet X-Display Location support.
-
-   CK_FORWARD_X
-          Telnet Forward X Windows Session Data option. Used to protect
-          the privacy and integrity of X Windows Sessions when secure
-          telnet sessions are in use.
-
-   NOFORWARDX
-          Do not include Telnet Forward X Windows Session Data option.
-
-   Besides the strong forms of security listed above, C-Kermit also
-   embodies various internal security features, including:
-
-   NOPUSH
-          Compiling with the NOPUSH symbol defined removes all the "shell
-          escape" features from the program, including the PUSH, RUN, and
-          SPAWN commands, the "!" and "@" command prefixes, OPEN !READ,
-          OPEN !WRITE, job control (including the SUSPEND command), the
-          REDIRECT command, shell/DCL escape from CONNECT mode, as well
-          as the server's execution of REMOTE HOST commands (and, of
-          course, the ENABLE HOST command). Add NODISPO to also prevent
-          acceptance of incoming MAIL or REMOTE PRINT files. For UNIX,
-          also be sure to read [130]Section 11 of the [131]Unix C-Kermit
-          Installation Instructions. about set[ug]id configuration.
-          Additional restrictions can be enforced when in server mode;
-          read about the DISABLE command in the user manual.
-
-   NOCCTRAP
-          Compiling with NOCCTRAP prevents the trapping of SIGINT by
-          Kermit. Thus if the user generates a SIGINT signal (e.g. by
-          typing the system's interrupt character), Kermit will exit
-          immediately, rather than returning to its prompt.
-
-   NOPUSH and NOCCTRAP together allow Kermit to be run from restricted
-   shells, preventing access to system functions.
-
-   [ [132]C-Kermit Home ] [ [133]Kermit Home ]
-    ________________________________________________________________________
-
-  11. ENABLING SELECT()
-
-   [ [134]Top ] [ [135]Contents ] [ [136]Next ] [ [137]Previous ]
-
-   Kermit works best if it can do nonblocking reads, nondestructive input
-   buffer checking, and millisecond sleeps. All of these functions can be
-   accomplished by the select() function, which, unfortunately, is not
-   universally available. Furthermore, select() is required if incoming
-   TCP/IP connections are to be supported.
-
-   select() was introduced with Berkeley UNIX, rejected by AT&T for
-   System V, but is gradually creeping in to all UNIX versions (and other
-   operating systems too) by virtue of its presence in the sockets
-   library, which is needed for TCP/IP. AT&T SVID for System V R4
-   includes select(), but that does not mean that all SVR4
-   implementations have it.
-
-   Furthermore, even when select() is available, it might work only on
-   socket file descriptors, but not on others like serial ports, pipes,
-   etc. For example, in AOS/VS and BeOS, it works only with file
-   descriptors that were created by socket() and opened by connect() or
-   accept().
-
-   Other alternatives include poll() and rdchk(). Only one of these three
-   functions should be included. The following symbols govern this:
-
-     SELECT  Use select() (BSD, or systems with sockets libraries)
-     CK_POLL Use poll()   (System V)
-     RDCHK   Use rdchk()  (SCO XENIX and UNIX)
-
-   If your system supports the select() function, but your version of
-   C-Kermit does not, try adding:
-
-  -DSELECT
-
-   to the CFLAGS, and removing -DRDCHK or -DCK_POLL if it is there. If
-   you get compilation errors, some adjustments to ck*tio.c and/or
-   ck*net.c might be needed; search for SELECT (uppercase) in these files
-   (note that there are several variations on the calling conventions for
-   select()).
-
-   Various macros and data types need to be defined in order to use
-   select(). Usually these are picked up from <types.h> or <sys/types.h>.
-   But on some systems, they are in <sys/select.h>. In that case, add the
-   following:
-
-  -DSELECT_H
-
-   to the CFLAGS to tell C-Kermit to #include <sys/select.h>. A good
-   indication that you need to do this would be if you get compile-time
-   complaints about "fd_set" or "FD_SET" not being declared or defined.
-
-   In UNIX, the use of select() vs fork() in the CONNECT command is
-   independent of the above considerations, and is governed by choosing a
-   particular makefile target.
-
-   As of C-Kermit 7.0, select() is also the preferred control mechanism
-   for the CONNECT command. Unfortunately, the structures used by the
-   original UNIX CONNECT command, based on fork(), and those used by
-   select(), are so different, it was not practical to implement them
-   both in one module. So the select()-based CONNECT command module for
-   UNIX is [138]ckucns.c, and the fork-based one remains [139]ckucon.c.
-   To choose the fork-based one, which is more portable (but slower and
-   more fragile), use "wermit" as the make target. To choose the
-   select-based one, use "xermit". Only do this if you can verify that
-   the CONNECT command works on serial connections and PIPE connections
-   as well as TCP connections.
-
-     The select()-based Unix CONNECT module, ckucns.c, must be used if
-     encryption is to be done, since the fork() version (ckucon.c) loses
-     its ability to share vital state information between the two forks.
-     Also note that the select() version is superior in many other ways
-     too. For example, it recovers better from exterior killing, forced
-     disconnections, etc, plus it goes faster.
-
-   SHOW VERSIONS tells whether the CONNECT module uses fork() or
-   select().
-
-   C-Kermit 8.0 adds learned script capability, which depends on
-   select(). All the "wermit" based targets (as opposed to "xermit") had
-   NOLEARN added to them. Whenever changing a target over from wermit to
-   xermit, also remember to remove NOLEARN.
-
-   [ [140]C-Kermit Home ] [ [141]Kermit Home ]
-    ________________________________________________________________________
-
-  12. I/O REDIRECTION
-
-   [ [142]Top ] [ [143]Contents ] [ [144]Next ] [ [145]Previous ]
-
-   The REDIRECT command allows a local program to be run with its i/o
-   redirected over the communications connection. Your version of
-   C-Kermit has a REDIRECT command if it was built with the following
-   CFLAG:
-
-  -DCK_REDIR
-
-   This, in turn, is possible only if the underlying API is there. In the
-   case of UNIX this is just the wait() system call, so all UNIX versions
-   get this feature as of 6.0.192 (earlier versions needed a <sys/wait.h>
-   header file defining the symbols WIFEXITED and WEXITSTATUS).
-
-   As of version 7.0, file transfer can be done using pipes and filters.
-   To enable this feature, #define PIPESEND (and fill in the code). To
-   disable on systems where it is normally enabled, define NOPIPESEND.
-   This feature is, of course, also disabled by building with NOPUSH (or
-   giving the "nopush" command at runtime).
-
-   C-Kermit 7.0 also adds the PIPE and SET HOST /COMMAND commands, which
-   provide another form of redirection. This feature is selected with
-   -DNETCMD. CK_RDIR must also be defined, since the same mechanisms are
-   used internally.
-
-   [ [146]C-Kermit Home ] [ [147]Kermit Home ]
-    ________________________________________________________________________
-
-  13. FLOATING-POINT NUMBERS, TIMERS, AND ARITHMETIC
-
-   [ [148]Top ] [ [149]Contents ] [ [150]Next ] [ [151]Previous ]
-
-   Floating-point support was added in C-Kermit 7.0.
-
-   Floating-point numbers are enabled internally, at least for use in
-   high-precision file-transfer timers and statistics, unless the
-   following symbol is defined at compile time:
-
-  -DNOFLOAT
-
-   This might be necessary on old PCs that do not have built-in
-   floating-point hardware.
-
-   When NOFLOAT is not defined, the following symbol tells which
-   floating-point type to use:
-
-  -DCKFLOAT=xxxx
-
-   The value is either "double" (normal for 32- and 16-bit architectures)
-   or "float" (normal for 64-bit architectures).
-
-   C-Kermit can be configured to use high-precision file-transfer timers
-   for more accurate statistics. This feature is enabled with:
-
-  -DGFTIMER
-
-   and disabled with:
-
-  -DNOGFTIMER
-
-   If you try to build with -DGFTIMER but you get compilation errors,
-   either fix them (and send email to kermit@columbia.edu telling what
-   you did), or else give up and use -DNOGFTIMER (or -DNOFLOAT) instead.
-   Hint: depending on your machine architecture, you might have better
-   luck using double than float as the data type for floating-point
-   numbers, or vice versa. Look in [152]ckcdeb.h for the CKFLOAT
-   definition.
-
-   Floating-point arithmetic is also supported in the script programming
-   language. First via the \fpp...() functions, such as \fppadd(), which
-   adds two floating-point numbers, second in S-Expressions. Addition,
-   subtraction, multiplication, and division are always available. But
-   other functions such as logs, raising to powers, sines and cosines,
-   etc, require the C Math library. To include user-level floating-point
-   math you must put:
-
-  -DFNFLOAT
-
-   and in Unix you must link with the Math library:
-
-  LIBS=".... -lm"
-
-   In K95 and VMS, FNFLOAT is defined automatically if CKFLOAT is
-   defined. In Unix, however, FNFLOAT must be added to each makefile
-   target individually, because of the special linking instructions that
-   must also be added to each target.
-
-   Note: S-Expressions require FNFLOAT.
-
-   [ [153]C-Kermit Home ] [ [154]Kermit Home ]
-    ________________________________________________________________________
-
-  14. SPECIAL CONFIGURATIONS
-
-   [ [155]Top ] [ [156]Contents ] [ [157]Previous ]
-
-   As of C-Kermit 7.0, if you build C-Kermit normally, but with -DNOICP
-   (No Interactive Command Parser), you get a program capable of making
-   serial connections (but not dialing) and network connections (if
-   TCPSOCKET or other network option included), and can also transfer
-   files using Kermit protocol, but only via autodownload/upload.
-   Furthermore, if you call the executable "telnet", it will act like
-   Telnet -- using the command-line options. However, in this case there
-   is nothing to escape back to, so if you type Ctrl-\c, it just prints a
-   message to this effect.
-
-   You can also build C-Kermit with -DNOXFER, meaning omit all the
-   file-transfer features. This leaves you with a scriptable
-   communications program that is considerably smaller than the full
-   C-Kermit.
-
-   [ [158]C-Kermit Home ] [ [159]Kermit Home ]
-    ________________________________________________________________________
-
-  APPENDIX I: SUMMARY OF COMPILE-TIME OPTIONS
-
-   [ [160]Top ] [ [161]Contents ]
-
-   These are the symbols that can be specified on the cc command line,
-   listed alphabetically. Others are used internally, including those
-   taken from header files, those defined by the compiler itself, and
-   those inferred from the ones given below. Kermit's SHOW VERSIONS
-   command attempts to display most of these. See [162]ckcdeb.h and
-   [163]ckcnet.h for inference rules. For example SVR3 implies ATTSV,
-   MULTINET implies TCPSOCKET, and so on.
-
-   Here is the complete list of the Kermit-specific compile-time
-   switches:
-
-   ACUCNTRL Select BSD 4.3-style acucntrl() bidirectional tty control.
-   aegis Build for Apollo Aegis (predefined on Apollo systems).
-   AIX370 Build for IBM AIX/370 for IBM mainframes.
-   AIXESA Build for IBM AIX/ESA for IBM mainframes.
-   AIXPS2 Build for IBM AIX 3.0 for PS/2 series (never formally
-   released).
-   AIXRS Build for IBM AIX 3.x on RS/6000.
-   AIX41 Build for IBM AIX 4.x on RS/6000.
-   AMIGA Build for Commodore Amiga with Intuition OS.
-   ATT6300 Build for AT&T 6300 PLUS.
-   ATT7300 Build for AT&T 7300 UNIX PC (3B1).
-   ATTSV Build for AT&T System III or V UNIX.
-   AUX Build for Apple A/UX for the Macintosh.
-   BIGBUFOK OK to use big buffers - "memory is not a problem"
-   BPS_xxxx Enable SET SPEED xxxx
-   BSD29 Build for BSD 2.9 or 2.10.
-   BSD4 Build for BSD 4.2.
-   BSD41 Build for BSD 4.1.
-   BSD43 Build for BSD 4.3.
-   BSD44 Build for BSD 4.4.
-   C70 Build for BBN C/70.
-   CIE Build for CIE Systems 680/20.
-   CKCONINTB4CB Work around prompt-disappears after escape back from
-   CONNECT.
-   CKLEARN Build with support for learned scripts.
-   CKLOGDIAL Enable connection log.
-   CKMAXPATH Maximum length for a fully qualified filename.
-   CKREGEX (misnomer) Include [...] or {xxx,xxx,xxx} matching in
-   ckmatch().
-   CKSYSLOG Enable syslogging.
-   CK_ANSIC Enable ANSI C constructs - prototypes, etc.
-   CK_ANSILIBS Use header files for ANSI C libraries.
-   CK_APC Enable APC execution by CONNECT module.
-   CK_CURSES Enable fullscreen file transfer display.
-   CK_DSYSINI Use system-wide init file, with name supplied by Kermit.
-   CK_DTRCD DTR/CD flow control is available.
-   CK_FAST Build with fast Kermit protocol defaults.
-   CK_FORK_SIG UNIX only: signal() number for CONNECT module forks.
-   CK_IFRO IF REMOTE command is available (and can run in remote mode).
-   CK_INI_A System-wide init file takes precedence over user's.
-   CK_INI_B User's init file takes precedence over the system-wide one.
-   CK_LABELED Include support for SET FILE TYPE LABELED.
-   CK_LBRK This version can send Long BREAK.
-   CK_LINGER Add code to turn of TCP socket "linger" parameter.
-   CK_MKDIR This version has a zmkdir() command to create directories.
-   CK_NAWS Include TELNET Negotiate About Window Size support.
-   CK_NEWTERM Use newterm() rather than initscr() to initialize curses.
-   CK_PAM Include PAM authentication (might also require -lpam).
-   CK_PCT_BAR Fullscreen file transfer display should include
-   "thermometer".
-   CK_POLL System-V or POSIX based UNIX has poll() function.
-   CK_POSIX_SIG Use POSIX signal handing: sigjmp_buf, sigsetjmp,
-   siglongjmp.
-   CK_READ0 read(fd,&x,0) can be used to test TCP/IP connections.
-   CK_REDIR Enable the REDIRECT command.
-   CK_RESEND Include the RESEND command (needs zfseek() + append).
-   CK_RTSCTS RTS/CTS flow control is available.
-   CK_SHADOW Include support for shadow passwords (e.g. for IKSD
-   authentication).
-   CK_SOCKBUF Enable TCP socket-buffer-size-increasing code.
-   CK_SOCKS UNIX only: Build with socks library rather than regular
-   sockets
-   CK_SOCKS5 UNIX only: Build with socks 5 lib rather than regular
-   sockets
-   CK_SPEED Enable control-character unprefixing.
-   CK_SYSINI="xxxxx" Quoted string to be used as system-wide init file
-   name.
-   CK_TIMERS Build with support for dynamically calculated packet
-   timeouts.
-   CK_TMPDIR This version of Kermit has an isdir() function.
-   CK_TTYFD Defined on systems where the communications connection file
-   descriptor (ttyfd) can be passed to other processes as a command-line
-   argument via \v(ttyfd).
-   CK_URL Parse URLs as well as hostnames, etc.
-   CK_XONXOFF Xon/Xoff flow control available.
-   CK_XYZ Include support for XYZMODEM protocols.
-   CK_WREFRESH Curses package includes wrefresh(),clearok() for screen
-   refresh.
-   CKFLOAT=type Floating-point data type, "double" or "float".
-   CKTYP_H=xxx Force include of xxx as <types.h> file.
-   CLSOPN When hanging up a tty device, also close and reopen it.
-   CMDDEP Maximum recursion depth for self-referential user-defined fn's.
-   COHERENT Build for Mark Williams Coherent UNIX
-   CONGSPD Define if this version has congspd() routine in ck?tio.c
-   datageneral Build for Data General AOS/VS or AOS/VS II
-   DCLPOPEN popen() is available but needs to be declared
-   DEC_TCPIP Build with support for DEC TCP/IP (UCX) for (Open)VMS
-   DGUX430 Build for DG/UX 4.30
-   DGUX540 Build for DG/UX 5.40
-   DEFPAR=x Default parity, 0, 'e', 'o', 'm', or 's'.
-   DFTTY=xxx Default communications device name.
-   DIRENT UNIX directory structure to be taken from <dirent.h>.
-   DIRPWDRP Prompt for password in REMOTE CWD command.
-   DTILDE Include UNIX ~ notation for username/home-directory
-   DYNAMIC Allocate file transfer packet buffers dynamically with malloc.
-   ENCORE Build for Encore Multimax computers.
-   EXCELAN Build with excelan TCP/IP.
-   FNFLOAT Include floating-point math functions (logs, sin, cos, exp,
-   etc)
-   FT18 Build for Fortune For:Pro 1.8.
-   FT21 Build for Fortune For:Pro 2.1.
-   GEMDOS Build for Atari ST GEMDOS.
-   GFTIMER Use high-precision floating-point file-transfer timers.
-   GID_T=xxx Group IDs are of type xxx (usually int, short, or gid_t).
-   HADDRLIST If gethostbyname() hostent struct contains a list of
-   addresses.
-   HDBUUCP Build with support for Honey DanBer UUCP.
-   HPUX Build for Hewlett Packard HP-UX.
-   HPUX9 Build for Hewlett Packard HP-UX 9.x.
-   HPUX10 Build for Hewlett Packard HP-UX 10.x.
-   HWPARITY Define if this version can SET PARITY HARDWARE { EVEN,
-   ODD...}
-   I386IX Build for Interactive System V R3.
-   IFDEBUG Add IF stmts "if (deblog)" before "debug()" calls.
-   INADDRX TCP/IP inet_addr() type is struct inaddr, not unsigned long.
-   INTERLAN Build with support for Racal/Interlan TCP/IP.
-   ISDIRBUG System defs of S_ISDIR and S_ISREG have bug, define
-   ourselves.
-   ISIII Build for Interactive System III.
-   IX370 Build for IBM IX/370.
-   KANJI Build with Kanji character-set translation support.
-   LCKDIR UUCP lock directory is /usr/spool/uucp/LCK/.
-   LFDEVNO UUCP lockfile name uses device numbers, as in SVR4.
-   LINUXFSSTND For Linux, use FSSTND UUCP lockfile conventions (default).
-   LOCK_DIR=xxx UUCP lock directory is xxx (quoted string).
-   LOCKF Use lockf() (in addition to lockfiles) on serial lines
-   LONGFN BSD long filenames supported using <dir.h> and opendir().
-   LYNXOS Build for Lynx OS 2.2 or later (POSIX-based).
-   MAC Build for Apple Macintosh with Mac OS.
-   MATCHDOT Make wildcards match filenames that start with period (.)
-   MAXRP=number Maximum receive-packet length.
-   MAXSP=number Maximum send-packet length.
-   MDEBUG Malloc-debugging requested.
-   MINIDIAL Minimum modem dialer support: CCITT, Hayes, Unkown, and None.
-   MINIX Build for MINIX.
-   MIPS Build for MIPS workstation.
-   MULTINET Build with support for TGV MultiNet TCP/IP (VAX/VMS).
-   M_UNIX Defined by SCO.
-   NAP The nap() is available (conflicts with SELECT and USLEEP)
-   NAPHACK The nap() call is available but only as syscall(3112,...)
-   NDIR BSD long filenames supported using <ndir.h> and opendir().
-   NDGPWNAM Don't declare getpwnam().
-   NDSYSERRLIST Don't declare sys_errlist[].
-   NEEDSELECTDEFS select() is avaible but we need to define FD_blah
-   ourselves.
-   NETCMD Build with support for SET HOST /COMMAND and PIPE commands.
-   NEXT Build for NeXT Mach 1.x or 2.x or 3.0, 3.1, or 3.2.
-   NEXT33 Build for NeXT Mach 3.3.
-   NOANSI Disable ANSI C function prototyping.
-   NOAPC Do not include CK_APC code.
-   NOARROWKEYS Exclude code to parse ANSI arrow-key sequences.
-   NOB_xxxx Disable SET SPEED xxxx
-   NOBIGBUF Override BIGBUFOK when it is the default
-   NOBRKC Don't try to refer to t_brkc or t_eof tchars structure members.
-   NOCKFQHOSTNAME Exclude code to get fully qualified hostname in case it
-   causes core dumps.
-   NOCCTRAP Disable Control-C (SIGINT) trapping.
-   NOCKSPEED Disable control-prefix removal feature (SET CONTROL).
-   NOCKTIMERS Build without support for dynamic timers.
-   NOCKXYZ Overrides CK_XYZ.
-   NOCKREGEX Do not include [...] or {xxx,xxx,xxx} matching in ckmatch().
-   NOCMDL Build with no command-line option processing.
-   NOCOTFMC No Close(Open()) To Force Mode Change (UNIX version).
-   NOCSETS Build with no support for character set translation.
-   NOCYRIL Build with no support for Cyrillic character set translation.
-   NOCYRILLIC Ditto.
-   NODEBUG Build with no debug logging capability.
-   NODIAL Build with no DIAL or SET DIAL commands.
-   NODISPO Build to always refuse incoming MAIL or REMOTE PRINT files.
-   DNODISPLAY Build with no file-transfer display.
-   NOESCSEQ Build with no support for ANSI escape sequence recognition.
-   NOFAST Do not make FAST Kermit protocol settings the default.
-   NOFDZERO Do not use file descriptor 0 for remote-mode file transfer.
-   NOFILEH Do not #include <sys/file.h>.
-   NOFLOAT Don't include any floating-point data types or operations.
-   NOFRILLS Build with "no frills" (this should be phased out...)
-   NOFTRUNCATE Include this on UNIXes that don't have ftruncate().
-   NOGETUSERSHELL Include this on UNIXes that don't have getusershell().
-   NOGFTIMER Don't use high-precision floating-point file-transfer
-   timers.
-   NOHEBREW Build with no support for Hebrew character sets.
-   NOHELP Build with no built-in help.
-   NOIKSD Build with IKSD support excluded.
-   NOINITGROUPS Include this on UNIXes that don't have initgroups().
-   NOICP Build with no interactive command parser.
-   NOJC Build with no support for job control (suspend).
-   NOKANJI Build with no support for Japanese Kanji character sets.
-   NOKVERBS Build with no support for keyboard verbs (\Kverbs).
-   NOLATIN2 Build with no ISO Latin-2 character-set translation support.
-   NOLEARN Build with no support for learned scripts.
-   NOLINKBITS Use of S_ISLNK and _IFLNK untrustworthy; use readlink()
-   instead.
-   NOLOCAL Build without any local-mode features: No Making Connections.
-   NOLOGDIAL Disable connection log.
-   NOLOGIN Build without IKSD (network login) support.
-   NOLSTAT Not OK to use lstat().
-   NOMDMHUP Build without "modem-specific hangup" (e.g. ATH0) feature.
-   NOMHHOST Exclude the multihomed-host TCP/IP code (if compilcation
-   errors)
-   NOMINPUT Build without MINPUT command.
-   NOMSEND Build with no MSEND command.
-   NONAWS Do not include TELNET Negotiate About Window Size support.
-   NONET Do not include any network support.
-   NONOSETBUF (See NOSETBUF)
-   NOPARSEN Build without automatic parity detection.
-   NOPIPESEND Disable file transfer using pipes and filters.
-   NOPOLL Override CK_POLL definition.
-   NOPOPEN The popen() library call is not available.
-   NOPURGE Build with no PURGE command.
-   NOPUSH Build with no escapes to operating system.
-   NOREALPATH In UNIX, realpath() function is not available.
-   NORECALL Disable the command-recall feature.
-   NOREDIRECT Disable REDIRECT command.
-   NORENAME Don't use rename() system call, use link()/unlink() (UNIX).
-   NORESEND Build with no RESEND command.
-   NORETRY Build with no command-retry feature.
-   NOSCRIPT Build with no SCRIPT command.
-   NOSELECT Don't try to use select().
-   NOSERVER Build with no SERVER mode and no server-related commands.
-   NOSETBUF Don't make console writes unbuffered.
-   NONOSETBUF DO make console writes unbuffered.
-   NOSETREU setreuid() and/or setregid() not available.
-   NOSHOW Build with no SHOW command (not recommended!).
-   NOSIGWINCH Disable SIGWINCH signal trapping.
-   NOSPL Build with no script programming language.
-   NOSTAT Don't call stat() from mainline code.
-   NOSYMLINK Include this for UNIXes that don't have readlink().
-   NOSYSIOCTLH Do not #include <sys/ioctl.h>.
-   NOSYSTIMEH Co not include <sys/time.h>.
-   NOSYSLOG Disable syslogging code.
-   NOTCPOPTS Build with no SET TCP options or underlying support.
-   NOTLOG Build with no support for transaction logging.
-   NOTM_ISDST Struct tm has no tm_isdst member.
-   NOUNICODE Build with no support for Unicode character-set translation.
-   NOURL Don't parse URLs
-   NOUUCP Build with no UUCP lockfile support (dangerous!).
-   NOWARN Make EXIT WARNING be OFF by default (otherwise it's ON).
-   NOWREFRESH Override built-in definition of CK_WREFRESH (q.v.).
-   NOXFER Build with no Kermit or other file-transfer protocols.
-   NOXMIT Build with no TRANSMIT command.
-   NOXPRINT Disables transparent print code.
-   OLDMSG Use old "entering server mode" message (see [164]ckcmai.c).
-   OLINUXHISPEED Build in old Linux hi-serial-speed code (for Linux <=
-   1.0).
-   OPENBSD Build for OpenBSD.
-   OS2 Build for OS/2.
-   OSF Build for OSF/1.
-   OSFPC Build for OSF/1 on a PC.
-   OSF32 Digital UNIX 3.2 or later.
-   OSF40 Build for Digital UNIX 4.0.
-   OSF50 Build for Digital UNIX 5.0.
-   OSK Build for OS-9.
-   OXOS Build for Olivetti X/OS 2.3.
-   PCIX Build for PC/IX
-   PID_T=xxx Type for pids is xxx (normally int or pid_t).
-   POSIX Build for POSIX: use POSIX header files, functions, etc.
-   _POSIX_SOURCE Disable non-POSIX features.
-   PROVX1 Build for Venix 1.0 on DEC Professional 3xx.
-   PTX Build for Dynix/PTX
-   PWID_T=xxx getpwid() type is xxx.
-   RBSIZ=xxx Define overall size of receive-packet buffer (with DYNAMIC).
-   RDCHK rdchk() system call is available.
-   RENAME rename() system call is available (UNIX).
-   RTAIX Build for AIX 2.2.1 on IBM RT PC.
-   RTU Build for Masscomp / Concurrent RTU.
-   SAVEDUID BSD or other non-AT&T UNIX has saved-setuid feature.
-   SBSIZ=xxx Define overall size of send-packet buffer (use with
-   DYNAMIC).
-   SDIRENT Directory structure specified in <sys/dirent.h>.
-   SELECT select() function available (conflicts with RDCHK and CK_POLL)
-   SELECT_H Include <sys/select.h> for select()-releated definitions.
-   SETEUID BSD 4.4-style seteXid() functions available.
-   SIG_V Type for signal() is void. Used to override normal assumption.
-   SIG_I Type for signal() is int. Used to override normal assumption.
-   SOCKOPT_T Override default data type for get/setsockopt() option
-   length.
-   SOLARIS Build for Solaris.
-   SOLARIS25 Build for Solaris 2.5 or later.
-   SONYNEWS Build for Sony NEWS-OS.
-   STERMIOX <sys/termiox.h> is available.
-   STRATUS Build for Stratus VOS.
-   STRATUSX25 Include Stratus VOS X.25 support.
-   SUN4S5 Build for SUNOS 4.x in the System V R3 environment.
-   SUNOS4 Build for SUNOS 4.0 in the BSD environment.
-   SUNOS41 Build for SUNOS 4.1 in the BSD environment.
-   SUNX25 Build with support for SunLink X.25.
-   SVR3 Build for AT&T System V Release 3.
-   SVR3JC Allow job control support on System V Release 3 UNIX versions.
-   SVR4 Build for AT&T System V Release 4.
-   SW_ACC_ID UNIX only -- swap real & effective ids around access()
-   calls.
-   sxaE50 Build for PFU Compact A Series SX/A TISP.
-   SYSLOGLEVEL=n Force syslogging at given level.
-   SYSTIMEH Include <sys/time.h>.
-   SYSUTIMEH Include <sys/utime.h> for setting file dates (88OPEN)
-   TCPSOCKET Build with support for TCP/IP via Berkeley sockets library.
-   TERMIOX <termiox.h> header file is available (mostly SVR4).
-   TNCODE Include TELNET-specific code.
-   TOWER1 Build for NCR Tower 1632 with OS 1.02.
-   TRS16 Build for Tandy 16/6000.
-   UID_T=xxx Type for uids is xxx (normally int or uid_t).
-   UNIX Must be defined for all UNIX versions.
-   UNIX351M AT&T UNIX 3.51m on the AT&T 7300 UNIX PC.
-   USE_ARROWKEYS Include code to parse ANSI arrow-key sequences.
-   USE_LSTAT OK to use lstat().
-   USE_MEMCPY Define this if memcpy()/memset()/memmove() available.
-   USE_STRERROR Define this if strerror() is available.
-   USLEEP usleep() system call available (conflicts with NAP & SELECT).
-   UTEK Build for Tektronix workstations with UTEK OS.
-   UTIMEH Include <utime.h> for setting file dates (SVR4, POSIX)
-   UTS24 Build for Amdahl UTS 2.4.
-   V7 Build for Version 7 UNIX.
-   VMS Build for VAX/VMS.
-   VOID=xxx VOID type for functions (int or void).
-   VXVE Build for CDC VX/VE 5.2.1.
-   WAIT_T=xxx Type of argument passed to wait().
-   WINTCP Build with Wollongong VAX/VMS TCP/IP (implies TCPSOCKET)
-   WOLLONGONG Build with Wollongong UNIX TCP/IP (implies TCPSOCKET)
-   XENIX Build for Xenix (SCO, Tandy, others).
-   XNDIR Support for BSD long filenames via <sys/ndir.h>.
-   XYZ_INTERNAL Support for XYZMODEM protocols is internal, not external.
-   ZFCDAT Define this if zfcdat() function is available in Kermit.
-   ZILOG Build for Zilog ZEUS.
-   ZJDATE Has zjdate() function that converts date to Julian format.
-   XPRINT Transparent print code included in CONNECT module.
-
-   [ [165]Top ] [ [166]Contents ] [ [167]C-Kermit Home ] [ [168]Kermit
-   Home ]
-     _________________________________________________________________
-
-
-    C-Kermit Configuration Options / [169]The Kermit Project /
-    [170]Columbia University / [171]kermit@columbia.edu / 14 March 2003
-
-References
-
-   1. http://www.columbia.edu/kermit/
-   2. http://www.columbia.edu/
-   3. http://www.columbia.edu/kermit/ckccfg.html
-   4. http://www.columbia.edu/kermit/ckermit.html
-   5. http://www.columbia.edu/kermit/index.html
-   6. http://www.columbia.edu/kermit/ckccfg.html#x1
-   7. http://www.columbia.edu/kermit/ckccfg.html#x2
-   8. http://www.columbia.edu/kermit/ckccfg.html#x3
-   9. http://www.columbia.edu/kermit/ckccfg.html#x4
-  10. http://www.columbia.edu/kermit/ckccfg.html#x5
-  11. http://www.columbia.edu/kermit/ckccfg.html#x6
-  12. http://www.columbia.edu/kermit/ckccfg.html#x7
-  13. http://www.columbia.edu/kermit/ckccfg.html#x8
-  14. http://www.columbia.edu/kermit/ckccfg.html#x9
-  15. http://www.columbia.edu/kermit/ckccfg.html#x10
-  16. http://www.columbia.edu/kermit/ckccfg.html#x11
-  17. http://www.columbia.edu/kermit/ckccfg.html#x12
-  18. http://www.columbia.edu/kermit/ckccfg.html#x13
-  19. http://www.columbia.edu/kermit/ckccfg.html#x14
-  20. http://www.columbia.edu/kermit/ckccfg.html#xa1
-  21. http://www.columbia.edu/kermit/ckuins.html
-  22. http://www.columbia.edu/kermit/ckermit.html
-  23. http://www.columbia.edu/kermit/index.html
-  24. http://www.columbia.edu/kermit/ckccfg.html#top
-  25. http://www.columbia.edu/kermit/ckccfg.html#contents
-  26. http://www.columbia.edu/kermit/ckccfg.html#x2
-  27. http://www.columbia.edu/kermit/ckccfg.html#x0
-  28. http://www.columbia.edu/kermit/ckermit.html
-  29. http://www.columbia.edu/kermit/index.html
-  30. http://www.columbia.edu/kermit/ckccfg.html#top
-  31. http://www.columbia.edu/kermit/ckccfg.html#contents
-  32. http://www.columbia.edu/kermit/ckccfg.html#x3
-  33. http://www.columbia.edu/kermit/ckccfg.html#x1
-  34. ftp://kermit.columbia.edu/kermit/c-kermit/ckutio.c
-  35. ftp://kermit.columbia.edu/kermit/c-kermit/ckcdeb.h
-  36. ftp://kermit.columbia.edu/kermit/c-kermit/ckuus3.c
-  37. ftp://kermit.columbia.edu/kermit/c-kermit/ckcdeb.h
-  38. ftp://kermit.columbia.edu/kermit/c-kermit/ckutio.c
-  39. ftp://kermit.columbia.edu/kermit/c-kermit/ckutio.c
-  40. http://www.columbia.edu/kermit/ckermit.html
-  41. http://www.columbia.edu/kermit/index.html
-  42. http://www.columbia.edu/kermit/ckccfg.html#top
-  43. http://www.columbia.edu/kermit/ckccfg.html#contents
-  44. http://www.columbia.edu/kermit/ckccfg.html#x4
-  45. http://www.columbia.edu/kermit/ckccfg.html#x2
-  46. ftp://kermit.columbia.edu/kermit/c-kermit/makefile
-  47. http://www.columbia.edu/kermit/ckuins.html
-  48. http://www.columbia.edu/kermit/ckuins.html#x4
-  49. http://www.columbia.edu/kermit/ckuins.html#x9.2
-  50. ftp://kermit.columbia.edu/kermit/c-kermit/ckuusx.c
-  51. ftp://kermit.columbia.edu/kermit/c-kermit/ckutio.c
-  52. ftp://kermit.columbia.edu/kermit/c-kermit/ckufio.c
-  53. ftp://kermit.columbia.edu/kermit/c-kermit/ckuusx.c
-  54. ftp://kermit.columbia.edu/kermit/c-kermit/ckucmd.c
-  55. http://www.columbia.edu/kermit/ckermit.html
-  56. http://www.columbia.edu/kermit/index.html
-  57. http://www.columbia.edu/kermit/ckccfg.html#top
-  58. http://www.columbia.edu/kermit/ckccfg.html#contents
-  59. http://www.columbia.edu/kermit/ckccfg.html#x5
-  60. http://www.columbia.edu/kermit/ckccfg.html#x3
-  61. http://www.columbia.edu/kermit/unicode.html
-  62. http://www.columbia.edu/kermit/ckermit.html
-  63. http://www.columbia.edu/kermit/index.html
-  64. http://www.columbia.edu/kermit/ckccfg.html#top
-  65. http://www.columbia.edu/kermit/ckccfg.html#contents
-  66. http://www.columbia.edu/kermit/ckccfg.html#x6
-  67. http://www.columbia.edu/kermit/ckccfg.html#x4
-  68. ftp://kermit.columbia.edu/kermit/c-kermit/ckuusr.h
-  69. ftp://kermit.columbia.edu/kermit/c-kermit/ckuusr.h
-  70. http://www.columbia.edu/kermit/ckermit.html
-  71. http://www.columbia.edu/kermit/index.html
-  72. http://www.columbia.edu/kermit/ckccfg.html#top
-  73. http://www.columbia.edu/kermit/ckccfg.html#contents
-  74. http://www.columbia.edu/kermit/ckccfg.html#x7
-  75. http://www.columbia.edu/kermit/ckccfg.html#x5
-  76. http://www.columbia.edu/kermit/ckccfg.html#x6.1
-  77. http://www.columbia.edu/kermit/ckccfg.html#x6.2
-  78. http://www.columbia.edu/kermit/ckccfg.html#x6.3
-  79. http://www.columbia.edu/kermit/ckccfg.html#x6.4
-  80. http://www.columbia.edu/kermit/ckccfg.html#x4
-  81. http://www.columbia.edu/kermit/gkermit.html
-  82. ftp://kermit.columbia.edu/kermit/c-kermit/ckuusr.h
-  83. ftp://kermit.columbia.edu/kermit/c-kermit/ckcker.h
-  84. ftp://kermit.columbia.edu/kermit/c-kermit/ckcdeb.h
-  85. http://www.columbia.edu/kermit/ckermit.html
-  86. http://www.columbia.edu/kermit/index.html
-  87. http://www.columbia.edu/kermit/ckccfg.html#top
-  88. http://www.columbia.edu/kermit/ckccfg.html#contents
-  89. http://www.columbia.edu/kermit/ckccfg.html#x8
-  90. http://www.columbia.edu/kermit/ckccfg.html#x6
-  91. ftp://kermit.columbia.edu/kermit/c-kermit/ckudia.c
-  92. http://www.columbia.edu/kermit/ckermit.html
-  93. http://www.columbia.edu/kermit/index.html
-  94. http://www.columbia.edu/kermit/ckccfg.html#top
-  95. http://www.columbia.edu/kermit/ckccfg.html#contents
-  96. http://www.columbia.edu/kermit/ckccfg.html#x9
-  97. http://www.columbia.edu/kermit/ckccfg.html#x7
-  98. http://www.columbia.edu/kermit/ckccfg.html#x8.1
-  99. http://www.columbia.edu/kermit/ckccfg.html#x8.2
- 100. http://www.columbia.edu/kermit/ckccfg.html#x8.3
- 101. http://www.columbia.edu/kermit/ckccfg.html#x8.1.1
- 102. http://www.columbia.edu/kermit/ckccfg.html#x8.1.2
- 103. http://www.columbia.edu/kermit/ckccfg.html#x8.1.3
- 104. http://www.columbia.edu/kermit/ckccfg.html#x8.1.4
- 105. http://www.columbia.edu/kermit/ckccfg.html#x8.1.5
- 106. http://www.columbia.edu/kermit/ckccfg.html#x8.1.6
- 107. ftp://kermit.columbia.edu/kermit/c-kermit/ckcnet.h
- 108. ftp://kermit.columbia.edu/kermit/c-kermit/ckctel.c
- 109. ftp://kermit.columbia.edu/kermit/c-kermit/ckctel.c
- 110. ftp://kermit.columbia.edu/kermit/c-kermit/ckctel.h
- 111. ftp://kermit.columbia.edu/kermit/c-kermit/ckcftp.c
- 112. http://www.columbia.edu/kermit/ckermit.html
- 113. ftp://kermit.columbia.edu/kermit/c-kermit/ckcnet.c
- 114. ftp://kermit.columbia.edu/kermit/c-kermit/ckcnet.h
- 115. ftp://kermit.columbia.edu/kermit/c-kermit/ckutio.c
- 116. http://www.columbia.edu/kermit/ckccfg.html#x11
- 117. mailto:kermit@columbia.edu
- 118. http://www.columbia.edu/kermit/ckermit.html
- 119. http://www.columbia.edu/kermit/index.html
- 120. http://www.columbia.edu/kermit/ckccfg.html#top
- 121. http://www.columbia.edu/kermit/ckccfg.html#contents
- 122. http://www.columbia.edu/kermit/ckccfg.html#x10
- 123. http://www.columbia.edu/kermit/ckccfg.html#x8
- 124. http://www.columbia.edu/kermit/ckermit.html
- 125. http://www.columbia.edu/kermit/index.html
- 126. http://www.columbia.edu/kermit/ckccfg.html#top
- 127. http://www.columbia.edu/kermit/ckccfg.html#contents
- 128. http://www.columbia.edu/kermit/ckccfg.html#x11
- 129. http://www.columbia.edu/kermit/ckccfg.html#x9
- 130. http://www.columbia.edu/kermit/ckuins.html#x11
- 131. http://www.columbia.edu/kermit/ckuins.html
- 132. http://www.columbia.edu/kermit/ckermit.html
- 133. http://www.columbia.edu/kermit/index.html
- 134. http://www.columbia.edu/kermit/ckccfg.html#top
- 135. http://www.columbia.edu/kermit/ckccfg.html#contents
- 136. http://www.columbia.edu/kermit/ckccfg.html#x12
- 137. http://www.columbia.edu/kermit/ckccfg.html#x10
- 138. ftp://kermit.columbia.edu/kermit/c-kermit/ckucns.c
- 139. ftp://kermit.columbia.edu/kermit/c-kermit/ckucon.c
- 140. http://www.columbia.edu/kermit/ckermit.html
- 141. http://www.columbia.edu/kermit/index.html
- 142. http://www.columbia.edu/kermit/ckccfg.html#top
- 143. http://www.columbia.edu/kermit/ckccfg.html#contents
- 144. http://www.columbia.edu/kermit/ckccfg.html#x13
- 145. http://www.columbia.edu/kermit/ckccfg.html#x11
- 146. http://www.columbia.edu/kermit/ckermit.html
- 147. http://www.columbia.edu/kermit/index.html
- 148. http://www.columbia.edu/kermit/ckccfg.html#top
- 149. http://www.columbia.edu/kermit/ckccfg.html#contents
- 150. http://www.columbia.edu/kermit/ckccfg.html#x14
- 151. http://www.columbia.edu/kermit/ckccfg.html#x12
- 152. ftp://kermit.columbia.edu/kermit/c-kermit/ckcdeb.h
- 153. http://www.columbia.edu/kermit/ckermit.html
- 154. http://www.columbia.edu/kermit/index.html
- 155. http://www.columbia.edu/kermit/ckccfg.html#top
- 156. http://www.columbia.edu/kermit/ckccfg.html#contents
- 157. http://www.columbia.edu/kermit/ckccfg.html#x13
- 158. http://www.columbia.edu/kermit/ckermit.html
- 159. http://www.columbia.edu/kermit/index.html
- 160. http://www.columbia.edu/kermit/ckccfg.html#top
- 161. http://www.columbia.edu/kermit/ckccfg.html#contents
- 162. ftp://kermit.columbia.edu/kermit/c-kermit/ckcdeb.h
- 163. ftp://kermit.columbia.edu/kermit/c-kermit/ckcnet.h
- 164. ftp://kermit.columbia.edu/kermit/c-kermit/ckcmai.c
- 165. http://www.columbia.edu/kermit/ckccfg.html#top
- 166. http://www.columbia.edu/kermit/ckccfg.html#contents
- 167. http://www.columbia.edu/kermit/ckermit.html
- 168. http://www.columbia.edu/kermit/index.html
- 169. http://www.columbia.edu/kermit/index.html
- 170. http://www.columbia.edu/
- 171. mailto:kermit@columbia.edu
index 31f9c55..34ff008 100644 (file)
--- a/ckcdeb.h
+++ b/ckcdeb.h
@@ -1,13 +1,13 @@
 /*  C K C D E B . H  */
 
 /*
-  Tue Apr  6 14:00:16 2004
+Mon Aug 23 09:22:05 2010
 
   NOTE TO CONTRIBUTORS: This file, and all the other C-Kermit files, must be
   compatible with C preprocessors that support only #ifdef, #else, #endif,
   #define, and #undef.  Please do not use #if, logical operators, or other
   later-model preprocessor features in any of the portable C-Kermit modules.
-  You can, of course, use these constructions in platform-specific modules 
+  You can, of course, use these constructions in platform-specific modules
   when you know they are supported.
 */
 
@@ -26,7 +26,7 @@
   Author: Frank da Cruz <fdc@columbia.edu>,
   Columbia University Academic Information Systems, New York City.
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2010,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
 /*
   Etymology: The name of this file means "C-Kermit Common-C-Language Debugging
   Header", because originally it contained only the formats (F000-F111) for
-  the debug() and tlog() functions.  Since then it has grown to inlcude all
+  the debug() and tlog() functions.  Since then it has grown to include all
   material required by all other C-Kermit modules, including the non-Kermit
-  specific ones.
+  specific ones.  In other words, this is the one header file that is
+  guaranteed to be included by all C-Kermit source modules.
 */
 
 #ifndef CKCDEB_H                       /* Don't include me more than once. */
 #endif /* ULONG */
 #endif /* OS2 */
 
-/* Structure definitions for Kermit file attributes */
-/* All strings come as pointer and length combinations */
-/* Empty string (or for numeric variables, -1) = unused attribute. */
-
-struct zstr {             /* string format */
-    int len;             /* length */
-    char *val;            /* value */
-};
-struct zattr {            /* Kermit File Attribute structure */
-    long lengthk;         /* (!) file length in K */
-    struct zstr type;     /* (") file type (text or binary) */
-    struct zstr date;     /* (#) file creation date yyyymmdd[ hh:mm[:ss]] */
-    struct zstr creator;  /* ($) file creator id */
-    struct zstr account;  /* (%) file account */
-    struct zstr area;     /* (&) area (e.g. directory) for file */
-    struct zstr password; /* (') password for area */
-    long blksize;         /* (() file blocksize */
-    struct zstr xaccess;  /* ()) file access: new, supersede, append, warn */
-    struct zstr encoding; /* (*) encoding (transfer syntax) */
-    struct zstr disp;     /* (+) disposition (mail, message, print, etc) */
-    struct zstr lprotect; /* (,) protection (local syntax) */
-    struct zstr gprotect; /* (-) protection (generic syntax) */
-    struct zstr systemid; /* (.) ID for system of origin */
-    struct zstr recfm;    /* (/) record format */
-    struct zstr sysparam; /* (0) system-dependent parameter string */
-    long length;          /* (1) exact length on system of origin */
-    struct zstr charset;  /* (2) transfer syntax character set */
-#ifdef OS2
-    struct zstr longname; /* OS/2 longname if applicable */
-#endif /* OS2 */
-    struct zstr reply;    /* This goes last, used for attribute reply */
-};
-
-/* Kermit file information structure */
-
-struct filinfo {
-  int bs;                              /* Blocksize */
-  int cs;                              /* Character set */
-  long rl;                             /* Record length */
-  int org;                             /* Organization */
-  int fmt;                             /* Record format */
-  int cc;                              /* Carriage control */
-  int typ;                             /* Type (text/binary) */
-  int dsp;                             /* Disposition */
-  char *os_specific;                   /* OS-specific attributes */
-#ifdef OS2
-  unsigned long int lblopts;           /* LABELED FILE options bitmask */
-#else
-  int lblopts;
-#endif /* OS2 */
-};
-
 #ifdef MACOSX10                                /* Mac OS X 1.0 */
 #ifndef MACOSX                         /* implies Mac OS X */
 #define MACOSX
@@ -150,6 +99,20 @@ struct filinfo {
 #endif /* ANYSCO */
 #endif /* UNIXWARE */
 
+#ifndef MINIX                          /* Minix versions */
+#ifdef MINIX315
+#define MINIX
+#else
+#ifdef MINIX3
+#define MINIX
+#else
+#ifdef MINIX2
+#define MINIX
+#endif /* MINIX2 */
+#endif /* MINIX3 */
+#endif /* MINIX315 */
+#endif /* MINIX */
+
 #ifdef CK_SCO32V4                      /* SCO 3.2v4 */
 #ifndef ANYSCO
 #define ANYSCO
@@ -194,6 +157,18 @@ struct filinfo {
 
 /* Built-in makefile entries */
 
+#ifdef SOLARIS11                       /* Solaris 11 implies 10 */
+#ifndef SOLARIS10
+#define SOLARIS10
+#endif /* SOLARIS10 */
+#endif /* SOLARIS11 */
+
+#ifdef SOLARIS10                       /* Solaris 10 implies 9 */
+#ifndef SOLARIS9
+#define SOLARIS9
+#endif /* SOLARIS9 */
+#endif /* SOLARIS10 */
+
 #ifdef SOLARIS9                                /* Solaris 9 implies 8 */
 #ifndef SOLARIS8
 #define SOLARIS8
@@ -242,6 +217,27 @@ struct filinfo {
 #define POSIX_CRTSCTS
 #endif /* POSIX_CRTSCTS */
 #endif /* POSIX */
+#ifndef SVR4
+#define SVR4
+#endif /* SVR4 */
+#ifndef STERMIOX
+#define STERMIOX
+#endif /* STERMIOX */
+#ifndef SELECT
+#define SELECT
+#endif /* SELECT */
+#ifndef FNFLOAT
+#define FNFLOAT
+#endif /* FNFLOAT */
+#ifndef DIRENT
+#define DIRENT
+#endif /* DIRENT */
+#ifndef BIGBUFOK
+#define BIGBUFOK
+#endif /* BIGBUFOK */
+#ifndef CK_NEWTERM
+#define CK_NEWTERM
+#endif /* CK_NEWTERM */
 #endif /* SOLARIS */
 
 #ifdef SUN4S5                          /* Sun-4 System V environment */
@@ -672,6 +668,11 @@ struct filinfo {
 #include <stdio.h>                     /* Begin by including this. */
 #include <ctype.h>                     /* and this. */
 
+#ifdef VMS
+#include <types.h>                     /* Ensure off_t. */
+#include "ckvrms.h"                    /* Get NAMDEF NAMX_C_MAXRSS. */
+#endif /* def VMS */
+
 /* System-type compilation switches */
 
 #ifdef FT21                            /* Fortune For:Pro 2.1 implies 1.8 */
@@ -1148,10 +1149,10 @@ struct filinfo {
 #endif /* OSKORUNIX */
 
 #ifdef OS2
-#define CK_ANSIC            /* OS/2 supports ANSIC and more extensions */
+#define CK_ANSIC                /* OS/2 supports ANSIC and more extensions */
 #endif /* OS2 */
 
-#ifdef OSF50               /* Newer OSF/1 versions imply older ones */
+#ifdef OSF50                      /* Newer OSF/1 versions imply older ones */
 #ifndef OSF40
 #define OSF40
 #endif /* OSF40 */
@@ -1429,15 +1430,40 @@ _PROTOTYP(int ckxfprintf,(FILE *, const char *, ...));
 #endif /* CK_POSIX_SIG */
 #endif /* QNX */
 
-/* Void type */
-
+/* 
+  void type, normally available only in ANSI compilers.
+  The HP-UX exception (for its "bundled" non-ANSI C compiler)
+  is known to be valid back to HP-UX 6.5.
+  Adjustments might be needed for earlier HP-UX versions.
+*/
 #ifndef VOID                           /* Used throughout all C-Kermit */
 #ifdef CK_ANSIC                                /* modules... */
 #define VOID void
 #else
+#ifdef HPUX
+#define VOID void
+#else
 #define VOID int
+#endif /* HPUX */
 #endif /* CK_ANSIC */
 #endif /* VOID */
+/*
+  Exactly the same as VOID but for use in contexts where the VOID symbol
+  conflicts some header-file definition.  This is needed for the section
+  of ckuusx.c that provides C-Kermit's curses interface, roughly the
+  second half of ckuusx.c.
+*/
+#ifndef CKVOID
+#ifdef CK_ANSIC
+#define CKVOID void
+#else
+#ifdef HPUX
+#define CKVOID void
+#else
+#define CKVOID int
+#endif /* HPUX */
+#endif /* CK_ANSIC */
+#endif /* CKVOID */
 
 /* Const type */
 
@@ -1975,18 +2001,6 @@ _PROTOTYP( void bleep, (short) );
 #endif /* TLOG */
 #endif /* NOICP */
 
-#ifndef TLOG
-#define tlog(a,b,c,d)
-#else
-#ifndef CKCMAI
-/* Debugging included.  Declare debug log flag in main program only. */
-extern int tralog, tlogfmt;
-#endif /* CKCMAI */
-_PROTOTYP(VOID dotlog,(int, char *, char *, long));
-#define tlog(a,b,c,d) if (tralog && tlogfmt) dotlog(a,b,c,d)
-_PROTOTYP(VOID doxlog,(int, char *, long, int, int, char *));
-#endif /* TLOG */
-
 /* Formats for debug() and tlog() */
 
 #define F000 0
@@ -2141,14 +2155,43 @@ _PROTOTYP(VOID doxlog,(int, char *, long, int, int, char *));
 #ifdef USE_UU_LOCK                     /* FreeBSD or other with uu_lock() */
 #define USETTYLOCK
 #else
-#ifdef HAVE_BAUDBOY                    /* Red Hat Linux >= 7.2 */
+/*
+  Prior to 8.0.299 Alpha.08 this was HAVE_BAUDBOY which was added for
+  Red Hat 7.2 in May 2003 but which is no longer supported in Debian and
+  OpenSuse (at least).
+*/
+#ifdef HAVE_LOCKDEV
 #define USETTYLOCK
-#endif /* HAVE_BAUDBOY */
+#endif /* HAVE_LOCKDEV */
 #endif /* USE_UU_LOCK */
 #endif /* AIXRS */
 #endif /* USETTYLOCK */
 #endif /* NOTTYLOCK */
 
+#ifndef NO_OPENPTY                     /* Can use openpty() */
+#ifndef HAVE_OPENPTY
+#ifdef __linux__
+#define HAVE_OPENPTY
+#else
+#ifdef __FreeBSD__
+#define HAVE_OPENPTY
+#else
+#ifdef __OpenBSD__
+#define HAVE_OPENPTY
+#else
+#ifdef __NetBSD__
+#define HAVE_OPENPTY
+#else
+#ifdef MACOSX10
+#define HAVE_OPENPTY
+#endif /* MACOSX10 */
+#endif /* __NetBSD__ */
+#endif /* __OpenBSD__ */
+#endif /* __FreeBSD__ */
+#endif /* __linux__ */
+#endif /* HAVE_OPENPTY */
+#endif /* NO_OPENPTY */
+
 /* Kermit feature selection */
 
 #ifndef NOSPL
@@ -2454,7 +2497,7 @@ _PROTOTYP(VOID doxlog,(int, char *, long, int, int, char *));
 extern long ztmsec, ztusec;            /* Fraction of sec of current time */
 #endif /* CKCMAI */
 
-#ifndef NOUNPREFIXZERO                 /* Allow unprefixing of  NUL (0) */
+#ifndef NOUNPREFIXZERO                 /* Allow unprefixing of NUL (0) */
 #ifndef UNPREFIXZERO                   /* in file-transfer packets */
 #define UNPREFIXZERO
 #endif /* UNPREFIXZERO */
@@ -2605,10 +2648,19 @@ extern long ztmsec, ztusec;             /* Fraction of sec of current time */
 #define CKHTTP
 #endif /* mips */
 #endif /* ultrix */
+#ifdef __NetBSD__                      /* NetBSD */
+#define CKHTTP
+#endif /* __NetBSD__ */
+#ifdef __FreeBSD__
+#define CKHTTP
+#endif /* __FreeBSD__ */
+#ifdef __OpenBSD__
+#define CKHTTP
+#endif /* __OpenBSD__ */
 /* Add more here... */
 #endif /* CKHTTP */
 #ifndef CKHTTP                         /* If CKHTTP not defined yet */
-#define NOHTTP                         /* then define HOHTTP */
+#define NOHTTP                         /* then define NOHTTP */
 #endif /* CKHTTP */
 #endif /* NOHTTP */
 
@@ -3332,6 +3384,7 @@ _PROTOTYP( int ttruncmd, (char *) );
 #endif /* CK_TTGWSIZ */
 #endif /* NOTTGWSIZ */
 
+#ifdef OS2
 /* OS/2 C-Kermit features not available in 16-bit version... */
 
 #ifdef OS2ONLY
@@ -3361,14 +3414,10 @@ _PROTOTYP( int ttruncmd, (char *) );
 
 /* OS/2 C-Kermit features not available in Windows NT version... */
 
-#ifdef OS2
 #ifdef NT
 #ifdef PCFONTS                         /* PC Font support */
 #undef PCFONTS
 #endif /* PCFONTS */
-#ifdef NPIPE                           /* Named Pipes communication */
-#undef NPIPE
-#endif /* NPIPE */
 #ifdef OS2PM                           /* Presentation Manager */
 #undef OS2PM
 #endif /* OS2PM */
@@ -4479,15 +4528,23 @@ extern int errno;
 #else
 /*
   The following declaration would cause problems for VMS and OS/2, in which
-  errno is an "extern volatile int noshare"...
+  errno is an "extern volatile int noshare"...  NOTE: by now (2007) the
+  following is an anachronism and should be the execption rather than the
+  rule.
 */
- extern int errno;                     /* Needed by most modules. */
+extern int errno;
 #endif /* __GLIBC__ */
 #endif /* OS2 */
 #endif /* VMS */
 #endif /* STRATUS */
 #endif /* _CRAY */
 
+#ifdef UNIX                            /* Catch-all so we can have */
+#ifndef ESRCH                          /* access to error mnemonics */
+#include <errno.h>                     /* in all modules - 2007/08/25 */
+#endif /* ESRCH */
+#endif /* UNIX */
+
 #ifdef pdp11                           /* Try to make some space on PDP-11 */
 #ifndef NODIAL
 #define NODIAL
@@ -4611,35 +4668,6 @@ extern int errno;
 #endif /* BIGBUFOK */
 #endif /* DEBUG */
 
-#ifndef DEBUG
-/* Compile all the debug() statements away.  Saves a lot of space and time. */
-#define debug(a,b,c,d)
-#define hexdump(a,b,c)
-/* Now define the debug() macro. */
-#else /* DEBUG */
-_PROTOTYP(int dodebug,(int,char *,char *,long));
-_PROTOTYP(int dohexdump,(CHAR *,CHAR *,int));
-#ifdef IFDEBUG
-/* Use this form to avoid function calls: */
-#ifdef COMMENT
-#define debug(a,b,c,d) if (deblog) dodebug(a,b,(char *)(c),(long)d)
-#define hexdump(a,b,c) if (deblog) dohexdump((CHAR *)(a),(CHAR *)(b),c)
-#else
-#ifdef CK_ANSIC
-#define debug(a,b,c,d) ((void)(deblog?dodebug(a,b,(char *)(c),(long)d):0))
-#define hexdump(a,b,c) ((void)(deblog?dohexdump((CHAR *)(a),(CHAR *)(b),c):0))
-#else
-#define debug(a,b,c,d) (deblog?dodebug(a,b,(char *)(c),(long)d):0)
-#define hexdump(a,b,c) (deblog?dohexdump((CHAR *)(a),(CHAR *)(b),c):0)
-#endif /* CK_ANSIC */
-#endif /* COMMENT */
-#else /* IFDEBUG */
-/* Use this form to save space: */
-#define debug(a,b,c,d) dodebug(a,b,(char *)(c),(long)d)
-#define hexdump(a,b,c) dohexdump((CHAR *)(a),(CHAR *)(b),c)
-#endif /* IFDEBUG */
-#endif /* DEBUG */
-
 /* File System Defaults */
 
 #ifndef UIDBUFLEN                      /* Length of User ID */
@@ -4972,6 +5000,203 @@ typedef unsigned int u_int;
 #endif /* STRATUS */                   /* End of types.h section */
 
 /*
+  File lengths and offsets.  This section is expected to grow as we
+  support long files on 32-bit platforms.  We want this data type to be
+  signed because so many functions return either a file size or a negative
+  value to indicate an error.
+*/
+#ifndef CK_OFF_T
+#ifdef OS2
+#ifdef NT
+#define CK_OFF_T __int64
+#else
+#define CK_OFF_T long
+#endif  /* NT */
+#endif /* OS2 */
+#endif /* CK_OFF_T */
+
+/* FreeBSD and OpenBSD set off_t to the appropriate size unconditionally */
+
+#ifndef CK_OFF_T
+#ifdef __FreeBSD__
+#define CK_OFF_T off_t
+#else
+#ifdef __OpenBSD__
+#define CK_OFF_T off_t
+#endif /* __OpenBSD__ */
+#endif /* __FreeBSD__ */
+#endif /* CK_OFF_T */
+
+/* 32-bit platforms that support long files thru "transitional interface" */
+/* These include Linux, Solaris, NetBSD... */
+
+#ifdef AIXRS
+#ifdef _LARGE_FILES
+#ifndef CK_OFF_T
+#define CK_OFF_T off_t
+#endif /* CK_OFF_T */
+#endif /* _LARGE_FILES */
+#endif /* AIXRS */
+
+#ifdef _LARGEFILE_SOURCE
+#ifndef CK_OFF_T
+#define CK_OFF_T off_t
+#endif /* CK_OFF_T */
+#ifdef IRIX
+#define CKFSEEK(a,b,c) fseek64(a,b,c)
+#define CKFTELL(a) ftell64(a)
+#else /* IRIX */
+#define CKFSEEK(a,b,c) fseeko(a,b,c)
+#define CKFTELL(a) ftello(a)
+#endif /* IRIX */
+#else  /* Not  _LARGEFILE_SOURCE */
+#define CKFSEEK(a,b,c) fseek(a,b,c)
+#define CKFTELL(a) ftell(a)
+/* See below the next section for the catch-all case */
+#endif /* _LARGEFILE_SOURCE */
+
+/* 32-bit or 64-bit platforms */
+
+/* CK_64BIT is a compile-time symbol indicating a true 64-bit build */
+/* meaning that longs and pointers are 64 bits */
+
+#ifndef VMS                            /* VMS Alpha and IA64 are 32-bit! */
+#ifndef CK_64BIT
+#ifdef _LP64                           /* Solaris */
+#define CK_64BIT
+#else
+#ifdef __LP64__                                /* MacOS X 10.4 (or _LP64,__ppc64__) */
+#define CK_64BIT
+#else
+#ifdef __arch64__                      /* gcc alpha, sparc */
+#define CK_64BIT
+#else
+#ifdef __alpha                         /* Alpha decc (or __ALPHA) */
+#define CK_64BIT
+#else
+#ifdef __amd64                         /* AMD x86_64 (or __x86_64) */
+#define CK_64BIT
+#else
+#ifdef __ia64                          /* Intel IA64 */
+#ifndef HPUX
+#define CK_64BIT
+#endif /* HPUX */
+#endif /* __ia64 */
+#endif /* __amd64 */
+#endif /* __alpha */
+#endif /* __arch64__ */
+#endif /* __LP64__ */
+#endif /* _LP64 */
+#endif /* CK_64BIT */
+#endif /* VMS */
+
+#ifndef CK_OFF_T
+#ifdef CK_64BIT
+#define CK_OFF_T off_t                 /* This has to be signed */
+#else  /* CK_64BIT */
+#define CK_OFF_T long                  /* Signed */
+#endif /* CK_64BIT */
+#endif /* CK_OFF_T */
+
+#ifndef TLOG
+#define tlog(a,b,c,d)
+#else
+#ifndef CKCMAI
+/* Debugging included.  Declare debug log flag in main program only. */
+extern int tralog, tlogfmt;
+#endif /* CKCMAI */
+_PROTOTYP(VOID dotlog,(int, char *, char *, CK_OFF_T));
+#define tlog(a,b,c,d) if (tralog && tlogfmt) dotlog(a,b,c,(CK_OFF_T)d)
+_PROTOTYP(VOID doxlog,(int, char *, CK_OFF_T, int, int, char *));
+#endif /* TLOG */
+
+#ifndef DEBUG
+/* Compile all the debug() statements away.  Saves a lot of space and time. */
+#define debug(a,b,c,d)
+#define ckhexdump(a,b,c)
+/* Now define the debug() macro. */
+#else /* DEBUG */
+_PROTOTYP(int dodebug,(int,char *,char *,CK_OFF_T));
+_PROTOTYP(int dohexdump,(CHAR *,CHAR *,int));
+#ifdef IFDEBUG
+/* Use this form to avoid function calls: */
+#ifdef COMMENT
+#define debug(a,b,c,d) if (deblog) dodebug(a,b,(char *)(c),(CK_OFF_T)(d))
+#define ckhexdump(a,b,c) if (deblog) dohexdump((CHAR *)(a),(CHAR *)(b),c)
+#else
+#ifdef CK_ANSIC
+#define debug(a,b,c,d) \
+((void)(deblog?dodebug(a,b,(char *)(c),(CK_OFF_T)(d)):0))
+#define ckhexdump(a,b,c) \
+((void)(deblog?dohexdump((CHAR *)(a),(CHAR *)(b),c):0))
+#else
+#define debug(a,b,c,d) (deblog?dodebug(a,b,(char *)(c),(CK_OFF_T)(d)):0)
+#define ckhexdump(a,b,c) (deblog?dohexdump((CHAR *)(a),(CHAR *)(b),c):0)
+#endif /* CK_ANSIC */
+#endif /* COMMENT */
+#else /* IFDEBUG */
+/* Use this form to save space: */
+#define debug(a,b,c,d) dodebug(a,b,(char *)(c),(CK_OFF_T)(d))
+#define ckhexdump(a,b,c) dohexdump((CHAR *)(a),(CHAR *)(b),c)
+#endif /* IFDEBUG */
+#endif /* DEBUG */
+
+
+/* Structure definitions for Kermit file attributes */
+/* All strings come as pointer and length combinations */
+/* Empty string (or for numeric variables, -1) = unused attribute. */
+
+struct zstr {             /* string format */
+    int len;             /* length */
+    char *val;            /* value */
+};
+
+struct zattr {            /* Kermit File Attribute structure */
+    CK_OFF_T lengthk;    /* (!) file length in K */
+    struct zstr type;     /* (") file type (text or binary) */
+    struct zstr date;     /* (#) file creation date yyyymmdd[ hh:mm[:ss]] */
+    struct zstr creator;  /* ($) file creator id */
+    struct zstr account;  /* (%) file account */
+    struct zstr area;     /* (&) area (e.g. directory) for file */
+    struct zstr password; /* (') password for area */
+    long blksize;         /* (() file blocksize */
+    struct zstr xaccess;  /* ()) file access: new, supersede, append, warn */
+    struct zstr encoding; /* (*) encoding (transfer syntax) */
+    struct zstr disp;     /* (+) disposition (mail, message, print, etc) */
+    struct zstr lprotect; /* (,) protection (local syntax) */
+    struct zstr gprotect; /* (-) protection (generic syntax) */
+    struct zstr systemid; /* (.) ID for system of origin */
+    struct zstr recfm;    /* (/) record format */
+    struct zstr sysparam; /* (0) system-dependent parameter string */
+    CK_OFF_T length;      /* (1) exact length on system of origin */
+    struct zstr charset;  /* (2) transfer syntax character set */
+#ifdef OS2
+    struct zstr longname; /* OS/2 longname if applicable */
+#endif /* OS2 */
+    struct zstr reply;    /* This goes last, used for attribute reply */
+};
+
+/* Kermit file information structure */
+
+struct filinfo {
+  int bs;                              /* Blocksize */
+  int cs;                              /* Character set */
+  long rl;                             /* Record length */
+  int org;                             /* Organization */
+  int fmt;                             /* Record format */
+  int cc;                              /* Carriage control */
+  int typ;                             /* Type (text/binary) */
+  int dsp;                             /* Disposition */
+  char *os_specific;                   /* OS-specific attributes */
+#ifdef OS2
+  unsigned long int lblopts;           /* LABELED FILE options bitmask */
+#else
+  int lblopts;
+#endif /* OS2 */
+};
+
+
+/*
   Data type for pids.  If your system uses a different type, put something
   like -DPID_T=pid_t on command line, or override here.
 */
@@ -5113,12 +5338,12 @@ _PROTOTYP( int zchkpid, (unsigned long) );
 _PROTOTYP( VOID z_exec, (char *, char **, int) );
 #endif /* CKEXEC */
 _PROTOTYP( int chkfn, (int) );
-_PROTOTYP( long zchki, (char *) );
+_PROTOTYP( CK_OFF_T zchki, (char *) );
 #ifdef VMSORUNIX
-_PROTOTYP( long zgetfs, (char *) );
+_PROTOTYP( CK_OFF_T zgetfs, (char *) );
 #else
 #ifdef OS2
-_PROTOTYP( long zgetfs, (char *) );
+_PROTOTYP( CK_OFF_T zgetfs, (char *) );
 #else
 #define zgetfs(a) zchki(a)
 #endif /* OS2 */
@@ -5149,7 +5374,7 @@ _PROTOTYP( int znext, (char *) );
 #ifdef ZXREWIND
 _PROTOTYP( int zxrewind, (void) );
 #endif /* ZXREWIND */
-_PROTOTYP( int zchkspa, (char *, long) );
+_PROTOTYP( int zchkspa, (char *, CK_OFF_T) );
 _PROTOTYP( VOID znewn, (char *, char **) );
 _PROTOTYP( int zrename, (char *, char *) );
 _PROTOTYP( int zcopy, (char *, char *) );
@@ -5165,7 +5390,7 @@ _PROTOTYP( int zmail, (char *, char *) );
 _PROTOTYP( int zprint, (char *, char *) );
 _PROTOTYP( char * tilde_expand, (char *) );
 _PROTOTYP( int zmkdir, (char *) ) ;
-_PROTOTYP( int zfseek, (long) ) ;
+_PROTOTYP( int zfseek, (CK_OFF_T) ) ;
 #ifdef ZFNQFP
 _PROTOTYP( struct zfnfp * zfnqfp, (char *, int, char * ) ) ;
 #else
@@ -5685,7 +5910,9 @@ extern int _flsbuf(char c,FILE *stream);
   and pause.  Otherwise, no prototypes.
 */
 #ifdef VMS
+#include <signal.h>  /* SMS: sleep() for old (V4.0-000) DEC C. */
 #include <unixio.h>
+#include <unixlib.h> /* SMS: getpid() for old (V4.0-000) DEC C. */
 #endif /* VMS */
 
 #ifdef NEXT
@@ -5783,6 +6010,12 @@ _PROTOTYP( long atol, (char *) );
 /* or #define NULL ((void *) 0) */
 #endif /* NULL */
 
+/* Macro to differentiate "" from NULL (to avoid comparisons with literals) */
+
+#ifndef isemptystring
+#define isemptystring(s) ((s?(*s?0:1):0))
+#endif /* isemptystring */
+
 /* Maximum length for a fully qualified filename, not counting \0 at end. */
 /*
   This is a rough cut, and errs on the side of being too big.  We don't
@@ -5790,40 +6023,40 @@ _PROTOTYP( long atol, (char *) );
   symbols, for fear of introducing unnecessary conflicts.
 */
 #ifndef CKMAXPATH
+#ifdef VMS                             /* VMS may have bad (small, ODS2) */
+#define CKMAXPATH NAMX_C_MAXRSS                /* PATH_MAX, so use NAMX_C_MAXRSS. */
+#else /* def VMS */
 #ifdef MAXPATHLEN                      /* (it probably isn't) */
 #define CKMAXPATH MAXPATHLEN
 #else
 #ifdef PATH_MAX                                /* POSIX */
 #define CKMAXPATH PATH_MAX
-#else
+#else /* def PATH_MAX */
 #ifdef MAC
 #define CKMAXPATH 63
-#else
+#else /* def MAC */
 #ifdef pdp11
 #define CKMAXPATH 255
-#else
+#else /* def pdp11 */
 #ifdef UNIX                            /* Even though some are way less... */
 #define CKMAXPATH 1024
-#else
-#ifdef VMS
-#define CKMAXPATH 675                  /* (derivation is complicated...) */
-#else
+#else /* def UNIX */
 #ifdef STRATUS
 #define CKMAXPATH 256                  /* == $MXPL from PARU.H */
-#else
+#else /* def STRATUS */
 #ifdef datageneral
 #define CKMAXPATH 256                  /* == $MXPL from PARU.H */
-#else
+#else /* def datageneral */
 #define CKMAXPATH 255
-#endif /* STRATUS */
-#endif /* datageneral */
-#endif /* VMS */
-#endif /* UNIX */
-#endif /* pdp11 */
-#endif /* MAC */
-#endif /* PATH_MAX */
-#endif /* MAXPATHLEN */
-#endif /* CKMAXPATH */
+#endif /* def STRATUS [else] */
+#endif /* def datageneral [else] */
+#endif /* def UNIX [else] */
+#endif /* def pdp11 [else] */
+#endif /* def MAC [else] */
+#endif /* def PATH_MAX [else] */
+#endif /* def MAXPATHLEN [else] */
+#endif /* def VMS [else] */
+#endif /* ndef CKMAXPATH */
 
 /* Maximum length for the name of a tty device */
 
@@ -6275,8 +6508,12 @@ struct keytab {                          /* Keyword table */
 };
 #endif /* CK_KEYTAB */
 
+#ifdef UNIX
+_PROTOTYP( int isalink, (char *));
+#endif /* UNIX */
+
 #ifdef NETPTY
-_PROTOTYP( int do_pty, (char *));
+_PROTOTYP( int do_pty, (int *, char *, int));
 _PROTOTYP( VOID end_pty, (void));
 #endif /* NETPTY */
 
@@ -6363,6 +6600,7 @@ _PROTOTYP(DWORD ckGetLongPathname,(LPCSTR lpFileName,
                                    LPSTR lpBuffer, DWORD cchBuffer));
 #endif /* NT */
 
+
 #include "ckclib.h"
 
 /* End of ckcdeb.h */
index 06b97a2..5fa0507 100644 (file)
--- a/ckcfn2.c
+++ b/ckcfn2.c
@@ -6,7 +6,7 @@
   Author: Frank da Cruz <fdc@columbia.edu>,
   Columbia University Academic Information Systems, New York City.
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2011,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -219,8 +219,8 @@ extern int autopar;
 
 extern int spsiz, spmax, rpsiz, timint, timef, npad, bestlen, maxsend;
 extern int rpt, rptq, rptflg, capas, spsizf, en_fin, tsecs, flow;
-extern int pktnum, sndtyp, rcvtyp, bctr, bctu, bctl, rsn, rln, maxtry, size;
-extern int osize, maxsize, spktl, rpktl, nfils, stdouf, fsecs;
+extern int pktnum, sndtyp, rcvtyp, bctr, bctu, bctf, bctl, rsn, rln, maxtry;
+extern int size, osize, maxsize, spktl, rpktl, nfils, stdouf, fsecs;
 extern int turn, turnch, displa, pktlog, seslog, xflg, mypadn;
 extern int hcflg, server, cxseen, czseen, discard, slostart;
 extern int nakstate, quiet, success, xitsta, what, filestatus;
@@ -231,8 +231,8 @@ extern int carrier, fdispla, srvidl;
 extern CKFLOAT fptsecs, fpfsecs, fpxfsecs;
 #endif /* GFTIMER */
 
-extern long filcnt, filrej, ffc, flci, flco, tlci, tlco, tfc, speed;
-extern long filcps, tfcps;
+extern long filcnt, filrej, speed, filcps, tfcps;
+extern CK_OFF_T ffc, flci, flco, tlci, tlco, tfc;
 
 extern char *cmarg, filnam[];
 
@@ -696,6 +696,8 @@ input() {
 #ifdef CK_TIMERS
                if (rttflg && timint)   /* Dynamic round trip timers? */
                  getrtt(nakstate, rsn); /* yes, do it. */
+                else                     /* JHD 20100208 */
+                  rcvtimo = timint;      /* JHD 20100208 */
 #endif /* CK_TIMERS */
                debug(F101,"input rsn=winlo","",rsn);
                break;
@@ -984,6 +986,8 @@ input() {
 #ifdef CK_TIMERS
                    if (rttflg && timint) /* If doing dynamic timers */
                      getrtt(nakstate, rsn); /* call routine to set it. */
+                   else                     /* JHD 20100208 */
+                     rcvtimo = timint;      /* JHD 20100208 */
 #endif /* CK_TIMERS */
 /*
   NOTE: The following statement frees the buffer of the ACK we just got.
@@ -1102,6 +1106,11 @@ input() {
   would cause needless cycles of repeated packets.  Therefore we flush the
   communications input buffer now to try to get rid of undesired and unneeded
   packets that we have not read yet.
+
+  Actually, the first sentence above is not entirely true: there could be an
+  Error packet waiting to be read.  Flushing an E packet is bad because it
+  will not be resent, and we'll go into a cycle of timing out and
+  retransmitting up to the retry limit.  - fdc 2007/03/02
 */
     if (wslotn == 1                    /* (not wslots!) */
 #ifdef STREAMING
@@ -1283,10 +1292,12 @@ spack(pkttyp,n,len,d) char pkttyp; int n, len; CHAR *d;
 #ifdef DEBUG
     if (deblog) {                      /* Save lots of function calls! */
        debug(F101,"spack n","",n);
+#ifdef COMMENT
        if (pkttyp != 'D') {            /* Data packets would be too long */
            debug(F111,"spack data",data,data);
            debug(F111,"spack d",d,d);
        }
+#endif /* COMMENT */
        debug(F101,"spack len","",len);
        debug(F101,"spack copy","",copy);
     }
@@ -1295,6 +1306,7 @@ spack(pkttyp,n,len,d) char pkttyp; int n, len; CHAR *d;
     longpkt = (len + bctl + 2) > 94;   /* Decide whether it's a long packet */
     mydata = data - 7 + (longpkt ? 0 : 3); /* Starting position of header */
     k = sseqtbl[n];                    /* Packet structure info for pkt n */
+#ifdef COMMENT
 #ifdef DEBUG
     if (deblog) {                      /* Save 2 more function calls... */
        debug(F101,"spack mydata","",mydata);
@@ -1307,6 +1319,7 @@ spack(pkttyp,n,len,d) char pkttyp; int n, len; CHAR *d;
        }
     }
 #endif /* DEBUG */
+#endif /* COMMENT */
     if (k > -1) {
        s_pkt[k].pk_adr = mydata;       /* Remember address of packet. */
        s_pkt[k].pk_seq = n;            /* Record sequence number */
@@ -1812,7 +1825,7 @@ rcalcpsz() {
       x = (long) (npad+5+3+bctr+5+bctr); /* count packet and ack. */
 
     /* then set x = packet length ** 2 */
-    x = x * ( ffc / (long) numerrs);   /* careful of overflow */
+    x = x * ( ffc / (CK_OFF_T) numerrs); /* careful of overflow */
 
     /* calculate the long integer sqrt(x) quickly */
     q = 500;
@@ -1878,18 +1891,24 @@ resend(n) int n; {                      /* Send packet n again. */
   operation (spackets < 63), then we have to resend the ACK to an I or S
   packet, complete with parameters in the data field.  So we take a chance and
   send a copy of the parameters in an ACK packet with block check type 1.
+  (Or 3 if SET BLOCK 5.)
 */
-               int bctlsav;            /* Temporary storage */
-               int bctusav;
-               bctlsav = bctl;         /* Save current block check length */
-               bctusav = bctu;         /* and type */
-               bctu = bctl = 1;        /* Set block check to 1 */
-               x = spack('Y',0,(int)strlen((char *)myinit),(CHAR *)myinit);
-               if (x < 0) return(x);
-               logpkt('#',n,(CHAR *)"<reconstructed>",0); /* Log it */
-               bctu = bctusav;         /* Restore block check type */
-               bctl = bctlsav;         /* and length */
-
+               if (bctf) {             /* Force Type 3 on all packets? */
+                  x = spack('Y',0,(int)strlen((char *)myinit),(CHAR *)myinit);
+                   if (x < 0) return(x);
+                   logpkt('#',n,(CHAR *)"<reconstructed>",0); /* Log it */
+               } else {                /* Regular Kermit protocol */
+                   int bctlsav;        /* Temporary storage */
+                   int bctusav;
+                   bctlsav = bctl;     /* Save current block check length */
+                   bctusav = bctu;     /* and type */
+                   bctu = bctl = 1;    /* Set block check to 1 */
+                  x = spack('Y',0,(int)strlen((char *)myinit),(CHAR *)myinit);
+                   if (x < 0) return(x);
+                   logpkt('#',n,(CHAR *)"<reconstructed>",0); /* Log it */
+                   bctu = bctusav;     /* Restore block check type */
+                   bctl = bctlsav;     /* and length */
+               }
            } else {                    /* Not the first packet */
 /*
   It's not the first packet of the protocol operation.  It's some other packet
@@ -2638,16 +2657,22 @@ autodown(ch) int ch;
 /*  C H K S P K T  --  Check if buf contains a valid S or I packet  */
 
 int
-chkspkt(buf) char *buf; {
+chkspkt(packet) char *packet; {
+    int i;
     int buflen;
     int len = -1;
     CHAR chk;
     char type = 0;
-    char *s = buf;
+    char *s = NULL;
+    char *buf = NULL;
+    char tmpbuf[100];                  /* Longest S/I packet is about 30 */
 
-    if (!buf) return(0);
-    buflen = strlen(buf);
+    if (!packet) return(0);
+    buflen = ckstrncpy(tmpbuf,packet,100); /* Make a pokeable copy */
     if (buflen < 5) return(0);         /* Too short */
+    if (buflen > 100) return(0);       /* Too long to be an S or I packet */
+    s = buf = tmpbuf;                  /* Point to beginning of copy */
+
     if (*s++ != stchr) return(0);      /* SOH */
     len = xunchar(*s++);               /* Length */
     if (len < 0) return(0);
@@ -2658,10 +2683,23 @@ chkspkt(buf) char *buf; {
     if (buflen < len + 2) return(0);
     s += (len - 3);                    /* Position of checksum */
     chk = (CHAR) (*s);                 /* Checksum */
-    *s = NUL;
-    if (xunchar(chk) != chk1((CHAR *)(buf+1),buflen-2)) /* Check it */
-      return(0);
-    *s = chk;
+    *s = NUL;                     /* Temporarily null-terminate data field */
+    if (xunchar(chk) != chk1((CHAR *)(buf+1),buflen-2)) { /* Check it */
+       /*
+         In C-Kermit 9.0 and later, an S or I packet can have a 
+         Type 3 Block check ("help set block-check" for details).
+       */
+       unsigned crc;                   /* Failed... Try Type 3 block check */
+       *s = chk;                       /* Replace last byte */
+       s -= 2;                         /* Back up two bytes */
+       crc = (xunchar(s[0]) << 12)     /* Convert 3 bytes to numeric CRC */
+           | (xunchar(s[1]) << 6)
+           | (xunchar(s[2]));
+       chk = (CHAR)(*s);               /* Copy 1st byte of 3-byte CRC */
+       *s = NUL;                       /* Null-terminate data field */
+       if (crc != chk3((CHAR *)(buf+1),strlen(buf+1)))
+         return(0);
+    }
     return(type == 'S' ? 1 : 2);
 }
 #endif /* CK_AUTODL */
@@ -2729,7 +2767,7 @@ rpack() {
        x = parchk(recpkt, stchr, j);   /* Check parity */
        debug(F000,"autodownload parity","",parity);
        debug(F000,"autodownload parchk","",x);
-       if (x > -1 && parity != x) {
+       if (x > 0 && parity != x) {
            autopar = 1;
            parity = x;
        }
@@ -2943,13 +2981,30 @@ rpack() {
     }
 /*
   Separate the data from the block check, accounting for the case where
-  a packet was retransmitted after the block check switched.
+  a packet was retransmitted after the block check switched.  The "Type 3
+  Forced" business is new to C-Kermit 9.0.
 */
-    if (type == 'I' || type == 'S') {  /* I & S packets always have type 1 */
-       chklen = 1;
-       rln = rln + bctl - 1;
+    if (bctf) {                        /* Type 3 forced on all packets */
+       bctl = chklen = 3;
+    } else if ((type == 'I' || type == 'S')) { /* Otherwise... */
+       if (recpkt[11] == '5') {        /* Sender is forcing Type 3 */
+           bctf = 1;                   /* So we will too */
+           bctl = chklen = 3;
+           debug(F100,"RECOGNIZE BLOCK CHECK TYPE 5","",0);
+       } else {                        /* Normal case */
+           /* I & S packets always have type 1 */
+           chklen = 1;
+           rln = rln + bctl - 1;
+       }
     } else if (type == 'N') {          /* A NAK packet never has data */
        chklen = xunchar(recpkt[lp]) - 2;
+       if (chklen < 1 || chklen > 3) { /* JHD 13 Apr 2010 */
+           debug(F101,"rpack bad nak chklen","",chklen);
+           freerbuf(k);
+           logpkt('r',-1,(CHAR *)"<crunched:chklen>",0);
+           xxscreen(SCR_PT,'%',(long)pktnum,"(bad nak)");
+           return('Q');
+       }
        rln = rln + bctl - chklen;
     } else chklen = bctl;
 #ifdef DEBUG
@@ -3238,13 +3293,11 @@ tstats() {
        tlog(F101," effective data rate     ","",(long) xx);
     }
 #else
-    tlog(F101," elapsed time (seconds)  ","",(long) tsecs);
-    if (tsecs > 0) {
-       long lx;
-       lx = (tfc * 10L) / (long) tsecs;
-       tlog(F101," effective data rate     ","",lx/10L);
-    }
+    tlog(F101," elapsed time (seconds)  ","",tsecs);
+    if (tsecs > 0)
+      tlog(F101," effective data rate     ","",(tfc / tsecs));
 #endif /* GFTIMER */
+
     tlog(F100,"","",0L);               /* Leave a blank line */
 }
 
index c499421..2d58a56 100644 (file)
--- a/ckcfn3.c
+++ b/ckcfn3.c
@@ -6,7 +6,7 @@
   Author: Frank da Cruz <fdc@columbia.edu>,
   Columbia University Academic Information Systems, New York City.
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2010,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -215,8 +215,8 @@ extern char ** sndfilter;
 #endif /* PIPESEND */
 
 extern int unkcs, wmax, wcur, discard, bctu, bctl, local, fdispla, what,
-  sendmode, opnerr, dest, epktrcvd, epktsent, filestatus, eofmethod, dispos;
-extern long sendstart, calibrate, fncnv, fnrpath;
+    sendmode, opnerr, dest, epktrcvd, epktsent, filestatus, eofmethod, dispos,
+    fncnv, fnrpath;
 
 extern char * ofn2;
 extern char * rfspec, * sfspec, * prfspec, * psfspec, * rrfspec, * prrfspec;
@@ -265,7 +265,9 @@ extern int atfrmi, atfrmo, atcrei, atcreo, atacti, atacto;
 extern int quiet;
 #endif /* datageneral */
 
-extern long fsize, filcnt, ffc, tfc;
+extern long filcnt;
+extern CK_OFF_T fsize, ffc, tfc, sendstart, calibrate;
+CK_OFF_T rs_len;
 
 #ifndef NOCSETS
 _PROTOTYP (VOID setxlate, (void));
@@ -1183,8 +1185,12 @@ sattr(xp, flag) int xp, flag; {          /* Send Attributes */
          left++;
     }
     /* File length in K */
-    if (atleno && !done[xunchar(c = '!')] && x.lengthk > -1L) {
+    if (atleno && !done[xunchar(c = '!')] && x.lengthk > (CK_OFF_T)-1) {
+#ifdef COMMENT
        sprintf((char *) &data[i+2],"%ld",x.lengthk); /* safe */
+#else
+       ckstrncpy((char *)&data[i+2],ckfstoa(x.lengthk),32);
+#endif /* COMMENT */
        aln = (int)strlen((char *)(data+i+2));
        if (max - i >= aln + 2) {
            data[i] = c;
@@ -1198,8 +1204,12 @@ sattr(xp, flag) int xp, flag; {          /* Send Attributes */
        }
     }
     /* File length in bytes */
-    if (atleno && !done[xunchar(c = '1')] && x.length > -1L) {
+    if (atleno && !done[xunchar(c = '1')] && x.length > (CK_OFF_T)-1) {
+#ifdef COMMENT
        sprintf((char *) &data[i+2],"%ld",x.length); /* safe */
+#else
+       ckstrncpy((char *)&data[i+2],ckfstoa(x.length),32);
+#endif /* COMMENT */
        aln = (int)strlen((char *)(data+i+2));
        if (max - i >= aln + 2) {
            data[i] = c;
@@ -1369,17 +1379,17 @@ rsattr(s) CHAR *s; {                    /* Read response to attribute packet */
     }
 #ifdef CK_RESEND
     if (sendmode == SM_RESEND && *s == '1') { /* RESEND length */
-       int n; long z; CHAR *p;
+       int n; CK_OFF_T z; CHAR *p;
        p = s + 1;
        n = xunchar(*p++);
        debug(F101,"rsattr RESEND n","",n);
-       z = 0L;
+       z = (CK_OFF_T)0;
        while (n-- > 0)                 /* We assume the format is good. */
-         z = 10L * z + (long) (*p++ - '0');
+         z = (CK_OFF_T)10 * z + (CK_OFF_T)(*p++ - '0');
        debug(F101,"rsattr RESEND z","",z);
-       if (z > 0L) sendstart = z;
+       if (z > (CK_OFF_T)0) sendstart = z;
        debug(F101,"rsattr RESEND sendstart","",sendstart);
-       if (sendstart > 0L)
+       if (sendstart > (CK_OFF_T)0)
          if (zfseek(sendstart) < 0)    /* Input file is already open. */
            return(0);
 #ifdef CK_CURSES
@@ -1392,8 +1402,6 @@ rsattr(s) CHAR *s; {                      /* Read response to attribute packet */
     return(0);
 }
 
-long rs_len = 0L;                      /* Length of file being resent to */
-
 /*
   Get attributes from incoming A packet.  Returns:
    0 on success, file is to be accepted
@@ -1403,7 +1411,7 @@ int
 gattr(s, yy) CHAR *s; struct zattr *yy; { /* Read incoming attribute packet */
     char c, d;
     char *ff;
-    int aln, i;
+    int aln, i, overflow = 0;
 
 #ifndef NOCSETS
     extern int r_cset, axcset[];
@@ -1469,13 +1477,15 @@ gattr(s, yy) CHAR *s; struct zattr *yy; { /* Read incoming attribute packet */
     while (c = *s++) {                 /* Get attribute tag */
        aln = xunchar(*s++);            /* Length of attribute string */
        switch (c) {
+#ifdef COMMENT                         /* This case combined with '1' below */
          case '!':                     /* File length in K */
            for (i = 0; (i < aln) && (i < ABUFL); i++) /* Copy it */
              abuf[i] = *s++;
            abuf[i] = '\0';             /* Terminate with null */
            if (i < aln) s += (aln - i); /* If field was too long for buffer */
-           yy->lengthk = atol(abuf);   /* Convert to number */
+           yy->lengthk = ckatofs(abuf); /* Convert to number */
            break;
+#endif /* COMMENT */
 
          case '/':                     /* Record format */
            rfbuf[1] = NUL;
@@ -1659,7 +1669,7 @@ gattr(s, yy) CHAR *s; struct zattr *yy; { /* Read incoming attribute packet */
              dsbuf[i] = *s++;          /* Copy it into a separate string */
            dsbuf[i] = '\0';
            if (i < aln) s += (aln - i);
-           rs_len = 0;
+           rs_len = (CK_OFF_T)0;
            if (atdisi) {               /* We are doing this attribute */
                /* Copy it into the attribute structure */
                yy->disp.val = dsbuf;   /* Pointer to string */
@@ -1736,7 +1746,7 @@ gattr(s, yy) CHAR *s; struct zattr *yy; { /* Read incoming attribute packet */
   the Recover attribute now.  So better to leave as-is.  Anyway, it's probably
   more useful this way.
 */
-                   if (rs_len > 0L) {
+                   if (rs_len > (CK_OFF_T)0) {
                        fncsav = fncact; /* Save collision action */
                        fncact = XYFX_A; /* Switch to APPEND */
                    }
@@ -1780,15 +1790,40 @@ gattr(s, yy) CHAR *s; struct zattr *yy; { /* Read incoming attribute packet */
            }
            break;
 
-         case '1':                     /* File length in bytes */
-           for (i = 0; (i < aln) && (i < ABUFL); i++) /* Copy it */
-             abuf[i] = *s++;
-           abuf[i] = '\0';             /* Terminate with null */
-           if (i < aln) s += (aln - i);
-           yy->length = atol(abuf);    /* Convert to number */
-           debug(F111,"gattr length",abuf,(int) yy->length);
-           break;
-
+         case '!':                     /* File length in K */
+         case '1': {                   /* File length in bytes */
+             char * l2;
+             CK_OFF_T xlen;
+             for (i = 0; (i < aln) && (i < ABUFL); i++) /* Copy it */
+               abuf[i] = *s++;
+             abuf[i] = '\0';           /* Terminate with null */
+             if (i < aln) s += (aln - i);
+             if (rdigits(abuf)) {      /* Make sure string is all digits */
+                 xlen = ckatofs(abuf); /* Convert to number */
+                 l2 = ckfstoa(xlen);   /* Convert number back to string */
+                 if (c == '1')
+                   debug(F111,"gattr length",abuf,xlen);
+                 else
+                   debug(F111,"gattr lengthk",abuf,xlen);
+                 if (ckstrcmp(abuf,l2,-1,1)) { /* This is how we check... */
+                     xlen = (CK_OFF_T)-2; /* -2 = unk, possibly too long */
+                     overflow++;
+                     debug(F111,"gattr overflow",
+                           (c == '1') ? "length" : "lengthk",
+                           xlen);
+                 }
+                 if (c == '1') {
+                     yy->length = xlen;
+                     debug(F101,"gattr length","",xlen);
+                 } else {
+                     yy->lengthk = xlen;
+                     debug(F101,"gattr lengthk","",xlen);
+                 }
+             }
+             /* If the length field is not numeric accept the file */
+             /* anyway but with an unknown length */
+             break;
+         }
 
 #ifdef CK_PERMS
          case ',':                     /* System-dependent protection code */
@@ -1822,34 +1857,42 @@ gattr(s, yy) CHAR *s; struct zattr *yy; { /* Read incoming attribute packet */
        }
     }
 
-    /* Check file length now, because we also need to know the file type */
+    /* Check space now, because we also need to know the file type */
     /* in case zchkspa() differentiates text and binary (VMS version does) */
 
-    if (atleni) {                      /* Length attribute enabled? */
-       if (yy->length > -1L) {         /* Length-in-bytes attribute rec'd? */
+    if (atleni && !calibrate) {                /* Length attribute enabled? */
+       if (yy->length > (CK_OFF_T)-1) { /* Length-in-bytes attribute rec'd? */
            if (!zchkspa(ff,(yy->length))) { /* Check space */
                retcode = -1;                /* Not enuf */
                *rp++ = '1';
                if (!opnerr) tlog(F100," refused: length bytes","",0);
            }
-       } else if (yy->lengthk > -1L) { /* Length in K attribute rec'd? */
-           if (!zchkspa(ff,(yy->lengthk * 1024))) {
+       } else if (yy->lengthk > (CK_OFF_T)-1) { /* Length in K received? */
+           long xlen;
+           xlen = yy->lengthk * 1024;
+           if (!zchkspa(ff,xlen)) {
                retcode = -1;           /* Check space */
                *rp++ = '!';
                if (!opnerr) tlog(F100," refused: length K","",0);
            }
        }
     }
-    if (yy->length > -1L) {            /* Remember the file size */
-       fsize = yy->length;
-    } else if (yy->lengthk > -1L) {
-       fsize = yy->lengthk * 1024L;
-    } else fsize = -1L;
+    if (retcode > -1L) {               /* Remember the file size */
+       if (yy->length > (CK_OFF_T)-1) {
+           fsize = yy->length;
+       } else if (yy->lengthk > (CK_OFF_T)-1 && !overflow) {
+           fsize = yy->lengthk * 1024L;
+       } else fsize = yy->length;      /* (e.g. -2L) */
+    }
 
 #ifdef DEBUG
     if (deblog) {
+#ifdef COMMENT
        sprintf(abuf,"%ld",fsize);      /* safe */
-       debug(F110,"gattr fsize",abuf,0);
+#else
+       ckstrncpy(abuf,ckfstoa(fsize),ABUFL);
+#endif /* COMMENT */
+debug(F110,"gattr fsize",abuf,0);
     }
 #endif /* DEBUG */
 
@@ -1867,7 +1910,11 @@ gattr(s, yy) CHAR *s; struct zattr *yy; { /* Read incoming attribute packet */
        } else {                        /* Binary mode */
            retcode = 0;                /* Accept the file */
            discard = 0;                /* If SET FILE COLLISION DISCARD */
+#ifdef COMMENT
            sprintf(rpbuf+2,"%ld",rs_len); /* Reply with length of file */
+#else
+           ckstrncpy(rpbuf+2,ckfstoa(rs_len),RPBUFL-2);
+#endif /* COMMENT */
            rpbuf[0] = '1';             /* '1' means Length in Bytes */
            rpbuf[1] = tochar((int)strlen(rpbuf+2)); /* Length of length */
            debug(F111,"gattr RESEND OK",rpbuf,retcode);
@@ -1896,7 +1943,7 @@ gattr(s, yy) CHAR *s; struct zattr *yy; { /* Read incoming attribute packet */
 
 int
 initattr(yy) struct zattr *yy; {
-    yy->lengthk = yy->length = -1L;
+    yy->lengthk = yy->length = (CK_OFF_T)-1;
     yy->type.val = "";
     yy->type.len = 0;
     yy->date.val = "";
@@ -1999,7 +2046,7 @@ opena(f,zz) char *f; struct zattr *zz; {
 
     adebu(f,zz);                       /* Write attributes to debug log */
 
-    ffc = 0L;                          /* Init file-character counter */
+    ffc = (CK_OFF_T)0;                 /* Init file-character counter */
 
 #ifdef PIPESEND
     if (pipesend)                      /* Receiving to a pipe - easy. */
@@ -2107,7 +2154,7 @@ opena(f,zz) char *f; struct zattr *zz; {
        debug(F101,"opena binary","",binary);
 
 #ifdef COMMENT
-       if (fsize > -1L)
+       if (fsize >= 0)
 #endif /* COMMENT */
          xxscreen(SCR_FS,0,fsize,"");
 
@@ -2337,7 +2384,7 @@ openo(name,zz,fcb) char *name; struct zattr *zz; struct filinfo *fcb; {
 int
 opent(zz) struct zattr *zz; {
     int x;
-    ffc = tfc = 0L;
+    ffc = tfc = (CK_OFF_T)0;
     x = zopeno(ZCTERM,"",zz,NULL);
     debug(F101,"opent zopeno","",x);
     if (x >= 0) {
@@ -2352,7 +2399,7 @@ opent(zz) struct zattr *zz; {
 
 int
 ckopenx(zz) struct zattr *zz; {
-    ffc = tfc = 0L;                    /* Reset counters */
+    ffc = tfc = (CK_OFF_T)0;           /* Reset counters */
     o_isopen = 1;
     debug(F101,"ckopenx fsize","",fsize);
     xxscreen(SCR_FS,0,fsize,"");       /* Let screen display know the size */
@@ -2409,7 +2456,7 @@ clsif() {
            }
 #endif /* TLOG */
        } else if (!epktrcvd && !epktsent && !cxseen && !czseen) {
-           long zz;
+           CK_OFF_T zz;
            zz = ffc;
 #ifdef CK_RESEND
            if (sendmode == SM_RESEND || sendmode == SM_PSEND)
@@ -2450,7 +2497,7 @@ clsif() {
     }
     i_isopen = 0;
     hcflg = 0;                         /* Reset flags */
-    sendstart = 0L;                    /* Don't do this again! */
+    sendstart = (CK_OFF_T)0;           /* Don't do this again! */
 #ifdef COMMENT
 /*
   This prevents a subsequent call to clsof() from deleting the file
@@ -2546,7 +2593,7 @@ clsof(disp) int disp; {
 #endif /* TLOG */
        }
     }
-    rs_len = 0;
+    rs_len = (CK_OFF_T)0;
     o_isopen = 0;                      /* The file is not open any more. */
     cxseen = 0;                                /* Reset per-file interruption flag */
     return(x);                         /* Send back zclose() return code. */
index 53ea236..0f2bd86 100644 (file)
--- a/ckcfns.c
+++ b/ckcfns.c
@@ -1,4 +1,4 @@
-char *fnsv = "C-Kermit functions, 8.0.223, 1 May 2003";
+char *fnsv = "C-Kermit functions, 9.0.233, 3 Jun 2011";
 
 char *nm[] =  { "Disabled", "Local only", "Remote only", "Enabled" };
 
@@ -10,7 +10,7 @@ char *nm[] =  { "Disabled", "Local only", "Remote only", "Enabled" };
   Author: Frank da Cruz <fdc@columbia.edu>,
   Columbia University Academic Information Systems, New York City.
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2011,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -41,7 +41,6 @@ int gnferror = 0;                     /* gnfile() failure reason */
 extern CHAR feol;
 extern int byteorder, xflg, what, fmask, cxseen, czseen, nscanfile, sysindex;
 extern int xcmdsrc, dispos, matchfifo;
-extern long ffc;
 extern int inserver;
 
 extern int nolinks;
@@ -82,9 +81,6 @@ _PROTOTYP( int lookup, (struct keytab[], char *, int, int *) );
 #ifndef NOSPL
 _PROTOTYP( int zzstring, (char *, char **, int *) );
 #endif /* NOSPL */
-#ifdef OS2ORUNIX
-_PROTOTYP( long zfsize, (char *) );
-#endif /* OS2ORUNIX */
 
 #ifdef OS2
 #include <io.h>
@@ -103,12 +99,14 @@ extern int srvcdmsg, srvidl, idletmo;
 extern char * cdmsgfile[];
 extern int spsiz, spmax, rpsiz, timint, srvtim, rtimo, npad, ebq, ebqflg,
  rpt, rptq, rptflg, capas, keep, fncact, pkttim, autopar, spsizr, xitsta;
-extern int pktnum, bctr, bctu, bctl, clfils, sbufnum, protocol,
+extern int pktnum, bctr, bctu, bctf, bctl, clfils, sbufnum, protocol,
  size, osize, spktl, nfils, ckwarn, timef, spsizf, sndtyp, rcvtyp, success;
 extern int parity, turn, network, whatru, fsecs, justone, slostart,
  ckdelay, displa, mypadn, moving, recursive, nettype;
-extern long filcnt, flci, flco, tlci, tlco, tfc, fsize, sendstart, rs_len;
-extern long filrej, oldcps, cps, peakcps, ccu, ccp, calibrate, filestatus;
+extern long filcnt;
+extern CK_OFF_T
+ tfc, fsize, sendstart, rs_len, flci, flco, tlci, tlco, calibrate;
+extern long filrej, oldcps, cps, peakcps, ccu, ccp, filestatus;
 extern int fblksiz, frecl, frecfm, forg, fcctrl, fdispla, skipbup;
 extern int spackets, rpackets, timeouts, retrans, crunched, wmax, wcur;
 extern int hcflg, binary, fncnv, b_save, f_save, server;
@@ -197,6 +195,8 @@ _PROTOTYP( int szeof, (CHAR *s) );
 _PROTOTYP( VOID fnlist, (void) );
 #endif /* NOXFER */
 
+extern CK_OFF_T ffc;
+
 /* Character set Translation */
 
 #ifndef NOCSETS
@@ -263,8 +263,8 @@ char sndnafter[19]  = { NUL, NUL };
 char sndnbefore[19] = { NUL, NUL };
 char *sndexcept[NSNDEXCEPT]  = { NULL, NULL };
 char *rcvexcept[NSNDEXCEPT]  = { NULL, NULL };
-long sndsmaller = -1L;
-long sndlarger  = -1L;
+CK_OFF_T sndsmaller = (CK_OFF_T)-1;
+CK_OFF_T sndlarger  = (CK_OFF_T)-1;
 
 /* Variables defined in this module but shared by other modules. */
 
@@ -438,7 +438,7 @@ encstr(s) CHAR* s;
     rc = 0;                            /* Return code. */
     m = memstr; p = memptr;            /* Save these. */
     memptr = (char *)s;                        /* Point to the string. */
-    debug(F101,"encstr memptr 1","",memptr);
+    /* debug(F101,"encstr memptr 1","",memptr); */
     memstr = 1;                                /* Flag memory string as source. */
     first = 1;                         /* Initialize character lookahead. */
     *data = NUL;                       /* In case s is empty */
@@ -689,7 +689,7 @@ bdecode(buf,fn) register CHAR *buf; register int (*fn)();
 
 /*  P N B Y T E  --  Output next byte to file or other destination  */
 
-static long offc = 0L;
+static CK_OFF_T offc = 0L;
 
 static int
 #ifdef CK_ANSIC
@@ -786,7 +786,7 @@ xpnbyte(a,tcs,fcs,fn) int a, tcs, fcs; int (*fn)();
                                        /* swapping must be 0 or 1 */
     if (a == -1 && (tcs | fcs) == 0) { /* Reset in case previous run */
        bn = 0;                         /* left bn at 1... */
-       offc = 0L;
+       offc = (CK_OFF_T)0;
        debug(F101,"xpnbyte RESET","",bn);
        return(0);
     }
@@ -929,7 +929,7 @@ xpnbyte(a,tcs,fcs,fn) int a, tcs, fcs; int (*fn)();
             } output;
 #endif /* OS2 */
 #endif /* IKSDONLY */
-           if (offc == 0L && ucsbom) { /* Beginning of file? */
+           if (!offc && ucsbom) {      /* Beginning of file? */
 
 #ifndef IKSDONLY
 #ifdef OS2
@@ -989,8 +989,8 @@ xpnbyte(a,tcs,fcs,fn) int a, tcs, fcs; int (*fn)();
 #ifdef OS2
             if (fn == NULL && !k95stdout && !inserver) {
                 offc++;
-                output.bytes[0] = uc.x_char[1-swapping];
-                output.bytes[1] = uc.x_char[swapping];
+                output.bytes[0] = uc.x_char[swapping];
+                output.bytes[1] = uc.x_char[1-swapping];
 
                 VscrnWrtUCS2StrAtt(VCMD,
                                    &output.ucs2,
@@ -1191,7 +1191,7 @@ xpnbyte(a,tcs,fcs,fn) int a, tcs, fcs; int (*fn)();
        }
        if (fcs == FC_UCS2) {           /* And FCS is UCS-2 */
            /* Write out the bytes in the appropriate byte order */
-           if (offc == 0 && ucsbom) {  /* Beginning of file? */
+           if (!offc && ucsbom) {      /* Beginning of file? */
                if ((rc = pnbyte((ucsorder ? 0xff : 0xfe),fn)) < 0) /* BOM */
                  return(rc);
                if ((rc = pnbyte((ucsorder ? 0xfe : 0xff),fn)) < 0)
@@ -1466,7 +1466,7 @@ decode(buf,fn,xlate) register CHAR *buf; register int (*fn)(); int xlate;
 #ifdef KANJI
                if (!binary && tcharset == TC_JEUC &&
                    fcharset != FC_JEUC) { /* Translating from J-EUC */
-                   if (ffc == 0L) xkanjf();
+                   if (!ffc) xkanjf();
                    if (xkanji(a,fn) < 0)  /* to something else? */
                      return(-1);
                    else t = 1;
@@ -1670,7 +1670,7 @@ bgetpkt(bufmax) int bufmax; {
 #endif /* DEBUG */
 
     if (first == 1) {                  /* If first character of this file.. */
-       ffc = 0L;                       /* reset file character counter */
+       ffc = (CK_OFF_T)0;              /* reset file character counter */
 #ifdef COMMENT
 /* Moved to below */
        first = 0;                      /* Next character won't be first */
@@ -2012,7 +2012,7 @@ xgnbyte(tcs,fcs,fn) int tcs, fcs, (*fn)();
 #endif /* KANJI */
 
 #ifdef DEBUG
-    if (deblog && ffc == 0) {
+    if (deblog && !ffc) {
        debug(F101,"xgnbyte initial swap","",swapping);
     }
 #endif /* DEBUG */
@@ -2026,7 +2026,7 @@ xgnbyte(tcs,fcs,fn) int tcs, fcs, (*fn)();
        haveuc = 0;
 #ifdef UNICODE
        if (fcs == FC_UCS2) {           /* UCS-2: Read two bytes */
-           if (ffc == 0)               /* Beginning of file? */
+           if (!ffc)                   /* Beginning of file? */
              swapping = 0;             /* Reset byte-swapping flag */
            uc.x_short = 0;
          bomskip:
@@ -2051,7 +2051,7 @@ xgnbyte(tcs,fcs,fn) int tcs, fcs, (*fn)();
                    if (docrc && (what & W_SEND))
                      dofilcrc(x);
 #endif /* NOXFER */
-                   if (ffc == 2) {     /* Second char of file */
+                   if (ffc == (CK_OFF_T)2) { /* Second char of file */
                        debug(F001,"xgnbyte 1st UCS2","",uc.x_short);
                        debug(F111,"xgnbyte fileorder","A",fileorder);
                        if (fileorder < 0) /* Byte order of this file */
@@ -2131,7 +2131,7 @@ xgnbyte(tcs,fcs,fn) int tcs, fcs, (*fn)();
          if (fcsinfo[fcs].alphabet == AL_JAPAN) { /* Japanese source file */
            int c7, x, y;
            if (fcs == FC_JIS7) {       /* If file charset is JIS-7 */
-               if (ffc == 0L)          /* If first byte of file */
+               if (!ffc)               /* If first byte of file */
                  j7init();             /* Initialize JIS-7 parser */
                x = getj7();            /* Get a JIS-7 byte */
            } else                      /* Otherwise */
@@ -2257,7 +2257,38 @@ xgnbyte(tcs,fcs,fn) int tcs, fcs, (*fn)();
   too soon and so might not have known whether it was a file transfer or a
   local operation.
 */
+/*
+  (Many years later...) In testing this code I noticed that TRANSLATE'ing
+  Russian text from UTF-8 to ISO Latin/Cyrillic produced all question marks.
+  Rereading the previous paragraph it seems to me we are (I am) overloading
+  this function with responsibilites, satisfying the needs of file transfer
+  (local file charset -> transfer charset for outbound packet) and local file
+  conversion.  In the case of TRANSLATE, we call (xgnbyte(), xpnbyte()) in a
+  loop, expecting the xgnbyte() will feed UCS2 to xpnbyte().  But the
+  following code does what xpnbyte() is going to do, returning (in this case)
+  an ISO Latin/Cyrillic byte stream, which xpnbyte() believes to be UCS2, and
+  comes up with nonsense.  Not wanting to rip the whole thing apart and start
+  over, I made the following change that should do no harm, upon observing
+  that if the input character set is UTF-8 or UCS-2, then when we get here it
+  has already been converted to UCS2, so if we are not transferring a file, we
+  don't need to do anything else except put the bytes in the right place to be
+  returned, which is done further along.
+*/
+#ifdef COMMENT
+         /* Previous code */
          xx = (what & W_SEND) ? xut : xuf;
+#else
+         /* New code 2011-06-03 */
+         if (what & W_SEND) {
+             xx = xut;
+         } else {
+             if (fcs == FC_UCS2 || fcs == FC_UTF8)
+               xx = NULL;
+             else
+               xx = xuf;
+         }
+#endif /* COMMENT */
+
          eolflag = 0;
          if (haveuc) {                 /* File is Unicode */
              /* See Unicode TR13, "Converting to Other Character Sets" */
@@ -2550,7 +2581,7 @@ getpkt(bufmax,xlate) int bufmax, xlate; { /* Fill one packet buffer */
        debug(F101,"getpkt first uflag","",uflag);
        debug(F101,"getpkt first rt","",rt);
        if (!memstr && !funcstr)        /* and real file... */
-         ffc = 0L;                     /* reset file character counter */
+         ffc = (CK_OFF_T)0;            /* reset file character counter */
 #ifdef COMMENT
        /* Moved to below... */
        first = 0;                      /* Next character won't be first */
@@ -3034,7 +3065,11 @@ tinit(flag) int flag; {
     /* This stuff is only for BEFORE S/I/Y negotiation, not after */
 
     if (flag) {
-       bctu = bctl = 1;                /* Reset block check type to 1 */
+       if (bctf) {                   /* Force Block Check 3 on all packets */
+           bctu = bctl = 3;            /* Set block check type to 3 */
+       } else {
+           bctu = bctl = 1;            /* Reset block check type to 1 */
+       }
        myinit[0] = '\0';               /* Haven't sent init string yet */
        rqf = -1;                       /* Reset 8th-bit-quote request flag */
        ebq = MYEBQ;                    /* Reset 8th-bit quoting stuff */
@@ -3127,17 +3162,17 @@ rinit(d) CHAR *d; {
 VOID
 resetc() {
     rptn = 0;                          /* Repeat counts */
-    fsecs = flci = flco = 0L;          /* File chars in and out */
+    fsecs = flci = flco = (CK_OFF_T)0; /* File chars in and out */
 #ifdef GFTIMER
     fpfsecs = 0.0;
 #endif /* GFTIMER */
-    tfc = tlci = tlco = 0L;            /* Total file, line chars in & out */
+    tfc = tlci = tlco = (CK_OFF_T)0;   /* Total file, line chars in & out */
     ccu = ccp = 0L;                    /* Control-char statistics */
 #ifdef COMMENT
-    fsize = -1L;                       /* File size */
+    fsize = (CK_OFF_T)-1;              /* File size */
 #else
     if (!(what & W_SEND))
-      fsize = -1L;
+      fsize = (CK_OFF_T)-1;
     debug(F101,"resetc fsize","",fsize);
 #endif /* COMMENT */
     timeouts = retrans = 0;            /* Timeouts, retransmissions */
@@ -3341,7 +3376,7 @@ xsinit() {
 char ofn1[CKMAXPATH+4];                        /* Buffer for output file name */
 char * ofn2;                           /* Pointer to backup file name */
 int ofn1x;                             /* Flag output file already exists */
-long ofn1len = 0L;
+CK_OFF_T ofn1len = (CK_OFF_T)0;
 int opnerr;                            /* Flag for open error */
 
 int                                    /* Returns success ? 1 : 0 */
@@ -3362,9 +3397,9 @@ rcvfil(n) char *n; {
 #endif /* PIPESEND */
 #ifdef CALIBRATE
     extern int dest;
-    int csave;
+    CK_OFF_T csave;
     csave = calibrate;                 /* So we can decode filename */
-    calibrate = 0;
+    calibrate = (CK_OFF_T)0;
 #endif /* CALIBRATE */
 
     ofperms = "";                      /* Reset old-file permissions */
@@ -3735,7 +3770,7 @@ Please confirm output file specification or supply an alternative:";
     debug(F101,"rcvfil dirflg","",dirflg);
     ofn1len = zchki(ofn1);             /* File already exists? */
     debug(F111,"rcvfil ofn1len",ofn1,ofn1len);
-    ofn1x = (ofn1len != -1);
+    ofn1x = (ofn1len != (CK_OFF_T)-1);
 
     if ( (
 #ifdef UNIX
@@ -3948,9 +3983,9 @@ Please confirm output file specification or supply an alternative:";
 
     debug(F110,"rcvfilx: n",n,0);
     debug(F110,"rcvfilx: ofn1",ofn1,0);
-    ffc = 0L;                          /* Init per-file counters */
+    ffc = (CK_OFF_T)0;                 /* Init per-file counters */
     cps = oldcps = 0L;
-    rs_len = 0L;
+    rs_len = (CK_OFF_T)0;
     rejection = -1;
     fsecs = gtimer();                  /* Time this file started */
 #ifdef GFTIMER
@@ -4218,7 +4253,7 @@ sfile(x) int x; {
        if (!cmarg2) cmarg2 = "";
 #ifdef DEBUG
        if (deblog) {
-           debug(F111,"sfile cmarg2",cmarg2,cmarg2);
+           /* debug(F111,"sfile cmarg2",cmarg2,cmarg2); */
            debug(F101,"sfile binary 1","",binary);
            debug(F101,"sfile wearealike","",wearealike);
            debug(F101,"sfile xfermode","",xfermode);
@@ -4499,7 +4534,7 @@ sfile(x) int x; {
             return(0);
         }
        if (sendmode == SM_PSEND)       /* PSENDing? */
-         if (sendstart > 0L)           /* Starting position */
+         if (sendstart > (CK_OFF_T)0)  /* Starting position */
            if (zfseek(sendstart) < 0)  /* seek to it... */
              return(0);
 #endif /* CK_RESEND */
@@ -4597,7 +4632,7 @@ sfile(x) int x; {
     }
     intmsg(++filcnt);                  /* Count file, give interrupt msg */
     first = 1;                         /* Init file character lookahead. */
-    ffc = 0L;                          /* Init file character counter. */
+    ffc = (CK_OFF_T)0;                 /* Init file character counter. */
     cps = oldcps = 0L;                 /* Init cps statistics */
     rejection = -1;
     fsecs = gtimer();                  /* Time this file started */
@@ -5157,7 +5192,7 @@ spar(s) CHAR *s; {                        /* Set parameters */
     if (biggest >= 8) {
        if (s[8] == 'B') x = 4;
        else x = s[8] - '0';
-       if ((x < 1) || (x > 4)) x = 1;
+       if ((x < 1) || (x > 5)) x = 1;  /* "5" 20110605 */
     }
     bctr = x;
 
@@ -5424,7 +5459,8 @@ spar(s) CHAR *s; {                        /* Set parameters */
 */
 int
 gnfile() {
-    int i = 0, x = 0; long y = 0L;
+    int i = 0, x = 0;
+    CK_OFF_T filesize = 0;
     int dodirstoo = 0;
     int retcode = 0;
 
@@ -5438,8 +5474,16 @@ gnfile() {
     debug(F101,"gnfile recursive","",recursive);
     debug(F101,"gnfile dodirstoo","",dodirstoo);
     gnferror = 0;
-    fsize = -1L;                       /* Initialize file size */
+    fsize = (CK_OFF_T)-1;              /* Initialize file size */
     fullname[0] = NUL;
+
+#ifdef VMS
+    /* 
+      In VMS, zopeni() sets binary 0/1 automatically from the file
+      attributes.  Don't undo it here.
+    */
+    debug(F101,"gnfile VMS binary","",binary);
+#else  /* VMS */
     if (!(what & W_REMO) && (xfermode == XMODE_A)
 #ifndef NOMSEND
        && !addlist
@@ -5454,6 +5498,8 @@ gnfile() {
            binary = gnf_binary;        /* Restore prevailing transfer mode */
        debug(F101,"gnfile binary = gnf_binary","",gnf_binary);
     }
+#endif /* VMS */
+
 #ifdef PIPESEND
     debug(F101,"gnfile pipesend","",pipesend);
     if (pipesend) {                    /* First one */
@@ -5486,7 +5532,7 @@ gnfile() {
        extern char sndxnam[];          /* Pseudo filename */
        debug(F100,"gnfile array","",0);
        nfils = 0;
-       fsize = -1L;                    /* Size unknown */
+       fsize = (CK_OFF_T)-1;           /* Size unknown */
        sndsrc = 0;
        ckstrncpy(filnam,sndxnam,CKMAXPATH);
        return(1);
@@ -5511,8 +5557,8 @@ gnfile() {
 
 /* Loop through file list till we find a readable, sendable file */
 
-    y = -1L;                           /* Loop exit (file size) variable */
-    while (y < 0L) {                   /* Keep trying till we get one... */
+    filesize = (CK_OFF_T)-1;           /* Loop exit (file size) variable */
+    while (filesize < 0) {             /* Keep trying till we get one... */
        retcode = 0;
        if (sndsrc > 0) {               /* File list in cmlist or file */
            if (filefile) {             /* Reading list from file... */
@@ -5557,7 +5603,7 @@ nextinpath:
                fromgetpath = 0;
                if (server && !isabsolute(filnam) && (ngetpath > i)) {
                    ckstrncpy(fullname,getpath[i],CKMAXPATH+1);
-                   strncat(fullname,filnam,CKMAXPATH);
+                   ckstrncat(fullname,filnam,CKMAXPATH);
                    debug(F111,"gnfile getpath",fullname,i);
                    fromgetpath = 1;
                    i++;
@@ -5578,7 +5624,7 @@ nextinpath:
                    ) { /* It looks wild... */
                    /* First check if a file with this name exists */
                    debug(F110,"gnfile wild",fullname,0);
-                   if (zchki(fullname) > -1) {
+                   if (zchki(fullname) >= 0) {
                        /*
                           Here we have a file whose name actually
                           contains wildcard characters.
@@ -5665,17 +5711,17 @@ gotnam:
                if (*dirp) ckstrncpy(fullname,dirp,CKMAXPATH+1);
            }
 #endif /* DTILDE */
-           y = zchki(fullname);        /* Check if file readable */
-           debug(F111,"gnfile zchki",fullname,y);
-           retcode = (int) y;          /* Possible return code */
-           if (y == -2L && dodirstoo) {
-               y = 0L;
+           filesize = zchki(fullname); /* Check if file readable */
+           debug(F111,"gnfile zchki",fullname,filesize);
+           retcode = filesize;         /* Possible return code */
+           if (filesize == (CK_OFF_T)-2 && dodirstoo) {
+               filesize = 0;
            }
-           if (y < 0L) {
-               gnferror = (int) y;
+           if (filesize < 0) {
+               gnferror = (int)filesize;
                debug(F101,"gnfile gnferror C","",gnferror);
            }
-           if (y == -1L) {             /* If not found */
+           if (filesize == (CK_OFF_T)-1) { /* If not found */
                debug(F100,"gnfile -1","",0);
 #ifndef NOSERVER
                if (server && ngetpath > i)
@@ -5690,8 +5736,8 @@ gotnam:
                  doxlog(what,fullname,fsize,binary,1,"Skipped");
 #endif /* TLOG */
                continue;
-           } else if (y < 0) {
-               if (y == -3) {          /* Exists but not readable */
+           } else if (filesize < 0) {
+               if (filesize == (CK_OFF_T)-3) { /* Exists but not readable */
                    debug(F100,"gnfile -3","",0);
                    filrej++;           /* Count this one as not sent */
                    tlog(F110,"Read access denied",fullname,0); /* Log this */
@@ -5705,7 +5751,12 @@ gotnam:
                continue;
            } else {
                int xx;
-               fsize = y;
+               fsize = filesize;
+/* +++ */
+    debug(F111,"gnfile sndsmaller",ckfstoa(sndsmaller),sndsmaller);
+    debug(F111,"gnfile sndlarger",ckfstoa(sndlarger),sndlarger);
+    debug(F111,"gnfile (CK_OFF_T)-1",ckfstoa((CK_OFF_T)-1),(CK_OFF_T)-1);
+
                xx = fileselect(fullname,
                                sndafter, sndbefore,
                                sndnafter,sndnbefore,
@@ -5714,7 +5765,7 @@ gotnam:
                                NSNDEXCEPT,sndexcept);
                debug(F111,"gnfile fileselect",fullname,xx);
                if (!xx) {
-                   y = -1L;
+                   filesize = (CK_OFF_T)-1;
                    gnferror = -6;
                    debug(F101,"gnfile gnferror D","",gnferror);
                    continue;
@@ -5733,7 +5784,7 @@ gotnam:
                            NSNDEXCEPT,sndexcept)) {
                gnferror = -6;
                debug(F111,"gnfile fileselect",fullname,gnferror);
-               y = -1L;
+               filesize = (CK_OFF_T)-1;
                continue;
            }
            ckstrncpy(filnam,fullname,CKMAXPATH+1);
@@ -5789,7 +5840,7 @@ static int  funclen =  0;
 static int  nxpnd   = -1;
 static long ndirs   =  0;
 static long nfiles  =  0;
-static long nbytes  =  0;
+static CK_OFF_T nbytes  =  0;
 
 int
 sndstring(p) char * p; {
@@ -6154,7 +6205,7 @@ nxtdir(
     char *filetag = "files";
     char *bytetag = "bytes";
 #endif /* OSK */
-    long len = 0;
+    CK_OFF_T len = 0;
     int x, itsadir = 0, gotone = 0;
 
 #ifdef DEBUG
@@ -6278,19 +6329,19 @@ nxtdir(
        } else {                        /* Regular file */
 #ifdef VMS
            sprintf((char *)linebuf,
-                   "%-22s%10ld  %s  %s\n", p, len, dstr, name);
+                   "%-22s%10s  %s  %s\n", p, ckfstoa(len), dstr, name);
 #else
            if (p)
              sprintf((char *)linebuf,
-                     "%10s%10ld  %s  %s%s%s\n",
-                     p, len, dstr, name,
+                     "%10s%10s  %s  %s%s%s\n",
+                     p, ckfstoa(len), dstr, name,
                      *lnk ? " -> " : "",
                      lnk
                      );
            else
              sprintf((char *)linebuf,
-                     "%10ld  %s  %s%s%s\n",
-                     len, dstr, name,
+                     "%10s  %s  %s%s%s\n",
+                     ckfstoa(len), dstr, name,
                      *lnk ? " -> " : "",
                      lnk
                      );
@@ -6313,28 +6364,28 @@ nxtdir(
            dirtag = "directory";
         if (nfiles == 1)
            filetag = "file";
-        if (nbytes == 1)
+        if (nbytes == (CK_OFF_T)1)
            bytetag = "byte";
         sprintf((char *)funcbuf,
-           "%sSummary: %ld %s, %ld %s, %ld %s%s",
-           blankline,
-           ndirs,
-           dirtag,
-           nfiles,
-           filetag,
-           nbytes,
-           bytetag,
-           endline);
+               "%sSummary: %ld %s, %ld %s, %s %s%s",
+               blankline,
+               ndirs,
+               dirtag,
+               nfiles,
+               filetag,
+               ckfstoa(nbytes),
+               bytetag,
+               endline);
 #else
         sprintf((char *)funcbuf,
-               "%sSummary: %ld director%s, %ld file%s, %ld byte%s%s",
+               "%sSummary: %ld director%s, %ld file%s, %s byte%s%s",
                blankline,
                ndirs,
                (ndirs == 1) ? "y" : "ies",
                nfiles,
                (nfiles == 1) ? "" : "s",
-               nbytes,
-               (nbytes == 1) ? "" : "s",
+               ckfstoa(nbytes),
+               (nbytes == (CK_OFF_T)1) ? "" : "s",
                endline
                );
 #endif /* OSK */
@@ -6414,7 +6465,7 @@ snddir(spec) char * spec; {
     debug(F110,"snddir name 1",name,0);
     ndirs = 0L;
     nfiles = 0L;
-    nbytes = 0L;
+    nbytes = (CK_OFF_T)0;
 
     if (zfnqfp(name,CKMAXPATH,fnbuf))
 
@@ -6504,7 +6555,8 @@ snddir(spec) char * spec; {
     first = 1;                         /* Init getchx lookahead */
     funcstr = 1;                       /* Just set the flag. */
     funcptr = nxtdir;                  /* And the pointer. */
-    rc = sinit();
+    binary = XYFT_T;                   /* Text mode for this */
+    rc = sinit();                      /* 26 Aug 2005 */
     debug(F111,"snddir","sinit()",rc);
     return(rc);
 #else
@@ -6562,12 +6614,12 @@ nxtdel(
 
       if (nxpnd == 0) {
          sprintf((char *)funcbuf,
-                 "%s%ld file%s deleted, %ld byte%s freed%s",
+                 "%s%ld file%s deleted, %s byte%s freed%s",
                  endline,
                  nfiles,
                  (nfiles == 1) ? "" : "s",
-                 nbytes,
-                 (nbytes == 1) ? "" : "s",
+                 ckfstoa(nbytes),
+                 (nbytes == (CK_OFF_T)1) ? "" : "s",
                  endline
                  );
          nxpnd--;
@@ -6611,7 +6663,8 @@ snddel(spec) char * spec; {
     }
 #endif /* OS2 */
 
-    nfiles = nbytes = 0L;
+    nfiles = 0L;
+    nbytes = (CK_OFF_T)0;
     sprintf((char *)funcbuf,"Deleting \"%s\"%s",name,endline);
     funcnxt = 0;
     funclen = strlen((char *)funcbuf);
@@ -6913,6 +6966,10 @@ remset(s) char *s; {
            bctr = 4;
            c_save = -1;
            return(1);
+       } else if (*p == '5') {
+           bctr = 3;
+           c_save = -1;
+           return(1);
        }
        return(0);
       case 401:                                /* Receive packet-length */
index d8d9ddd..7667940 100644 (file)
--- a/ckcftp.c
+++ b/ckcftp.c
@@ -1,6 +1,8 @@
+#define FTP_TIMEOUT
+
 /*  C K C F T P  --  FTP Client for C-Kermit  */
 
-char *ckftpv = "FTP Client, 8.0.226, 7 Jan 2004";
+char *ckftpv = "FTP Client, 9.0.259, 15 Jun 2011";
 
 /*
   Authors:
@@ -9,7 +11,7 @@ char *ckftpv = "FTP Client, 8.0.226, 7 Jan 2004";
     Frank da Cruz <fdc@columbia.edu>,
       The Kermit Project, Columbia University.
 
-  Copyright (C) 2000, 2004,
+  Copyright (C) 2000, 2011,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -174,7 +176,12 @@ extern int TlsIndex;
 #include <setret.h>
 #endif /* ZILOG */
 #include "ckcsig.h"
+#ifdef VMS
+/* 2010-03-09 SMS.  VAX C needs help to find "sys".  It's easier not to try. */
+#include <stat.h>
+#else /* def VMS */
 #include <sys/stat.h>
+#endif /* def VMS [else] */
 #include <ctype.h>
 #include <errno.h>
 #ifndef NOTIMEH
@@ -194,6 +201,10 @@ extern int TlsIndex;
 #include "ckctel.h"                     /* (then why include it again?) */
 #include "ckcxla.h"
 
+#ifdef CK_SSL
+#include "ckuath.h"                    /* SMS 2007/02/15 */
+#endif /* def CK_SSL */
+
 /*
   How to get the struct timeval definition so we can call select().  The
   xxTIMEH symbols are defined in ckcdeb.h, overridden in various makefile
@@ -242,7 +253,12 @@ struct timezone {
 #endif /* NOSYSTIMEBH */
 #endif /* DCLTIMEVAL */
 
+/* 2010-03-09 SMS.  VAX C needs help to find "sys".  It's easier not to try. */
+#ifdef VMS
+#include <types.h>
+#else /* def VMS */
 #include <sys/types.h>
+#endif /* def VMS [else] */
 #include <stdio.h>
 #include <string.h>
 #ifdef HAVE_STDLIB_H
@@ -265,6 +281,9 @@ struct timezone {
 #endif /* POSIX */
 #endif /* COMMENT */
 
+#ifdef VMS                             /* SMS 2007/02/15 */
+#include "ckvrtl.h"                    /* for utime() */
+#else  /* def VMS */
 #ifdef SYSUTIMEH
 #include <sys/utime.h>
 #else
@@ -273,6 +292,7 @@ struct timezone {
 #define SYSUTIMEH
 #endif /* UTIMEH */
 #endif /* SYSUTIMEH */
+#endif /* def VMS */
 #endif /* NOSETTIME */
 
 #ifndef SCO_OSR504
@@ -281,10 +301,30 @@ struct timezone {
 #endif /* SELECT_H */
 #endif /* SCO_OSR504 */
 
+#ifndef INADDR_NONE                    /* 2010-03-29 */
+#define INADDR_NONE -1
+#endif /* INADDR_NONE */
+
 /* select() dialects... */
 
 #ifdef UNIX
 #define BSDSELECT                       /* BSD select() syntax/semantics */
+#ifndef FD_SETSIZE
+#define FD_SETSIZE 128
+#endif /* FD_SETSIZE */
+#ifdef HPUX6                           /* For HP-UX 6.5 circa 1989 */
+typedef long fd_mask;
+#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */
+#ifndef howmany
+#define howmany(x, y)   (((x)+((y)-1))/(y))
+#endif /* howmany */
+#define FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
+#define FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
+#define FD_ISSET(n, p)  ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
+#define FD_COPY(f, t)   bcopy(f, t, sizeof(*(f)))
+#define FD_ZERO(p)      bzero(p, sizeof(*(p)))
+#endif /* HPUX6 */
+
 #else
 #ifdef OS2                              /* OS/2 or Win32 */
 #ifdef NT
@@ -295,6 +335,10 @@ struct timezone {
 #endif /* OS2 */
 #endif /* UNIX */
 
+#ifdef VMS
+#define BSDSELECT                      /* SMS 2007/02/15 */
+#endif /* def VMS */
+
 /* Other select() peculiarities */
 
 #ifdef HPUX
@@ -414,7 +458,9 @@ int ssl_ftp_proxy = 0;                  /* FTP over SSL/TLS Proxy Server */
 #endif /* KRB4 */
 #ifdef KRB5
 #ifndef HEIMDAL
+#ifndef NOFTP_GSSAPI                   /* 299 */
 #define FTP_GSSAPI
+#endif /* NOFTP_GSSAPI */
 #endif /* HEIMDAL */
 #endif /* KRB5 */
 #endif /* CK_KERBEROS */
@@ -500,6 +546,113 @@ int ssl_ftp_proxy = 0;                  /* FTP over SSL/TLS Proxy Server */
 #include <gssapi/gssapi_generic.h>
 #include <gssapi/gssapi_krb5.h>
 static gss_ctx_id_t gcontext;
+
+#ifdef MACOSX
+/** exported constants defined in gssapi_krb5{,_nx}.h **/
+
+/* these are bogus, but will compile */
+
+/*
+ * The OID of the draft krb5 mechanism, assigned by IETF, is:
+ *      iso(1) org(3) dod(5) internet(1) security(5)
+ *      kerberosv5(2) = 1.3.5.1.5.2
+ * The OID of the krb5_name type is:
+ *      iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
+ *      krb5(2) krb5_name(1) = 1.2.840.113554.1.2.2.1
+ * The OID of the krb5_principal type is:
+ *      iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
+ *      krb5(2) krb5_principal(2) = 1.2.840.113554.1.2.2.2
+ * The OID of the proposed standard krb5 mechanism is:
+ *      iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
+ *      krb5(2) = 1.2.840.113554.1.2.2
+ * The OID of the proposed standard krb5 v2 mechanism is:
+ *      iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
+ *      krb5v2(3) = 1.2.840.113554.1.2.3
+ *
+ */
+
+/*
+ * Encoding rules: The first two values are encoded in one byte as 40
+ * * value1 + value2.  Subsequent values are encoded base 128, most
+ * significant digit first, with the high bit (\200) set on all octets
+ * except the last in each value's encoding.
+ */
+
+static CONST gss_OID_desc
+ck_krb5_gss_oid_array[] = {
+   /* this is the official, rfc-specified OID */
+   {9, "\052\206\110\206\367\022\001\002\002"},
+   /* this is the unofficial, wrong OID */
+   {5, "\053\005\001\005\002"},
+   /* this is the v2 assigned OID */
+   {9, "\052\206\110\206\367\022\001\002\003"},
+   /* these two are name type OID's */
+   {10, "\052\206\110\206\367\022\001\002\002\001"},
+   {10, "\052\206\110\206\367\022\001\002\002\002"},
+   { 0, 0 }
+};
+
+static
+CONST gss_OID_desc * CONST gss_mech_krb5_v2 = ck_krb5_gss_oid_array+2;
+
+#ifdef MACOSX103
+static
+CONST gss_OID_desc * CONST gss_mech_krb5 = ck_krb5_gss_oid_array+0;
+#endif /* MACOSX103 */
+
+#ifndef MACOSX
+static
+CONST gss_OID_desc * CONST gss_mech_krb5 = ck_krb5_gss_oid_array+0;
+static
+CONST gss_OID_desc * CONST gss_mech_krb5_old = ck_krb5_gss_oid_array+1;
+static
+CONST gss_OID_desc * CONST gss_nt_krb5_name = ck_krb5_gss_oid_array+3;
+static
+CONST gss_OID_desc * CONST gss_nt_krb5_principal = ck_krb5_gss_oid_array+4;
+#endif /* MACOSX */
+
+/*
+ * See krb5/gssapi_krb5.c for a description of the algorithm for
+ * encoding an object identifier.
+ */
+
+/*
+ * The OID of user_name is:
+ *      iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
+ *      generic(1) user_name(1) = 1.2.840.113554.1.2.1.1
+ * machine_uid_name:
+ *      iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
+ *      generic(1) machine_uid_name(2) = 1.2.840.113554.1.2.1.2
+ * string_uid_name:
+ *      iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
+ *      generic(1) string_uid_name(3) = 1.2.840.113554.1.2.1.3
+ * service_name:
+ *      iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
+ *      generic(1) service_name(4) = 1.2.840.113554.1.2.1.4
+ * exported_name:
+ *      1(iso), 3(org), 6(dod), 1(internet), 5(security), 6(nametypes),
+ *          4(gss-api-exported-name)
+ * host_based_service_name (v2):
+ *      iso (1) org (3), dod (6), internet (1), security (5), nametypes(6),
+ *      gss-host-based-services(2)
+ */
+
+static gss_OID_desc ck_oids[] = {
+   {10, "\052\206\110\206\367\022\001\002\001\001"},
+   {10, "\052\206\110\206\367\022\001\002\001\002"},
+   {10, "\052\206\110\206\367\022\001\002\001\003"},
+   {10, "\052\206\110\206\367\022\001\002\001\004"},
+   { 6, "\053\006\001\005\006\004"},
+   { 6, "\053\006\001\005\006\002"},
+};
+
+static gss_OID ck_gss_nt_user_name = ck_oids+0;
+static gss_OID ck_gss_nt_machine_uid_name = ck_oids+1;
+static gss_OID ck_gss_nt_string_uid_name = ck_oids+2;
+static gss_OID ck_gss_nt_service_name = ck_oids+3;
+static gss_OID ck_gss_nt_exported_name = ck_oids+4;
+static gss_OID ck_gss_nt_service_name_v2 = ck_oids+5;
+#endif /* MACOSX */
 #endif /* FTP_GSSAPI */
 
 #ifdef OS2
@@ -647,7 +800,14 @@ extern int success, nfils, sndsrc, quiet, nopush, recursive, inserver, binary;
 extern int filepeek, nscanfile, fsecs, xferstat, xfermode, lastxfer, tsecs;
 extern int backgrd, spackets, rpackets, spktl, rpktl, xaskmore, cmd_rows;
 extern int nolinks, msgflg, keep;
-extern long fsize, ffc, tfc, filcnt, xfsecs, tfcps, cps, oldcps;
+extern CK_OFF_T fsize, ffc, tfc, sendstart, sndsmaller, sndlarger, rs_len;
+extern long filcnt, xfsecs, tfcps, cps, oldcps;
+
+#ifdef FTP_TIMEOUT
+int ftp_timed_out = 0;
+long ftp_timeout = 0;
+#endif /* FTP_TIMEOUT */
+
 #ifdef GFTIMER
 extern CKFLOAT fptsecs, fpfsecs, fpxfsecs;
 #else
@@ -673,7 +833,6 @@ extern int fcharset;
 extern char sndbefore[], sndafter[], *sndexcept[]; /* Selection criteria */
 extern char sndnbefore[], sndnafter[], *rcvexcept[];
 extern CHAR feol;
-extern long sendstart, sndsmaller, sndlarger, rs_len;
 
 extern char * remdest;
 extern int remfile, remappd, rempipe;
@@ -749,6 +908,7 @@ int ftp_log = 1;                        /* FTP Auto-login */
 int sav_log = -1;
 int ftp_action = 0;                     /* FTP action from command line */
 int ftp_dates = 1;                      /* Set file dates from server */
+int ftp_xfermode = XMODE_A;            /* FTP-specific transfer mode */
 
 char ftp_reply_str[FTP_BUFSIZ] = "";    /* Last line of previous reply */
 char ftp_srvtyp[SRVNAMLEN] = { NUL, NUL }; /* Server's system type */
@@ -832,7 +992,7 @@ static int stouarg = 1;
 static int typesent = 0;
 static int havesigint = 0;
 static long havetype =  0;
-static long havesize = -1L;
+static CK_OFF_T havesize = (CK_OFF_T)-1;
 static char * havemdtm = NULL;
 static int mgetmethod = 0;             /* NLST or MLSD */
 static int mgetforced = 0;
@@ -948,7 +1108,9 @@ FILE * fp_nml = NULL;                   /* Namelist file pointer */
 
 static int csocket = -1;                /* Control socket */
 static int connected = 0;               /* Connected to FTP server */
-static short ftp_port = 0;              /* FTP port */
+/* static unsigned short ftp_port = 0; */ /* FTP port */ 
+/* static int ftp_port = 0; */         /* SMS 2007/02/15 */
+static int ftp_port = 0;               /* fdc 2007/08/30 */
 #ifdef FTPHOST
 static int hostcmd = 0;                 /* Has HOST command been sent */
 #endif /* FTPHOST */
@@ -1015,6 +1177,7 @@ static char ftpcmdbuf[FTP_BUFSIZ];
 #define FTP_VDI 36
 #define FTP_ENA 37
 #define FTP_DIS 38
+#define FTP_REP 39
 
 struct keytab gprtab[] = {              /* GET-PUT-REMOTE keywords */
     { "auto",    2, 0 },
@@ -1061,6 +1224,8 @@ static struct keytab ftpcmdtab[] = {    /* FTP command table */
     { "quote",     FTP_QUO, 0 },
     { "reget",     FTP_RGE, 0 },
     { "rename",    FTP_REN, 0 },
+    { "reput",     FTP_REP, 0 },
+    { "resend",    FTP_REP, CM_INV },
     { "reset",     FTP_RES, 0 },
     { "rmdir",     FTP_RMD, 0 },
     { "send",      FTP_PUT, CM_INV },
@@ -1162,6 +1327,7 @@ static int nftpena = (sizeof(ftpenatab) / sizeof(struct keytab)) - 1;
 #define FTS_APW 25                     /* Anonymous password */
 #define FTS_DIS 26                     /* File-transfer display style */
 #define FTS_BUG 27                      /* Bug(s) */
+#define FTS_TMO 28                     /* Timeout */
 
 /* FTP BUGS */
 
@@ -1327,6 +1493,9 @@ static struct keytab ftpset[] = {       /* SET FTP commmand table */
 #else
     { "srp",                      FTS_SRP, CM_INV },
 #endif /* FTP_SRP */
+#ifdef FTP_TIMEOUT
+    { "timeout",                  FTS_TMO, 0 },
+#endif /* FTP_TIMEOUT */
     { "type",                     FTS_TYP, 0 },
     { "unique-server-names",      FTS_USN, 0 },
     { "verbose-mode",             FTS_VBM, 0 },
@@ -1899,8 +2068,8 @@ ftplogend() {
     if (t2 > -1L) {
         ftplogprev = t2;
         p = hhmmss(t2);
-        strncat(ftplogbuf,"E=",CXLOGBUFL); /* Append to log record */
-        strncat(ftplogbuf,p,CXLOGBUFL);
+        ckstrncat(ftplogbuf,"E=",CXLOGBUFL); /* Append to log record */
+        ckstrncat(ftplogbuf,p,CXLOGBUFL);
     } else
       ftplogprev = 0L;
     debug(F101,"ftp cx log dialog","",dialog);
@@ -1925,7 +2094,8 @@ dologftp() {
 
     ckmakxmsg(ftplogbuf,CXLOGBUFL,
               ckdate()," ",strval(ftp_logname,NULL)," ",ckgetpid(),
-              " T=FTP N=", strval(ftp_host,NULL)," H=",myhost," ",NULL,NULL);
+              " T=FTP N=", strval(ftp_host,NULL)," H=",myhost,
+              " P=", ckitoa(ftp_port)," "); /* SMS 2007/02/15 */
     debug(F110,"ftp cx log begin",ftplogbuf,0);
 }
 #endif /* CKLOGDIAL */
@@ -2055,7 +2225,7 @@ doftparg(c) char c;
           case 'a':                     /* "ascii" */
           case 'b':                     /* Binary */
             binary = (c == 'b') ? FTT_BIN : FTT_ASC;
-            xfermode = XMODE_M;
+            ftp_xfermode = XMODE_M;
             filepeek = 0;
             patterns = 0;
             break;
@@ -2397,10 +2567,10 @@ ftpissecure() {
 }
 
 static VOID
-ftscreen(n, c, z, s) int n; char c; long z; char * s; {
+ftscreen(n, c, z, s) int n; char c; CK_OFF_T z; char * s; {
     if (displa && fdispla && !backgrd && !quiet && !out2screen) {
         if (!dpyactive) {
-            ckscreen(SCR_PT,'S',0L,"");
+            ckscreen(SCR_PT,'S',(CK_OFF_T)0,"");
             dpyactive = 1;
         }
         ckscreen(n,c,z,s);
@@ -2470,9 +2640,9 @@ dosetftp() {
         if ((x = cmkey(ftptyp,nftptyp,"","",xxstring)) < 0)
           return(x);
         if ((y = cmcfm()) < 0) return(y);
-        ftp_typ = x;
-        g_ftp_typ = x;
-        tenex = (ftp_typ == FTT_TEN);
+       ftp_typ = x;
+       g_ftp_typ = x;
+       tenex = (ftp_typ == FTT_TEN);
         return(1);
 
       case FTS_USN:                     /* Unique server names */
@@ -2521,9 +2691,19 @@ dosetftp() {
       case FTS_DAT:
         return(seton(&ftp_dates));      /* Set file dates */
 
+#ifdef FTP_TIMEOUT
+      case FTS_TMO:                    /* Timeout */
+        if ((x = cmnum("Number of seconds","0",10,&z,xxstring)) < 0)
+          return(x);
+        if ((y = cmcfm()) < 0)
+          return(y);
+       ftp_timeout = z;
+       return(success = 1);
+#endif /* FTP_TIMEOUT */
+
       case FTS_STO: {                  /* Server time offset */
          char * s, * p = NULL;
-         int k;
+         long k;
          if ((x = cmfld("[+-]hh[:mm[:ss]]","+0",&s,xxstring)) < 0)
            return(x);
          if (!strcmp(s,"+0")) {
@@ -2939,6 +3119,15 @@ openftp(s,opn_tls) char * s; int opn_tls; {
     return(rc);
 }
 
+VOID                                   /* 12 Aug 2007 */
+doftpglobaltype(x) int x; {
+    ftp_xfermode = XMODE_M;            /* Set manual FTP transfer mode */
+    ftp_typ = x;                       /* Used by top-level BINARY and */
+    g_ftp_typ = x;                     /* ASCII commands. */
+    get_auto = 0;
+    forcetype = 1;
+}
+
 int
 doftpacct() {
     int x;
@@ -2955,17 +3144,32 @@ doftpacct() {
 
 int
 doftpusr() {                            /* Log in as USER */
+    extern char uidbuf[];
+    extern char pwbuf[];
+    extern int  pwflg, pwcrypt;
     int x;
     char *s, * acct = "";
 
     debok = 0;                          /* Don't log */
-    if ((x = cmfld("Remote username or ID","",&s,xxstring)) < 0)
+
+    if ((x = cmfld("Remote username or ID",uidbuf,&s,xxstring)) < 0)
       return(x);
     ckstrncpy(line,brstrip(s),LINBUFSIZ); /* brstrip: 15 Jan 2003 */
-    if ((x = cmfld("Remote password","",&s,xxstring)) < 0)
-      if (x != -3)
-        return(x);
-    ckstrncpy(tmpbuf,brstrip(s),TMPBUFSIZ);
+    if ((x = cmfld("Remote password","",&s,xxstring)) < 0) {
+        if (x == -3) { /* no input */
+            if ( pwbuf[0] && pwflg ) {
+                ckstrncpy(tmpbuf,(char *)pwbuf,TMPBUFSIZ);
+#ifdef OS2
+                if ( pwcrypt )
+                    ck_encrypt((char *)tmpbuf);
+#endif /* OS2 */
+            }
+        } else {
+            return(x);
+        }
+    } else {
+        ckstrncpy(tmpbuf,brstrip(s),TMPBUFSIZ);
+    }
     if ((x = cmtxt("Remote account\n or Enter or CR to confirm the command",
                    "", &s, xxstring)) < 0)
       return(x);
@@ -2993,6 +3197,7 @@ doftptyp(type) int type; {              /* TYPE */
     CHECKCONN();
     ftp_typ = type;
     changetype(ftp_typ,ftp_vbm);
+    debug(F101,"doftptyp changed type","",type);
     return(1);
 }
 
@@ -3244,22 +3449,32 @@ doftpcdup() {                           /* CDUP */
 
 /* s y n c d i r  --  Synchronizes client & server directories */
 
-/* Used with recursive PUTs; Returns 0 on failure, 1 on success */
-
-static int cdlevel = 0, cdsimlvl = 0;
+/*
+  Call with:
+    local = pointer to pathname of local file to be sent.
+    sim   = 1 for simulation, 0 for real uploading.
+  Returns 0 on failure, 1 on success.
+
+  The 'local' argument is relative to the initial directory of the MPUT,
+  i.e. the root of the tree being uploaded.  If the directory of the
+  argument file is different from the directory of the previous file
+  (which is stored in global putpath[]), this routine does the appropriate
+  CWDs, CDUPs, and/or MKDIRs to position the FTP server in the same place.
+*/
+static int cdlevel = 0, cdsimlvl = 0;  /* Tree-level trackers */
 
 static int
 syncdir(local,sim) char * local; int sim; {
     char buf[CKMAXPATH+1];
     char tmp[CKMAXPATH+1];
     char msgbuf[CKMAXPATH+64];
-    char c, * p = local, * s = buf, * q = buf;
+    char c, * p = local, * s = buf, * q = buf, * psep, * ssep;
     int i, k = 0, done = 0, itsadir = 0, saveq;
 
     debug(F110,"ftp syncdir local (new)",local,0);
     debug(F110,"ftp syncdir putpath (old)",putpath,0);
 
-    itsadir = isdir(local);
+    itsadir = isdir(local);            /* Is the local file a directory? */
     saveq = quiet;
 
     while ((*s = *p)) {                 /* Copy the argument filename */
@@ -3270,12 +3485,12 @@ syncdir(local,sim) char * local; int sim; {
         s++;
         p++;
     }
-    if (!itsadir)
-      *q = NUL;                         /* Keep just the path part */
+    if (!itsadir)                      /* If it's a regular file */
+      *q = NUL;                         /* keep just the path part */
 
     debug(F110,"ftp syncdir buf",buf,0);
-    if (!strcmp(buf,putpath)) {         /* Same as for previous file? */
-        if (itsadir) {                  /* It's a directory? */
+    if (!strcmp(buf,putpath)) {         /* Same path as previous file? */
+        if (itsadir) {                  /* This file is a directory? */
             if (doftpcwd(local,0)) {    /* Try to CD to it */
                 doftpcdup();            /* Worked - CD back up */
             } else if (sim) {           /* Simulating... */
@@ -3284,19 +3499,19 @@ syncdir(local,sim) char * local; int sim; {
                 } else if (fdispla) {
                     ckmakmsg(msgbuf,CKMAXPATH,
                              "WOULD CREATE DIRECTORY",local,NULL,NULL);
-                    ftscreen(SCR_ST,ST_MSG,0l,msgbuf);
+                    ftscreen(SCR_ST,ST_MSG,(CK_OFF_T)0,msgbuf);
                 }
                 /* See note above */
                 return(0);
             } else if (!doftpxmkd(local,0)) { /* Can't CD - try to create */
                 return(0);
-            } else {
+            } else {                   /* Remote directory created OK */
                 if (fdispla == XYFD_B) {
                     printf("CREATED DIRECTORY %s\n",local);
                 } else if (fdispla) {
                     ckmakmsg(msgbuf,CKMAXPATH+64,
                              "CREATED DIRECTORY ",local,NULL,NULL);
-                    ftscreen(SCR_ST,ST_MSG,0l,msgbuf);
+                    ftscreen(SCR_ST,ST_MSG,(CK_OFF_T)0,msgbuf);
                 }
             }
         }
@@ -3309,26 +3524,40 @@ syncdir(local,sim) char * local; int sim; {
     p = buf;                            /* New */
     s = putpath;                        /* Old */
 
-    debug(F110,"ftp syncdir A p",p,0);
-    debug(F110,"ftp syncdir A s",s,0);
-
-    while (*p != NUL && *s != NUL && *p == *s) p++,s++;
+    debug(F110,"ftp syncdir A (old) s",s,0); /* Previous */
+    debug(F110,"ftp syncdir A (new) p",p,0); /* New */
 
-    if (*s == '/' && !*p) s++;          /* Don't count initial slash */
+    psep = buf;
+    ssep = putpath;
+    while (*p != NUL && *s != NUL && *p == *s) {
+       if (*p == '/') { psep = p+1; ssep = s+1; }
+       p++,s++;
+    }
+    /*
+      psep and ssep point to the first path segment that differs.
+      We have to do as many CDUPs as there are path segments in ssep.
+      then we have to do as many MKDs and CWDs as there are segments in psep.
+    */
+    s = ssep;
+    p = psep;
 
-    debug(F110,"ftp syncdir B p",p,0);
-    debug(F110,"ftp syncdir B s",s,0);
+    debug(F110,"ftp syncdir B (old) s",s,0); /* Previous */
+    debug(F110,"ftp syncdir B (new) p",p,0); /* New */
 
-    /* p and s now point to the leftmost spot where they differ */
+    /* p and s now point to the leftmost spot where the paths differ */
 
     if (*s) {                           /* We have to back up */
-        k = 1;                          /* How many levels */
-        while ((c = *s++)) {            /* Count dirseps */
+        k = 1;                          /* How many levels counting this one */
+        while ((c = *s++)) {            /* Count dirseps remaining in prev */
             if (c == '/' && *s)
               k++;
         }
-        for (i = 0; i < k; i++) {       /* Do that many CDUPs */
-            debug(F111,"ftp syncdir up",p,i+1);
+       debug(F101,"ftp syncdir levels up","",k);
+
+        for (i = 1; i <= k; i++) {       /* Do that many CDUPs */
+            debug(F111,"ftp syncdir CDUP A",p,i);
+           if (fdispla == XYFD_B)
+             printf(" CDUP\n");
             if (sim && cdsimlvl) {
                 cdsimlvl--;
             } else {
@@ -3342,10 +3571,14 @@ syncdir(local,sim) char * local; int sim; {
         if (!*p)                        /* If we don't have to go down */
           goto xcwd;                    /* we're done. */
     }
+#ifdef COMMENT
     while (p > buf && *p && *p != '/')  /* If in middle of segment */
       p--;                              /* back up to beginning */
     if (*p == '/')                      /* and terminate there */
       p++;
+#endif /* COMMENT */
+
+    debug(F110,"ftp syncdir NEW PATH",p,0);
 
     s = p;                              /* Point to start of new down path. */
     while (1) {                         /* Loop through characters. */
@@ -3359,15 +3592,17 @@ syncdir(local,sim) char * local; int sim; {
                 if (!doftpcwd(p,0)) {   /* Try to CD to it */
                     if (sim) {
                         if (fdispla == XYFD_B) {
-                            printf("WOULD CREATE DIRECTORY %s\n",local);
+                            printf(" WOULD CREATE DIRECTORY %s\n",local);
                         } else if (fdispla) {
-                            ckmakmsg(msgbuf,CKMAXPATH,"WOULD CREATE DIRECTORY",
+                            ckmakmsg(msgbuf,CKMAXPATH,
+                                    "WOULD CREATE DIRECTORY",
                                      local,NULL,NULL);
-                            ftscreen(SCR_ST,ST_MSG,0l,msgbuf);
+                            ftscreen(SCR_ST,ST_MSG,(CK_OFF_T)0,msgbuf);
                         }
                         cdsimlvl++;
                     } else {
                         if (!doftpxmkd(p,0)) { /* Can't CD - try to create */
+                           debug(F110,"ftp syncdir mkdir failed",p,0); 
 /*
   Suppose we are executing SEND /RECURSIVE.  Locally we have a directory
   FOO but the remote has a regular file with the same name.  We can't CD
@@ -3377,17 +3612,21 @@ syncdir(local,sim) char * local; int sim; {
                             quiet = saveq;
                             return(0);
                         }
+                       debug(F110,"ftp syncdir mkdir OK",p,0); 
                         if (fdispla == XYFD_B) {
-                            printf("CREATED DIRECTORY %s\n",p);
+                            printf(" CREATED DIRECTORY %s\n",p);
                         } else if (fdispla) {
                             ckmakmsg(msgbuf,CKMAXPATH,
                                      "CREATED DIRECTORY ",p,NULL,NULL);
-                            ftscreen(SCR_ST,ST_MSG,0l,msgbuf);
+                            ftscreen(SCR_ST,ST_MSG,(CK_OFF_T)0,msgbuf);
                         }
                         if (!doftpcwd(p,0)) { /* Try again to CD */
+                           debug(F110,"ftp syncdir CD failed",p,0); 
                             quiet = saveq;
                             return(0);
                         }
+                        if (fdispla == XYFD_B) printf(" CWD %s\n",p);
+                       debug(F110,"ftp syncdir CD OK",p,0); 
                     }
                 }
                 cdlevel++;
@@ -3554,26 +3793,31 @@ setmodtime(f,t) char * f; time_t t;
     int x, rc = 0;
 #ifdef BSD44
     struct timeval tp[2];
-#else
+#else  /* def BSD44 */
 #ifdef V7
     struct utimbuf {
         time_t timep[2];
     } tp;
-#else
+#else  /* def V7 */
 #ifdef SYSUTIMEH
 #ifdef NT
     struct _utimbuf tp;
 #else /* NT */
     struct utimbuf tp;
 #endif /* NT */
-#else
+#else /* def SYSUTIMEH */
+#ifdef VMS
+    struct utimbuf tp;
+#define SYSUTIMEH               /* Our utimbuf matches this one. */
+#else /* def VMS */
     struct utimbuf {
         time_t atime;
         time_t mtime;
     } tp;
-#endif /* SYSUTIMEH */
-#endif /* V7 */
-#endif /* BSD44 */
+#endif /* def VMS [else] */
+#endif /* def SYSUTIMEH [else] */
+#endif /* def V7 [else] */
+#endif /* def BSD44 [else] */
 
     if (stat(f,&sb) < 0) {
         debug(F111,"setmodtime stat failure",f,errno);
@@ -3672,7 +3916,8 @@ chkmodtime(local,remote,fc) char * local, * remote; int fc; {
     if (fc == 0) {
         rc = stat(local,&statbuf);
         if (rc == 0) {                  /* Get local file's mod time */
-            tmlocal = gmtime(&statbuf.st_mtime); /* Convert to struct tm */
+           /* Convert to struct tm */
+            tmlocal = gmtime((time_t *)&statbuf.st_mtime);
 #ifdef DEBUG
             if (tmlocal) {
                 dbtime(local,tmlocal);
@@ -3814,7 +4059,7 @@ getfile(remote,local,recover,append,pipename,xlate,fcs,rcs)
 
 #ifdef PATTERNS
     /* Automatic type switching? */
-    if (xfermode == XMODE_A && patterns && get_auto && !forcetype) {
+    if (ftp_xfermode == XMODE_A && patterns && get_auto && !forcetype) {
         int x;
         x = matchname(remote,0,servertype);
         debug(F111,"ftp getfile matchname",remote,x);
@@ -3845,7 +4090,8 @@ getfile(remote,local,recover,append,pipename,xlate,fcs,rcs)
       xlate = 0;
 #endif /* NOCSETS */
 
-    if (!pipename && (!local || !local[0]))
+    if (!local) local = "";
+    if (!pipename && !*local)
       local = remote;
 
     out2screen = !strcmp(local,"-");
@@ -3859,8 +4105,8 @@ getfile(remote,local,recover,append,pipename,xlate,fcs,rcs)
           ckstrncpy(fullname,local,CKMAXPATH+1);
     }
     if (!out2screen && displa && fdispla) { /* Screen */
-        ftscreen(SCR_FN,'F',(long)pktnum,remote);
-        ftscreen(SCR_AN,0,0L,fullname);
+        ftscreen(SCR_FN,'F',(CK_OFF_T)pktnum,remote);
+        ftscreen(SCR_AN,0,(CK_OFF_T)0,fullname);
         ftscreen(SCR_FS,0,fsize,"");
     }
     tlog(F110,ftp_typ ? "ftp get BINARY:" : "ftp get TEXT:", remote, 0);
@@ -3893,45 +4139,54 @@ getfile(remote,local,recover,append,pipename,xlate,fcs,rcs)
     sec = (t1 - t0) / 1000;
     xfsecs = (int)sec;
 #endif /* GFTIMER */
+
+#ifdef FTP_TIMEOUT
+    if (ftp_timed_out)
+      rc = -4;
+#endif /* FTP_TIMEOUT */
+
     debug(F111,"ftp recvrequest rc",remote,rc);
     if (cancelfile || cancelgroup) {
         debug(F111,"ftp get canceled",ckitoa(cancelfile),cancelgroup);
-        ftscreen(SCR_ST,ST_INT,0l,"");
+        ftscreen(SCR_ST,ST_INT,(CK_OFF_T)0,"");
     } else if (rc > 0) {
         debug(F111,"ftp get skipped",ckitoa(cancelfile),cancelgroup);
-        ftscreen(SCR_ST,ST_SKIP,0l,cmarg);
+        ftscreen(SCR_ST,ST_SKIP,(CK_OFF_T)0,cmarg);
     } else if (rc < 0) {
         switch (ftpcode) {
           case -4:                      /* Network error */
           case -2:                      /* File error */
-            ftscreen(SCR_ST,ST_MSG,0l,ck_errstr());
+            ftscreen(SCR_ST,ST_MSG,(CK_OFF_T)0,ck_errstr());
             break;
           case -3:
-            ftscreen(SCR_ST,ST_MSG,0l,"Failure to make data connection");
+            ftscreen(SCR_ST,ST_MSG,(CK_OFF_T)0,
+                    "Failure to make data connection");
             break;
-          case -1:
-            ftscreen(SCR_ST,ST_INT,0l,""); /* (should be covered above) */
+          case -1:                     /* (should be covered above) */
+            ftscreen(SCR_ST,ST_INT,(CK_OFF_T)0,"");
             break;
           default:
-            ftscreen(SCR_ST,ST_MSG,0l,&ftp_reply_str[4]);
+            ftscreen(SCR_ST,ST_MSG,(CK_OFF_T)0,&ftp_reply_str[4]);
         }
     } else {                            /* Tudo bem */
-        ftscreen(SCR_PT,'Z',0L,"");
+        ftscreen(SCR_PT,'Z',(CK_OFF_T)0,"");
         if (rc == 0) {
-            ftscreen(SCR_ST,ST_OK,0L,""); /* For screen */
+            ftscreen(SCR_ST,ST_OK,(CK_OFF_T)0,""); /* For screen */
             makestr(&rrfspec,remote);     /* For WHERE command */
             makestr(&rfspec,fullname);
         }
     }
-    if (ftp_dates)                     /* If FTP DATES ON... */
-      if (!pipename && !out2screen)    /* and it's a real file */
-       if (rc < 1 && rc != -3)         /* and it wasn't skipped */
-         if (connected)                /* and we still have a connection */
-           if (zchki(local) > -1) {    /* and the file wasn't discarded */
-               chkmodtime(local,remote,1); /* set local file date */
-               debug(F110,"ftp get set date",local,0);
-           }
-    filcnt++;                           /* Used by \v(filenum) */
+    if (rc > -1) {
+       if (ftp_dates)                  /* If FTP DATES ON... */
+         if (!pipename && !out2screen) /* and it's a real file */
+           if (rc < 1 && rc != -3)     /* and it wasn't skipped */
+             if (connected)            /* and we still have a connection */
+               if (zchki(local) > -1) { /* and the file wasn't discarded */
+                   chkmodtime(local,remote,1); /* set local file date */
+                   debug(F110,"ftp get set date",local,0);
+               }
+       filcnt++;                       /* Used by \v(filenum) */
+    }
 #ifdef TLOG
     if (tralog) {
         if (rc > 0) {
@@ -3940,6 +4195,10 @@ getfile(remote,local,recover,append,pipename,xlate,fcs,rcs)
             tlog(F101," complete, size", "", fsize);
         } else if (cancelfile) {
             tlog(F100," canceled by user","",0);
+#ifdef FTP_TIMEOUT
+        } else if (ftp_timed_out) {
+            tlog(F100," timed out","",0);
+#endif /* FTP_TIMEOUT */
         } else {
             tlog(F110," failed:",ftp_reply_str,0);
         }
@@ -3957,7 +4216,7 @@ static int
 putfile(cx,
     local,remote,force,moving,mvto,rnto,srvrn,x_cnv,x_usn,xft,prm,fcs,rcs,flg)
     char * local, * remote, * mvto, *rnto, *srvrn;
-    int cx, force, moving, x_cnv, x_usn, xft, fcs, rcs, flg;
+    int cx, force, moving, x_cnv, x_usn, xft, fcs, rcs, flg, prm;
 
 /* putfile */ {
 
@@ -3982,7 +4241,7 @@ putfile(cx,
     ofcs = fcs;                         /* Save charset args */
     orcs = rcs;
 
-    sendstart = 0L;
+    sendstart = (CK_OFF_T)0;
     restart = flg & PUT_RES;
     if (!remote)
       remote = "";
@@ -4003,7 +4262,7 @@ putfile(cx,
       nc = x_cnv;
 
     /* If Transfer Mode is Automatic, determine file type */
-    if (xfermode == XMODE_A && filepeek && !pipesend) {
+    if (ftp_xfermode == XMODE_A && filepeek && !pipesend) {
         if (isdir(local)) {             /* If it's a directory */
             k = FT_BIN;                 /* skip the file scan */
         } else {
@@ -4097,8 +4356,8 @@ putfile(cx,
     fullname[CKMAXPATH] = NUL;
 
     if (displa && fdispla) {            /* Screen */
-        ftscreen(SCR_FN,'F',(long)pktnum,local);
-        ftscreen(SCR_AN,0,0L,asname);
+        ftscreen(SCR_FN,'F',(CK_OFF_T)pktnum,local);
+        ftscreen(SCR_AN,0,(CK_OFF_T)0,asname);
         ftscreen(SCR_FS,0,fsize,"");
     }
 #ifdef DOUPDATE
@@ -4107,12 +4366,13 @@ putfile(cx,
         debug(F111,"ftp putfile chkmodtime",asname,mt);
         if (mt == 0 && ((flg & PUT_DIF) == 0)) { /* Local is older */
             tlog(F110,"ftp put /update SKIP (Older modtime): ",fullname,0);
-            ftscreen(SCR_ST,ST_SKIP,SKP_DAT,fullname); /* Skip this one */
+           /* Skip this one */
+            ftscreen(SCR_ST,ST_SKIP,(CK_OFF_T)SKP_DAT,fullname);
             filcnt++;
             return(SKP_DAT);
         } else if (mt == 1) {           /* Times are equal */
             tlog(F110,"ftp put /update SKIP (Equal modtime): ",fullname,0);
-            ftscreen(SCR_ST,ST_SKIP,SKP_EQU,fullname); /* Skip it */
+            ftscreen(SCR_ST,ST_SKIP,(CK_OFF_T)SKP_EQU,fullname); /* Skip it */
             filcnt++;
             return(SKP_DAT);
         }
@@ -4171,18 +4431,18 @@ putfile(cx,
 
     if (cancelfile || cancelgroup) {
         debug(F111,"ftp put canceled",ckitoa(cancelfile),cancelgroup);
-        ftscreen(SCR_ST,ST_INT,0l,"");
+        ftscreen(SCR_ST,ST_INT,(CK_OFF_T)0,"");
     } else if (rc > 0) {
         debug(F101,"ftp put skipped",local,rc);
-        ftscreen(SCR_ST,ST_SKIP,rc,fullname);
+        ftscreen(SCR_ST,ST_SKIP,(CK_OFF_T)rc,fullname);
     } else if (rc < 0) {
         debug(F111,"ftp put error",local,ftpcode);
-        ftscreen(SCR_ST,ST_MSG,0L,&ftp_reply_str[4]);
+        ftscreen(SCR_ST,ST_MSG,(CK_OFF_T)0,&ftp_reply_str[4]);
     } else {
         debug(F111,"ftp put not canceled",ckitoa(displa),fdispla);
-        ftscreen(SCR_PT,'Z',0L,"");
+        ftscreen(SCR_PT,'Z',(CK_OFF_T)0,"");
         debug(F111,"ftp put ST_OK",local,rc);
-        ftscreen(SCR_ST,ST_OK,0L,"");
+        ftscreen(SCR_ST,ST_OK,(CK_OFF_T)0,"");
         debug(F110,"ftp put old sfspec",sfspec,0);
         makestr(&sfspec,fullname);      /* For WHERE command */
         debug(F110,"ftp put new sfspec",sfspec,0);
@@ -4264,7 +4524,7 @@ putfile(cx,
              );
         if (x < 0)
           return(-1);
-        /* ftscreen(SCR_ST,ST_MSG,0L,mvto); */
+        /* ftscreen(SCR_ST,ST_MSG,(CK_OFF_T)0,mvto); */
 
     } else if (rnto) {
         char * s = rnto;
@@ -4289,7 +4549,7 @@ putfile(cx,
                  );
             if (x < 0)
               return(-1);
-            /* ftscreen(SCR_ST,ST_MSG,0L,s); */
+            /* ftscreen(SCR_ST,ST_MSG,(CK_OFF_T)0,s); */
         }
     }
 
@@ -4440,6 +4700,47 @@ iscanceled() {
     return(rc);
 }
 
+#ifdef FTP_TIMEOUT
+/* fc = 0 for read; 1 for write */
+static int
+check_data_connection(fd,fc) int fd, fc; {
+    int x;
+    struct timeval tv;
+    fd_set in, out, err;
+
+    if (ftp_timeout < 1L)
+      return(0);
+
+    FD_ZERO(&in);
+    FD_ZERO(&out);
+    FD_ZERO(&err);
+    FD_SET(fd,fc ? &out : &in);
+    tv.tv_sec = ftp_timeout;           /* Time limit */
+    tv.tv_usec = 0L;
+
+#ifdef INTSELECT
+    x = select(FD_SETSIZE,(int *)&in,(int *)&out,(int *)&err,&tv);
+#else
+    x = select(FD_SETSIZE,&in,&out,&err,&tv);
+#endif /* INTSELECT */
+
+    if (x == 0) {
+#ifdef EWOULDBLOCK
+       errno = EWOULDBLOCK;
+#else
+#ifdef EAGAIN
+       errno = EAGAIN;
+#else
+       errno = 11;
+#endif /* EAGAIN */
+#endif /* EWOULDBLOCK */
+       debug(F100,"ftp check_data_connection TIMOUT","",0);
+       return(-3);
+    }
+    return(0);
+}
+#endif /* FTP_TIMEOUT */
+
 /* zzsend - used by buffered output macros. */
 
 static int
@@ -4457,6 +4758,15 @@ zzsend(fd,c) int fd; CHAR c;
 
     if (iscanceled())                   /* Check for cancellation */
       return(-9);
+
+#ifdef FTP_TIMEOUT    
+    ftp_timed_out = 0;
+    if (check_data_connection(fd,1) < 0) {
+       ftp_timed_out = 1;
+       return(-3);
+    }
+#endif /* FTP_TIMEOUT */
+
     rc = (!ftpissecure()) ?
       send(fd, (SENDARG2TYPE)ucbuf, nout, 0) :
         secure_putbuf(fd, ucbuf, nout);
@@ -4467,7 +4777,7 @@ zzsend(fd,c) int fd; CHAR c;
     pktnum++;
     if (rc > -1 && fdispla != XYFD_B) {
         spktl = nout;
-        ftscreen(SCR_PT,'D',spackets,NULL);
+        ftscreen(SCR_PT,'D',(CK_OFF_T)spackets,NULL);
     }
     return(rc);
 }
@@ -4594,8 +4904,7 @@ cmdlinput(stay) int stay; {
     lastxfer = W_FTP|W_SEND;
     xferstat = success;
     if (dpyactive)
-      ftscreen(SCR_TC,0,0L,"");
-
+      ftscreen(status > 0 ? SCR_TC : SCR_CW, 0, (CK_OFF_T)0, "");
     if (!stay)
       doexit(success ? GOOD_EXIT : BAD_EXIT, -1);
     return(success);
@@ -4632,11 +4941,7 @@ doftpput(cx,who) int cx, who;
     int sec = 0;
 #endif /* GFTIMER */
 
-    struct stringint {                  /* Temporary array for switch values */
-        char * sval;
-        int ival;
-    } pv[SND_MAX+1];
-
+    struct stringint pv[SND_MAX+1];    /* Temporary array for switch values */
     success = 0;                        /* Assume failure */
     forcetype = 0;                      /* No /TEXT or /BINARY given yet */
     out2screen = 0;                     /* Not outputting file to screen */
@@ -4671,6 +4976,7 @@ doftpput(cx,who) int cx, who;
     for (i = 0; i <= SND_MAX; i++) {    /* Initialize switch values */
         pv[i].sval = NULL;              /* to null pointers */
         pv[i].ival = -1;                /* and -1 int values */
+        pv[i].wval = (CK_OFF_T)-1;     /* and -1 wide values */
     }
     if (who == 0) {                     /* Called with unprefixed command */
         switch (cx) {
@@ -4681,6 +4987,8 @@ doftpput(cx,who) int cx, who;
           case XXMSE:   mput++; break;
         }
     } else {
+       if (cx == FTP_REP)
+         pv[SND_RES].ival = 1;
         if (cx == FTP_MPU)
           mput++;
     }
@@ -4956,13 +5264,14 @@ doftpput(cx,who) int cx, who;
             break;
 
           case SND_SMA:                 /* Smaller / larger than */
-          case SND_LAR:
-            if (!getval) break;
-            if ((x = cmnum("Size in bytes","0",10,&y,xxstring)) < 0)
-              goto xputx;
-            pv[n].ival = y;
-            break;
-
+          case SND_LAR: {
+             CK_OFF_T y;
+             if (!getval) break;
+             if ((x = cmnumw("Size in bytes","0",10,&y,xxstring)) < 0)
+               goto xputx;
+             pv[n].wval = y;
+             break;
+         }
           case SND_FIL:                 /* Name of file containing filenames */
             if (!getval) break;
             if ((x = cmifi("Name of file containing list of filenames",
@@ -5153,7 +5462,7 @@ doftpput(cx,who) int cx, who;
     } else if (pv[SND_TEN].ival > 0) {  /* and /TENEX*/
         forcetype = 1;
         ftp_typ = FTT_TEN;
-    } else if (ftp_cmdlin && xfermode == XMODE_M) {
+    } else if (ftp_cmdlin && ftp_xfermode == XMODE_M) {
         forcetype = 1;
         ftp_typ = binary;
         g_ftp_typ = binary;
@@ -5457,8 +5766,7 @@ like \\v(filename)" :
         /* Not MSEND, MMOVE, /LIST, or /ARRAY */
         nfils = sndsrc = -1;
         if (!wild) {
-            y = zchki(s);
-            if (y < 0) {
+            if (zchki(s) < 0) {
                 printf("?Read access denied - \"%s\"\n", s);
                 x = -9;
                 goto xputx;
@@ -5558,9 +5866,9 @@ like \\v(filename)" :
         if (pv[SND_EXC].ival > 0)
           makelist(pv[SND_EXC].sval,sndexcept,NSNDEXCEPT);
         if (pv[SND_SMA].ival > -1)
-          sndsmaller = pv[SND_SMA].ival;
+          sndsmaller = pv[SND_SMA].wval;
         if (pv[SND_LAR].ival > -1)
-          sndlarger = pv[SND_LAR].ival;
+          sndlarger = pv[SND_LAR].wval;
         if (pv[SND_NAM].ival > -1)
           x_cnv = pv[SND_NAM].ival;
         if (pv[SND_USN].ival > -1)
@@ -5655,7 +5963,7 @@ like \\v(filename)" :
         putflags = 0;
 #endif /* PIPESEND */
 
-    tfc = 0L;                           /* Initialize stats and counters */
+    tfc = (CK_OFF_T)0;                 /* Initialize stats and counters */
     filcnt = 0;
     pktnum = 0;
     spackets = 0L;
@@ -5688,6 +5996,7 @@ like \\v(filename)" :
         if (x == 0)                     /* (see gnfile() comments...) */
           x = gnferror;
         debug(F111,"FTP PUT gnfile",filnam,x);
+        debug(F111,"FTP PUT binary",filnam,binary);
 
         switch (x) {
           case 1:                       /* File to send */
@@ -5815,7 +6124,7 @@ like \\v(filename)" :
         lastxfer = W_FTP|W_SEND;
         xferstat = success;
         if (dpyactive)
-          ftscreen(SCR_TC,0,0L,"");
+         ftscreen(status > 0 ? SCR_TC : SCR_CW, 0, (CK_OFF_T)0, "");
     }
     for (i = 0; i <= SND_MAX; i++) {    /* Free malloc'd memory */
         if (pv[i].sval)
@@ -5867,7 +6176,7 @@ cmdlinget(stay) int stay; {
     mgetforced = 0;
 
     havetype = 0;
-    havesize = -1L;
+    havesize = (CK_OFF_T)-1;
     makestr(&havemdtm,NULL);
 
     if (ftp_fnc < 0)
@@ -5938,11 +6247,11 @@ cmdlinget(stay) int stay; {
         cancelfile = 0;                 /* This file not canceled yet */
         s = cmlist[mgetx];
         rc = 0;                         /* Initial return code */
-       fsize = -1L;
+       fsize = (CK_OFF_T)-1;
        if (sizeok) {
            x = ftpcmd("SIZE",s,lcs,rcs,ftp_vbm); /* Get remote file's size */
            if (x == REPLY_COMPLETE)
-             fsize = atol(&ftp_reply_str[4]);
+             fsize = ckatofs(&ftp_reply_str[4]);
        }
         ckstrncpy(filnam,s,CKMAXPATH);  /* For \v(filename) */
         debug(F111,"ftp cmdlinget filnam",filnam,fsize);
@@ -5952,8 +6261,7 @@ cmdlinget(stay) int stay; {
 
         /* If local file already exists, take collision action */
 
-        x = zchki(s2);
-        if (x > -1) {
+        if (zchki(s2) > -1) {
             switch (ftp_fnc) {
               case XYFX_A:              /* Append */
                 append = 1;
@@ -5979,8 +6287,8 @@ cmdlinget(stay) int stay; {
                   break;
               }
               case XYFX_D:              /* Discard */
-                ftscreen(SCR_FN,'F',0L,s);
-                ftscreen(SCR_ST,ST_SKIP,SKP_NAM,s);
+                ftscreen(SCR_FN,'F',(CK_OFF_T)0,s);
+                ftscreen(SCR_ST,ST_SKIP,(CK_OFF_T)SKP_NAM,s);
                 tlog(F100," refused: name","",0);
                 debug(F110,"ftp cmdlinget skip name",s2,0);
                 goto xclget;
@@ -6022,6 +6330,10 @@ cmdlinget(stay) int stay; {
           goto xclget;
         if (rc < 0) {
             ftp_fai++;
+#ifdef FTP_TIMEOUT
+           if (ftp_timed_out)
+             status = 0;
+#endif /* FTP_TIMEOUT */
             if (geterror) {
                 status = 0;
                 done++;
@@ -6074,7 +6386,7 @@ cmdlinget(stay) int stay; {
            continue;
        }
         rc = 0;                         /* Initial return code */
-       if (havesize > -1L) {           /* Already have file size? */
+       if (havesize > (CK_OFF_T)-1) {  /* Already have file size? */
            fsize = havesize;
        } else {                        /* No - must ask server */
            /*
@@ -6086,11 +6398,11 @@ cmdlinget(stay) int stay; {
              of the file, rather than its true size.
            */
            changetype(ftp_typ,0);      /* Change to requested type */
-           fsize = -1L;
+           fsize = (CK_OFF_T)-1;
            if (sizeok) {
                x = ftpcmd("SIZE",s,lcs,rcs,ftp_vbm);
                if (x == REPLY_COMPLETE)
-                 fsize = atol(&ftp_reply_str[4]);
+                 fsize = ckatofs(&ftp_reply_str[4]);
            }
        }
         ckstrncpy(filnam,s,CKMAXPATH);  /* For \v(filename) */
@@ -6101,8 +6413,7 @@ cmdlinget(stay) int stay; {
 
         /* If local file already exists, take collision action */
 
-        x = zchki(s2);
-        if (x > -1) {
+        if (zchki(s2) > -1) {
             switch (ftp_fnc) {
               case XYFX_A:              /* Append */
                 append = 1;
@@ -6128,8 +6439,8 @@ cmdlinget(stay) int stay; {
                   break;
               }
               case XYFX_D:      /* Discard */
-                ftscreen(SCR_FN,'F',0L,s);
-                ftscreen(SCR_ST,ST_SKIP,SKP_NAM,s);
+                ftscreen(SCR_FN,'F',(CK_OFF_T)0,s);
+                ftscreen(SCR_ST,ST_SKIP,(CK_OFF_T)SKP_NAM,s);
                 tlog(F100," refused: name","",0);
                 debug(F110,"ftp cmdlinget skip name",s2,0);
                 continue;
@@ -6161,6 +6472,10 @@ cmdlinget(stay) int stay; {
           continue;
         if (rc < 0) {
             ftp_fai++;
+#ifdef FTP_TIMEOUT
+           if (ftp_timed_out)
+             status = 0;
+#endif /* FTP_TIMEOUT */
             if (geterror) {
                 status = 0;
                 done++;
@@ -6194,7 +6509,7 @@ cmdlinget(stay) int stay; {
     lastxfer = W_FTP|W_RECV;
     xferstat = success;
     if (dpyactive)
-      ftscreen(SCR_TC,0,0L,"");
+      ftscreen(status > 0 ? SCR_TC : SCR_CW, 0, (CK_OFF_T)0, "");
     if (!stay)
       doexit(success ? GOOD_EXIT : BAD_EXIT, -1);
     return(success);
@@ -6219,7 +6534,8 @@ doftpget(cx,who) int cx, who; {         /* who == 1 for ftp, 0 for kermit */
     int moving = 0, deleting = 0, toscreen = 0, haspath = 0;
     int gotsize = 0;
     int matchdot = 0;
-    long getlarger = -1, getsmaller = -1;
+    CK_OFF_T getlarger = (CK_OFF_T)-1;
+    CK_OFF_T getsmaller = (CK_OFF_T)-1;
     char * msg, * s, * s2, * nam, * pipename = NULL, * pn = NULL;
     char * src = "", * local = "";
     char * pat = "";
@@ -6234,10 +6550,7 @@ doftpget(cx,who) int cx, who; {         /* who == 1 for ftp, 0 for kermit */
     int sec = 0;
 #endif /* GFTIMER */
 
-    struct stringint {                  /* Temporary array for switch values */
-        char * sval;
-        int ival;
-    } pv[SND_MAX+1];
+    struct stringint pv[SND_MAX+1];    /* Temporary array for switch values */
 
     success = 0;                        /* Assume failure */
     forcetype = 0;                      /* No /TEXT or /BINARY given yet */
@@ -6281,7 +6594,7 @@ doftpget(cx,who) int cx, who; {         /* who == 1 for ftp, 0 for kermit */
     pipesend = 0;
 
     havetype = 0;
-    havesize = -1L;
+    havesize = (CK_OFF_T)-1;
     makestr(&havemdtm,NULL);
 
     if (g_ftp_typ > -1) {               /* Restore TYPE if saved */
@@ -6291,6 +6604,7 @@ doftpget(cx,who) int cx, who; {         /* who == 1 for ftp, 0 for kermit */
     for (i = 0; i <= SND_MAX; i++) {    /* Initialize switch values */
         pv[i].sval = NULL;              /* to null pointers */
         pv[i].ival = -1;                /* and -1 int values */
+        pv[i].wval = (CK_OFF_T)-1;     /* and -1 wide values */
     }
     zclose(ZMFILE);                     /* In case it was left open */
 
@@ -6530,13 +6844,14 @@ doftpget(cx,who) int cx, who; {         /* who == 1 for ftp, 0 for kermit */
             break;
 
           case SND_SMA:                 /* Smaller / larger than */
-          case SND_LAR:
-            if (!getval) break;
-            if ((x = cmnum("Size in bytes","0",10,&y,xxstring)) < 0)
-              goto xgetx;
-            pv[n].ival = y;
-            break;
-
+          case SND_LAR: {
+             CK_OFF_T y;
+             if (!getval) break;
+             if ((x = cmnumw("Size in bytes","0",10,&y,xxstring)) < 0)
+               goto xgetx;
+             pv[n].wval = y;
+             break;
+         }
           case SND_FIL:                 /* Name of file containing filnames */
             if (!getval) break;
             if ((x = cmifi("Name of file containing list of filenames",
@@ -6693,7 +7008,7 @@ doftpget(cx,who) int cx, who; {         /* who == 1 for ftp, 0 for kermit */
     } else if (pv[SND_TEN].ival > 0) {  /* and /TENEX*/
         forcetype = 1;
         ftp_typ = FTT_TEN;
-    } else if (ftp_cmdlin && xfermode == XMODE_M) {
+    } else if (ftp_cmdlin && ftp_xfermode == XMODE_M) {
         forcetype = 1;
         ftp_typ = binary;
         g_ftp_typ = binary;
@@ -6724,12 +7039,15 @@ doftpget(cx,who) int cx, who; {         /* who == 1 for ftp, 0 for kermit */
 
 /* Set up /MOVE and /RENAME */
 
+#ifdef COMMENT
+    /* Conflict exists only for PUT - removed 13 Mar 2006 - fdc */
     if (pv[SND_DEL].ival > 0 &&
         (pv[SND_MOV].ival > 0 || pv[SND_REN].ival > 0)) {
         printf("?Sorry, /DELETE conflicts with /MOVE or /RENAME\n");
         x = -9;
         goto xgetx;
     }
+#endif /* COMMENT */
 #ifdef CK_TMPDIR
     if (pv[SND_MOV].ival > 0 && pv[SND_MOV].sval) {
         int len;
@@ -6843,10 +7161,10 @@ doftpget(cx,who) int cx, who; {         /* who == 1 for ftp, 0 for kermit */
       deleting = 1;
     if (pv[SND_EXC].ival > 0)
       makelist(pv[SND_EXC].sval,rcvexcept,NSNDEXCEPT);
-    if (pv[SND_SMA].ival > -1)
-      getsmaller = pv[SND_SMA].ival;
-    if (pv[SND_LAR].ival > -1)
-      getlarger = pv[SND_LAR].ival;
+    if (pv[SND_SMA].wval > -1)
+      getsmaller = pv[SND_SMA].wval;
+    if (pv[SND_LAR].wval > -1)
+      getlarger = pv[SND_LAR].wval;
     if (pv[SND_NAM].ival > -1)
       x_cnv = pv[SND_NAM].ival;
     if (pv[SND_ERR].ival > -1)
@@ -6906,7 +7224,7 @@ doftpget(cx,who) int cx, who; {         /* who == 1 for ftp, 0 for kermit */
     }
 #endif /* PIPESEND */
 
-    tfc = 0L;                           /* Initialize stats and counters */
+    tfc = (CK_OFF_T)0;                 /* Initialize stats and counters */
     filcnt = 0;
     pktnum = 0;
     rpackets = 0L;
@@ -6942,7 +7260,7 @@ doftpget(cx,who) int cx, who; {         /* who == 1 for ftp, 0 for kermit */
     what = mdel ? W_FTP|W_FT_DELE : W_RECV|W_FTP; /* What we're doing */
 
     cancelgroup = 0;                    /* Group not canceled yet */
-    if (!(xfermode == XMODE_A && patterns && get_auto && !forcetype))
+    if (!(ftp_xfermode == XMODE_A && patterns && get_auto && !forcetype))
       changetype(ftp_typ,0);           /* Change to requested type */
     binary = ftp_typ;                   /* For file-transfer display */
     first = 1;                          /* For MGET list */
@@ -6976,7 +7294,7 @@ doftpget(cx,who) int cx, who; {         /* who == 1 for ftp, 0 for kermit */
         /* do something here if proxy */
 #endif /* FTP_PROXY */
 
-        rs_len = 0L;                    /* REGET position */
+        rs_len = (CK_OFF_T)0;          /* REGET position */
         cancelfile = 0;                 /* This file not canceled yet */
         haspath = 0;                    /* Recalculate this each time thru */
 
@@ -7024,8 +7342,8 @@ doftpget(cx,who) int cx, who; {         /* who == 1 for ftp, 0 for kermit */
                                             );
                    debug(F110,"ftp mget remote_files C",s,0);
                     if (!s) {
-                        ftscreen(SCR_FN,'F',0L,s);
-                        ftscreen(SCR_ST,ST_MSG,0L,"File not found");
+                        ftscreen(SCR_FN,'F',(CK_OFF_T)0,s);
+                        ftscreen(SCR_ST,ST_MSG,(CK_OFF_T)0,"File not found");
                         tlog(F110,"ftp get file not found:",s,0);
                         goto again;
                     }
@@ -7281,7 +7599,7 @@ doftpget(cx,who) int cx, who; {         /* who == 1 for ftp, 0 for kermit */
            local = *s2 ? s2 : s;
 
            if (!skipthis && x_fnc == XYFX_D) { /* File Collision = Discard */
-               int x;
+               CK_OFF_T x;
                x = zchki(local);
                debug(F111,"ftp get DISCARD zchki",local,x);
                if (x > -1) {
@@ -7318,7 +7636,7 @@ doftpget(cx,who) int cx, who; {         /* who == 1 for ftp, 0 for kermit */
         /* Initialize file size to -1 in case server doesn't understand */
         /* SIZE command, so xxscreen() will know we don't know the size */
 
-        fsize = -1L;
+        fsize = (CK_OFF_T)-1;
 
        /* Ask for size now only if we need it for selection */
        /* because if you're going thru a list 100,000 files to select */
@@ -7326,8 +7644,8 @@ doftpget(cx,who) int cx, who; {         /* who == 1 for ftp, 0 for kermit */
 
        gotsize = 0;
         if (!mdel && !skipthis &&        /* Don't need size for DELE... */
-           (getsmaller > -1L || getlarger > -1L)) {
-           if (havesize > -1L) {       /* Already have file size? */
+           (getsmaller >= (CK_OFF_T)0  || getlarger >= (CK_OFF_T)0)) {
+           if (havesize >= (CK_OFF_T)0) { /* Already have file size? */
                fsize = havesize;
                gotsize = 1;
            } else {                    /* No - must ask server */
@@ -7340,19 +7658,19 @@ doftpget(cx,who) int cx, who; {         /* who == 1 for ftp, 0 for kermit */
                  of the file, rather than its true size.
                */
                changetype(ftp_typ,0);  /* Change to requested type */
-               fsize = -1L;
+               fsize = (CK_OFF_T)-1;
                if (sizeok) {
                    x = ftpcmd("SIZE",s,x_csl,x_csr,ftp_vbm);
                    if (x == REPLY_COMPLETE) {
-                       fsize = atol(&ftp_reply_str[4]);
+                       fsize = ckatofs(&ftp_reply_str[4]);
                        gotsize = 1;
                    }
                }
            }
             if (gotsize) {
-                if (getsmaller > -1L && fsize >= getsmaller)
+                if (getsmaller >= (CK_OFF_T)0 && fsize >= getsmaller)
                   skipthis++;
-                if (getlarger > -1L && fsize <= getlarger)
+                if (getlarger >= (CK_OFF_T)0 && fsize <= getlarger)
                   skipthis++;
                 if (skipthis) {
                     debug(F111,"ftp get skip size",s,fsize);
@@ -7371,11 +7689,11 @@ doftpget(cx,who) int cx, who; {         /* who == 1 for ftp, 0 for kermit */
             }
         }
         if (skipthis) {                 /* Skipping this file? */
-            ftscreen(SCR_FN,'F',0L,s);
+            ftscreen(SCR_FN,'F',(CK_OFF_T)0,s);
             if (msg)
-              ftscreen(SCR_ST,ST_ERR,0L,msg);
+              ftscreen(SCR_ST,ST_ERR,(CK_OFF_T)0,msg);
             else
-              ftscreen(SCR_ST,ST_SKIP,0L,s);
+              ftscreen(SCR_ST,ST_SKIP,(CK_OFF_T)0,s);
             continue;
         }
         if (fp_nml) {                   /* /NAMELIST only - no transfer */
@@ -7399,7 +7717,8 @@ doftpget(cx,who) int cx, who; {         /* who == 1 for ftp, 0 for kermit */
                 rc = -1;                /* Failure is fatal */
                 if (geterror) {
                     status = 0;
-                    ftscreen(SCR_EM,0,0L,"Directory creation failure");
+                    ftscreen(SCR_EM,0,(CK_OFF_T)0,
+                            "Directory creation failure");
                     break;
                 }
             }
@@ -7411,15 +7730,15 @@ doftpget(cx,who) int cx, who; {         /* who == 1 for ftp, 0 for kermit */
         pn = NULL;
 
        if (!gotsize && !mdel) {        /* Didn't get size yet */
-           if (havesize > -1L) {       /* Already have file size? */
+           if (havesize > (CK_OFF_T)-1) { /* Already have file size? */
                fsize = havesize;
                gotsize = 1;
            } else {                    /* No - must ask server */
-               fsize = -1L;
+               fsize = (CK_OFF_T)-1;
                if (sizeok) {
                    x = ftpcmd("SIZE",s,x_csl,x_csr,ftp_vbm);
                    if (x == REPLY_COMPLETE) {
-                       fsize = atol(&ftp_reply_str[4]);
+                       fsize = ckatofs(&ftp_reply_str[4]);
                        gotsize = 1;
                    }
                }
@@ -7482,11 +7801,12 @@ doftpget(cx,who) int cx, who; {         /* who == 1 for ftp, 0 for kermit */
                 !rcvfilter &&
 #endif /* PIPESEND */
                 !toscreen) {
+               CK_OFF_T x;
                 x = zchki(s2);
                 debug(F111,"ftp get zchki",s2,x);
                 debug(F111,"ftp get x_fnc",s2,x_fnc);
 
-                if (x > -1 && !restart) {
+                if (x > (CK_OFF_T)-1 && !restart) {
                    int x = -1;
                    char * newname = NULL;
 
@@ -7507,7 +7827,8 @@ doftpget(cx,who) int cx, who; {         /* who == 1 for ftp, 0 for kermit */
                            debug(F111,"ftp get rename incoming",newname,x);
                        }
                        if (x < 0) {
-                           ftscreen(SCR_EM,0,0L,"Backup/Rename failed");
+                           ftscreen(SCR_EM,0,(CK_OFF_T)0,
+                                    "Backup/Rename failed");
                            x = 0;
                            goto xgetx;
                        }
@@ -7541,9 +7862,11 @@ doftpget(cx,who) int cx, who; {         /* who == 1 for ftp, 0 for kermit */
 #ifdef DEBUG
             if (deblog) {
                 debug(F111,"ftp get rc",s,rc);
+                debug(F111,"ftp get ftp_timed_out",s,ftp_timed_out);
                 debug(F111,"ftp get cancelfile",s,cancelfile);
                 debug(F111,"ftp get cancelgroup",s,cancelgroup);
                 debug(F111,"ftp get renaming",s,renaming);
+                debug(F111,"ftp get moving",s,moving);
             }
 #endif /* DEBUG */
         }
@@ -7557,7 +7880,8 @@ doftpget(cx,who) int cx, who; {         /* who == 1 for ftp, 0 for kermit */
                         ? 1 : -1;
                     tlog(F110, (rc > -1) ?
                          " deleted" : " failed to delete", s, 0);
-                } else if (renaming && rcv_rename && !toscreen) {
+                }
+               if (renaming && rcv_rename && !toscreen) {
                     char *p;            /* Rename downloaded file */
 #ifndef NOSPL
                     char tmpbuf[CKMAXPATH+1];
@@ -7635,9 +7959,16 @@ doftpget(cx,who) int cx, who; {         /* who == 1 for ftp, 0 for kermit */
           continue;
         if (rc < 0) {
             ftp_fai++;
+#ifdef FTP_TIMEOUT
+           debug(F101,"ftp get ftp_timed_out","",ftp_timed_out);
+           if (ftp_timed_out) {
+               status = 0;
+                ftscreen(SCR_EM,0,(CK_OFF_T)0,"GET timed out");
+           }
+#endif /* FTP_TIMEOUT */
             if (geterror) {
                 status = 0;
-                ftscreen(SCR_EM,0,0L,"Fatal download error");
+                ftscreen(SCR_EM,0,(CK_OFF_T)0,"Fatal download error");
                 done++;
             }
         }
@@ -7671,7 +8002,13 @@ doftpget(cx,who) int cx, who; {         /* who == 1 for ftp, 0 for kermit */
           fclose(fp_nml);
         fp_nml = NULL;
     }
-    if (x > -1) {                       /* Download successful */
+    if (
+#ifdef COMMENT
+       x > -1
+#else
+       success
+#endif /* COMMENT */
+       ) {                             /* Download successful */
 #ifdef GFTIMER
         t1 = gmstimer();                /* End time */
         sec = (CKFLOAT)((CKFLOAT)(t1 - t0) / 1000.0); /* Stats */
@@ -7687,7 +8024,7 @@ doftpget(cx,who) int cx, who; {         /* who == 1 for ftp, 0 for kermit */
         xferstat = success;
     }
     if (dpyactive)
-      ftscreen(SCR_TC,0,0L,"");
+      ftscreen(success > 0 ? SCR_TC : SCR_CW, 0, (CK_OFF_T)0, "");
 #ifdef CK_TMPDIR
     if (f_tmpdir) {                     /* If we changed to download dir */
         zchdir((char *) savdir);        /* Go back where we came from */
@@ -7734,6 +8071,8 @@ doftpsite() {                             /* Send a SITE command */
     int reply;
     char * s;
     int lcs = -1, rcs = -1;
+    int save_vbm = ftp_vbm;
+
 #ifndef NOCSETS
     if (ftp_xla) {
         lcs = ftp_csl;
@@ -7747,11 +8086,14 @@ doftpsite() {                           /* Send a SITE command */
     CHECKCONN();
     ckstrncpy(line,s,LINBUFSIZ);
     if (testing) printf(" ftp site \"%s\"...\n",line);
+    if (!ftp_vbm)
+        ftp_vbm = !ckstrcmp("HELP",line,4,0);
     if ((reply = ftpcmd("SITE",line,lcs,rcs,ftp_vbm)) == REPLY_PRELIM) {
        do {
            reply = getreply(0,lcs,rcs,ftp_vbm,0);
        } while (reply == REPLY_PRELIM);
     }
+    ftp_vbm = save_vbm;
     return(success = (reply == REPLY_COMPLETE));
 }
 
@@ -7788,7 +8130,8 @@ doftprmt(cx,who) int cx, who; {         /* who == 1 for ftp, 0 for kermit */
         if ((x = cmtxt("Remote directory", "", &s, xxstring)) < 0)
           return(x);
         ckstrncpy(line,s,LINBUFSIZ);
-        return(doftpcwd((char *)line,1));
+       s = brstrip(line);
+        return(doftpcwd(s,1));
       case XZPWD:                       /* RPWD */
         return(doftppwd());
       case XZDEL:                       /* RDEL */
@@ -8105,6 +8448,7 @@ doxftp() {                              /* Command parser for built-in FTP */
       case FTP_PUT:                     /* PUT */
       case FTP_MPU:                     /* MPUT */
       case FTP_APP:                     /* APPEND */
+      case FTP_REP:                    /* REPUT */
         return(doftpput(cx,1));
 
       case FTP_PWD:                     /* PWD */
@@ -8198,7 +8542,7 @@ doxftp() {                              /* Command parser for built-in FTP */
         if ((x = cmtxt("remote filename", "", &s, xxstring)) < 0)
           return(x);
         CHECKCONN();
-        success = remote_files(1,(CHAR *)s,NULL,0) ? 1 : 0;
+        success = remote_files(1,(CHAR *)s,(CHAR *)s,0) ? 1 : 0;
         return(success);
 
       case FTP_FEA:                     /* RFC2389 */
@@ -8271,7 +8615,7 @@ shopl(x) int x; {
 }
 
 int
-shoftp(brief) {
+shoftp(brief) int brief; {
     char * s = "?";
     int n, x;
 
@@ -8311,6 +8655,9 @@ shoftp(brief) {
       case FTT_BIN: s = "binary"; break;
       case FTT_TEN: s = "tenex"; break;
     }
+#ifdef FTP_TIMEOUT
+    printf(" ftp timeout:                   %ld\n",ftp_timeout);
+#endif /* FTP_TIMEOUT */
     printf(" ftp type:                      %s\n",s);
     printf(" ftp get-filetype-switching:    %s\n",showoff(get_auto));
     printf(" ftp dates:                     %s\n",showoff(ftp_dates));
@@ -8623,7 +8970,7 @@ static char * fhs_mge[] = {             /* MGET */
 #endif /* NOCSETS */
     "  /SERVER-RENAME:text",
     "    Each server source file is to be renamed on the server as indicated",
-    "    immediately after, but only if, it has arrived succesfully.",
+    "    immediately after, but only if, it has arrived successfully.",
     "  /SMALLER-THAN:number",
     "    Download only those files smaller than the given number of bytes.",
     "  /TEXT",                          /* /ASCII */
@@ -8876,6 +9223,13 @@ static char * fhs_put[] = {             /* PUT, SEND */
     "  to send the file or files.  See HELP FTP MPUT.",
     ""
 };
+static char * fhs_reput[] = {          /* REPUT, RESEND */
+    "Syntax: [ FTP ] REPUT [ switches ] filespec [ as-name ]",
+    "  Synonym for FTP PUT /RECOVER.  Recovers an interrupted binary-mode",
+    "  upload from the point of failure if the FTP server supports recovery.",
+    "  Synonym: [ FTP ] RESEND.  For details see HELP FTP MPUT.",
+    ""
+};
 static char * fhs_pwd[] = {             /* PWD */
     "Syntax: FTP PWD",
     "  Asks the FTP server to reveal its current working directory.",
@@ -9034,6 +9388,8 @@ doftphlp() {
         return(hmsga(fhs_opt));
       case FTP_PUT:                     /* PUT, SEND */
         return(hmsga(fhs_put));
+      case FTP_REP:                     /* REPUT, RESEND */
+        return(hmsga(fhs_reput));
       case FTP_PWD:                     /* PWD */
         return(hmsga(fhs_pwd));
       case FTP_QUO:                     /* QUOTE */
@@ -9253,8 +9609,31 @@ dosetftphlp() {
         printf("  Establishes the default transfer mode.\n");
         printf("  TENEX is used for uploading 8-bit binary files to 36-bit\n");
         printf("  platforms such as TENEX and TOPS-20 and for downloading\n");
-        printf("  them again.\n\n");
+        printf("  them again.  ASCII is a synonym for TEXT.  Normally each\n");
+        printf("  file's type is determined automatically from its contents\n"
+              );
+        printf("  or its name; SET FTP TYPE does not prevent that, it only\n");
+        printf("  tells which mode to use when the type can't be determined\n"
+              );
+        printf("  automatically.  To completely disable automatic transfer-\n"
+              );
+        printf("  mode switching and force either text or binary mode, give\n"
+              );
+        printf("  the top-level command ASCII or BINARY, as in traditional\n");
+        printf("  FTP clients.\n\n");
+        return(0);
+
+#ifdef FTP_TIMEOUT
+      case FTS_TMO:
+       printf("\nSyntax: SET FTP TIMEOUT number-of-seconds\n");
+       printf("  Establishes a timeout for FTP transfers.\n");
+       printf("  The timeout applies per network read or write on the data\n");
+       printf("  connection, not to the whole transfer.  By default the\n");
+       printf("  timeout value is 0, meaning no timeout.  Use a positive\n");
+       printf("  number to escape gracefully from hung data connections or\n");
+       printf("  directory listings.\n\n");
         return(0);
+#endif /* FTP_TIMEOUT */
 
 #ifdef PATTERNS
       case FTS_GFT:
@@ -9601,7 +9980,9 @@ ftpclose() {
     extern int quitting;
     if (!connected)
       return(0);
-    if (!ftp_vbm && !quiet) printlines = 1;
+    ftp_xfermode = xfermode;
+    if (!ftp_vbm && !quiet)
+      printlines = 1;
     ftpcmd("QUIT",NULL,0,0,ftp_vbm);
     if (csocket) {
 #ifdef CK_SSL
@@ -9686,7 +10067,7 @@ ftpopen(remote, service, use_tls) char * remote, * service; int use_tls; {
             }
         } else {
             ftp_port = destsp->s_port;
-            ftp_port = ntohs(ftp_port);
+            ftp_port = ntohs((unsigned short)ftp_port);        /* SMS 2007/02/15 */
         }
     } else
         ftp_port = atoi(service);
@@ -9744,6 +10125,8 @@ ftpopen(remote, service, use_tls) char * remote, * service; int use_tls; {
         if (!connected)
          goto fail;
 
+       ftp_xfermode = xfermode;
+
 #ifdef CKLOGDIAL
         dologftp();
 #endif /* CKLOGDIAL */
@@ -10390,7 +10773,7 @@ parsefeat(s) char * s; {                /* Parse a FEATURE response */
          break;
        kwbuf[i] = s[i];
     }
-    if (s[i] && s[i] != SP)
+    if (s[i] && s[i] != SP && s[i] != CR && s[i] != LF)
       return;
     kwbuf[i] = NUL;
     /* xlookup requires a full (but case independent) match */
@@ -10459,7 +10842,7 @@ parsefacts(s) char * s; {               /* Parse MLS[DT] File Facts */
            debug(F110,"ftp parsefact mdtm",havemdtm,0);
            break;
          case FACT_SIZE:               /* Size */
-           havesize = atol(s);
+           havesize = ckatofs(s);
            debug(F101,"ftp parsefact size","",havesize);
            break;
          case FACT_TYPE:               /* Type */
@@ -11093,7 +11476,7 @@ doftpsend(threadinfo) VOID * threadinfo;
     if (initconn()) {
 #ifndef NOHTTP
         int y = -1;
-        debug(F101,"doftpsend","tcp_http_proxy",tcp_http_proxy);
+        /* debug(F101,"doftpsend","tcp_http_proxy",tcp_http_proxy); */
 
        /*  If the connection failed and we are using an HTTP Proxy
         *  and the reason for the failure was an authentication
@@ -11375,22 +11758,23 @@ doftpsend2(threadinfo) VOID * threadinfo;
             }
             if (*p && *p != CR) {       /* Bad number */
                 debug(F110,"doftpsend2 bad size",ftp_reply_str,0);
-                sendstart = 0L;
+                sendstart = (CK_OFF_T)0;
             } else if (sendstart > fsize) { /* Remote file bigger than local */
-                debug(F110,"doftpsend2 big size",ckltoa(fsize),sendstart);
-                sendstart = 0L;
+                debug(F110,"doftpsend2 big size",ckfstoa(fsize),sendstart);
+                sendstart = (CK_OFF_T)0;
             }
            /* Local is newer */
             debug(F111,"doftpsend2 size",ftpsnd.remote,sendstart);
             if (chkmodtime(ftpsnd.local,ftpsnd.remote,0) == 2) {
                 debug(F110,"doftpsend2 date mismatch",ftp_reply_str,0);
-                sendstart = 0L;         /* Send the whole file */
+                sendstart = (CK_OFF_T)0; /* Send the whole file */
             }
         }
         changetype(ftp_typ,0);          /* Change back to appropriate type */
-        if (sendstart > 0L) {           /* Still restarting? */
+        if (sendstart > (CK_OFF_T)0) { /* Still restarting? */
             if (sendstart == fsize) {   /* Same size - no need to send */
-                debug(F111,"doftpsend2 /restart SKIP",fsize,sendstart);
+                debug(F111,"doftpsend2 /restart SKIP",
+                     ckfstoa(fsize),sendstart);
                 zclose(ZIFILE);
                 ftpsndret = SKP_RES;
 #ifdef NTSIG
@@ -11429,7 +11813,7 @@ doftpsend2(threadinfo) VOID * threadinfo;
             sendmode = SM_RESEND;
             ftpsnd.cmd = "APPE";
 #endif /* COMMENT */
-            /* sendstart = 0L; */
+            /* sendstart = (CK_OFF_T)0; */
         }
     }
 #endif /* FTP_RESTART */
@@ -11439,6 +11823,7 @@ doftpsend2(threadinfo) VOID * threadinfo;
 
     x = ftpcmd(ftpsnd.cmd, ftpsnd.remote, ftpsnd.incs, ftpsnd.outcs, ftp_vbm);
     debug(F111,"doftpsend2 ftpcode",ftpsnd.cmd,ftpcode);
+    debug(F101,"doftpsend2 ftpcmd","",x);
 
     if (x != REPLY_PRELIM && unique) {
        /*
@@ -11465,6 +11850,7 @@ doftpsend2(threadinfo) VOID * threadinfo;
         if (ftpsnd.oldintp)
           signal(SIGPIPE, ftpsnd.oldintp);
 #endif /* SIGPIPE */
+       debug(F101,"doftpsend2 not REPLY_PRELIM","",x);
         zclose(ZIFILE);
 #ifdef PIPESEND
         if (sndfilter)
@@ -11476,7 +11862,9 @@ doftpsend2(threadinfo) VOID * threadinfo;
 #endif /* NTSIG */
         return;
     }
+    debug(F100,"doftpsend2 getting data connection...","",0);
     dout = dataconn(ftpsnd.lmode);             /* Get data connection */
+    debug(F101,"doftpsend2 dataconn","",dout);
     if (dout == -1) {
         failftpsend2(threadinfo);
 #ifdef NTSIG
@@ -11485,8 +11873,9 @@ doftpsend2(threadinfo) VOID * threadinfo;
         return;
     }
     /* Initialize per-file stats */
-    ffc = 0L;                           /* Character counter */
+    ffc = (CK_OFF_T)0;                 /* Character counter */
     cps = oldcps = 0L;                  /* Thruput */
+    n = 0;
 #ifdef GFTIMER
     rftimer();                          /* reset f.p. timer */
 #endif /* GFTIMER */
@@ -11494,15 +11883,27 @@ doftpsend2(threadinfo) VOID * threadinfo;
 #ifdef SIGPIPE
     ftpsnd.oldintp = signal(SIGPIPE, SIG_IGN);
 #endif /* SIGPIPE */
+    debug(F101,"doftpsend2 curtype","",curtype);
     switch (curtype) {
       case FTT_BIN:                     /* Binary mode */
       case FTT_TEN:
         errno = d = 0;
+#ifdef VMS
+       /*
+         This is because VMS zxin() is C-Library fread() 
+          but the file was opened with zopeni(), which is RMS.
+       */
+       while (((c = zminchar()) > -1) && !cancelfile) {
+           ffc++;
+           if (zzout(dout,c) < 0)
+             break;
+       }
+#else  /* VMS */
         while ((n = zxin(ZIFILE,buf,FTP_BUFSIZ - 1)) > 0 && !cancelfile) {
             ftpsnd.bytes += n;
             ffc += n;
             debug(F111,"doftpsend2 zxin",ckltoa(n),ffc);
-            hexdump("doftpsend2 zxin",buf,16);
+            ckhexdump("doftpsend2 zxin",buf,16);
 #ifdef CK_SSL
             if (ssl_ftp_data_active_flag) {
                 for (bufp = buf; n > 0; n -= d, bufp += d) {
@@ -11512,7 +11913,7 @@ doftpsend2(threadinfo) VOID * threadinfo;
                     pktnum++;
                     if (fdispla != XYFD_B) {
                         spktl = d;
-                        ftscreen(SCR_PT,'D',spackets,NULL);
+                        ftscreen(SCR_PT,'D',(CK_OFF_T)spackets,NULL);
                     }
                 }
             } else {
@@ -11525,7 +11926,7 @@ doftpsend2(threadinfo) VOID * threadinfo;
                     pktnum++;
                     if (fdispla != XYFD_B) {
                         spktl = d;
-                        ftscreen(SCR_PT,'D',spackets,NULL);
+                        ftscreen(SCR_PT,'D',(CK_OFF_T)spackets,NULL);
                     }
                 }
 #ifdef CK_SSL
@@ -11534,6 +11935,9 @@ doftpsend2(threadinfo) VOID * threadinfo;
             if (d <= 0)
               break;
         }
+#endif /* VMS */
+
+       debug(F111,"doftpsend2 XX zxin",ckltoa(n),ffc);
         if (n < 0)
           fprintf(stderr, "local: %s: %s\n", ftpsnd.local, ck_errstr());
         if (d < 0 || (d = secure_flush(dout)) < 0) {
@@ -11685,9 +12089,30 @@ sendrequest(cmd, local, remote, xlate, incs, outcs, restart)
       pipesend = 1;                     /* set this for open and i/o */
 #endif /* PIPESEND */
     
-    if (openi(local) == 0)              /* Try to open the input file */
-        return(-1);
+#ifdef VMS
+    debug(F101,"XXX before openi binary","",binary);
+    debug(F101,"XXX before openi ftp_typ","",ftp_typ);
+#endif /* VMS */
+
+    if (openi(local) == 0)             /* Try to open the input file */
+      return(-1);
 
+#ifdef VMS
+    debug(F101,"XXX after openi binary","",binary);
+    debug(F101,"XXX after openi ftp_typ","",ftp_typ);
+    if (!forcetype) {
+       if (binary != ftp_typ) {        /* VMS zopeni() sets binary */
+           debug(F101,"XXX changing type","",binary);
+           doftptyp(binary);
+           debug(F101,"XXX after doftptyp","",ftp_typ);
+
+           /* **** */
+           if (displa && fdispla) {    /* Update file type display */
+               ftscreen(SCR_FN,'F',(CK_OFF_T)0,local);
+           }
+       }
+    }
+#endif /* VMS */
     ftpsndret = 0;
     ftpsnd.incs = incs;
     ftpsnd.outcs = outcs;
@@ -11760,7 +12185,7 @@ struct xx_ftprecv {
     char * lmode;
     char * pipename;
     int    tcrflag;
-    long   localsize;
+    CK_OFF_T localsize;
 };
 static struct xx_ftprecv ftprecv;
 
@@ -11934,6 +12359,12 @@ failftprecv2(threadinfo) VOID * threadinfo;
         return;
     }
     cancel_remote(ftprecv.din);
+
+#ifdef FTP_TIMEOUT
+    if (ftp_timed_out && out2screen && !quiet)
+      printf("\n?Timed out.\n");
+#endif /* FTP_TIMEOUT */
+
     if (ftpcode > -1)
       ftpcode = -1;
     if (data >= 0) {
@@ -12012,7 +12443,7 @@ doftprecv2(threadinfo) VOID * threadinfo;
 #endif /* CK_ANSIC */
 {
     register int c, d;
-    long bytes = 0L;
+    CK_OFF_T bytes = (CK_OFF_T)0;
     int bare_lfs = 0;
     int blksize = 0;
     ULONG start = 0L, stop;
@@ -12024,6 +12455,10 @@ doftprecv2(threadinfo) VOID * threadinfo;
 #endif /* CK_URL */
     extern int adl_ask;
 
+#ifdef FTP_TIMEOUT
+    ftp_timed_out = 0;
+#endif /* FTP_TIMEOUT */
+
     ftprecv.din = -1;
 #ifdef NTSIG
     if (threadinfo) {                   /* Thread local storage... */
@@ -12041,7 +12476,7 @@ doftprecv2(threadinfo) VOID * threadinfo;
 #endif /* CK_LOGIN */
 
     if (ftprecv.recover) {                      /* Initiate recovery */
-        x = ftpcmd("REST",ckltoa(ftprecv.localsize),-1,-1,ftp_vbm);
+        x = ftpcmd("REST",ckfstoa(ftprecv.localsize),-1,-1,ftp_vbm);
         debug(F111,"ftp reply","REST",x);
         if (x == REPLY_CONTINUE) {
             ftprecv.lmode = "ab";
@@ -12153,7 +12588,7 @@ Please confirm output file specification or supply an alternative:";
     }
     debug(F111,"ftp get rcvbufsiz",ftprecv.local,rcvbufsiz);
 
-    ffc = 0L;                           /* Character counter */
+    ffc = (CK_OFF_T)0;                 /* Character counter */
     cps = oldcps = 0L;                  /* Thruput */
     start = gmstimer();                 /* Start time (msecs) */
 #ifdef GFTIMER
@@ -12199,12 +12634,20 @@ Please confirm output file specification or supply an alternative:";
             bytes += c;
             ffc += c;
         }
+#ifdef FTP_TIMEOUT
+       if (c == -3) {
+            debug(F100,"ftp recvrequest timeout","",0); 
+            bytes = (CK_OFF_T)-1;
+           ftp_timed_out = 1;
+           ftpcode = -3;
+       } else
+#endif /* FTP_TIMEOUT */
         if (c < 0) {
             debug(F111,"ftp recvrequest errno",ckitoa(c),errno);
             if (c == -1 && errno != EPIPE)
               if ((!dpyactive || ftp_deb))
                 perror("netin");
-            bytes = -1;
+            bytes = (CK_OFF_T)-1;
             ftpcode = -4;
         }
         if (d < c) {
@@ -12302,7 +12745,11 @@ Please confirm output file specification or supply an alternative:";
 #endif /* NOCSETS */
             while (1) {
                 c = secure_getc(ftprecv.din,0);
-                if (cancelfile) {
+                if (cancelfile
+#ifdef FTP_TIMEOUT
+                   || ftp_timed_out
+#endif /* FTP_TIMEOUT */
+                   ) {
                     failftprecv2(threadinfo);
 #ifdef NTSIG
                     ckThreadEnd(threadinfo);
@@ -12360,10 +12807,10 @@ Please confirm output file specification or supply an alternative:";
                 printf("File might not have transferred correctly.\n");
             }
             if (ftprecv.din == -1) {
-                bytes = -1;
+                bytes = (CK_OFF_T)-1;
             }
             if (c == -2)
-              bytes = -1;
+              bytes = (CK_OFF_T)-1;
             break;
 #ifndef NOCSETS
         }
@@ -12442,7 +12889,7 @@ recvrequest(cmd, local, remote, lmode, printnames, recover, pipename,
     }
 #endif /* DEBUG */
 
-    ftprecv.localsize = 0L;
+    ftprecv.localsize = (CK_OFF_T)0;
 
     if (remfile) {                      /* See remcfm(), remtxt() */
         if (rempipe) {
@@ -12490,8 +12937,8 @@ recvrequest(cmd, local, remote, lmode, printnames, recover, pipename,
     }
 #endif /* COMMENT */
 
-    ftprecv.localsize = 0L;            /* Local file size */
-    rs_len = 0L;                        /* Recovery point */
+    ftprecv.localsize = (CK_OFF_T)0;   /* Local file size */
+    rs_len = (CK_OFF_T)0;              /* Recovery point */
 
     debug(F101,"ftp recvrequest recover","",recover);
     if (recover) {                      /* Recovering... */
@@ -12553,6 +13000,14 @@ recvrequest(cmd, local, remote, lmode, printnames, recover, pipename,
     ftprecv.oldintr = signal(SIGINT, cancelrecv);
     if (cc_execute(ckjaddr(recvcancel), doftprecv, failftprecv) < 0)
       return -1;
+
+#ifdef FTP_TIMEOUT
+    debug(F111,"ftp recvrequest ftprecvret",remote,ftprecvret);
+    debug(F111,"ftp recvrequest ftp_timed_out",remote,ftp_timed_out);
+    if (ftp_timed_out)
+      ftprecvret = -1;
+#endif /* FTP_TIMEOUT */
+
     if (ftprecvret < 0)
       return -1;
 
@@ -12629,7 +13084,8 @@ initconn() {
             *q = '\0';
 
             hisctladdr.sin_addr.s_addr = inet_addr(host);
-            if (hisctladdr.sin_addr.s_addr != -1) {
+            if (hisctladdr.sin_addr.s_addr != INADDR_NONE) /* 2010-03-29 */
+           {
                 debug(F110,"initconn A",host,0);
                 hisctladdr.sin_family = AF_INET;
             } else {
@@ -12918,7 +13374,7 @@ ssl_dataconn() {
                     return(-1);
                 } else {
                     if (!out2screen && displa && fdispla) {
-                        ftscreen(SCR_TC,0,0L,"Display canceled");
+                        ftscreen(SCR_TC,0,(CK_OFF_T)0,"Display canceled");
                         /* fdispla = XYFD_B; */
                     }
 
@@ -12943,7 +13399,7 @@ ssl_dataconn() {
                 }
             } else {
                 if (!out2screen && displa && fdispla == XYFD_C) {
-                    ftscreen(SCR_TC,0,0L,"Display canceled");
+                    ftscreen(SCR_TC,0,(CK_OFF_T)0,"Display canceled");
                     /* fdispla = XYFD_B; */
                 }
 
@@ -13327,6 +13783,17 @@ proxtrans(cmd, local, remote, unique) char *cmd, *local, *remote; int unique; {
 #ifdef FTP_SECURITY
 #ifdef FTP_GSSAPI
 
+#ifdef COMMENT
+/* ck_gss_mech_krb5 is not declared anywhere */
+struct {
+    CONST gss_OID_desc * CONST * mech_type;
+    char *service_name;
+} gss_trials[] = {
+    { &ck_gss_mech_krb5, "ftp" },
+    { &ck_gss_mech_krb5, "host" },
+};
+#else
+/* This matches what is declared above */
 struct {
     CONST gss_OID_desc * CONST * mech_type;
     char *service_name;
@@ -13334,6 +13801,8 @@ struct {
     { &gss_mech_krb5, "ftp" },
     { &gss_mech_krb5, "host" },
 };
+#endif /* COMMENT */
+
 
 int n_gss_trials = sizeof(gss_trials)/sizeof(gss_trials[0]);
 #endif /* FTP_GSSAPI */
@@ -14167,6 +14636,8 @@ ftp_hookup(host, port, tls) char * host; int port; int tls; {
     debtim = 1;
 #endif /* DEBUG */
 
+    debug(F111,"ftp_hookup",host,port);
+
 #ifndef NOHTTP
     if (tcp_http_proxy) {
         struct servent *destsp;
@@ -14200,7 +14671,8 @@ ftp_hookup(host, port, tls) char * host; int port; int tls; {
     }
     memset((char *)&hisctladdr, 0, sizeof (hisctladdr));
     hisctladdr.sin_addr.s_addr = inet_addr(host);
-    if (hisctladdr.sin_addr.s_addr != -1) {
+    if (hisctladdr.sin_addr.s_addr != INADDR_NONE) /* 2010-03-29 */
+    {
         debug(F110,"ftp hookup A",hostname,0);
         hisctladdr.sin_family = AF_INET;
         ckstrncpy(hostnamebuf, hostname, MAXHOSTNAMELEN);
@@ -14242,6 +14714,14 @@ ftp_hookup(host, port, tls) char * host; int port; int tls; {
     }
     hisctladdr.sin_port = htons(cport);
     errno = 0;
+
+#ifdef COMMENT
+  printf("hisctladdr=%d\n",sizeof(hisctladdr));
+  printf("hisctladdr.sin_addr=%d\n",sizeof(hisctladdr.sin_addr));
+  printf("sockaddr_in=%d\n",sizeof(struct sockaddr_in));
+  printf("hisctladdr.sin_addr.s_addr=%d\n",sizeof(hisctladdr.sin_addr.s_addr));
+#endif /* COMMENT */
+
 #ifdef HADDRLIST
     debug(F100,"ftp hookup HADDRLIST","",0);
     while
@@ -14502,7 +14982,7 @@ ftp_init() {
     if (servertype == SYS_UNIX && proxy) unix_proxy = 1;
 #endif /* FTP_PROXY */
 
-    if (ftp_cmdlin && xfermode == XMODE_M)
+    if (ftp_cmdlin && ftp_xfermode == XMODE_M)
       ftp_typ = binary;                 /* Type given on command line */
     else                                /* Otherwise set it automatically */
       ftp_typ = alike ? FTT_BIN : FTT_ASC;
@@ -15221,8 +15701,8 @@ remote_files(new_query, arg, pattern, proxy_switch)
     if (ftp_deb)
       printf("[%s]\n",(char *)buf);
 
-    havesize = -1L;                    /* Initialize file facts... */
-    havetype = -0;
+    havesize = (CK_OFF_T)-1;           /* Initialize file facts... */
+    havetype = 0;
     makestr(&havemdtm,NULL);
     p = (char *)buf;
 
@@ -15427,7 +15907,7 @@ secure_flush(fd) int fd; {
     if (rc > -1 && len > 0 && fdispla != XYFD_B) {
        spackets++;
         spktl = len;
-        ftscreen(SCR_PT,'D',spackets,NULL);
+        ftscreen(SCR_PT,'D',(CK_OFF_T)spackets,NULL);
     }
     return(rc);
 }
@@ -15466,6 +15946,14 @@ secure_write(fd, buf, nbyte)
 {
     int ret;
 
+#ifdef FTP_TIMEOUT    
+    ftp_timed_out = 0;
+    if (check_data_connection(fd,1) < 0) {
+       ftp_timed_out = 1;
+       return(-3);
+    }
+#endif /* FTP_TIMEOUT */
+
     if (!ftpissecure()) {
         if (nout > 0) {
             if ((ret = send(fd, (SENDARG2TYPE)ucbuf, nout, 0)) < 0)
@@ -15698,6 +16186,7 @@ secure_putbuf(fd, buf, nbyte) int fd; CHAR * buf; unsigned int nbyte;
     return(0);
 }
 
+
 /* fc = 0 means to get a byte; nonzero means to initialize buffer pointers */
 
 static int
@@ -15715,21 +16204,35 @@ secure_getbyte(fd,fc) int fd,fc; {
     if (nin == 0) {
         if (iscanceled())
           return(-9);
+
+#ifdef FTP_TIMEOUT
+       if (check_data_connection(fd,0) < 0)
+         return(-3);
+#endif /* FTP_TIMEOUT */
+
 #ifdef CK_SSL
         if (ssl_ftp_data_active_flag) {
             int count, error;
             count = SSL_read(ssl_ftp_data_con, ucbuf, ucbufsiz);
             error = SSL_get_error(ssl_ftp_data_con,count);
+#ifdef DEBUG
+           if (error != SSL_ERROR_NONE)
+             debug(F101,"ftp secure_getbyte error","",error);
+           if (count == 0)
+             debug(F101,"ftp secure_getbyte count","",count);
+#endif /* DEBUG */
             switch (error) {
               case SSL_ERROR_NONE:
-                nin = bufp = count;
-                rpackets++;
-                pktnum++;
-                if (fdispla != XYFD_B) {
-                    rpktl = count;
-                    ftscreen(SCR_PT,'D',rpackets,NULL);
-                }
-                break;
+               if (count > 0) {
+                   nin = bufp = count;
+                   rpackets++;
+                   pktnum++;
+                   if (fdispla != XYFD_B) {
+                       rpktl = count;
+                       ftscreen(SCR_PT,'D',(CK_OFF_T)rpackets,NULL);
+                   }
+                   break;
+               }
               case SSL_ERROR_WANT_WRITE:
               case SSL_ERROR_WANT_READ:
               case SSL_ERROR_SYSCALL:
@@ -15875,7 +16378,7 @@ secure_getbyte(fd,fc) int fd,fc; {
               pktnum++;
               if (fdispla != XYFD_B) {
                   rpktl = nin;
-                  ftscreen(SCR_PT,'D',rpackets,NULL);
+                  ftscreen(SCR_PT,'D',(CK_OFF_T)rpackets,NULL);
               }
           }
     }
@@ -15893,9 +16396,11 @@ secure_getbyte(fd,fc) int fd,fc; {
  *   c>=0 on success (character value)
  *   -1   on EOF
  *   -2   on security error
+ *   -3   on timeout (if built with FTP_TIMEOUT defined)
  */
 static int
 secure_getc(fd,fc) int fd,fc; {                /* file descriptor, function code */
+
     if (!ftpissecure()) {
         static unsigned int nin = 0, bufp = 0;
        if (fc) {
@@ -15906,20 +16411,30 @@ secure_getc(fd,fc) int fd,fc; {               /* file descriptor, function code */
         if (nin == 0) {
             if (iscanceled())
               return(-9);
+
+#ifdef FTP_TIMEOUT
+           if (check_data_connection(fd,0) < 0) {
+                debug(F100,"secure_getc TIMEOUT","",0);
+                nin = bufp = 0;
+               ftp_timed_out = 1;
+               return(-3);
+           }           
+#endif /* FTP_TIMEOUT */
+
             nin = bufp = recv(fd,(char *)ucbuf,actualbuf,0);
-            if (nin <= 0) {
+            if ((nin == 0) || (nin == (unsigned int)-1)) {
                 debug(F111,"secure_getc recv errno",ckitoa(nin),errno);
                 debug(F101,"secure_getc returns EOF","",EOF);
                 nin = bufp = 0;
                 return(EOF);
             }
             debug(F101,"ftp secure_getc recv","",nin);
-            hexdump("ftp secure_getc recv",ucbuf,16);
+            ckhexdump("ftp secure_getc recv",ucbuf,16);
             rpackets++;
             pktnum++;
             if (fdispla != XYFD_B) {
                 rpktl = nin;
-                ftscreen(SCR_PT,'D',rpackets,NULL);
+                ftscreen(SCR_PT,'D',(CK_OFF_T)rpackets,NULL);
             }
         }
         return(ucbuf[bufp - nin--]);
@@ -15955,6 +16470,11 @@ secure_read(fd, buf, nbyte) int fd; char *buf; int nbyte; {
             if (!i)
               c = 0;
             return(i);
+#ifdef FTP_TIMEOUT
+          case -3:
+            debug(F101,"ftp secure_read timeout","",c);
+           return(c);
+#endif /* FTP_TIMEOUT */
           default:
             buf[i++] = c;
         }
index b392b89..890f666 100644 (file)
--- a/ckcker.h
+++ b/ckcker.h
@@ -4,7 +4,7 @@
   Author: Frank da Cruz <fdc@columbia.edu>,
   Columbia University Academic Information Systems, New York City.
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2009,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -600,18 +600,19 @@ _PROTOTYP( int z_close, (int) );
 _PROTOTYP( int z_out, (int, char *, int, int) );
 _PROTOTYP( int z_in, (int, char *, int, int, int) );
 _PROTOTYP( int z_flush, (int) );
-_PROTOTYP( int z_seek, (int, long) );
-_PROTOTYP( int z_line, (int, long) );
+_PROTOTYP( int z_seek, (int, CK_OFF_T) );
+_PROTOTYP( int z_line, (int, CK_OFF_T) );
 _PROTOTYP( int z_getmode, (int) );
 _PROTOTYP( int z_getfnum, (int) );
-_PROTOTYP( long z_getpos, (int) );
-_PROTOTYP( long z_getline, (int) );
-_PROTOTYP( long z_count, (int, int) );
+_PROTOTYP( CK_OFF_T z_getpos, (int) );
+_PROTOTYP( CK_OFF_T z_getline, (int) );
+_PROTOTYP( CK_OFF_T z_count, (int, int) );
 _PROTOTYP( char * z_getname, (int) );
 _PROTOTYP( char * ckferror, (int) );
 #endif /* CKCHANNELIO */
 
 _PROTOTYP( int scanfile, (char *, int *, int) );
+_PROTOTYP( int scanstring, (char *) );
 
 /*  Buffered file i/o ...  */
 #ifdef OS2                             /* K-95 */
@@ -687,15 +688,15 @@ extern char ** sndarray;
 #define xxscreen(a,b,c,d)
 #define ckscreen(a,b,c,d)
 #else
-_PROTOTYP( VOID ckscreen, (int, char, long, char *) );
+_PROTOTYP( VOID ckscreen, (int, char, CK_OFF_T, char *) );
 #ifdef VMS
 #define xxscreen(a,b,c,d) \
 if (local && fdispla != XYFD_N) \
-ckscreen((int)a,(char)b,(long)c,(char *)d)
+ckscreen((int)a,(char)b,(CK_OFF_T)c,(char *)d)
 #else
 #define xxscreen(a,b,c,d) \
 if (local && !backgrd && fdispla != XYFD_N) \
-ckscreen((int)a,(char)b,(long)c,(char *)d)
+ckscreen((int)a,(char)b,(CK_OFF_T)c,(char *)d)
 #endif /* VMS */
 #endif /* NODISPLAY */
 
@@ -724,6 +725,7 @@ ckscreen((int)a,(char)b,(long)c,(char *)d)
 #define SCR_QE 14      /* quantity equals (e.g. "foo: 7") */
 #define SCR_CW 15      /* close screen window */
 #define SCR_CD 16       /* display current directory */
+#define SCR_MS 17      /* message from client */
 
 /* Skip reasons */
 
@@ -1316,7 +1318,7 @@ _PROTOTYP( int doarg, (char) );
 _PROTOTYP( int doxarg, (char **, int) );
 _PROTOTYP( VOID usage, (void) );
 _PROTOTYP( VOID doclean, (int) );
-_PROTOTYP( int sndhlp, () );
+_PROTOTYP( int sndhlp, (void) );
 _PROTOTYP( int sndstring, (char *) );
 _PROTOTYP( VOID ckhost, (char *, int) );
 _PROTOTYP( int gettcs, (int, int) );
@@ -1364,11 +1366,9 @@ _PROTOTYP( VOID fxdinit, (int) );
 
 _PROTOTYP( int fileselect, (char *,
                            char *, char *, char *, char *,
-                           long, long,
+                           CK_OFF_T, CK_OFF_T,
                            int, int,
                            char **) );
-
-
 _PROTOTYP( char * whoami, (void) );
 _PROTOTYP( int shoesc, (int) );
 
@@ -1401,6 +1401,11 @@ _PROTOTYP(int uq_mtxt, (char *,char **,int,struct txtbox[]) );
 _PROTOTYP(int uq_file, (char *,char *,int,char **,char *,char *,int));
 
 #ifdef CK_URL
+struct urlopt {
+    char * nam;
+    char * val;
+};
+#define MAX_URL_OPTS    16
 struct urldata {
     char * sav;                        /* The URL itself */
     char * svc;                        /* Service */
@@ -1409,6 +1414,8 @@ struct urldata {
     char * hos;                        /* Host */
     char * por;                        /* Port */
     char * pth;                        /* Path */
+    int    nopts;               /* number of options */
+    struct urlopt opt[MAX_URL_OPTS];   /* options */
 };
 _PROTOTYP(int urlparse, (char *, struct urldata *));
 #endif /* CK_URL */
index 36bf111..ac6f62d 100644 (file)
--- a/ckclib.c
+++ b/ckclib.c
@@ -1,4 +1,4 @@
-char * cklibv = "C-Kermit library, 8.0.033, 16 Mar 2003";
+char * cklibv = "C-Kermit library, 9.0.049, 30 Dec 2010";
 
 #define CKCLIB_C
 
@@ -8,7 +8,7 @@ char * cklibv = "C-Kermit library, 8.0.033, 16 Mar 2003";
   Author: Frank da Cruz <fdc@columbia.edu>,
   Columbia University Academic Information Systems, New York City.
 
-  Copyright (C) 1999, 2004,
+  Copyright (C) 1999, 2010,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -33,6 +33,8 @@ char * cklibv = "C-Kermit library, 8.0.033, 16 Mar 2003";
     ckuitoa()    - Converts unsigned int to string.
     ckltoa()     - Converts long to string.
     ckultoa()    - Converts unsigned long to string.
+    ckfstoa()    - Converts off_t-type integer (long or long long) to string.
+    ckatofs()    - Converts a numeric string to an off_t-type integer.
     ckctoa()     - Converts char to string.
     ckmakmsg()   - Constructs a message from 4 source strings.
     ckmakxmsg()  - Constructs a message from 12 source strings.
@@ -59,6 +61,7 @@ char * cklibv = "C-Kermit library, 8.0.033, 16 Mar 2003";
     ulongtohex() - Converts an unsigned long to a hex string.
     hextoulong() - Converts a hex string to an unsigned long.
     cksplit()    - Splits a string into an array of words.
+    ispattern()  - Tells if argument string is a pattern.
 
   Prototypes are in ckclib.h.
 
@@ -188,7 +191,7 @@ ckstrncat(dest,src,len) char * dest, * src; int len;
     s1--;                              /* (back up over NUL) */
 
     i = 0;
-    s2 = src;
+    s2 = (char *)src;
     while (*s2++) i++;                 /* i = strlen(src); */
 
     if (i > (len-j))
@@ -200,7 +203,7 @@ ckstrncat(dest,src,len) char * dest, * src; int len;
     strncpy(&dest[j],src,i);
 #else
     j = i;                             /* This should be a bit faster...    */
-    s2 = src;                          /* depends on strcpy implementation; */
+    s2 = (char *)src;                 /* depends on strcpy implementation; */
     while ((*s1++ = *s2++) && j--)     /* at least it shouldn't be slower.  */
       ;
     dest[len-1] = NUL;                 /* In case of early exit. */
@@ -277,6 +280,7 @@ ckmakxmsg(buf,len,s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11,s12)
     char *s;
     char *p, *a[12];
 
+
     if (!buf) return(n);               /* No destination */
     if (len < 1) return(n);            /* No size */
 
@@ -496,7 +500,7 @@ ckultoa(unsigned long n)
 #else
 ckultoa(n) unsigned long n;
 #endif /* CK_ANSIC */
-/* ckltoa */ {
+/* ckultoa */ {
     char buf[32];                      /* Internal working buffer */
     char * p, * s, * q;
     int k, x, len = 0;
@@ -550,6 +554,84 @@ ckltox(n) long n;
 }
 
 
+/*  C K F S T O A  --  File Size (or offset) to string  */
+
+/* This is just like ckltoa() except for the data type of the argument. */
+/* It's mainly for printing file sizes without having to know their data */
+/* type, so we don't have to hardware "%ld" or "%lld" into printf()s. */
+/* Works for 32 or 64 bits, according to CK_OFF_T definition. */
+
+char *
+#ifdef CK_ANSIC
+ckfstoa(CK_OFF_T n)
+#else
+ckfstoa(n) CK_OFF_T n;
+#endif /* CK_ANSIC */
+/* ckfstoa */ {
+    char buf[32];                      /* Internal working buffer */
+    char * p, * s, * q;
+    int k, x, len = 0, sign = 0;
+
+    if (n < (CK_OFF_T)0) {             /* Sign */
+       n = (CK_OFF_T)0 - n;
+       sign = 1;
+    }
+    buf[31] = NUL;                     /* 2^63-1 is about 20 decimal digits */
+    for (k = 30; k > 0; k--) {         /* Convert number to string */
+       x = n % (CK_OFF_T)10;
+       if (x < 0) {
+           /* x += 10; */
+           ckstrncpy(&buf[23],"OVERFLOW",32);
+           sign = 0;
+           k = 23;
+           break;
+       }
+       buf[k] = x + '0';
+       n = n / (CK_OFF_T)10;
+       if (!n)
+         break;
+    }
+    if (sign) buf[--k] = '-';          /* Add sign if necessary */
+    len = 31 - k;
+    if (len + numbp > NUMBUF)
+      numbp = 0;
+    p = numbuf + numbp;
+    q = p;
+    s = buf + k;
+    while ((*p++ = *s++)) ;            /* Copy */
+    *p++ = NUL;
+    numbp += len+1;
+    return(q);                         /* Return pointer */
+}
+
+/*  C K A T O F S  --  String to File Size (or offset) */
+
+/* This is the inverse of ckfstoa(), a replacement for atol() that works */
+/* for either 32-bit or 64-bit arguments, according to CK_OFF_T definition. */
+/* Like atol(), there is no error indication. */
+
+CK_OFF_T
+#ifdef CK_ANSIC
+ckatofs(char * s)
+#else
+ckatofs(s) char * s;
+#endif /* CK_ANSIC */
+/* ckatofs */ {
+    CK_OFF_T result = (CK_OFF_T)0;
+    int minus = 0;
+    while (*s && (*s == SP || *s == HT)) s++;
+    if (*s == '+') s++;
+    if (*s == '-') {
+       minus = 1;
+       s++;
+    }
+    while (isdigit(*s)) {
+       result = (result * (CK_OFF_T)10) + (CK_OFF_T)(*s - '0');
+       s++;
+    }
+    return(minus ? -result : result);
+}
+
 /*  C K I T O A  --  Int to string  -- FOR DISCIPLINED USE ONLY  */
 
 char *
@@ -710,6 +792,7 @@ brstrip(p) char *p; {
 
 #else
 /* New version handles braces and doublequotes */
+/* WARNING: this function writes into its argument, it always has. */
 
 char *
 brstrip(p) char *p; {
@@ -1265,6 +1348,7 @@ ckstrpre(s1,s2) char *s1, *s2; {
     regular expression it matches any string of zero or more a's followed by
     one b.  Regular expressions are especially useful in matching strings of
     (say) digits, or letters, e.g. "[0-9]*" matches any string of digits.
+    So far, Kermit doesn't do this.
 */
 static char * mypat = NULL;            /* For rewriting pattern */
 static int matchpos = 0;
@@ -1276,13 +1360,44 @@ static char * ostring = NULL;
 #define MATCHRETURN(x,y) { rc=y; where=x; goto xckmatch; }
 static char * lastpat = NULL;
 
+static int xxflag = 0;                 /* Global bailout flag for ckmatch() */
+
+int
+ispattern(s) char * s; {
+    int quote = 0, sbflag = 0, sb = 0, cbflag = 0, cb = 0;
+    
+    char c = 0;
+    if (*s == '^') return(1);
+    while ((c = *s++)) {
+       if (quote) {
+           quote = 0;
+           continue;
+       }
+       if (c == '\\') {
+           quote = 1;
+           continue;
+       }
+       if (c == '*') return(1);
+       if (c == '?') return(1);
+       /* Unquoted brackets or braces must match */
+       if (c == '[') { sbflag++; sb++; continue; }
+       if (c == ']') { sb--; continue; }
+       if (c == '{') { cbflag++; cb++; continue; }
+       if (c == '}') { cb--; continue; }
+       if (!*s && c == '$') return(1);
+    }
+    return(sbflag || cbflag);
+}
+
 int
 ckmatch(pattern, string, icase, opts) char *pattern,*string; int icase, opts; {
     int q = 0, i = 0, k = -1, x, flag = 0;
     int rc = 0;                                /* Return code */
+    int havestar = 0;
     int where = -1;
     CHAR cp;                           /* Current character from pattern */
     CHAR cs;                           /* Current character from string */
+    char * patstart;                   /* Start of pattern */
     int plen, dot, globbing, xstar = 0;
     int bronly = 0;                    /* Whole pattern is {a,b,c,...} */
 
@@ -1294,11 +1409,17 @@ ckmatch(pattern, string, icase, opts) char *pattern,*string; int icase, opts; {
 
     if (!string) string = "";
     if (!pattern) pattern = "";
+
     if (!*pattern) {                   /* Empty pattern matches anything */
        matchdepth++;                   /* (it wasn't incremented yet) */
        MATCHRETURN(0,1);
+    } else if (!*string) {
+       MATCHRETURN(0,0);
     }
+    patstart = pattern;                        /* Remember beginning of pattern */
+
     if (matchdepth == 0) {             /* Top-level call? */
+       xxflag = 0;
        stringpos = 0;                  /* Reset indices etc. */
        matchpos = 0;
        matchend = 0;
@@ -1307,7 +1428,7 @@ ckmatch(pattern, string, icase, opts) char *pattern,*string; int icase, opts; {
        if (*pattern == '{')            /* Entire pattern is {a,b.c} */
          bronly = 1;                   /* Maybe */
        dot = (opts & 1) ||             /* Match leading dot (if file) */
-           (opts & 2 == 0) ||          /* always if not file */
+           ((opts & 2) == 0) ||        /* always if not file */
            (pattern[0] == '.');        /* or if pattern starts with '.' */
 
        plen = strlen(pattern);         /* Length of pattern */
@@ -1428,7 +1549,8 @@ ckmatch(pattern, string, icase, opts) char *pattern,*string; int icase, opts; {
            }
            debug(F110,"CKMATCH ? pat",pattern,0);
            debug(F110,"CKMATCH ? str",string,0);
-           pattern++, string++;
+           pattern++;
+           string++;
            stringpos++;
            continue;
 #ifdef CKREGEX
@@ -1437,12 +1559,14 @@ ckmatch(pattern, string, icase, opts) char *pattern,*string; int icase, opts; {
            char * psave = NULL;        /* and backup pointer */
            CHAR clist[256];            /* Character list from brackets */
            CHAR c, c1, c2;
+
            for (i = 0; i < 256; i++)   /* memset() etc not portable */
              clist[i] = NUL;
            psave = ++pattern;          /* Where pattern starts */
            debug(F111,"CKMATCH [] ",pattern-1, matchpos);
            for (flag = 0; !flag; pattern++) { /* Loop thru pattern */
                c = (CHAR)*pattern;     /* Current char */
+               debug(F000,">>> pattern char","",c);
                if (q) {                /* Quote within brackets */
                    q = 0;
                    clist[c] = 1;
@@ -1488,8 +1612,30 @@ ckmatch(pattern, string, icase, opts) char *pattern,*string; int icase, opts; {
                    continue;
                }
            }
-           if (!clist[(unsigned)cs]) { /* Match? */
-               MATCHRETURN(5,0);       /* Nope, done. */
+           debug(F000,">>> cs","",cs);
+           debug(F101,">>> clist[cs]","",clist[cs]);
+           debug(F000,">>> string",string,*string);
+
+           if (!clist[(unsigned)cs]) { /* No match? */
+               if (!*string) {         /* This clause 16 Jun 2005 */
+                   MATCHRETURN(5,0);   /* Nope, done. */
+               }
+/*
+  We need to fail here if the [clist] is not allowed to float.
+  The [clist] is not allowed to float if it is not preceded
+  by an asterisk, right?  30 Dec 2005.
+*/
+               if (!havestar) {
+                   MATCHRETURN(500,0);
+               }
+               string++;               /* From here to end added 2005/6/15 */
+               stringpos++;
+               pattern = lastpat;      /* Back up pattern */
+               k = ckmatch(pattern,string,icase,opts);
+               if (xxflag) MATCHRETURN(0,0);
+               if (!matchpos && k > 0)
+                 matchpos = stringpos;
+               MATCHRETURN(5, (*string) ? matchpos : 0);
            }
            if (!matchpos) {
                matchpos = stringpos;
@@ -1599,6 +1745,7 @@ ckmatch(pattern, string, icase, opts) char *pattern,*string; int icase, opts; {
 #endif /* DEBUG */
                                free(tp);
                                tp = NULL;
+                               if (xxflag) MATCHRETURN(0,0);
                                if (k == 0) {
                                    matchpos = savpos;
                                }
@@ -1632,6 +1779,7 @@ ckmatch(pattern, string, icase, opts) char *pattern,*string; int icase, opts; {
            char * psave;
            char * p, * s = NULL;       /* meaning match anything */
            int k, n, q = 0;
+           havestar++;                 /* The rest can float */
            while (*pattern == '*')     /* Collapse successive asterisks */
              pattern++;
            psave = pattern;            /* First non-asterisk after asterisk */
@@ -1762,19 +1910,39 @@ ckmatch(pattern, string, icase, opts) char *pattern,*string; int icase, opts; {
            } else {                    /* A meta char follows asterisk */
                if (!*string)
                  MATCHRETURN(17, matchpos = 0);
-               while (*string && (k = ckmatch(p,string,icase,opts) < 1)) {
+#ifdef COMMENT
+               /* This is more elegant but it doesn't work. */
+               p--;
+               string++;
+               stringpos++;
+               k = ckmatch(p,string,icase,opts);
+#else
+               while (*string && ((k = ckmatch(p,string,icase,opts)) < 1)) {
+                   if (xxflag) MATCHRETURN(0,0);
                    string++;
                    stringpos++;
                }
+               if (!*string && k < 1) {
+/*
+  Definitely no match so we set a global flag to inibit further backing up
+  and retrying by previous incarnations, since they don't see that the string
+  and/or pattern, which are on the stack, have been exhausted at this level.
+*/
+                   xxflag++;
+                   debug(F111,"CKMATCH DEFINITELY NO MATCH",p,k);
+                   MATCHRETURN(91,0);
+               }
+#endif /* COMMENT */
                debug(F111,"CKMATCH *<meta> k",string, k);
                if (!matchpos && k > 0) {
                    matchpos = stringpos;
-                   debug(F111,"CKMATCH *<meta>",string, matchpos);
+                   debug(F111,"CKMATCH *<meta> matchpos",string, matchpos);
                }
                MATCHRETURN(12, (*string) ? matchpos : 0);
            }
        } else if (cs == cp) {
-           pattern++, string++;
+           pattern++;
+           string++;
            stringpos++;
            if (!matchpos) {
                matchpos = stringpos;
@@ -1788,20 +1956,21 @@ ckmatch(pattern, string, icase, opts) char *pattern,*string; int icase, opts; {
   xckmatch:
     {
 #ifdef DEBUG
-       char msgbuf[96];
+       char msgbuf[256];
 #endif /* DEBUG */
        if (matchdepth > 0)
          matchdepth--;
        matchpos = rc;
 #ifdef DEBUG
-       ckmakxmsg(msgbuf,96,
+       ckmakxmsg(msgbuf,256,
                  "CKMATCH RETURN[",
                  ckitoa(where),
                  "] matchpos=",
                  ckitoa(matchpos),
                  " matchdepth=",
                  ckitoa(matchdepth),
-                 " string=",NULL,NULL,NULL,NULL,NULL
+                 " pat=",pattern,
+                 " string=",string,NULL,NULL
                  );
        debug(F110,msgbuf,string,0);
 #endif /* DEBUG */
@@ -2016,8 +2185,19 @@ char *
 ckradix(s,in,out) char * s; int in, out; {
     char c, *r = rxresult;
     int d, minus = 0;
+#ifdef COMMENT
     unsigned long zz = 0L;
     long z = 0L;
+#else
+    /*
+      To get 64 bits on 32-bit hardware we use off_t, but there
+      is no unsigned version of off_t, so we lose the ability to
+      detect overflow.
+    */
+    CK_OFF_T zz = (CK_OFF_T)0;
+    CK_OFF_T z = (CK_OFF_T)0;
+#endif /* COMMENT */
+
     if (in < 2 || in > 36)             /* Verify legal input radix */
       return(NULL);
     if (out < 2 || out > 36)           /* and output radix. */
@@ -2222,7 +2402,7 @@ b64tob8(s,n,out,len) char * s,* out; int n, len; { /* Decode */
 /* C H K N U M  --  See if argument string is an integer  */
 
 /* Returns 1 if OK, zero if not OK */
-/* If OK, string should be acceptable to atoi() */
+/* If OK, string should be acceptable to atoi() or atol() or ckatofs() */
 /* Allows leading space, sign */
 
 int
@@ -2593,7 +2773,7 @@ cksplit(fc,n1,s1,s2,s3,n2,n3,n4) int fc,n1,n2,n3,n4; char *s1, *s2, *s3; {
     int    gr_stk[NESTMAX];            /* Nesting bracket stack */
     int    gr_lvl = 0;                 /* Nesting level */
     int    wordnum = 0;                        /* Current word number */
-    char   c = 'A';                    /* Current char (dummy start value) */
+    CHAR   c = 'A';                    /* Current char (dummy start value) */
     int    class = 0;                  /* Current character class */
     int    state = ST_BW;              /* Current FSA state */
     int    len = 0;                    /* Length of current word */
@@ -2601,7 +2781,16 @@ cksplit(fc,n1,s1,s2,s3,n2,n3,n4) int fc,n1,n2,n3,n4; char *s1, *s2, *s3; {
     int    gquote = 0;                 /* Quoted group */
     int    cquote = 0;                 /* Quoted character */
     int    collapse = 1;               /* Collapse adjacent separators */
+    int    all = 0;                    /* s3 == ALL */
+    int    csv = 0;                    /* s3 == CSV */
+    int    tsv = 0;                    /* s3 == TSV */
+    int    prevstate = -1;
 
+    unsigned int hex80 = 128;
+    unsigned int hexff = 255;
+    CHAR notsepbuf[256];
+
+    notsepbuf[0] = NUL;                        /* Keep set for "ALL" */
     if (n4) collapse = 0;              /* Don't collapse */
 
     for (i = 0; i < NESTMAX; i++)      /* Initialize nesting stack */
@@ -2619,16 +2808,24 @@ cksplit(fc,n1,s1,s2,s3,n2,n3,n4) int fc,n1,n2,n3,n4; char *s1, *s2, *s3; {
     if (splitting) {                   /* If splitting n = word count */
        n = 0;                          /* Initialize it */
     } else {                           /* Otherwise */
+#ifdef COMMENT
        if (n1 < 1) {                   /* If 0 (or less) */
            ck_sval.a_size = 0;         /* nothing to do. */
            return(&ck_sval);
        }
+#else
+       if (n1 == 0) {                  /* If 0 */
+           ck_sval.a_size = 0;         /* nothing to do. */
+           return(&ck_sval);
+       }
+#endif /* COMMENT */
        n = n1;                         /* n = desired word number. */
     }
     slen = 0;                          /* Get length of s1 */
     debug(F111,"cksplit",s1,n);
 
     p = s1;
+
 #ifdef COMMENT
     while (*p++) slen++;               /* Make pokeable copy of s1 */
     if (!splitbuf || slen > nsplitbuf) { /* Allocate buffer if needed */
@@ -2680,16 +2877,53 @@ cksplit(fc,n1,s1,s2,s3,n2,n3,n4) int fc,n1,n2,n3,n4; char *s1, *s2, *s3; {
     sep = s2;                          /* s2 = break set */
     if (!sep) sep = "";
     notsep = s3;                       /* s3 = include set */
-    if (!notsep) notsep = "";
+    if (!notsep) {
+       notsep = "";
+    } else if ((all = !ckstrcmp(notsep,"ALL",3,1)) ||
+              (csv = !ckstrcmp(notsep,"CSV",3,1)) ||
+              (tsv = !ckstrcmp(notsep,"TSV",3,1))) {
+       int i, flag; CHAR c;
+       int n = 0;
+       char * ss;
+       if (!all && (csv || tsv)) {
+           all = 1;
+           collapse = 0;
+       }
+       if (csv || tsv) {
+           all = 1;
+           collapse = 0;
+       }
+       for (i = 1; i < 256; i++) {
+           flag = 0;
+           ss = sep;
+           while (c = *ss++ && !flag) {
+               if (c == i) flag++;
+           }
+           if (!flag) notsepbuf[n++] = c;
+       }
+       notsepbuf[n] = NUL;
+       notsep = (char *)notsepbuf;
+       debug(F110,"CKMATCH NOTSEPBUF ALL",notsep,0);
+    }
+    if (*s && csv) {                   /* For CSV skip leading whitespace */
+        while (*s == SP || *s == HT)
+         s++;
+       c = *s;
+    }
+    if (n2 == 0 && csv) n2 = 1;                /* CSV implies doublequote grouping */
     if (n2 < 0) n2 = 63;               /* n2 = grouping mask */
     grouping = n2;
     p = "";                            /* Pointer to current word */
     while (c) {                                /* Loop through string */
        c = *s;
        class = 0;
-       if (!cquote && c == CMDQ) {     /* If CMDQ */
-           cquote++;                   /* next one is quoted */
-           goto nextc;                 /* go get it */
+       if (!csv && !tsv) {             /* fdc 2010-12-30 */
+           /* In CSV and TSV splitting, backslash is not special */
+           if (!cquote && c == CMDQ) { /* If CMDQ */
+               cquote++;               /* next one is quoted */
+               goto nextc;             /* go get it */
+           }
+
        }
        if (cquote && c == CMDQ) {      /* Quoted CMDQ is special */
            if (state != ST_BW) {       /* because it can still separate */
@@ -2709,7 +2943,7 @@ cksplit(fc,n1,s1,s2,s3,n2,n3,n4) int fc,n1,n2,n3,n4; char *s1, *s2, *s3; {
            cquote = 0;
            x = 1;
        } else {                        /* Character is not quoted */
-           if (c < SP) {               /* Get its class */
+           if (!all && c < SP) {       /* Get its class */
                x = 0;                  /* x == 0 means "is separator" */
            } else if (*sep) {          /* Break set given */
                ss = sep;
@@ -2718,7 +2952,8 @@ cksplit(fc,n1,s1,s2,s3,n2,n3,n4) int fc,n1,n2,n3,n4; char *s1, *s2, *s3; {
            } else {                    /* Default break set is */
                x = ((c >= 'a' && c <= 'z') || /* all but alphanumerics */
                     (c >= '0' && c <= '9') ||
-                    (c >= 'A' && c <= 'Z')
+                    (c >= 'A' && c <= 'Z') ||
+                    ((unsigned int)c >= hex80 && (unsigned int)c <= hexff)
                     );
            }
            if (x == 0 && *notsep && c) { /* Include set if given */
@@ -2751,6 +2986,10 @@ cksplit(fc,n1,s1,s2,s3,n2,n3,n4) int fc,n1,n2,n3,n4; char *s1, *s2, *s3; {
                }
            }
        }
+       debug(F000,"cksplit char",s,c);
+       debug(F101,"cksplit state","",state);
+       debug(F101,"cksplit class","",class);
+
        switch (state) {                /* State switcher... */
          case ST_BW:                   /* BETWEENWORDS */
            if (class & CL_OPN) {       /* Group opener */
@@ -2761,6 +3000,7 @@ cksplit(fc,n1,s1,s2,s3,n2,n3,n4) int fc,n1,n2,n3,n4; char *s1, *s2, *s3; {
                if (gr_lvl >= NESTMAX)
                  goto xxsplit;
                gr_stk[gr_lvl] = gr_cls[ko];
+               prevstate = state;
                state = ST_IG;          /* Switch to INGROUP state */
            } else if (class & CL_DAT) { /* Data character */
                gr_lvl = 0;             /* Clear group nesting stack */
@@ -2772,6 +3012,7 @@ cksplit(fc,n1,s1,s2,s3,n2,n3,n4) int fc,n1,n2,n3,n4; char *s1, *s2, *s3; {
                    p--;
                    gquote = 0;
                }
+               prevstate = state;
                state = ST_IW;          /* Switch to INWORD state */
            } else if (class & CL_QUO) { /* Group quote */
                gquote = gr_lvl+1;      /* Remember quoted level */
@@ -2784,18 +3025,40 @@ cksplit(fc,n1,s1,s2,s3,n2,n3,n4) int fc,n1,n2,n3,n4; char *s1, *s2, *s3; {
          case ST_IW:                   /* INWORD (but not in a group) */
            if (class & CL_SEP) {       /* Ends on any kind of separator */
                *s = NUL;               /* Terminate this word */
-               wordnum++;              /* Count it */
-               if (splitting) {        /* Dispose of it appropriately */
-                   if (wordnum > max) {   /* Add to array if splitting */
-                       ck_sval.a_size = -2;
+               if (csv) {              /* If comma-separated list */
+                   char * s2 = s;      /* discard surrounding spaces */
+                   while (s2 > splitbuf) { /* first backwards... */
+                       s2--;
+                       if (*s2 == SP || *s2 == HT)
+                         *s2 = NUL;
+                       else
+                         break;
+                   }
+                   s2 = s+1;           /* Then forwards... */
+                   while (*s2 && (*s2 == SP || *s2 == HT))
+                     *s2++;
+                   s = s2-1;
+               }
+               if (!csv || prevstate != ST_IG) {
+                   wordnum++;                /* Count it */
+                   if (splitting || n < 0) { /* Dispose of it appropriately */
+                       if (wordnum > max) {  /* Add to array if splitting */
+                           ck_sval.a_size = -2;
+                           return(&ck_sval);
+                       }
+                       /* This inelegant bit corrects an edge condition */
+                       if (csv && !*p && (!c || !*(s+1))) {
+                           wordnum--;
+                       } else {
+                           setword(wordnum,p,len);
+                       }
+                   } else if (wordnum == n) { /* Searching for word n */
+                       setword(1,p,len);
+                       ck_sval.a_size = 1;
                        return(&ck_sval);
                    }
-                   setword(wordnum,p,len);
-               } else if (wordnum == n) { /* Searching for word n */
-                   setword(1,p,len);
-                   ck_sval.a_size = 1;
-                   return(&ck_sval);
                }
+               prevstate = state;
                state = ST_BW;          /* Switch to BETWEENWORDS state */
                len = 0;
            }
@@ -2803,6 +3066,14 @@ cksplit(fc,n1,s1,s2,s3,n2,n3,n4) int fc,n1,n2,n3,n4; char *s1, *s2, *s3; {
 
          case ST_IG:                   /* INGROUP */
            if (class & CL_CLS) {       /* Have group closer? */
+               if (csv) {
+                   if (*(s+1) == c) {
+                       char *s2 = s;
+                       while ((*s2 = *(s2+1))) s2++;
+                       s++;
+                       c = *s;
+                   }
+               }
                if (c == gr_stk[gr_lvl]) { /* Does it match current opener? */
                    gr_lvl--;              /* Yes, pop stack */
                    if (gr_lvl < 0)        /* Don't pop it too much */
@@ -2812,10 +3083,9 @@ cksplit(fc,n1,s1,s2,s3,n2,n3,n4) int fc,n1,n2,n3,n4; char *s1, *s2, *s3; {
                          s++;
                        c = *s;
                        *s = NUL;       /* we have word. */
-
                        wordnum++;      /* Count and dispose of it. */
                        len--;
-                       if (splitting) {
+                       if (splitting || n < 0) {
                            if (wordnum > max) {
                                ck_sval.a_size = -2;
                                return(&ck_sval);
@@ -2826,6 +3096,7 @@ cksplit(fc,n1,s1,s2,s3,n2,n3,n4) int fc,n1,n2,n3,n4; char *s1, *s2, *s3; {
                            ck_sval.a_size = 1;
                            return(&ck_sval);
                        }
+                       prevstate = state;
                        state = ST_BW;  /* Switch to BETWEENWORDS state */
                        len = 0;
                    }
@@ -2846,26 +3117,44 @@ cksplit(fc,n1,s1,s2,s3,n2,n3,n4) int fc,n1,n2,n3,n4; char *s1, *s2, *s3; {
     } /* while (c) */
 
     if (gr_lvl > 0) {                  /* In case of an unclosed group */
-       if (splitting) {                /* make it the last word. */
+       if (splitting || n < 0) {       /* make it the last word. */
            if (++wordnum > max) {
                ck_sval.a_size = -2;
                return(&ck_sval);
            }
            setword(wordnum,p+1,len);
-       } else if (wordnum == n) {
+       } else if (wordnum == n) {      /* Counting from left */
            setword(1,p+1,len);
            ck_sval.a_size = 1;
            return(&ck_sval);
-       }
+       } else  if (n < 0 && (wordnum + n > -1)) { /* Counting from right */
+           char * s = wordarray[wordnum + n + 1];
+           if (!s) s = "";
+           setword(1,s,strlen(s));
+           ck_sval.a_size = 1;
+           return(&ck_sval);
+        }
     }
-    if (!splitting) {                  /* Wanted word n but there was none? */
-       setword(1,NULL,0);
-       ck_sval.a_size = 0;
+    if (!splitting) {                  /* Fword... */
+       if (n < 0 && (wordnum + n > -1)) { /* Counting from right */
+           char * s = wordarray[wordnum + n + 1];
+           if (!s) s = "";
+           setword(1,s,strlen(s));
+           ck_sval.a_size = 1;
+           return(&ck_sval);
+        }
+       setword(1,NULL,0);              /* From left... */
+       ck_sval.a_size = 0;             /* but there weren't n words */
        return(&ck_sval);
     } else {                           /* Succeed otherwise */
        ck_sval.a_size = wordnum;
+/* 
+  Always put a null element at the end of the array.  It does no harm in
+  the normal case, and it's required if we're making an argv[] array to 
+  pass to execvp().  This element is not included in the count.
+*/
        if (wordnum < MAXWORDS)
-         setword(wordnum+1,NULL,0);
+          setword(wordnum+1,NULL,0);
     }
 #ifdef DEBUG
     if (deblog) {
@@ -2880,4 +3169,34 @@ cksplit(fc,n1,s1,s2,s3,n2,n3,n4) int fc,n1,n2,n3,n4; char *s1, *s2, *s3; {
     return(&ck_sval);
 }
 
+/*
+  ckhexbytetoint() expects a string of two hex characters,
+  returns the int equivalent or -1 on error.
+*/
+int
+#ifdef CK_ANSIC
+ckhexbytetoint( char * s )
+#else
+ckhexbytetoint(s) char * s;
+#endif /* CK_ANSIC */
+{
+    int i, c[2];
+    if (!s) return(-1);
+    if ((int)strlen(s) != 2) return(-1);
+    for (i = 0; i < 2; i++) {
+       c[i] = *s++;
+       if (!c[i]) return(-1);
+       if (islower(c[i])) c[i] = toupper(c[i]);
+       if (c[i] >= '0' && c[i] <= '9') {
+           c[i] -= 0x30;
+       } else if (c[i] >= 'A' && c[i] <= 'F') {
+           c[i] -= 0x37;
+       } else {
+           return(-1);
+       }
+    }
+    return(c[0] * 16 + c[1]);
+}
+
+
 /* End of ckclib.c */
index a258664..af09c0e 100644 (file)
--- a/ckclib.h
+++ b/ckclib.h
@@ -3,7 +3,7 @@
   Author: Frank da Cruz <fdc@columbia.edu>,
   Columbia University Academic Information Systems, New York City.
 
-  Copyright (C) 2002, 2004,
+  Copyright (C) 2002, 2009,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -41,8 +41,11 @@ _PROTOTYP( char * ckitoa, (int) );
 _PROTOTYP( char * ckuitoa, (unsigned int) );
 _PROTOTYP( char * ckltoa, (long) );
 _PROTOTYP( char * ckultoa, (unsigned long) );
+_PROTOTYP( char * ckfstoa, (CK_OFF_T) );
+_PROTOTYP( CK_OFF_T ckatofs, (char *) );
 _PROTOTYP( char * ckitox, (int) );
 _PROTOTYP( char * ckltox, (long) );
+_PROTOTYP( int ispattern, (char *) );
 _PROTOTYP( int ckmatch, (char *, char *, int, int ) );
 _PROTOTYP( VOID ckmemcpy, (char *, char *, int) );
 _PROTOTYP( char * ckstrchr, (char *, char) );
@@ -97,4 +100,5 @@ _PROTOTYP( long hextoulong, (char *, int) );
 _PROTOTYP( struct stringarray * cksplit, (int,int,
                                           char *,char *,char *,int,int,int) );
 
+_PROTOTYP( int ckhexbytetoint, (char *) );
 #endif /* CKCLIB_H */
index 33504dc..e29f51a 100644 (file)
--- a/ckcmai.c
+++ b/ckcmai.c
@@ -1,24 +1,26 @@
-#define EDITDATE  "10 Apr 2004"                /* Update these with each edit */
-#define EDITNDATE "20040410"           /* Keep them in sync */
-/* Sat Apr 10 12:05:49 2004 */
+#define EDITDATE  "15 Jun 2011"                /* Last edit date dd mmm yyyy */
+#define EDITNDATE "20110615"           /* Keep them in sync */
+/* Wed Jun 15 07:12:45 2011 */
+
+/* ckcmai.c - Main program for C-Kermit plus some miscellaneous functions */
 
 /*
   ckcsym.h is used for for defining symbols that normally would be defined
   using -D or -d on the cc command line, for use with compilers that don't
-  support this feature.  Must be before any tests for preprocessor symbols.
+  support this feature.  Must come before any tests for preprocessor symbols.
 */
 #include "ckcsym.h"
 /*
-  Consolidated program version information (for UNIX also see ckuver.h).
-  See makever() below for how they are used.
+  Consolidated program C-Kermit version information for all platforms
+  (but for UNIX also see ckuver.h).  See makever() below for how they are used.
 */
-/* #ifdef COMMENT */                    /* Uncomment this for test version */
-#ifndef OS2
-#ifndef BETATEST
-#define BETATEST
+#ifdef COMMENT                    /* Uncomment this for real K95 version */
+#ifndef OS2                            /* OS2 actually means Kermit 95. */
+#ifndef BETATEST                       /* It's because Kermit 95 started */
+#define BETATEST                       /* out as C-Kermit for OS/2. */
 #endif /* BETATEST */
 #endif /* OS2 */
-/* #endif */ /* COMMENT */
+#endif /* COMMENT */
 
 #ifdef BETATEST
 #ifdef OS2
 #endif /* OS2 */
 #endif /* BETATEST */
 
-#ifndef MAC
+char * ck_cryear = "2011";             /* C-Kermit copyright year */
+
+#ifndef MAC                            /* MAC = Kermit for MAC OS 6, 7, ... */
 /*
   Note: initialize ck_s_test to "" if this is not a test version.
   Use (*ck_s_test != '\0') to decide whether to print test-related messages.
 */
+
 #ifndef BETATEST
 #ifndef OS2                             /* UNIX, VMS, etc... (i.e. C-Kermit) */
-char *ck_s_test = "";                  /* "Dev","Alpha","Beta","RC", or "" */
-char *ck_s_tver = "";                  /* Test version number or "" */
+char *ck_s_test = "Beta";              /* "Dev","Alpha","Beta","RC", or "" */
+char *ck_s_tver = "01";                        /* Test version number or "" */
 #else  /* OS2 */
 char *ck_s_test = "";                  /* (i.e. K95) */
 char *ck_s_tver = "";
@@ -47,7 +52,7 @@ char *ck_s_tver = "";
 #endif /* BETATEST */
 #else /* MAC */
 char *ck_s_test = "Pre-Alpha";          /* Mac Kermit is always a test... */
-char *ck_s_tver = "";
+char *ck_s_tver = "";                  /* (pre Mac OS X 10, that is!) */
 #endif /* MAC */
 
 #ifdef BETADATE                         /* Date of this version or edit */
@@ -59,15 +64,15 @@ char *ck_s_date = EDITDATE;         /* See top */
 char *buildid = EDITNDATE;             /* See top */
 
 #ifdef UNIX
-static char sccsid[] = "@(#)C-Kermit 8.0.211";
+static char sccsid[] = "@(#)C-Kermit 9.0.299";
 #endif /* UNIX */
 
-char *ck_s_ver = "8.0.211";             /* C-Kermit version string */
-long  ck_l_ver =  800211L;              /* C-Kermit version number */
+char *ck_s_ver = "9.0.299";             /* C-Kermit version string */
+long  ck_l_ver =  900299L;              /* C-Kermit version number */
 
 #ifdef OS2
-char *ck_s_xver = "2.2.0";             /* Product-specific version string */
-long  ck_l_xver = 2200L;                /* Product-specific version number */
+char *ck_s_xver = "3.0.0";             /* Product-specific version string */
+long  ck_l_xver = 3000L;                /* Product-specific version number */
 #else
 #ifdef MAC
 char *ck_s_xver = "0.995";              /* Product-specific version string */
@@ -119,154 +124,58 @@ char * myhome = NULL;                    /* Home directory override */
 
 /*
   Author: Frank da Cruz (fdc@columbia.edu),
-  Columbia University Academic Information Systems, New York City.
+  Columbia University in the city of New York,
+  Computer Center / Center for Computing Activities / Information Technology.
+  I am no longer at Columbia U as of 1 July 2011, but the email address
+  should still work.  The Kermit website http://kermit.columbia.edu should
+  still be available and under my control, as well as the Kermit FTP site,
+  ftp://kermit.columbia.edu/kermit/.
 
 COPYRIGHT NOTICE:
 */
 
-#ifdef OS2
-char *wiksdcpr[] = {
-"Windows Internet Kermit Service Daemon (WIKSD):",
-"Copyright (C) 1985, 2004, Trustees of Columbia University in the City of New",
-"York.  All rights reserved.",
-" ",
-"PERMISSIONS:",
-" ",
-"  The WIKSD software may be obtained directly, in binary form only, from",
-"  the Kermit Project at Columbia University by any individual for his or",
-"  her OWN USE, and by any company or other organization for its own",
-"  INTERNAL DISTRIBUTION and use, including installation on servers that",
-"  are accessed by customers or clients, WITHOUT EXPLICIT LICENSE.  All",
-"  other forms of redistribution must be licensed from the Kermit Project",
-"  at Columbia University.  These permissions apply only to the nonsecure",
-"  version of WIKSD.",
-" ",
-"DISCLAIMER:",
-" ",
-"  THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE",
-"  TRUSTEES OF COLUMBIA UNIVERSITY IN THE CITY OF NEW YORK AS TO ITS",
-"  FITNESS FOR ANY PURPOSE, AND WITHOUT WARRANTY BY THE TRUSTEES OF",
-"  COLUMBIA UNIVERSITY IN THE CITY OF NEW YORK OF ANY KIND, EITHER",
-"  EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED",
-"  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.",
-"  THE TRUSTEES OF COLUMBIA UNIVERSITY IN THE CITY OF NEW YORK SHALL NOT",
-"  BE LIABLE FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL,",
-"  OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT OR IN",
-"  CONNECTION WITH THE USE OF THE SOFTWARE, EVEN IF IT HAS BEEN OR IS",
-"  HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.  YOU SHALL",
-"  INDEMNIFY AND HOLD HARMLESS THE TRUSTEES OF COLUMBIA UNIVERSITY IN",
-"  THE CITY OF NEW YORK, ITS EMPLOYEES AND AGENTS FROM AND AGAINST ANY",
-"  AND ALL CLAIMS, DEMANDS, LOSS, DAMAGE OR EXPENSE (INCLUDING",
-"  ATTORNEYS' FEES) ARISING OUT OF YOUR USE OF THIS SOFTWARE.",
-" ",
-"The above copyright notice, permissions notice, and disclaimer may not be",
-"removed, altered, or obscured and shall be included in all copies of the",
-"WIKSD software.  The Trustees of Columbia University in the City of",
-"New York reserve the right to revoke this permission if any of the terms",
-"of use set forth above are breached.",
-" ",
-"For further information, contact the Kermit Project, Columbia University,",
-"612 West 115th Street, New York NY 10025-7799, USA; Phone +1 (212) 854 3703,",
-"Fax +1 (212) 662 6442, kermit@columbia.edu, http://www.columbia.edu/kermit/",
-""
-};
-#endif /* OS2 */
-
 char *copyright[] = {
 
 #ifdef pdp11
-"Copyright (C) 1985, 2004, Trustees of Columbia University, NYC.",
+"Copyright (C) 1985, %s, Trustees of Columbia University, NYC.",
 "All rights reserved.",
 " ",
 #else
-#ifdef OS2
-"Copyright (C) 1985, 2004, Trustees of Columbia University in the City of New",
-"York.  All rights reserved.  This software is furnished under license",
-"and may not be reproduced without license to do so.  This copyright notice",
-"must not be removed, altered, or obscured.",
-" ",
-"  THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE",
-"  TRUSTEES OF COLUMBIA UNIVERSITY IN THE CITY OF NEW YORK AS TO ITS",
-"  FITNESS FOR ANY PURPOSE, AND WITHOUT WARRANTY BY THE TRUSTEES OF",
-"  COLUMBIA UNIVERSITY IN THE CITY OF NEW YORK OF ANY KIND, EITHER",
-"  EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED",
-"  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.",
-"  THE TRUSTEES OF COLUMBIA UNIVERSITY IN THE CITY OF NEW YORK SHALL NOT",
-"  BE LIABLE FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL,",
-"  OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT OR IN",
-"  CONNECTION WITH THE USE OF THE SOFTWARE, EVEN IF IT HAS BEEN OR IS",
-"  HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.  YOU SHALL",
-"  INDEMNIFY AND HOLD HARMLESS THE TRUSTEES OF COLUMBIA UNIVERSITY IN",
-"  THE CITY OF NEW YORK, ITS EMPLOYEES AND AGENTS FROM AND AGAINST ANY",
-"  AND ALL CLAIMS, DEMANDS, LOSS, DAMAGE OR EXPENSE (INCLUDING",
-"  ATTORNEYS' FEES) ARISING OUT OF YOUR USE OF THIS SOFTWARE.",
-" ",
-#else
-"Copyright (C) 1985, 2004,",
+"Copyright (C) 1985, %s,",
 "  The Trustees of Columbia University in the City of New York.",
 "  All rights reserved.",
 " ",
-"PERMISSIONS:",
-" ",
-"The C-Kermit software may be obtained directly from the Kermit Project at",
-"Columbia University (or from any source explicitly licensed by the Kermit",
-"Project or implicitly licensed by Clause (A) below) by any individual for",
-"his or her OWN USE, and by any company or other organization for its own",
-"INTERNAL DISTRIBUTION and use, including installation on servers that are",
-"accessed by customers or clients, WITHOUT EXPLICIT LICENSE.",
-" ",
-"Conditions for REDISTRIBUTION are as follows:",
+"Redistribution and use in source and binary forms, with or without",
+"modification, are permitted provided that the following conditions",
+"are met:",
 " ",
-"(A) The C-Kermit software, in source and/or binary form, may be",
-"    included WITHOUT EXPLICIT LICENSE in distributions of OPERATING",
-"    SYSTEMS that have OSI (Open Source Initiative, www.opensource.org)",
-"    approved licenses, even if non-Open-Source applications (but not",
-"    operating systems) are included in the same distribution.  Such",
-"    distributions include, but are not limited to, CD-ROM, FTP site,",
-"    Web site, or preinstalled software on a new GENERAL-PURPOSE",
-"    computer, as long as the primary character of the distribution is",
-"    an Open Source operating system with accompanying utilities.  The",
-"    C-Kermit source code may not be changed without the consent of the",
-"    Kermit Project, which will not be unreasonably withheld (this is",
-"    simply a matter of keeping a consistent and supportable code base).",
+" + Redistributions of source code must retain the above copyright",
+"   notice, this list of conditions and the following disclaimer.",
 " ",
-"(B) Inclusion of C-Kermit software in whole or in part, in any form, in",
-"    or with any product not covered by Clause (A), or its distribution",
-"    by any commercial enterprise to its actual or potential customers",
-"    or clients except as in Clause (A), requires a license from the",
-"    Kermit Project, Columbia University; contact kermit@columbia.edu.",
+" + Redistributions in binary form must reproduce the above copyright",
+"   notice, this list of conditions and the following disclaimer in",
+"   the documentation and/or other materials provided with the",
+"   distribution.",
 " ",
-"The name of Columbia University may not be used to endorse or promote",
-"products derived from or including the C-Kermit software without specific",
-"prior written permission.",
+" + Neither the name of the <ORGANIZATION> nor the names of its",
+"   contributors may be used to endorse or promote products derived",
+"   from this software without specific prior written permission.",
 " ",
-"DISCLAIMER:",
-" ",
-"  THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE",
-"  TRUSTEES OF COLUMBIA UNIVERSITY IN THE CITY OF NEW YORK AS TO ITS",
-"  FITNESS FOR ANY PURPOSE, AND WITHOUT WARRANTY BY THE TRUSTEES OF",
-"  COLUMBIA UNIVERSITY IN THE CITY OF NEW YORK OF ANY KIND, EITHER",
-"  EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED",
-"  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.",
-"  THE TRUSTEES OF COLUMBIA UNIVERSITY IN THE CITY OF NEW YORK SHALL NOT",
-"  BE LIABLE FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL,",
-"  OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT OF OR",
-"  IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN IF IT HAS BEEN OR IS",
-"  HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.  YOU SHALL",
-"  INDEMNIFY AND HOLD HARMLESS THE TRUSTEES OF COLUMBIA UNIVERSITY IN",
-"  THE CITY OF NEW YORK, ITS EMPLOYEES AND AGENTS FROM AND AGAINST ANY",
-"  AND ALL CLAIMS, DEMANDS, LOSS, DAMAGE OR EXPENSE (INCLUDING",
-"  ATTORNEYS' FEES) ARISING OUT OF YOUR USE OF THIS SOFTWARE.",
-" ",
-"The above copyright notice, permissions notice, and disclaimer may not be",
-"removed, altered, or obscured and shall be included in all copies of the",
-"C-Kermit software.  The Trustees of Columbia University in the City of",
-"New York reserve the right to revoke this permission if any of the terms",
-"of use set forth above are breached.",
-#endif /* OS2 */
+"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS",
+"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT",
+"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR",
+"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT",
+"HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,",
+"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT",
+"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,",
+"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY",
+"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT",
+"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE",
+"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.",
 #endif /* pdp11 */
 
 #ifdef OS2
+"Portions Copyright (C) 2002-2005, Secure Endpoints Inc, New York NY USA.",
 "Portions Copyright (C) 1995, Oy Online Solutions Ltd., Jyvaskyla, Finland.",
 #endif /* OS2 */
 
@@ -284,13 +193,15 @@ char *copyright[] = {
 
 #ifndef pdp11
 " ",
-"For further information, contact the Kermit Project, Columbia University,",
-"612 West 115th Street, New York NY 10025-7799, USA; phone +1 (212) 854 3703,",
-"fax +1 (212) 663 8202 or +1 (212) 662 6442, email kermit@columbia.edu,",
-"Web http://www.columbia.edu/kermit/ or http://www.kermit-project.org/.",
+"For further information, visit the Kermit Project website:",
+"http://www.columbia.edu/kermit/ .",
 #endif /* pdp11 */
 ""};
 
+/* Windows IKSD copyright used to be separate */
+char *wiksdcpr = (char *) copyright;
+
+
 /*
 DOCUMENTATION:
 
@@ -309,9 +220,10 @@ ACKNOWLEDGMENTS:
 
   The Kermit file transfer protocol was developed at the Columbia University
   Center for Computing Activities (CUCCA), which was since renamed to Columbia
-  University Academic Information Systems (AcIS).  Kermit is named after
-  Kermit the Frog, star of the television series THE MUPPET SHOW; the name is
-  used by permission of Henson Associates, Inc.
+  University Academic Information Systems (AcIS) and after that Columbia
+  University Information Technology (CUIT).  Kermit is named after Kermit the
+  Frog, star of the television series THE MUPPET SHOW; the name is used by
+  permission of Henson Associates, Inc.
 
   Thanks to at least the following people for their contributions to this
   program over the years, and apologies to anyone who was inadvertantly
@@ -331,6 +243,7 @@ ACKNOWLEDGMENTS:
    Stan Barber, Rice U
    Jim Barbour, U of Colorado
    Donn Baumgartner, Dell
+   Ian Beckwith, Debian Project
    Nelson Beebe, U of Utah
    Gerry Belanger, Cognitronics
    Karl Berry, UMB
@@ -339,10 +252,12 @@ ACKNOWLEDGMENTS:
    Gary Bilkus
    Peter Binderup, Denmark
    David Bolen, Advanced Networks and Services, Inc.
+   Joop Bonen
    Marc Boucher, U of Montreal
    Charles Brooks, EDN
    Bob Brown
    Mike Brown, Purdue U
+   Rob Brown
    Jack Bryans, California State U at Long Beach
    Mark Buda, DEC (VMS)
    Fernando Cabral, Padrao iX, Brasilia
@@ -358,6 +273,7 @@ ACKNOWLEDGMENTS:
    Howard Chu, U of Michigan
    Bill Coalson, McDonnell Douglas
    Bertie Coopersmith, London
+   Christian Corti
    Chet Creider, U of Western Ontario
    Alan Crosswell, Columbia U
    Jeff Damens, (formerly of) Columbia U
@@ -380,6 +296,7 @@ ACKNOWLEDGMENTS:
    Herm Fischer, Encino, CA (extensive contributions to version 4.0)
    Carl Fongheiser, CWRU
    Mike Freeman, Bonneville Power Authority
+   Carl Friedberg
    Marcello Frutig, Catholic University, Sao Paulo, Brazil (X.25 support)
    Hirofumi Fujii, Japan Nat'l Lab for High Energy Physics, Tokyo (Kanji)
    Chuck Fuller, Westinghouse Corporate Computer Services
@@ -449,6 +366,7 @@ ACKNOWLEDGMENTS:
    Douglas Kingston, morgan.com
    Lawrence Kirby, Wiltshire, UK
    Tom Kloos, Sequent Computer Systems
+   Guenter Knauf
    Jim Knutson, U of Texas at Austin
    John T. Kohl (BSDI)
    Scott Kramer, SRI International, Menlo Park, CA
@@ -463,6 +381,7 @@ ACKNOWLEDGMENTS:
    Bert Laverman, Groningen U, Netherlands
    Steve Layton
    David Lawyer, UC Irvine
+   Jason Lehr
    David LeVine, National Semiconductor Corporation
    Daniel S. Lewart, UIUC
    S.O. Lidie, Lehigh U
@@ -474,6 +393,7 @@ ACKNOWLEDGMENTS:
    Kevin Lowey, U of Saskatchewan (OS/2)
    Andy Lowry, Columbia U
    James Lummel, Caprica Telecomputing Resources (QNX)
+   Lewis McCarthy
    David MacKenzie, Environmental Defense Fund, U of Maryland
    John Mackin, University of Sidney, Australia
    Martin Maclaren, Bath U, UK
@@ -487,6 +407,7 @@ ACKNOWLEDGMENTS:
    Hellmuth Michaelis, Hanseatischer Computerservice GmbH, Hamburg, Germany
    Leslie Mikesell, American Farm Bureau
    Todd Miller, Courtesan Consulting
+   Gary Mills
    Martin Minow, DEC (VMS)
    Pawan Misra, Bellcore
    Ken Mizialko, IBM, Manassas, VA
@@ -518,6 +439,7 @@ ACKNOWLEDGMENTS:
    Tony Querubin, U of Hawaii
    Jean-Pierre Radley
    Anton Rang
+   Mike Rechtman
    Scott Ribe
    Alan Robiette, Oxford University, UK
    Michel Robitaille, U of Montreal (Mac)
@@ -538,9 +460,11 @@ ACKNOWLEDGMENTS:
    Dan Schullman, DEC (modems, DIAL command, etc)
    John Schultz, 3M
    Steven Schultz, Contel (PDP-11)
+   Steven Schweda
    APPP Scorer, Leeds Polytechnic, UK
    Gordon Scott, Micro Focus, Newbury UK
    Gisbert W. Selke, WIdO, Bonn, Germany
+   Kijal Shah
    David Singer, IBM Almaden Research Labs
    David Sizeland, U of London Medical School
    Fridrik Skulason, Iceland
@@ -556,6 +480,7 @@ ACKNOWLEDGMENTS:
    James R. Swenson, Accu-Weather, Inc.
    Ted T'so, MIT (Linux)
    Andy Tanenbaum, Vrije U, Amsterdam, Netherlands
+   Seth Theriault, Columbia U
    Glen Thobe
    Markku Toijala, Helsinki U of Technology
    Teemu Torma, Helsinki U of Technology
@@ -574,11 +499,13 @@ ACKNOWLEDGMENTS:
    Paul Vixie, DEC
    Bernie Volz, Process Software
    Eduard Vopicka, Prague University of Economics, Czech Republic
+   Martin Vorlaender
    Dimitri Vulis, CUNY
    Roger Wallace, Raytheon
    Stephen Walton, Calif State U, Northridge (Amiga)
    Jamie Watson, Adasoft, Switzerland (AIX)
    Rick Watson, U of Texas (Macintosh)
+   Eric Weaver, Columbia U
    Scott Weikart (Association for Progressive Communications)
    Robert Weiner, Programming Plus, New York City
    Lauren Weinstein, Vortex Technlogy
@@ -796,6 +723,7 @@ int spsiz = DSPSIZ,                     /* Current packet size to send */
     bctr = DFBCT,                       /* Block check type requested */
     bctu = 1,                           /* Block check type used */
     bctl = 1,                           /* Block check length */
+    bctf = 0,                          /* Block check type 3 forced on all */
     c_save = -1,                        /* Block check saving and restoring */
     ss_save = -1,                       /* Slow-start saving and restoring */
     ebq =  MYEBQ,                       /* 8th bit prefix */
@@ -821,6 +749,8 @@ int xfrxla = 0;                         /* Character-set translation */
 int xfrxla = 1;                         /* enabled or disabled */
 #endif /* NOCSETS */
 
+int havelfs = 0;                       /* Large file support available */
+
 #ifndef NOXFER
 int epktflg = 0;                        /* E-PACKET command active */
 
@@ -1071,14 +1001,18 @@ extern VOID zsyslog();
 extern int ckxlogging, ckxsyslog;
 #endif /* CKSYSLOG */
 
+CK_OFF_T fsize = (CK_OFF_T)0,          /* Size of current file */
+ sendstart = (CK_OFF_T)0,              /* SEND start position */
+ calibrate = (CK_OFF_T)0;              /* Nonzero if calibration run */
+
 int nzxopts = 0;                        /* Options for nzxpand() */
 int nfils = 0;                          /* Number of files in file group */
-long fsize = 0L;                        /* Size of current file */
+int wildena = 1;                       /* Wildcard expansion enabled */
 #ifdef UNIX
-int wildxpand = 0;                      /* Who expands wildcards */
+int wildxpand = 0;                      /* Who expands wildcards, 0=Kermit.. */
 #else /* UNIX */
 #ifdef STRATUS
-int wildxpand = 1;
+int wildxpand = 1;                     /* 1=Shell. */
 #endif /* STRATUS */
 #endif /* UNIX */
 #ifdef UNIXOROSK
@@ -1321,14 +1255,16 @@ int xsuspend = 0;
 
 /* Statistics variables */
 
-long filcnt,                    /* Number of files in transaction */
-    filrej,                     /* Number of files rejected in transaction */
+CK_OFF_T
     flci,                       /* Characters from line, current file */
     flco,                       /* Chars to line, current file  */
     tlci,                       /* Chars from line in transaction */
     tlco,                       /* Chars to line in transaction */
     ffc,                        /* Chars to/from current file */
-    tfc,                        /* Chars to/from files in transaction */
+    tfc;                        /* Chars to/from files in transaction */
+
+long filcnt,                    /* Number of files in transaction */
+    filrej,                     /* Number of files rejected in transaction */
     cps = 0L,                   /* Chars/sec last transfer */
     peakcps = 0L,               /* Peak chars/sec last transfer */
     ccu,                        /* Control chars unprefixed in transaction */
@@ -1351,6 +1287,7 @@ int deblog = 0,                         /* Debug log is open */
     debxlen = 54,                       /* Default length for debug strings */
     debses = 0,                         /* Flag for DEBUG SESSION */
     debtim = 0,                         /* Include timestamp in debug log */
+    debmsg = 0,                         /* Debug messages on/off */
     pktlog = 0,                         /* Flag for packet logging */
     seslog = 0,                         /* Session logging */
     dialog = 0,                         /* DIAL logging */
@@ -1448,9 +1385,6 @@ char * g_snd_rename = NULL;
 char * g_rcv_move = NULL;
 char * g_rcv_rename = NULL;
 
-long sendstart = 0L;                    /* SEND start position */
-long calibrate = 0L;                    /* Nonzero if calibration run */
-
 #ifdef CK_TRIGGER
 char *tt_trigger[TRIGGERS] = { NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL };
 CHAR *tt_trmatch[TRIGGERS] = { NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL };
@@ -1699,6 +1633,8 @@ getsysix(s) char *s; {                  /* Get system-type index */
 
 /* Tell if a pathname is absolute (versus relative) */
 /* This should be parceled out to each of the ck*fio.c modules... */
+/* VMS isabsolute() is now in ckvfio.c. */
+#ifndef VMS
 int
 isabsolute(path) char * path; {
     int rc = 0;
@@ -1709,21 +1645,6 @@ isabsolute(path) char * path; {
       return(0);
     x = (int) strlen(path);
     debug(F111,"isabsolute",path,x);
-#ifdef VMS
-    rc = 0;
-    x = ckindex("[",path,0,0,0);        /* 1-based */
-    if (!x)
-       x = ckindex("<",path,0,0,0);
-    debug(F111,"isabsolute left bracket",path,x);
-    if (!x) {
-        x = ckindex(":",path,-1,1,1);
-        if (x)
-          debug(F111,"isabsolute logical",path,x);
-    }
-    if (x > 0)
-      if (path[x] != '.')               /* 0-based */
-        rc = 1;
-#else
 #ifdef UNIX
     if (*path == '/'
 #ifdef DTILDE
@@ -1731,14 +1652,14 @@ isabsolute(path) char * path; {
 #endif /* DTILDE */
         )
       rc = 1;
-#else
+#else /* def UNIX */
 #ifdef OS2
     if (*path == '/' || *path == '\\')
       rc = 1;
     else if (isalpha(*path) && x > 2)
       if (*(path+1) == ':' && (*(path +2) == '/' || *(path+2) == '\\'))
         rc = 1;
-#else
+#else /* def OS2 */
 #ifdef AMIGA
     if (*path == '/'
 #ifdef DTILDE
@@ -1746,7 +1667,7 @@ isabsolute(path) char * path; {
 #endif /* DTILDE */
         )
       rc = 1;
-#else
+#else /* def AMIGA */
 #ifdef OSK
     if (*path == '/'
 #ifdef DTILDE
@@ -1754,17 +1675,17 @@ isabsolute(path) char * path; {
 #endif /* DTILDE */
         )
       rc = 1;
-#else
+#else /* def OSK */
 #ifdef datageneral
     if (*path == ':')
       rc = 1;
-#else
+#else /* def datageneral */
 #ifdef MAC
     rc = 0;                             /* Fill in later... */
-#else
+#else /* def MAC */
 #ifdef STRATUS
     rc = 0;                             /* Fill in later... */
-#else
+#else /* def STRATUS */
 #ifdef GEMDOS
     if (*path == '/' || *path == '\\')
       rc = 1;
@@ -1779,10 +1700,10 @@ isabsolute(path) char * path; {
 #endif /* AMIGA */
 #endif /* OS2 */
 #endif /* UNIX */
-#endif /* VMS */
     debug(F101,"isabsolute rc","",rc);
     return(rc);
 }
+#endif /* ndef VMS */
 
 /*  See if I have direct access to the keyboard  */
 
@@ -2288,7 +2209,7 @@ ikslogin() {
         if (nmac) {                     /* Any macros defined? */
             int k;                      /* Yes */
             char * cmd = "on_login";    /* MSVC 2.x compiler error */
-            k = mlook(mactab,cmd,nmac); /* Look up "on_exit" */
+            k = mlook(mactab,cmd,nmac); /* Look up "on_login" */
             if (k >= 0) {               /* If found, */
 #ifdef IKSDCONF
                 int saved = iksdcf;
@@ -2394,8 +2315,10 @@ failtakeini(threadinfo) VOID * threadinfo;
 #ifdef GEMDOS
     cc_clean();                         /* Atari: Clean up after ^C-trap. */
 #endif /* GEMDOS */
+    fixcmd();
     if (!cfilef) {
-        conoll("Interrupt during initialization or command-line processing.");
+        conoll("Interrupted during initialization or \
+command-line processing.");
         conoll("C-Kermit quitting...");
     }
     doexit(BAD_EXIT,-1);                /* Exit with bad status. */
@@ -2538,15 +2461,16 @@ docmdfile(threadinfo) VOID * threadinfo;
 #ifndef NOSPL
     addmac("\\%0",cmdfil);
 #endif /* NOSPL */
-    dotake(cmdfil);                     /* execute it */
-    while (tlevel > -1) {               /* until it runs out. */
+    dotake(cmdfil);                    /* Set up the command file */
+    if (tlevel > -1)                   /* Remember we did this */
+      cfilef = 1;
+    while (tlevel > -1) {               /* Execute it until it runs out. */
         sstate = parser(1);             /* Loop getting commands. */
         if (sstate) proto();            /* Enter protocol if requested. */
 #ifdef NTSIG
         ck_ih();
 #endif /* NTSIG */
     }
-    cfilef = 1;                         /* Remember we did this */
 
 #ifdef NTSIG
     ckThreadEnd(threadinfo);
@@ -2564,9 +2488,11 @@ failcmdfile(threadinfo) VOID * threadinfo;
 #ifdef GEMDOS
     cc_clean();                         /* Atari: Clean up after ^C-trap. */
 #endif /* GEMDOS */
+    fixcmd();
     if (!cfilef) {
-        conoll("Interrupt during initialization or command-line processing.");
-        conoll("C-Kermit quitting...");
+       conoll("Interrupted during initialization or \
+command-line processing.");
+       conoll("C-Kermit quitting...");
     }
     doexit(BAD_EXIT,-1);                /* Exit with bad status. */
 }
@@ -2661,6 +2587,7 @@ setprefix(z) int z; {                   /* Initial control-char prefixing */
 VOID
 makever() {                             /* Make version string from pieces */
     int x, y;
+    char * s;
 #ifndef OS2
 #ifndef MAC
     ck_s_xver = ck_s_ver;               /* Fill in C-Kermit version number */
@@ -2676,6 +2603,14 @@ makever() {                             /* Make version string from pieces */
         return;
     }
     x += y + 1;
+  
+    s = " OPEN SOURCE:";               /* C-Kermit 9.0 and later */
+    y = strlen(s);
+    if (CKVERLEN < x + y + 1)
+      return;
+    ckstrncat(versio,s,CKVERLEN);
+
+    x += y + 1;
     if (*ck_s_who) {
         y = strlen(ck_s_who);
         if (CKVERLEN < x + y + 1)
@@ -2957,8 +2892,41 @@ main(argc,argv) int argc; char **argv;
     *pfha = (short) 0;                  /* No user protection fault handler */
 #endif /* datageneral */
 
+    int unbuf = 0;                     /* nonzero for unbuffered stdout */
+
+/* setbuf has to be called on the file descriptor before it is used */
+
+#ifdef UNIX
+#ifdef NONOSETBUF                      /* Unbuffered console i/o */
+    unbuf++;                           /* as a compile-time option */
+#endif /* NONOSETBUF */
+    if (!unbuf) {                      /* Or as a command-line selection */
+       int i, n;                       /* We have to pre-pre-scan for */
+       char * s;                       /* this one. */
+       for (i = 1; i < argc; i++) {
+           s = argv[i];
+           if (!s) n = 0; else n = (int)strlen(s);
+           if (n > 4) {
+               if (!ckstrcmp("--unbuffered",s,n,0)) {
+                   unbuf++;
+                   break;
+               }
+           }
+       }
+    }
+    if (unbuf)
+      setbuf(stdout,NULL);
+#endif /* UNIX */
+
 /* Do some initialization */
 
+#ifdef VMS
+#ifdef __DECC
+    /* Get some RMS default settings. */
+    get_rms_defaults();
+#endif /* def __DECC */
+#endif /* def VMS */
+
 #ifndef MAC
     xargc = xargs = argc;               /* Make global copies of argc */
     xargv = argv;                       /* ...and argv. */
@@ -3031,6 +2999,9 @@ main(argc,argv) int argc; char **argv;
         byteorder = 0;                  /* Big Endian */
         bigendian = 1;
     }
+    if (sizeof(CK_OFF_T) == 8)         /* Large files and ints? */
+      havelfs = 1;
+
     if (sysinit() < 0)                  /* System-dependent initialization. */
       fatal("Can't initialize!");
     else
@@ -3365,6 +3336,8 @@ main(argc,argv) int argc; char **argv;
                 switch (ttnproto) {
                  case NP_SSL:
                  case NP_TLS:
+                 case NP_SSL_RAW:
+                 case NP_TLS_RAW:
                  case NP_SSL_TELNET:
                  case NP_TLS_TELNET:
                     doexit(BAD_EXIT,1);
index 3bae53e..5384e00 100644 (file)
--- a/ckcnet.c
+++ b/ckcnet.c
@@ -1,9 +1,9 @@
-char *cknetv = "Network support, 8.0.283, 7 Feb 2004";
+char *cknetv = "Network support, 9.0.296, 16 Mar 2010";
 
 /*  C K C N E T  --  Network support  */
 
 /*
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2010,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -72,8 +72,15 @@ char *cknetv = "Network support, 8.0.283, 7 Feb 2004";
 #ifdef USE_NAMESER_COMPAT
 #include <arpa/nameser_compat.h>
 #endif /* USE_NAMESER_COMPAT */
+
+#ifdef MINIX3
+#include <net/gen/resolv.h>
+#include <net/gen/nameser.h>
+#else
 #include <arpa/nameser.h>
 #include <resolv.h>
+#endif /* MINIX 3 */
+
 #ifndef PS2AIX10
 #ifndef BSD4
 #ifndef I386IX
@@ -138,10 +145,22 @@ extern int inserver;
 #endif /* IKSD */
 
 char myipaddr[20] = { '\0' };           /* Global copy of my IP address */
+char hostipaddr[64] = { '\0' };                /* Global copy of remote IP address */
 
 #ifdef NETCONN
 /* Don't need any of this if there is no network support. */
 
+#ifndef OS2
+/* Current fd-swapping hack is not thread-safe */
+#define HTTP_BUFFERING
+#endif /* OS2 */
+
+#ifdef HTTP_BUFFERING
+#define HTTP_INBUFLEN 8192
+static char http_inbuf[HTTP_INBUFLEN];
+static int http_bufp = 0, http_count;
+#endif /* HTTP_BUFFERING */
+
 /*
   NETLEBUF is (must be) defined for those platforms that call this
   module to do network i/o (e.g. netinc(), nettchk(), etc) rather
@@ -182,7 +201,9 @@ int tt_push_inited = 0;
 
 #ifdef HPUX
 #ifndef HPUX7                           /* HPUX 7.00 doesn't have it */
+#ifndef HPUX6                           /* HPUX 6.00 doesn't have it */
 #include <arpa/inet.h>                  /* For inet_ntoa() prototype */
+#endif /* HPUX6 */
 #endif /* HPUX7 */
 #endif /* HPUX */
 
@@ -580,7 +601,7 @@ le_puts(s,n) CHAR * s; int n;
     int rc = 0;
     int i = 0;
     CHAR * p = (CHAR *)"le_puts";
-    hexdump(p,s,n);
+    ckhexdump(p,s,n);
     for (i = 0; i < n; i++)
       rc = le_putchar((char)s[i]);
     debug(F101,"le_puts","",rc);
@@ -597,7 +618,7 @@ le_putstr(s) CHAR * s;
     CHAR * p;
     int rc = 0;
     p = (CHAR *)"le_putstr";
-    hexdump(p,s,(int)strlen((char *)s));
+    ckhexdump(p,s,(int)strlen((char *)s));
     for (p = s; *p && !rc; p++)
       rc = le_putchar(*p);
     return(rc);
@@ -1279,7 +1300,7 @@ ttbufr() {                              /* TT Buffer Read */
               return(-2);
 #endif /* OS2ONLY */
           } else {                      /* we got out-of-band data */
-              hexdump("ttbufr out-of-band chars",&ttibuf[ttibp+ttibn],count);
+              ckhexdump("ttbufr out-of-band chars",&ttibuf[ttibp+ttibn],count);
 #ifdef BETADEBUG
               bleep(BP_NOTE);
 #endif /* BETADEBUG */
@@ -1561,8 +1582,11 @@ inet_ntoa(in) struct in_addr in; {
 
 int ucx_port_bug = 0;                   /* Explained below */
 
-#ifndef __DECC                          /* VAXC or GCC */
-
+#ifdef OLDIP                           /* Very old VAXC or GCC */
+/*
+  Note that my oldest VAX C (V3.1-051) does not need (or want) OLDIP,
+  hence the "Very old" in the comment - SMS, 2010/03/15.
+*/
 #define getservbyname my_getservbyname
 
 #ifdef CK_ANSIC
@@ -1638,9 +1662,15 @@ my_getservbyname (service, proto) char *service, *proto; {
     }
     return &sent;
 }
-#endif /* __DECC */
+#endif /* def OLDIP */
 #endif /* DEC_TCPIP */
 #endif /* EXCELAN */
+
+int
+gettcpport() {
+    return(svcnum);
+}
+
 #endif /* TCPSOCKET */
 
 #ifndef NOTCPOPTS
@@ -2418,8 +2448,17 @@ tcpsocket_open(name,lcl,nett,timo) char * name; int * lcl; int nett; int timo {
 
     netclos();                          /* Close any previous connection. */
     ckstrncpy(namecopy, name, NAMECPYL); /* Copy the hostname. */
+#ifdef COMMENT
+    /* Jeff's version from 30 Dec 2005 doesn't inhibit Telnet */
+    if (ttnproto != NP_TCPRAW &&
+       ttnproto != NP_SSL_RAW &&
+       ttnproto != NP_TLS_RAW)
+      ttnproto = NP_NONE;               /* No protocol selected yet. */
+#else
+    /* fdc's version from 4 Dec 2005 works ok */
     if (ttnproto != NP_TCPRAW)
       ttnproto = NP_NONE;               /* No protocol selected yet. */
+#endif /* COMMENT */
     debug(F110,"tcpsocket_open namecopy",namecopy,0);
 
     /* Assign the socket number to ttyfd and then fill in tcp structures */
@@ -2525,8 +2564,16 @@ tcpsocket_open(name,lcl,nett,timo) char * name; int * lcl; int nett; int timo {
     else
 #endif /* RLOGCODE */
     /* Assume the service is TELNET. */
-    if (ttnproto != NP_TCPRAW)
-        ttnproto = NP_TELNET;           /* Yes, set global flag. */
+#ifdef COMMENT
+      /* Jeff's code from 2005/12/30 */
+      if (ttnproto != NP_TCP_RAW &&
+         ttnproto != NP_SSL_RAW &&
+         ttnproto != NP_TLS_RAW)
+#else
+      /* fdc's code from 2005/12/04 */
+      if (ttnproto != NP_TCPRAW)
+#endif /* COMMENT */
+       ttnproto = NP_TELNET;           /* Yes, set global flag. */
 #ifdef CK_SECURITY
     /* Before Initialization Telnet/Rlogin Negotiations Init Kerberos */
     ck_auth_init((tcp_rdns && host && host->h_name && host->h_name[0]) ?
@@ -2594,10 +2641,18 @@ tcpsrv_open(name,lcl,nett,timo) char * name; int * lcl; int nett; int timo; {
 
     netclos();                          /* Close any previous connection. */
     ckstrncpy(namecopy, name, NAMECPYL); /* Copy the hostname. */
-#ifdef COMMENT
     /* Don't do this. */
+#ifdef COMMENT
+    /* fdc */
     if (ttnproto != NP_TCPRAW)
       ttnproto = NP_NONE;               /* No protocol selected yet. */
+#endif /* COMMENT */
+#ifdef COMMENT
+    /* Jeff */
+    if (ttnproto != NP_TCP_RAW &&
+       ttnproto != NP_SSL_RAW &&
+       ttnproto != NP_TLS_RAW)
+      ttnproto = NP_NONE;               /* No protocol selected yet. */
 #endif /* COMMENT */
     debug(F110,"tcpsrv_open namecopy",namecopy,0);
 
@@ -2799,7 +2854,11 @@ tcpsrv_open(name,lcl,nett,timo) char * name; int * lcl; int nett; int timo; {
 #endif /* HPUX1010 */
 #else
 #ifdef __DECC
+#ifdef INTSELECT
+                       (int *)
+#else /* def INTSELECT */
                        (fd_set *)
+#endif /* def INTSELECT [else] */
 #endif /* __DECC */
 #endif /* HPUX */
                        &rfds, NULL, NULL, &tv) > 0) &&
@@ -2887,10 +2946,17 @@ tcpsrv_open(name,lcl,nett,timo) char * name; int * lcl; int nett; int timo; {
         x = (unsigned short)service->s_port;
         service2 = getservbyname("telnet", "tcp");
         if (service2 && x == service2->s_port) {
+#ifdef COMMENT
+           /* Jeff 2005/12/30 */
+           if (ttnproto != NP_TCPRAW && /* Yes... */
+                ttnproto != NP_SSL_RAW &&
+                ttnproto != NP_TLS_RAW) /* and if raw port not requested */
+#else
+           /* fdc 2005/12/04 */
             if (ttnproto != NP_TCPRAW)  /* Yes and if raw port not requested */
-              ttnproto = NP_TELNET;     /* Set protocol to TELNET. */
+#endif /*  */
+              ttnproto = NP_TELNET;    /* set protocol to TELNET. */
         }
-
         ckstrncpy(ipaddr,(char *)inet_ntoa(saddr.sin_addr),20);
         if (tcp_rdns) {
             if (!quiet) {
@@ -2906,8 +2972,8 @@ tcpsrv_open(name,lcl,nett,timo) char * name; int * lcl; int nett; int timo; {
                 }
                 name[0] = '*';
                 ckstrncpy(&name[1],host->h_name,78);
-                strncat(name,":",80-strlen(name));
-                strncat(name,p,80-strlen(name));
+                ckstrncat(name,":",80-strlen(name));
+                ckstrncat(name,p,80-strlen(name));
                 if (!quiet
 #ifndef NOICP
                     && !doconx
@@ -3089,6 +3155,9 @@ ckgetpeer() {
     static char namebuf[256];
     static struct hostent *host;
     static struct sockaddr_in saddr;
+#ifdef GPEERNAME_T
+    static GPEERNAME_T saddrlen;
+#else
 #ifdef PTX
     static size_t saddrlen;
 #else
@@ -3101,13 +3170,34 @@ ckgetpeer() {
     static size_t saddrlen;
 #else  /* UNIXWARE */
 #ifdef DEC_TCPIP
+/* 2010-03-08 SMS.
+ * Coincidentally, the condition for integer arguments in select(),
+ * which is actually "defined( _DECC_V4_SOURCE)", works for an integer
+ * argument in getpeername().  Sadly, due to a lack of foresight,
+ * "defined( _DECC_V4_SOURCE)" doesn't work with DEC C V4.0, so the
+ * user-specified INTSELECT is used instead.  Most likely, "size_t"
+ * should be used instead of "unsigned int", but I'm a coward.
+ */
+#ifdef INTSELECT
+    static int saddrlen;
+#else /* def INTSELECT */
     static unsigned int saddrlen;
+#endif /* def INTSELECT [else] */
+#else
+#ifdef MACOSX10
+    static unsigned int saddrlen;
+#else
+#ifdef CK_64BIT
+    static socklen_t saddrlen;
 #else
     static int saddrlen;
-#endif /* VMS */
+#endif /* CK_64BIT */
+#endif /* MACOSX10 */
+#endif /* DEC_TCPIP */
 #endif /* UNIXWARE */
 #endif /* AIX42 */
 #endif /* PTX */
+#endif /* GPEERNAME_T */
     saddrlen = sizeof(saddr);
     if (getpeername(ttyfd,(struct sockaddr *)&saddr,&saddrlen) < 0) {
         debug(F111,"ckgetpeer failure",ckitoa(ttyfd),errno);
@@ -3179,11 +3269,13 @@ ckgetfqhostname(name) char * name;
 #else  /* HADDRLIST */
         bcopy(host->h_addr, (caddr_t)&r_addr.sin_addr, host->h_length);
 #endif /* HADDRLIST */
+#ifdef COMMENT
 #ifndef EXCELAN
         debug(F111,"BCOPY","host->h_addr",host->h_addr);
 #endif /* EXCELAN */
         debug(F111,"BCOPY"," (caddr_t)&r_addr.sin_addr",
               (caddr_t)&r_addr.sin_addr);
+#endif /* COMMENT */
         debug(F111,"BCOPY","host->h_length",host->h_length);
 
 #ifdef NT
@@ -3208,7 +3300,7 @@ ckgetfqhostname(name) char * name;
 #endif /* HADDRLIST */
 
     if (i > 0)
-      strncat(namebuf,&name[i-1],256-strlen(namebuf)-strlen(&name[i-1]));
+      ckstrncat(namebuf,&name[i-1],256-strlen(namebuf)-strlen(&name[i-1]));
     debug(F110,"ckgetfqhn()",namebuf,0);
     return(namebuf);
 #endif /* NOCKGETFQHOST */
@@ -3235,7 +3327,7 @@ setnproto(p) char * p;
 #ifdef CK_SSL
         /* Commonly used SSL ports (might not be in services file) */
         else if (!strcmp("https",p)) {
-          ttnproto = NP_SSL;
+          ttnproto = NP_SSL_RAW;
           ssl_only_flag = 1;
         } else if (!strcmp("ssl-telnet",p)) {
           ttnproto = NP_TELNET;
@@ -3279,7 +3371,13 @@ setnproto(p) char * p;
             break;
 #ifdef CK_SSL
           case 443:
+#ifdef COMMENT
+           /* Jeff 2005/12/30 */
+            ttnproto = NP_SSL_RAW;
+#else
+           /* fdc 2005/12/04 */
             ttnproto = NP_SSL;
+#endif /* COMMENT */
             ssl_only_flag = 1;
             break;
           case 151:
@@ -3424,10 +3522,13 @@ ckgetservice(hostname, servicename, ip, iplen)
   type rather than modem type.  Designed to be called from within ttopen.
 */
 
+#define XXNAMELEN 256
+static char xxname[XXNAMELEN];
+
 int
 netopen(name, lcl, nett) char *name; int *lcl, nett; {
     char *p;
-    int i, x, dns = 0;
+    int i, x, rc_inet_addr = 0, dns = 0;
 #ifdef TCPSOCKET
     int isconnect = 0;
 #ifdef SO_OOBINLINE
@@ -4045,33 +4146,46 @@ _PROTOTYP(SIGTYP x25oobh, (int) );
     iax.s_addr = inet_addr(namecopy);
     debug(F111,"netopen inet_addr",namecopy,iax.s_addr);
 #else /* INADDR_NONE */
+#ifdef SOLARIS
+    /* In Solaris inet_addr() is of type in_addr_t which is uint32_t */
+    /* (unsigned) yet it returns -1 (signed) on failure. */
+    /* It makes a difference in 64-bit builds. */
+    rc_inet_addr = inet_addr(namecopy);        /* Assign return code to an int */
+    iax = (unsigned) rc_inet_addr;     /* and from there to whatever.. */
+#else
 #ifndef datageneral
     iax = (unsigned int) inet_addr(namecopy);
 #else
     iax = -1L;
 #endif /* datageneral */
+#endif /* SOLARIS */
+    debug(F111,"netopen rc_inet_addr",namecopy,rc_inet_addr);
     debug(F111,"netopen inet_addr",namecopy,iax);
 #endif /* INADDR_NONE */
 #endif /* INADDRX */
 
     dns = 0;
     if (
-#ifdef INADDR_NONE
 /* This might give warnings on 64-bit platforms but they should be harmless */
 /* because INADDR_NONE should be all 1's anyway, thus the OR part is */
 /* probably superfluous -- not sure why it's even there, maybe it should be */
 /* removed. */
-        iax.s_addr == INADDR_NONE || iax.s_addr == (unsigned long) -1L
+#ifdef SOLARIS
+       rc_inet_addr == -1
+#else
+#ifdef INADDR_NONE
+        iax.s_addr == INADDR_NONE /* || iax.s_addr == (unsigned long) -1L */
 #else /* INADDR_NONE */
         iax < 0
 #endif /* INADDR_NONE */
+#endif /* SOLARIS */
         ) {
         if (!quiet) {
             printf(" DNS Lookup... ");
             fflush(stdout);
         }
         if ((host = gethostbyname(namecopy)) != NULL) {
-            debug(F100,"netopen gethostbyname != NULL","",0);
+            debug(F110,"netopen gethostbyname != NULL",namecopy,0);
             host = ck_copyhostent(host);
             dns = 1;                    /* Remember we performed dns lookup */
             r_addr.sin_family = host->h_addrtype;
@@ -4079,13 +4193,25 @@ _PROTOTYP(SIGTYP x25oobh, (int) );
 #ifndef NOHTTP
                  && (tcp_http_proxy == NULL)
 #endif /* NOHTTP */
-                 ) {                   /* Copying into our argument? */
+               ) {
+#ifdef COMMENT
+                ckstrncpy(xxname,host->h_name,XXNAMELEN);
+               debug(F110,"netopen xxname[1]",xxname,0);
+                if ((XXNAMELEN - (int)strlen(name)) > ((int)strlen(svcbuf)+1)){
+                    ckstrncat(xxname,":",XXNAMELEN - (int)strlen(xxname));
+                    ckstrncat(xxname,svcbuf,XXNAMELEN - (int)strlen(xxname));
+                   debug(F110,"netopen xxname[2]",xxname,0);
+                }
+               name = (char *)xxname;
+#else
                 ckstrncpy(name,host->h_name,80);  /* Bad Bad Bad */
                 if ( (80-strlen(name)) > (strlen(svcbuf)+1) ) {
-                    strncat(name,":",80-strlen(name));
-                    strncat(name,svcbuf,80-strlen(name));
+                    ckstrncat(name,":",80-strlen(name));
+                    ckstrncat(name,svcbuf,80-strlen(name));
                 }
+#endif /* COMMENT */
             }
+           debug(F110,"netopen name after lookup",name,0);
 
 #ifdef HADDRLIST
 #ifdef h_addr
@@ -4100,20 +4226,22 @@ _PROTOTYP(SIGTYP x25oobh, (int) );
             bcopy(host->h_addr, (caddr_t)&r_addr.sin_addr, host->h_length);
 #endif /* h_addr */
 #else  /* HADDRLIST */
+#ifdef HPUX6
+           r_addr.sin_addr.s_addr = (u_long)host->h_addr;
+#else  /* HPUX6 */
             bcopy(host->h_addr, (caddr_t)&r_addr.sin_addr, host->h_length);
+#endif /* HPUX6 */
 #endif /* HADDRLIST */
-#ifndef EXCELAN
-            debug(F111,"BCOPY","host->h_addr",host->h_addr);
-#endif /* EXCELAN */
-            debug(F111,"BCOPY"," (caddr_t)&r_addr.sin_addr",
-                  (caddr_t)&r_addr.sin_addr);
-            debug(F111,"BCOPY"," r_addr.sin_addr.s_addr",
-                  r_addr.sin_addr.s_addr);
+
+#ifndef HPUX6
             debug(F111,"BCOPY","host->h_length",host->h_length);
+#endif /* HPUX6 */
         }
     }
 #endif /* NOMHHOST */
 
+    debug(F101,"netopen dns","",dns);
+
     if (!dns) {
 #ifdef INADDRX
 /* inet_addr() is of type struct in_addr */
@@ -4530,7 +4658,14 @@ _PROTOTYP(SIGTYP x25oobh, (int) );
     /* See if the service is TELNET. */
     if (x == TELNET_PORT) {
         /* Yes, so if raw port not requested */
+#ifdef COMMENT
+       /* Jeff 2005/12/30 */
+        if (ttnproto != NP_TCPRAW && ttnproto != NP_SSL_RAW && 
+           ttnproto != NP_TLS_RAW && ttnproto != NP_NONE)
+#else
+       /* fdc 2005/12/04 */
         if (ttnproto != NP_TCPRAW && ttnproto != NP_NONE)
+#endif /* COMMENT */
           ttnproto = NP_TELNET;         /* Select TELNET protocol. */
     }
 #ifdef RLOGCODE
@@ -4795,8 +4930,8 @@ _PROTOTYP(SIGTYP x25oobh, (int) );
             if (*s) {                   /* Copying into our argument? */
                 ckstrncpy(name,s,80);   /* Bad Bad Bad */
                 if ( (80-strlen(name)) > (strlen(svcbuf)+1) ) {
-                    strncat(name,":",80-strlen(name));
-                    strncat(name,svcbuf,80-strlen(name));
+                    ckstrncat(name,":",80-strlen(name));
+                    ckstrncat(name,svcbuf,80-strlen(name));
                 }
             }
             if (!quiet && *s
@@ -4922,6 +5057,8 @@ _PROTOTYP(SIGTYP x25oobh, (int) );
 
     debug(F101,"netopen service","",svcnum);
     debug(F110,"netopen name",name,0);
+    debug(F110,"netopen ipaddr",ipaddr,0);
+    ckstrncpy(hostipaddr,ipaddr,63);
 
     if (lcl) if (*lcl < 0)              /* Local mode. */
       *lcl = 1;
@@ -4980,7 +5117,14 @@ netclos() {
 #endif /* VMS */
 #ifdef TNCODE
           if (ttnproto == NP_TELNET) {
-            if ( !TELOPT_ME(TELOPT_LOGOUT) ) {
+            if (!TELOPT_ME(TELOPT_LOGOUT)
+#ifdef COMMENT
+/* Jeff 2005/12/30 */
+#ifdef CK_SSL
+                && !ssl_raw_flag && !tls_raw_flag
+#endif /* CK_SSL */
+#endif /* COMMENT */
+               ) {
                /* Send LOGOUT option before close */
                if (tn_sopt(DO,TELOPT_LOGOUT) >= 0) {
                    TELOPT_UNANSWERED_DO(TELOPT_LOGOUT) = 1;
@@ -5562,12 +5706,12 @@ nettchk() {                             /* for reading from network */
         if (x >= 1) {                   /* Oops, actually got a byte? */
 #ifdef OS2
             /* In OS/2 we read directly into ttibuf[] */
-            hexdump("nettchk got real data",&ttibuf[ttibp+ttibn],x);
+            ckhexdump("nettchk got real data",&ttibuf[ttibp+ttibn],x);
             ttibn += x;
 #else /* OS2 */
 #ifdef CK_SSL
            if ( ssl_active_flag || tls_active_flag ) {
-               hexdump("nettchk got real data",&ttibuf[ttibp+ttibn],x);
+               ckhexdump("nettchk got real data",&ttibuf[ttibp+ttibn],x);
                ttibn += x;
            } else 
 #endif /* CK_SSL */
@@ -5722,7 +5866,7 @@ netxin(n,buf) int n; CHAR * buf; {
 #ifdef KRB5
 #ifdef RLOGCODE
     if (ttnproto == NP_EK5LOGIN) {
-        if ((len = krb5_des_read(ttyfd,buf,n,0)) < 0)
+        if ((len = krb5_des_read(ttyfd,(char *)buf,n,0)) < 0)
           return(-1);
         else
           return(len);
@@ -5730,7 +5874,7 @@ netxin(n,buf) int n; CHAR * buf; {
 #endif /* RLOGCODE */
 #ifdef KRB5_U2U
     if (ttnproto == NP_K5U2U) {
-        if ((len = krb5_u2u_read(ttyfd,buf,n)) < 0)
+        if ((len = krb5_u2u_read(ttyfd,(char *)buf,n)) < 0)
           return(-1);
         else
           return(len);
@@ -5984,9 +6128,15 @@ netinc(timo) int timo; {
                 WSASafeToCancel = 1;
 #endif /* NT */
                 rc = select(FD_SETSIZE,
-#ifndef __DECC
+#ifdef __DECC
+#ifdef INTSELECT
+                            (int *)
+#else /* def INTSELECT */
                             (fd_set *)
-#endif /* __DECC */
+#endif /* def INTSELECT [else] */
+#else /* def __DECC */
+                            (fd_set *)
+#endif /* def __DECC [else] */
                             &rfds, NULL, NULL, &tv);
                 if (rc < 0) {
                     int s_errno = socket_errno;
@@ -6138,7 +6288,7 @@ netinc(timo) int timo; {
                     extern int tt_type_mode;
                     if ( !ISVTNT(tt_type_mode) )
 #endif /* OS2 */
-                    hexdump("netinc &ttbuf[ttibp]",&ttibuf[ttibp],ttibn);
+                    ckhexdump("netinc &ttbuf[ttibp]",&ttibuf[ttibp],ttibn);
                 }
 #endif /* BETADEBUG */
             }
@@ -6179,7 +6329,7 @@ nettol(s,n) CHAR *s; int n; {
     }
     debug(F101,"nettol TCPIPLIB ttnet","",ttnet);
 #ifdef COMMENT
-    hexdump("nettol",s,n);
+    ckhexdump("nettol",s,n);
 #endif /* COMMENT */
 
 #ifdef CK_KERBEROS
@@ -6825,6 +6975,7 @@ getlocalipaddr() {
     /* if still not resolved, then try second strategy */
     /* This second strategy does not work on Windows */
 
+    debug(F100,"getlocalipaddr","",0);
     memset(&l_sa,0,slen);
     memset(&r_sa,0,slen);
 
@@ -6885,6 +7036,7 @@ getlocalipaddrs(buf,bufsz,index)
     struct in_addr laddr;
 #endif /* COMMENT */
 
+    debug(F100,"getlocalipaddrs","",0);
     memset(&l_sa,0,slen);
     memset(&r_sa,0,slen);
 
@@ -6909,7 +7061,7 @@ getlocalipaddrs(buf,bufsz,index)
         /* resolve host name for local address */
         debug(F110,"getlocalipaddrs","calling gethostbyname()",0);
         host = gethostbyname(localhost);
-        debug(F111,"getlocalipaddrs","gethostbyname() returned",host);
+        /* debug(F111,"getlocalipaddrs","gethostbyname() returned",host); */
         if (host) {
 #ifdef HADDRLIST
             host = ck_copyhostent(host);
@@ -9793,6 +9945,10 @@ x25dump_prim(primitive)    N_npi_ctl_t *primitive; {
 #endif /* SYSUTIMEH */
 #endif /* OS2 */
 
+#ifdef VMS                             /* SMS 2007/02/15 */
+#include "ckvrtl.h"
+#endif /* def VMS */
+
 #ifndef HTTP_VERSION
 #define HTTP_VERSION "HTTP/1.1"
 #endif /* HTTP_VERSION */
@@ -10240,9 +10396,9 @@ http_open(hostname, svcname, use_ssl, rdns_name, rdns_len, agent)
 /* because INADDR_NONE should be all 1's anyway, thus the OR part is */
 /* probably superfluous -- not sure why it's even there, maybe it should be */
 /* removed. */
-        iax.s_addr == INADDR_NONE || iax.s_addr == (unsigned long) -1L
+        iax.s_addr == INADDR_NONE /* || iax.s_addr == (unsigned long) -1L */
 #else /* INADDR_NONE */
-        iax < 0
+        iax == -1
 #endif /* INADDR_NONE */
         ) {
         if (!quiet) {
@@ -10274,6 +10430,7 @@ http_open(hostname, svcname, use_ssl, rdns_name, rdns_len, agent)
 #else  /* HADDRLIST */
             bcopy(host->h_addr, (caddr_t)&r_addr.sin_addr, host->h_length);
 #endif /* HADDRLIST */
+#ifdef COMMENT
 #ifndef EXCELAN
             debug(F111,"BCOPY","host->h_addr",host->h_addr);
 #endif /* EXCELAN */
@@ -10281,6 +10438,7 @@ http_open(hostname, svcname, use_ssl, rdns_name, rdns_len, agent)
                   (caddr_t)&r_addr.sin_addr);
             debug(F111,"BCOPY"," r_addr.sin_addr.s_addr",
                   r_addr.sin_addr.s_addr);
+#endif /* COMMENT */
             debug(F111,"BCOPY","host->h_length",host->h_length);
         }
     }
@@ -10724,6 +10882,11 @@ http_close()
     int x = 0;
     debug(F101,"http_close","",httpfd);
 
+#ifdef HTTP_BUFFERING
+    http_count = 0;
+    http_bufp = 0;
+#endif /* HTTP_BUFFERING */
+
     if (httpfd == -1)                    /* Was open? */
       return(0);                        /* Wasn't. */
 
@@ -10772,7 +10935,7 @@ http_tol(s,n) CHAR *s; int n; {
     }
     debug(F101,"http_tol TCPIPLIB ttnet","",ttnet);
 #ifdef COMMENT
-    hexdump("http_tol",s,n);
+    ckhexdump("http_tol",s,n);
 #endif /* COMMENT */
 
 #ifdef CK_SSL
@@ -10943,12 +11106,15 @@ http_tol(s,n) CHAR *s; int n; {
     }
 }
 
-
 int
 http_inc(timo) int timo; {
     int x=-1; unsigned char c;             /* The locals. */
 
     if (httpfd == -1) {
+#ifdef HTTP_BUFFERING
+       http_count = 0;
+       http_bufp = 0;
+#endif /* HTTP_BUFFERING */
         debug(F100,"http_inc socket is closed","",0);
         return(-2);
     }
@@ -11066,6 +11232,13 @@ http_inc(timo) int timo; {
         }
     }
 #endif /* CK_SSL */
+
+#ifdef HTTP_BUFFERING
+    /* Skip all the select() stuff if we have bytes buffered locally */
+    if (http_count > 0)
+      goto getfrombuffer;
+#endif /* HTTP_BUFFERING */
+
     {
 #ifdef BSDSELECT
         fd_set rfds;
@@ -11096,6 +11269,10 @@ http_inc(timo) int timo; {
                 int s_errno = socket_errno;
                 debug(F111,"http_inc","select",rc);
                 debug(F111,"http_inc","socket_errno",s_errno);
+#ifdef HTTP_BUFFERING
+               http_count = 0;
+               http_bufp = 0;
+#endif /* HTTP_BUFFERING */
                 if (s_errno)
                     return(-1);
             }
@@ -11113,6 +11290,10 @@ http_inc(timo) int timo; {
                 if (!timo) {
 #ifdef TCPIPLIB
                     if ((rc = socket_write(httpfd,"",0)) < 0) {
+#ifdef HTTP_BUFFERING
+                       http_count = 0;
+                       http_bufp = 0;
+#endif /* HTTP_BUFFERING */
                         int s_errno = socket_errno;
                         debug(F101,"http_inc socket_write error","",s_errno);
 #ifdef OS2
@@ -11123,6 +11304,10 @@ http_inc(timo) int timo; {
                     }
 #else /* TCPIPLIB */
                     if ((rc = write(httpfd,"",0)) < 0) {
+#ifdef HTTP_BUFFERING
+                       http_count = 0;
+                       http_bufp = 0;
+#endif /* HTTP_BUFFERING */
                         debug(F101,"http_inc socket_write error","",errno);
                         return(-1); /* Call it an i/o error */
                     }
@@ -11158,6 +11343,10 @@ http_inc(timo) int timo; {
     }
 
     if (timo && x < 0) {        /* select() timed out */
+#ifdef HTTP_BUFFERING
+       http_count = 0;
+       http_bufp = 0;
+#endif /* HTTP_BUFFERING */
         debug(F100,"http_inc select() timed out","",0);
         return(-1); /* Call it an i/o error */
     }
@@ -11257,11 +11446,48 @@ http_inc(timo) int timo; {
             }
         }
 #endif /* CK_SSL */
+
+#ifdef HTTP_BUFFERING
+/*
+  Buffering code added by fdc 15 Dec 2005 for non-SSL case only because HTTP
+  GETs were orders of magnitude too slow due to the single-byte read()s.  The
+  file-descriptor swapping is pretty gross, but the more elegant solution
+  (calling a nettchk() like routine with the fd as a parameter) doesn't work,
+  because nettchk() relies on too many other routines that, like itself, are
+  hardwired for ttyfd.
+*/
+  getfrombuffer:
+       if (--http_count >= 0) {
+           c = http_inbuf[http_bufp++];
+           x = 1;
+       } else {
+           int savefd;
+           savefd = ttyfd;
+           ttyfd = httpfd;
+           x = nettchk();
+           ttyfd = savefd;             
+           debug(F101,"http_inc nettchk","",x);
+           if (x > HTTP_INBUFLEN)
+             x = HTTP_INBUFLEN;
+#ifdef TCPIPLIB
+           x = socket_read(httpfd,http_inbuf,x);
+#else  /* Not TCPIPLIB */
+           x = read(httpfd,http_inbuf,x);
+#endif /* TCPIPLIB */
+           http_count = 0;
+           http_bufp = 0;
+           if (x > 0) {
+               c = http_inbuf[http_bufp++];
+               http_count = x - 1;
+           }
+       }
+#else  /* Not HTTP_BUFFERING */
 #ifdef TCPIPLIB
         x = socket_read(httpfd,&c,1);
-#else
+#else  /* Not TCPIPLIB */
         x = read(httpfd,&c,1);
-#endif
+#endif /* TCPIPLIB */
+#endif /* HTTP_BUFFERING */
 
         if (x <= 0) {
             int s_errno = socket_errno;
@@ -11492,6 +11718,7 @@ http_get(agent, hdrlist, user, pwd, array, local, remote, stdio)
             } else if (!ckstrcmp(buf,"Transfer-Encoding:",18,0)) {
                 if ( ckindex("chunked",buf,18,0,0) != 0 )
                     chunked = 1;
+               debug(F101,"http_get chunked","",chunked);
             }
             i = 0;
         } else {
@@ -11955,6 +12182,7 @@ http_index(agent, hdrlist, user, pwd, array, local, remote, stdio)
                 } else if (!ckstrcmp(buf,"Transfer-Encoding:",18,0)) {
                     if ( ckindex("chunked",buf,18,0,0) != 0 )
                         chunked = 1;
+                   debug(F101,"http_index chunked","",chunked);
                 }
                 printf("%s\n",buf);
             }
@@ -12139,7 +12367,7 @@ http_put(agent, hdrlist, mime, user, pwd, array, local, remote, dest, stdio)
 #ifdef CMDATE2TM
     ckstrncat(request,http_now(),len);
 #else
-    strcat(request,...);
+    ckstrncat(request,...,len);
 #endif /* CMDATE2TM */
     ckstrncat(request,"\r\n",len);
     ckstrncat(request,"Host: ", len);
@@ -12259,6 +12487,7 @@ http_put(agent, hdrlist, mime, user, pwd, array, local, remote, dest, stdio)
                     } else if (!ckstrcmp(buf,"Transfer-Encoding:",18,0)) {
                         if ( ckindex("chunked",buf,18,0,0) != 0 )
                             chunked = 1;
+                       debug(F101,"http_put chunked","",chunked);
                     }
                     if ( stdio )
                         printf("%s\n",buf);
@@ -12432,7 +12661,7 @@ http_delete(agent, hdrlist, user, pwd, array, remote)
 #ifdef CMDATE2TM
     ckstrncat(request,http_now(),len);
 #else
-    strcat(request,...);
+    ckstrncat(request,...,len);
 #endif /* CMDATE2TM */
     ckstrncat(request,"\r\n",len);
     ckstrncat(request,"Host: ", len);
@@ -12515,6 +12744,7 @@ http_delete(agent, hdrlist, user, pwd, array, remote)
                 } else if (!ckstrcmp(buf,"Transfer-Encoding:",18,0)) {
                     if ( ckindex("chunked",buf,18,0,0) != 0 )
                         chunked = 1;
+                   debug(F101,"http_delete chunked","",chunked);
                 }
                 printf("%s\n",buf);
             }
@@ -12705,7 +12935,13 @@ http_post(agent, hdrlist, mime, user, pwd, array, local, remote, dest,
     sprintf(buf,"Content-length: %d\r\n",filelen); /* safe */
     ckstrncat(request,buf,len);
     ckstrncat(request,"\r\n",len);
+#ifdef COMMENT
+    /* This is apparently a mistake - the previous ckstrncat() already  */
+    /* appended a blank line to the request.  There should only be one. */
+    /* Servers are not required by RFC 2616 to ignore extraneous empty  */
+    /* lines.  -fdc, 28 Aug 2005. */
     ckstrncat(request,"\r\n",len);
+#endif /* COMMENT */
 
     /* Now we have the contents of the file */
   postopen:
@@ -12780,6 +13016,7 @@ http_post(agent, hdrlist, mime, user, pwd, array, local, remote, dest,
                     } else if (!ckstrcmp(buf,"Transfer-Encoding:",18,0)) {
                         if ( ckindex("chunked",buf,18,0,0) != 0 )
                             chunked = 1;
+                       debug(F101,"http_post chunked","",chunked);
                     }
                     if (stdio)
                         printf("%s\n",buf);
@@ -12899,7 +13136,6 @@ http_connect(socket, agent, hdrlist, user, pwd, array, host_port)
     char b64out[256];
     char * headers[HTTPHEADCNT];
     int    connected = 0;
-    int    chunked = 0;
 
     tcp_http_proxy_errno = 0;
 
@@ -13599,11 +13835,11 @@ fwdx_open_client_channel(channel) int channel; {
 
     env = getenv("DISPLAY");
     if ( !env )
-        env = tn_get_display();
+      env = (char *)tn_get_display();
     if ( env )
-        ckstrncpy(buf,env,256);
+      ckstrncpy(buf,env,256);
     else
-        ckstrncpy(buf,"127.0.0.1:0.0",256);
+      ckstrncpy(buf,"127.0.0.1:0.0",256);
 
     bzero((char *)&saddr,sizeof(saddr));
     saddr.sin_family = AF_INET;
@@ -13741,11 +13977,11 @@ fwdx_server_avail() {
 
     env = getenv("DISPLAY");
     if ( !env )
-        env = tn_get_display();
+      env = (char *)tn_get_display();
     if ( env )
-        ckstrncpy(buf,env,256);
+      ckstrncpy(buf,env,256);
     else
-        ckstrncpy(buf,"127.0.0.1:0.0",256);
+      ckstrncpy(buf,"127.0.0.1:0.0",256);
 
     bzero((char *)&saddr,sizeof(saddr));
     saddr.sin_family = AF_INET;
@@ -14071,7 +14307,7 @@ fwdx_write_data_to_channel(channel, data, len)
 
     sock = TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].fd;
     debug(F111,"fwdx_write_data_to_channel","socket",sock);
-    hexdump("fwdx_write_data_to_channel",data,len);
+    ckhexdump("fwdx_write_data_to_channel",data,len);
 
   fwdx_write_data_to_channel_retry:
 
index c8d5576..edb390e 100644 (file)
--- a/ckcnet.h
+++ b/ckcnet.h
@@ -4,7 +4,7 @@
   Author: Frank da Cruz <fdc@columbia.edu>
   Columbia University Academic Information Systems, New York City.
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2009,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -80,6 +80,9 @@
 #define NP_K5U2U       18               /* TCP/IP Kerberos 5 User to User */
 #define NP_CTERM       19               /* DEC CTERM */
 #define NP_LAT         20               /* DEC LAT */
+#define NP_SSL_RAW     21              /* SSL with no Telnet permitted */
+#define NP_TLS_RAW     22              /* TLS with no Telnet permitted */
+
 /* others here... */
 
 #ifdef CK_SSL
@@ -191,11 +194,17 @@ _PROTOTYP( int netopen, (char *, int *, int) );
 _PROTOTYP( int netclos, (void) );
 _PROTOTYP( int netflui, (void) );
 _PROTOTYP( int nettchk, (void) );
+_PROTOTYP( int netxchk, (int) );
 _PROTOTYP( int netbreak, (void) );
 _PROTOTYP( int netinc, (int) );
 _PROTOTYP( int netxin, (int, CHAR *) );
 _PROTOTYP( int nettol, (CHAR *, int) );
 _PROTOTYP( int nettoc, (CHAR) );
+#ifdef TCPSOCKET
+_PROTOTYP( int gettcpport, (void) );
+_PROTOTYP( int gettcpport, (void) );
+#endif /* TCPSOCKET */
+
 /*
   SunLink X.25 support by Marcello Frutig, Catholic University,
   Rio de Janeiro, Brazil, 1990.
@@ -734,6 +743,16 @@ _PROTOTYP( int x25local_nua, (char *) ); /* find local NUA */
 #endif /* bcopy */
 #endif /* VMS */
 
+#ifdef HPUX6
+/* These are missing in HP-UX 6.xx */
+#ifndef bzero
+#define bzero(s,n) memset(s,0,n)
+#endif /* bzero */
+#ifndef bcopy
+#define bcopy(h,a,l) memcpy(a,h,l)
+#endif /* bcopy */
+#endif /* HPUX6 */
+
 #ifdef UNIX                             /* UNIX section */
 
 #ifdef SVR4
@@ -980,6 +999,9 @@ typedef unsigned int u_int;
 #endif /* IF_DOT_H */
 
 #include <in.h>
+#ifdef VMS
+#include <inet.h>                      /* (SMS 2007/02/15) */
+#endif /* VMS */
 #include <netdb.h>
 #include <socket.h>
 #include "ckvioc.h"
@@ -1366,8 +1388,27 @@ extern char * tcp_http_proxy_pwd;       /* Password of user */
 
 /* Type needed as 5th argument (length) to get/setsockopt() */
 
+#ifdef TRU64
+/* They say it themselves - this does not conform to standards */
+#define socklen_t int
+#else
+#ifdef HPUX
+#define socklen_t int
+#endif /* HPUX */
+#endif /* TRU64 */
+
+#ifndef SOCKOPT_T
+#ifdef CK_64BIT
+#define SOCKOPT_T socklen_t
+#endif /* CK_64BIT */
+#endif /* SOCKOPT_T */
+
 #ifndef SOCKOPT_T
 #define SOCKOPT_T int
+#ifdef MACOSX10
+#undef SOCKOPT_T
+#define SOCKOPT_T unsigned int
+#else
 #ifdef AIX42
 #undef SOCKOPT_T
 #define SOCKOPT_T unsigned long
@@ -1396,12 +1437,23 @@ extern char * tcp_http_proxy_pwd;       /* Password of user */
 #endif /* NT */
 #endif /* PTX */
 #endif /* AIX42 */
+#endif /* MACOSX10 */
 #endif /* SOCKOPT_T */
 
 /* Ditto for getsockname() */
 
 #ifndef GSOCKNAME_T
+#ifdef CK_64BIT
+#define GSOCKNAME_T socklen_t
+#endif /* CK_64BIT */
+#endif /* GSOCKNAME_T */
+
+#ifndef GSOCKNAME_T
 #define GSOCKNAME_T int
+#ifdef MACOSX10
+#undef GSOCKNAME_T
+#define GSOCKNAME_T unsigned int
+#else
 #ifdef PTX
 #undef GSOCKNAME_T
 #define GSOCKNAME_T size_t
@@ -1425,6 +1477,7 @@ extern char * tcp_http_proxy_pwd;       /* Password of user */
 #endif /* UNIXWARE */
 #endif /* AIX41 */
 #endif /* PTX */
+#endif /* MACOSX10 */
 #endif /* GSOCKNAME_T */
 
 #endif /* TCPSOCKET */
diff --git a/ckcplm.txt b/ckcplm.txt
deleted file mode 100644 (file)
index 9c2f44f..0000000
+++ /dev/null
@@ -1,3076 +0,0 @@
-
-                         C-Kermit Program Logic Manual
-
-     Frank da Cruz
-     [1]The Kermit Project
-     [2]Columbia University
-
-   As of: C-Kermit 8.0.211, 10 April 2004
-   This page last updated: Sat Apr 10 16:45:30 2004 (New York USA Time)
-
-     IF YOU ARE READING A PLAIN-TEXT version of this document, note that
-     this file is a plain-text dump of a Web page. You can visit the
-     original (and possibly more up-to-date) Web page here:
-
-  [3]http://www.columbia.edu/kermit/ckcplm.html
-
-   [ [4]C-Kermit Home ] [ [5]Kermit Home ]
-    ________________________________________________________________________
-
-  CONTENTS
-
-  1. [6]INTRODUCTION
-  2. [7]FILES
-  3. [8]SOURCE CODE PORTABILITY AND STYLE
-  4. [9]MODULES
-     4.A. [10]Group A: Library Routines
-     4.B. [11]Group B: Kermit File Transfer
-     4.C. [12]Group C: Character-Set Conversion
-     4.D. [13]Group D: User Interface
-     4.E. [14]Group E: Platform-Dependent I/O
-     4.F. [15]Group F: Network Support
-     4.G. [16]Group G: Formatted Screen Support
-     4.H. [17]Group H: Pseudoterminal Support
-     4.I. [18]Group I: Security
-  I. [19]APPENDIX I: FILE PERMISSIONS
-    ________________________________________________________________________
-
-  1. INTRODUCTION
-
-   The Kermit Protocol is specified in the book Kermit, A File Transfer
-   Protocol by Frank da Cruz, Digital Press / Butterworth Heinemann,
-   Newton, MA, USA (1987), 379 pages, ISBN 0-932376-88-6. It is assumed
-   the reader is familiar with the Kermit protocol specification.
-
-   This file describes the relationship among the modules and functions
-   of C-Kermit 5A and later, and other programming considerations.
-   C-Kermit is designed to be portable to any kind of computer that has a
-   C compiler. The source code is broken into many files that are grouped
-   according to their function, as shown in the [20]Contents.
-
-   C-Kermit has seen constant development since 1985. Throughout its
-   history, there has been a neverending tug-of-war among:
-
-    a. Functionality: adding new features, fixing bugs, improving
-       performance.
-    b. Adding support for new platforms.
-    c. "Buzzword 1.0 compliance".
-
-   The latter category is the most frustrating, since it generally
-   involves massive changes just to keep the software doing what it did
-   before in some new setting: e.g. the K&R-to-ANSIC conversion (which
-   had to be done, of course, without breaking K&R); Y2K (not a big deal
-   in our case); the many and varied UNIX and other API "standards";
-   IPv6.
-
-   [ [21]Contents ] [ [22]C-Kermit ] [ [23]Kermit Home ]
-    ________________________________________________________________________
-
-  2. FILES
-
-   C-Kermit source files begin with the two letters "ck", for example
-   ckutio.c. Filenames are kept short (6.3) for maximum portability and
-   (obviously I hope) do not contain spaces or more than one period. The
-   third character in the name denotes something about the function group
-   and the expected level of portability:
-
-     a     General descriptive material and documentation (text)
-     b     BOO file encoders and decoders (obsolete)
-     c     All platforms with C compilers (*)
-     d     Data General AOS/VS
-     e     Reserved for "ckermit" files, like ckermit.ini, ckermit2.txt
-     f     (reserved)
-     g     (reserved)
-     h     (reserved)
-     i     Commodore Amiga (Intuition)
-     j     (unused)
-     k     (unused)
-     l     Stratus VOS
-     m     Macintosh with Mac OS 1-9
-     n     Microsoft Windows NT/2000/XP
-     o     OS/2 and/or Microsoft Windows 9x/ME/NT/2000/XP
-     p     Plan 9 from Bell Labs
-     q     (reserved)
-     r     DEC PDP-11 with RSTS/E (never used, open for reassigment)
-     s     Atari ST GEMDOS (last supported in version 5A(189))
-     t     DEC PDP-11 with RT-11 (never used, open for reassigment)
-     u     Unix-based operating systems (*)
-     v     VMS and OpenVMS
-     w     Wart (Lex-like preprocessor, platform independent)
-     x     (reserved)
-     y     (reserved)
-     z     (reserved)
-     0-3   (reserved)
-     4     IBM AS/400
-     5-8   (reserved)
-     9     Microware OS-9
-     _     Encryption modules
-
-   (*) In fact there is little distinction between the ckc*.* and cku*.*
-   categories. It would make more sense for all cku*.* modules to be
-   ckc*.* ones, except ckufio.c, ckutio.c, ckucon.c, ckucns.c, and
-   ckupty.c, which truly are specific to Unix. The rest (ckuus*.c,
-   ckucmd.c, etc) are quite portable.
-
-   One hint before proceeding: functions are scattered all over the
-   ckc*.c and cku*.c modules, where function size has begun to take
-   precedence over the desirability of grouping related functions
-   together, the aim being to keep any particular module from growing
-   disproportionately large. The easiest way (in UNIX) to find out in
-   what source file a given function is defined is like this (where the
-   desired function is foo()...):
-
-  grep ^foo\( ck*.c
-
-   This works because the coding convention has been to make function
-   names always start on the left margin with their contents indented,
-   for example:
-
-static char *
-foo(x,y) int x, y; {
-    ...
-}
-
-   Also note the style for bracket placement. This allows
-   bracket-matching text editors (such as EMACS) to help you make sure
-   you know which opening bracket a closing bracket matches, particularly
-   when the opening bracket is above the visible screen, and it also
-   makes it easy to find the end of a function (search for '}' on the
-   left margin).
-
-   Of course EMACS tags work nicely with this format too:
-
-  $ cd kermit-source-directory
-  $ etags ck[cu]*.c
-  $ emacs
-  Esc-X Visit-Tags-Table<CR><CR>
-
-   (but remember that the source file for ckcpro.c is [24]ckcpro.w!)
-
-   Also:
-
-     * Tabs should be set every 8 spaces, as on a VT100.
-     * All lines must no more than 79 characters wide after tab
-       expansion.
-     * Note the distinction between physical tabs (ASCII 9) and the
-       indentation conventions, which are: 4 for block contents, 2 for
-       most other stuff (obviously this is not a portability issue, just
-       style).
-
-   [ [25]Contents ] [ [26]C-Kermit ] [ [27]Kermit Home ]
-    ________________________________________________________________________
-
-  3. SOURCE CODE PORTABILITY AND STYLE
-
-   C-Kermit was designed in 1985 as a platform-independent replacement
-   for the earlier Unix Kermit. c-Kermit's design was expected to promote
-   portability, and judging from the number of platforms to which it has
-   been adapted since then, the model is effective, if not ideal
-   (obviously if we had it all to do over, we'd change a few things). To
-   answer the oft-repeated question: "Why are there so many #ifdefs?",
-   it's because:
-
-     * Many of them are related to feature selection and program size,
-       and so need to be there anyway.
-     * Those that treat compiler, library, platform, header-file, and
-       similar differences have built up over time as hundreds of people
-       all over the world adapted C-Kermit to their particular
-       environments and sent back their changes. There might be more
-       politically-correct ways to achieve portability, but this one is
-       natural and proven. The basic idea is to introduce changes that
-       can be selected by defining a symbol, which, if not defined,
-       leaves the program exactly as it was before the changes.
-     * Although it might be possible to "clean up" the "#ifdef mess",
-       nobody has access to all the hundreds of platforms served by the
-       #ifdefs to check the results.
-
-   And to answer the second-most-oft-repeated question: "Why don't you
-   just use GNU autoconfig / automake / autowhatever instead of
-   hard-coding all those #ifdefs?" Answers:
-
-     * The GNU tools are not available on all the platforms where
-       C-Kermit must be built and I wouldn't necessarily trust them if
-       they were.
-     * Each platform is a moving target, so the tools themselves would
-       need to updated before Kermit could be updated.
-     * It would only add another layer of complexity to an already
-       complex process.
-     * Conversion at this point would not be practical unless there was a
-       way to test the results on all the hundreds of platforms where
-       C-Kermit is supposed to build.
-
-   When writing code for the system-indendent C-Kermit modules, please
-   stick to the following coding conventions to ensure portability to the
-   widest possible variety of C preprocessors, compilers, and linkers, as
-   well as certain network and/or email transports. The same holds true
-   for many of the "system dependent" modules too; particularly the Unix
-   ones, since they must be buildable by a wide variety of compilers and
-   linkers, new and old.
-
-   This list does not purport to be comprehensive, and although some
-   items on it might seem far-fetched, they would not be listed unless I
-   had encountered them somewhere, some time. I wish I had kept better
-   records so I could cite specific platforms and compilers.
-
-     * Try to keep variable and function names unique within 6
-       characters, especially if they are used across modules, since 6 is
-       the maximum for some old linkers (actually, this goes back to
-       TOPS-10 and -20 and other old DEC OS's where C-Kermit never ran
-       anyway; a more realistic maximum is probably somewhere between 8
-       and 16). We know for certain that VAX C has a 31-character max
-       because it complains -- others might not complain, but just
-       silently truncate, thus folding two or more routines/variables
-       into one.
-     * Keep preprocessor symbols unique within 8 characters; that's the
-       max for some preprocessors (sorry, I can't give a specific
-       example, but in 1988 or thereabouts, I had to change character-set
-       symbols like TC_LATIN1 and TC_LATIN2 to TC_1LATIN and TC_2LATIN
-       because the digits were being truncated and ignored on a platform
-       where I actually had to build C-Kermit 5A; unfortunately I didn't
-       note which platform -- maybe some early Ultrix version?)
-     * Don't create preprocessor symbols, or variable or function names,
-       that start with underscore (_). These are usually reserved for
-       internal use by the compiler and header files.
-     * Don't put #include directives inside functions or { blocks }.
-     * Don't use the #if or #elif preprocessor constructions, only use
-       #ifdef, #ifndef, #define, #undef, and #endif.
-     * Put tokens after #endif in comment brackets, e.g.
-       #endif /* FOO */.
-     * Don't indent preprocessor statements - # must always be first char
-       on line.
-     * Don't put whitespace after # in preprocessor statements.
-     * Don't use #pragma, even within #ifdefs -- it makes some
-       preprocessors give up.
-     * Same goes for #module, #if, etc - #ifdefs do NOT protect them.
-     * Don't use logical operators in preprocessor constructions.
-     * Avoid #ifdefs inside argument list to function calls (I can't
-       remember why this one is here, but probably needn't be; we do this
-       all the time).
-     * Always cast strlen() in expressions to int:
-       if ((int)strlen(foo) < x)...
-     * Any variable whose value might exceed 16383 should be declared as
-       long, or if that is not possible, then as unsigned.
-     * Avoid typedefs; they might be portable but they are very confusing
-       and there's no way to test for their presence or absence at
-       compile time. Use preprocessor symbols instead if possible; at
-       least you can test their definitions.
-     * Unsigned long is not portable; use a preprocessor symbol (Kermit
-       uses ULONG for this).
-     * Long long is not portable. If you really need it, be creative.
-     * Similarly 1234LL is not portable, nor almost any other constant
-       modifier other than L.
-     * Unsigned char is not portable, use CHAR (a preprocessor symbol
-       defined in the Kermit header files) and always take precautions
-       against character signage (more about this [28]below).
-     * Don't use initializers with automatic arrays or structs: it's not
-       portable.
-     * Don't use big automatic arrays or structs in functions that might
-       be called recursively; some platforms have fixed-size stacks (e.g.
-       Windows 9x: 256K) and recursive functions crash with stack
-       overflow. Even when there is not a compiler limitation, this
-       causes memory to be consumed without bound, and can end up filling
-       swap space.
-     * Don't assume that struct assignment performs a copy, or that it
-       even exists.
-     * Don't use sizeof to get the size of an array; someone might come
-       along later and and change it from static to malloc'd. Always use
-       a symbol to refer to the array's size.
-     * Don't put prototypes for static functions into header files that
-       are used by modules that don't contain that function; the link
-       step can fail with unresolved references (e.g. on AOS/VS).
-     * Avoid the construction *++p (the order of evaluation varies; it
-       shouldn't but at least one compiler had a bug that made me include
-       this item).
-     * Don't use triple assignments, like a = b = c = 0; (or quadruple,
-       etc). Some compilers generate bad code for these, or crash, etc
-       (some version of DEC C as I recall).
-     * Some compilers don't allow structure members to have the same
-       names as other identifiers. Try to give structure members unique
-       names.
-     * Don't assume anything about order of evaluation in boolean
-       expressions, or that they will stop early if a required condition
-       is not true, e.g.:
-  if (i > 0 && p[i-1] == blah)
-       can still dump core if i == 0 (hopefully this is not true of any
-       modern compiler, but I would not have said this if it did not
-       actually happen somewhere).
-     * Don't have a switch() statement with no cases (e.g. because of
-       #ifdefs); this is a fatal error in some compilers.
-     * Don't put lots of code in a switch case; move it out to a separate
-       function; some compilers run out of memory when presented with a
-       huge switch() statement -- it's not the number of cases that
-       matters; it's the overall amount of code.
-     * Some compilers might also limit the number of switch() cases, e.g.
-       to 254.
-     * Don't put anything between "switch() {" and "case:" -- switch
-       blocks are not like other blocks.
-     * Don't jump into or out of switches.
-     * Don't make character-string constants longer than about 250 bytes.
-       Longer strings should be broken up into arrays of strings.
-     * Don't write into character-string constants (obviously). Even when
-       you know you are not writing past the end; the compiler or linker
-       might have put them into read-only and/or shared memory, and/or
-       coalesced multiple equal constants so if you change one you change
-       them all.
-     * Don't depend on '\r' being carriage return.
-     * Don't depend on '\n' being linefeed or for that matter any SINGLE
-       character.
-     * Don't depend on '\r' and '\n' being different (e.g. as separate
-       switch() cases).
-     * In other words, don't use \n or \r to stand for specific
-       characters; use \012 and \015 instead.
-     * Don't code for "buzzword 1.0 compliance", unless "buzzword" is K&R
-       and "1.0" is the first edition.
-     * Don't use or depend on anything_t (size_t, pid_t, etc), except
-       time_t, without #ifdef protection (time_t is the only one I've
-       found that is accepted everywhere). This is a tough one because
-       the same function might require (say) a size_t arg on one
-       platform, whereas size_t is unheard of on another; or worse, it
-       might require a totally different data type, like int or long or
-       some other typedef'd thing. It has often proved necessary to
-       define a symbol to stand for the type of a particular argument to
-       a particular library or system function to get around this
-       problem.
-     * Don't use or depend on internationalization ("i18n") features,
-       wchar_t, locales, etc, in portable code; they are not portable.
-       Anyway, locales are not the right model for Kermit's
-       multi-character-set support. Kermit does all character-set
-       conversion itself and does not use any external libraries or
-       functions.
-     * In particular, don't use any library functions that deal with wide
-       characters or Unicode in any form. These are not only nonportable,
-       but a constantly shifting target (e.g. the ones in glibc).
-     * Don't make any assumption about signal handler type. It can be
-       void, int, long, or anything else. Always declare signal handlers
-       as SIGTYP (see definition in ckcdeb.h and augment it if necessary)
-       and always use SIGRETURN at exit points from signal handlers.
-     * Signals should always be re-armed to be used again (this barely
-       scratches the surface -- the differences between BSD/V7 and System
-       V and POSIX signal handling are numerous, and some platforms do
-       not even support signals, alarms, or longjmps correctly or at all
-       -- avoid all of this if you can).
-     * On the other hand, don't assume that signals are disarmed after
-       being raised. In some platforms you have to re-arm them, in others
-       they stay armed.
-     * Don't call malloc() and friends from a signal handler; don't do
-       anything but setting integer global variables in a signal handler.
-     * malloc() does not initialize allocated memory -- it never said it
-       did. Don't expect it to be all 0's.
-     * Did You Know: malloc() can succeed and the program can still dump
-       core later when it attempts to use the malloc'd memory? (This
-       happens when allocation is deferred until use and swap space is
-       full.)
-     * memset(), memmove(), and memcpy() are not portable, don't use them
-       without protecting them in ifdefs (we have USE_MEMCPY for this).
-       bzero()/bcopy() too, except we're guaranteed to have
-       bzero()/bcopy() when using the sockets library (not really). See
-       examples in the source.
-     * Don't assume that strncpy() stops on the first null byte -- most
-       versions always copy the number of bytes given in arg 3, padding
-       out with 0's and overwriting whatever was there before. Use
-       C-Kermit ckstrncpy() if you want predictable non-padding behavior,
-       guaranteed NUL-termination, and a useful return code.
-     * DID YOU KNOW.. that some versions of inet_blah() routines return
-       IP addresses in network byte order, while others return them local
-       machine byte order? So passing them to ntohs() or whatever is not
-       always the right thing to do.
-     * Don't use ANSI-format function declarations without #ifdef
-       CK_ANSIC, and always provide an #else for the non-ANSI case.
-     * Use the Kermit _PROTOTYP() macro for declaring function
-       prototypes; it works in both the ANSI and non-ANSI cases.
-     * Don't depend on any other ANSI preprocessor features like
-       "pasting" -- they are often missing or nonoperational.
-     * Don't assume any C++ syntax or semantics.
-     * Don't use // as a comment introducer. C is not C++.
-     * Don't declare a string as "char foo[]" in one module and "extern
-       char * foo" in another, or vice-versa: this causes core dumps.
-     * With compiler makers falling all over themselves trying to outdo
-       each other in ANSI strictness, it has become increasingly
-       necessary to cast EVERYTHING. This is increasingly true for char
-       vs unsigned char. We need to use unsigned chars if we want to deal
-       with 8-bit character sets, but most character- and string-oriented
-       APIs want (signed) char arguments, so explicit casts are
-       necessary. It would be nice if every compiler had a
-       -funsigned-char option (as gcc does), but they don't.
-     * a[x], where x is an unsigned char, can produce a wild memory
-       reference if x, when promoted to an int, becomes negative. Cast it
-       to (unsigned), even though it ALREADY IS unsigned.
-     * Be careful how you declare functions that have char or long
-       arguments; for ANSI compilers you MUST use ANSI declarations to
-       avoid promotion problems, but you can't use ANSI declarations with
-       non-ANSI compilers. Thus declarations of such functions must be
-       hideously entwined in #ifdefs. Example: latter:
-  int                          /*  Put character in server command buffer  */
-  #ifdef CK_ANSIC
-  putsrv(char c)
-  #else
-  putsrv(c) char c;
-  #endif /* CK_ANSIC */
-  /* putsrv */ {
-      *srvptr++ = c;
-      *srvptr = '\0';           /* Make sure buffer is null-terminated */
-      return(0);
-  }
-     * Be careful how you return characters from functions that return
-       int values -- "getc-like functions" -- in the ANSI world. Unless
-       you explicitly cast the return value to (unsigned), it is likely
-       to be "promoted" to an int and have its sign extended.
-     * At least one compiler (the one on DEC OSF/1 1.3) treats "/*" and
-       "*/" within string constants as comment begin and end. No amount
-       of #ifdefs will get around this one. You simply can't put these
-       sequences in a string constant, e.g. "/usr/local/doc/*.*".
-     * Avoid putting multiple macro references on a single line, e.g.:
-  putchar(BS); putchar(SP); putchar(BS)
-
-   This overflows the CPP output buffer of more than a few C
-   preprocessors (this happened, for example, with SunOS 4.1 cc, which
-   evidently has a 1K macro expansion buffer).
-
-   C-Kermit needs constant adjustment to new OS and compiler releases.
-   Every new OS release shuffles header files or their contents, or
-   prototypes, or data types, or levels of ANSI strictness, etc. Every
-   time you make an adjustment to remove a new compilation error, BE VERY
-   CAREFUL to #ifdef it on a symbol unique to the new configuration so
-   that the previous configuration (and all other configurations on all
-   other platforms) remain as before.
-
-   Assume nothing. Don't assume header files are where they are supposed
-   to be, that they contain what you think they contain, that they define
-   specific symbols to have certain values -- or define them at all!
-   Don't assume system header files protect themselves against multiple
-   inclusion. Don't assume that particular system or library calls are
-   available, or that the arguments are what you think they are -- order,
-   data type, passed by reference vs value, etc. Be conservative when
-   attempting to write portable code. Avoid all advanced features.
-
-   If you see something that does not make sense, don't assume it's a
-   mistake -- it might be there for a reason, and changing it or removing
-   is likely to cause compilation, linking, or runtime failures sometime,
-   somewhere. Some huge percentage of the code, especially in the
-   platform-dependent modules, is workarounds for compiler, linker, or
-   API bugs.
-
-   But finally... feel free to violate any or all of these rules in
-   platform-specific modules for environments in which the rules are
-   certain not to apply. For example, in VMS-specific code, it is OK to
-   use #if, because VAX C, DEC C, and VMS GCC all support it.
-
-   [ [29]Contents ] [ [30]C-Kermit ] [ [31]Kermit Home ]
-    ________________________________________________________________________
-
-  3.1. Memory Leaks
-
-   The C language and standard C library are notoriously inadequate and
-   unsafe. Strings are arrays of characters, usually referenced through
-   pointers. There is no native string datatype. Buffers are fixed size,
-   and C provides no runtime bounds checking, thus allowing overwriting
-   of other data or even program code. With the popularization of the
-   Internet, the "buffer exploit" has become a preferred method for
-   hackers to hijack privileged programs; long data strings are fed to a
-   program in hopes that it uses unsafe C library calls such as strcpy()
-   or sprintf() to copy strings into automatic arrays, thus overwriting
-   the call stack, and therefore the routine's return address. When such
-   a hole is discovered, a "string" can be constructed that contains
-   machine code to hijack the program's privileges and penetrate the
-   system.
-
-   This problem is partially addressed by the strn...() routines, which
-   should always be used in preference to their str...() equivalents
-   (except when the copy operation has already been prechecked, or there
-   is a good reason for not using them, e.g. the sometimes undesirable
-   side effect of strncpy() zeroing the remainder of the buffer). The
-   most gaping whole, however, is sprintf(), which performs no length
-   checking on its destination buffer, and is not easy to replace.
-   Although snprintf() routines are starting to appear, they are not yet
-   widespread, and certainly not universal, nor are they especially
-   portable, or even full-featured.
-
-   For these reasons, we have started to build up our own little library
-   of C Library replacements, ckclib.[ch]. These are safe and highly
-   portable primitives for memory management and string manipulation,
-   such as:
-
-   ckstrncpy()
-          Like strncpy but returns a useful value, doesn't zero buffer.
-
-   ckitoa()
-          Opposite of atoi()
-
-   ckltoa()
-          Opposite of atol()
-
-   ckctoa()
-          Returns character as string
-
-   ckmakmsg()
-          Used with ck?to?() as a safe sprintf() replacement for up to 4
-          items
-
-   ckmakxmsg()
-          Like ckmakmsg() but accepts up to 12 items
-
-   More about library functions in [32]Section 4.A.
-
-   [ [33]Contents ] [ [34]C-Kermit ] [ [35]Kermit Home ]
-    ________________________________________________________________________
-
-  3.2. The "char" vs "unsigned char" Dilemma
-
-   This is one of the most aggravating and vexing characteristics of the
-   C language. By design, chars (and char *'s) are SIGNED. But in the
-   modern era, however, we need to process characters that can have (or
-   include) 8-bit values, as in the ISO Latin-1, IBM CP 850, or UTF-8
-   character sets, so this data must be treated as unsigned. But some C
-   compilers (such as those based on the Bell UNIX V7 compiler) do not
-   support "unsigned char" as a data type. Therefore we have the macro or
-   typedef CHAR, which we use when we need chars to be unsigned, but
-   which, unfortunately, resolves itself to "char" on those compilers
-   that don't support "unsigned char". AND SO... We have to do a lot of
-   fiddling at runtime to avoid sign extension and so forth.
-
-   Some modern compilers (e.g. IBM, DEC, Microsoft) have options that say
-   "make all chars be unsigned" (e.g. GCC "-funsigned-char") and we use
-   them when they are available. Other compilers don't have this option,
-   and at the same time, are becoming increasingly strict about type
-   mismatches, and spew out torrents of warnings when we use a CHAR where
-   a char is expected, or vice versa. We fix these one by one using
-   casts, and the code becomes increasingly ugly. But there remains a
-   serious problem, namely that certain library and kernel functions have
-   arguments that are declared as signed chars (or pointers to them),
-   whereas our character data is unsigned. Fine, we can can use casts
-   here too -- but who knows what happens inside these routines.
-
-   [ [36]Contents ] [ [37]C-Kermit ] [ [38]Kermit Home ]
-    ________________________________________________________________________
-
-  4. MODULES
-
-   When C-Kermit is on the far end of a connection, it is said to be in
-   remote mode. When C-Kermit has made a connection to another computer,
-   it is in local mode. (If C-Kermit is "in the middle" of a multihop
-   connection, it is still in local mode.)
-
-   On another axis, C-Kermit can be in any of several major states:
-
-   Command State
-          Reading and writing from the job's controlling terminal or
-          "console". In this mode, all i/o is handled by the Group E
-          conxxx() (console i/o) routines.
-
-   Protocol State
-          Reading and writing from the communicatons device. In this
-          mode, all i/o is handled by the Group E ttxxx() (terminal i/o)
-          routines.
-
-   Terminal State
-          Reading from the keyboard with conxxx() routines and writing to
-          the communications device with ttxxx() routines AND vice-versa.
-
-   When in local mode, the console and communications device are
-   distinct. During file transfer, Kermit may put up a file-transfer
-   display on the console and sample the console for interruption
-   signals.
-
-   When in remote mode, the console and communications device are the
-   same, and therefore there can be no file-transfer display on the
-   console or interruptions from it (except for "in-band" interruptions
-   such as ^C^C^C).
-
-   [ [39]Contents ] [ [40]C-Kermit ] [ [41]Kermit Home ]
-    ________________________________________________________________________
-
-  4.A. Group A: Library Functions
-
-   Library functions, strictly portable, can be used by all modules on
-   all platforms: [42]ckclib.h, [43]ckclib.c.
-
-   (To be filled in... For now, see [44]Section 3.1 and the comments in
-   ckclib.c.)
-
-   [ [45]Contents ] [ [46]C-Kermit ] [ [47]Kermit Home ]
-    ________________________________________________________________________
-
-  4.B. Group B: Kermit File Transfer
-
-   The Kermit protocol kernel. These files, whose names start with "ckc
-   are supposed to be totally portable C, and are expected to compile
-   correctly on any platform with any C compiler. "Portable" does not
-   mean the same as as "ANSI" -- these modules must compile on 10- and
-   20-year old computers, with C preprocessors, compilers, and/or linkers
-   that have all sorts of restrictions. The Group B modules do not
-   include any header files other than those that come with Kermit
-   itself. They do not contain any library calls except from the standard
-   C library (e.g. printf()). They most certainly do not contain any
-   system calls. Files:
-
-   [48]ckcsym.h
-          For use by C compilers that don't allow -D on the command line.
-
-   [49]ckcasc.h
-          ASCII character symbol definitions.
-
-   [50]ckcsig.h
-          System-independent signal-handling definitions and prototypes.
-
-   [51]ckcdeb.h
-          Originally, debugging definitions. Now this file also contains
-          all definitions and prototypes that are shared by all modules
-          in all groups.
-
-   [52]ckcker.h
-          Kermit protocol symbol definitions.
-
-   [53]ckcxla.h
-          Character-set-related symbol definitions (see next section).
-
-   [54]ckcmai.c
-          The main program. This module contains the declarations of all
-          the protocol-related global variables that are shared among the
-          other modules.
-
-   [55]ckcpro.w
-          The protocol module itself, written in "wart", a lex-like
-          preprocessor that is distributed with Kermit under the name
-          CKWART.C.
-
-   [56]ckcfns.c, [57]ckcfn2.c, [58]ckcfn3.c
-          The protocol support functions used by the protocol module.
-
-   [59]Group B modules may call upon functions from [60]Group E, but not
-   from [61]Group D modules (with the single exception that the main
-   program invokes the user interface, which is in Group D). (This last
-   assertion is really only a conjecture.)
-
-   [ [62]Contents ] [ [63]C-Kermit ] [ [64]Kermit Home ]
-    ________________________________________________________________________
-
-  4.C. Group C: Character-Set Conversion
-
-   Character set translation tables and functions. Used by the [65]Group
-   B, protocol modules, but may be specific to different computers. (So
-   far, all character character sets supported by C-Kermit are supported
-   in [66]ckuxla.c and [67]ckuxla.h, including Macintosh and IBM
-   character sets). These modules should be completely portable, and not
-   rely on any kind of system or library services.
-
-   [68]ckcxla.h
-          Character-set definitions usable by all versions of C-Kermit.
-
-   ck?xla.h
-          Character-set definitions for computer "?", e.g. [69]ckuxla.h
-          for UNIX, [70]ckmxla.h for Macintosh.
-
-   [71]ck?xla
-          Character-set translation tables and functions for computer
-          "?", For example, CKUXLA.C for UNIX, CKMXLA.C for Macintosh. So
-          far, these are the only two such modules. The UNIX module is
-          used for all versions of C-Kermit except the Macintosh version.
-
-   [72]ckcuni.h
-          Unicode definitions
-
-   [73]ckcuni.c
-          Unicode module
-
-   Here's how to add a new file character set in the original
-   (non-Unicode modules). Assuming it is based on the Roman (Latin)
-   alphabet. Let's call it "Barbarian". First, in ck?xla.h, add a
-   definition for FC_BARBA (8 chars maximum length) and increase
-   MAXFCSETS by 1. Then, in ck?xla.c:
-
-     * Add a barbarian entry into the fcsinfo array.
-     * Add a "barbarian" entry to file character set keyword table,
-       fcstab.
-     * Add a "barbarian" entry to terminal character set keyword table,
-       ttcstab.
-     * Add a translation table from Latin-1 to barbarian: yl1ba[].
-     * Add a translation table from barbarian to Latin-1: ybal1[].
-     * Add a translation function from Barbarian to ASCII: xbaas().
-     * Add a translation function from Barbarian to Latin-1: xbal1().
-     * Add a translation function from Latin-1 to Barbarian: xl1ba().
-     * etc etc for each transfer character set...
-     * Add translation function pointers to the xls and xlr tables.
-
-   Other translations involving Barbarian (e.g. from Barbarian to
-   Latin-Cyrillic) are performed through these tables and functions. See
-   ckuxla.h and ckuxla.c for extensive examples.
-
-   To add a new Transfer Character Set, e.g. Latin Alphabet 9 (for the
-   Euro symbol), again in the "old" character-set modules:
-
-   In ckcxla.h:
-
-          + Add a TC_xxxx definition and increase MAXTCSETS accordingly.
-
-   In ck?xla.h (since any transfer charset is also a file charset):
-
-          + Add an FC_xxxx definition and increase MAXFCSETS accordingly.
-
-   In ck?xla.c:
-
-          + Add a tcsinfo[] entry.
-          + Make a tcstab[] keyword table entry.
-          + Make an fcsinfo[] table entry.
-          + Make an fcstab[] keyword table entry.
-          + Make a tcstab[] keyword table entry.
-          + If necessary, make a langinfo[] table entry.
-          + Make entries in the function pointer arrays.
-          + Provide any needed functions.
-
-   As of C-Kermit 7.0, character sets are also handled in parallel by the
-   new (and very large) Unicode module, ckcuni.[ch]. Eventually we should
-   phase out the old way, described just above, and operate entirely in
-   (and through) Unicode. The advantages are many. The disadvantages are
-   size and performance. To add a character to the Unicode modules:
-
-   In ckcuni.h:
-
-          + (To be filled in...)
-
-   In ckcuni.c:
-
-          + (To be filled in...)
-
-   [ [74]Contents ] [ [75]C-Kermit ] [ [76]Kermit Home ]
-    ________________________________________________________________________
-
-  4.D. Group D: User Interface
-
-   This is the code that communicates with the user, gets her commands,
-   informs her of the results. It may be command-line oriented,
-   interactive prompting dialog, menus and arrow keys, windows and mice,
-   speech recognition, telepathy, etc. The one provided is command-and
-   prompt, with the ability to read commands from various sources: the
-   console keyboard, a file, or a macro definition. The user interface
-   has three major functions:
-
-    1. Sets the parameters for the file transfer and then starts it. This
-       is done by setting certain (many) global variables, such as the
-       protocol machine start state, the file specification, file type,
-       communication parameters, packet length, window size, character
-       set, etc.
-    2. Displays messages on the user's screen during the file transfer,
-       using the screen() function, which is called by the group-1
-       modules.
-    3. Executes any commands directly that do not require Kermit
-       protocol, such as the CONNECT command, local file management
-       commands, parameter-setting commands, FTP client commands, etc.
-
-   If you plan to imbed the [77]Group B, files into a program with a
-   different user interface, your interface must supply an appropriate
-   screen() function, plus a couple related ones like chkint() and
-   intmsg() for handling keyboard (or mouse, etc) interruptions during
-   file transfer. The best way to find out about this is to link all the
-   C-Kermit modules together except the ckuu*.o and ckucon.o modules, and
-   see which missing symbols turn up.
-
-   C-Kermit's character-oriented user interface (as opposed to the
-   Macintosh version's graphical user interface) consists of the
-   following modules. C-Kermit can be built with an interactive command
-   parser, a command-line-option-only parser, a graphical user interface,
-   or any combination, and it can even be built with no user interface at
-   all (in which case it runs as a remote-mode Kermit server).
-
-   [78]ckucmd.h
-   [79]ckucmd.c
-          The command parsing primitives used by the interactive command
-          parser to parse keywords, numbers, filenames, etc, and to give
-          help, complete fields, supply defaults, allow abbreviations and
-          editing, etc. This package is totally independent of Kermit,
-          but does depend on the [80]Group E functions.
-
-   [81]ckuusr.h
-          Definitions of symbols used in Kermit's commands.
-
-   ckuus*.c
-          Kermit's interactive command parser, including the script
-          programming language: [82]ckuusr.c (includes top-level keyword
-          tables); [83]ckuus2.c (HELP command text); [84]ckuus3.c (most
-          of the SET command); [85]ckuus4.c (includes variables and
-          functions); ckuus[567].c (miscellaneous);
-
-   [86]ckuusy.c
-          The command-line-option parser.
-
-   [87]ckuusx.c
-          User interface functions common to both the interactive and
-          command-line parsers.
-
-   [88]ckuver.h
-          Version heralds for different implementations.
-
-   [89]ckuscr.c
-          The (old, uucp-like) SCRIPT command
-
-   [90]ckudia.c
-          The DIAL command. Includes specific knowledge of many types of
-          modems.
-
-   Note that none of the above files is actually Unix-specific. Over time
-   they have proven to be portable among all platforms where C-Kermit is
-   built: Unix, VMS, AOS/VS, Amiga, OS-9, VOS, etc etc. Thus the third
-   letter should more properly be "c", but changing it would be too
-   confusing.
-
-   ck?con.c, ckucns.c
-          The CONNECT command. Terminal connection, and in some cases
-          (Macintosh, Windows) also terminal emulation. NOTE: As of
-          C-Kermit 7.0, there are two different CONNECT modules for UNIX:
-          [91]ckucon.c -- the traditional, portable, fork()-based version
-          -- and [92]ckucns.c, a new version that uses select() rather
-          than forks so it can handle encryption. ckucns.c is the
-          preferred version for Unix; ckucon.c is not likely to keep pace
-          with it in terms of upgrades, etc. However, since select() is
-          not portable to every platform, ckucon.c will be kept
-          indefinitely for those platforms that can't use ckucns.c. NOTE:
-          SunLink X.25 support is available only in ckucon.c.
-
-   ck_*.*, ckuat*.*
-          Modules having to do with authentication and encryption. Since
-          the relaxation of USA export laws, they are included with the
-          general source-code distribution. Secure C-Kermit binaries can
-          be built using special targets in the standard makefile.
-          However, secure prebuilt binaries may not be distributed.
-
-   For other implementations, the files may, and probably do, have
-   different names. For example, the Macintosh graphical user interface
-   filenames start with "ckm". Kermit 95 uses the ckucmd and ckuus*
-   modules, but has its own CONNECT command modules. And so on.
-
-   Here is a brief description of C-Kermit's "user interface interface",
-   from ckuusr.c. It is nowhere near complete; in particular, hundreds of
-   global variables are shared among the many modules. These should, some
-   day, be collected into classes or structures that can be passed around
-   as needed; not only for purity's sake, but also to allow for multiple
-   simultaneous communication sessions and or user interfaces. Our list
-   of things to do is endless, and reorganizing the source is almost
-   always at the bottom.
-
-   The ckuus*.c modules (like many of the ckc*.c modules) depend on the
-   existence of C library features like fopen, fgets, feof, (f)printf,
-   argv/argc, etc. Other functions that are likely to vary among
-   operating systems -- like setting terminal modes or interrupts -- are
-   invoked via calls to functions that are defined in the [93]Group E
-   platform-dependent modules, ck?[ft]io.c. The command line parser
-   processes any arguments found on the command line, as passed to main()
-   via argv/argc. The interactive parser uses the facilities of the cmd
-   package (developed for this program, but, in theory, usable by any
-   program). Any command parser may be substituted for this one. The only
-   requirements for the Kermit command parser are these:
-
-    1. Set parameters via global variables like duplex, speed, ttname,
-       etc. See [94]ckcmai.c for the declarations and descriptions of
-       these variables.
-    2. If a command can be executed without the use of Kermit protocol,
-       then execute the command directly and set the sstate (start state)
-       variable to 0. Examples include SET commands, local directory
-       listings, the CONNECT command.
-    3. If a command requires the Kermit protocol, set the following
-       variables:
- sstate                             string data
-   'x' (enter server mode)            (none)
-   'r' (send a 'get' command)         cmarg, cmarg2
-   'v' (enter receive mode)           cmarg2
-   'g' (send a generic command)       cmarg
-   's' (send files)                   nfils, cmarg & cmarg2 OR cmlist
-   'c' (send a remote host command)   cmarg
-
-       cmlist is an array of pointers to strings.
-       cmarg, cmarg2 are pointers to strings.
-       nfils is an integer (hmmm, probably should be an unsigned long).
-
-        cmarg can be:
-                A filename string (possibly wild), or:
-                a pointer to a prefabricated generic command string, or:
-                a pointer to a host command string.
-
-        cmarg2 is:
-                The name to send a single file under, or:
-                the name under which to store an incoming file; must not
-                be wild.
-                If it's the name for receiving, a null value means to
-                store the file under the name it arrives with.
-
-        cmlist is:
-                A list of nonwild filenames, such as passed via argv.
-
-        nfils is an integer, interpreted as follows:
-                -1: filespec (possibly wild) in cmarg, must be expanded
-                internally.
-                0: send from stdin (standard input).
-                >0: number of files to send, from cmlist.
-
-   The screen() function is used to update the screen during file
-   transfer. The tlog() function writes to a transaction log (if TLOG is
-   defined). The debug() function writes to a debugging log (if DEBUG is
-   defined). The intmsg() and chkint() functions provide the user i/o for
-   interrupting file transfers.
-
-   [ [95]Contents ] [ [96]C-Kermit ] [ [97]Kermit Home ]
-    ________________________________________________________________________
-
-  4.E. Group E: Platform-Dependent I/O
-
-   Platform-dependent function definitions. All the Kermit modules,
-   including the command package, call upon these functions, which are
-   designed to provide system-independent primitives for controlling and
-   manipulating devices and files. For Unix, these functions are defined
-   in the files [98]ckufio.c (files), [99]ckutio.c (communications), and
-   [100]ckusig.c (signal handling).
-
-   For VMS, the files are [101]ckvfio.c, ckvtio.c, and [102]ckusig.c (VMS
-   can use the same signal handling routines as Unix). It doesn't really
-   matter what the files are called, except for Kermit distribution
-   purposes (grouping related files together alphabetically), only that
-   each function is provided with the name indicated, observes the same
-   calling and return conventions, and has the same type.
-
-   The Group E modules contain both functions and global variables that
-   are accessed by modules in the other groups. These are now described.
-
-   (By the way, I got this list by linking all the C-Kermit modules
-   together except ckutio and ckufio. These are the symbols that ld
-   reported as undefined. But that was a long time ago, probably circa
-   Version 6.)
-
-  4.E.1. Global Variables
-
-   char *DELCMD;
-          Pointer to string containing command for deleting files.
-          Example: char *DELCMD = "rm -f "; (UNIX)
-          Example: char *DELCMD = "delete "; (VMS)
-          Note trailing space. Filename is concatenated to end of this
-          string. NOTE: DELCMD is used only in versions that do not
-          provide their own built-in DELETE command.
-
-   char *DIRCMD;
-          Pointer to string containing command for listing files when a
-          filespec is given.
-          Example: char *DIRCMD = "/bin/ls -l "; (UNIX)
-          Example: char *DIRCMD = "directory "; (VMS)
-          Note trailing space. Filename is concatenated to end of this
-          string. NOTE: DIRCMD is used only in versions that do not
-          provide their own built-in DIRECTORY command.
-
-   char *DIRCM2;
-          Pointer to string containing command for listing files when a
-          filespec is not given. (currently not used, handled in another
-          way.)
-          Example: char *DIRCMD2 = "/bin/ls -ld *";
-          NOTE: DIRCMD2 is used only in versions that do not provide
-          their own built-in DIRECTORY command.
-
-   char *PWDCMD;
-          Pointer to string containing command to display current
-          directory.
-          Example: char *PWDCMD = "pwd ";
-          NOTE: PWDCMD is used only in versions that do not provide their
-          own built-in PWD command.
-
-   char *SPACMD;
-          Pointer to command to display free disk space in current
-          device/directory.
-          Example: char *SPACMD = "df .";
-          NOTE: SPACMD is used only in versions that do not provide their
-          own built-in SPACE command.
-
-   char *SPACM2;
-          Pointer to command to display free disk space in another
-          device/directory.
-          Example: char *SPACM2 = "df ";
-          Note trailing space. Device or directory name is added to this
-          string. NOTE: SPACMD2 is used only in versions that do not
-          provide their own built-in SPACE command.
-
-   char *TYPCMD;
-          Pointer to command for displaying the contents of a file.
-          Example: char *TYPCMD = "cat ";
-          Note trailing space. Device or directory name is added to this
-          string. NOTE: TYPCMD is used only in versions that do not
-          provide their own built-in TYPE command.
-
-   char *WHOCMD;
-          Pointer to command for displaying logged-in users.
-          Example: char *WHOCMD = "who ";
-          Note trailing space. Specific user name may be added to this
-          string.
-
-   int backgrd = 0;
-          Flag for whether program is running in foreground (0) or
-          background (nonzero). Background operation implies that screen
-          output should not be done and that all errors should be fatal.
-
-   int ckxech;
-          Flag for who is to echo console typein:
-          1: The program (system is not echoing).
-          0: The OS, front end, terminal, etc (not this program).
-
-   char *ckxsys;
-          Pointer to string that names the computer and operating system.
-          Example: char *ckxsys = " NeXT Mach 1.0";
-          Tells what computer system ckxv applies to. In UNIX Kermit,
-          this variable is also used to print the program herald, and in
-          the SHOW VERSION command.
-
-   char *ckxv;
-          Pointer to version/edit info of ck?tio.c module.
-          Example: char *ckxv = "UNIX Communications Support, 6.0.169, 6
-          Sep 96";
-          Used by SHOW VERSION command.
-
-   char *ckzsys;
-          Like ckxsys, but briefer.
-          Example: char *ckzsys = " 4.3 BSD";
-          Tells what platform ckzv applies to. Used by the SHOW VERSION
-          command.
-
-   char *ckzv;
-          Pointer to version/edit info of ck?fio.c module.
-          Example: char *ckzv = "UNIX File support, 6.0.113, 6 Sep 96";
-          Used by SHOW VERSION command.
-
-   int dfflow;
-          Default flow control. 0 = none, 1 = Xon/Xoff, ... (see FLO_xxx
-          symbols in ckcdeb.h)
-          Set by Group E module. Used by [103]ckcmai.c to initialize flow
-          control variable.
-
-   int dfloc;
-          Default location. 0 = remote, 1 = local. Set by Group E module.
-          Used by ckcmai.c to initialize local variable. Used in various
-          places in the user interface.
-
-   int dfprty;
-          Default parity. 0 = none, 'e' = even, 'o' = odd, 'm' = mark,
-          's' = space. Set by Group E module. Used by ckcmai.c to
-          initialize parity variable.
-
-   char *dftty;
-          Default communication device. Set by Group E module. Used in
-          many places. This variable should be initialized the the symbol
-          CTTNAM, which is defined in ckcdeb.h, e.g. as "/dev/tty" for
-          UNIX, "TT:" for VMS, etc. Example: char *dftty = CTTNAM;
-
-   char *mtchs[];
-          Array of string pointers to filenames that matched the most
-          recent wildcard match, i.e. the most recent call to zxpand().
-          Used (at least) by command parsing package for partial filename
-          completion.
-
-   int tilde_expand;
-          Flag for whether to attempt to expand leading tildes in
-          directory names (used in UNIX only, and then only when the
-          symbol DTILDE is defined.
-
-   int ttnproto;
-          The protocol being used to communicate over a network device.
-          Values are defined in ckcnet.h. Example: NP_TELNET is network
-          protocol "telnet".
-
-   int maxnam;
-          The maximum length for a filename, exclusive of any device or
-          directory information, in the format of the host operating
-          system.
-
-   int maxpath;
-          The maximum length for a fully specified filename, including
-          device designator, directory name, network node name, etc, in
-          the format of the host operating system, and including all
-          punctuation.
-
-   int ttyfd;
-          File descriptor of the communication device. -1 if there is no
-          open or usable connection, including when C-Kermit is in remote
-          mode. Since this is not implemented everywhere, references to
-          it are in #ifdef CK_TTYFD..#endif.
-
-   [ [104]Contents ] [ [105]C-Kermit ] [ [106]Kermit Home ]
-    ________________________________________________________________________
-
-  4.E.2. Functions
-
-   These are divided into three categories: file-related functions (B.1),
-   communication functions (B.2), and miscellaneous functions (B.3).
-
-    4.E.2.1. File-Related Functions
-
-   In most implementations, these are collected together into a module
-   called ck?fio.c, where ? = "u" ([107]ckutio.c for Unix), "v"
-   ([108]ckvtio.c for VMS), [109]etc. To be totally platform-independent,
-   C-Kermit maintains its own file numbers, and provides the functions
-   described in this section to deal with the files associated with them.
-   The file numbers are referred to symbolically, and are defined as
-   follows in ckcker.h:
-
-  #define ZCTERM      0           /* Console terminal */
-  #define ZSTDIO      1           /* Standard input/output */
-  #define ZIFILE      2           /* Current input file for SEND command */
-  #define ZOFILE      3           /* Current output file for RECEIVE command */
-  #define ZDFILE      4           /* Current debugging log file */
-  #define ZTFILE      5           /* Current transaction log file */
-  #define ZPFILE      6           /* Current packet log file */
-  #define ZSFILE      7           /* Current session log file */
-  #define ZSYSFN      8           /* Input from a system function (pipe) */
-  #define ZRFILE      9           /* Local file for READ command */  (NEW)
-  #define ZWFILE     10           /* Local file for WRITE command */ (NEW)
-  #define ZMFILE     11           /* Auxilliary file for internal use */ (NEW)
-  #define ZNFILS     12           /* How many defined file numbers */
-
-   In the descriptions below, fn refers to a filename, and n refers to
-   one of these file numbers. Functions are of type int unless otherwise
-   noted, and are listed mostly alphabetically.
-
-   int
-          chkfn(n) int n;
-          Checks the file number n. Returns:
-           -1: File number n is out of range
-            0: n is in range, but file is not open
-            1: n in range and file is open
-
-   int
-          iswild(filspec) char *filespec;
-          Checks if the file specification is "wild", i.e. contains
-          metacharacters or other notations intended to match multiple
-          filenames. Returns:
-            0: not wild
-            1: wild.
-
-   int
-          isdir(string) char *string;
-          Checks if the string is the name of an existing directory. The
-          idea is to check whether the string can be "cd'd" to, so in
-          some cases (e.g. DOS) it might also indicate any file
-          structured device, such as a disk drive (like A:). Other
-          nonzero returns indicate system-dependent information; e.g. in
-          VMS isdir("[.FOO]") returns 1 but isdir("FOO.DIR;1") returns 2
-          to indicate the directory-file name is in a format that needs
-          conversion before it can be combined with a filename. Returns:
-            0: not a directory (including any kind of error)
-            1: it is an existing directory
-
-   char *
-          zfcdat(name) char *name;
-          Returns modification (preferably, otherwise creation) date/time
-          of file whose name is given in the argument string. Return
-          value is a pointer to a string of the form yyyymmdd hh:mm:ss,
-          for example 19931231 23:59:59, which represents the local time
-          (no timezone or daylight savings time finagling required).
-          Returns the null string ("") on failure. The text pointed to by
-          the string pointer might be in a static buffer, and so should
-          be copied to a safe place by the caller before any subsequent
-          calls to this function.
-
-   struct zfnfp *
-          zfnqfp(fn, buflen, buf) char * fn; int buflen; char * buf;
-          Given the filename fn, the corresponding fully qualified,
-          absolute filename is placed into the buffer buf, whose length
-          is buflen. On failure returns a NULL pointer. On success
-          returns a pointer to a struct zfnfp containing pointers to the
-          full pathname and to just the filename, and an int giving the
-          length of the full pathname. All references to this function in
-          mainline code must be protected by #ifdef ZFNQFP..#endif,
-          because it is not present in all of the ck*fio.c modules. So if
-          you implement this function in a version that did not have it
-          before, be sure to add #define ZFNQFP in the appropriate spot
-          in ckcdeb.h or in the build-procedure CFLAGS.
-
-   int
-          zcmpfn(s1,s2) char * s2, * s2;
-          Compares two filenames to see if they refer to the same.
-          Internally, the arguments can be converted to fully qualified
-          pathnames, e.g. with zfnqfp(), realpath(), or somesuch. In Unix
-          or other systems where symbolic links exist, the link should be
-          resolved before making the comparison or looking at the inodes.
-          Returns:
-            0: Files are not identical.
-            1: Files are identical.
-
-   int
-          zfseek(pos) long pos;
-          Positions the input pointer on the current input file to the
-          given position. The pos argument is 0-based, the offset
-          (distance in bytes) from beginning of the file. Needed for
-          RESEND, PSEND, and other recovery operations. This function is
-          not necessarily possible on all systems, e.g. record-oriented
-          systems. It should only be used on binary files (i.e. files we
-          are sending in binary mode) and stream-oriented file systems.
-          Returns:
-           -1: on failure.
-            0: On success.
-
-   int
-          zchdir(dirnam) char *dirnam;
-          Changes current or default directory to the one given in
-          dirnam. Returns:
-            0: On failure.
-            1: on success.
-
-   long
-          zchki(fn) char *fn;
-          Check to see if file with name fn is a regular, readable,
-          existing file, suitable for Kermit to send -- not a directory,
-          not a symbolic link, etc. Returns:
-           -3: if file exists but is not accessible (e.g.
-          read-protected);
-           -2: if file exists but is not of a readable type (e.g. a
-          directory);
-           -1: on error (e.g. file does not exist, or fn is garbage);
-          >=0: (length of file) if file exists and is readable.
-          Also see isdir(), zgetfs().
-
-   int
-          zchkpid(pid) unsigned long pid;
-          Returns:
-            1: If the given process ID (e.g. pid in UNIX) is valid and
-          active
-            0: otherwise.
-
-   long
-          zgetfs(fn) char *fn;
-          Gets the size of the given file, regardless of accessibility.
-          Used for directory listings. Unlike zchki(), should return the
-          size of any kind of file, even a directory. zgetfs() also
-          should serve as a mini "get file info" function that can be
-          used until we design a better one, by also setting some global
-          variables:
-            int zgfs_link   = 1/0 = file is (not) a symbolic link.
-            int zgfs_dir    = 1/0 = file is (not) a directory.
-            char linkname[] = if zgfs_link != 0, name of file link points
-          to.
-          Returns:
-           -1: on error (e.g. file does not exist, or fn is garbage);
-          >=0: (length of file) if file exists and is readable.
-
-   int
-          zchko(fn) char *fn;
-          Checks to see if a file of the given name can be created.
-          Returns:
-           -1: if file cannot be created, or on any kind of error.
-            0: if file can be created.
-
-   int
-          zchkspa(fn,len) char *f; long len;
-          Checks to see if there is sufficient space to store the file
-          named fn, which is len bytes long. If you can't write a
-          function to do this, then just make a dummy that always returns
-          1; higher level code will recover from disk-full errors. The
-          receiving Kermit uses this function to refuse an incoming file
-          based on its size, via the attribute mechanism. Returns:
-           -1: on error.
-            0: if there is not enough space.
-            1: if there is enough space.
-
-   int
-          zchin(n,c) int n; int *c;
-          Gets a character from file number n, return it in c (call with
-          &c). Returns:
-           -1: on failure, including EOF.
-            0: on success with character in c.
-
-   int
-          zchout(n,c) int n; char c;
-          Writes the character c to file number n. Returns:
-           -1: on error.
-            0: on success.
-
-   int
-          zclose(n) int n;
-          Closes file number n. Returns:
-           -1: on error.
-            1: on success.
-
-   int
-          zdelet(fn) char *name;
-          Attempts to delete (remove, erase) the named file. Returns:
-           -1: on error.
-            1: if file was deleted successfully.
-
-   char *
-          zgperm(char * f)
-          Returns a pointer to the system-dependent numeric
-          permissions/protection string for file f, or NULL upon failure.
-          Used if CK_PERMS is defined.
-
-   char *
-          ziperm(char * f)
-          Returns a pointer to the system-dependent symbolic
-          permissions/protection string for file f, or NULL upon failure.
-          Used if CK_PERMS is defined. Example: In UNIX zgperm(f) might
-          return "100770", but ziperm() might return "-rwxrwx---". In
-          VMS, zgperm() would return a hexadecimal string, but ziperm()
-          would return something like "(RWED,RWED,RE,)".
-
-   char *
-          zgtdir()
-          Returns a pointer to the name of the current directory, folder,
-          etc, or a NULL pointer if the current directory cannot be
-          determined. If possible, the directory specification should be
-          (a) fully specified, e.g. as a complete pathname, and (b) be
-          suitable for appending a filename. Thus, for example, Unix
-          directory names should end with '/'. VMS directory names should
-          look like DEV:[NAME] (rather than, say, NAME.DIR;1).
-
-   char *
-          zhome()
-          Returns a pointer to a string containing the user's home
-          directory, or NULL upon error. Should be formatted like
-          zgtdir() (q.v.).
-
-   int
-          zinfill()
-          Fill buffer from input file. This function is used by the macro
-          zminchar(), which is defined in ckcker.h. zminchar() manages
-          its own buffer, and calls zinfill() to fill it whenever it
-          becomes empty. It is used only for sending files, and reads
-          characters only from file number ZIFILE. zinfill() returns -1
-          upon end of file, -2 upon fatal error, and -3 upon timeout
-          (e.g. when reading from a pipe); otherwise it returns the first
-          character from the buffer it just read.
-
-   int
-          zkself()
-          Kills the current job, session, process, etc, logs out,
-          disappears. Used by the Kermit server when it receives a BYE
-          command. On failure, returns -1. On success, does not return at
-          all! This function should not be called until all other steps
-          have been taken to close files, etc.
-
-   VOID
-          zstrip(fn,&fn2) char *fn1, **fn2;
-          Strips device and directory, etc, from file specification fn,
-          leaving only the filename (including "extension" or "filetype"
-          -- the part after the dot). For example DUA0:[PROGRAMS]OOFA.C;3
-          becomes OOFA.C, or /usr/fdc/oofa.c becomes oofa.c. Returns a
-          pointer to result in fn2.
-
-   int
-          zsetperm(char * file, unsigned int code)
-          Set permissions of file to given system-dependent code.   0: On
-          failure.
-            1: on success.
-
-   int
-          zsetroot(char * dir)
-          Sets the root for the user's file access, like Unix chroot(),
-          but does not require privilege. In Unix, this must be
-          implemented entirely by Kermit's own file access routines.
-          Returns:
-            1: Success
-           -1: Invalid argument
-           -2:
-           -3: Internal error
-           -4: Access to given directory denied
-           -5: New root not within old root
-
-   int
-          zinroot(char * file)
-          If no root is set (zsetroot()), returns 1.
-          Otherwise, if given file is in the root, returns 1.
-          Otherwise, returns 0.
-
-   VOID
-          zltor(fn,fn2) char *fn1, *fn2;
-          Local-To-Remote filename translation. OBSOLETE: replaced by
-          nzltor() (q.v.). Translates the local filename fn into a format
-          suitable for transmission to an arbitrary type of computer, and
-          copies the result into the buffer pointed to by fn2.
-          Translation may involve (a) stripping the device and/or
-          directory/path name, (b) converting lowercase to uppercase, (c)
-          removing spaces and strange characters, or converting them to
-          some innocuous alphabetic character like X, (d) discarding or
-          converting extra periods (there should not be more than one).
-          Does its best. Returns no value. name2 is a pointer to a
-          buffer, furnished by the caller, into which zltor() writes the
-          resulting name. No length checking is done.
-
-   #ifdef NZLTOR
-          VOID
-          nzltor(fn,fn2,convert,pathnames,max) char *fn1,*fn2; int
-          convert,pathnames,max;
-          Replaces zltor(). This new version handles pathnames and checks
-          length. fn1 and fn2 are as in zltor(). This version is called
-          unconditionally for each file, rather than only when filename
-          conversion is enabled. Pathnames can have the following values:
-
-            PATH_OFF: Pathname, if any, is to be stripped
-            PATH_REL: The relative pathname is to be included
-            PATH_ABS: The full pathname is to be included
-
-          After handling pathnames, conversion is done to the result as
-          in the zltor() description if convert != 0; if relative or
-          absolute pathnames are included, they are converted to UNIX
-          format, i.e. with slash (/) as the directory separator. The max
-          parameter specifies the maximum size of fn2. If convert > 0,
-          the regular conversions are done; if convert < 0, minimal
-          conversions are done (we skip uppercasing the letters, we allow
-          more than one period, etc; this can be used when we know our
-          partner is UNIX or similar).
-
-   #endif /* NZLTOR */
-
-   int
-          nzxpand(fn,flags) char *fn; int flags;
-          Replaces zxpand(), which is obsolete as of C-Kermit 7.0.
-          Call with:
-            fn = Pointer to filename or pattern.
-            flags = option bits:
-              flags & ZX_FILONLY  Match regular files
-              flags & ZX_DIRONLY  Match directories
-              flags & ZX_RECURSE  Descend through directory tree
-              flags & ZX_MATCHDOT Match "dot files"
-              flags & ZX_NOBACKUP Don't match "backup files"
-              flags & ZX_NOLINKS  Don't follow symlinks.
-
-          Returns the number of files that match fn, with data structures
-          set up so the first file (if any) will be returned by the next
-          znext() call. If ZX_FILONLY and ZX_DIRONLY are both set, or
-          neither one is set, files and directories are matched. Notes:
-
-         1. It is essential that the number returned by nzxpand() reflect
-            the actual number of filenames that will be returned by
-            znext() calls. In other words:
-  for (n = nzxpand(string,flags); n > 0; n--) {
-      znext(buf);
-      printf("%s\n", buf);
-  }
-            should print all the file names; no more, no less.
-         2. In UNIX, DOS, OS-9, etc, where directories contain entries
-            for themselves (.) and the superior directory (..), these
-            should NOT be included in the list under any circumstances,
-            including when ZX_MATCHDOT is set.
-         3. Additional option bits might be added in the future, e.g. for
-            sorting (sort by date/name/size, reverse/ascending, etc).
-            Currently this is done only in higher level code (through a
-            hack in which the nzxpand() exports its filename array, which
-            is not portable because not all OS's can use this mechanism).
-
-   int
-          zmail(addr,fn) char *addr, fn;
-          Send the local, existing file fn as e-mail to the address addr.
-          Returns:
-            0: on success
-            2: if mail delivered but temp file can't be deleted
-           -2: if mail can't be delivered
-
-   int
-          zmkdir(path) char *path;
-          The path can be a file specification that might contain
-          directory information, in which the filename is expected to be
-          included, or an unambiguous directory specification (e.g. in
-          UNIX it must end with "/"). This routine attempts to create any
-          directories in the given path that don't already exist. Returns
-          0 or greater success: no directories needed creation, or else
-          all directories that needed creation were created successfully;
-          the return code is the number of directories that were created.
-          Returns -1 on failure to create any of the needed directories.
-
-   int
-          zrmdir(path) char *path;
-          Attempts to remove the given directory. Returns 0 on success,
-          -1 on failure. The detailed semantics are open -- should it
-          fail if the directory contains any files or subdirectories,
-          etc. It is probably best for this routine to behave in whatever
-          manner is customary on the underlying platform; e.g. in UNIX,
-          VMS, DOS, etc, where directories can not be removed unless they
-          are empty.
-
-   VOID
-          znewn(fn,s) char *fn, **s;
-          Transforms the name fn into a filename that is guaranteed to be
-          unique. If the file fn does not exist, then the new name is the
-          same as fn; Otherwise, it's different. this function does its
-          best, returns no value. New name is created in caller's space.
-          Call like this: znewn(old,&new);. The second parameter is a
-          pointer to the new name. This pointer is set by znewn() to
-          point to a static string in its own space, so be sure to the
-          result to a safe place before calling this function again.
-
-   int
-          znext(fn) char *fn;
-          Copies the next file name from a file list created by zxpand()
-          into the string pointed to by fn (see zxpand). If no more
-          files, then the null string is placed there. Returns 0 if there
-          are no more filenames, with 0th element the array pointed to by
-          fn set to NUL. If there is a filename, it is stored in the
-          array pointed to by fn and a positive number is returned. NOTE:
-          This is a change from earlier definitions of this function
-          (pre-1999), which returned the number of files remaining; thus
-          0 was the return value when returning the final file. However,
-          no mainline code ever depended on the return value, so this
-          change should be safe.
-
-   int
-          zopeni(n,fn) int n; char *fn;
-          Opens the file named fn for input as file number n. Returns:
-            0: on failure.
-            1: on success.
-
-   int
-          zopeno(n,fn,zz,fcb) int n; char *name; struct zattr *zz; struct
-          filinfo *fcb;
-          Attempts to open the named file for output as file number n. zz
-          is a Kermit file attribute structure as defined in ckcdeb.h,
-          containing various information about the file, including its
-          size, creation date, and so forth. This function should attempt
-          to honor as many of these as possible. fcb is a "file control
-          block" in the traditional sense, defined in ckcdeb.h,
-          containing information relevant to complicated file systems
-          like VMS (RMS), IBM MVS, etc, like blocksize, record length,
-          organization, record format, carriage control, etc. Returns:
-            0: on failure.
-            1: on success.
-
-   int
-          zoutdump()
-          Dumps a file output buffer. Used with the macro zmchout()
-          defined in ckcker.h. Used only with file number ZOFILE, i.e.
-          the file that is being received by Kermit during file transfer.
-          Returns:
-           -1: on failure.
-            0: on success.
-
-   int
-          zprint(p,fn) char *p, *f;
-          Prints the file with name fn on a local printer, with options
-          p. Returns:
-            0: on success
-            3: if file sent to printer but can't be deleted
-           -3: if file can't be printed
-
-   int
-          zrename(fn,fn2) char *fn, *fn2;
-          Changes the name of file fn to fn2. If fn2 is the name of an
-          existing directory, or a file-structured device, then file fn
-          is moved to that directory or device, keeping its original
-          name. If fn2 lacks a directory separator when passed to this
-          function, an appropriate one is supplied. Returns:
-           -1: on failure.
-            0: on success.
-
-   int
-          zcopy(source,dest) char * source, * dest;
-          Copies the source file to the destination. One file only. No
-          wildcards. The destination string may be a filename or a
-          directory name. Returns:
-            0: on success.
-           <0: on failure:
-            -2: source file is not a regular file.
-            -3: source file not found.
-            -4: permission denied.
-            -5: source and destination are the same file.
-            -6: i/o error.
-            -1: other error.
-
-   char *
-          zlocaltime(char *)
-          Call with: "yyyymmdd hh:mm:ss" GMT/UTC date-time. Returns
-          pointer to local date-time string "yyyymmdd hh:mm:ss" on
-          success, NULL on failure.
-
-   VOID
-          zrtol(fn,fn2) char *fn, *fn2;
-          Remote-To-Local filename translation. OBSOLETE: replaced by
-          nzrtol(). Translates a "standard" filename to a local filename.
-          For example, in Unix this function might convert an
-          all-uppercase name to lowercase, but leave lower- or mix-case
-          names alone. Does its best, returns no value. New name is in
-          string pointed to by fn2. No length checking is done.
-
-   #ifdef NZLTOR
-   int
-          nzrtol(fn,fn2,convert,pathnames,max) char *fn1,*fn2; int
-          convert,pathnames,max;
-          Replaces zrtol. Like zrtol but handles pathnames and checks
-          length. See nzltor for detailed description of parameters.
-
-   #endif /* NZLTOR */
-
-   int
-          zsattr(xx) struct zattr *xx;
-          Fills in a Kermit file attribute structure for the file which
-          is to be sent, namely the currently open ZIFILE. Note that this
-          is not a very good design, but we're stuck with it. Callers
-          must ensure that zsattr() is called only on real files, not on
-          pipes, internally generated file-like objects such as server
-          REMOTE command responses, etc. Returns:
-           -1: on failure.
-            0: on success with the structure filled in.
-          If any string member is null, it should be ignored by the
-          caller.
-          If any numeric member is -1, it should be ignored by the
-          caller.
-
-   int
-          zshcmd(s) char *s;
-          s contains to pointer to a command to be executed by the host
-          computer's shell, command parser, or operating system. If the
-          system allows the user to choose from a variety of command
-          processors (shells), then this function should employ the
-          user's preferred shell. If possible, the user's job
-          (environment, process, etc) should be set up to catch keyboard
-          interruption signals to allow the user to halt the system
-          command and return to Kermit. The command must run in ordinary,
-          unprivileged user mode. If possible, this function should
-          return -1 on failure to start the command, or else it should
-          return 1 if the command succeeded and 0 if it failed.
-
-   int
-          pexitstatus
-          zshcmd() and zsyscmd() should set this to the command's actual
-          exit status code if possible.
-
-   int
-          zsyscmd(s) char *s;
-          s contains to pointer to a command to be executed by the host
-          computer's shell, command parser, or operating system. If the
-          system allows the user to choose from a variety of command
-          processors (shells), then this function should employ the
-          system standard shell (e.g. /bin/sh for Unix), so that the
-          results will always be the same for everybody. If possible, the
-          user's job (environment, process, etc) should be set up to
-          catch keyboard interruption signals to allow the user to halt
-          the system command and return to Kermit. The command must run
-          in ordinary, unprivileged user mode. If possible, this function
-          should return -1 on failure to start the command, or else it
-          should return 1 if the command succeeded and 0 if it failed.
-
-   VOID
-          z_exec(s,args) char * s; char * args[];
-          This one executes the command s (which is searched for using
-          the system's normal searching mechanism, such as PATH in UNIX),
-          with the given argument vector, which follows the conventions
-          of UNIX argv[]: the name of the command pointed to by element
-          0, the first arg by element 1, and so on. A null args[] pointer
-          indicates the end of the arugment list. All open files must
-          remain open so the exec'd process can use them. Returns only if
-          unsuccessful.
-
-   int
-          zsinl(n,s,x) int n, x; char *s;
-          Reads a line from file number n. Writes the line into the
-          address s provided by the caller. Writing terminates when
-          newline is read, but with newline discarded. Writing also
-          terminates upon EOF or if length x is exhausted. Returns:
-           -1: on EOF or error.
-            0: on success.
-
-   int
-          zsout(n,s) int n; char *s;
-          Writes the string s out to file number n. Returns:
-           -1: on failure.
-            0: on success.
-
-   int
-          zsoutl(n,s) int n; char *s;
-          Writes the string s out to file number n and adds a line
-          (record) terminator (boundary) appropriate for the system and
-          the file format. Returns:
-           -1: on failure.
-            0: on success.
-
-   int
-          zsoutx(n,s,x) int n, x; char *s;
-          Writes exactly x characters from string s to file number n. If
-          s has fewer than x characters, then the entire string s is
-          written. Returns:
-           -1: on failure.
-          >= 0: on success, the number of characters actually written.
-
-   int
-          zstime(fn,yy,x) char *fn; struct zattr *yy; int x;
-          Sets the creation date (and other attributes) of an existing
-          file, or compares a file's creation date with a given date.
-          Call with:
-
-   fn: pointer to name of existing file.
-   yy: Pointer to a Kermit file attribute structure in which yy->date.val
-   is a date of the form yyyymmdd hh:mm:ss, e.g. 19900208 13:00:00, which
-   is to be used for setting or comparing the file date. Other attributes
-   in the struct can also be set, such as the protection/permission (See
-   [110]Appendix I), when it makes sense (e.g. "yy->lprotect.val" can be
-   set if the remote system ID matches the local one).
-    x: A function code: 0 means to set the file's creation date as given.
-   1 means compare the date from the yy struct with the file's date.
-
-          Returns:
-           -1: on any kind of error.
-            0: if x is 0 and the file date was set successfully.
-            0: if x is 1 and date from attribute structure > file
-          creation date.
-            1: if x is 1 and date from attribute structure <= file
-          creation date.
-
-   VOID
-          zstrip(name,name2) char *name, **name2;
-          Strips pathname from filename "name". Constructs the resulting
-          string in a static buffer in its own space and returns a
-          pointer to it in name2. Also strips device name, file version
-          numbers, and other "non-name" material.
-
-   int
-          zxcmd(n,s) char *s;
-          Runs a system command so its output can be accessed as if it
-          were file n. The command is run in ordinary, unprivileged user
-          mode.
-          If n is ZSTDIO or ZCTERM, returns -1.
-          If n is ZIFILE or ZRFILE, then Kermit reads from the command,
-          otherwise Kermit writes to the command.
-          Returns 0 on error, 1 on success.
-
-   int
-          zxpand(fn) char *fn;
-          OBSOLETE: Replaced by nzxpand(), q.v.
-
-   #ifdef ZXREWIND
-   int
-          zxrewind()
-          Returns the number of files returned by the most recent
-          nzxpand() call, and resets the list to the beginning so the
-          next znext() call returns the first file. Returns -1 if zxpand
-          has not yet been called. If this function is available,
-          ZXREWIND should be defined; otherwise it should not be
-          referenced.
-
-   #endif /* ZXREWIND */
-
-   int
-          xsystem(cmd) char *cmd;
-          Executes the system command without redirecting any of its i/o,
-          similar (well, identical) to system() in Unix. But before
-          passing the command to the system, xsystem() ensures that all
-          privileges are turned off, so that the system command executes
-          in ordinary unprivileged user mode. If possible, xsystem()
-          returns the return code of the command that was executed.
-
-    4.E.2.2. IKSD Variables and Functions
-
-   These must be implemented in any C-Kermit version that is to be
-   installed as an Internet Kermit Service Daemon (IKSD). IKSD is
-   expected to be started by the Internet Daemon (e.g. inetd) with its
-   standard i/o redirected to the incoming connection.
-
-   int ckxanon;
-          Nonzero if anonymous logins allowed.
-
-   extern int inserver;
-          Nonzero if started in IKSD mode.
-
-   extern int isguest;
-          Nonzero if IKSD and user logged in anonymously.
-
-   extern char * homdir;
-          Pointer to user's home directory.
-
-   extern char * anonroot;
-          Pointer to file-system root for anonymous users.
-
-   Existing functions must make "if (inserver && isguest)" checks for
-   actions that would not be legal for guests: zdelete(), zrmdir(),
-   zprint(), zmail(), etc.
-
-   int
-          zvuser(name) char * name;
-          Verifies that user "name" exists and is allowed to log in. If
-          the name is "ftp" or "anonymous" and ckxanon != 0, a guest
-          login is set up. Returns 0 if user not allowed to log in,
-          nonzero if user may log in.
-
-   int
-          zvpass(string) char * string;
-          Verifies password of the user from the most recent zvuser()
-          call. Returns nonzero if password is valid for user, 0 if it
-          isn't. Makes any appropriate system log entries (IKSD logins,
-          failed login attempts, etc). If password is valid, logs the
-          user in as herself (if real user), or sets up restricted
-          anonymous access if user is guest (e.g. changes file-system
-          root to anonroot and sets isguest = 1).
-
-   VOID
-          zsyslog()
-          Begins any desired system logging of an IKSD session.
-
-   VOID
-          zvlogout()
-          Terminates an IKSD session. In most cases this is simply a
-          wrapper for exit() or doexit(), with some system logging added.
-
-    4.E.2.3. Privilege Functions
-
-   These functions are used by C-Kermit to adapt itself to operating
-   systems where the program can be made to run in a "privileged" mode,
-   e.g. setuid or setgid in Unix. C-Kermit should NOT read and write
-   files or start subprocesses as a privileged program. This would
-   present a serious threat to system security. The security package has
-   been installed to prevent such security breaches by turning off the
-   program's special privileges at all times except when they are needed.
-
-   In UNIX, the only need Kermit has for privileged status is access to
-   the UUCP lockfile directory, in order to read, create, and destroy
-   lockfiles, and to open communication devices that are normally
-   protected against the user (see the [111]Unix C-Kermit Installation
-   Instructions for discussion). Therefore, privileges should only be
-   enabled for these operations and disabled at all other times. This
-   relieves the programmer of the responsibility of putting expensive and
-   unreliable access checks around every file access and subprocess
-   creation.
-
-   Strictly speaking, these functions are not required in all C-Kermit
-   implementations, because their use (so far, at least) is internal to
-   the Group E modules. However, they should be included in all C-Kermit
-   implementations for operating systems that support the notion of a
-   privileged program (UNIX, RSTS/E, what others?).
-
-   int
-          priv_ini()
-          Determine whether the program is running in privileged status.
-          If so, turn off the privileges, in such a way that they can be
-          turned on again when needed. Called from sysinit() at program
-          startup time. Returns:
-            0 on success
-            nonzero on failure, in which case the program should halt
-          immediately.
-
-   int
-          priv_on()
-          If the program is not privileged, this function does nothing.
-          If the program is privileged, this function returns it to
-          privileged status. priv_ini() must have been called first.
-          Returns:
-            0 on success
-            nonzero on failure
-
-   int
-          priv_off()
-          Turns privileges off (if they are on) in such a way that they
-          can be turned back on again. Returns:
-            0 on success
-            nonzero on failure
-
-   int
-          priv_can()
-          Turns privileges off in such a way that they cannot be turned
-          back on. Returns:
-            0 on success
-            nonzero on failure
-
-   int
-          priv_chk()
-          Attempts to turns privileges off in such a way that they can be
-          turned on again later. Then checks to make sure that they were
-          really turned off. If they were not really turned off, then
-          they are cancelled permanently. Returns:
-            0 on success
-            nonzero on failure
-
-    4.E.2.4. Console-Related Functions
-
-   These relate to the program's "console", or controlling terminal, i.e.
-   the terminal that the user is logged in on and types commands at, or
-   on a PC or workstation, the actual keyboard and screen.
-
-   int
-          conbin(esc) char esc;
-          Puts the console into "binary" mode, so that Kermit's command
-          parser can control echoing and other treatment of characters
-          that the user types. esc is the character that will be used to
-          get Kermit's attention during packet mode; puts this in a
-          global place. Sets the ckxech variable. Returns:
-           -1: on error.
-            0: on success.
-
-   int
-          concb(esc) char esc;
-          Put console in "cbreak" (single-character wakeup) mode. That
-          is, ensure that each console character is available to the
-          program immediately when the user types it. Otherwise just like
-          conbin(). Returns:
-           -1: on error.
-            0: on success.
-
-   int
-          conchk()
-          Returns a number, 0 or greater, the number of characters
-          waiting to be read from the console, i.e. the number of
-          characters that the user has typed that have not been read yet
-          by Kermit.
-
-   long
-          congspd();
-          Returns the speed ("baud rate") of the controlling terminal, if
-          known, otherwise -1L.
-
-   int
-          congks(timo) int timo;
-          Get Keyboard Scancode. Reads a keyboard scan code from the
-          physical console keyboard. If the timo parameter is greater
-          than zero, then times out and returns -2 if no character
-          appears within the given number of seconds. Upon any other kind
-          of error, returns -1. Upon success returns a scan code, which
-          may be any positive integer. For situations where scan codes
-          cannot be read (for example, when an ASCII terminal is used as
-          the job's controlling terminal), this function is identical to
-          coninc(), i.e. it returns an 8-bit character value. congks() is
-          for use with workstations whose keyboards have Alternate,
-          Command, Option, and similar modifier keys, and Function keys
-          that generate codes greater than 255.
-
-   int
-          congm()
-          Console get modes. Gets the current console terminal modes and
-          saves them so that conres() can restore them later. Returns 1
-          if it got the modes OK, 0 if it did nothing (e.g. because
-          Kermit is not connected with any terminal), -1 on error.
-
-   int
-          coninc(timo) int timo;
-          Console Input Character. Reads a character from the console. If
-          the timo parameter is greater than zero, then coninc() times
-          out and returns -2 if no character appears within the given
-          number of seconds. Upon any other kind of error, returns -1.
-          Upon success, returns the character itself, with a value in the
-          range 0-255 decimal.
-
-   VOID
-          conint(f,s) SIGTYP (*f)(), (*s)();
-          Sets the console to generate an interrupt if the user types a
-          keyboard interrupt character, and to transfer control the
-          signal-handling function f. For systems with job control, s is
-          the address of the function that suspends the job. Sets the
-          global variable "backgrd" to zero if Kermit is running in the
-          foreground, and to nonzero if Kermit is running in the
-          background. See ckcdeb.h for the definition of SIGTYP. No
-          return value.
-
-   VOID
-          connoi()
-          Console no interrupts. Disable keyboard interrupts on the
-          console. No return value.
-
-   int
-          conoc(c) char c;
-          Writes character c to the console terminal. Returns:
-          0 on failure, 1 on success.
-
-   int
-          conol(s) char *s;
-          Writes string s to the console. Returns -1 on error, 0 or
-          greater on success.
-
-   int
-          conola(s) char *s[]; {
-          Writes an array of strings to the console. Returns -1 on error,
-          0 or greater on success.
-
-   int
-          conoll(s) char *s;
-          Writes string s to the console, followed by the necessary line
-          termination characters to put the console cursor at the
-          beginning of the next line. Returns -1 on error, 0 or greater
-          on success.
-
-   int
-          conres()
-          Restores the console terminal to the modes obtained by congm().
-          Returns: -1 on error, 0 on success.
-
-   int
-          conxo(x,s) int x; char *s;
-          Write x characters from string s to the console. Returns 0 or
-          greater on success, -1 on error.
-
-   char *
-          conkbg();
-          Returns a pointer to the designator of the console keyboard
-          type. For example, on a PC, this function would return "88",
-          "101", etc. Upon failure, returns a pointer to the empty
-          string.
-
-    4.E.2.5. Communications Functions
-
-   The communication device is the device used for terminal emulation and
-   file transfer. It may or may not be the same device as the console,
-   and it may or may not be a terminal (serial-port) device; it could
-   also be a network connection. For brevity, the communication device is
-   referred to here as the "tty". When the communication device is the
-   same as the console device, Kermit is said to be in remote mode. When
-   the two devices are different, Kermit is in local mode.
-
-   int
-          ttchk()
-          Returns the number of characters that have arrived at the
-          communication device but have not yet been read by ttinc(),
-          ttinl(), and friends. If communication input is buffered (and
-          it should be), this is the sum of the number of unread
-          characters in Kermit's buffer PLUS the number of unread
-          characters in the operating system's internal buffer. The call
-          must be nondestructive and nonblocking, and as inexpensive as
-          possible. Returns:
-            0: or greater on success,
-            0: in case of internal error,
-           -1: or less when it determines the connection has been broken,
-          or there is no connection.
-
-          That is, a negative return from ttchk() should reliably
-          indicate that there is no usable connection. Furthermore,
-          ttchk() should be callable at any time to see if the connection
-          is open. When the connection is open, every effort must be made
-          to ensure that ttchk returns an accurate number of characters
-          waiting to be read, rather than just 0 (no characters) or 1 (1
-          or more characters), as would be the case when we use select().
-          This aspect of ttchk's operation is critical to successful
-          operation of sliding windows and streaming, but "nondestructive
-          buffer peeking" is an obscure operating system feature, and so
-          when it is not available, we have to do it ourselves by
-          managing our own internal buffer at a level below ttinc(),
-          ttinl(), etc, as in the UNIX version (non-FIONREAD case).
-
-          An external global variable, clsondisc, if nonzero, means that
-          if a serial connection drops (carrier on-to-off transition
-          detected by ttchk()), the device should be closed and released
-          automatically.
-
-   int
-          ttclos()
-          Closes the communication device (tty or network). If there were
-          any kind of exclusive access locks connected with the tty,
-          these are released. If the tty has a modem connection, it is
-          hung up. For true tty devices, the original tty device modes
-          are restored. Returns:
-           -1: on failure.
-            0: on success.
-
-   int
-          ttflui()
-          Flush communications input buffer. If any characters have
-          arrived but have not yet been read, discard these characters.
-          If communications input is buffered by Kermit (and it should
-          be), this function flushes Kermit's buffer as well as the
-          operating system's internal input buffer. Returns:
-           -1: on failure.
-            0: on success.
-
-   int
-          ttfluo()
-          Flush tty output buffer. If any characters have been written
-          but not actually transmitted (e.g. because the system has been
-          flow-controlled), remove them from the system's output buffer.
-          (Note, this function is not actually used, but it is
-          recommended that all C-Kermit programmers add it for future
-          use, even if it is only a dummy function that returns 0
-          always.)
-
-   int
-          ttgmdm()
-          Looks for the modem signals CTS, DSR, and CTS, and returns
-          those that are on in as its return value, in a bit mask as
-          described for ttwmdm, in which a bit is on (1) or off (0)
-          according to whether the corresponding signal is on (asserted)
-          or off (not asserted). Return values:
-           -3: Not implemented
-           -2: if the line does not have modem control
-           -1: on error
-          >=0: on success, with bit mask containing the modem signals.
-
-   long
-          ttgspd()
-          Returns the current tty speed in BITS (not CHARACTERS) per
-          second, or -1 if it is not known or if the tty is really a
-          network, or upon any kind of error. On success, the speed
-          returned is the actual number of bits per second, like 1200,
-          9600, 19200, etc.
-
-   int
-          ttgwsiz()
-          Get terminal window size. Returns -1 on error, 0 if the window
-          size can't be obtained, 1 if the window size has been
-          successfully obtained. Upon success, the external global
-          variables tt_rows and tt_cols are set to the number of screen
-          rows and number of screen columns, respectively. As this
-          function is not implemented in all ck*tio.c modules, calls to
-          it must be wrapped in #ifdef CK_TTGWSIZ..#endif. NOTE: This
-          function must be available to use the TELNET NAWS feature
-          (Negotiate About Window Size) as well as Rlogin.
-
-   int
-          tthang()
-          Hang up the current tty device. For real tty devices, turn off
-          DTR for about 1/3-1/2 second (or other length of time,
-          depending on the system). If the tty is really a network
-          connection, close it. Returns:
-           -1: on failure.
-            0: if it does not even try to hang up.
-            1: if it believes it hung up successfully.
-
-   VOID
-          ttimoff()
-          Turns off all pending timer interrupts.
-
-   int
-          ttinc(timo) int timo; (function is old, return codes are new)
-          Reads one character from the communication device. If timo is
-          greater than zero, wait the given number of seconds and then
-          time out if no character arrives, otherwise wait forever for a
-          character. Returns:
-           -3: internal error (e.g. tty modes set wrong)
-           -2: communications disconnect
-           -1: timeout or other error
-          >=0: the character that was read.
-          It is HIGHLY RECOMMENDED that ttinc() be internally buffered so
-          that calls to it are relatively inexpensive. If it is possible
-          to to implement ttinc() as a macro, all the better, for example
-          something like:
-
-  #define ttinc(t) ( (--txbufn >= 0) ? txbuf[ttbufp++] : txbufr(t) )
-
-          (see description of txbufr() below)
-
-   int
-          ttinl(dest,max,timo,eol,start,turn) int max,timo,turn; CHAR
-          *dest, eol, start;
-          ttinl() is Kermit's packet reader. Reads a packet from the
-          communications device, or up to max characters, whichever
-          occurs first. A line is a string of characters starting with
-          the start character up to and including the character given in
-          eol or until the length is exhausted, or, if turn != 0, until
-          the line turnaround character (turn) is read. If turn is 0,
-          ttinl() *should* use the packet length field to detect the end,
-          to allow for the possibility that the eol character appears
-          unprefixed in the packet data. (The turnaround character is for
-          half-duplex linemode connections.)
-
-          If timo is greater than zero, ttinl() times out if the eol
-          character is not encountered within the given number of seconds
-          and returns -1.
-
-          The characters that were input are copied into "dest" with
-          their parity bits stripped if parity is not none. The first
-          character copied into dest should be the start character, and
-          the last should be the final character of the packet (the last
-          block check character). ttinl() should also absorb and discard
-          the eol and turn characters, and any other characters that are
-          waiting to be read, up until the next start character, so that
-          subsequent calls to ttchk() will not succeed simply because
-          there are some terminators still sitting in the buffer that
-          ttinl() didn't read. This operation, if performed, MUST NOT
-          BLOCK (so if it can't be performed in a guaranteed nonblocking
-          way, don't do it).
-
-          On success, ttinl() returns the number of characters read.
-          Optionally, ttinl() can sense the parity of incoming packets.
-          If it does this, then it should set the global variable ttprty
-          accordingly. ttinl() should be coded to be as efficient as
-          possible, since it is at the "inner loop" of packet reception.
-          ttinl() returns:
-           -1: Timeout or other possibly correctable error.
-           -2: Interrupted from keyboard.
-           -3: Uncorrectable i/o error -- connection lost, configuration
-          problem, etc.
-          >=0: on success, the number of characters that were actually
-          read and placed in the dest buffer, not counting the trailing
-          null.
-
-   int
-          ttoc(c) char c;
-          Outputs the character c to the communication line. If the
-          operation fails to complete within two seconds, this function
-          returns -1. Otherwise it returns the number of characters
-          actually written to the tty (0 or 1). This function should only
-          be used for interactive, character-mode operations, like
-          terminal connection, script execution, dialer i/o, where the
-          overhead of the signals and alarms does not create a
-          bottleneck. (THIS DESCRIPTION NEEDS IMPROVEMENT -- If the
-          operation fails within a "certain amount of time"... which
-          might be dependent on the communication method, speed, etc. In
-          particular, flow-control deadlocks must be accounted for and
-          broken out of to prevent the program from hanging indefinitely,
-          etc.)
-
-   int
-          ttol(s,n) int n; char *s;
-          Kermit's packet writer. Writes the n characters of the string
-          pointed to to by s. NOTE: It is ttol's responsibility to write
-          ALL of the characters, not just some of them. Returns:
-           -1: on a possibly correctable error (so it can be retried).
-           -3: on a fatal error, e.g. connection lost.
-          >=0: on success, the actual number of characters written (the
-          specific number is not actually used for anything).
-
-   int
-          ttopen(ttname,lcl,modem,timo) char *ttname; int *lcl, modem,
-          timo;
-          Opens a tty device, if it is not already open. ttopen must
-          check to make sure the SAME device is not already open; if it
-          is, ttopen returns successfully without doing anything. If a
-          DIFFERENT device is currently open, ttopen() must call ttclos()
-          to close it before opening the new one.
-
-        Parameters:
-
-              ttname:
-                      character string - device name or network host
-                      name.
-
-              lcl:
-                      If called with lcl < 0, sets value of lcl as
-                      follows:
-                      0: the terminal named by ttname is the job's
-                      controlling terminal.
-                      1: the terminal named by ttname is not the job's
-                      controlling terminal.
-                      If the device is already open, or if the requested
-                      device can't be opened, then lcl remains (and is
-                      returned as) -1.
-
-              modem:
-                      Less than zero: this is the negative of the network
-                      type, and ttname is a network host name. Network
-                      types (from [112]ckcnet.h:
-
-  NET_TCPB 1   TCP/IP Berkeley (socket)  (implemented in [113]ckutio.c)
-  NET_TCPA 2   TCP/IP AT&T (streams)     (not yet implemented)
-  NET_DEC  3   DECnet                    (not yet implemented)
-
-                      Zero or greater: ttname is a terminal device name.
-                      Zero means a direct connection (don't use modem
-                      signals). Positive means use modem signals
-                      depending on the current setting of ttcarr (see
-                      ttscarr()).
-
-              timo:
-                      > 0: number of seconds to wait for open() to return
-                      before timing out.
-                      <=0: no timer, wait forever (e.g. for incoming
-                      call).
-                      For real tty devices, ttopen() attempts to gain
-                      exclusive access to the tty device, for example in
-                      UNIX by creating a "lockfile" (in other operating
-                      systems, like VMS, exclusive access probably
-                      requires no special action).
-
-        Side effects:
-                Copies its arguments and the tty file descriptor to
-                global variables that are available to the other
-                tty-related functions, with the lcl value altered as
-                described above. Gets all parameters and settings
-                associated with the line and puts them in a global area,
-                so that they can be restored by ttres(), e.g. when the
-                device is closed.
-
-        Returns:
-                  0: on success
-                 -5: if device is in use
-                 -4: if access to device is denied
-                 -3: if access to lock mechanism denied
-                 -2: upon timeout waiting for device to open
-                 -1: on other error
-
-   int
-          ttpkt(speed,flow,parity) long speed; int flow, parity;
-          Puts the currently open tty device into the appropriate modes
-          for transmitting and receiving Kermit packets.
-
-        Arguments:
-
-              speed:
-                      if speed > -1, and the device is a true tty device,
-                      and Kermit is in local mode, ttpkt also sets the
-                      speed.
-
-              flow:
-                      if in the range 0-3, ttpkt selects the
-                      corresponding type of flow control. Currently 0 is
-                      defined as no flow control, 1 is Xon/Xoff, and no
-                      other types are defined. If (and this is a horrible
-                      hack, but it goes back many years and will be hard
-                      to eradicate) flow is 4, then the appropriate tty
-                      modes are set for modem dialing, a special case in
-                      which we talk to a modem-controlled line without
-                      requiring carrier. If flow is 5, then we require
-                      carrier.
-
-              parity:
-                      This is simply copied into a global variable so
-                      that other functions (like ttinl, ttinc, etc) can
-                      use it.
-
-        Side effects:
-                Copies its arguments to global variables, flushes the
-                terminal device input buffer.
-
-        Returns:
-                 -1: on error.
-                  0: on success.
-
-   int
-          ttsetflow(int)
-          Enables the given type of flow control on the open serial
-          communications device immediately. Arguments are the FLO_xxx
-          values from ckcdeb.h, except FLO_DIAL, FLO_DIAX, or FLO_AUTO,
-          which are not actual flow-control types. Returns 0 on success,
-          -1 on failure.
-
-   #ifdef TTSPDLIST
-   long *
-          ttspdlist()
-          Returns a pointer to an array of longs, or NULL on failure. On
-          success, element 0 of the array contains number, n, indicating
-          how many follow. Elements 1-n are serial speeds, expressed in
-          bits per second, that are legal on this platform. The user
-          interface may use this list to construct a menu, keyword table,
-          etc.
-
-   #endif /* TTSPDLIST */
-
-   int
-          ttres()
-          Restores the tty device to the modes and settings that were in
-          effect at the time it was opened (see ttopen). Returns:
-           -1: on error.
-            0: on success.
-
-   int
-          ttruncmd(string) char * string;
-          Runs the given command on the local system, but redirects its
-          input and output to the communication (SET LINE, SET PORT, or
-          SET HOST) device. Returns:
-            0: on failure.
-            1: on success.
-
-   int
-          ttscarr(carrier) int carrier;
-          Copies its argument to a variable that is global to the other
-          tty-related functions, and then returns it. The values for
-          carrier are defined in ckcdeb.h: CAR_ON, CAR_OFF, CAR_AUTO.
-          ttopen(), ttpkt(), and ttvt() use this variable when deciding
-          how to open the tty device and what modes to select. The
-          meanings are these:
-
-   CAR_OFF: Ignore carrier at all times.
-   CAR_ON: Require carrier at all times, except when dialing. This means,
-   for example, that ttopen() could hang forever waiting for carrier if
-   it is not present.
-   CAR_AUTO: If the modem type is zero (i.e. the connection is direct),
-   this is the same as CAR_OFF. If the modem type is positive, then heed
-   carrier during CONNECT (ttvt mode), but ignore it at other times
-   (packet mode, during SET LINE, etc). Compatible with pre-5A versions
-   of C-Kermit. This should be the default carrier mode.
-
-          Kermit's DIAL command ignores the carrier setting, but
-          ttopen(), ttvt(), and ttpkt() all honor the carrier option in
-          effect at the time they are called. None of this applies to
-          remote mode (the tty device is the job's controlling terminal)
-          or to network host connections (modem type is negative).
-
-   int
-          ttsndb()
-          Sends a BREAK signal on the tty device. On a real tty device,
-          send a real BREAK lasting approximately 275 milliseconds. If
-          this is not possible, simulate a BREAK by (for example)
-          dropping down some very low baud rate, like 50, and sending a
-          bunch of null characters. On a network connection, do the
-          appropriate network protocol for BREAK. Returns:
-           -1: on error.
-            0: on success.
-
-   int
-          ttsndlb()
-          Like ttsndb(), but sends a "Long BREAK" (approx 1.5 seconds).
-          For network connections, it is identical to ttsndb().
-          Currently, this function is used only if CK_LBRK is defined (as
-          it is for UNIX and VMS).
-
-   int
-          ttsspd(cps) int cps;
-          For serial devices only, set the device transmission speed to
-          (note carefully) TEN TIMES the argument. The argument is in
-          characters per second, but transmission speeds are in bits per
-          second. cps are used rather than bps because high speeds like
-          38400 are not expressible in a 16-bit int but longs cannot be
-          used because keyword-table values are ints and not longs. If
-          the argument is 7, then the bps is 75, not 70. If the argument
-          is 888, this is a special code for 75/1200 split-speed
-          operation (75 bps out, 1200 bps in). Returns:
-           -1: on error, meaning the requested speed is not valid or
-          available.
-          >=0: on success (don't try to use this value for anything).
-
-   int
-          ttvt(speed,flow) long speed; int flow;
-          Puts the currently open tty device into the appropriate modes
-          for terminal emulation. The arguments are interpreted as in
-          ttpkt(). Side effects: ttvt() stores its arguments in global
-          variables, and sets a flag that it has been called so that
-          subsequent calls can be ignored so long as the arguments are
-          the same as in the last effective call. Other functions, such
-          as ttopen(), ttclose(), ttres(), ttvt(), etc, that change the
-          tty device in any way must unset this flag. In UNIX Kermit,
-          this flag is called tvtflg.
-
-   int
-          ttwmdm(mdmsig,timo) int mdmsig, timo;
-          Waits up to timo seconds for all of the given modem signals to
-          appear. mdmsig is a bit mask, in which a bit is on (1) or off
-          (0) according to whether the corresponding signal is to be
-          waited for. These symbols are defined in ckcdeb.h:
-            BM_CTS (bit 0) means wait for Clear To Send
-            BM_DSR (bit 1) means wait for Data Set Ready
-            BM_DCD (bit 2) means wait for Carrier Detect
-          Returns:
-           -3: Not implemented.
-           -2: This line does not have modem control.
-           -1: Timeout: time limit exceeded before all signals were
-          detected.
-            1: Success.
-
-   int
-          ttxin(n,buf) int n; CHAR *buf;
-          Reads x characters from the tty device into the specified buf,
-          stripping parity if parity is not none. This call waits
-          forever, there is no timeout. This function is designed to be
-          called only when you know that at least x characters are
-          waiting to be read (as determined, for example, by ttchk()).
-          This function should use the same buffer as ttinc().
-
-   int
-          txbufr(timo) int timo;
-          Reads characters into the internal communications input buffer.
-          timo is a timeout interval, in seconds. 0 means no timeout,
-          wait forever. Called by ttinc() (and possibly ttxin() and
-          ttinl()) when the communications input buffer is empty. The
-          buffer should be called ttxbuf[], its length is defined by the
-          symbol TXBUFL. The global variable txbufn is the number of
-          characters available to be read from ttxbuf[], and txbufp is
-          the index of the next character to be read. Should not be
-          called if txbufn > 0, in which case the buffer does not need
-          refilling. This routine returns:
-            -2: Communications disconnect
-            -1: Timeout
-          >=0: A character (0 - 255) On success, the first character that
-          was read, with the variables txbufn and txbufp set
-          appropriately for any remaining characters.
-          NOTE: Currently this routine is used internally only by the
-          UNIX and VMS versions. The aim is to make it available to all
-          versions so there is one single coherent and efficient way of
-          reading from the communications device or network.
-
-    4.E.2.6. Miscellaneous system-dependent functions
-
-   VOID
-          ztime(s) char **s;
-          Returns a pointer, s, to the current date-and-time string in s.
-          This string must be in the fixed-field format associated with
-          the C runtime asctime() function, like: "Sun Sep 16 13:23:45
-          1973\n" so that callers of this function can extract the
-          different fields. The pointer value is filled in by ztime, and
-          the data it points to is not safe, so should be copied to a
-          safe place before use. ztime() has no return value. As a side
-          effect, this routine can also fill in the following two
-          external variables (which must be defined in the
-          system-dependendent modules for each platform):
-            long ztusec: Fraction of seconds of clock time, microseconds.
-            long ztmsec: Fraction of seconds of clock time, milliseconds.
-          If these variables are not set by zstime(), they remain at
-          their initial value of -1L.
-
-   int
-          gtimer()
-          Returns the current value of the elapsed time counter in
-          seconds (see rtimer), or 0 on any kind of error.
-
-   #ifdef GFTIMER
-          CKFLOAT
-          gftimer()
-          Returns the current value of the elapsed time counter in
-          seconds, as a floating point number, capable of representing
-          not only whole seconds, but also the fractional part, to the
-          millisecond or microsecond level, whatever precision is
-          available. Requires a function to get times at subsecond
-          precision, as well as floating-point support. That's why it's
-          #ifdef'd.
-
-   #endif /* GFTIMER */
-
-   int
-          msleep(m) int m;
-          Sleeps (pauses, does nothing) for m milliseconds (a millisecond
-          is one thousandth of a second). Returns:
-           -1: on failure.
-            0: on success.
-
-   VOID
-          rtimer()
-          Sets the elapsed time counter to zero. If you want to time how
-          long an operation takes, call rtimer() when it starts and
-          gtimer when it ends. rtimer() has no return value.
-
-   #ifdef GFTIMER
-          VOID
-          rftimer()
-          Sets the elapsed time counter to zero. If you want to time how
-          long an operation takes, call rftimer() when it starts and
-          gftimer when it ends. rftimer() has no return value. Note:
-          rftimer() is to be used with gftimer() and rtimer() is to be
-          used with gtimer(). See the rftimer() description.
-
-   #endif /* GFTIMER */
-
-   int
-          sysinit()
-          Does whatever needs doing upon program start. In particular, if
-          the program is running in any kind of privileged mode, turns
-          off the privileges (see priv_ini()). Returns:
-           -1: on error.
-            0: on success.
-
-   int
-          syscleanup()
-          Does whatever needs doing upon program exit. Returns:
-           -1: on error.
-            0: on success.
-
-   int
-          psuspend()
-          Suspends the Kermit process, puts it in the background so it
-          can be continued ("foregrounded") later. Returns:
-           -1: if this function is not supported.
-            0: on success.
-
-   [ [114]Contents ] [ [115]C-Kermit ] [ [116]Kermit Home ]
-    ________________________________________________________________________
-
-  4.F. Group F: Network Support
-
-   As of version 5A, C-Kermit includes support for several networks.
-   Originally, this was just worked into the ttopen(), ttclos(), ttinc(),
-   ttinl(), and similar routines in [117]ckutio.c. But this made it
-   impossible to share this code with non-UNIX versions, like VMS,
-   AOS/VS, OS/2, etc. So as of edit 168, network code has been separated
-   out into its own module and header file, ckcnet.c and ckcnet.h:
-
-     [118]ckcnet.h: Network-related symbol definitions.
-     [119]ckcnet.c: Network i/o (TCP/IP, X.25, etc), shared by most
-   platforms.
-     [120]cklnet.c: Network i/o (TCP/IP, X.25, etc) specific to Stratus
-   VOS.
-
-   The routines and variables in these modules fall into two categories:
-
-    1. Support for specific network packages like SunLink X.25 and TGV
-       MultiNet, and:
-    2. support for specific network virtual terminal protocols like CCITT
-       X.3 and TCP/IP Telnet.
-
-   Category (1) functions are analogs to the tt*() functions, and have
-   names like netopen, netclos, nettinc, etc. Group A-D modules do not
-   (and must not) know anything about these functions -- they continue to
-   call the old Group E functions (ttopen, ttinc, etc). Category (2)
-   functions are protocol specific and have names prefixed by a protocol
-   identifier, like tn for telnet x25 for X.25.
-
-   ckcnet.h contains prototypes for all these functions, as well as
-   symbol definitions for network types, protocols, and network- and
-   protocol- specific symbols, as well as #includes for the header files
-   necessary for each network and protocol.
-
-   The following functions are to be provided for networks that do not
-   use normal system i/o (open, read, write, close):
-
-   int
-          netopen()
-          To be called from within ttopen() when a network connection is
-          requested. Calling conventions and purpose same as Group E
-          ttopen().
-
-   int
-          netclos()
-          To be called from within ttclos() when a network connection is
-          being closed. Calling conventions and purpose same as Group E
-          ttclos().
-
-   int
-          nettchk()
-          To be called from within ttchk(). Calling conventions and
-          purpose same as Group E ttchk().
-
-   int
-          netflui()
-          To be called from within ttflui(). Calling conventions and
-          purpose same as Group E ttflui().
-
-   int
-          netbreak()
-          To send a network break (attention) signal. Calling conventions
-          and purpose same as Group E ttsndbrk().
-
-   int
-          netinc()
-          To get a character from the network. Calling conventions same
-          as Group E ttsndbrk().
-
-   int
-          nettoc()
-          Send a "character" (byte) to the network. Calling conventions
-          same as Group E ttoc().
-
-   int
-          nettol()
-          Send a "line" (sequence of bytes) to the network. Calling
-          conventions same as Group E ttol().
-
-   Conceivably, some systems support network connections simply by
-   letting you open a device of a certain name and letting you do i/o to
-   it. Others (like the Berkeley sockets TCP/IP library on UNIX) require
-   you to open the connection in a special way, but then do normal i/o
-   (read, write). In such a case, you would use netopen(), but you would
-   not use nettinc, nettoc, etc.
-
-   VMS TCP/IP products have their own set of functions for all network
-   operations, so in that case the full range of netxxx() functions is
-   used.
-
-   The technique is to put a test in each corresponding ttxxx() function
-   to see if a network connection is active (or is being requested), test
-   for which kind of network it is, and if necessary route the call to
-   the corresponding netxxx() function. The netxxx() function must also
-   contain code to test for the network type, which is available via the
-   global variable ttnet.
-
-   [ [121]Contents ] [ [122]C-Kermit ] [ [123]Kermit Home ]
-      ______________________________________________________________________
-
-    4.F.1. Telnet Protocol
-
-   (This section needs a great deal of updating...)
-
-   As of edit 195, Telnet protocol is split out into its own files, since
-   it can be implemented in remote mode, which does not have a network
-   connection:
-
-      [124]ckctel.h: Telnet protocol symbol definitions.
-      [125]ckctel.c: Telnet protocol.
-
-   The Telnet protocol is supported by the following variables and
-   routines:
-
-   int tn_init
-          Nonzero if telnet protocol initialized, zero otherwise.
-
-   int
-          tn_init()
-          Initialize the telnet protocol (send initial options).
-
-   int
-          tn_sopt()
-          Send a telnet option.
-
-   int
-          tn_doop()
-          Receive and act on a telnet option from the remote.
-
-   int
-          tn_sttyp()
-          Send terminal type using telnet protocol.
-      ______________________________________________________________________
-
-    4.F.2. FTP Protocol
-
-   (To be filled in...)
-      ______________________________________________________________________
-
-    4.F.3. HTTP Protocol
-
-   (To be filled in...)
-      ______________________________________________________________________
-
-    4.F.4. X.25 Networks
-
-   These routines were written SunLink X.25 and have since been adapted
-   to at least on one other: IBM AIXLink/X.25.
-
-   int
-          x25diag()
-          Reads and prints X.25 diagnostics
-
-   int
-          x25oobh()
-          X.25 out of band signal handler
-
-   int
-          x25intr()
-          Sends X.25 interrupt packet
-
-   int
-          x25reset()
-          Resets X.25 virtual circuit
-
-   int
-          x25clear()
-          Clear X.25 virtual circuit
-
-   int
-          x25stat()
-          X.25 status
-
-   int
-          setqbit()
-          Sets X.25 Q-bit
-
-   int
-          resetqbit()
-          Resets X.25 Q-bit
-
-   int
-          x25xin()
-          Reads n characters from X.25 circuit.
-
-   int
-          x25inl()
-          Read a Kermit packet from X.25 circuit.
-
-   [ [126]Contents ] [ [127]C-Kermit ] [ [128]Kermit Home ]
-      ______________________________________________________________________
-
-    4.F.5. Adding New Network Types
-
-   Example: Adding support for IBM X.25 and Hewlett Packard X.25. First,
-   add new network type symbols for each one. There are already some
-   network types defined for other X.25 packages:
-
-  NET_SX25 is the network-type ID for SunLink X.25.
-  NET_VX25 is the network-type ID for VOS X.25.
-
-   So first you should new symbols for the new network types, giving them
-   the next numbers in the sequence, e.g.:
-
-#define NET_HX25 11                     /* Hewlett-Packard X.25 */
-#define NET_IX25 12                     /* IBM X.25 */
-
-   This is in ckcnet.h.
-
-   Then we need symbols to say that we are actually compiling in the code
-   for these platforms. These would be defined on the cc command line:
-
-  -DIBMX25  (for IBM)
-  -DHPX25   (for HP)
-
-   So we can build C-Kermit versions for AIX and HP-UX both with and
-   without X.25 support (since not all AIX and IBM systems have the
-   needed libraries, and so an executable that was linked with them might
-   no load).
-
-   Then in ckcnet.h:
-
-#ifdef IBMX25
-#define ANYX25
-#endif /* IBMX25 */
-
-#ifdef HPX25
-#define ANYX25
-#endif /* HPX25 */
-
-   And then use ANYX25 for code that is common to all of them, and IBMX25
-   or HPX25 for code specific to IBM or HP.
-
-   It might also happen that some code can be shared between two or more
-   of these, but not the others. Suppose, for example, that you write
-   code that applies to both IBM and HP, but not Sun or VOS X.25. Then
-   you add the following definition to ckcnet.h:
-
-#ifndef HPORIBMX25
-#ifdef HPX25
-#define HPORIBMX25
-#else
-#ifdef IBMX25
-#define HPORIBMX25
-#endif /* IBMX25 */
-#endif /* HPX25 */
-#endif /* HPORIBMX25 */
-
-   You can NOT use constructions like "#if defined (HPX25 || IBMX25)";
-   they are not portable.
-
-   [ [129]Contents ] [ [130]C-Kermit ] [ [131]Kermit Home ]
-    ________________________________________________________________________
-
-  4.G. Group G: Formatted Screen Support
-
-   So far, this is used only for the fullscreen local-mode file transfer
-   display. In the future, it might be extended to other uses. The
-   fullscreen display code is in and around the routine screenc() in
-   [132]ckuusx.c.
-
-   In the UNIX version, we use the curses library, plus one call from the
-   termcap library. In other versions (OS/2, VMS, etc) we insert dummy
-   routines that have the same names as curses routines. So far, there
-   are two methods for simulating curses routines:
-
-    1. In VMS, we use the Screen Management Library (SMG), and insert
-       stubs to convert curses calls into SMG calls.
-    2. In OS/2, we use the MYCURSES code, in which the stub routines
-       actually emit the appropriate escape sequences themselves.
-
-   Here are the stub routines:
-
-   int
-          tgetent(char *buf, char *term)
-          Arguments are ignored. Returns 1 if the user has a supported
-          terminal type, 0 otherwise. Sets a global variable (for
-          example, "isvt52" or "isdasher") to indicate the terminal type.
-
-   VOID
-          move(int row, int col)
-          Sends the escape sequence to position the cursor at the
-          indicated row and column. The numbers are 0-based, e.g. the
-          home position is 0,0.
-
-   int
-          clear()
-          Sends the escape sequence to clear the screen.
-
-   int
-          clrtoeol()
-          Sends the escape sequence to clear from the current cursor
-          position to the end of the line.
-
-   In the MYCURSES case, code must be added to each of the last three
-   routines to emit the appropriate escape sequences for a new terminal
-   type.
-
-   clearok(curscr), wrefresh()
-          In real curses, these two calls are required to refresh the
-          screen, for example after it was fractured by a broadcast
-          message. These are useful only if the underlying screen
-          management service keeps a copy of the entire screen, as curses
-          and SMG do. C-Kermit does not do this itself.
-
-   [ [133]Contents ] [ [134]C-Kermit ] [ [135]Kermit Home ]
-    ________________________________________________________________________
-
-  4.H. Group H: Pseudoterminal Support
-
-   (To be filled in...)
-    ________________________________________________________________________
-
-  4.I. Group I: Security
-
-   (To be filled in...)
-
-   [ [136]Contents ] [ [137]C-Kermit ] [ [138]Kermit Home ]
-    ________________________________________________________________________
-
-  APPENDIX I. FILE PERMISSIONS
-
-  I.1. Format of System-Dependent File Permissions in A-Packets
-
-   The format of this field (the "," attribute) is interpreted according
-   to the System ID ("." Attribute).
-
-   For UNIX (System ID = U1), it's the familiar 3-digit octal number, the
-   low-order 9 bits of the filemode: Owner, Group, World, e.g. 660 =
-   read/write access for owner and group, none for world, recorded as a
-   3-digit octal string. High-order UNIX permission bits are not
-   transmitted.
-
-   For VMS (System ID = D7), it's a 4-digit hex string, representing the
-   16-bit file protection WGOS fields (World,Group,Owner,System), in that
-   order (which is the reverse of how they're shown in a directory
-   listing); in each field, Bit 0 = Read, 1 = Write, 2 = Execute, 3 =
-   Delete. A bit value of 0 means permission is granted, 1 means
-   permission is denied. Sample:
-
-  r-01-00-^A/!FWERMIT.EXE'"
-  s-01-00-^AE!Y/amd/watsun/w/fdc/new/wermit.exe.DV
-  r-02-01-^A]"A."D7""B8#119980101 18:14:05!#8531&872960,$A20B-!7(#512@ #.Y
-  s-02-01-^A%"Y.5!
-
-   A VMS directory listing shows the file's protection as (E,RWED,RED,RE)
-   which really means (S=E,O=RWED,G=RED,W=RE), which is reverse order
-   from the internal storage, so (RE,RED,RWED,E). Now translate each
-   letter to its corresponding bit:
-
-  RE=0101, RED=1101, RWED=1111, E=0010
-
-   Now reverse the bits:
-
-  RE=1010, RED=0010, RWED=0000, E=1101
-
-   This gives the 16-bit quantity:
-
-  1010001000001101
-
-   This is the internal representation of the VMS file permission; in
-   hex:
-
-  A20B
-
-   as shown in the sample packet above.
-
-   The VMS format probably would also apply to RSX or any other FILES-11
-   system.
-
-  I.2. Handling of Generic Protection
-
-   To be used when the two systems are different (and/or do not recognize
-   or understand each other's local protection codes).
-
-   First of all, the book is wrong. This should not be the World
-   protection, but the Owner protection. The other fields should be set
-   according to system defaults (e.g. UNIX umask, VMS default protection,
-   etc), except that no non-Owner field should give more permissions than
-   the Owner field.
-
-   [ [139]Top ] [ [140]Contents ] [ [141]C-Kermit Home ] [ [142]Kermit
-   Home ]
-     _________________________________________________________________
-
-
-    C-Kermit Program Logic Manual / [143]The Kermit Project /
-    [144]Columbia University / [145]kermit@columbia.edu / 10 April 2004
-
-References
-
-   1. http://www.columbia.edu/kermit/
-   2. http://www.columbia.edu/
-   3. http://www.columbia.edu/kermit/ckcplm.html
-   4. http://www.columbia.edu/kermit/ckermit.html
-   5. http://www.columbia.edu/kermit/index.html
-   6. http://www.columbia.edu/kermit/ckcplm.html#x1
-   7. http://www.columbia.edu/kermit/ckcplm.html#x2
-   8. http://www.columbia.edu/kermit/ckcplm.html#x3
-   9. http://www.columbia.edu/kermit/ckcplm.html#x4
-  10. http://www.columbia.edu/kermit/ckcplm.html#x4.A
-  11. http://www.columbia.edu/kermit/ckcplm.html#x4.B
-  12. http://www.columbia.edu/kermit/ckcplm.html#x4.C
-  13. http://www.columbia.edu/kermit/ckcplm.html#x4.D
-  14. http://www.columbia.edu/kermit/ckcplm.html#x4.E
-  15. http://www.columbia.edu/kermit/ckcplm.html#x4.F
-  16. http://www.columbia.edu/kermit/ckcplm.html#x4.G
-  17. http://www.columbia.edu/kermit/ckcplm.html#x4.H
-  18. http://www.columbia.edu/kermit/ckcplm.html#x4.I
-  19. http://www.columbia.edu/kermit/ckcplm.html#xa1
-  20. http://www.columbia.edu/kermit/ckcplm.html#contents
-  21. http://www.columbia.edu/kermit/ckcplm.html#contents
-  22. http://www.columbia.edu/kermit/ckermit.html
-  23. http://www.columbia.edu/kermit/index.html
-  24. ftp://kermit.columbia.edu/kermit/c-kermit/ckcpro.w
-  25. http://www.columbia.edu/kermit/ckcplm.html#contents
-  26. http://www.columbia.edu/kermit/ckermit.html
-  27. http://www.columbia.edu/kermit/index.html
-  28. http://www.columbia.edu/kermit/ckcplm.html#x3.2
-  29. http://www.columbia.edu/kermit/ckcplm.html#contents
-  30. http://www.columbia.edu/kermit/ckermit.html
-  31. http://www.columbia.edu/kermit/index.html
-  32. http://www.columbia.edu/kermit/ckcplm.html#x4.A
-  33. http://www.columbia.edu/kermit/ckcplm.html#contents
-  34. http://www.columbia.edu/kermit/ckermit.html
-  35. http://www.columbia.edu/kermit/index.html
-  36. http://www.columbia.edu/kermit/ckcplm.html#contents
-  37. http://www.columbia.edu/kermit/ckermit.html
-  38. http://www.columbia.edu/kermit/index.html
-  39. http://www.columbia.edu/kermit/ckcplm.html#contents
-  40. http://www.columbia.edu/kermit/ckermit.html
-  41. http://www.columbia.edu/kermit/index.html
-  42. ftp://kermit.columbia.edu/kermit/c-kermit/ckclib.h
-  43. ftp://kermit.columbia.edu/kermit/c-kermit/ckclib.c
-  44. http://www.columbia.edu/kermit/ckcplm.html#x3.1
-  45. http://www.columbia.edu/kermit/ckcplm.html#contents
-  46. http://www.columbia.edu/kermit/ckermit.html
-  47. http://www.columbia.edu/kermit/index.html
-  48. ftp://kermit.columbia.edu/kermit/c-kermit/ckcsym.h
-  49. ftp://kermit.columbia.edu/kermit/c-kermit/ckcasc.h
-  50. ftp://kermit.columbia.edu/kermit/c-kermit/ckcsig.h
-  51. ftp://kermit.columbia.edu/kermit/c-kermit/ckcdeb.h
-  52. ftp://kermit.columbia.edu/kermit/c-kermit/ckcker.h
-  53. ftp://kermit.columbia.edu/kermit/c-kermit/ckcxla.h
-  54. ftp://kermit.columbia.edu/kermit/c-kermit/ckcmai.c
-  55. ftp://kermit.columbia.edu/kermit/c-kermit/ckcpro.w
-  56. ftp://kermit.columbia.edu/kermit/c-kermit/ckcfns.c
-  57. ftp://kermit.columbia.edu/kermit/c-kermit/ckcfn2.c
-  58. ftp://kermit.columbia.edu/kermit/c-kermit/ckcfn3.c
-  59. http://www.columbia.edu/kermit/ckcplm.html#x4.B
-  60. http://www.columbia.edu/kermit/ckcplm.html#x4.E
-  61. http://www.columbia.edu/kermit/ckcplm.html#x4.D
-  62. http://www.columbia.edu/kermit/ckcplm.html#contents
-  63. http://www.columbia.edu/kermit/ckermit.html
-  64. http://www.columbia.edu/kermit/index.html
-  65. http://www.columbia.edu/kermit/ckcplm.html#x4.B
-  66. ftp://kermit.columbia.edu/kermit/c-kermit/ckuxla.c
-  67. ftp://kermit.columbia.edu/kermit/c-kermit/ckuxla.h
-  68. ftp://kermit.columbia.edu/kermit/c-kermit/ckcxla.h
-  69. ftp://kermit.columbia.edu/kermit/c-kermit/ckuxla.h
-  70. ftp://kermit.columbia.edu/kermit/c-kermit/ckmxla.h
-  71. ftp://kermit.columbia.edu/kermit/c-kermit/ck?xla
-  72. ftp://kermit.columbia.edu/kermit/c-kermit/ckcuni.h
-  73. ftp://kermit.columbia.edu/kermit/c-kermit/ckcuni.c
-  74. http://www.columbia.edu/kermit/ckcplm.html#contents
-  75. http://www.columbia.edu/kermit/ckermit.html
-  76. http://www.columbia.edu/kermit/index.html
-  77. http://www.columbia.edu/kermit/ckcplm.html#x4.B
-  78. ftp://kermit.columbia.edu/kermit/c-kermit/ckucmd.h
-  79. ftp://kermit.columbia.edu/kermit/c-kermit/ckucmd.c
-  80. http://www.columbia.edu/kermit/ckcplm.html#x4.E
-  81. ftp://kermit.columbia.edu/kermit/c-kermit/ckuusr.h
-  82. ftp://kermit.columbia.edu/kermit/c-kermit/ckuusr.c
-  83. ftp://kermit.columbia.edu/kermit/c-kermit/ckuus2.c
-  84. ftp://kermit.columbia.edu/kermit/c-kermit/ckuus3.c
-  85. ftp://kermit.columbia.edu/kermit/c-kermit/ckuus4.c
-  86. ftp://kermit.columbia.edu/kermit/c-kermit/ckuusy.c
-  87. ftp://kermit.columbia.edu/kermit/c-kermit/ckuusx.c
-  88. ftp://kermit.columbia.edu/kermit/c-kermit/ckuver.h
-  89. ftp://kermit.columbia.edu/kermit/c-kermit/ckuscr.c
-  90. ftp://kermit.columbia.edu/kermit/c-kermit/ckudia.c
-  91. ftp://kermit.columbia.edu/kermit/c-kermit/ckucon.c
-  92. ftp://kermit.columbia.edu/kermit/c-kermit/ckucns.c
-  93. http://www.columbia.edu/kermit/ckcplm.html#x4.E
-  94. ftp://kermit.columbia.edu/kermit/c-kermit/ckcmai.c
-  95. http://www.columbia.edu/kermit/ckcplm.html#contents
-  96. http://www.columbia.edu/kermit/ckermit.html
-  97. http://www.columbia.edu/kermit/index.html
-  98. ftp://kermit.columbia.edu/kermit/c-kermit/ckufio.c
-  99. ftp://kermit.columbia.edu/kermit/c-kermit/ckutio.c
- 100. ftp://kermit.columbia.edu/kermit/c-kermit/ckusig.c
- 101. ftp://kermit.columbia.edu/kermit/c-kermit/ckvfio.c
- 102. ftp://kermit.columbia.edu/kermit/c-kermit/ckusig.c
- 103. ftp://kermit.columbia.edu/kermit/c-kermit/ckcmai.c
- 104. http://www.columbia.edu/kermit/ckcplm.html#contents
- 105. http://www.columbia.edu/kermit/ckermit.html
- 106. http://www.columbia.edu/kermit/index.html
- 107. ftp://kermit.columbia.edu/kermit/c-kermit/ckutio.c
- 108. ftp://kermit.columbia.edu/kermit/c-kermit/ckvtio.c
- 109. http://www.columbia.edu/kermit/ckcplm.html#x2
- 110. http://www.columbia.edu/kermit/ckcplm.html#xa1
- 111. http://www.columbia.edu/kermit/ckuins.html
- 112. ftp://kermit.columbia.edu/kermit/c-kermit/ckcnet.h
- 113. ftp://kermit.columbia.edu/kermit/c-kermit/ckutio.c
- 114. http://www.columbia.edu/kermit/ckcplm.html#contents
- 115. http://www.columbia.edu/kermit/ckermit.html
- 116. http://www.columbia.edu/kermit/index.html
- 117. ftp://kermit.columbia.edu/kermit/c-kermit/ckutio.c
- 118. ftp://kermit.columbia.edu/kermit/c-kermit/ckcnet.h
- 119. ftp://kermit.columbia.edu/kermit/c-kermit/ckcnet.c
- 120. ftp://kermit.columbia.edu/kermit/c-kermit/cklnet.c
- 121. http://www.columbia.edu/kermit/ckcplm.html#contents
- 122. http://www.columbia.edu/kermit/ckermit.html
- 123. http://www.columbia.edu/kermit/index.html
- 124. ftp://kermit.columbia.edu/kermit/c-kermit/ckctel.h
- 125. ftp://kermit.columbia.edu/kermit/c-kermit/ckctel.c
- 126. http://www.columbia.edu/kermit/ckcplm.html#contents
- 127. http://www.columbia.edu/kermit/ckermit.html
- 128. http://www.columbia.edu/kermit/index.html
- 129. http://www.columbia.edu/kermit/ckcplm.html#contents
- 130. http://www.columbia.edu/kermit/ckermit.html
- 131. http://www.columbia.edu/kermit/index.html
- 132. ftp://kermit.columbia.edu/kermit/c-kermit/ckuusx.c
- 133. http://www.columbia.edu/kermit/ckcplm.html#contents
- 134. http://www.columbia.edu/kermit/ckermit.html
- 135. http://www.columbia.edu/kermit/index.html
- 136. http://www.columbia.edu/kermit/ckcplm.html#contents
- 137. http://www.columbia.edu/kermit/ckermit.html
- 138. http://www.columbia.edu/kermit/index.html
- 139. http://www.columbia.edu/kermit/ckcplm.html#top
- 140. http://www.columbia.edu/kermit/ckcplm.html#contents
- 141. http://www.columbia.edu/kermit/ckermit.html
- 142. http://www.columbia.edu/kermit/index.html
- 143. http://www.columbia.edu/kermit/index.html
- 144. http://www.columbia.edu/
- 145. mailto:kermit@columbia.edu
diff --git a/ckcpro.c b/ckcpro.c
new file mode 100644 (file)
index 0000000..3c51b6b
--- /dev/null
+++ b/ckcpro.c
@@ -0,0 +1,3814 @@
+
+/* WARNING -- This C source program generated by Wart preprocessor. */
+/* Do not edit this file; edit the Wart-format source file instead, */
+/* and then run it through Wart to produce a new C source file.     */
+
+/* Wart Version Info: */
+char *wartv = "Wart Version 2.14, 10 Nov 1999";
+
+char *protv =                                                     /* -*-C-*- */
+"C-Kermit Protocol Module 8.0.160, 12 Aug 2007";
+
+int kactive = 0;                       /* Kermit protocol is active */
+
+#define PKTZEROHACK
+
+/* C K C P R O  -- C-Kermit Protocol Module, in Wart preprocessor notation. */
+/*
+  Author: Frank da Cruz <fdc@columbia.edu>,
+  Columbia University Academic Information Systems, New York City.
+
+  Copyright (C) 1985, 2007,
+    Trustees of Columbia University in the City of New York.
+    All rights reserved.  See the C-Kermit COPYING.TXT file or the
+    copyright text in the ckcmai.c module for disclaimer and permissions.
+*/
+#ifndef NOXFER
+#include "ckcsym.h"
+#include "ckcdeb.h"
+#include "ckcasc.h"
+#include "ckcker.h"
+#ifdef OS2
+#ifndef NT
+#define INCL_NOPM
+#define INCL_VIO                       /* Needed for ckocon.h */
+#include <os2.h>
+#undef COMMENT
+#endif /* NT */
+#include "ckocon.h"
+#endif /* OS2 */
+
+/*
+ Note -- This file may also be preprocessed by the UNIX Lex program, but
+ you must indent the above #include statements before using Lex, and then
+ restore them to the left margin in the resulting C program before compilation.
+ Also, the invocation of the "wart()" function below must be replaced by an
+ invocation  of the "yylex()" function.  It might also be necessary to remove
+ comments in the (%)(%)...(%)(%) section.
+*/
+
+/* State definitions for Wart (or Lex) */
+#define ipkt 1
+#define rfile 2
+#define rattr 3
+#define rdpkt 4
+#define ssinit 5
+#define ssfile 6
+#define ssattr 7
+#define ssdata 8
+#define sseof 9
+#define sseot 10
+#define serve 11
+#define generic 12
+#define get 13
+#define rgen 14
+#define ssopkt 15
+#define ropkt 16
+
+_PROTOTYP(static VOID xxproto,(void));
+_PROTOTYP(static VOID wheremsg,(void));
+_PROTOTYP(int wart,(void));
+_PROTOTYP(static int sgetinit,(int,int));
+_PROTOTYP(int sndspace,(int));
+
+/* External C-Kermit variable declarations */
+  extern char *versio, *srvtxt, *cmarg, *cmarg2, **cmlist, *rf_err;
+  extern char * rfspec, * sfspec, * srfspec, * rrfspec;
+  extern char * prfspec, * psfspec, * psrfspec, * prrfspec;
+  extern char *cdmsgfile[];
+  extern char * snd_move, * snd_rename, * srimsg;
+  extern char filnam[], ofilnam[], fspec[], ttname[], ofn1[];
+  extern CHAR sstate, *srvptr, *data;
+  extern int timint, rtimo, nfils, hcflg, xflg, flow, mdmtyp, network;
+  extern int oopts, omode, oname, opath, nopush, isguest, xcmdsrc, rcdactive;
+  extern int rejection, moving, fncact, bye_active, urserver, fatalio;
+  extern int protocol, prefixing, filcnt, carrier, fnspath, interrupted;
+  extern int recursive, inserver, nzxopts, idletmo, srvidl, xfrint;
+  extern struct ck_p ptab[];
+  extern int remfile, rempipe, xferstat, filestatus, wearealike, fackpath;
+  extern int patterns, filepeek, gnferror;
+  extern char * remdest;
+
+#ifdef PKTZEROHACK
+#define PKTZEROLEN 32
+static char ipktack[PKTZEROLEN];
+static int ipktlen = 0;
+#endif /* PKTZEROHACK */
+
+static int s_timint = -1;              /* For saving timeout value */
+static int myjob = 0;
+static int havefs = 0;
+#ifdef CK_LOGIN
+static int logtries = 0;
+#endif /* CK_LOGIN */
+
+static int cancel = 0;
+int fackbug = 0;
+
+#ifdef STREAMING
+extern int streaming, streamok;
+
+static VOID
+streamon() {
+    if (streamok) {
+       debug(F100,"streamon","",0);
+       streaming = 1;
+       timint = 0;                     /* No timeouts while streaming. */
+    }
+}
+
+#ifdef COMMENT                         /* (not used) */
+static VOID
+streamoff() {
+    if (streaming) {
+       debug(F100,"streamoff","",0);
+       streaming = 0;
+       timint = s_timint;              /* Restore timeout */
+    }
+}
+#endif /* COMMENT */
+#else /* STREAMING */
+#define streamon()
+#define streamoff()
+#endif /* STREAMING */
+
+#ifndef NOSPL
+_PROTOTYP( int addmac, (char *, char *) );
+_PROTOTYP( int zzstring, (char *, char **, int *) );
+#endif /* NOSPL */
+#ifndef NOICP
+_PROTOTYP( int cmdsrc, (void) );
+#endif /* NOICP */
+
+#ifndef NOSERVER
+  extern char * x_user, * x_passwd, * x_acct;
+  extern int x_login, x_logged;
+#endif /* NOSERVER */
+
+#include "ckcnet.h"
+
+#ifdef TNCODE
+  extern int ttnproto;                 /* Network protocol */
+#endif /* TNCODE */
+
+#ifdef CK_SPEED
+  extern short ctlp[];                 /* Control-character prefix table */
+#endif /* CK_SPEED */
+
+#ifdef TNCODE
+  extern int tn_b_nlm, tn_b_xfer, tn_nlm;
+#ifdef CK_ENCRYPTION
+  extern int tn_no_encrypt_xfer;
+#endif /* CK_ENCRYPTION */
+#endif /* TNCODE */
+
+#ifdef TCPSOCKET
+#ifndef NOLISTEN
+  extern int tcpsrfd;
+#endif /* NOLISTEN */
+#endif /* TCPSOCKET */
+
+  extern int cxseen, czseen, server, srvdis, local, displa, bctu, bctr, bctl;
+  extern int quiet, tsecs, parity, backgrd, nakstate, atcapu, wslotn, winlo;
+  extern int wslots, success, xitsta, rprintf, discard, cdtimo, keep, fdispla;
+  extern int timef, stdinf, rscapu, sendmode, epktflg, epktrcvd, epktsent;
+  extern int binary, fncnv;
+  extern long speed, ffc, crc16, calibrate, dest;
+#ifdef COMMENT
+  extern char *TYPCMD, *DIRCMD, *DIRCM2;
+#endif /* COMMENT */
+#ifndef OS2
+  extern char *SPACMD, *SPACM2, *WHOCMD;
+#endif /* OS2 */
+  extern CHAR *rdatap;
+  extern struct zattr iattr;
+
+#ifdef VMS
+  extern int batch;
+#endif /* VMS */
+
+#ifdef GFTIMER
+  extern CKFLOAT fptsecs;
+#endif /* GFTIMER */
+
+  extern CHAR *srvcmd;
+  extern CHAR *epktmsg;
+
+#ifdef CK_TMPDIR
+extern int f_tmpdir;                   /* Directory changed temporarily */
+extern char savdir[];                  /* For saving current directory */
+extern char * dldir;
+#endif /* CK_TMPDIR */
+
+  extern int query;                    /* Query-active flag */
+#ifndef NOSPL
+  extern int cmdlvl;
+  char querybuf[QBUFL+1] = { NUL, NUL }; /* QUERY response buffer */
+  char *qbufp = querybuf;              /* Pointer to it */
+  int qbufn = 0;                       /* Length of data in it */
+#else
+  extern int tlevel;
+#endif /* NOSPL */
+
+#ifndef NOICP
+  extern int escape;
+#endif /* NOICP */
+/*
+  If the following flag is nonzero when the protocol module is entered,
+  then server mode persists for exactly one transaction, rather than
+  looping until BYE or FINISH is received.
+*/
+extern int justone;
+
+static int r_save = -1;
+static int p_save = -1;
+
+/* Function to let remote-mode user know where their file(s) went */
+
+int whereflg = 1;                      /* Unset with SET XFER REPORT */
+
+static VOID
+wheremsg() {
+    extern int quiet, filrej;
+    int n;
+    n = filcnt - filrej;
+    debug(F101,"wheremsg n","",n);
+
+    debug(F110,"wheremsg prfspec",prfspec,0);
+    debug(F110,"wheremsg rfspec",rfspec,0);
+    debug(F110,"wheremsg psfspec",psfspec,0);
+    debug(F110,"wheremsg sfspec",sfspec,0);
+
+    debug(F110,"wheremsg prrfspec",prrfspec,0);
+    debug(F110,"wheremsg rrfspec",rrfspec,0);
+    debug(F110,"wheremsg psrfspec",psrfspec,0);
+    debug(F110,"wheremsg srfspec",srfspec,0);
+
+    if (!quiet && !local) {
+       if (n == 1) {
+           switch (myjob) {
+             case 's':
+               if (sfspec) {
+                   printf(" SENT: [%s]",sfspec);
+                   if (srfspec)
+                     printf(" To: [%s]",srfspec);
+                   printf(" (%s)\r\n", success ? "OK" : "FAILED");
+               }
+               break;
+             case 'r':
+             case 'v':
+               if (rrfspec) {
+                   printf(" RCVD: [%s]",rrfspec);
+                   if (rfspec)
+                     printf(" To: [%s]",rfspec);
+                   printf(" (%s)\r\n", success ? "OK" : "FAILED");
+               }
+           }
+       } else if (n > 1) {
+           switch (myjob) {
+             case 's':
+               if (sfspec) {
+                   printf(" SENT: (%d files)",n);
+                   if (srfspec)
+                     printf(" Last: [%s]",srfspec);
+                   printf(" (%s)\r\n", success ? "OK" : "FAILED");
+               }
+               break;
+             case 'r':
+             case 'v':
+               if (rrfspec) {
+                   printf(" RCVD: (%d files)",n);
+                   if (rfspec)
+                     printf(" Last: [%s]",rfspec);
+                   printf(" (%s)\r\n", success ? "OK" : "FAILED");
+               }
+           }
+       } else if (n == 0) {
+           if (myjob == 's')
+             printf(" SENT: (0 files)          \r\n");
+           else if (myjob == 'r' || myjob == 'v')
+             printf(" RCVD: (0 files)          \r\n");
+       }
+    }
+}
+
+static VOID
+rdebug() {
+    if (server)
+      debug(F111,"RESUME","server=1",justone);
+    else
+      debug(F111,"RESUME","server=0",justone);
+}
+
+/* Flags for the ENABLE and DISABLE commands */
+extern int
+  en_cpy, en_cwd, en_del, en_dir, en_fin, en_get, en_bye, en_mai, en_pri,
+  en_hos, en_ren, en_sen, en_spa, en_set, en_typ, en_who, en_ret, en_xit,
+  en_mkd, en_rmd;
+#ifndef NOSPL
+extern int en_asg, en_que;
+#endif /* NOSPL */
+extern int what, lastxfer;
+
+/* Global variables declared here */
+
+  int whatru = 0;                      /* What are you. */
+  int whatru2 = 0;                     /* What are you, cont'd. */
+
+/* Local variables */
+
+  static char vstate = 0;              /* Saved State   */
+  static char vcmd = 0;                /* Saved Command */
+  static int reget = 0;                        /* Flag for executing REGET */
+  static int retrieve = 0;             /* Flag for executing RETRIEVE */
+  static int opkt = 0;                 /* Send Extended GET packet */
+
+  static int x;                                /* General-purpose integer */
+  static char *s;                      /* General-purpose string pointer */
+
+/* Macros - Note, BEGIN is predefined by Wart (and Lex) as "state = ", */
+/* BEGIN is NOT a GOTO! */
+#define TINIT if (tinit(1) < 0) return(-9)
+#define SERVE { TINIT; resetc(); nakstate=1; what=W_NOTHING; cmarg2=""; \
+sendmode=SM_SEND; havefs=0; recursive=r_save; fnspath=p_save; BEGIN serve; }
+#define RESUME { rdebug(); if (!server) { wheremsg(); return(0); } else \
+if (justone) { justone=0; wheremsg(); return(0); } else { SERVE; } }
+
+#ifdef GFTIMER
+#define QUIT x=quiet; quiet=1; clsif(); clsof(1); tsecs=gtimer(); \
+ fptsecs=gftimer(); quiet=x; return(success)
+#else
+#define QUIT x=quiet; quiet=1; clsif(); clsof(1); tsecs=gtimer(); quiet=x; \
+ return(success)
+#endif /* GFTIMER */
+
+/*
+  By late 1999, the big switch() statement generated from the following state
+  table began choking even gcc, so here we extract the code from the larger
+  states into static routines to reduce the size of the cases and the
+  switch() overall.  The routines follow the state table; the prototypes are
+  here.  Each of these routines simply contains the text from the
+  corresponding case, but with return(-1) added in appropriate places; see
+  instructions after the state table switcher.
+*/
+static int rc;                         /* Return code for these routines */
+static int rcv_s_pkt();                        /* Received an S packet */
+static int rcv_firstdata();            /* Received first Data packet */
+static int rcv_shortreply();           /* Short reply to a REMOTE command  */
+static int srv_query();                        /* Server answers an query */
+static int srv_copy();                 /* Server executes REMOTE COPY */
+static int srv_rename();               /* Server executes REMOTE RENAME */
+static int srv_login();                        /* Server executes REMOTE LOGIN */
+static int srv_timeout();              /* Server times out */
+
+
+#define BEGIN state =
+
+int state = 0;
+
+int
+wart()
+{
+    int c,actno;
+    extern char tbl[];
+    while (1) {
+       c = input() - 32;
+       debug(F000,"PROTO input",ckitoa(state),c+32);
+       if (c < 0 || c > 95) c = 0;
+       if ((actno = tbl[c + state*96]) != -1)
+           switch(actno) {
+case 1:
+    { TINIT;                           /* Send file(s) */
+    if (sinit() > 0) BEGIN ssinit;
+       else RESUME; }
+    break;
+case 2:
+    { TINIT; nakstate = 1; BEGIN get; }
+    break;
+case 3:
+    {                                  /* Client sends a GET command */
+    TINIT;
+    vstate = get;
+    reget = 0;
+    retrieve = 0;
+    opkt = 0;
+    vcmd = 0;
+#ifdef PKTZEROHACK
+    ipktack[0] = NUL;
+#endif /* PKTZEROHACK */
+    if (sipkt('I') >= 0)
+      BEGIN ipkt;
+    else
+      RESUME;
+}
+    break;
+case 4:
+    {                                  /* Client sends a RETRIEVE command */
+    TINIT;
+    vstate = get;
+    reget = 0;
+    retrieve = 1;
+    opkt = 0;
+    vcmd = 0;
+    if (sipkt('I') >= 0)
+      BEGIN ipkt;
+    else
+      RESUME;
+}
+    break;
+case 5:
+    {                                  /* Client sends a REGET command */
+    TINIT;
+    vstate = get;
+    reget = 1;
+    retrieve = 0;
+    opkt = 0;
+    vcmd = 0;
+    if (sipkt('I') >= 0)
+      BEGIN ipkt;
+    else
+      RESUME;
+}
+    break;
+case 6:
+    {                                  /* Client sends Extended GET Packet */
+    TINIT;
+    vstate = get;
+    reget = oopts & GOPT_RES;
+    retrieve = oopts & GOPT_DEL;
+    opkt = 1;
+    vcmd = 0;
+    if (sipkt('I') >= 0)
+      BEGIN ipkt;
+    else
+      RESUME;
+}
+    break;
+case 7:
+    {                                  /* Client sends a Host command */
+    TINIT;
+    vstate = rgen;
+    vcmd = 'C';
+    if (sipkt('I') >= 0)
+      BEGIN ipkt;
+    else
+      RESUME;
+}
+    break;
+case 8:
+    { TINIT;                           /* Client sends a Kermit command */
+    vstate = rgen;
+    vcmd = 'K';
+    if (sipkt('I') >= 0)
+      BEGIN ipkt;
+    else
+      RESUME;
+}
+    break;
+case 9:
+    {                                  /* Client sends a REMOTE command */
+    TINIT;
+    vstate = rgen;
+    vcmd = 'G';
+    if (sipkt('I') >= 0)
+      BEGIN ipkt;
+    else
+      RESUME;
+}
+    break;
+case 10:
+    {                                  /* Enter server mode */
+    int x;
+    x = justone;
+    if (!ENABLED(en_del)) {            /* If DELETE is disabled */
+       if (fncact == XYFX_B ||         /* undo any file collision action */
+           fncact == XYFX_U ||         /* that could result in deletion or */
+           fncact == XYFX_A ||         /* modification of existing files. */
+           fncact == XYFX_X) {
+#ifndef NOICP
+           extern int g_fncact;
+           g_fncact = fncact;          /* Save current setting */
+#endif /* NOICP */
+           fncact = XYFX_R;            /* Change to RENAME */
+           debug(F101,"server DELETE disabled so fncact RENAME","",fncact);
+       }
+    }
+    SERVE;                             /* tinit() clears justone... */
+    justone = x;
+#ifdef IKSDB
+    if (ikdbopen) slotstate(what, "SERVER", "", "");
+#endif /* IKSDB */
+}
+    break;
+case 11:
+    {
+    int b1 = 0, b2 = 0;
+    if (!data) TINIT;                  /* "ABEND" -- Tell other side. */
+#ifndef pdp11
+    if (epktflg) {                     /* If because of E-PACKET command */
+       b1 = bctl; b2 = bctu;           /* Save block check type */
+       bctl = bctu = 1;                /* set it to 1 */
+    }
+#endif /* pdp11 */
+    errpkt((CHAR *)"User cancelled");  /* Send the packet */
+#ifndef pdp11
+    if (epktflg) {                     /* Restore the block check */
+       epktflg = 0;
+       bctl = b1; bctu = b2;
+    }
+#endif /* pdp11 */
+    success = 0;
+    return(0);                         /* Return from protocol. */
+}
+    break;
+case 12:
+    {          /* Receive Send-Init packet. */
+    rc = rcv_s_pkt();
+    cancel = 0;                                /* Reset cancellation counter */
+    debug(F101,"rcv_s_pkt","",rc);
+    if (rc > -1) return(rc);           /* (see below) */
+}
+    break;
+case 13:
+    {                          /* Get ack for I-packet */
+    int x = 0;
+#ifdef PKTZEROHACK
+    ckstrncpy(ipktack,(char *)rdatap,PKTZEROLEN); /* Save a copy of the ACK */
+    ipktlen = strlen(ipktack);
+#endif /* PKTZEROHACK */
+    spar(rdatap);                      /* Set parameters */
+    cancel = 0;
+    winlo = 0;                         /* Set window-low back to zero */
+    debug(F101,"<ipkt>Y winlo","",winlo);
+    urserver = 1;                      /* So I know I'm talking to a server */
+    if (vcmd) {                                /* If sending a generic command */
+       if (tinit(0) < 0) return(-9);   /* Initialize many things */
+       x = scmd(vcmd,(CHAR *)cmarg);   /* Do that */
+       if (x >= 0) x = 0;              /* (because of O-Packet) */
+       debug(F101,"proto G packet scmd","",x);
+       vcmd = 0;                       /* and then un-remember it. */
+    } else if (vstate == get) {
+       debug(F101,"REGET sstate","",sstate);
+       x = srinit(reget, retrieve, opkt); /* GET or REGET, etc */
+    }
+    if (x < 0) {                       /* If command was too long */
+       if (!srimsg)
+         srimsg = "Error sending string";
+       errpkt((CHAR *)srimsg);         /* cancel both sides. */
+       success = 0;
+       RESUME;
+    } else if (x > 0) {                        /* Need to send more O-Packets */
+       BEGIN ssopkt;
+    } else {
+       rtimer();                       /* Reset the elapsed seconds timer. */
+#ifdef GFTIMER
+       rftimer();
+#endif /* GFTIMER */
+       winlo = 0;                      /* Window back to 0, again. */
+       debug(F101,"<ipkt>Y vstate","",vstate);
+       nakstate = 1;                   /* Can send NAKs from here. */
+       BEGIN vstate;                   /* Switch to desired state */
+    }
+}
+    break;
+case 14:
+    {                          /* Got ACK to O-Packet */
+    debug(F100,"CPCPRO <ssopkt>Y","",0);
+    x = sopkt();
+    debug(F101,"CPCPRO <ssopkt>Y x","",x);
+    if (x < 0) {                       /* If error */
+       errpkt((CHAR *)srimsg);         /* cancel both sides. */
+       success = 0;
+       RESUME;
+    } else if (x == 0) {               /* This was the last O-Packet */
+       rtimer();                       /* Reset the elapsed seconds timer. */
+#ifdef GFTIMER
+       rftimer();
+#endif /* GFTIMER */
+       winlo = 0;                      /* Window back to 0, again. */
+       debug(F101,"<ssopkt>Y winlo","",winlo);
+       nakstate = 1;                   /* Can send NAKs from here. */
+       BEGIN vstate;                   /* Switch to desired state */
+    }
+    debug(F101,"CPCPRO <ssopkt>Y not changing state","",x);
+}
+    break;
+case 15:
+    {                          /* Ignore Error reply to I packet */
+    int x = 0;
+    winlo = 0;                         /* Set window-low back to zero */
+    debug(F101,"<ipkt>E winlo","",winlo);
+    if (vcmd) {                                /* In case other Kermit doesn't */
+       if (tinit(0) < 0) return(-9);
+       x = scmd(vcmd,(CHAR *)cmarg);   /* understand I-packets. */
+       if (x >= 0) x = 0;              /* (because of O-Packet) */
+       vcmd = 0;                       /* Otherwise act as above... */
+    } else if (vstate == get) x = srinit(reget, retrieve, opkt);
+    if (x < 0) {                       /* If command was too long */
+       errpkt((CHAR *)srimsg);         /* cancel both sides. */
+       success = 0;
+       RESUME;
+    } else if (x > 0) {                        /* Need to send more O-Packets */
+       BEGIN ssopkt;
+    } else {
+       freerpkt(winlo);                /* Discard the Error packet. */
+       debug(F101,"<ipkt>E winlo","",winlo);
+       winlo = 0;                      /* Back to packet 0 again. */
+       nakstate = 1;                   /* Can send NAKs from here. */
+       BEGIN vstate;
+    }
+}
+    break;
+case 16:
+    {          /* Resend of previous I-pkt ACK, same seq number */
+    freerpkt(0);                       /* Free the ACK's receive buffer */
+    resend(0);                         /* Send the GET packet again. */
+}
+    break;
+case 17:
+    {                          /* Get I-packet */
+#ifndef NOSERVER
+    spar(rdatap);                      /* Set parameters from it */
+    ack1(rpar());                      /* Respond with our own parameters */
+#ifdef COMMENT
+    pktinit();                         /* Reinitialize packet numbers */
+#else
+#ifdef COMMENT
+    /* This can't be right - it undoes the stuff we just negotiated */
+    x = justone;
+    tinit(1);                          /* Reinitialize EVERYTHING */
+    justone = x;                       /* But this... */
+#else
+    tinit(0);                          /* Initialize most things */
+#endif /* COMMENT */
+#endif /* COMMENT */
+#endif /* NOSERVER */
+    cancel = 0;                                /* Reset cancellation counter */
+}
+    break;
+case 18:
+    {                          /* GET */
+#ifndef NOSERVER
+    if (x_login && !x_logged) {
+       errpkt((CHAR *)"Login required");
+       SERVE;
+    } else if (sgetinit(0,0) < 0) {
+       RESUME;
+    } else {
+#ifdef CKSYSLOG
+       if (ckxsyslog >= SYSLG_PR && ckxlogging)
+         cksyslog(SYSLG_PR, 1, "server", "GET", (char *)srvcmd);
+#endif /* CKSYSLOG */
+       BEGIN ssinit;
+    }
+#endif /* NOSERVER */
+}
+    break;
+case 19:
+    {                          /* GET /DELETE (RETRIEVE) */
+#ifndef NOSERVER
+    if (x_login && !x_logged) {
+       errpkt((CHAR *)"Login required");
+       RESUME;
+    } else if (!ENABLED(en_del)) {
+       errpkt((CHAR *)"Deleting files is disabled");
+       RESUME;
+    } else if (sgetinit(0,0) < 0) {
+       RESUME;
+    } else {
+       moving = 1;
+#ifdef CKSYSLOG
+       if (ckxsyslog >= SYSLG_PR && ckxlogging)
+         cksyslog(SYSLG_PR, 1, "server", "GET /DELETE", (char *)srvcmd);
+#endif /* CKSYSLOG */
+       BEGIN ssinit;
+    }
+#endif /* NOSERVER */
+}
+    break;
+case 20:
+    {                          /* GET /RECURSIVE */
+#ifndef NOSERVER
+    recursive = 1;                     /* Set these before sgetinit() */
+    if (fnspath == PATH_OFF)
+      fnspath = PATH_REL;              /* Don't worry, they will be */
+    if (x_login && !x_logged) {                /* reset next time through. */
+       errpkt((CHAR *)"Login required");
+       RESUME;
+    } else if (sgetinit(0,0) < 0) {
+       RESUME;
+    } else {
+#ifdef CKSYSLOG
+       if (ckxsyslog >= SYSLG_PR && ckxlogging)
+         cksyslog(SYSLG_PR, 1, "server", "GET /RECURSIVE", (char *)srvcmd);
+#endif /* CKSYSLOG */
+       BEGIN ssinit;
+    }
+#endif /* NOSERVER */
+}
+    break;
+case 21:
+    {                          /* GET /RECURSIVE /DELETE */
+#ifndef NOSERVER
+    recursive = 1;                     /* Set these before sgetinit() */
+    if (fnspath == PATH_OFF)
+      fnspath = PATH_REL;              /* Don't worry, they will be */
+    moving = 1;                                /* reset next time through. */
+    if (x_login && !x_logged) {
+       errpkt((CHAR *)"Login required");
+       RESUME;
+    } else if (!ENABLED(en_del)) {
+       errpkt((CHAR *)"Deleting files is disabled");
+       RESUME;
+    } else if (sgetinit(0,0) < 0) {
+       RESUME;
+    } else {
+#ifdef CKSYSLOG
+       if (ckxsyslog >= SYSLG_PR && ckxlogging)
+         cksyslog(SYSLG_PR,1,"server",
+                  "GET /RECURSIVE /DELETE",(char *)srvcmd);
+#endif /* CKSYSLOG */
+       BEGIN ssinit;
+    }
+#endif /* NOSERVER */
+}
+    break;
+case 22:
+    {                          /* GET /RECOVER (REGET) */
+#ifndef NOSERVER
+    if (x_login && !x_logged) {
+       errpkt((CHAR *)"Login required");
+       SERVE;
+    } else if (sgetinit(1,0) < 0) {
+       RESUME;
+    } else {
+#ifdef CKSYSLOG
+       if (ckxsyslog >= SYSLG_PR && ckxlogging)
+         cksyslog(SYSLG_PR, 1, "server", "GET /RECOVER", (char *)srvcmd);
+#endif /* CKSYSLOG */
+       BEGIN ssinit;
+    }
+#endif /* NOSERVER */
+}
+    break;
+case 23:
+    {                          /* Extended GET */
+#ifndef NOSERVER
+    if (x_login && !x_logged) {                /* (any combination of options) */
+       errpkt((CHAR *)"Login required");
+       SERVE;
+    } else if ((x = sgetinit(0,1)) < 0) {
+       debug(F101,"CKCPRO <serve>O sgetinit fail","",x);
+       RESUME;
+    } else if (x == 0) {
+       debug(F101,"CKCPRO <serve>O sgetinit done","",x);
+#ifdef CKSYSLOG
+       if (ckxsyslog >= SYSLG_PR && ckxlogging)
+         cksyslog(SYSLG_PR, 1, "server", "EXTENDED GET", (char *)srvcmd);
+#endif /* CKSYSLOG */
+       BEGIN ssinit;
+    } else {                           /* Otherwise stay in this state */
+       debug(F101,"CKCPRO <serve>O sgetinit TBC","",x);
+       ack();
+       BEGIN ropkt;
+    }
+#endif /* NOSERVER */
+}
+    break;
+case 24:
+    {
+#ifndef NOSERVER
+    if (x_login && !x_logged) {                /* (any combination of options) */
+       errpkt((CHAR *)"Login required");
+       SERVE;
+    } else if ((x = sgetinit(0,1)) < 0) {
+       debug(F101,"CKCPRO <ropkt>O sgetinit fail","",x);
+       RESUME;
+    } else if (x == 0) {
+       debug(F101,"CKCPRO <ropkt>O sgetinit done","",x);
+#ifdef CKSYSLOG
+       if (ckxsyslog >= SYSLG_PR && ckxlogging)
+         cksyslog(SYSLG_PR, 1, "server", "EXTENDED GET", (char *)srvcmd);
+#endif /* CKSYSLOG */
+       BEGIN ssinit;
+    } else {                           /* Otherwise stay in this state */
+       debug(F101,"CKCPRO <ropkt>O sgetinit TBC","",x);
+       ack();
+    }
+#endif /* NOSERVER */
+}
+    break;
+case 25:
+    {                          /* Generic server command */
+#ifndef NOSERVER
+    srvptr = srvcmd;                   /* Point to command buffer */
+    decode(rdatap,putsrv,0);           /* Decode packet data into it */
+    putsrv(NUL);                       /* Insert a couple nulls */
+    putsrv(NUL);                       /* for termination */
+    if (srvcmd[0]) {
+       sstate = srvcmd[0];             /* Set requested start state */
+       if (x_login && !x_logged &&     /* Login required? */
+           /* Login, Logout, and Help are allowed when not logged in */
+           sstate != 'I' && sstate != 'L' && sstate != 'H') {
+           errpkt((CHAR *)"Login required");
+           SERVE;
+       } else {
+           nakstate = 0;               /* Now I'm the sender. */
+           what = W_REMO;              /* Doing a REMOTE command. */
+#ifdef STREAMING
+           if (!streaming)
+#endif /* STREAMING */
+             if (timint < 1)
+               timint = chktimo(rtimo,timef); /* Switch to per-packet timer */
+           binary = XYFT_T;            /* Switch to text mode */
+           BEGIN generic;              /* Switch to generic command state */
+       }
+    } else {
+       errpkt((CHAR *)"Badly formed server command"); /* report error */
+       RESUME;                 /* & go back to server command wait */
+    }
+#endif /* NOSERVER */
+}
+    break;
+case 26:
+    {                          /* Receive Host command */
+#ifndef NOSERVER
+    if (x_login && !x_logged) {
+       errpkt((CHAR *)"Login required");
+       SERVE;
+    } else if (!ENABLED(en_hos)) {
+       errpkt((CHAR *)"REMOTE HOST disabled");
+       RESUME;
+    } else if (nopush) {
+       errpkt((CHAR *)"HOST commands not available");
+       RESUME;
+    } else {
+       srvptr = srvcmd;                /* Point to command buffer */
+       decode(rdatap,putsrv,0);        /* Decode command packet into it */
+       putsrv(NUL);                    /* Null-terminate */
+       nakstate = 0;                   /* Now sending, not receiving */
+       binary = XYFT_T;                /* Switch to text mode */
+       if (syscmd((char *)srvcmd,"")) { /* Try to execute the command */
+           what = W_REMO;              /* Doing a REMOTE command. */
+#ifdef STREAMING
+           if (!streaming)
+#endif /* STREAMING */
+             if (timint < 1)
+               timint = chktimo(rtimo,timef); /* Switch to per-packet timer */
+#ifdef CKSYSLOG
+           if (ckxsyslog >= SYSLG_PR && ckxlogging)
+             cksyslog(SYSLG_PR, 1, "server", "REMOTE HOST", (char *)srvcmd);
+#endif /* CKSYSLOG */
+           BEGIN ssinit;               /* If OK, send back its output */
+       } else {                        /* Otherwise */
+           errpkt((CHAR *)"Can't do system command"); /* report error */
+           RESUME;                     /* & go back to server command wait */
+       }
+    }
+#endif /* NOSERVER */
+}
+    break;
+case 27:
+    {                          /* Interrupted or connection lost */
+    rc = srv_timeout();
+    debug(F101,"srv_timeout","",rc);
+    if (rc > -1) return(rc);           /* (see below) */
+}
+    break;
+case 28:
+    {                          /* Server got a NAK in command-wait */
+#ifndef NOSERVER
+    errpkt((CHAR *)"Did you say RECEIVE instead of GET?");
+    RESUME;
+#endif /* NOSERVER */
+}
+    break;
+case 29:
+    {                          /* Any other command in this state */
+#ifndef NOSERVER
+    if (c != ('E' - SP) && c != ('Y' - SP)) /* except E and Y packets. */
+      errpkt((CHAR *)"Unimplemented server function");
+    /* If we answer an E with an E, we get an infinite loop. */
+    /* A Y (ACK) can show up here if we sent back a short-form reply to */
+    /* a G packet and it was echoed.  ACKs can be safely ignored here. */
+    RESUME;                            /* Go back to server command wait. */
+#endif /* NOSERVER */
+}
+    break;
+case 30:
+    {                          /* Login/Out */
+    rc = srv_login();
+    debug(F101,"<generic>I srv_login","",rc);
+    if (rc > -1) return(rc);           /* (see below) */
+}
+    break;
+case 31:
+    {                          /* Got REMOTE CD command */
+#ifndef NOSERVER
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE CD", (char *)srvcmd);
+#endif /* CKSYSLOG */
+    if (!ENABLED(en_cwd)) {
+       errpkt((CHAR *)"REMOTE CD disabled");
+       RESUME;
+    } else {
+       char * p = NULL;
+       x = cwd((char *)(srvcmd+1));    /* Try to change directory */
+#ifdef IKSDB
+       if (ikdbopen) slotstate(what,"REMOTE CD", (char *)(srvcmd+2), "");
+#endif /* IKSDB */
+       if (!x) {                       /* Failed */
+           errpkt((CHAR *)"Can't change directory");
+           RESUME;                     /* Back to server command wait */
+       } else if (x == 2) {            /* User wants message */
+           if (!ENABLED(en_typ)) {     /* Messages (REMOTE TYPE) disabled? */
+               errpkt((CHAR *)"REMOTE TYPE disabled");
+               RESUME;
+           } else {                    /* TYPE is enabled */
+               int i;
+               for (i = 0; i < 8; i++) {
+                   if (zchki(cdmsgfile[i]) > -1) {
+                       break;
+                   }
+               }
+               binary = XYFT_T;        /* Use text mode for this. */
+               if (i < 8 && sndtype(cdmsgfile[i])) { /* Have readme file? */
+                   BEGIN ssinit;       /* OK */
+               } else {                /* not OK */
+                   p = zgtdir();
+                   if (!p) p = "";
+                   success = (*p) ? 1 : 0;
+                   ack1((CHAR *)p);    /* ACK with new directory name */
+                   success = 1;
+                   RESUME;             /* wait for next server command */
+               }
+           }
+       } else {                        /* User doesn't want message */
+           p =zgtdir();
+           if (!p) p = "";
+           success = (*p) ? 1 : 0;
+           ack1((CHAR *)p);
+           success = 1;
+           RESUME;                     /* Wait for next server command */
+       }
+    }
+#endif /* NOSERVER */
+}
+    break;
+case 32:
+    {                          /* Got REMOTE PWD command */
+#ifndef NOSERVER
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE PWD", NULL);
+#endif /* CKSYSLOG */
+    if (!ENABLED(en_cwd)) {
+       errpkt((CHAR *)"REMOTE CD disabled");
+       RESUME;
+    } else {
+       if (encstr((CHAR *)zgtdir()) > -1) { /* Encode current directory */
+           ack1(data);                 /* If it fits, send it back in ACK */
+           success = 1;
+       } else {                        /* Failed */
+           ack();                      /* Send empty ACK */
+           success = 0;                /* and indicate failure locally */
+       }
+       RESUME;                         /* Back to server command wait */
+    }
+#endif /* NOSERVER */
+}
+    break;
+case 33:
+    {                          /* REMOTE DIRECTORY command */
+#ifndef NOSERVER
+    char *n2;
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE DIRECTORY", (char *)srvcmd);
+#endif /* CKSYSLOG */
+    if (!ENABLED(en_dir)) {            /* If DIR is disabled, */
+       errpkt((CHAR *)"REMOTE DIRECTORY disabled"); /* refuse. */
+       RESUME;
+    } else {                           /* DIR is enabled. */
+#ifdef IKSDB
+       if (ikdbopen) slotstate(what,"REMOTE DIR", (char *)(srvcmd+2), "");
+#endif /* IKSDB */
+       if (!ENABLED(en_cwd)) {         /* But CWD is disabled */
+           zstrip((char *)(srvcmd+2),&n2); /* and they included a pathname, */
+           if (strcmp((char *)(srvcmd+2),n2)) { /* so refuse. */
+               errpkt((CHAR *)"Access denied");
+               RESUME;                 /* Remember, this is not a goto! */
+           }
+       }
+       if (state == generic) {                 /* It's OK to go ahead. */
+#ifdef COMMENT
+           n2 = (*(srvcmd+2)) ? DIRCMD : DIRCM2;
+           if (syscmd(n2,(char *)(srvcmd+2)))  /* If it can be done */
+#else
+           int x;
+           if ((x = snddir((char*)(srvcmd+2))) > 0)
+#endif /* COMMENT */
+           {
+               BEGIN ssinit;           /* send the results back; */
+           } else {                    /* otherwise */
+               if (x < 0)
+                 errpkt((CHAR *)"No files match");
+               else
+                 errpkt((CHAR *)"Can't list directory");
+               RESUME;                 /* return to server command wait */
+           }
+       }
+    }
+#endif /* NOSERVER */
+}
+    break;
+case 34:
+    {                          /* REMOTE DELETE (Erase) */
+#ifndef NOSERVER
+    char *n2;
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE DELETE", (char *)srvcmd);
+#endif /* CKSYSLOG */
+    if (!ENABLED(en_del)) {
+       errpkt((CHAR *)"REMOTE DELETE disabled");
+       RESUME;
+    } else {                           /* DELETE is enabled */
+#ifdef IKSDB
+       if (ikdbopen) slotstate(what,"REMOTE DELETE", (char *)(srvcmd+2), "");
+#endif /* IKSDB */
+       if (!ENABLED(en_cwd)) {         /* but CWD is disabled */
+           zstrip((char *)(srvcmd+2),&n2); /* and they included a pathname, */
+           if (strcmp((char *)(srvcmd+2),n2)) { /* so refuse. */
+               errpkt((CHAR *)"Access denied");
+               RESUME;                 /* Remember, this is not a goto! */
+           }
+       } else if (isdir((char *)(srvcmd+2))) { /* A directory name? */
+           errpkt((CHAR *)"It's a directory");
+           RESUME;
+       }
+       if (state == generic) {         /* It's OK to go ahead. */
+           int x;
+           if ((x = snddel((char*)(srvcmd+2))) > 0) {
+               BEGIN ssinit;           /* If OK send results back */
+           } else {                    /* otherwise */
+               if (x < 0)
+                 errpkt((CHAR *)"File not found"); /* report failure */
+               else
+                 errpkt((CHAR *)"DELETE failed");
+               RESUME;                 /* & return to server command wait */
+           }
+       }
+    }
+#endif /* NOSERVER */
+}
+    break;
+case 35:
+    {                          /* FINISH */
+#ifndef NOSERVER
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "FINISH", NULL);
+#endif /* CKSYSLOG */
+#ifdef IKSDB
+    if (ikdbopen) slotstate(what,"SERVER FINISH", "", "");
+#endif /* IKSDB */
+    if (!ENABLED(en_fin)) {
+       errpkt((CHAR *)"FINISH disabled");
+       RESUME;
+    } else {
+       ack();                          /* Acknowledge */
+       xxscreen(SCR_TC,0,0L,"");       /* Display */
+       success = 1;
+       return(0);                      /* Done */
+    }
+#endif /* NOSERVER */
+}
+    break;
+case 36:
+    {                          /* EXIT */
+#ifndef NOSERVER
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE EXIT", NULL);
+#endif /* CKSYSLOG */
+#ifdef IKSDB
+    if (ikdbopen) slotstate(what,"REMOTE EXIT", "", "");
+#endif /* IKSDB */
+    if (!ENABLED(en_xit)) {
+       errpkt((CHAR *)"EXIT disabled");
+       RESUME;
+    } else {
+       ack();                          /* Acknowledge */
+       xxscreen(SCR_TC,0,0L,"");       /* Display */
+       doexit(GOOD_EXIT,xitsta);
+    }
+#endif /* NOSERVER */
+}
+    break;
+case 37:
+    {                          /* BYE (Logout) */
+#ifndef NOSERVER
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "BYE", NULL);
+#endif /* CKSYSLOG */
+#ifdef IKSDB
+    if (ikdbopen) slotstate(what,"SERVER BYE", "", "");
+#endif /* IKSDB */
+    if (!ENABLED(en_bye)) {
+       errpkt((CHAR *)"BYE disabled");
+       RESUME;
+    } else {
+       ack();                          /* Acknowledge */
+       success = 1;
+       msleep(750);                    /* Give the ACK time to get out */
+       if (local)
+         ttres();                      /* Reset the terminal */
+       xxscreen(SCR_TC,0,0L,"");       /* Display */
+       doclean(1);                     /* Clean up files, etc */
+#ifdef DEBUG
+       debug(F100,"C-Kermit BYE - Loggin out...","",0);
+       zclose(ZDFILE);
+#endif /* DEBUG */
+#ifdef IKSD
+#ifdef CK_LOGIN
+       if (inserver)
+         ckxlogout();
+       else
+#endif /* CK_LOGIN */
+#endif /* IKSD */
+#ifdef TCPSOCKET
+#ifndef NOLISTEN
+         if (network && tcpsrfd > 0 && !inserver)
+           doexit(GOOD_EXIT,xitsta);
+       else
+#endif /* NOLISTEN */
+#endif /* TCPSOCKET */
+         return(zkself());             /* Try to log self out */
+    }
+#endif /* NOSERVER */
+}
+    break;
+case 38:
+    {                          /* REMOTE HELP */
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE HELP", NULL);
+#endif /* CKSYSLOG */
+#ifdef IKSDB
+    if (ikdbopen) slotstate(what,"REMOTE HELP", "", "");
+#endif /* IKSDB */
+#ifndef NOSERVER
+    if (sndhlp()) {
+       BEGIN ssinit;                   /* try to send it */
+    } else {                           /* If not ok, */
+       errpkt((CHAR *)"Can't send help"); /* send error message instead */
+       RESUME;                         /* and return to server command wait */
+    }
+#endif /* NOSERVER */
+}
+    break;
+case 39:
+    {                            /* REMOTE RENAME */
+    rc = srv_rename();
+    debug(F101,"srv_rename","",rc);
+    if (rc > -1) return(rc);           /* (see below) */
+}
+    break;
+case 40:
+    {                            /* REMOTE COPY */
+    rc = srv_copy();
+    debug(F101,"srv_copy","",rc);
+    if (rc > -1) return(rc);           /* (see below) */
+}
+    break;
+case 41:
+    {                          /* REMOTE SET */
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE SET", (char *)srvcmd);
+#endif /* CKSYSLOG */
+#ifndef NOSERVER
+#ifdef IKSDB
+    if (ikdbopen) slotstate(what,"REMOTE SET", (char *)(srvcmd+1), "");
+#endif /* IKSDB */
+    if (!ENABLED(en_set)) {
+       errpkt((CHAR *)"REMOTE SET disabled");
+       RESUME;
+    } else {
+       if (remset((char *)(srvcmd+1))) { /* Try to do what they ask */
+           success = 1;
+           ack();                      /* If OK, then acknowledge */
+       } else                          /* Otherwise */
+         errpkt((CHAR *)"Unknown REMOTE SET parameter"); /* give error msg */
+       RESUME;                         /* Return to server command wait */
+    }
+#endif /* NOSERVER */
+}
+    break;
+case 42:
+    {                          /* REMOTE TYPE */
+#ifndef NOSERVER
+    char *n2;
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE TYPE", (char *)srvcmd);
+#endif /* CKSYSLOG */
+    if (!ENABLED(en_typ)) {
+       errpkt((CHAR *)"REMOTE TYPE disabled");
+       RESUME;
+    } else {
+#ifdef IKSDB
+       if (ikdbopen) slotstate(what,"REMOTE TYPE", (char *)(srvcmd+2), "");
+#endif /* IKSDB */
+       if (!ENABLED(en_cwd)) {         /* If CWD disabled */
+           zstrip((char *)(srvcmd+2),&n2); /* and they included a pathname, */
+           if (strcmp((char *)(srvcmd+2),n2)) { /* refuse. */
+               errpkt((CHAR *)"Access denied");
+               RESUME;                 /* Remember, this is not a goto! */
+           }
+       }
+       if (state == generic) {         /* It's OK to go ahead. */
+           binary = XYFT_T;            /* Use text mode for this. */
+           if (                        /* (RESUME didn't change state) */
+#ifdef COMMENT
+             syscmd(TYPCMD,(char *)(srvcmd+2)) /* Old way */
+#else
+             sndtype((char *)(srvcmd+2)) /* New way */
+#endif /* COMMENT */
+               )
+             BEGIN ssinit;             /* OK */
+           else {                      /* not OK */
+               errpkt((CHAR *)"Can't type file"); /* give error message */
+               RESUME;                 /* wait for next server command */
+           }
+       }
+    }
+#endif /* NOSERVER */
+}
+    break;
+case 43:
+    {                          /* REMOTE MKDIR */
+#ifndef NOSERVER
+#ifdef CK_MKDIR
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE MKDIR", (char *)srvcmd);
+#endif /* CKSYSLOG */
+#ifdef IKSDB
+    if (ikdbopen) slotstate(what,"REMOTE MKDIR", (char *)(srvcmd+2), "");
+#endif /* IKSDB */
+    if (!ENABLED(en_mkd)) {
+       errpkt((CHAR *)"REMOTE MKDIR disabled");
+       RESUME;
+    } else if (!ENABLED(en_cwd)) {     /* If CWD disabled */
+       errpkt((CHAR *)"Directory access restricted");
+       RESUME;                         /* Remember, this is not a goto! */
+    }
+    if (state == generic) {            /* OK to go ahead. */
+       char *p = NULL;
+       x = ckmkdir(0,(char *)(srvcmd+2),&p,0,1); /* Make the directory */
+       if (!p) p = "";
+       if (x > -1) {
+           encstr((CHAR *)p);          /* OK - encode the name */
+           ack1(data);                 /* Send short-form response */
+           success = 1;
+           RESUME;
+       } else {                        /* not OK */
+           if (!*p) p = "Directory creation failure";
+           errpkt((CHAR *)p);          /* give error message */
+           RESUME;                     /* Wait for next server command */
+       }
+    }
+#else
+    errpkt((CHAR *)"REMOTE MKDIR not available");
+    RESUME;
+#endif /* CK_MKDIR */
+#endif /* NOSERVER */
+}
+    break;
+case 44:
+    {                          /* REMOTE RMDIR */
+#ifndef NOSERVER
+#ifdef CK_MKDIR
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE RMDIR", (char *)srvcmd);
+#endif /* CKSYSLOG */
+#ifdef IKSDB
+    if (ikdbopen) slotstate(what,"REMOTE RMDIR", (char *)(srvcmd+2), "");
+#endif /* IKSDB */
+    if (!ENABLED(en_rmd)) {
+       errpkt((CHAR *)"REMOTE RMDIR disabled");
+       RESUME;
+    } else if (!ENABLED(en_cwd)) {     /* If CWD disabled */
+       errpkt((CHAR *)"Directory access restricted");
+       RESUME;                         /* Remember, this is not a goto! */
+    }
+    if (state == generic) {            /* OK to go ahead. */
+       char *p = NULL;
+       x = ckmkdir(1,(char *)(srvcmd+2),&p,0,1);
+       if (!p) p = "";
+       if (x > -1) {
+           encstr((CHAR *)p);          /* OK - encode the name */
+           ack1(data);                 /* Send short-form response */
+           success = 1;
+           RESUME;
+       } else {                        /* not OK */
+           if (!*p) p = "Directory removal failure";
+           errpkt((CHAR *)p);          /* give error message */
+           RESUME;                     /* Wait for next server command */
+       }
+    }
+#else
+    errpkt((CHAR *)"REMOTE RMDIR not available");
+    RESUME;
+#endif /* CK_MKDIR */
+#endif /* NOSERVER */
+}
+    break;
+case 45:
+    {                          /* REMOTE SPACE */
+#ifndef NOSERVER
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE SPACE", (char *)srvcmd);
+#endif /* CKSYSLOG */
+    if (!ENABLED(en_spa)) {
+       errpkt((CHAR *)"REMOTE SPACE disabled");
+       RESUME;
+    } else {
+       x = srvcmd[1];                  /* Get area to check */
+       x = ((x == NUL) || (x == SP)
+#ifdef OS2
+            || (x == '!') || (srvcmd[3] == ':')
+#endif /* OS2 */
+            );
+#ifdef IKSDB
+       if (ikdbopen) slotstate(what,
+                             "REMOTE SPACE",
+                             (x ? "" : (char *)srvcmd),
+                             ""
+                             );
+#endif /* IKSDB */
+       if (!x && !ENABLED(en_cwd)) {   /* CWD disabled */
+           errpkt((CHAR *)"Access denied"); /* and non-default area given, */
+           RESUME;                     /* refuse. */
+       } else {
+#ifdef OS2
+_PROTOTYP(int sndspace,(int));
+           if (sndspace(x ? toupper(srvcmd[2]) : 0)) {
+               BEGIN ssinit;           /* send the report. */
+           } else {                    /* If not ok, */
+               errpkt((CHAR *)"Can't send space"); /* send error message */
+               RESUME;                 /* and return to server command wait */
+           }
+#else
+            if (nopush)
+              x = 0;
+            else
+              x = (x ? syscmd(SPACMD,"") : syscmd(SPACM2,(char *)(srvcmd+2)));
+           if (x) {                    /* If we got the info */
+               BEGIN ssinit;           /* send it */
+           } else {                    /* otherwise */
+               errpkt((CHAR *)"Can't check space"); /* send error message */
+               RESUME;                 /* and await next server command */
+           }
+#endif /* OS2 */
+       }
+    }
+#endif /* NOSERVER */
+}
+    break;
+case 46:
+    {                          /* REMOTE WHO */
+#ifndef NOSERVER
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE WHO", (char *)srvcmd);
+#endif /* CKSYSLOG */
+#ifdef IKSDB
+    if (ikdbopen) slotstate(what,"REMOTE WHO", (char *)(srvcmd+2), "");
+#endif /* IKSDB */
+    if (!ENABLED(en_who)) {
+       errpkt((CHAR *)"REMOTE WHO disabled");
+       RESUME;
+    } else {
+#ifdef OS2
+_PROTOTYP(int sndwho,(char *));
+           if (sndwho((char *)(srvcmd+2))) {
+               BEGIN ssinit;           /* try to send it */
+           } else {                    /* If not ok, */
+               errpkt((CHAR *)"Can't do who command"); /* send error msg */
+               RESUME;                 /* and return to server command wait */
+           }
+#else
+       if (syscmd(WHOCMD,(char *)(srvcmd+2))) {
+           BEGIN ssinit;
+       } else {
+           errpkt((CHAR *)"Can't do who command");
+           RESUME;
+       }
+#endif /* OS2 */
+    }
+#endif /* NOSERVER */
+}
+    break;
+case 47:
+    {                          /* Variable query or set */
+    rc = srv_query();
+    debug(F101,"srv_query","",rc);
+    if (rc > -1) return(rc);
+}
+    break;
+case 48:
+    {                          /* REMOTE MESSAGE command */
+#ifndef NOSERVER
+    debug(F110,"RMSG",(char *)srvcmd+2,0);
+    xxscreen(SCR_MS,0,0L,(char *)(srvcmd+2));
+    ack();
+    RESUME;
+#endif /* NOSERVER */
+}
+    break;
+case 49:
+    {                          /* Interrupted or connection lost */
+#ifndef NOSERVER
+    if (fatalio) {                     /* Connection lost */
+#ifdef CKSYSLOG
+       if (ckxsyslog >= SYSLG_PR && ckxlogging)
+         cksyslog(SYSLG_PR, 1, "server", "Interrupted", NULL);
+#endif /* CKSYSLOG */
+       success = 0;
+       xitsta |= (what & W_KERMIT);
+       QUIT;
+    } else if (interrupted) {
+       if (!ENABLED(en_fin)) {         /* Ctrl-C typed */
+           errpkt((CHAR *)"QUIT disabled");
+           RESUME;
+       } else {
+#ifdef CKSYSLOG
+           if (ckxsyslog >= SYSLG_PR && ckxlogging)
+             cksyslog(SYSLG_PR, 1, "server", "Interrupted", NULL);
+#endif /* CKSYSLOG */
+           success = 0;
+           xitsta |= (what & W_KERMIT);
+           QUIT;
+       }
+    } else {                           /* Shouldn't happen */
+       debug(F100,"SERVER (generic) GOT UNEXPECTED 'q'","",0);
+       QUIT;
+    }
+#endif /* NOSERVER */
+}
+    break;
+case 50:
+    {                          /* Anything else in this state... */
+#ifndef NOSERVER
+    errpkt((CHAR *)"Unimplemented REMOTE command"); /* Complain */
+    RESUME;                            /* and return to server command wait */
+#endif /* NOSERVER */
+}
+    break;
+case 51:
+    {                          /* Sent BYE and connection broken */
+    if (bye_active && ttchk() < 0) {
+       msleep(500);
+       bye_active = 0;
+       ttclos(0);                      /* Close our end of the connection */
+       clsof(0);
+       return(success = 1);
+    } else {                           /* Other generic command */
+       return(success = 0);            /* or connection not broken */
+    }
+}
+    break;
+case 52:
+    {                          /* Short-Form reply */
+    rc = rcv_shortreply();
+    debug(F101,"<rgen>Y rcv_shortreply","",rc);
+    if (rc > -1) return(rc);
+}
+    break;
+case 53:
+    {                          /* File header */
+    /* char *n2; */
+    extern int rsn;
+    debug(F101,"<rfile>F winlo 1","",winlo);
+    xflg = 0;                          /* Not screen data */
+    if (!czseen)
+      cancel = 0;                      /* Reset cancellation counter */
+#ifdef CALIBRATE
+    if (dest == DEST_N)
+      calibrate = 1;
+#endif /* CALIBRATE */
+    if (!rcvfil(filnam)) {             /* Figure out local filename */
+       errpkt((CHAR *)rf_err);         /* Trouble */
+       RESUME;
+    } else {                           /* Real file, OK to receive */
+       char * fnp;
+       debug(F111,"<rfile>F winlo 2",fspec,winlo);
+       if (filcnt == 1)                /* rcvfil set this to 1 for 1st file */
+         crc16 = 0L;                   /* Clear file CRC */
+       fnp = fspec;                    /* This is the full path */
+       if (server && !ENABLED(en_cwd) || /* if DISABLE CD */
+           !fackpath                     /* or F-ACK-PATH OFF */
+           ) {
+           zstrip(fspec,&fnp);         /* don't send back full path */
+       }
+       encstr((CHAR *)fnp);
+       if (fackbug)
+         ack();
+       else
+         ack1(data);                   /* Send it back in ACK */
+       initattr(&iattr);               /* Clear file attribute structure */
+       streamon();
+       if (window(wslotn) < 0) {       /* Allocate negotiated window slots */
+           errpkt((CHAR *)"Can't open window");
+           RESUME;
+       }
+#ifdef IKSDB
+       if (ikdbopen) slotstate(what,
+                             server ? "SERVER" : "",
+                             "RECEIVE",
+                             fspec
+                             );
+#endif /* IKSDB */
+       BEGIN rattr;                    /* Now expect Attribute packets */
+    }
+}
+    break;
+case 54:
+    {                          /* X-packet instead of file header */
+    xflg = 1;                          /* Screen data */
+    if (!czseen)
+      cancel = 0;                      /* Reset cancellation counter */
+    ack();                             /* Acknowledge the X-packet */
+    initattr(&iattr);                  /* Initialize attribute structure */
+    streamon();
+    if (window(wslotn) < 0) {          /* allocate negotiated window slots */
+       errpkt((CHAR *)"Can't open window");
+       RESUME;
+    }
+#ifndef NOSPL
+    if (query) {                       /* If this is the response to */
+       qbufp = querybuf;               /* a query that we sent, initialize */
+       qbufn = 0;                      /* the response buffer */
+       querybuf[0] = NUL;
+    }
+#endif /* NOSPL */
+    what = W_REMO;                     /* we're doing a REMOTE command */
+#ifdef IKSDB
+    if (ikdbopen) slotstate(what,
+                         server ? "SERVER" : "",
+                         "RECEIVE",
+                         fspec
+                         );
+#endif /* IKSDB */
+    BEGIN rattr;                       /* Expect Attribute packets */
+}
+    break;
+case 55:
+    {                          /* Attribute packet */
+    if (gattr(rdatap,&iattr) == 0) {   /* Read into attribute structure */
+#ifdef CK_RESEND
+       ack1((CHAR *)iattr.reply.val);  /* Reply with data */
+#else
+       ack();                          /* If OK, acknowledge */
+#endif /* CK_RESEND */
+    } else {                           /* Otherwise */
+       extern long fsize;
+       char *r;
+       r = getreason(iattr.reply.val);
+       ack1((CHAR *)iattr.reply.val);  /* refuse to accept the file */
+       xxscreen(SCR_ST,ST_REFU,0L,r);  /* reason */
+#ifdef TLOG
+       if (tralog && !tlogfmt)
+         doxlog(what,filnam,fsize,binary,1,r);
+#endif /* TLOG */
+    }
+}
+    break;
+case 56:
+    {                          /* First data packet */
+    debug(F100,"<rattr> D firstdata","",0);
+    rc = rcv_firstdata();
+    debug(F101,"rcv_firstdata rc","",rc);
+    if (rc > -1) return(rc);           /* (see below) */
+}
+    break;
+case 57:
+    {                          /* EOT, no more files */
+    ack();                             /* Acknowledge the B packet */
+    reot();                            /* Do EOT things */
+#ifdef CK_TMPDIR
+/* If we were cd'd temporarily to another device or directory ... */
+    if (f_tmpdir) {
+       int x;
+       x = zchdir((char *) savdir);    /* ... restore previous directory */
+       f_tmpdir = 0;                   /* and remember we did it. */
+       debug(F111,"ckcpro.w B tmpdir restoring",savdir,x);
+    }
+#endif /* CK_TMPDIR */
+    RESUME;                            /* and quit */
+}
+    break;
+case 58:
+    {                          /* Got Data packet */
+    debug(F101,"<rdpkt>D cxseen","",cxseen);
+    debug(F101,"<rdpkt>D czseen","",czseen);
+    if (cxseen || czseen || discard) { /* If file or group interruption */
+       CHAR * msg;
+       msg = czseen ? (CHAR *)"Z" : (CHAR *)"X";
+#ifdef STREAMING
+       if (streaming) {                /* Need to cancel */
+           debug(F111,"<rdpkt>D streaming cancel",msg,cancel);
+           if (cancel++ == 0) {        /* Only do this once */
+               ack1(msg);              /* Put "X" or "Z" in ACK */
+           } else if (czseen) {
+               errpkt((CHAR *)"User canceled");
+               RESUME;
+           } else {
+               fastack();
+           }
+       } else
+#endif /* STREAMING */
+         ack1(msg);
+    } else {                           /* No interruption */
+       int rc, qf;
+#ifndef NOSPL
+       qf = query;
+#else
+       qf = 0;
+#endif /* NOSPL */
+#ifdef CKTUNING
+       rc = (binary && !parity) ?
+         bdecode(rdatap,putfil):
+           decode(rdatap, qf ? puttrm : putfil, 1);
+#else
+       rc = decode(rdatap, qf ? puttrm : putfil, 1);
+#endif /* CKTUNING */
+       if (rc < 0) {
+           discard = (keep == 0 || (keep == SET_AUTO && binary != XYFT_T));
+           errpkt((CHAR *)"Error writing data"); /* If failure, */
+           RESUME;
+       } else                          /* Data written OK, send ACK */
+#ifdef STREAMING
+         if (streaming)
+           fastack();
+       else
+#endif /* STREAMING */
+         ack();
+    }
+}
+    break;
+case 59:
+    {                          /* EOF immediately after A-Packet. */
+    rf_err = "Can't create file";
+    timint = s_timint;
+    if (discard) {                     /* Discarding a real file... */
+       x = 1;
+    } else if (xflg) {                 /* If screen data */
+       if (remfile) {                  /* redirected to file */
+           if (rempipe)                /* or pipe */
+             x = openc(ZOFILE,remdest); /* Pipe: start command */
+           else
+             x = opena(remdest,&iattr); /* File: open with attributes */
+       } else {                        /* otherwise */
+           x = opent(&iattr);          /* "open" the screen */
+       }
+#ifdef CALIBRATE
+    } else if (calibrate) {            /* If calibration run */
+       x = ckopenx(&iattr);            /* do this */
+#endif /* CALIBRATE */
+    } else {                           /* otherwise */
+       x = opena(filnam,&iattr);       /* open the file, with attributes */
+       if (x == -17) {                 /* REGET skipped because same size */
+           discard = 1;
+           rejection = 1;
+       }
+    }
+    if (!x || reof(filnam, &iattr) < 0) { /* Close output file */
+       errpkt((CHAR *) rf_err);        /* If problem, send error msg */
+       RESUME;                         /* and quit */
+    } else {                           /* otherwise */
+       if (x == -17)
+         xxscreen(SCR_ST,ST_SKIP,SKP_RES,"");
+       ack();                          /* acknowledge the EOF packet */
+       BEGIN rfile;                    /* and await another file */
+    }
+}
+    break;
+case 60:
+    {                                  /* Ctrl-C or connection loss. */
+    timint = s_timint;
+    window(1);                         /* Set window size back to 1... */
+    cxseen = 1;
+    x = clsof(1);                      /* Close file */
+    return(success = 0);               /* Failed */
+}
+    break;
+case 61:
+    {                          /* End Of File (EOF) Packet */
+/*  wslots = 1;        */                      /* (don't set) Window size back to 1 */
+#ifndef COHERENT /* Coherent compiler blows up on this switch() statement. */
+    x = reof(filnam, &iattr);          /* Handle the EOF packet */
+    switch (x) {                       /* reof() sets the success flag */
+      case -5:                         /* Handle problems */
+       errpkt((CHAR *)"RENAME failed"); /* Fatal */
+       RESUME;
+       break;
+      case -4:
+       errpkt((CHAR *)"MOVE failed");  /* Fatal */
+       RESUME;
+       break;
+      case -3:                         /* If problem, send error msg */
+       errpkt((CHAR *)"Can't print file"); /* Fatal */
+       RESUME;
+       break;
+      case -2:
+       errpkt((CHAR *)"Can't mail file"); /* Fatal */
+       RESUME;
+       break;
+      case 2:                          /* Not fatal */
+      case 3:
+       xxscreen(SCR_EM,0,0L,"Receiver can't delete temp file");
+       RESUME;
+       break;
+      default:
+       if (x < 0) {                    /* Fatal */
+           errpkt((CHAR *)"Can't close file");
+           RESUME;
+       } else {                        /* Success */
+#ifndef NOSPL
+           if (query)                  /* Query reponses generally */
+             conoll("");               /* don't have line terminators */
+#endif /* NOSPL */
+           if (czseen) {               /* Batch canceled? */
+               if (cancel++ == 0) {    /* If we haven't tried this yet */
+                   ack1((CHAR *)"Z");  /* Try it once */
+               } else {                /* Otherwise */
+                   errpkt((CHAR *)"User canceled"); /* quite with Error */
+                   RESUME;
+               }
+           } else
+             ack();                    /* Acknowledge the EOF packet */
+           BEGIN rfile;                /* and await another file */
+       }
+    }
+#else
+    if (reof(filnam, &iattr) < 0) {    /* Close the file */
+       errpkt((CHAR *)"Error at end of file");
+       RESUME;
+    } else {                           /* reof() sets success flag */
+       ack();
+       BEGIN rfile;
+    }
+#endif /* COHERENT */
+}
+    break;
+case 62:
+    {                          /* ACK for Send-Init */
+    spar(rdatap);                      /* set parameters from it */
+    cancel = 0;
+    bctu = bctr;                       /* switch to agreed-upon block check */
+    bctl = (bctu == 4) ? 2 : bctu;     /* Set block-check length */
+#ifdef CK_RESEND
+    if ((sendmode == SM_RESEND) && (!atcapu || !rscapu)) { /* RESEND */
+       errpkt((CHAR *) "RESEND capabilities not negotiated");
+       RESUME;
+    } else {
+#endif /* CK_RESEND */
+       what = W_SEND;                  /* Remember we're sending */
+       lastxfer = W_SEND;
+       x = sfile(xflg);                /* Send X or F header packet */
+       cancel = 0;                     /* Reset cancellation counter */
+       if (x) {                        /* If the packet was sent OK */
+           if (!xflg && filcnt == 1)   /* and it's a real file */
+             crc16 = 0L;               /* Clear the file CRC */
+           resetc();                   /* reset per-transaction counters */
+           rtimer();                   /* reset timers */
+#ifdef GFTIMER
+           rftimer();
+#endif /* GFTIMER */
+           streamon();                 /* turn on streaming */
+#ifdef IKSDB
+           if (ikdbopen) slotstate(what,
+                                 (server ? "SERVER" : ""),
+                                 "SEND",
+                                 filnam
+                                 );
+#endif /* IKSDB */
+           BEGIN ssfile;               /* and switch to receive-file state */
+       } else {                        /* otherwise send error msg & quit */
+           s = xflg ? "Can't execute command" : (char *)epktmsg;
+           if (!*s) s = "Can't open file";
+           errpkt((CHAR *)s);
+           RESUME;
+       }
+#ifdef CK_RESEND
+    }
+#endif /* CK_RESEND */
+}
+    break;
+case 63:
+    {                          /* R packet was retransmitted. */
+    xsinit();                          /* Resend packet 0 */
+}
+    break;
+case 64:
+    {                          /* Same deal if G packet comes again */
+    xsinit();
+}
+    break;
+case 65:
+    {                          /* Same deal if C packet comes again */
+    xsinit();
+}
+    break;
+case 66:
+    {                          /* ACK for F or X packet */
+    srvptr = srvcmd;                   /* Point to string buffer */
+    decode(rdatap,putsrv,0);           /* Decode data field, if any */
+    putsrv(NUL);                       /* Terminate with null */
+    ffc = 0L;                          /* Reset file byte counter */
+    debug(F101,"<ssfile>Y cxseen","",cxseen);
+    if (*srvcmd) {                     /* If remote name was recorded */
+        if (sendmode != SM_RESEND) {
+           if (fdispla == XYFD_C || fdispla == XYFD_S)
+             xxscreen(SCR_AN,0,0L,(char *)srvcmd);
+           tlog(F110," remote name:",(char *) srvcmd,0L);
+           makestr(&psrfspec,(char *)srvcmd);
+        }
+    }
+    if (cxseen||czseen) {              /* Interrupted? */
+       debug(F101,"<ssfile>Y canceling","",0);
+       x = clsif();                    /* Close input file */
+       sxeof(1);                       /* Send EOF(D) */
+       BEGIN sseof;                    /* and switch to EOF state. */
+    } else if (atcapu) {               /* If attributes are to be used */
+       if (sattr(xflg | stdinf, 1) < 0) { /* send them */
+           errpkt((CHAR *)"Can't send attributes"); /* if problem, say so */
+           RESUME;                     /* and quit */
+       } else BEGIN ssattr;            /* if ok, switch to attribute state */
+    } else {                           /* Attributes not negotiated */
+       if (window(wslotn) < 0) {       /* Open window */
+           errpkt((CHAR *)"Can't open window");
+           RESUME;
+       } else if ((x = sdata()) == -2) { /* Send first data packet data */
+           window(1);                  /* Connection lost, reset window */
+           x = clsif();                /* Close input file */
+           return(success = 0);        /* Return failure */
+       } else if (x == -9) {           /* User interrupted */
+           errpkt((CHAR *)"User cancelled"); /* Send Error packet */
+           window(1);                  /* Set window size back to 1... */
+           timint = s_timint;          /* Restore timeout */
+           return(success = 0);        /* Failed */
+       } else if (x < 0) {             /* EOF (empty file) or interrupted */
+           window(1);                  /* put window size back to 1, */
+           debug(F101,"<ssfile>Y cxseen","",cxseen);
+           x = clsif();                /* If not ok, close input file, */
+           if (x < 0)                  /* treating failure as interruption */
+             cxseen = 1;               /* Send EOF packet */
+           seof(cxseen||czseen);
+           BEGIN sseof;                /* and switch to EOF state. */
+       } else {                        /* First data sent OK */
+           BEGIN ssdata;               /* All ok, switch to send-data state */
+       }
+    }
+}
+    break;
+case 67:
+    {                          /* Got ACK to A packet */
+    ffc = 0L;                          /* Reset file byte counter */
+    debug(F101,"<ssattr>Y cxseen","",cxseen);
+    if (cxseen||czseen) {              /* Interrupted? */
+       debug(F101,"<sattr>Y canceling","",0);
+       x = clsif();                    /* Close input file */
+       sxeof(1);                       /* Send EOF(D) */
+       BEGIN sseof;                    /* and switch to EOF state. */
+    } else if (rsattr(rdatap) < 0) {   /* Was the file refused? */
+       discard = 1;                    /* Set the discard flag */
+       clsif();                        /* Close the file */
+       sxeof(1);                       /* send EOF with "discard" code */
+       BEGIN sseof;                    /* switch to send-EOF state */
+    } else if ((x = sattr(xflg | stdinf, 0)) < 0) { /* Send more? */
+       errpkt((CHAR *)"Can't send attributes"); /* Trouble... */
+       RESUME;
+    } else if (x == 0) {               /* No more to send so now the data */
+       if (window(wslotn) < 0) {       /* Allocate negotiated window slots */
+           errpkt((CHAR *)"Can't open window");
+           RESUME;
+       }
+       if ((x = sdata()) == -2) {      /* File accepted, send first data */
+           window(1);                  /* Connection broken */
+           x = clsif();                /* Close file */
+           return(success = 0);        /* Return failure */
+       } else if (x == -9) {           /* User interrupted */
+           errpkt((CHAR *)"User cancelled"); /* Send Error packet */
+           window(1);                  /* Set window size back to 1... */
+           timint = s_timint;          /* Restore timeout */
+           return(success = 0);        /* Failed */
+       } else if (x < 0) {             /* If data was not sent */
+           window(1);                  /* put window size back to 1, */
+           debug(F101,"<ssattr>Y cxseen","",cxseen);
+           if (clsif() < 0)            /* Close input file */
+             cxseen = 1;               /* Send EOF packet */
+           seof(cxseen||czseen);
+           BEGIN sseof;                /* and switch to EOF state. */
+       } else {
+           BEGIN ssdata;               /* All ok, switch to send-data state */
+       }
+    }
+}
+    break;
+case 68:
+    {                                  /* Ctrl-C or connection loss. */
+    window(1);                         /* Set window size back to 1... */
+    cxseen = 1;                                /* To indicate interruption */
+    x = clsif();                       /* Close file */
+    return(success = 0);               /* Failed */
+}
+    break;
+case 69:
+    {                          /* Got ACK to Data packet */
+    canned(rdatap);                    /* Check if file transfer cancelled */
+    debug(F111,"<ssdata>Y cxseen",rdatap,cxseen);
+    debug(F111,"<ssdata>Y czseen",rdatap,czseen);
+    if ((x = sdata()) == -2) {         /* Try to send next data */
+       window(1);                      /* Connection lost, reset window */
+       x = clsif();                    /* Close file */
+       return(success = 0);            /* Failed */
+    } else if (x == -9) {              /* User interrupted */
+       errpkt((CHAR *)"User cancelled"); /* Send Error packet */
+       window(1);                      /* Set window size back to 1... */
+       timint = s_timint;              /* Restore original timeout */
+       return(success = 0);            /* Failed */
+    } else if (x < 0) {                        /* EOF - finished sending data */
+       debug(F101,"<ssdata>Y cxseen","",cxseen);
+       window(1);                      /* Set window size back to 1... */
+       if (clsif() < 0)                /* Close input file */
+         cxseen = 1;                   /* Send EOF packet */
+       debug(F101,"<ssdata>Y CALLING SEOF()","",cxseen);
+       seof(cxseen||czseen);
+       BEGIN sseof;                    /* and enter send-eof state */
+    }
+    /* NOTE: If x == 0 it means we're draining: see sdata()! */
+}
+    break;
+case 70:
+    {                          /* Got ACK to EOF */
+    int g, xdiscard;
+    canned(rdatap);                    /* Check if file transfer cancelled */
+    debug(F111,"<sseof>Y cxseen",rdatap,cxseen);
+    debug(F111,"<sseof>Y czseen",rdatap,czseen);
+    debug(F111,"<sseof>Y discard",rdatap,discard);
+    xdiscard = discard;
+    discard = 0;
+    success = (cxseen == 0 && czseen == 0); /* Transfer status... */
+    debug(F101,"<sseof>Y success","",success);
+    if (success && rejection > 0)          /* If rejected, succeed if */
+      if (rejection != '#' &&              /* reason was date */
+         rejection != 1 && rejection != '?') /* or name; */
+       success = 0;                        /* fail otherwise. */
+    cxseen = 0;                                /* This goes back to zero. */
+    if (success) {                     /* Only if transfer succeeded... */
+       xxscreen(SCR_ST,ST_OK,0L,"");
+       if (!xdiscard) {
+           makestr(&sfspec,psfspec);   /* Record filenames for WHERE */
+           makestr(&srfspec,psrfspec);
+       }
+       if (moving) {                   /* If MOVE'ing */
+           x = zdelet(filnam);         /* Try to delete the source file */
+#ifdef TLOG
+           if (tralog) {
+               if (x > -1) {
+                   tlog(F110," deleted",filnam,0);
+               } else {
+                   tlog(F110," delete failed:",ck_errstr(),0);
+               }
+           }
+#endif /* TLOG */
+       } else if (snd_move) {          /* Or move it */
+           int x;
+           x = zrename(filnam,snd_move);
+#ifdef TLOG
+           if (tralog) {
+               if (x > -1) {
+                   tlog(F110," moved to ",snd_move,0);
+               } else {
+                   tlog(F110," move failed:",ck_errstr(),0);
+               }
+           }
+#endif /* TLOG */
+       } else if (snd_rename) {        /* Or rename it */
+           char *s = snd_rename;       /* Renaming string */
+#ifndef NOSPL
+           int y;                      /* Pass it thru the evaluator */
+           extern int cmd_quoting;     /* for \v(filename) */
+           if (cmd_quoting) {          /* But only if cmd_quoting is on */
+               y = MAXRP;
+               s = (char *)srvcmd;
+               zzstring(snd_rename,&s,&y);
+               s = (char *)srvcmd;
+           }
+#endif /* NOSPL */
+           if (s) if (*s) {
+               int x;
+               x = zrename(filnam,s);
+#ifdef TLOG
+           if (tralog) {
+               if (x > -1) {
+                   tlog(F110," renamed to",s,0);
+               } else {
+                   tlog(F110," rename failed:",ck_errstr(),0);
+               }
+           }
+#endif /* TLOG */
+#ifdef COMMENT
+               *s = NUL;
+#endif /* COMMENT */
+           }
+       }
+    }
+    if (czseen) {                      /* Check group interruption flag */
+       g = 0;                          /* No more files if interrupted */
+    } else {                           /* Otherwise... */
+#ifdef COMMENT
+       /* This code makes any open error fatal to a file-group transfer. */
+       g = gnfile();
+       debug(F111,"<sseof>Y gnfile",filnam,g);
+       if (g > 0) {                    /* Any more files to send? */
+           if (sfile(xflg))            /* Yes, try to send next file header */
+             BEGIN ssfile;             /* if ok, enter send-file state */
+           else {                      /* otherwise */
+               s = xflg ? "Can't execute command" : (char *)epktmsg;
+               if (!*s) s = "Can't open file";
+               errpkt((CHAR *)s);      /* send error message */
+               RESUME;                 /* and quit */
+           }
+       } else {                        /* No next file */
+           tsecs = gtimer();           /* get statistics timers */
+#ifdef GFTIMER
+           fptsecs = gftimer();
+#endif /* GFTIMER */
+           seot();                     /* send EOT packet */
+           BEGIN sseot;                /* enter send-eot state */
+       }
+#else  /* COMMENT */
+       while (1) {                     /* Keep trying... */
+           g = gnfile();               /* Get next file */
+           debug(F111,"<sseof>Y gnfile",filnam,g);
+           if (g == 0 && gnferror == 0) /* No more, stop trying */
+             break;
+           if (g > 0) {                /* Have one */
+               if (sfile(xflg)) {      /* Try to open and send F packet */
+                   BEGIN ssfile;       /* If OK, enter send-file state */
+                   break;              /* and break out of loop. */
+               }
+           } /* Otherwise keep trying to get one we can send... */
+       }
+    }
+    if (g == 0) {
+       debug(F101,"<sseof>Y no more files","",czseen);
+       tsecs = gtimer();               /* Get statistics timers */
+#ifdef GFTIMER
+       fptsecs = gftimer();
+#endif /* GFTIMER */
+       seot();                         /* Send EOT packet */
+       BEGIN sseot;                    /* Enter send-eot state */
+    }
+#endif /* COMMENT */
+}
+    break;
+case 71:
+    {                          /* Got ACK to EOT */
+    debug(F101,"sseot justone","",justone);
+    RESUME;                            /* All done, just quit */
+}
+    break;
+case 72:
+    {                                  /* Got Error packet, in any state */
+    char *s = "";
+    window(1);                         /* Close window */
+    timint = s_timint;                 /* Restore original timeout */
+    if (*epktmsg)                      /* Message from Error packet */
+      s = (char *)epktmsg;
+    if (!*s) {                         /* If not there then maybe here */
+       s = (char *)rdatap;
+       ckstrncpy((char *)epktmsg,(char *)rdatap,PKTMSGLEN);
+    }
+    if (!*s)                           /* Hopefully we'll never see this. */
+      s = "Unknown error";
+    success = 0;                       /* For IF SUCCESS/FAIL. */
+    debug(F101,"ckcpro.w justone at E pkt","",justone);
+
+    success = 0;                       /* Transfer failed */
+    xferstat = success;                        /* Remember transfer status */
+    if (!epktsent) {
+       x = quiet; quiet = 1;           /* Close files silently, */
+       epktrcvd = 1;                   /* Prevent messages from clsof() */
+       clsif();
+       clsof(1);                       /* discarding any output file. */
+       ermsg(s);                       /* Issue the message (calls screen). */
+       quiet = x;                      /* Restore quiet state */
+    }
+    tstats();                          /* Get stats */
+/*
+  If we are executing commands from a command file or macro, let the command
+  file or macro decide whether to exit, based on SET { TAKE, MACRO } ERROR.
+*/
+    if (
+#ifndef NOICP
+       !xcmdsrc &&
+#endif /* NOICP */
+       backgrd && !server)
+      fatal("Protocol error");
+    xitsta |= (what & W_KERMIT);       /* Save this for doexit(). */
+#ifdef CK_TMPDIR
+/* If we were cd'd temporarily to another device or directory ... */
+    if (f_tmpdir) {
+       int x;
+       x = zchdir((char *) savdir);    /* ... restore previous directory */
+       f_tmpdir = 0;                   /* and remember we did it. */
+       debug(F111,"ckcpro.w E tmpdir restored",savdir,x);
+    }
+#endif /* CK_TMPDIR */
+#ifdef IKSDB
+    if (ikdbopen) slotstate(what,"ERROR", (char *)epktmsg, "");
+#endif /* IKSDB */
+    RESUME;
+}
+    break;
+case 73:
+    { success = 0; QUIT; }
+    break;
+case 74:
+    {                                  /* Anything not accounted for above */
+    errpkt((CHAR *)"Unexpected packet type"); /* Give error message */
+    window(1);
+    xitsta |= (what & W_KERMIT);       /* Save this for doexit(). */
+    RESUME;                            /* and quit */
+}
+    break;
+
+           }
+    }
+}
+
+char tbl[] = {
+ -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 11, 74,  7, 74, 74, 74,  9,  4, 74,  5,  8, 74, 74, 74,  6,
+ 74, 73,  3,  1, 74, 74,  2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
+ -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 15, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74, 74, 13, 74, 74, 74, 74, 74, 74,
+ 74, 11, 74,  7, 74, 74, 74,  9,  4, 74,  5,  8, 74, 74, 74,  6,
+ 74, 73,  3,  1, 74, 74,  2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
+ -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 57, 74, 74, 72, 53, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74, 54, 74, 74, 74, 74, 74, 74, 74,
+ 74, 11, 74,  7, 74, 74, 74,  9,  4, 74,  5,  8, 74, 74, 74,  6,
+ 74, 73,  3,  1, 74, 74,  2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
+ -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 55, 74, 74, 56, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 59, 74, 74, 74, 74, 74,
+ 74, 11, 74,  7, 74, 74, 74,  9,  4, 74,  5,  8, 74, 74, 74,  6,
+ 74, 73,  3,  1, 74, 74,  2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
+ -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 58, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 61, 74, 74, 74, 74, 74,
+ 74, 11, 74,  7, 74, 74, 74,  9,  4, 74,  5,  8, 74, 74, 74,  6,
+ 74, 60,  3,  1, 74, 74,  2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
+ -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 65, 74, 72, 74, 64, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 63, 74, 74, 74, 74, 74, 74, 62, 74, 74, 74, 74, 74, 74,
+ 74, 11, 74,  7, 74, 74, 74,  9,  4, 74,  5,  8, 74, 74, 74,  6,
+ 74, 73,  3,  1, 74, 74,  2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
+ -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74, 74, 66, 74, 74, 74, 74, 74, 74,
+ 74, 11, 74,  7, 74, 74, 74,  9,  4, 74,  5,  8, 74, 74, 74,  6,
+ 74, 73,  3,  1, 74, 74,  2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
+ -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74, 74, 67, 74, 74, 74, 74, 74, 74,
+ 74, 11, 74,  7, 74, 74, 74,  9,  4, 74,  5,  8, 74, 74, 74,  6,
+ 74, 73,  3,  1, 74, 74,  2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
+ -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74, 74, 69, 74, 74, 74, 74, 74, 74,
+ 74, 11, 74,  7, 74, 74, 74,  9,  4, 74,  5,  8, 74, 74, 74,  6,
+ 74, 68,  3,  1, 74, 74,  2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
+ -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74, 74, 70, 74, 74, 74, 74, 74, 74,
+ 74, 11, 74,  7, 74, 74, 74,  9,  4, 74,  5,  8, 74, 74, 74,  6,
+ 74, 73,  3,  1, 74, 74,  2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
+ -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74, 74, 71, 74, 74, 74, 74, 74, 74,
+ 74, 11, 74,  7, 74, 74, 74,  9,  4, 74,  5,  8, 74, 74, 74,  6,
+ 74, 73,  3,  1, 74, 74,  2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
+ -1, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 26, 29, 29, 29, 25, 19, 17, 22, 29, 29, 29, 28, 23,
+ 29, 29, 18, 12, 29, 29, 20, 21, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 11, 29,  7, 29, 29, 29,  9,  4, 29,  5,  8, 29, 29, 29,  6,
+ 29, 27,  3,  1, 29, 29,  2, 29, 10, 29, 29, 29, 29, 29, 29, 29,
+ -1, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 32, 50, 31, 33, 34, 35, 50, 38, 30, 50, 40, 37, 48, 50, 50,
+ 50, 50, 39, 41, 42, 45, 47, 46, 36, 50, 50, 50, 50, 50, 50, 50,
+ 50, 11, 50,  7, 44, 50, 50,  9,  4, 50,  5,  8, 50, 43, 50,  6,
+ 50, 49,  3,  1, 50, 50,  2, 50, 10, 50, 50, 50, 50, 50, 50, 50,
+ -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 72, 74, 74, 74, 17, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 12, 74, 74, 74, 74, 74, 16, 74, 74, 74, 74, 74, 74,
+ 74, 11, 74,  7, 74, 74, 74,  9,  4, 74,  5,  8, 74, 74, 74,  6,
+ 74, 73,  3,  1, 74, 74,  2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
+ -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 72, 53, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 12, 74, 74, 74, 74, 54, 52, 74, 74, 74, 74, 74, 74,
+ 74, 11, 74,  7, 74, 74, 74,  9,  4, 74,  5,  8, 74, 74, 74,  6,
+ 74, 51,  3,  1, 74, 74,  2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
+ -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74, 74, 14, 74, 74, 74, 74, 74, 74,
+ 74, 11, 74,  7, 74, 74, 74,  9,  4, 74,  5,  8, 74, 74, 74,  6,
+ 74, 73,  3,  1, 74, 74,  2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
+  0, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 24,
+ 74, 74, 74, 12, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 11, 74,  7, 74, 74, 74,  9,  4, 74,  5,  8, 74, 74, 74,  6,
+ 74, 73,  3,  1, 74, 74,  2, 74, 10, 74, 74, 74, 74, 74, 74,74
+};
+
+
+/*
+  From here down to proto() are routines that were moved out of the state
+  table switcher because the resulting switch() had become too large.
+  To move the contents of a state-table case to a routine:
+    1. Add a prototype to the list above the state table switcher.
+    2. Make a routine with an appropriate name, returning int.
+    3. Move the code into it.
+    4. Put a call to the new routine in the former spot:
+         rc = name_of_routine();
+         if (rc > -1) return(rc);
+    5. Add "return(-1);" after every RESUME, SERVE, or BEGIN macro and
+       at the end if the code is open-ended.
+*/
+static int
+rcv_firstdata() {
+    extern int dispos;
+    debug(F101,"rcv_firstdata","",dispos);
+
+    if (discard) {                     /* if we're discarding the file */
+       ack1((CHAR *)"X");              /* just ack the data like this. */
+       cancel++;                       /* and count it */
+       BEGIN rdpkt;                    /* and wait for more data packets. */
+       return(-1);
+    } else {                           /* Not discarding. */
+       rf_err = "Can't open file";
+       if (xflg) {                     /* If screen data */
+           if (remfile) {              /* redirected to file */
+               if (rempipe)            /* or pipe */
+                 x = openc(ZOFILE,remdest); /* Pipe: start command */
+               else
+                 x = opena(remdest,&iattr); /* File: open with attributes */
+           } else {                    /* otherwise */
+               x = opent(&iattr);      /* "open" the screen */
+           }
+       } else {                        /* otherwise */
+#ifdef CALIBRATE
+           if (calibrate) {            /* If calibration run */
+               x = ckopenx(&iattr);    /* open nothing */
+#ifdef STREAMING
+               if (streaming)          /* Streaming */
+                 fastack();            /* ACK without ACKing. */
+               else
+#endif /* STREAMING */
+                 ack();                /* Send real ACK */
+               BEGIN rdpkt;            /* Proceed to next state */
+               return(-1);
+           } else
+#endif /* CALIBRATE */
+#ifdef UNIX
+/*
+  In UNIX we can pipe the file data into the mail program, which is to be
+  preferred to writing it out to a temp file and then mailing it afterwards.
+  This depends rather heavily on all UNIXes having a mail command that
+  accepts '-s "subject"' on the command line.  MAILCMD (e.g. mail, Mail, mailx)
+  is defined in ckufio.c.
+*/
+           if (dispos == 'M') {        /* Mail... */
+               char *s;
+               char * tmp = NULL;
+               int n = 0;
+               extern char *MAILCMD;
+               s = iattr.disp.val + 1;
+               n = (int)strlen(MAILCMD) +    /* Mail command */
+                 (int)strlen(s) +            /* address */
+                 (int)strlen(ofilnam) + 32;  /* subject */
+               if (tmp = (char *)malloc(n)) {
+                   ckmakxmsg(tmp,n,
+                             MAILCMD," -s \"",ofilnam,"\" ",s,
+                             NULL,NULL,NULL,NULL,NULL,NULL,NULL);
+                   debug(F111,"rcv_firsdata mail",tmp,(int)strlen(tmp));
+                   x = openc(ZOFILE,(char *)tmp);
+                   free(tmp);
+               } else
+                 x = 0;
+           } else if (dispos == 'P') { /* Ditto for print */
+               char * tmp = NULL;
+               int n;
+               extern char *PRINTCMD;
+               n = (int)strlen(PRINTCMD) + (int)strlen(iattr.disp.val+1) + 4;
+               if (tmp = (char *)malloc(n)) {
+                   sprintf(tmp,        /* safe (prechecked) */
+                           "%s %s", PRINTCMD, iattr.disp.val + 1);
+                   x = openc(ZOFILE,(char *)tmp);
+                   free(tmp);
+               } else
+                 x = 0;
+           } else
+#endif /* UNIX */
+             x = opena(filnam,&iattr); /* open the file, with attributes */
+       }
+       if (x) {                        /* If file was opened ok */
+           int rc, qf;
+#ifndef NOSPL
+           qf = query;
+#else
+           qf = 0;
+#endif /* NOSPL */
+
+#ifdef CKTUNING
+           rc = (binary && !parity) ?
+             bdecode(rdatap,putfil):
+              decode(rdatap, qf ? puttrm : putfil, 1);
+#else
+           rc = decode(rdatap, qf ? puttrm : putfil, 1);
+#endif /* CKTUNING */
+           if (rc < 0) {
+               errpkt((CHAR *)"Error writing data");
+               RESUME;
+               return(-1);
+           }
+#ifdef STREAMING
+           if (streaming)              /* Streaming was negotiated */
+             fastack();                /* ACK without ACKing. */
+           else
+#endif /* STREAMING */
+             ack();                    /* acknowledge it */
+           BEGIN rdpkt;                /* and switch to receive-data state */
+           return(-1);
+       } else {                        /* otherwise */
+           errpkt((CHAR *) rf_err);    /* send error packet */
+           RESUME;                     /* and quit. */
+           return(-1);
+       }
+    }
+}
+
+static int
+rcv_shortreply() {
+#ifdef PKTZEROHACK
+    success = 0;
+    debug(F111,"rcv_shortreply",rdatap,ipktlen);
+    if (ipktack[0] && !strncmp(ipktack,(char *)rdatap,ipktlen)) {
+       /* No it's the ACK to the I packet again */
+       x = scmd(vcmd,(CHAR *)cmarg);   /* So send the REMOTE command again */
+       /* Maybe this should be resend() */
+       debug(F110,"IPKTZEROHACK",ipktack,x);
+       if (x < 0) {
+           errpkt((CHAR *)srimsg);
+           RESUME;
+           return(-1);
+       }
+    } else {
+       ipktack[0] = NUL;
+#endif /* PKTZEROHACK */
+       urserver = 1;
+#ifndef NOSERVER
+#ifndef NOSPL
+       if (query) {                    /* If to query, */
+           qbufp = querybuf;           /*  initialize query response buffer */
+           qbufn = 0;
+           querybuf[0] = NUL;
+       }
+#endif /* NOSPL */
+       x = 1;
+       if (remfile) {                  /* Response redirected to file */
+           rf_err = "Can't open file";
+           if (rempipe)                /* or pipe */
+             x =
+#ifndef NOPUSH
+               zxcmd(ZOFILE,remdest)   /* Pipe: Start command */
+#else
+               0
+#endif /* NOPUSH */
+               ;
+           else
+             x = opena(remdest,&iattr); /* File: Open with attributes */
+           debug(F111,"rcv_shortreply remfile",remdest,x);
+       } else {
+           x = opent(&iattr);          /* "open" the screen */
+       }
+       if (x) {                        /* If file was opened ok */
+           if (decode(rdatap,
+#ifndef NOSPL
+                      (query || !remfile) ? puttrm :
+#else
+                      !remfile ? puttrm :
+#endif /* NOSPL */
+                      zputfil, 1) < 0) { /* Note: zputfil, not putfil. */
+               errpkt((CHAR *)"Error writing data");
+               RESUME;
+               return(-1);
+           } else {
+               if (rdatap)             /* If we had data */
+                 if (*rdatap)          /* add a line terminator */
+                   if (remfile) {      /* to file */
+                       zsoutl(ZOFILE,"");
+                   } else {            /* or to screen. */
+#ifndef NOICP
+                       if (!query || !xcmdsrc)
+#endif /* NOICP */
+                         if (!(quiet && rcdactive))
+                           conoll("");
+                   }
+               if (bye_active && network) { /* I sent BYE or REMOTE LOGOUT */
+                   msleep(500);        /* command and got the ACK... */
+                   bye_active = 0;
+                   ttclos(0);
+               }
+               clsof(0);
+               if (!epktsent && !epktrcvd) /* If no error packet... */
+                 success = 1;          /* success. */
+               RESUME;
+               return(-1);
+           }
+       } else {                        /* File not opened OK */
+           errpkt((CHAR *) rf_err);    /* send error message */
+           RESUME;                     /* and quit. */
+           return(-1);
+       }
+#endif /* NOSERVER */
+#ifdef PKTZEROHACK
+    }
+#endif /* PKTZEROHACK */
+    debug(F101,"rcv_shortreply fallthru","",success);
+    return(-1);
+}
+
+
+static int
+srv_query() {
+#ifndef NOSERVER
+#ifndef NOSPL
+    char c;
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE QUERY", (char *)srvcmd);
+#endif /* CKSYSLOG */
+#ifdef IKSDB
+    if (ikdbopen) slotstate(what,"REMOTE QUERY", (char *)(srvcmd+2), "");
+#endif /* IKSDB */
+    c = *(srvcmd+2);                   /* Q = Query, S = Set */
+    if (c == 'Q') {                    /* Query */
+       if (!ENABLED(en_que)) { /* Security */
+           errpkt((CHAR *)"REMOTE QUERY disabled");
+           RESUME;
+           return(-1);
+       } else {                        /* Query allowed */
+           int n; char *p, *q;
+           qbufp = querybuf;           /* Wipe out old stuff */
+           qbufn = 0;
+           querybuf[0] = NUL;
+           p = (char *) srvcmd + 3;    /* Pointer for making wrapper */
+           n = strlen((char *)srvcmd); /* Position of end */
+           c = *(srvcmd+4);            /* Which type of variable */
+
+           if (*(srvcmd+6) == CMDQ) {  /* Starts with command quote? */
+               p = (char *) srvcmd + 6; /* Take it literally */
+               if (*p == CMDQ) p++;
+           } else {                    /* They played by the rules */
+               if (c == 'K') {         /* Kermit variable */
+                   int k;
+                   k = (int) strlen(p);
+                   if (k > 0 && p[k-1] == ')') {
+                       p = (char *)(srvcmd + 4);
+                       *(srvcmd+4) = CMDQ;
+                       *(srvcmd+5) = 'f'; /* Function, so make it \f...() */
+                   } else {
+                       *(srvcmd+3) = CMDQ; /* Stuff wrapping into buffer */
+                       *(srvcmd+4) = 'v';  /* Variable, so make it \v(...) */
+                       *(srvcmd+5) = '(';  /* around variable name */
+                       *(srvcmd+n) = ')';
+                       *(srvcmd+n+1) = NUL;
+                   }
+               } else {
+                   *(srvcmd+3) = CMDQ; /* Stuff wrapping into buffer */
+                   *(srvcmd+4) = 'v'; /*  Variable, so make it \v(...) */
+                   *(srvcmd+5) = '(';  /* around variable name */
+                   *(srvcmd+n) = ')';
+                   *(srvcmd+n+1) = NUL;
+                   if (c == 'S') {     /* System variable */
+                       *(srvcmd+4) = '$'; /*  so it's \$(...) */
+                   } else if (c == 'G') { /* Non-\ Global variable */
+                       *(srvcmd+4) = 'm'; /*  so wrap it in \m(...) */
+                   }
+               }
+           }                           /* Now evaluate it */
+           n = QBUFL;                  /* Max length */
+           q = querybuf;               /* Where to put it */
+           if (zzstring(p,&q,&n) < 0) {
+               errpkt((n > 0) ? (CHAR *)"Can't get value"
+                              : (CHAR *)"Value too long"
+                      );
+               RESUME;
+               return(-1);
+           } else {
+               if (encstr((CHAR *)querybuf) > -1) { /* Encode it */
+                   ack1(data);         /* If it fits, send it back in ACK */
+                   success = 1;
+                   RESUME;
+                   return(-1);
+               } else if (sndstring(querybuf)) { /* Long form response */
+                   BEGIN ssinit;
+                   return(-1);
+               } else {                /* sndhlp() fails */
+                   errpkt((CHAR *)"Can't send value");
+                   RESUME;
+                   return(-1);
+               }
+           }
+       }
+    } else if (c == 'S') {             /* Set (assign) */
+       if (!ENABLED(en_asg)) {         /* Security */
+           errpkt((CHAR *)"REMOTE ASSIGN disabled");
+           RESUME;
+           return(-1);
+       } else {                        /* OK */
+           int n;
+           n = xunchar(*(srvcmd+3));   /* Length of name */
+           n = 3 + n + 1;              /* Position of length of value */
+           *(srvcmd+n) = NUL;          /* Don't need it */
+           if (addmac((char *)(srvcmd+4),(char *)(srvcmd+n+1)) < 0)
+             errpkt((CHAR *)"REMOTE ASSIGN failed");
+           else {
+               ack();
+               success = 1;
+           }
+           RESUME;
+           return(-1);
+       }
+    } else {
+       errpkt((CHAR *)"Badly formed server command");
+       RESUME;
+       return(-1);
+    }
+#else
+    errpkt((CHAR *)"Variable query/set not available");
+    RESUME;
+    return(-1);
+#endif /* NOSPL */
+#endif /* NOSERVER */
+}
+
+static int
+srv_copy() {
+#ifndef NOSERVER
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE COPY", (char *)srvcmd);
+#endif /* CKSYSLOG */
+#ifdef ZCOPY
+    if (!ENABLED(en_cpy)) {
+       errpkt((CHAR *)"REMOTE COPY disabled");
+       RESUME;
+       return(-1);
+    } else {
+       char *str1, *str2, f1[256], f2[256];
+       int  len1, len2;
+        len1 = xunchar(srvcmd[1]);     /* Separate the parameters */
+        len2 = xunchar(srvcmd[2+len1]);
+        strncpy(f1,(char *)(srvcmd+2),len1);
+        f1[len1] = NUL;
+        strncpy(f2,(char *)(srvcmd+3+len1),len2);
+        f2[len2] = NUL;
+#ifdef IKSDB
+       if (ikdbopen) slotstate(what,"REMOTE COPY", f1, f2);
+#endif /* IKSDB */
+       if (!ENABLED(en_cwd)) {         /* If CWD is disabled */
+           zstrip(f1,&str1);           /* and they included a pathname, */
+            zstrip(f2,&str2);
+           if (strcmp(f1,str1) || strcmp(f2,str2)) { /* Refuse. */
+               errpkt((CHAR *)"Access denied");
+               RESUME;                 /* Remember, this is not a goto! */
+               return(-1);
+           }
+       }
+       if (state == generic) {         /* It's OK to go ahead. */
+            if (zcopy(f1,f2)) {                /* Try */
+               errpkt((CHAR *)"Can't copy file"); /* give error message */
+           } else {
+               success = 1;
+               ack();
+           }
+            RESUME;                    /* wait for next server command */
+           return(-1);
+       }
+    }
+    return(-1);
+#else /* no ZCOPY */
+    errpkt((CHAR *)"REMOTE COPY not available"); /* give error message */
+    RESUME;                            /* wait for next server command */
+    return(-1);
+#endif /* ZCOPY */
+#endif /* NOSERVER */
+}
+
+static int
+srv_rename() {
+#ifndef NOSERVER
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE RENAME", (char *)srvcmd);
+#endif /* CKSYSLOG */
+#ifdef ZRENAME
+    if (!ENABLED(en_ren)) {
+       errpkt((CHAR *)"REMOTE RENAME disabled");
+       RESUME;
+       return(-1);
+    } else {                           /* RENAME is enabled */
+       char *str1, *str2, f1[256], f2[256];
+       int len1, len2;
+       len1 = xunchar(srvcmd[1]);      /* Separate the parameters */
+       len2 = xunchar(srvcmd[2+len1]);
+       strncpy(f1,(char *)(srvcmd+2),len1);
+       f1[len1] = NUL;
+       strncpy(f2,(char *)(srvcmd+3+len1),len2);
+       f2[len2] = NUL;
+       len2 = xunchar(srvcmd[2+len1]);
+       strncpy(f1,(char *)(srvcmd+2),len1);
+       f1[len1] = NUL;
+       strncpy(f2,(char *)(srvcmd+3+len1),len2);
+       f2[len2] = NUL;
+#ifdef IKSDB
+       if (ikdbopen) slotstate(what,"REMOTE RENAME", f1, f2);
+#endif /* IKSDB */
+       if (!ENABLED(en_cwd)) {         /* If CWD is disabled */
+           zstrip(f1,&str1);           /* and they included a pathname, */
+           zstrip(f2,&str2);
+           if ( strcmp(f1,str1) || strcmp(f2,str2) ) { /* refuse. */
+               errpkt((CHAR *)"Access denied");
+               RESUME;                 /* Remember, this is not a goto! */
+               return(-1);
+           }
+       }
+       if (state == generic) {         /* It's OK to go ahead. */
+           if (zrename(f1,f2)) {       /* Try */
+               errpkt((CHAR *)"Can't rename file"); /* Give error msg */
+           } else {
+               success = 1;
+               ack();
+           }
+           RESUME;                     /* Wait for next server command */
+           return(-1);
+       }
+    }
+    return(-1);
+#else /* no ZRENAME */
+    /* Give error message */
+    errpkt((CHAR *)"REMOTE RENAME not available");
+    RESUME;                            /* Wait for next server command */
+    return(-1);
+#endif /* ZRENAME */
+#endif /* NOSERVER */
+}
+
+static int
+srv_login() {
+#ifndef NOSERVER
+    char f1[LOGINLEN+1], f2[LOGINLEN+1], f3[LOGINLEN+1];
+    CHAR *p;
+    int len, i;
+
+    debug(F101,"REMOTE LOGIN x_login","",x_login);
+    debug(F101,"REMOTE LOGIN x_logged","",x_logged);
+
+    f1[0] = NUL; f2[0] = NUL; f3[0] = NUL;
+    len = 0;
+    if (srvcmd[1])                     /* First length field */
+      len = xunchar(srvcmd[1]);                /* Separate the parameters */
+
+    if (x_login) {                     /* Login required */
+       if (x_logged) {                 /* And already logged in */
+           if (len > 0) {              /* Logging in again */
+               errpkt((CHAR *)"Already logged in.");
+           } else {                    /* Logging out */
+               debug(F101,"REMOTE LOGOUT","",x_logged);
+#ifdef CKSYSLOG
+               if (ckxsyslog >= SYSLG_PR && ckxlogging)
+                 cksyslog(SYSLG_PR, 1, "server", "REMOTE LOGOUT", NULL);
+#endif /* CKSYSLOG */
+#ifdef IKSDB
+               if (ikdbopen) slotstate(what,"REMOTE LOGOUT", "", "");
+#endif /* IKSDB */
+               tlog(F110,"Logged out",x_user,0);
+               ack1((CHAR *)"Logged out");
+               success = 1;
+               msleep(500);
+#ifdef CK_LOGIN
+               x_logged = 0;
+#ifdef IKSD
+               if (inserver)
+                 ckxlogout();
+#endif /* IKSD */
+#endif /* CK_LOGIN */
+           }
+       } else {                        /* Not logged in yet */
+           debug(F101,"REMOTE LOGIN len","",len);
+           if (len > 0) {              /* Have username */
+#ifdef CKSYSLOG
+               if (ckxsyslog >= SYSLG_PR && ckxlogging)
+                 cksyslog(SYSLG_PR, 1, "server", "REMOTE LOGIN", NULL);
+#endif /* CKSYSLOG */
+               if (len > LOGINLEN) {
+                   errpkt((CHAR *)"Username too long");
+               }
+               p = srvcmd + 2;         /* Point to it */
+               for (i = 0; i < len; i++) /* Copy it */
+                 f1[i] = p[i];
+               f1[len] = NUL;          /* Terminate it */
+               p += len;               /* Point to next length field */
+               if (*p) {               /* If we have one */
+                   len = xunchar(*p++); /* decode it */
+                   if (len > 0 && len <= LOGINLEN) {
+                       for (i = 0; i < len; i++) /* Same deal for password */
+                         f2[i] = p[i];
+                       f2[len] = NUL;
+                       p += len;       /* And account */
+                       if (*p) {
+                           len = xunchar(*p++);
+                           if (len > 0 && len <= LOGINLEN) {
+                               for (i = 0; i < len; i++)
+                                 f3[i] = p[i]; /* Set but never used */
+                               f3[len] = NUL; /* (because account not used) */
+                           }
+                       }
+                   }
+               }
+               debug(F101,"REMOTE LOGIN 1","",x_logged);
+#ifdef IKSD
+#ifdef CK_LOGIN
+               if (inserver) {         /* Log in to system for real */
+                   x_logged = ckxlogin((CHAR *)f1,(CHAR *)f2,NULL,0);
+                   debug(F101,"REMOTE LOGIN 2","",x_logged);
+                   if (x_logged) {     /* Count attempts */
+                       logtries = 0;
+                       justone = 1;
+                   } else {
+                       logtries++;
+                       sleep(logtries);
+                   }
+               } else
+#endif /* CK_LOGIN */
+#endif /* IKSD */
+                 if (x_user && x_passwd) { /* User and password must match */
+                     if (!strcmp(x_user,f1)) /* SET SERVER LOGIN */
+                       if (!strcmp(x_passwd,f2))
+                         x_logged = 1;
+                     debug(F101,"REMOTE LOGIN 3","",x_logged);
+                 } else if (x_user) {  /* Only username given, no password */
+                     if (!strcmp(x_user,f1)) /* so only username must match */
+                       x_logged = 1;
+                     debug(F101,"REMOTE LOGIN 4","",x_logged);
+                 }
+#ifdef CK_LOGIN 
+                else {
+                   x_logged = ckxlogin((CHAR *)f1,(CHAR *)f2,NULL,0);
+                   debug(F101,"REMOTE LOGIN 5","",x_logged);
+                }
+#endif /* CK_LOGIN */
+               if (x_logged) {         /* Logged in? */
+                   tlog(F110,"Logged in", x_user, 0);
+                   if (isguest)
+                     ack1((CHAR *)"Logged in as guest - restrictions apply");
+                   else
+                     ack1((CHAR *)"Logged in");
+                   success = 1;
+               } else {
+                   tlog(F110,"Login failed", f1, 0);
+                   errpkt((CHAR *)"Access denied.");
+#ifdef IKSD
+#ifdef CK_LOGIN
+                   if (inserver && logtries > 2)
+                     ckxlogout();
+#endif /* CK_LOGIN */
+#endif /* IKSD */
+               }
+           } else {                    /* LOGOUT */
+               errpkt((CHAR *)"Logout ignored");
+           }
+       }
+    } else {                           /* Login not required */
+       if (len > 0)
+         errpkt((CHAR *)"Login ignored.");
+       else
+         errpkt((CHAR *)"Logout ignored.");
+    }
+#endif /* NOSERVER */
+    RESUME;
+    return(-1);
+}
+
+static int
+srv_timeout() {
+    /* K95 does this its own way */
+    if (idletmo) {
+#ifdef IKSD
+        if (inserver) {
+           printf("\r\nIKSD IDLE TIMEOUT: %d sec\r\n", srvidl);
+           doexit(GOOD_EXIT,xitsta);
+        }
+#endif /* IKSD */
+       idletmo = 0;
+       printf("\r\nSERVER IDLE TIMEOUT: %d sec\r\n", srvidl);
+       xitsta |= (what & W_KERMIT);
+       QUIT;
+    }
+#ifndef NOSERVER
+    else if (fatalio) {                        /* Connection lost */
+#ifdef CKSYSLOG
+         if (ckxsyslog >= SYSLG_PR && ckxlogging)
+           cksyslog(SYSLG_PR, 1, "server", "Connection lost", NULL);
+#endif /* CKSYSLOG */
+#ifdef IKSDB
+         if (ikdbopen) slotstate(what,"SERVER DISCONNECT",(char *)srvcmd, "");
+#endif /* IKSDB */
+       xitsta |= what;
+       QUIT;
+    } else if (interrupted) {          /* Interrupted by hand */
+       if (!ENABLED(en_fin)) {
+           errpkt((CHAR *)"QUIT disabled");
+           RESUME;
+           return(-1);
+       } else {
+           if (what == W_SEND || what == W_RECV || what == W_REMO) {
+               success = 0;
+#ifdef CKSYSLOG
+               if (ckxsyslog >= SYSLG_PR && ckxlogging)
+                 cksyslog(SYSLG_PR, 1, "server", "Interrupted", NULL);
+#endif /* CKSYSLOG */
+           } else if (what == W_NOTHING && filcnt == 0) {
+               success = 1;
+           } /* Otherwise leave success alone */
+           xitsta |= (what & W_KERMIT);
+           QUIT;
+       }
+    } else {                           /* Shouldn't happen */
+       debug(F100,"SERVER (top) GOT UNEXPECTED 'q'","",0);
+       QUIT;
+    }
+#endif /* NOSERVER */
+}
+
+static int
+rcv_s_pkt() {
+#ifndef NOSERVER
+    if (state == rgen)
+      urserver = 1;
+    if (/* state == serve && */ x_login && !x_logged) {
+       errpkt((CHAR *)"Login required");
+       SERVE;
+    } else
+#endif /* NOSERVER */
+      if (state == serve && !ENABLED(en_sen)) { /* Not in server mode */
+       errpkt((CHAR *)"SEND disabled"); /* when SEND is disabled. */
+       RESUME;
+       return(-1);
+    } else {                           /* OK to go ahead. */
+#ifdef CK_TMPDIR
+       if (dldir && !f_tmpdir) {       /* If they have a download directory */
+           debug(F110,"receive download dir",dldir,0);
+           if (s = zgtdir()) {         /* Get current directory */
+               debug(F110,"receive current dir",s,0);
+               if (zchdir(dldir)) {    /* Change to download directory */
+                   debug(F100,"receive zchdir ok","",0);
+                   ckstrncpy(savdir,s,TMPDIRLEN);
+                   f_tmpdir = 1;       /* Remember that we did this */
+               } else
+                 debug(F100,"receive zchdir failed","",0);
+           }
+       }
+#endif /* CK_TMPDIR */
+       nakstate = 1;                   /* Can send NAKs from here. */
+       rinit(rdatap);                  /* Set parameters */
+       bctu = bctr;                    /* Switch to agreed-upon block check */
+       bctl = (bctu == 4) ? 2 : bctu;  /* Set block-check length */
+       what = W_RECV;                  /* Remember we're receiving */
+       lastxfer = W_RECV;
+       resetc();                       /* Reset counters */
+       rtimer();                       /* Reset timer */
+#ifdef GFTIMER
+       rftimer();
+#endif /* GFTIMER */
+       streamon();
+       BEGIN rfile;                    /* Go into receive-file state */
+    }
+    return(-1);
+}
+
+
+/* END OF ROUTINES MOVED OUT OF STATE MACHINE */
+
+
+/*  P R O T O  --  Protocol entry function  */
+
+static int is_tn = 0;                  /* It's a Telnet connection */
+
+#ifdef CK_SPEED
+int f_ctlp = 0;                                /* Control-character prefix table */
+#ifdef COMMENT
+short s_ctlp[256];
+#endif /* COMMENT */
+#endif /* CK_SPEED */
+
+/*
+  This is simply a wrapper for the real protocol function just below,
+  that saves any items that might be changed automatically by protocol
+  negotiations and then restores them upon exit from protocol mode.
+*/
+VOID
+proto() {
+    extern int b_save, f_save, c_save, ss_save, slostart, reliable, urclear;
+#ifndef NOCSETS
+    extern int fcharset, fcs_save, tcharset, tcs_save;
+#endif /* NOCSETS */
+
+#ifdef PIPESEND
+    extern int pipesend;
+#endif /* PIPESEND */
+#ifndef NOLOCAL
+#ifdef OS2
+    extern int cursorena[], cursor_save, term_io;
+    extern BYTE vmode;
+    extern int display_demo;
+    int term_io_save;
+#endif /* OS2 */
+#endif /* NOLOCAL */
+#ifdef TNCODE
+    int _u_bin=0, _me_bin = 0;
+#ifdef IKS_OPTION
+    int /* _u_start=0, */ _me_start = 0;
+#endif /* IKS_OPTION */
+#endif /* TNCODE */
+#ifdef PATTERNS
+    int pa_save;
+    int i;
+#endif /* PATTERNS */
+    int scan_save;
+
+#ifdef PATTERNS
+    pa_save = patterns;
+#endif /* PATTERNS */
+    scan_save = filepeek;
+
+    myjob = sstate;
+
+#ifdef CK_LOGIN
+    if (isguest) {                     /* If user is anonymous */
+       en_pri = 0;                     /* disable printing */
+       en_mai = 0;                     /* and disable email */
+       en_del = 0;                     /* and file deletion */
+    }
+#endif /* CK_LOGIN */
+
+#ifndef NOLOCAL
+#ifdef OS2
+    cursor_save = cursorena[vmode];
+    cursorena[vmode] = 0;
+    term_io_save = term_io;
+    term_io = 0;
+#endif /* OS2 */
+#endif /* NOLOCAL */
+    b_save = binary;                   /* SET FILE TYPE */
+    f_save = fncnv;                    /* SET FILE NAMES */
+    c_save = bctr;
+    p_save = fnspath;
+    r_save = recursive;
+    s_timint = timint;
+    ss_save = slostart;
+#ifndef NOCSETS
+    fcs_save = fcharset;
+    tcs_save = tcharset;
+#endif /* NOCSETS */
+
+#ifdef COMMENT
+/* Don't do this because then user can never find out what happened. */
+#ifdef CK_SPEED
+    for (i = 0; i < 256; i++)
+      s_ctlp[i] = ctlp[i];
+    f_ctlp = 1;
+#endif /* CK_SPEED */
+#endif /* COMMENT */
+    if (reliable == SET_ON)
+      slostart = 0;
+    is_tn = (!local && sstelnet)
+#ifdef TNCODE
+      || (local && network && ttnproto == NP_TELNET)
+#endif /* TNCODE */
+       ;
+#ifdef TNCODE
+    if (is_tn) {
+        if (tn_b_xfer && !(sstelnet || inserver)) {
+           /* Save the current state of Telnet Binary */
+           _u_bin = TELOPT_U(TELOPT_BINARY);
+           _me_bin = TELOPT_ME(TELOPT_BINARY);
+
+           /* If either direction is not Binary attempt to negotiate it */
+           if (!_u_bin && TELOPT_U_MODE(TELOPT_BINARY) != TN_NG_RF) {
+               tn_sopt(DO,TELOPT_BINARY);
+               TELOPT_UNANSWERED_DO(TELOPT_BINARY) = 1;
+           }
+           if (!_me_bin && TELOPT_ME_MODE(TELOPT_BINARY) != TN_NG_RF) {
+               tn_sopt(WILL,TELOPT_BINARY);
+               TELOPT_UNANSWERED_WILL(TELOPT_BINARY) = 1;
+           }
+           if (!(_me_bin && _u_bin))
+             tn_wait("proto set binary mode");
+        }
+#ifdef IKS_OPTION
+#ifdef CK_XYZ
+        if (protocol != PROTO_K) {     /* Non-Kermit protocol selected */
+            if (TELOPT_U(TELOPT_KERMIT) &&
+                TELOPT_SB(TELOPT_KERMIT).kermit.u_start) {
+                iks_wait(KERMIT_REQ_STOP,0); /* Stop the other Server */
+               /* _u_start = 1; */
+            }
+            if (TELOPT_ME(TELOPT_KERMIT) &&
+                TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
+                tn_siks(KERMIT_STOP);  /* I'm not servering */
+               TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
+               _me_start = 1;
+            }
+        } else
+#endif /* CK_XYZ */
+        if (sstate == 'x' || sstate == 'v') { /* Responding to a request */
+            if (!inserver && TELOPT_U(TELOPT_KERMIT) &&
+                TELOPT_SB(TELOPT_KERMIT).kermit.u_start) {
+                iks_wait(KERMIT_REQ_STOP,0); /* Stop the other Server */
+               /* _u_start = 1; */
+            }
+            if (TELOPT_ME(TELOPT_KERMIT) &&
+                !TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
+                tn_siks(KERMIT_START); /* Send Kermit-Server Start */
+               TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 1;
+            }
+        } else {                       /* Initiating a request */
+            if (TELOPT_ME(TELOPT_KERMIT) &&
+                TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
+                tn_siks(KERMIT_STOP);  /* I'm not servering */
+               TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
+               _me_start = 1;
+            }
+            if (TELOPT_U(TELOPT_KERMIT) &&
+               !TELOPT_SB(TELOPT_KERMIT).kermit.u_start) {
+               /* Send Req-Server-Start */
+                if (!iks_wait(KERMIT_REQ_START,0)) {
+                    if (sstate != 's') {
+                       success = 0;    /* Other Kermit refused to serve */
+                       if (local)
+                         printf("A Kermit Server is not available\r\n");
+                       debug(F110,"proto()",
+                             "A Kermit Server is not available",0);
+                       tlog(F110,"IKS client/server failure",
+                             "A Kermit Server is not available",0);
+                       goto xxprotox;
+                    }
+               }
+            }
+        }
+#endif /* IKS_OPTION */
+#ifdef CK_ENCRYPTION
+        if (tn_no_encrypt_xfer && !(sstelnet || inserver)) {
+            ck_tn_enc_stop();
+        }
+#endif /* CK_ENCRYPTION */
+    }
+#endif /* TNCODE */
+
+    if (!xfrint) connoi();
+    xxproto();                         /* Call the real protocol function */
+
+#ifdef IKS_OPTION
+  xxprotox:
+#endif /* IKS_OPTION */
+    xferstat = success;                        /* Remember transfer status */
+    kactive = 0;
+
+#ifdef TNCODE
+#ifdef CK_ENCRYPTION
+        if (tn_no_encrypt_xfer && !(sstelnet || inserver)) {
+            ck_tn_enc_start();
+        }
+#endif /* CK_ENCRYPTION */
+#ifdef IKS_OPTION
+    if (TELOPT_ME(TELOPT_KERMIT) &&
+        TELOPT_SB(TELOPT_KERMIT).kermit.me_start && !_me_start) {
+        tn_siks(KERMIT_STOP);          /* Server is stopped */
+       TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
+    }
+#endif /* IKS_OPTION */
+    if (is_tn && tn_b_xfer && !(sstelnet || inserver)) {
+        /* if we negotiated Binary mode try to reset it */
+        if (!_u_bin) {
+            /* Check to see if the state changed during the transfer */
+           if (TELOPT_U(TELOPT_BINARY)) {
+               tn_sopt(DONT,TELOPT_BINARY);
+               TELOPT_UNANSWERED_DONT(TELOPT_BINARY) = 1;
+           } else
+             _u_bin = 1;               /* So we don't call tn_wait() */
+        }
+        if (!_me_bin) {
+            /* Check to see if the state changed during the transfer */
+           if (TELOPT_ME(TELOPT_BINARY)) {
+               tn_sopt(WONT,TELOPT_BINARY);
+               TELOPT_UNANSWERED_WONT(TELOPT_BINARY) = 1;
+           } else
+             _me_bin = 1;              /* So we don't call tn_wait() */
+       }
+       if (!(_me_bin && _u_bin))
+         tn_wait("proto reset binary mode");
+    }
+#endif /* TNCODE */
+
+#ifdef PATTERNS
+    patterns = pa_save;
+#endif /* PATTERNS */
+    filepeek = scan_save;
+
+#ifdef STREAMING
+    streaming = 0;
+    /* streamok = 0; */
+#endif /* STREAMING */
+#ifdef COMMENT
+#ifdef CK_SPEED
+    for (i = 0; i < 256; i++)
+      ctlp[i] = s_ctlp[i];
+    f_ctlp = 0;
+#endif /* CK_SPEED */
+#endif /* COMMENT */
+    urclear = 0;
+    if (!success) {
+       xitsta |= (what & W_KERMIT);
+       tlog(F110," failed:",(char *)epktmsg,0);
+    }
+    debug(F111,"proto xferstat",epktmsg,xferstat);
+    slostart = ss_save;
+    if (s_timint > -1) {               /* Because of REMOTE SET */
+       timint = s_timint;
+       s_timint = -1;
+    }
+    recursive = r_save;
+    fnspath = p_save;
+    if (c_save > -1) {                 /* Because of REMOTE SET */
+       bctr = c_save;
+       c_save = -1;
+    }
+    fncnv   = f_save;
+    binary  = b_save;
+#ifdef PIPESEND
+    pipesend = 0;                      /* Next time might not be pipesend */
+#endif /* PIPESEND */
+#ifndef NOLOCAL
+#ifdef OS2
+    cursorena[vmode] = cursor_save;
+    term_io = term_io_save;
+    display_demo = 1;
+#endif /* OS2 */
+#endif /* NOLOCAL */
+}
+
+static VOID
+xxproto() {
+    int x;
+    long lx;
+#ifdef CK_XYZ
+#ifdef XYZ_INTERNAL
+_PROTOTYP( int pxyz, (int) );
+#endif /* XYZ_INTERNAL */
+#endif /* CK_XYZ */
+
+    char xss[2];                       /* String representation of sstate */
+    xss[0] = sstate;
+    xss[1] = NUL;
+    s_timint = timint;
+
+    debug(F101,"xxproto entry justone","",justone);
+    success = 0;
+
+    retrieve = 0;                      /* Reset these ... */
+    reget = 0;
+    opkt = 0;
+
+    if (local && ttchk() < 0) {                /* Giving BYE or FIN */
+       if (bye_active) {               /* but there is no connection */
+           ttclos(0);
+           success = 1;
+           return;
+       }
+       /* Ditto for any REMOTE command */
+       if (sstate == 'g' && cmarg ) {
+           if (*cmarg == 'L' || *cmarg == 'F' || *cmarg == 'X')
+             success = 1;
+           else
+             printf("?No connection\r\n");
+           return;
+       }
+    }
+
+/* Set up the communication line for file transfer. */
+/* NOTE: All of the xxscreen() calls prior to the wart() invocation */
+/* could just as easily be printf's or, for that matter, hints. */
+
+    if (local && (speed < 0L) && (network == 0)) {
+       xxscreen(SCR_EM,0,0L,"Sorry, you must 'set speed' first");
+       return;
+    }
+    x = -1;
+    if (ttopen(ttname,&x,mdmtyp,cdtimo) < 0) {
+       debug(F111,"failed: proto ttopen local",ttname,local);
+       xxscreen(SCR_EM,0,0L,"Can't open line");
+       return;
+    }
+    if (x > -1) local = x;
+    debug(F111,"proto ttopen local",ttname,local);
+
+    lx = (local && !network) ? speed : -1;
+#ifdef NETCONN
+#ifdef CK_SPEED
+    if (is_tn) {
+       ctlp[(unsigned)255] = ctlp[CR] = 1;
+       if (parity == 'e' || parity == 'm') ctlp[127] = 1;
+       if (flow == FLO_XONX) {         /* Also watch out for Xon/Xoff */
+           ctlp[17] = ctlp[19] = 1;
+           ctlp[17+128] = ctlp[19+128] = 1;
+       }
+    }
+#endif /* CK_SPEED */
+#endif /* NETCONN */
+    if (ttpkt(lx,flow,parity) < 0) {   /* Put line in packet mode, */
+       xxscreen(SCR_EM,0,0L,"Can't condition line");
+       return;
+    }
+    if (local && !network && carrier != CAR_OFF) {
+       int x;                          /* Serial connection */
+       x = ttgmdm();                   /* with carrier checking */
+       if (x > -1) {
+           if (!(x & BM_DCD)) {
+               debug(F101,"proto ttgmdm","",0);
+               xxscreen(SCR_EM,0,0L,"Carrier required but not detected");
+               return;
+           }
+       }
+    }
+    /* Send remote side's "receive" or "server" startup string, if any */
+    if (local && ckindex((char *)xss,"srgcjhk",0,0,1)) {
+       char *s = NULL;
+        if (
+#ifdef IKS_OPTION
+           /* Don't send auto-blah string if we know other side is serving */
+           !TELOPT_U(TELOPT_KERMIT) ||
+           !TELOPT_SB(TELOPT_KERMIT).kermit.u_start
+#else
+           1
+#endif /* IKS_OPTION */
+           ) {
+           if (sstate == 's') {        /* Sending file(s) */
+               s = binary ? ptab[protocol].h_b_init : ptab[protocol].h_t_init;
+           } else if (protocol == PROTO_K) { /* Command for server */
+               s = ptab[protocol].h_x_init;
+           }
+       }
+#ifdef CK_SPEED
+#ifndef UNPREFIXZERO
+       if (protocol == PROTO_K)        /* Because of C-strings... */
+         ctlp[0] = 1;
+#endif /* UNPREFIXZERO */
+#endif /* CK_SPEED */
+       if (s) if (*s) {                /* If we have a command to send... */
+           char tmpbuf[356];
+           int tmpbufsiz = 356;
+           int stuff = -1, stuff2 = -1, len = 0;
+           extern int tnlm;
+           if (sstate == 's') {        /* Sending file(s) */
+#ifdef CK_XYZ
+               if (protocol == PROTO_X) {
+                   char * s2;
+                   s2 = cmarg2[0] ? cmarg2 : cmarg;
+                   if ((int)strlen(s) + (int)strlen(s2) + 4 < 356)
+                     sprintf(tmpbuf, s, s2);
+                   else
+                     tmpbuf[0] = NUL;
+               } else {
+#endif /* CK_XYZ */
+                   ckmakmsg(tmpbuf, 356, s, NULL, NULL, NULL);
+#ifdef CK_XYZ
+               }
+#endif /* CK_XYZ */
+           } else {                    /* Command for server */
+               ckstrncpy(tmpbuf,s,356);
+           }
+           ckstrncat(tmpbuf, "\015",sizeof(tmpbuf));
+           if (tnlm)                   /* TERMINAL NEWLINE ON */
+             stuff = LF;               /* Stuff LF */
+#ifdef TNCODE
+           /* TELNET NEWLINE MODE */
+           if (is_tn) {
+               switch (TELOPT_ME(TELOPT_BINARY) ? tn_b_nlm : tn_nlm) {
+                 case TNL_CR:
+                   break;
+                 case TNL_CRNUL:
+                   break;
+                 case TNL_CRLF:
+                   stuff2 = stuff;
+                   stuff = LF;
+                   break;
+               }
+           }
+#endif /* TNCODE */
+
+#ifdef NETCONN
+#ifdef TCPSOCKET
+#ifdef RLOGCODE
+           if (network && ttnproto == NP_RLOGIN) {
+               switch (tn_b_nlm) { /* Always BINARY */
+                 case TNL_CR:
+                   break;
+                 case TNL_CRNUL:
+                   stuff2 = stuff;
+                   stuff  = NUL;
+                   break;
+                 case TNL_CRLF:
+                   stuff2 = stuff;
+                   stuff = LF;
+                   break;
+               }
+           }
+#endif /* RLOGCODE */
+#endif /* TCPSOCKET */
+#endif /* NETCONN */
+
+           len = strlen(tmpbuf);
+           if (stuff >= 0 && len < tmpbufsiz - 1) {
+               tmpbuf[len++] = stuff;
+               if (stuff2 >= 0 && len < tmpbufsiz - 1)
+                 tmpbuf[len++] = stuff2;
+               tmpbuf[len] = NUL;
+           }
+           ttol((CHAR *)tmpbuf,len);
+           if (protocol == PROTO_K)    /* Give remote Kermit time to start */
+             msleep(400);
+       }
+    }
+
+#ifdef CK_XYZ
+    if (protocol != PROTO_K) {         /* Non-Kermit protocol selected */
+       char tmpbuf[356];
+       int tmpbufsiz = 356;
+       char * s = "";
+
+#ifdef CK_TMPDIR
+       if (sstate == 'v') {            /* If receiving and... */
+           if (dldir && !f_tmpdir) {   /* if they have a download directory */
+               if (s = zgtdir()) {     /* Get current directory */
+                   if (zchdir(dldir)) { /* Change to download directory */
+                       ckstrncpy(savdir,s,TMPDIRLEN);
+                       f_tmpdir = 1;   /* Remember that we did this */
+                   }
+               }
+           }
+       }
+#endif /* CK_TMPDIR */
+
+#ifdef XYZ_INTERNAL                    /* Internal */
+       success = !pxyz(sstate);
+#else
+#ifdef CK_REDIR                                /* External */
+       switch (sstate) {
+         case 's':                     /* 'Tis better to SEND... */
+           s = binary ? ptab[protocol].p_b_scmd : ptab[protocol].p_t_scmd;
+           break;
+         case 'v':                     /* ... than RECEIVE */
+           s = binary ? ptab[protocol].p_b_rcmd : ptab[protocol].p_t_rcmd;
+           break;
+       }
+       if (!s) s = "";
+       if (*s) {
+           if (sstate == 's') {        /* Sending */
+               extern int xfermode;
+               int k = 0, x = 0, b = binary;
+               /*
+                 If just one file we can scan it to set the xfer mode.
+                 Otherwise it's up to the external protocol program.
+               */
+               if (patterns && xfermode == XMODE_A && !iswild(fspec)) {
+                   extern int nscanfile;
+                   k = scanfile(fspec,&x,nscanfile);
+                   if (k > -1) {
+                       b = (k == FT_BIN) ? XYFT_B : XYFT_T;
+                       s = b ?
+                           ptab[protocol].p_b_scmd :
+                           ptab[protocol].p_t_scmd;
+                   }
+               }
+               if ((int)strlen(s) + (int)strlen(fspec) < tmpbufsiz) {
+                   sprintf(tmpbuf,s,fspec); /* safe (prechecked) */
+                   tlog(F110,"Sending",fspec,0L);
+               }
+           } else {                    /* Receiving */
+               if ((int)strlen(s) + (int)strlen(cmarg2) < tmpbufsiz) {
+                   sprintf(tmpbuf,s,cmarg2); /* safe (prechecked) */
+                   tlog(F110,"Receiving",cmarg2,0L);
+               }
+           }
+           tlog(F110," via external protocol:",tmpbuf,0);
+           debug(F110,"ckcpro ttruncmd",tmpbuf,0);
+           success = ttruncmd(tmpbuf);
+           tlog(F110," status:",success ? "OK" : "FAILED", 0);
+       } else {
+           printf("?Sorry, no external protocol defined for %s\r\n",
+                  ptab[protocol].p_name
+                  );
+       }
+#else
+       printf(
+"Sorry, only Kermit protocol is supported in this version of Kermit\n"
+              );
+#endif /* CK_REDIR */
+#endif /* XYZ_INTERNAL */
+       return;
+    }
+#endif /* CK_XYZ */
+
+#ifdef NTSIGX
+    conraw();
+    connoi();
+#else
+    if (!local)
+      connoi();                                /* No console interrupts if remote */
+#endif /* NTSIG */
+
+    kactive = 1;
+    if (sstate == 'x') {               /* If entering server mode, */
+       extern int howcalled;
+       server = 1;                     /* set flag, */
+       debug(F101,"server backgrd","",backgrd);
+       debug(F101,"server quiet","",quiet);
+       debug(F100,"SHOULD NOT SEE THIS IF IN BACKGROUND!","",0);
+       if (howcalled == I_AM_SSHSUB) { /* and issue appropriate message. */
+           ttol((CHAR *)"KERMIT READY TO SERVE...\015\012",26);
+       } else if (!local) {
+           if (!quiet && !backgrd
+#ifdef IKS_OPTION
+                && !TELOPT_ME(TELOPT_KERMIT) /* User was told by negotiation */
+#endif /* IKS_OPTION */
+               ) {
+               conoll(srvtxt);
+               conoll("KERMIT READY TO SERVE...");
+           }
+       } else {
+           conol("Entering server mode on ");
+           conoll(ttname);
+           conoll("Type Ctrl-C to quit.");
+           if (srvdis) intmsg(-1L);
+#ifdef TCPSOCKET
+#ifndef NOLISTEN
+           if (network && tcpsrfd > 0)
+             ttol((CHAR *)"KERMIT READY TO SERVE...\015\012",26);
+#endif /* NOLISTEN */
+#endif /* TCPSOCKET */
+       }
+    } else
+      server = 0;
+#ifdef VMS
+    if (!quiet && !backgrd)    /* So message doesn't overwrite prompt */
+      conoll("");
+    if (local) conres();       /* So Ctrl-C will work */
+#endif /* VMS */
+/*
+  If in remote mode, not shushed, not in background, and at top command level,
+  issue a helpful message telling what to do...
+*/
+    if (!local && !quiet && !backgrd) {
+       if (sstate == 'v') {
+           conoll("Return to your local Kermit and give a SEND command.");
+           conoll("");
+           conoll("KERMIT READY TO RECEIVE...");
+       } else if (sstate == 's') {
+           conoll("Return to your local Kermit and give a RECEIVE command.");
+           conoll("");
+           conoll("KERMIT READY TO SEND...");
+       } else if ( sstate == 'g' || sstate == 'r' || sstate == 'h' ||
+                   sstate == 'j' || sstate == 'c' ) {
+           conoll("Return to your local Kermit and give a SERVER command.");
+           conoll("");
+           conoll((sstate == 'r' || sstate == 'j' || sstate == 'h') ?
+                  "KERMIT READY TO GET..." :
+                  "KERMIT READY TO SEND SERVER COMMAND...");
+       }
+    }
+#ifdef COMMENT
+    if (!local) sleep(1);
+#endif /* COMMENT */
+/*
+  The 'wart()' function is generated by the wart program.  It gets a
+  character from the input() routine and then based on that character and
+  the current state, selects the appropriate action, according to the state
+  table above, which is transformed by the wart program into a big case
+  statement.  The function is active for one transaction.
+*/
+    rtimer();                          /* Reset elapsed-time timer */
+#ifdef GFTIMER
+    rftimer();
+#endif /* GFTIMER */
+    resetc();                          /* & other per-transaction counters. */
+
+    debug(F101,"proto calling wart, justone","",justone);
+
+    wart();                            /* Enter the state table switcher. */
+/*
+  Note: the following is necessary in case we have just done a remote-mode
+  file transfer, in which case the controlling terminal modes have been
+  changed by ttpkt().  In particular, special characters like Ctrl-C and
+  Ctrl-\ might have been turned off (see ttpkt).  So this call to ttres() is
+  essential.  IMPORTANT: restore interrupt handlers first, otherwise any
+  terminal interrupts that occur before this is done in the normal place
+  later will cause a crash.
+*/
+#ifdef OS2
+    ttres();                           /* Reset the communication device */
+#else
+    if (!local) {
+       setint();                       /* Arm interrupt handlers FIRST */
+       msleep(500);
+       ttres();                        /* Then restore terminal. */
+    }
+#endif /* OS2 */
+    xxscreen(SCR_TC,0,0L,"");          /* Transaction complete */
+    x = quiet;
+    quiet=1;
+    clsif();                           /* Failsafe in case we missed */
+    clsof(1);                          /* a case in the state machine. */
+    quiet = x;
+
+    if (server) {                      /* Back from packet protocol. */
+       if (!quiet && !backgrd
+#ifdef IKSD
+           && !inserver
+#endif /* IKSD */
+           ) {                         /* Give appropriate message */
+           conoll("");
+           conoll("C-Kermit server done");
+        }
+        server = 0;                    /* Not a server any more */
+    }
+}
+
+/*  S G E T I N I T  --  Handle incoming GET-Class packets  */
+
+/*
+  Returns:
+   -1: On error
+    0: GET packet processed OK - ready to Send.
+    1: Extended GET processed OK - wait for another.
+*/
+static int
+sgetinit(reget,xget) int reget, xget; {        /* Server end of GET command */
+    char * fs = NULL;                  /* Pointer to filespec */
+    int i, n, done = 0;
+#ifdef PIPESEND
+    extern int usepipes, pipesend;
+#endif /* PIPESEND */
+    extern int nolinks;
+
+    if (!ENABLED(en_get)) {            /* Only if not disabled!  */
+       errpkt((CHAR *)"GET disabled");
+       return(-1);
+    }
+
+    /* OK to proceed */
+
+    nolinks = recursive;
+    filcnt = 0;
+
+#ifdef WHATAMI
+    /* If they are alike this was already done in whoarewe() */
+    debug(F101,"sgetinit whatru","",whatru);
+    if (whatru & WMI_FLAG) {           /* Did we get WHATAMI info? */
+       debug(F101,"sgetinit binary (1)","",binary);
+#ifdef VMS
+       if (binary != XYFT_I && binary != XYFT_L)
+#else
+#ifdef OS2
+         if (binary != XYFT_L)
+#endif /* OS2 */
+#endif /* VMS */
+           binary = (whatru & WMI_FMODE) ? /* Yes, set file type */
+             XYFT_B : XYFT_T;  /* automatically */
+       debug(F101,"sgetinit binary (2)","",binary);
+       if (!wearealike)
+         fncnv = (whatru & WMI_FNAME) ? 1 : 0; /* And name conversion */
+    }
+#endif /* WHATAMI */
+
+    fs = (char *)srvcmd;
+    srvptr = srvcmd;                   /* Point to server command buffer */
+    decode(rdatap,putsrv,0);           /* Decode the GET command into it */
+    /* Accept multiple filespecs */
+    cmarg2 = "";                       /* Don't use cmarg2 */
+    cmarg = "";                                /* Don't use cmarg */
+
+    done = 1;                          /* Only 1 packet needed... */
+    if (xget) {                                /* Special decoding for Extended GET */
+       char L, next, c;                /* PLV items */
+       int len, val;                   /* More PLV items */
+       char * p = (char *)srvcmd;      /* String to decode */
+
+       done = 0;                       /* Maybe more packets needed */
+       fs = NULL;                      /* We don't know the filespec yet */
+       c = *p++;                       /* Get first parameter */
+
+       while (c) {                     /* For all parameters... */
+           debug(F000,"sgetinit c","",c);
+           L = *p++;                   /* Get length */
+           if (L >= SP)                /* Decode length */
+             len = xunchar(L);
+           else if (c == '@') {        /* Allow missing EOP length field */
+               len = 0;
+           } else {
+               len = (xunchar(*p++) * 95);
+               len += xunchar(*p++);
+           }
+           debug(F101,"sgetinit len","",len);
+           next = *(p+len);            /* Get next parameter */
+           *(p+len) = NUL;             /* Zero it out to terminal value */
+           debug(F110,"sgetinit p",p,0);
+           switch (c) {                /* Do the parameter */
+             case 'O':                 /* GET Options */
+               val = atoi(p);          /* Convert to int */
+               debug(F101,"sgetinit O val","",val);
+               if (val & GOPT_DEL) moving = 1;
+               if (val & GOPT_RES) reget = 1;
+               if (val & GOPT_REC) {
+                   recursive = 1;
+                   nolinks = 2;
+                   if (fnspath == PATH_OFF)
+                     fnspath = PATH_REL;
+               }
+               break;
+             case 'M':                 /* Transfer Mode */
+               val = atoi(p);
+               debug(F101,"sgetinit M val","",val);
+               if (val < 1)
+                 break;
+               patterns = 0;           /* Takes precedence over patterns */
+               filepeek = 0;           /* and FILE SCAN */
+               if (val == GMOD_TXT) binary = XYFT_T; /* Text */
+               if (val == GMOD_BIN) binary = XYFT_B; /* Binary */
+               if (val == GMOD_LBL) binary = XYFT_L; /* Labeled */
+               break;
+             case 'F':                 /* Filename */
+               fs = p;
+               debug(F110,"sgetinit filename",fs,0);
+               break;
+             case '@':                 /* End Of Parameters */
+               done = 1;
+               debug(F100,"sgetinit EOP","",0);
+               break;
+             default:
+               errpkt((CHAR *)"Unknown GET Parameter");
+               debug(F100,"sgetinit unknown parameter","",0);
+               return(-1);
+           }
+           p += (len + 1);
+           c = next;
+       }
+    }
+    if (!fs) fs = "";                  /* A filename is required */
+    if (*fs) {
+       havefs = 1;
+       n = 0;                          /* Check for quoted name */
+       if ((n = strlen(fs)) > 1) {
+           /* Note: this does not allow for multiple quoted names */
+           if ((fs[0] == '{' && fs[n-1] == '}') ||
+               (fs[0] == '"' && fs[n-1] == '"')) {
+               fs[n-1] = '\0';
+               fs++;
+               debug(F111,"sgetinit unquoted filename",fs,n);
+           } else
+             n = 0;                    /* This means no quoting */
+       }
+
+#ifdef PIPESEND
+       debug(F111,"sgetinit",fs,usepipes);
+       if (usepipes && ENABLED(en_hos) && *fs == '!') {
+           cmarg = fs + 1;             /* Point past the bang */
+           *fs = NUL;
+           nfils = -1;
+           pipesend = 1;
+           debug(F111,"sgetinit pipesend",cmarg,pipesend);
+       }
+       if (!pipesend) {                /* If it's not a pipe */
+#endif /* PIPESEND */
+           if (n == 0) {               /* If the name was not quoted */
+#ifndef NOMSEND
+               nfils = fnparse(fs);    /* Allow it to be a list of names */
+               debug(F111,"sgetinit A",fs,nfils);
+#ifdef COMMENT
+/* This doesn't work if a GET-PATH is set. */
+               if (nfils == 1 && !iswild(fs)) { /* Single file */
+                   char * m;
+                   if ((x = zchki(fs)) < 0) { /* Check if it's sendable */
+                       switch (x) {
+                         case -1: m = "File not found"; break;
+                         case -2: m = "Not a regular file"; break;
+                         case -3: m = "Read access denied"; break;
+                       }
+                       errpkt((CHAR *)m);
+                       return(-1);
+                   }
+               }
+#endif /* COMMENT */
+           } else {                    /* If it was quoted */
+#endif /* NOMSEND */
+               nzxopts = 0;
+#ifdef UNIXOROSK
+               if (matchdot)  nzxopts |= ZX_MATCHDOT;
+#endif /* UNIXOROSK */
+               if (recursive) nzxopts |= ZX_RECURSE;
+               /* Treat as a single filespec */
+               nfils = 0 - nzxpand(fs,nzxopts);
+               debug(F111,"sgetinit B",fs,nfils);
+               cmarg = fs;
+           }
+#ifdef PIPESEND
+       }
+#endif /* PIPESEND */
+    }
+    if (!done) {                       /* Need more O packets... */
+       debug(F100,"sgetinit O-Packet TBC","",0); /* To Be Continued */
+       return(1);
+    }
+    debug(F100,"sgetinit O-Packet done - havefs","",havefs);
+    if (!havefs) {                     /* Done - make sure we have filename */
+       errpkt((CHAR *)"GET without filename");
+       return(-1);
+    }
+    freerpkt(winlo);
+    winlo = 0;                         /* Back to packet 0 again. */
+    debug(F101,"sgetinit winlo","",winlo);
+    nakstate = 0;                      /* Now I'm the sender! */
+    if (reget) sendmode = SM_RESEND;
+    if (sinit() > 0) {                 /* Send Send-Init */
+#ifdef STREAMING
+       if (!streaming)
+#endif /* STREAMING */
+         timint = chktimo(rtimo,timef); /* Switch to per-packet timer */
+       return(0);                      /* If successful, switch state */
+    } else return(-1);                 /* Else back to server command wait */
+}
+
+#else  /* NOXFER */
+
+#include "ckcdeb.h"
+
+VOID
+proto() {
+    extern int success;
+    success = 0;
+}
+#endif /* NOXFER */
index cd9d1fa..a6b5f48 100644 (file)
--- a/ckcpro.w
+++ b/ckcpro.w
@@ -1,5 +1,5 @@
 char *protv =                                                     /* -*-C-*- */
-"C-Kermit Protocol Module 8.0.158, 11 Sep 2002";
+"C-Kermit Protocol Module 9.0.160, 16 Oct 2009";
 
 int kactive = 0;                       /* Kermit protocol is active */
 
@@ -10,7 +10,7 @@ int kactive = 0;                      /* Kermit protocol is active */
   Author: Frank da Cruz <fdc@columbia.edu>,
   Columbia University Academic Information Systems, New York City.
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2009,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -147,6 +147,7 @@ _PROTOTYP( int cmdsrc, (void) );
 #endif /* TCPSOCKET */
 
   extern int cxseen, czseen, server, srvdis, local, displa, bctu, bctr, bctl;
+  extern int bctf;
   extern int quiet, tsecs, parity, backgrd, nakstate, atcapu, wslotn, winlo;
   extern int wslots, success, xitsta, rprintf, discard, cdtimo, keep, fdispla;
   extern int timef, stdinf, rscapu, sendmode, epktflg, epktrcvd, epktsent;
@@ -230,7 +231,7 @@ wheremsg() {
                    printf(" SENT: [%s]",sfspec);
                    if (srfspec)
                      printf(" To: [%s]",srfspec);
-                   printf(" (%s)\n", success ? "OK" : "FAILED");
+                   printf(" (%s)\r\n", success ? "OK" : "FAILED");
                }
                break;
              case 'r':
@@ -239,7 +240,7 @@ wheremsg() {
                    printf(" RCVD: [%s]",rrfspec);
                    if (rfspec)
                      printf(" To: [%s]",rfspec);
-                   printf(" (%s)\n", success ? "OK" : "FAILED");
+                   printf(" (%s)\r\n", success ? "OK" : "FAILED");
                }
            }
        } else if (n > 1) {
@@ -249,7 +250,7 @@ wheremsg() {
                    printf(" SENT: (%d files)",n);
                    if (srfspec)
                      printf(" Last: [%s]",srfspec);
-                   printf(" (%s)\n", success ? "OK" : "FAILED");
+                   printf(" (%s)\r\n", success ? "OK" : "FAILED");
                }
                break;
              case 'r':
@@ -258,14 +259,14 @@ wheremsg() {
                    printf(" RCVD: (%d files)",n);
                    if (rfspec)
                      printf(" Last: [%s]",rfspec);
-                   printf(" (%s)\n", success ? "OK" : "FAILED");
+                   printf(" (%s)\r\n", success ? "OK" : "FAILED");
                }
            }
        } else if (n == 0) {
            if (myjob == 's')
-             printf(" SENT: (0 files)          \n");
+             printf(" SENT: (0 files)          \r\n");
            else if (myjob == 'r' || myjob == 'v')
-             printf(" RCVD: (0 files)          \n");
+             printf(" RCVD: (0 files)          \r\n");
        }
     }
 }
@@ -458,17 +459,22 @@ x {                                       /* Enter server mode */
 a {
     int b1 = 0, b2 = 0;
     if (!data) TINIT;                  /* "ABEND" -- Tell other side. */
+
+    if (!bctf) {                    /* Block check 3 forced on all packets */
 #ifndef pdp11
-    if (epktflg) {                     /* If because of E-PACKET command */
-       b1 = bctl; b2 = bctu;           /* Save block check type */
-       bctl = bctu = 1;                /* set it to 1 */
-    }
+       if (epktflg) {                  /* If because of E-PACKET command */
+           b1 = bctl; b2 = bctu;       /* Save block check type */
+           bctl = bctu = 1;            /* set it to 1 */
+       }
 #endif /* pdp11 */
+    }
     errpkt((CHAR *)"User cancelled");  /* Send the packet */
+    if (!bctf) {                    /* Block check 3 forced on all packets */
 #ifndef pdp11
-    if (epktflg) {                     /* Restore the block check */
-       epktflg = 0;
-       bctl = b1; bctu = b2;
+       if (epktflg) {                  /* Restore the block check */
+           epktflg = 0;
+           bctl = b1; bctu = b2;
+       }
     }
 #endif /* pdp11 */
     success = 0;
@@ -891,7 +897,7 @@ a {
                }
            }
        } else {                        /* User doesn't want message */
-           p =zgtdir();
+           p = zgtdir();
            if (!p) p = "";
            success = (*p) ? 1 : 0;
            ack1((CHAR *)p);
@@ -1069,7 +1075,7 @@ a {
        xxscreen(SCR_TC,0,0L,"");       /* Display */
        doclean(1);                     /* Clean up files, etc */
 #ifdef DEBUG
-       debug(F100,"C-Kermit BYE - Loggin out...","",0);
+       debug(F100,"C-Kermit BYE - Logging out...","",0);
        zclose(ZDFILE);
 #endif /* DEBUG */
 #ifdef IKSD
@@ -1100,7 +1106,7 @@ a {
     if (ikdbopen) slotstate(what,"REMOTE HELP", "", "");
 #endif /* IKSDB */
 #ifndef NOSERVER
-    if (sndhlp(NULL)) {
+    if (sndhlp()) {
        BEGIN ssinit;                   /* try to send it */
     } else {                           /* If not ok, */
        errpkt((CHAR *)"Can't send help"); /* send error message instead */
@@ -1353,6 +1359,15 @@ _PROTOTYP(int sndwho,(char *));
     if (rc > -1) return(rc);
 }
 
+<generic>M {                           /* REMOTE MESSAGE command */
+#ifndef NOSERVER
+    debug(F110,"RMSG",(char *)srvcmd+2,0);
+    xxscreen(SCR_MS,0,0L,(char *)(srvcmd+2));
+    ack();
+    RESUME;
+#endif /* NOSERVER */
+}
+
 <generic>q {                           /* Interrupted or connection lost */
 #ifndef NOSERVER
     if (fatalio) {                     /* Connection lost */
@@ -1679,8 +1694,14 @@ _PROTOTYP(int sndwho,(char *));
 <ssinit>Y {                            /* ACK for Send-Init */
     spar(rdatap);                      /* set parameters from it */
     cancel = 0;
-    bctu = bctr;                       /* switch to agreed-upon block check */
-    bctl = (bctu == 4) ? 2 : bctu;     /* Set block-check length */
+    if (bctf) {
+       bctu = 3;
+       bctl = 3;
+    } else {
+       bctu = bctr;                    /* switch to agreed-upon block check */
+       bctl = (bctu == 4) ? 2 : bctu;  /* Set block-check length */
+    }
+
 #ifdef CK_RESEND
     if ((sendmode == SM_RESEND) && (!atcapu || !rscapu)) { /* RESEND */
        errpkt((CHAR *) "RESEND capabilities not negotiated");
@@ -2719,8 +2740,13 @@ rcv_s_pkt() {
 #endif /* CK_TMPDIR */
        nakstate = 1;                   /* Can send NAKs from here. */
        rinit(rdatap);                  /* Set parameters */
-       bctu = bctr;                    /* Switch to agreed-upon block check */
-       bctl = (bctu == 4) ? 2 : bctu;  /* Set block-check length */
+       if (bctf) {
+           bctu = 3;
+           bctl = 3;
+       } else {
+           bctu = bctr;               /* switch to agreed-upon block check */
+           bctl = (bctu == 4) ? 2 : bctu; /* Set block-check length */
+       }
        what = W_RECV;                  /* Remember we're receiving */
        lastxfer = W_RECV;
        resetc();                       /* Reset counters */
@@ -3221,12 +3247,28 @@ _PROTOTYP( int pxyz, (int) );
        }
        if (!s) s = "";
        if (*s) {
-           if (sstate == 's') {
+           if (sstate == 's') {        /* Sending */
+               extern int xfermode;
+               int k = 0, x = 0, b = binary;
+               /*
+                 If just one file we can scan it to set the xfer mode.
+                 Otherwise it's up to the external protocol program.
+               */
+               if (patterns && xfermode == XMODE_A && !iswild(fspec)) {
+                   extern int nscanfile;
+                   k = scanfile(fspec,&x,nscanfile);
+                   if (k > -1) {
+                       b = (k == FT_BIN) ? XYFT_B : XYFT_T;
+                       s = b ?
+                           ptab[protocol].p_b_scmd :
+                           ptab[protocol].p_t_scmd;
+                   }
+               }
                if ((int)strlen(s) + (int)strlen(fspec) < tmpbufsiz) {
                    sprintf(tmpbuf,s,fspec); /* safe (prechecked) */
                    tlog(F110,"Sending",fspec,0L);
                }
-           } else {
+           } else {                    /* Receiving */
                if ((int)strlen(s) + (int)strlen(cmarg2) < tmpbufsiz) {
                    sprintf(tmpbuf,s,cmarg2); /* safe (prechecked) */
                    tlog(F110,"Receiving",cmarg2,0L);
index 30fb8bf..f0ba85c 100644 (file)
--- a/ckcsig.h
+++ b/ckcsig.h
@@ -6,7 +6,7 @@
   Author: Jeffrey E Altman (jaltman@secure-endpoints.com),
   Secure Endpoints Inc., New York City.
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2009,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
index f743820..e9f1295 100644 (file)
--- a/ckctel.c
+++ b/ckctel.c
@@ -1,4 +1,4 @@
-char *cktelv = "Telnet support, 8.0.269, 4 Mar 2004";
+char *cktelv = "Telnet support, 9.0.274, 16 Mar 2010";
 #define CKCTEL_C
 
 int sstelnet = 0;                       /* Do server-side Telnet negotiation */
@@ -18,7 +18,7 @@ int sstelnet = 0;                       /* Do server-side Telnet negotiation */
     Telnet KERMIT support by Jeffrey Altman
     Other contributions as indicated in the code.
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2010,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -91,6 +91,7 @@ int tn_init = 0;                        /* Telnet protocol initialized flag */
 int tn_begun = 0;                       /* Telnet protocol started flag */
 static int tn_first = 1;                /* First time init flag */
 extern int tn_exit;                     /* Exit on disconnect */
+extern int nettype;
 extern int inserver;                    /* Running as IKSD */
 char *tn_term = NULL;                   /* Terminal type override */
 
@@ -492,6 +493,8 @@ tn_wait(where) char * where;
     extern int ttcarr;
 #endif /* TN_COMPORT */
 
+    /* if (!IS_TELNET()) return(1); */
+
     rtimer();
 
     debug(F110,"tn_wait waiting for",where,0);
@@ -680,8 +683,10 @@ tn_push() {
 #ifdef NETLEBUF
     extern int tt_push_inited;
 #endif /* NETLEBUF */
+    /* if (!IS_TELNET()) return(1); */
+
     if (tn_wait_idx) {
-        hexdump((CHAR *)"tn_push",tn_wait_buf,tn_wait_idx);
+        ckhexdump((CHAR *)"tn_push",tn_wait_buf,tn_wait_idx);
 #ifdef NETLEBUF
         if (!tt_push_inited)            /* Local handling */
           le_init();
@@ -718,7 +723,6 @@ tn_sopt(cmd,opt) int cmd, opt; {        /* TELNET SEND OPTION */
     CHAR buf[5];
     char msg[128];
     int rc;
-
     if (ttnet != NET_TCPB) return(-1);  /* Must be TCP/IP */
     if (ttnproto != NP_TELNET) return(-1); /* Must be telnet protocol */
     if (!TELCMD_OK(cmd)) return(-1);
@@ -917,6 +921,8 @@ tn_flui() {
     extern int ckxech;
     int x = 0;
 
+    /* if (!IS_TELNET()) return(0); */
+
     /* Wait up to 5 sec for responses to outstanding telnet negotiations */
     while (x >= 0 && ttchk() > 0  && tn_wait_idx < TN_WAIT_BUF_SZ) {
         x = ttinc(1);
@@ -962,6 +968,8 @@ tn_get_display()
     /* explicitedly requested we try to send one via X-Display Location */
     /* But do not send a string at all if FORWARD_X is in use.          */
 
+    /* if (!IS_TELNET()) return(0); */
+
     debug(F110,"tn_get_display() myipaddr",myipaddr,0);
 #ifdef CK_ENVIRONMENT
     debug(F110,"tn_get_display() tn_env_disp",tn_env_disp,0);
@@ -1304,7 +1312,7 @@ fwdx_tn_sb( sb, n ) unsigned char * sb; int n;
         p[0] = sb[i++];
         p[1] = sb[i++];
         hchannel = ntohs(nchannel);
-        rc = fwdx_send_xauth_to_xserver(hchannel,(char *)&sb[3],n-5);
+        rc = fwdx_send_xauth_to_xserver(hchannel,(CHAR *)&sb[3],n-5);
         if ( rc >= 0 && n-5-rc > 0) {
             rc = fwdx_write_data_to_channel(hchannel,(char *)&sb[3+rc],n-5-rc);
             if ( rc < 0 ) {
@@ -1612,7 +1620,7 @@ fwdx_send_close(channel) int channel;
     sb_out[i++] = (CHAR) SE;                /* marked by IAC SE */
 #ifdef DEBUG
     if (deblog || tn_deb || debses) {
-        ckmakxmsg(fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
+        ckmakxmsg((char *)fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
                   TELOPT(TELOPT_FORWARD_X),
                   " CLOSE CHANNEL=",ckitoa(channel)," IAC SE",
                   NULL,NULL,NULL,NULL,NULL,NULL,NULL
@@ -1623,8 +1631,8 @@ fwdx_send_close(channel) int channel;
     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
 #endif
 #ifdef DEBUG
-    debug(F100,fwdx_msg_out,"",0);
-    if (tn_deb || debses) tn_debug(fwdx_msg_out);
+    debug(F100,(char *)fwdx_msg_out,"",0);
+    if (tn_deb || debses) tn_debug((char *)fwdx_msg_out);
 #endif /* DEBUG */
     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
 #ifdef OS2
@@ -1670,7 +1678,7 @@ fwdx_send_open(channel) int channel;
     sb_out[i++] = (CHAR) SE;                  /* marked by IAC SE */
 #ifdef DEBUG
     if (deblog || tn_deb || debses) {
-        ckmakxmsg(fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
+        ckmakxmsg((char *)fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
                   TELOPT(TELOPT_FORWARD_X),
                   " OPEN CHANNEL=",ckitoa(channel)," IAC SE",
                   NULL,NULL,NULL,NULL,NULL,NULL,NULL);
@@ -1680,8 +1688,8 @@ fwdx_send_open(channel) int channel;
     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
 #endif
 #ifdef DEBUG
-    debug(F100,fwdx_msg_out,"",0);
-    if (tn_deb || debses) tn_debug(fwdx_msg_out);
+    debug(F100,(char *)fwdx_msg_out,"",0);
+    if (tn_deb || debses) tn_debug((char *)fwdx_msg_out);
 #endif /* DEBUG */
     rc = (ttol((CHAR *)sb_out,i) < 0);        /* Send it. */
 #ifdef OS2
@@ -1732,7 +1740,7 @@ fwdx_client_reply_options(opts, n) char *opts; int n;
     sb_out[i++] = (CHAR) SE;                  /* marked by IAC SE */
 #ifdef DEBUG
     if (deblog || tn_deb || debses) {
-        ckmakxmsg(fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
+        ckmakxmsg((char *)fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
                   TELOPT(TELOPT_FORWARD_X),
                   " OPTIONS ",ckctox(sb_out[4],1)," IAC SE",
                   NULL,NULL,NULL,NULL,NULL,NULL,NULL);
@@ -1742,8 +1750,8 @@ fwdx_client_reply_options(opts, n) char *opts; int n;
     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
 #endif
 #ifdef DEBUG
-    debug(F100,fwdx_msg_out,"",0);
-    if (tn_deb || debses) tn_debug(fwdx_msg_out);
+    debug(F100,(char *)fwdx_msg_out,"",0);
+    if (tn_deb || debses) tn_debug((char *)fwdx_msg_out);
 #endif /* DEBUG */
     rc = (ttol((CHAR *)sb_out,i) < 0);        /* Send it. */
 #ifdef OS2
@@ -1778,7 +1786,7 @@ fwdx_send_options() {
 
 #ifdef DEBUG
     if (deblog || tn_deb || debses) {
-        ckmakmsg(fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
+        ckmakmsg((char *)fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
                  TELOPT(TELOPT_FORWARD_X),
                  " OPTIONS 00 IAC SE",NULL);
     }
@@ -1787,8 +1795,8 @@ fwdx_send_options() {
     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
 #endif
 #ifdef DEBUG
-    debug(F100,fwdx_msg_out,"",0);
-    if (tn_deb || debses) tn_debug(fwdx_msg_out);
+    debug(F100,(char *)fwdx_msg_out,"",0);
+    if (tn_deb || debses) tn_debug((char *)fwdx_msg_out);
 #endif /* DEBUG */
     rc = (ttol((CHAR *)sb_out,i) < 0);        /* Send it. */
 #ifdef OS2
@@ -1851,20 +1859,21 @@ fwdx_send_data_from_channel(channel, data, len)
 
 #ifdef DEBUG
             if (deblog || tn_deb || debses) {
-                ckmakxmsg( fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
+                ckmakxmsg( (char *)fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
                            TELOPT(TELOPT_FORWARD_X),
                            " DATA CHANNEL=",ckitoa(channel)," ",
                            NULL,NULL,NULL,NULL,NULL,NULL,NULL );
-                tn_hex(fwdx_msg_out,TN_MSG_LEN,&sb_priv[j_sav],j-(j_sav+2));
-                ckstrncat(fwdx_msg_out," IAC SE",TN_MSG_LEN);
+                tn_hex((CHAR *)fwdx_msg_out,
+                      TN_MSG_LEN,&sb_priv[j_sav],j-(j_sav+2));
+                ckstrncat((char *)fwdx_msg_out," IAC SE",TN_MSG_LEN);
             }
 #endif /* DEBUG */
 #ifdef OS2
             RequestTelnetMutex( SEM_INDEFINITE_WAIT );
 #endif
 #ifdef DEBUG
-            debug(F100,fwdx_msg_out,"",0);
-            if (tn_deb || debses) tn_debug(fwdx_msg_out);
+            debug(F100,(char *)fwdx_msg_out,"",0);
+            if (tn_deb || debses) tn_debug((char *)fwdx_msg_out);
 #endif /* DEBUG */
             rc = (ttol(sb_priv,j) < 0);                /* Send it. */
 #ifdef OS2
@@ -1894,20 +1903,20 @@ fwdx_send_data_from_channel(channel, data, len)
 
 #ifdef DEBUG
     if (deblog || tn_deb || debses) {
-        ckmakxmsg( fwdx_msg_out,TN_MSG_LEN,
+        ckmakxmsg( (char *)fwdx_msg_out,TN_MSG_LEN,
                    "TELNET SENT SB ",TELOPT(TELOPT_FORWARD_X),
                    " DATA ",ckctox(p[0],1)," ",ckctox(p[1],1)," ",
                    NULL,NULL,NULL,NULL,NULL);
-        tn_hex(fwdx_msg_out,TN_MSG_LEN,&sb_priv[6],j-8);
-        ckstrncat(fwdx_msg_out," IAC SE",TN_MSG_LEN);
+        tn_hex((CHAR *)fwdx_msg_out,TN_MSG_LEN,&sb_priv[6],j-8);
+        ckstrncat((char *)fwdx_msg_out," IAC SE",TN_MSG_LEN);
     }
 #endif /* DEBUG */
 #ifdef OS2
     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
 #endif
 #ifdef DEBUG
-    debug(F100,fwdx_msg_out,"",0);
-    if (tn_deb || debses) tn_debug(fwdx_msg_out);
+    debug(F100,(char *)fwdx_msg_out,"",0);
+    if (tn_deb || debses) tn_debug((char *)fwdx_msg_out);
 #endif /* DEBUG */
     rc = (ttol(sb_priv,j) < 0);                /* Send it. */
 #ifdef OS2
@@ -2052,10 +2061,10 @@ fwdx_send_xauth(void)
 
 #ifdef DEBUG
     if (deblog || tn_deb || debses) {
-        sprintf(fwdx_msg_out,"TELNET SENT SB %s OPTION_DATA XAUTH ",
+        sprintf((char *)fwdx_msg_out,"TELNET SENT SB %s OPTION_DATA XAUTH ",
                  TELOPT(TELOPT_FORWARD_X));
-        tn_hex(fwdx_msg_out,TN_MSG_LEN,&sb_priv[5],(p-sb_priv)-7);
-        ckstrncat(fwdx_msg_out," IAC SE",TN_MSG_LEN);
+        tn_hex((char *)fwdx_msg_out,TN_MSG_LEN,&sb_priv[5],(p-sb_priv)-7);
+        ckstrncat((char *)fwdx_msg_out," IAC SE",TN_MSG_LEN);
     }
 #endif /* DEBUG */
 
@@ -2064,8 +2073,8 @@ fwdx_send_xauth(void)
     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
 #endif
 #ifdef DEBUG
-    debug(F100,fwdx_msg_out,"",0);
-    if (tn_deb || debses) tn_debug(fwdx_msg_out);
+    debug(F100,(char *)fwdx_msg_out,"",0);
+    if (tn_deb || debses) tn_debug((char *)fwdx_msg_out);
 #endif /* DEBUG */
     rc = ( ttol(sb_priv,p-sb_priv) < 0 );                /* Send it. */
 #ifdef OS2
@@ -2631,6 +2640,8 @@ tn_set_modes() {
 
 VOID
 tn_sdsb() {
+    /* if (!IS_TELNET()) return; */
+
     if (TELOPT_SB(TELOPT_TTYPE).term.need_to_send) {
         tn_sttyp();
         TELOPT_SB(TELOPT_TTYPE).term.need_to_send = 0;
@@ -2684,6 +2695,8 @@ int
 tn_reset() {
     int x,opt,cmd;
 
+    /* if (!IS_TELNET()) return(1); */
+
     tn_wait_idx = 0;                    /* Clear the tn_push() buffer */
     tn_wait_tmo = TN_TIMEOUT;           /* Reset wait timer stats */
 
@@ -2855,6 +2868,8 @@ int
 tn_start() {
     int wait, x, opt;
 
+    /* if (!IS_TELNET()) return(0); */
+
     if (tn_init && tn_begun)
         return(0);
     tn_begun = 1;
@@ -3217,6 +3232,10 @@ tn_ini() {
 
     if (ttnet != NET_TCPB)              /* Make sure connection is TCP/IP */
       return(0);
+/*
+    if (!IS_TELNET())
+      return(0);
+*/
     if (tn_init)                        /* Have we done this already? */
       return(0);                        /* Don't do it again. */
 
@@ -3233,21 +3252,45 @@ tn_ini() {
         tn_init = 1;
         debug(F100,"tn_ini telnet negotiations ignored","tn_init",tn_init);
         return(0);
+#ifdef COMMENT
+      /* Jeff's code from 30 Dec 2005 - doesn't work with SSL POP server */
+      case NP_NONE:
+      case NP_SSL:
+      case NP_TLS:
+        ttnproto = NP_TELNET;           /* pretend it's telnet anyway, */
+        oldplex = duplex;               /* save old duplex value */
+        duplex = 1;                     /* and set to half duplex for telnet */
+        if (inserver)
+          debug(F100,"tn_ini skipping telnet negotiations","",0);
+       else
+         tn_wait("tn_ini - waiting to see if telnet negotiations were sent");
+       tn_push();
+        return(0);
+      case NP_SSL_RAW:
+      case NP_TLS_RAW:
+      case NP_TCPRAW:                   /* Raw socket requested. */
+        debug(F100,"tn_ini telnet negotiations ignored","tn_init",tn_init);
+        return(0);
+#else
+      /* My code from 4 Dec 2005 - works with SSL POP server */
       case NP_NONE:
       case NP_SSL:
       case NP_TLS:                      /* If not talking to a telnet port, */
+      case NP_SSL_RAW:                 /* SSL and TLS with Telnet */
+      case NP_TLS_RAW:                 /* negotiations disabled. */
         ttnproto = NP_TELNET;           /* pretend it's telnet anyway, */
         oldplex = duplex;               /* save old duplex value */
         duplex = 1;                     /* and set to half duplex for telnet */
         if (inserver)
           debug(F100,"tn_ini skipping telnet negotiations","",0);
-          else
-        tn_wait("tn_ini - waiting to see if telnet negotiations were sent");
+       else
+         tn_wait("tn_ini - waiting to see if telnet negotiations were sent");
        tn_push();
         return(0);
       case NP_TCPRAW:                   /* Raw socket requested. */
         debug(F100,"tn_ini telnet negotiations ignored","tn_init",tn_init);
         return(0);
+#endif /* COMMENT */
       case NP_KERMIT:                   /* switching to Telnet protocol */
       case NP_SSL_TELNET:
       case NP_TLS_TELNET:
@@ -3418,6 +3461,7 @@ tn_siks(cmd) int cmd; {         /* TELNET SEND IKS SUB */
 
     if (ttnet != NET_TCPB) return(0);   /* Must be TCP/IP */
     if (ttnproto != NP_TELNET) return(0); /* Must be telnet protocol */
+
     if (cmd < KERMIT_START || cmd > KERMIT_RESP_STOP) /* Illegal subcommand */
       return(-1);
 
@@ -3516,6 +3560,8 @@ tn_sb( opt, len, fn ) int opt; int * len; int (*fn)();
 #endif /* CK_ANSIC */
 /* tn_sb */ {
     int c, x, y, n, m, flag;
+    /* if (!IS_TELNET()) return(1); */
+
     debug(F100,"Entering tn_sb()","",0);
     *len = 0;                   /* Initialize Len to 0 */
     n = flag = 0;               /* Flag for when done reading SB */
@@ -3567,7 +3613,7 @@ tn_sb( opt, len, fn ) int opt; int * len; int (*fn)();
                 ckmakmsg( tn_msg,TN_MSG_LEN,
                           "TELNET RCVD SB ",TELOPT(opt),
                          " DATA(buffer-full) ",NULL);
-                tn_hex(tn_msg,TN_MSG_LEN,&sb[1],n-3);
+                tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&sb[1],n-3);
                 if (flag == 2)
                     ckstrncat(tn_msg," SE",TN_MSG_LEN);
                 else if (flag == 3)
@@ -4333,6 +4379,7 @@ tn_xdoop(z, echo, fn) CHAR z; int echo; int (*fn)();
 #endif /* NOICP */
 #endif /* IKS_OPTION */
 
+    /* if (!IS_TELNET()) return(7); */
 
 /* Have IAC, read command character. */
 
@@ -5040,10 +5087,10 @@ tn_xdoop(z, echo, fn) CHAR z; int echo; int (*fn)();
 #endif /* CK_SSL */
 
         if (!TELOPT_OK(x)) {
-            hexdump("unknown telnet subnegotiation",sb,n);
+            ckhexdump("unknown telnet subnegotiation",sb,n);
             break;
         } else if ( !(TELOPT_ME(x) || TELOPT_U(x)) ) {
-            hexdump("telnet option not negotiated",sb,n);
+            ckhexdump("telnet option not negotiated",sb,n);
             if (!tn_sb_bug)
                 break;
             if (TELOPT_UNANSWERED_WILL(x)) {
@@ -5140,7 +5187,7 @@ tn_xdoop(z, echo, fn) CHAR z; int echo; int (*fn)();
                       rc = -3;
                   } else {
 #ifndef NOLOCAL
-                      extern tls_norestore;
+                      extern int tls_norestore;
 #endif /* NOLOCAL */
                       printf("TLS failed:  Disconnecting...\n");
 #ifdef CK_ENCRYPTION
@@ -5259,7 +5306,7 @@ tn_xdoop(z, echo, fn) CHAR z; int echo; int (*fn)();
 #endif /* CK_AUTHENTICATION */
 #ifdef CK_ENCRYPTION
           case TELOPT_ENCRYPTION:
-            if (ck_tn_sb_encrypt(sb, n) < 0) {
+            if (ck_tn_sb_encrypt((char *)sb, n) < 0) {
                 if (TELOPT_U_MODE(x) == TN_NG_MU ||
                     TELOPT_ME_MODE(x) == TN_NG_MU)
                   {
@@ -5543,6 +5590,17 @@ tn_doop(z, echo, fn) CHAR z; int echo; int (*fn)();
 /* tn_doop */ {
     int x=0, y=0;
 
+    debug(F101,"tn_doop char","",z);
+    debug(F101,"tn_doop ttnproto","",ttnproto);
+
+    if (!IS_TELNET()) return(3);
+
+#ifdef CK_SSL
+    debug(F101,"tn_doop ssl_raw_flag","",ssl_raw_flag);
+    if (ssl_raw_flag || tls_raw_flag) return(7);
+#endif /* CK_SSL */
+    debug(F100,"tn_doop ttnproto proceeding...","",0);
+
     if (z != (CHAR) IAC) {
         debug(F101,"tn_doop bad call","",z);
         return(-1);
@@ -5779,7 +5837,7 @@ tn_snenv(sb, len) CHAR * sb; int len;
         uu = localuidbuf;
     }
 
-    hexdump((CHAR *)"tn_snenv sb[]",sb,len);
+    ckhexdump((CHAR *)"tn_snenv sb[]",sb,len);
     debug(F110,"tn_snenv uidbuf",uidbuf,0);
     debug(F110,"tn_snenv localuidbuf",localuidbuf,0);
     debug(F110,"tn_snenv tn_env_sys",tn_env_sys,0);
@@ -6320,6 +6378,8 @@ tn_sndfwdx() {                          /* Send Fwd X Screen number to host */
     char * disp;
     int i,rc;
 
+    /* if (!IS_TELNET()) return(0); */
+
     if (!TELOPT_U(TELOPT_FORWARD_X)) return(0);
 #ifdef CK_SSL
     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
@@ -6333,7 +6393,7 @@ tn_sndfwdx() {                          /* Send Fwd X Screen number to host */
      * the localhost; the screen defaults to 0
      */
 
-    disp = tn_get_display();
+    disp = (char *)tn_get_display();
     if (disp) {
         int colon,dot;
         colon = ckindex(":",disp,0,0,1);
@@ -6387,6 +6447,8 @@ tn_sndloc() {                           /* Send location. */
     int i,rc;                              /* Worker. */
     char *ttloc;
 
+    /* if (!IS_TELNET()) return(0); */
+
     if (!TELOPT_ME(TELOPT_SNDLOC)) return(0);
 
 #ifdef CK_SSL
@@ -6530,6 +6592,8 @@ tnc_init()
 /* tnc_init */ {
     debug(F100,"tnc_init","",0);
 
+    /* if (!IS_TELNET()) return(0); */
+
     if (tnc_signature) {
         free(tnc_signature);
         tnc_signature = NULL;
@@ -6562,6 +6626,8 @@ tn_sndcomport()
     int baud, datasize, parity, stopsize, oflow, iflow;
     CONST char * signature;
 
+    /* if (!IS_TELNET()) return(0); */
+
     debug(F100,"tnc_sndcomport","",0);
     signature = tnc_get_signature();
     baud = tnc_get_baud();
@@ -6583,6 +6649,9 @@ tnc_wait(msg, ms) CHAR * msg; int ms;
 #endif /* CK_ANSIC */
 /* tnc_wait */ {
     int rc, tn_wait_save = tn_wait_flg;
+
+    /* if (!IS_TELNET()) return(0); */
+
     debug(F111,"tnc_wait","begin",ms);
     if ( ms )
         TELOPT_SB(TELOPT_COMPORT).comport.wait_for_ms = 1;
index c05b3fb..242e396 100644 (file)
--- a/ckctel.h
+++ b/ckctel.h
@@ -6,15 +6,15 @@
            Frank da Cruz <fdc@columbia.edu>
   Columbia University Academic Information Systems, New York City.
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2009,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
 
   Notes:
+  . This file should be used in place of "arpa/telnet.h"
   . Only one source file should include #defines for
     TELCMDS, TELOPTS, TELOPT_STATES, SLC_NAMES, and AUTH_NAMES.
-  . This file should be used inplace of "arpa/telnet.h"
 */
 
 #ifndef CKCTEL_H
@@ -24,6 +24,9 @@
   Definitions for the TELNET protocol.
   can't rely on library header files for any of them.
 */
+#ifdef COMMENT
+/* In some compilers these are prone to sign extension */
+
 #ifndef IAC                             /* First the telnet commands */
 #define IAC 255
 #endif /* IAC */
 
 #define TN_SAK 200              /* IBM Secure Attention Key */
 #endif /* LAST_TN_CMD */
-
 #define SYNCH   242             /* for telfunc calls */
 
+#else
+/* Hex notation seems to suppress the sugn extension effect */
+
+
+#ifndef IAC                             /* First the telnet commands */
+#define IAC 0xff
+#endif /* IAC */
+#ifndef DONT
+#define DONT 0xfe                      /* 254 */
+#endif /* DONT */
+#ifndef DO
+#define DO 0xfd                                /* 253 */
+#endif /* DO */
+#ifndef WONT
+#define WONT 0xfc                      /* 252 */
+#endif /* WONT */
+#ifndef WILL
+#define WILL 0xfb                      /* 251 */
+#endif /* WILL */
+#ifndef SB
+#define SB 0xfa                                /* 250 */
+#endif /* SB */
+#ifndef TN_GA
+#define TN_GA 0xf9                     /* 249 */
+#endif /* TN_GA */
+#ifndef TN_EL
+#define TN_EL 0xf8                     /* 248 */
+#endif /* TN_EL */
+#ifndef TN_EC
+#define TN_EC 0xf7                     /* 247 */
+#endif /* TN_EC */
+#ifndef TN_AYT
+#define TN_AYT 0xf6                    /* 246 */
+#endif /* TN_AYT */
+#ifndef TN_AO
+#define TN_AO 0xf5                     /* 245 */
+#endif /* TN_AO */
+#ifndef TN_IP
+#define TN_IP 0xf4                     /* 244 */
+#endif /* TN_IP */
+#ifndef BREAK
+#define BREAK 0xf3                     /* 243 */
+#endif /* BREAK */
+#ifndef TN_DM
+#define TN_DM 0xf2                     /* 242 */
+#endif /* TN_DM */
+#ifndef TN_NOP
+#define TN_NOP 0xf1                    /* 241 */
+#endif /* TN_NOP */
+#ifndef SE
+#define SE 0xf0                                /* 240 */
+#endif /* SE */
+#ifndef TN_EOR
+#define TN_EOR 0xef                    /* 239 */
+#endif /* TN_EOR */
+#ifndef TN_ABORT
+#define TN_ABORT 0xee                  /* 238 */
+#endif /* TN_ABORT */
+#ifndef TN_SUSP
+#define TN_SUSP 0xed                   /* 237 */
+#endif /* TN_SUSP */
+#ifndef TN_EOF
+#define TN_EOF 0xec                    /* 236 */
+#endif /* TN_EOF */
+#ifndef LAST_TN_CMD
+#define LAST_TN_CMD 0xec               /* 236 */
+
+#define TN_SAK 0xc8                    /* 200 - IBM Secure Attention Key */
+#endif /* LAST_TN_CMD */
+#define SYNCH 0xf2                     /* 242 - for telfunc calls */
+
+#endif /* COMMENT */
+
 #ifdef TELCMDS
 char *telcmds[] = {
         "EOF", "SUSP", "ABORT", "EOR",
@@ -1070,8 +1145,10 @@ _PROTOTYP( VOID fwdx_check_sockets,(fd_set *));
 _PROTOTYP( int fwdx_init_fd_set,(fd_set *));
 _PROTOTYP( int fwdx_authorize_channel, (int, unsigned char *, int));
 _PROTOTYP( int fwdx_create_fake_xauth, (char *, int, int));
-_PROTOTYP( int fwdx_send_xauth, (VOID));
+_PROTOTYP( int fwdx_send_xauth_to_xserver, (int, unsigned char *, int len));
 _PROTOTYP( int fwdx_server_avail, (VOID));
+_PROTOTYP( int fwdx_parse_displayname, (char *, int *, char **, int *, int *, char **));
+
 #ifdef NT
 _PROTOTYP( VOID fwdx_thread,(VOID *));
 #endif /* NT */
index b579510..1f58548 100644 (file)
--- a/ckcuni.c
+++ b/ckcuni.c
@@ -1,4 +1,4 @@
-char * ckcuni = "Unicode support 8.0.115, 9 Oct 2002";
+char * ckcuni = "Unicode support 9.0.115, 16 Oct 2009";
 
 #ifdef OS2
 #define KERMITFONT
@@ -7,7 +7,7 @@ char * ckcuni = "Unicode support 8.0.115, 9 Oct 2002";
 /*  C K C U N I . C  --  Unicode/Terminal character-set translations  */
 
 /*
-  Copyright (C) 1999, 2004,
+  Copyright (C) 1999, 2009,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
index df978c2..06dff9b 100644 (file)
--- a/ckcuni.h
+++ b/ckcuni.h
@@ -1,7 +1,7 @@
 /*  C K C U N I . H  --  Unicode/Terminal character-set translations  */
 
 /*
-  Copyright (C) 1999, 2004,
+  Copyright (C) 1999, 2009,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
index e5dc887..6403c81 100644 (file)
--- a/ckcxla.h
+++ b/ckcxla.h
@@ -8,7 +8,7 @@
   Author: Frank da Cruz <fdc@columbia.edu>,
   The Kermit Project - Columbia University, New York City.
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2009,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -83,6 +83,9 @@
 #ifdef UNICODE
 #undef UNICODE
 #endif /* UNICODE */
+#ifndef NOUNICODE
+#define NOUNICODE
+#endif /* NOUNICODE */
 
 #else /* Not NOCSETS - Rest of this file... */
 
diff --git a/ckermit.ini b/ckermit.ini
deleted file mode 100644 (file)
index f007561..0000000
+++ /dev/null
@@ -1,618 +0,0 @@
-COMMENT - Standard C-Kermit initialization file
-;
-; For C-Kermit Version: 8.0
-;
-; Filename:
-;   .kermrc     (UNIX, OS-9, Aegis)
-;   CKERMIT.INI (OS/2, VMS, OpenVMS, AOS/VS, Atari ST, Commodore Amiga)
-;   ckermit.ini (Stratus VOS)
-;   K95.INI     (Kermit 95 -- but this big version is not used there)
-;   K2.INI      (Kermit/2  -- but ditto)
-;
-; Authors:
-;   Frank da Cruz, Christine M. Gianone, Jeffrey Altman
-;   Columbia University, New York, NY 10025-7799, USA
-;
-; This is the standard and recommended C-Kermit 8.0 initialization file.  To
-; override settings or definitions made in this file, to add new settings or
-; definitions, or to make any other desired customizations, create a separate,
-; personal customization file called:
-;
-;   .mykermrc     (UNIX, OS-9, Aegis, BeBox, Plan 9)
-;   CKERMOD.INI   (OS/2, VMS, OpenVMS, AOS/VS, Atari ST, Commodore Amiga)
-;   ckermod.ini   (VOS)
-;
-; You can also define the customization filename in an environment
-; variable (logical name in VMS), CKERMOD, which takes precedence over
-; the names shown above.
-;
-; WHAT THIS FILE DOES:
-;
-; . Defines your default dialing directory name:
-;     .kdd for UNIX, OS-9 and Aegis; CKERMIT.KDD for other operating systems.
-;        You can override this with the environment variable K_DIAL_DIRECTORY
-; . Defines your default network directory name:
-;     .knd for UNIX, OS-9 and Aegis; CKERMIT.KND for other operating systems.
-;        You can override this with the environment variable K_NET_DIRECTORY
-; . Defines your default services directory name:
-;     .ksd for UNIX, OS-9 and Aegis; CKERMIT.KSD for other operating systems.
-;        You can override this with environment variable K_SERVICE_DIRECTORY.
-; . Defines your customization file name (name given above)
-; . Performs system-dependent setups for UNIX, VMS, OS/2, etc.
-; . Defines VTPRINT macros for use with K95, MS-DOS Kermit, etc.
-; . If you have a services directory, all the macros needed to use it are
-;     defined.  If you don't have a services directory, the macros are not
-;     defined and Kermit starts faster.
-; . Executes your personal customization file, if you have one.
-;   NOTE: Your customization file is NOT executed by Kermit itself; it is
-;   executed by this file.
-;
-; In UNIX, with C-Kermit 7.0 and later, you can store this file with a name
-; other than .kermrc, and it will not be executed automatically, but, if you
-; give this file execute permission, you can execute directly because of the
-; "kerbang line" at the top, whenever you want all of the above actions to
-; occur.  The kerbang line must reflect the actual full path of the Kermit
-; 7.0-or-later executable.
-;
-; C-Kermit 6.0 is documented in the book "Using C-Kermit", 2nd Edition,
-; by Frank da Cruz and Christine M. Gianone, 1997, Digital Press /
-; Butterworth-Heinemann, ISBN 1-55558-164-1.  New features of subsequent
-; versions are documented at the Kermit website:
-; http://www.columbia.edu/kermit/
-;
-; Everything after this point depends on the script programming language.
-; The CHECK command terminates this command file immediately if the script
-; programming language (IF command) is not configured.
-;
-set take error on              ; This makes CHECK quit if no script language.
-check if                       ; Do we have an IF command?  If not, quit now.
-set take error off             ; Back to normal.
-
-local _sd _servicedir _xp       ; Declare local variables.
-
-COMMENT - C-Kermit version 6.0 or later required.
-;
-
-asg _xp \v(xprogram)
-if not def _xp asg _xp \v(program)
-if not equal "\m(_xp)" "C-Kermit" -
-  stop 1 \v(cmdfile): This initialization file is only for C-Kermit.
-echo Executing \v(cmdfile) for \v(system)...
-if < \v(version) 60000 -
-  stop 1 \v(cmdfile): C-Kermit 6.0 or later required.
-
-forward \v(system)             ; First do system-dependent items...
-
-:unknown                       ; Should not happen
-Stop 1 Error: System type unknown!
-
-:Aegis                         ; Apollo Aegis and
-:UNIX                          ; UNIX, all versions
-asg _myinit -
-  \v(home).mykermrc            ; Customization filename
-if remote forward COMMON        ; Skip local-mode items if "-R"
-asg _dialdir -
-  \v(home).kdd                 ; C-Kermit dialing directory
-asg _netdir -
-  \v(home).knd                 ; C-Kermit network directory
-asg _servicedir -
-  \v(home).ksd                 ; C-Kermit services directory
-forward COMMON                  ; End of UNIX section
-
-:OS9/68K                       ; OS-9
-asg _myinit -
-  \v(home).mykermrc            ; Customization filename
-if remote forward COMMON
-asg _dialdir -
-  \v(home).kdd                 ; C-Kermit dialing directory
-asg _netdir -
-  \v(home).knd                 ; C-Kermit network directory
-asg _servicedir -
-  \v(home).ksd                 ; C-Kermit services directory
-else set file display crt
-forward COMMON                 ; End of OS-9 section
-
-:VMS                           ; VMS and OpenVMS
-forward COMMON
-
-:OS/2                          ; Kermit 95
-:WIN32
-echo This initialization file is not for use with K95.
-forward COMMON                  ; End of OS/2 section
-
-:AOS/VS                                ; Data General AOS/VS
-set window 1                   ; Sliding windows don't work
-set file char dg-international ; File character-set
-set xfer char latin1           ; Transfer character-set
-set file display crt            ; File transfer fisplay
-def cli push                   ; Escape to CLI
-def reset -                    ; Macro to reset DG DASHER terminal
- run write [!ascii 236 306 301]
-forward COMMON                  ; End of AOS/VS section
-
-:Amiga                         ; Commodore Amiga
-def cls echo \27[H\27[2J       ; CLS command to clear the screen
-set file char latin1           ; Use Latin Alphabet 1 for file transfer
-set xfer char latin1           ; ...
-forward COMMON                  ; End of Amiga section
-
-:Atari_ST                      ; Atari ST
-def cls echo \27H\27J          ; Clear screen a`la VT52
-set server display on          ; Show file xfer display in server mode too
-set server timeout 15          ; Nonzero required for ^C interruption!
-forward COMMON                  ; End of Atari ST section
-
-:Macintosh                     ; Apple Macintosh
-set server display on          ; Show file xfer display in server mode too.
-forward COMMON
-
-:Stratus_VOS                    ; Stratus VOS
-asg _myinit \v(home)ckermod.ini
-if remote forward COMMON
-asg _dialdir \v(home)ckermit.kdd
-asg _netdir \v(home)ckermit.knd
-asg _servicedir \v(home)ckermit.ksd
-forward COMMON                  ; End of Stratus VOS section
-
-:COMMON                                ; For all systems
-
-; Define macros that are useful when running C-Kermit in remote mode.
-; These macros serve no purpose on local-mode-only versions such as
-; OS/2, Macintosh, Amiga, and Atari ST Kermit, so we skip defining them
-; for those systems.
-;
-if not = 0 \findex(\v(system),WIN32:OS/2:Macintosh:Amiga:Atari_ST) -
-  forward files
-
-; VTPRINT macro.  Print a file on your PC's local printer.
-
-def VTPRINT echo \27[5i, type \%1, echo \27[4i
-; or if your printer needs a formfeed to force the page out:
-; def VTPRINT  def echo \27[5i, type \%1, echo \12\27[4i
-
-; Macros for host-initiated file transfer using APC:
-;   NOT NEEDED ANY MORE because of autodownload/autoupload.
-;   Remove the following FORWARD command to reinstate these definitions:
-
-:FILES
-
-; Get customization and directory file names.  Environment variables take
-; precedence, so you do not have to edit this file to change these filenames.
-;
-if def \$(CKERMOD) assign _myinit \$(CKERMOD)
-if not def _myinit assign _myinit \v(home)CKERMOD.INI
-
-if remote forward CUSTOM ; Skip all this if -R given on command line
-
-if def \$(K_NET_DIRECTORY) assign _netdir \$(K_NET_DIRECTORY)
-if not def _netdir assign _netdir \v(home)CKERMIT.KND
-
-if def \$(K_DIAL_DIRECTORY) assign _dialdir \$(K_DIAL_DIRECTORY)
-if not def _dialdir assign _dialdir \v(home)CKERMIT.KDD
-
-CHECK DIAL                     ; Is there a DIAL command?
-xif fail {                     ; No.
-    echo DIAL disabled
-    forward CUSTOM
-}
-
-CHECK NETWORK
-xif success {
-    xif exist \m(_netdir) {
-       set net directory \m(_netdir)
-       echo { Network directory is \m(_netdir) }
-    }
-}
-
-if eq "\v(name)" "telnet" forward CUSTOM
-
-xif exist \m(_dialdir) {
-    set dial directory \m(_dialdir)
-    echo { Dial directory is \m(_dialdir) }
-}
-
-COMMENT - Services directory
-
-if def \$(K_SERVICE_DIRECTORY) assign _servicedir \$(K_SERVICE_DIRECTORY)
-if not def _servicedir assign _servicedir \v(home)CKERMIT.KSD
-
-; If no services directory is found skip all the big macro definitions and
-; go straight to the bottom, where we execute the customization file.
-
-if not exist \m(_servicedir) forward custom
-
-echo { Services directory is \m(_servicedir)}
-
-def MAX_SVCS 200               ; Adjust this if you have more entries
-define _sd 0                   ; Assume no services directory
-open read \m(_servicedir)      ; Try to open services directory file
-xif success {
-    declare \&d[\m(MAX_SVCS)]  ; It's open, declare directory array
-    for \%i 1 \m(MAX_SVCS) 1 { ; Read the lines into the array
-       read \&d[\%i]
-       if fail break
-    }
-    close read
-    xif > \%i  \m(MAX_SVCS) {
-       echo Too many entries in services directory
-       echo { Maximum is \m(MAX_SVCS).}
-       echo { Change definition of MAX_SVCS in \v(cmdfile) to allow more. }
-       echo { Services directory disabled.}
-    } else {
-        asg \&d[0] \feval(\%i - 1)
-        define _sd 1
-    }
-}
-
-xif not \m(_sd) {
-    def access echo { Services directory not available.}
-    asg list \m(access)
-} else {
-    def FIND {
-       set case off
-       for \%i 1 \&d[0] 1 {
-           if eq {\%1} {\fsubstr(\&d[\%i],1,\flen(\%1))} break
-       }
-       if not > \%i \&d[0] return \&d[\%i]
-    }
-    def LIST {
-       xif > \v(argc) 1 {
-           do find \%1
-           if def \v(return) echo \v(return)
-           else echo \%1: Not found
-       } else {
-           echo \&d[0] items in services directory:
-           for \%i 1 \&d[0] 1 { echo \fcont(\&d[\%i]) }
-       }
-    }
-    def SPLIT { asg _word1 \%1, asg _word2 \%2 }
-    def DOACCESS {               ; (Used internally by ACCESS macro)
-       do \%5 \%6 \%7 \%8 \%9   ; Do the connection macro
-       if fail end 1
-        split \%3                ; Get words from \%3
-       asg \%3 \m(_word1)
-       asg \%2 \m(_word2)
-       do \%3 \%4 {\%1} \%2     ; Login macro, userid, password, prompt
-    }
-    def ACCESS {
-       if not defined \%1 end 1 access what?        ; Check service
-       do find \%1                                  ; Look it up
-       if success doaccess {\%2} \v(return)         ; OK, try it
-       else end 1 "\%1" not in services directory   ; Not found
-       if fail end 1                                ; DOACCESS failed?
-       xif eq \v(cmdlevel) 1 {
-           echo
-           echo ACCESS: Login succeeded - CONNECTing...
-            show escape
-            output \13
-           connect /quietly
-        }
-    }
-}
-
-:CONNECTION ; Macros for making connections
-
-COMMENT - SERIAL macro.  Arguments:
-; \%1 = device name
-; \%2 = speed
-;
-def SERIAL {
-    if < \v(argc) 3                         ; All arguments given?
-      end 1 Usage: SERIAL device speed      ; No.
-    set line \%1                            ; OK, try to SET LINE.
-    if failure -                            ; If this failed,
-      end 1 Can't open device: \%1          ; print message and quit.
-    set speed \%2                           ; Try to set the speed.
-    if fail end 1 Unsupported speed: \%2    ; Failed.
-    echo Connection successful.             ; Succeeded.
-}
-
-COMMENT - NET macro.  Arguments:
-; \%1 = network type
-; \%2 = host name or address
-;
-def NET {
-    if < \v(argc) 3 end 1 Usage: NET network host
-    set network type \%1
-    if fail end 1 unsupported network: \%1
-    set login user                ; Don't send user ID.
-    set host \%2
-    if fail end 1 Can't reach host: \%2
-    echo Connection successful.
-}
-
-COMMENT - CALL macro.  Arguments:
-;
-; \%1 = modem type
-; \%2 = device name
-; \%3 = speed
-; \%4 = phone number
-;
-def CALL {
-    if < \v(argc) 5 -         ; All arguments present?
-      end 1 Usage: CALL modem device speed number
-    xif not equal {\v(modem)} {\%1} { ; Set modem type
-        set modem \%1
-        if fail end 1 unknown modem type: \%1
-    }
-    xif not equal {\v(line)} {\%2} { ; Communication device
-        set line \%2
-        if fail end 1 can't open device: \%2
-    }
-    xif not equal {\v(speed)} {\%3} { ; Communication speed
-        set speed \%3
-        if fail end 1 unsupported speed: \%3
-    }
-    dial \%4                  ; Dial the number
-    if fail end 1 Can't place call: \%4
-    end 0 Connection successful.
-}
-
-COMMENT - TCPCALL macro.  Arguments:
-;
-; \%1 = server name:port
-; \%2 = modem type
-; \%3 = phone number
-;
-def TCPCALL {
-    if < \v(argc) 4 -         ; All arguments present?
-      end 1 Usage: TCPCALL server[:port] modem number
-    set net type tcp/ip       ; Which network to use
-    if fail end 1 unsupported network: tcp/ip
-    set host \%1              ; Access server and port
-    if fail end 1 can't access server \%1
-    set modem \%2             ; Set modem type
-    if fail end 1 unknown modem type: \%2
-    dial \%3                  ; Dial the number
-    if fail end 1 Can't place call: \%3
-    end 0 Connection successful.
-}
-
-COMMENT - SPRINT macro.  Arguments:
-; \%1 = Service name or address
-;
-def SPRINT {
-    if < \v(argc) 2 end 1 Usage: \%0 service
-    set input timeout proceed
-    output @D\13
-    input 10 TERMINAL=
-    if fail end 1 No terminal prompt
-    out D1\13
-    inp 10 @
-    if fail end 1 No atsign prompt
-    output c \%1\13
-    input 10 CONNECTED
-    if fail end 1 Can't access \%1 from SprintNet
-}
-
-COMMENT - ULOGIN macro.  For logging into systems where user ID is required
-; but there is no password.  Arguments:
-; \%1 = UNIX user ID
-;
-define ULOGIN {
-    if < \v(argc) 2 end 1 Usage: \%0 userid
-    set input timeout proceed     ; Handle timeouts ourselves
-    set case on                   ; Case is important in UNIX
-    minput 5 login: Username: {User ID:} {User Name:}
-    out \%1\13                    ; Send username, carriage return
-    end 0
-}
-
-COMMENT - VMSLOGIN macro.  Arguments:
-; \%1 = VMS user ID
-; \%2 = Password.  If password not supplied, it is prompted for.
-; \%3 = System prompt.  If omitted a default is supplied.
-;
-define VMSLOGIN {
-    if < \v(argc) 2 end 1 Usage: \%0 userid [ password [ prompt ] ]
-    while not defined \%2 {
-        askq \%2 { \%1's password: }
-    }
-    set parity none               ; Set communication parameters
-    set duplex full
-    set handshake none
-    set input timeout proceed     ; Handle timeouts ourselves
-    in 5 Username:                ; Is prompt already there?
-    xif fail {                    ; No.
-        for \%i 1 3 1 {           ; Try 3 times to get it.
-            out \13               ; Send carriage return
-            in 5 Username:        ; Look for prompt
-            if success break      ; Success, go log in
-        }
-        if > \%i 3 end 1 No Username prompt
-    }
-    out \%1\13                    ; Send username, carriage return
-    inp 5 Password:               ; Wait 5 sec for this prompt
-    if fail end 1 No password prompt
-    pause                         ; Wait a sec
-    out \%2\13                    ; Send password
-    xif not emulation {           ; No emulator built in?
-        set input echo off        ; Protect terminal from this
-        minput 10 {\27Z} {\27[c} {\27[0c} ; Get terminal ID query
-        xif success {                     ; Got one
-            output \27[\?1c               ; Send VT100 terminal ID
-            in 2 \27[6n                   ; Screen dimension query?
-            if succ out \27[\v(rows);\v(cols)R ; Send dimensions
-        }
-        set input echo on         ; Echo input again
-    }
-    if not def \%3 -              ; If we were not given a prompt
-      asg \%3 {\v(prompt)}        ; use the SET LOGIN PROMPT value
-    if not def \%3 -              ; If we still don't have a prompt
-      asg \%3 {\13$\32}           ; use this one as the default
-    reinp 0 \%3                   ; Did we INPUT the prompt already?
-    if fail inp 60 \%3            ; No, look now.
-    if fail end 1
-}
-
-COMMENT - UNIXLOGIN macro.  Arguments:
-; \%1 = UNIX user ID
-; \%2 = Password.  If password not supplied, it is prompted for.
-; \%3 = System prompt.  If omitted a default is supplied.
-;
-define UNIXLOGIN {
-    local \%m \%i
-    if < \v(argc) 2 -
-      end 1 Usage: \%0 userid [ password [ prompt ] ]
-    while not defined \%2 {
-        askq \%2 { \%1's password: }
-    }
-    set input echo on
-    set parity none               ; Set communication parameters.
-    set duplex full
-    set handshake none
-    set input timeout proceed     ; Handle timeouts ourselves
-    set case on                   ; Case is important in UNIX
-    def \%m 10                    ; Waiting time for INPUT
-    for \%i 1 5 1 {
-        minput \%m login: {ssword:} {Password for \%1:}
-       if success break
-       output \B\13
-        \%m ::= 6-\%1
-    }
-    if > \%i 5 end 1 {No response from host}
-    xif = \v(minput) 1 {         ; Have username prompt
-       output \%1\13             ; Send username
-        minput 5 {ssword:} {ssword for \%1:} ; Wait for password prompt
-       if fail end 1 {No password prompt}
-    }
-    pause                         ; Wait a sec
-    out \%2\13                    ; Send password
-    if not def \%3 -              ; If we were not given a prompt
-      asg \%3 {\v(prompt)}        ; use the SET LOGIN PROMPT value
-    if not def \%3 -              ; If we still don't have a prompt
-      asg \%3 {\10$ }             ; use this one as the default
-    reinp 0 \%3                   ; Did we INPUT the prompt already?
-    if fail inp 60 \%3            ; No, look now.
-    if fail end 1
-}
-
-COMMENT - VMLINELOGIN macro.  Arguments:
-; \%1 = User ID
-; \%2 = Password
-;
-define VMLINELOGIN {
-    if < \v(argc) 2 -
-      end 1 Usage: \%0 userid [ password ]
-    while not defined \%2 {
-        askq \%2 { \%1's password: }
-    }
-    set parity mark               ; Set communication parameters
-    set flow none
-    set handshake xon
-    set duplex half
-    set input timeout quit        ; Don't bother with IF FAILURE
-    input 10 BREAK KEY            ; Look for BREAK KEY prompt
-    pause 1                       ; Wait a second
-    output \B                     ; Send BREAK
-    input 10 .\17, output logon \%1\13    ; Now log in
-    input 10 .\17, output \%2\13          ; Send password
-    input 10 .\17, output \13             ; Send carriage return
-    input 10 .\17, output \13             ; Send another one
-    end 0
-}
-
-COMMENT - VMFULLOGIN macro.  Arguments:
-; \%1 = User ID
-; \%2 = Password
-;
-define VMFULLOGIN {
-    if < \v(argc) 2 -
-      end 1 Usage: \%0 userid [ password ]
-    while not defined \%2 {
-        askq \%2 { \%1's password: }
-    }
-    set input timeout quit      ; Quit if INPUT fails
-    set parity even             ; Set communication parameters
-    set duplex full
-    set handshake none
-    set flow xon/xoff
-    out \13                     ; Send carriage return
-    inp 5 TERMINAL TYPE:        ; Get terminal-type prompt
-    out vt-100\13               ; Just send "vt-100"
-    inp 20 RUNNING              ; Get RUNNING message
-    pau 1                       ; Wait one second
-    out \%1\9\%2\13             ; Send user ID, tab, password
-    out \13\13                  ; Two more carriage returns
-    end 0
-}
-
-COMMENT - CISLOGIN macro.  Arguments:
-; \%1 = CompuServe User ID
-; \%2 = Password
-; \%3 = Prompt
-;
-define CISLOGIN {
-    if < \v(argc) 2 -
-      end 1 Usage: \%0 userid [ password [ prompt ] ]
-    while not defined \%2 {
-        askq \%2 { \%1's password: }
-    }
-    set terminal bytesize 7     ; No 8-bit characters
-    set input timeout quit      ; Skip the IF FAILURE's
-    output \13                  ; Send initial carriage return
-    input 5 Host Name:          ; Look for Host Name prompt
-    output cis\13               ; Send "cis" and carriage return
-    input 5 User ID:            ; Look for User ID prompt
-    output \%1\13               ; Send ID and carriage return
-    input Password:             ; Look for Password prompt
-    output \%2\13               ; Send password and CR
-    if not def \%3 asg \%3 \v(prompt)
-    if not def \%3 asg \%3 {CompuServe Information Service}
-    input 30 \%3
-    end 0
-}
-
-COMMENT - DOWLOGIN macro.  Arguments:
-; \%1 = Dow Jones Password
-;
-define DOWLOGIN {
-    while not defined \%1 {              ; Get password
-        askq \%1 { Dow Jones password: }
-    }
-    set input timeout proceed
-    input 20 SERVICE PLEASE\?\?\?\?      ; Look for Dow prompt
-    if fail end 1 No service prompt
-    out djnr\13                          ; Select DJNR
-    input 10 @@@@@@@@                        ; Get password prompt
-    if fail end 1 No password prompt
-    pause 1                              ; Wait a second, then...
-    output \%1\13                        ; send password and CR
-    input 30 ENTER QUERY                 ; Get DJNR query prompt
-    if fail end 1 No main query prompt
-    pause 1
-}
-
-COMMENT - DJNRSPRINT macro: Log in to Dow Jones via SprintNet.
-;
-def djnrsprint sprint dow, if success dowlogin
-
-COMMENT - NOLOGIN macro.  Does nothing.  Use when login not required.
-;
-def nologin comment
-
-:CUSTOM ; Customization file
-
-; In VMS and OpenVMS, allow for system-wide site customizations
-
-xif equal "\v(system)" "VMS" {
-    xif exist CKERMIT_INI:CKERMIT.SYS {
-       echo Executing CKERMIT_INI:CKERMIT.SYS
-       take CKERMIT_INI:CKERMIT.SYS
-    }
-}
-
-; Execute user's personal customization file
-
-xif exist \m(_myinit)  {               ; If it exists,
-    echo Executing \m(_myinit)...      ; print message,
-    take \m(_myinit)                   ; and TAKE the file.
-}
-
-; Finish up with traditional greeting.
-
-if < \v(ntime) 43200 echo Good Morning!
-  else if < \v(ntime) 61200 echo Good Afternoon!
-  else echo Good Evening.
-
-End ; of C-Kermit 8.0 initialization file.
diff --git a/ckermit70.txt b/ckermit70.txt
deleted file mode 100644 (file)
index 8aca397..0000000
+++ /dev/null
@@ -1,17956 +0,0 @@
-
-   [ [1]Contents ] [ [2]C-Kermit ] [ [3]Kermit Home ]
-
-                 Supplement to Using C-Kermit, Second Edition
-
-For C-Kermit 7.0
-
-As of C-Kermit version:  7.0.196
-This file last updated:  8 February 2000
-
-Authors: Frank da Cruz and Christine M. Gianone
-Address: The Kermit Project
-         Columbia University
-         612 West 115th Street
-         New York NY 10025-7799
-         USA
-Fax:     +1 (212) 662-6442
-E-Mail:  [4]kermit-support@columbia.edu
-Web:     [5]http://www.columbia.edu/kermit/
-Or:      [6]http://www.kermit-project.org/
-Or:      [7]http://www.columbia.nyc.ny.us/kermit/
-     _________________________________________________________________
-
-  NOTICES
-
-   This document:
-          Copyright Â© 1997, 2000, Frank da Cruz and Christine M. Gianone.
-          All rights reserved.
-
-   Kermit 95:
-          Copyright Â© 1995, 2000, Trustees of Columbia University in the
-          City of New York. All rights reserved.
-
-   C-Kermit:
-          Copyright Â© 1985, 2000,
-          Trustees of Columbia University in the City of New York. All
-          rights reserved. See the C-Kermit [8]COPYING.TXT file or the
-          copyright text in the [9]ckcmai.c module for disclaimer and
-          permissions.
-
-   When Kerberos(TM) and/or SRP(TM) (Secure Remote Password) and/or SSL
-          protocol are included:
-          Portions Copyright Â© 1990, Massachusetts Institute of
-          Technology.
-          Portions Copyright Â© 1991, 1993 Regents of the University of
-          California.
-          Portions Copyright Â© 1991, 1992, 1993, 1994, 1995 by AT&T.
-          Portions Copyright Â© 1997, Stanford University.
-          Portions Copyright Â© 1995-1997, Eric Young
-          <eay@cryptosoft.com>.
-
-   For the full text of the third-party copyright notices, see
-   [10]Appendix V.
-     _________________________________________________________________
-
-  WHAT IS IN THIS FILE
-
-   This file lists changes made to C-Kermit since the second edition of
-   the book [11]Using C-Kermit was published and C-Kermit 6.0 was
-   released in November 1996. Use this file as a supplement to the second
-   edition of Using C-Kermit until the third edition is published some
-   time in 2000. If the "most recent update" shown above is long ago,
-   contact Columbia University to see if there is a newer release.
-
-   For further information, also see the [12]CKCBWR.TXT ("C-Kermit
-   beware") file for hints, tips, tricks, restrictions, frequently asked
-   questions, etc, plus the system-specific "beware file", e.g.
-   [13]CKUBWR.TXT for UNIX, [14]CKVBWR.TXT for VMS, etc, and also any
-   system-specific update files such as KERMIT95.HTM for Kermit 95 (in
-   the DOCS\MANUAL\ subdirectory of your K95 directory).
-
-     This Web-based copy of the C-Kermit 7.0 update notes supersedes the
-     plain-text CKERMIT2.TXT file. All changes after 19 January 2000
-     appear only here in the Web version. If you need an up-to-date
-     plain-text copy, use your Web browser to save this page as plain
-     text. 
-     _________________________________________________________________
-
-  ABOUT FILENAMES
-
-   In this document, filenames are generally shown in uppercase, but on
-   file systems with case-sensitive names such as UNIX, OS-9, and AOS/VS,
-   lowercase names are used: [15]ckubwr.txt, [16]ckermit70.txt, etc.
-     _________________________________________________________________
-
-  ADDITIONAL FILES
-
-   Several other files accompany this new Kermit release:
-
-   SECURITY.TXT
-          Discussion of Kermit's new authentication and encryption
-          features:
-
-          + [17]Plain-text version
-          + [18]HTML (hypertext) version
-
-   IKSD.TXT
-          How to install and manage an Internet Kermit Service Daemon.
-
-          + [19]Plain-text version
-          + [20]HTML (hypertext) version
-
-          Also see [21]cuiksd.htm for instructions for use.
-
-   TELNET.TXT
-          A thorough presentation of Kermit's new advanced Telnet
-          features and controls.
-
-          + [22]Plain-text version
-          + [23]HTML (hypertext) version
-     _________________________________________________________________
-
-  THE NEW C-KERMIT LICENSE
-
-   The C-Kermit license was rewritten for version 7.0 to grant automatic
-   permission to packagers of free operating-system distributions to
-   include C-Kermit 7.0. Examples include Linux (GNU/Linux), FreeBSD,
-   NetBSD, etc. The new license is in the [24]COPYING.TXT file, and is
-   also displayed by C-Kermit itself when you give the VERSION or
-   COPYRIGHT command. The new C-Kermit license does not apply to
-   [25]Kermit 95.
-     _________________________________________________________________
-
-  ACKNOWLEDGMENTS
-
-   Thanks to Jeff Altman, who joined the Kermit Project in 1995, for much
-   of what you see in C-Kermit 7.0, especially in the networking and
-   security areas, and his key role in designing and implementing the
-   Internet Kermit Service Daemon. And special thanks to Lucas Hart for
-   lots of help with the VMS version; to Peter Eichhorn for continuous
-   testing on the full range of HP-UX versions and for a consolidated set
-   of HP-UX makefile targets; and to Colin Allen, Mark Allen, Roger
-   Allen, Ric Anderson, William Bader, Mitch Baker, Mitchell Bass, Nelson
-   Beebe, Gerry Belanger, Jeff Bernsten, Mark Berryman, John Bigg, Volker
-   Borchert, Jonathan Boswell, Tim Boyer, Frederick Bruckman, Kenneth
-   Cochran, Jared Crapo, Bill Delaney, Igor Sobrado Delgado, Clarence
-   Dold, Joe Doupnik, John Dunlap, Max Evarts, Patrick French, Carl
-   Friedberg, Carl Friend, Hirofumi Fujii, Andrew Gabriel, Gabe Garza,
-   Boyd Gerber, David Gerber, George Gilmer, Hunter Goatley, DJ Hagberg,
-   Kevin Handy, Andy Harper, Randolph Herber, Sven Holström, Michal
-   Jaegermann, Graham Jenkins, Dick Jones, Terry Kennedy, Robert D Keys,
-   Nick Kisseberth, Igor Kovalenko, David Lane, Adam Laurie, Jeff
-   Liebermann, Eric Lonvick, Hoi Wan Louis, Arthur Marsh, Gregorie
-   Martin, Peter Mauzey, Dragan Milicic, Todd Miller, Christian Mondrup,
-   Daniel Morato, Dat Nguyen, Herb Peyerl, Jean-Pierre Radley, Steve
-   Rance, Stephen Riehm, Nigel Roles, Larry Rosenman, Jay S Rouman, David
-   Sanderson, John Santos, Michael Schmitz, Steven Schultz, Bob Shair,
-   Richard Shuford, Fred Smith, Michael Sokolov, Jim Spath, Peter Szell,
-   Ted T'so, Brian Tillman, Linus Torvalds, Patrick Volkerding, Martin
-   Vorländer, Steve Walton, Ken Weaverling, John Weekley, Martin
-   Whitaker, Jim Whitby, Matt Willman, Joellen Windsor, Farrell Woods,
-   and many others for binaries, hosting, reviews, suggestions, advice,
-   bug reports, and all the rest over the 3+ year C-Kermit 7.0
-   development cycle. Thanks to Russ Nelson and the board of the Open
-   Software Initiative ([26]http://www.opensource.org) for their
-   cooperation in developing the new C-Kermit license and to the
-   proprietors of those free UNIX distributions that have incorporated
-   C-Kermit 7.0 for their cooperation and support, especially FreeBSD's
-   Jörg Wunsch.
-     _________________________________________________________________
-
-  NOTE TO KERMIT 95 USERS
-
-   Kermit 95 and C-Kermit share the same command and scripting language,
-   the same Kermit file-transfer protocol implementation, and much else
-   besides.
-
-   Like the book [27]Using C-Kermit, this file concentrates on the
-   aspects of C-Kermit that are common to all versions: UNIX, VMS,
-   Windows, OS/2, VOS, AOS/VS, etc. Please refer to your Kermit 95
-   documentation for information that is specific to Kermit 95.
-
-   C-Kermit 7.0 corresponds to Kermit 95 1.1.19.
-     _________________________________________________________________
-
-  C-KERMIT VERSIONS AND VERSION NUMBERS
-
-   "C-Kermit" refers to all the many programs that are compiled in whole
-   or in part from common C-language source code, comprising:
-
-     * A Kermit file transfer protocol module
-     * A command parser and script execution module
-     * A modem-dialing module
-     * A network support module
-     * A character-set translation module.
-
-   and several others. These "system-independent" modules are combined
-   with system-dependent modules for each platform to provide the
-   required input/output functions, and also in some cases overlaid with
-   an alternative user interface, such as Macintosh Kermit's
-   point-and-click interface, and in some cases also a terminal emulator,
-   as Kermit 95.
-
-   The C-Kermit version number started as 1.0, ... 3.0, 4.0, 4.1 and then
-   (because of confusion at the time with Berkeley UNIX 4.2), 4B, 4C, and
-   so on, with the specific edit number in parentheses, for example
-   4E(072) or 5A(188). This scheme was used through 5A(191), but now we
-   have gone back to the traditional numbering scheme with decimal
-   points: major.minor.edit; for example 7.0.196. Internal version
-   numbers (the \v(version) variable), however, are compatible in
-   C-Kermit 5A upwards.
-
-   Meanwhile, C-Kermit derivatives for some platforms (Windows,
-   Macintosh) might go through several releases while C-Kermit itself
-   remains the same. These versions have their own platform-specific
-   version numbers, such as Kermit 95 1.1.1, 1.1.2, and so on.
-
-   C-Kermit Version History:
-
-  1.0       1981-1982         Command-line only, 4.2 BSD UNIX only
-  2.0       (*)               (who remembers...)
-  3.0       May 1984          Command-line only, supports several platforms
-  4.0-4.1   Feb-Apr 1985 (*)  First interactive and modular version
-  4C(050)   May 1985
-  4D(060)   April 1986
-  4E(066)   August 1987       Long packets
-  4E(068)   January 1988
-  4E(072)   January 1989
-  4F(095)   August 1989 (*)   Attribute packets
-  5A(188)   November 1992     Scripting, TCP/IP, sliding windows (1)
-  5A(189)   September 1993    Control-char unprefixing
-  5A(190)   October 1994      Recovery
-  5A(191)   April 1995        OS/2 only
-  6.0.192   September 1996    Intelligent dialing, autodownload, lots more (2)
-  6.1.193   1997-98 (*)       Development only
-  6.1.194   June 1998         K95 only - switches, directory recursion, more
-  7.0.195   August 1999       IKSD + more (CU only as K95 1.1.18-CU)
-  7.0.196   1 January 2000    Unicode, lots more
-
-   (*) Never formally released (4.0 was a total rewrite)
-   (1) Using C-Kermit, 1st Edition
-   (2) Using C-Kermit, 2nd Edition
-     _________________________________________________________________
-
-CONTENTS
-
- I.  [28]C-KERMIT DOCUMENTATION
-
- II. [29]NEW FEATURES
-
-     (0) [30]INCOMPATIBILITIES WITH PREVIOUS RELEASES
-     (1) [31]PROGRAM AND FILE MANAGEMENT AND COMMANDS
-         1.0.  [32]Bug fixes
-         1.1.  [33]Command Continuation
-         1.2.  [34]Editor Interface
-         1.3.  [35]Web Browser and FTP Interface
-         1.4.  [36]Command Editing
-         1.5.  [37]Command Switches
-               1.5.1. [38]General Switch Syntax
-               1.5.2. [39]Order and Effect of Switches
-               1.5.3. [40]Distinguishing Switches from Other Fields
-               1.5.4. [41]Standard File Selection Switches
-               1.5.5. [42]Setting Preferences for Different Commands
-         1.6.  [43]Dates and Times
-         1.7.  [44]Partial Completion of Keywords
-         1.8.  [45]Command Recall
-         1.9.  [46]EXIT Messages
-         1.10. [47]Managing Keyboard Interruptions
-         1.11. [48]Taming the Wild Backslash -- Part Deux
-               1.11.1. [49]Background
-               1.11.2. [50]Kermit's Quoting Rules
-               1.11.3. [51]Passing DOS Filenames from Kermit to Shell Commands
-               1.11.4. [52]Using Variables to Hold DOS Filenames
-               1.11.5. [53]Passing DOS Filenames as Parameters to Macros
-               1.11.6. [54]Passing DOS File Names from Macro Parameters to the
-DOS Shell
-               1.11.7. [55]Passing DOS Filenames to Kermit from the Shell
-         1.12. [56]Debugging
-         1.13. [57]Logs
-         1.14. [58]Automatic File-Transfer Packet Recognition at the Command Pr
-ompt
-         1.15. [59]The TYPE Command
-         1.16. [60]The RESET Command
-         1.17. [61]The COPY and RENAME Commands
-         1.18. [62]The MANUAL Command
-         1.19. [63]String and Filename Matching Patterns
-         1.20. [64]Multiple Commands on One Line
-         1.21. [65]What Do I Have?
-         1.22. [66]Generalized File Input and Output
-               1.22.1. [67]Why Another I/O System?
-               1.22.2. [68]The FILE Command
-               1.22.3. [69]FILE Command Examples
-               1.22.4. [70]Channel Numbers
-               1.22.5. [71]FILE Command Error Codes
-               1.22.6. [72]File I/O Variables
-               1.22.7. [73]File I/O Functions
-               1.22.8. [74]File I/O Function Examples
-         1.23. [75]The EXEC Command
-         1.24. [76]Getting Keyword Lists with '?'
-     (2) [77]MAKING AND USING CONNECTIONS
-         2.0. [78]SET LINE and SET HOST Command Switches
-         2.1. [79]Dialing
-              2.1.1. [80]The Dial Result Message
-              2.1.2. [81]Long-Distance Dialing Changes
-              2.1.3. [82]Forcing Long-Distance Dialing
-              2.1.4. [83]Exchange-Specific Dialing Decisions
-              2.1.5. [84]Cautions about Cheapest-First Dialing
-              2.1.6. [85]Blind Dialing (Dialing with No Dialtone)
-              2.1.7. [86]Trimming the Dialing Dialog
-              2.1.8. [87]Controlling the Dialing Speed
-              2.1.9. [88]Pretesting Phone Number Conversions
-              2.1.10. [89]Greater Control over Partial Dialing
-              2.1.11. [90]New DIAL-related Variables and Functions
-              2.1.12. [91]Increased Flexibility of PBX Dialing
-              2.1.13. [92]The DIAL macro - Last-Minute Phone Number Conversions
-              2.1.14. [93]Automatic Tone/Pulse Dialing Selection
-              2.1.15. [94]Dial-Modifier Variables
-              2.1.16. [95]Giving Multiple Numbers to the DIAL Command
-         2.2. [96]Modems
-              2.2.1. [97]New Modem Types
-              2.2.2. [98]New Modem Controls
-         2.3. [99]TELNET and RLOGIN
-              2.3.0. [100]Bug Fixes
-              2.3.1. [101]Telnet Binary Mode Bug Adjustments
-              2.3.2. [102]VMS UCX Telnet Port Bug Adjustment
-              2.3.3. [103]Telnet New Environment Option
-              2.3.4. [104]Telnet Location Option
-              2.3.5. [105]Connecting to Raw TCP Sockets
-              2.3.6. [106]Incoming TCP Connections
-         2.4. [107]The EIGHTBIT Command
-         2.5. [108]The Services Directory
-         2.6. [109]Closing Connections
-         2.7. [110]Using C-Kermit with External Communication Programs
-              2.7.0. [111]C-Kermit over tn3270 and tn5250
-              2.7.1. [112]C-Kermit over Telnet
-              2.7.2. [113]C-Kermit over Rlogin
-              2.7.3. [114]C-Kermit over Serial Communication Programs
-              2.7.4. [115]C-Kermit over Secure Network Clients
-              2.7.4.1. [116]SSH
-              2.7.4.2. [117]SSL
-              2.7.4.3. [118]SRP
-              2.7.4.4. [119]SOCKS
-              2.7.4.5. [120]Kerberos and SRP
-         2.8. [121]Scripting Local Programs
-         2.9. [122]X.25 Networking
-              2.9.1. [123]IBM AIXLink/X.25 Network Provider Interface for AIX
-              2.9.2. [124]HP-UX X.25
-         2.10. [125]Additional Serial Port Controls
-         2.11. [126]Getting Access to the Dialout Device
-         2.12. [127]The Connection Log
-         2.13. [128]Automatic Connection-Specific Flow Control Selection
-         2.14. [129]Trapping Connection Establishment and Loss
-         2.15. [130]Contacting Web Servers with the HTTP Command
-     (3) [131]TERMINAL CONNECTION
-         3.1. [132]CONNECT Command Switches
-         3.2. [133]Triggers
-         3.3. [134]Transparent Printing
-         3.4. [135]Binary and Text Session Logs
-     (4) [136]FILE TRANSFER AND MANAGEMENT
-         4.0. [137]Bug Fixes, Minor Changes, and Clarifications
-         4.1. [138]File-Transfer Filename Templates
-         4.1.1. [139]Templates in the As-Name
-         4.1.2. [140]Templates on the Command Line
-         4.1.3. [141]Post-Transfer Renaming
-         4.2. [142]File-Transfer Pipes and Filters
-         4.2.1. [143]Introduction
-         4.2.1.1. [144]Terminology
-         4.2.1.2. [145]Notation
-         4.2.1.3. [146]Security
-         4.2.2. [147]Commands for Transferring from and to Pipes
-         4.2.2.1. [148]Sending from a Command
-         4.2.2.2. [149]Receiving to a Command
-         4.2.3. [150]Using File-Transfer Filters
-         4.2.3.1. [151]The SEND Filter
-         4.2.3.2. [152]The RECEIVE Filter
-         4.2.4. [153]Implicit Use of Pipes
-         4.2.5. [154]Success and Failure of Piped Commands
-         4.2.6. [155]Cautions about Using Pipes to Transfer Directory Trees
-         4.2.7. [156]Pipes and Encryption
-         4.2.8. [157]Commands and Functions Related to Pipes
-         4.2.8.1. [158]The OPEN !READ and OPEN !WRITE Commands
-         4.2.8.2. [159]The REDIRECT Command
-         4.2.8.3. [160]Receiving Mail and Print Jobs
-         4.2.8.4. [161]Pipe-Related Functions
-         4.3. [162]Automatic Per-File Text/Binary Mode Switching
-         4.3.1. [163]Exceptions
-         4.3.2. [164]Overview
-         4.3.3. [165]Commands
-         4.3.4. [166]Examples
-         4.4. [167]File Permissions
-         4.4.1. [168]When ATTRIBUTES PROTECTION is OFF
-         4.4.1.1. [169]Unix
-         4.4.1.2. [170]VMS
-         4.4.2. [171]When ATTRIBUTES PROTECTION is ON
-         4.4.2.1. [172]System-Specific Permissions
-         4.4.2.1.1. [173]UNIX
-         4.4.2.1.2. [174]VMS
-         4.4.2.2. [175]System-Independent Permissions
-         4.5. [176]File Management Commands
-         4.5.1. [177]The DIRECTORY Command
-         4.5.2. [178]The CD and BACK Commands
-         4.5.2.1. [179]Parsing Improvements
-         4.5.2.2. [180]The CDPATH
-         4.5.3. [181]Creating and Removing Directories
-         4.5.4. [182]The DELETE and PURGE Commands
-         4.6. [183]Starting the Remote Kermit Server Automatically
-         4.7. [184]File-Transfer Command Switches
-         4.7.1. [185]SEND Command Switches
-         4.7.2. [186]GET Command Switches
-         4.7.3. [187]RECEIVE Command Switches
-         4.8. [188]Minor Kermit Protocol Improvements
-         4.8.1. [189]Multiple Attribute Packets
-         4.8.2. [190]Very Short Packets
-         4.9. [191]Wildcard / File Group Expansion
-         4.9.1. [192]In UNIX C-Kermit
-         4.9.2. [193]In Kermit 95
-         4.9.3. [194]In VMS, AOS/VS, OS-9, VOS, etc.
-         4.10. [195]Additional Pathname Controls
-         4.11. [196]Recursive SEND and GET: Transferring Directory Trees
-         4.11.1. [197]Command-Line Options
-         4.11.2. [198]The SEND /RECURSIVE Command
-         4.11.3. [199]The GET /RECURSIVE Command
-         4.11.4. [200]New and Changed File Functions
-         4.11.5. [201]Moving Directory Trees Between Like Systems
-         4.11.6. [202]Moving Directory Trees Between Unlike Systems
-         4.12. [203]Where Did My File Go?
-         4.13. [204]File Output Buffer Control
-         4.14. [205]Improved Responsiveness
-         4.15. [206]Doubling and Ignoring Characters for Transparency
-         4.16. [207]New File-Transfer Display Formats
-         4.17. [208]New Transaction Log Formats
-         4.17.1. [209]The BRIEF Format
-         4.17.2. [210]The FTP Format
-         4.18. [211]Unprefixing NUL
-         4.19. [212]Clear-Channel Protocol
-         4.20. [213]Streaming Protocol
-         4.20.1. [214]Commands for Streaming
-         4.20.2. [215]Examples of Streaming
-         4.20.2.1. [216]Streaming on Socket-to-Socket Connections
-         4.20.2.2. [217]Streaming on Telnet Connections
-         4.20.2.3. [218]Streaming with Limited Packet Length
-         4.20.2.4. [219]Streaming on Dialup Connections
-         4.20.2.5. [220]Streaming on X.25 Connections
-         4.20.3. [221]Streaming - Preliminary Conclusions
-         4.21. [222]The TRANSMIT Command
-         4.22. [223]Coping with Faulty Kermit Implementations
-         4.22.1. [224]Failure to Accept Modern Negotiation Strings
-         4.22.2. [225]Failure to Negotiate 8th-bit Prefixing
-         4.22.3. [226]Corrupt Files
-         4.22.4. [227]Spurious Cancellations
-         4.22.5. [228]Spurious Refusals
-         4.22.6. [229]Failures during the Data Transfer Phase
-         4.22.7. [230]Fractured Filenames
-         4.22.8. [231]Bad File Dates
-         4.23. [232]File Transfer Recovery
-         4.24. [233]FILE COLLISION UPDATE Clarification
-         4.25. [234]Autodownload Improvements
-     (5) [235]CLIENT/SERVER
-         5.0. [236]Hints
-         5.1. [237]New Command-Line Options
-         5.2. [238]New Client Commands
-         5.3. [239]New Server Capabilities
-         5.3.1. [240]Creating and Removing Directories
-         5.3.2. [241]Directory Listings
-         5.4. [242]Syntax for Remote Filenames with Embedded Spaces
-         5.5. [243]Automatic Orientation Messages upon Directory Change
-         5.6. [244]New Server Controls
-         5.7. [245]Timeouts during REMOTE HOST Command Execution
-     (6) [246]INTERNATIONAL CHARACTER SETS
-         6.0. [247]ISO 8859-15 Latin Alphabet 9
-         6.1. [248]The HP-Roman8 Character Set
-         6.2. [249]Greek Character Sets
-         6.3. [250]Additional Latin-2 Character Sets
-         6.4. [251]Additional Cyrillic Character Sets
-         6.5. [252]Automatic Character-Set Switching
-         6.6. [253]Unicode
-         6.6.1. [254]Overview of Unicode
-         6.6.2. [255]UCS Byte Order
-         6.6.2. [256]UCS Transformation Formats
-         6.6.3. [257]Conformance Levels
-         6.6.4. [258]Relationship of Unicode with Kermit's Other Character Sets
-         6.6.5. [259]Kermit's Unicode Features
-         6.6.5.1. [260]File Transfer
-         6.6.5.2. [261]The TRANSLATE Command
-         6.6.5.3. [262]Terminal Connection
-         6.6.5.4. [263]The TRANSMIT Command
-         6.6.5.5. [264]Summary of Kermit Unicode Commands
-         6.7. [265]Client/Server Character-Set Switching
-     (7) [266]SCRIPT PROGRAMMING
-         7.0. [267]Bug Fixes
-         7.1. [268]The INPUT Command
-         7.1.1. [269]INPUT Timeouts
-         7.1.2. [270]New INPUT Controls
-         7.1.3. [271]INPUT with Pattern Matching
-         7.1.4. [272]The INPUT Match Result
-         7.2. [273]New or Improved Built-In Variables
-         7.3. [274]New or Improved Built-In Functions
-         7.4. [275]New IF Conditions
-         7.5. [276]Using More than Ten Macro Arguments
-         7.6. [277]Clarification of Function Call Syntax
-         7.7. [278]Autodownload during INPUT Command Execution
-         7.8. [279]Built-in Help for Functions.
-         7.9. [280]Variable Assignments
-         7.9.1. [281]Assignment Operators
-         7.9.2. [282]New Assignment Commands
-         7.10. [283]Arrays
-         7.10.1. [284]Array Initializers
-         7.10.2. [285]Turning a String into an Array of Words
-         7.10.3. [286]Arrays of Filenames
-         7.10.4. [287]Automatic Arrays
-         7.10.5. [288]Sorting Arrays
-         7.10.6. [289]Displaying Arrays
-         7.10.7. [290]Other Array Operations
-         7.10.8. [291]Hints for Using Arrays
-         7.10.9. [292]Do-It-Yourself Arrays
-         7.10.10. [293]Associative Arrays
-         7.11. [294]OUTPUT Command Improvements
-         7.12. [295]Function and Variable Diagnostics
-         7.13. [296]Return Value of Macros
-         7.14. [297]The ASSERT, FAIL, and SUCCEED Commands.
-         7.15. [298]Using Alarms
-         7.16. [299]Passing Arguments to Command Files
-         7.17. [300]Dialogs with Timed Responses
-         7.18. [301]Increased Flexibility of SWITCH Case Labels
-         7.19. "[302]Kerbang" Scripts
-         7.20. [303]IF and XIF Statement Syntax
-         7.20.1. [304]The IF/XIF Distinction
-         7.20.2. [305]Boolean Expressions (The IF/WHILE Condition)
-         7.21. [306]Screen Formatting and Cursor Control
-         7.22. [307]Evaluating Arithmetic Expressions
-         7.23. [308]Floating-Point Arithmetic
-         7.24. [309]Tracing Script Execution
-         7.25. [310]Compact Substring Notation
-         7.26. [311]New WAIT Command Options
-         7.26.1. [312]Waiting for Modem Signals
-         7.26.2. [313]Waiting for File Events
-         7.27. [314]Relaxed FOR and SWITCH Syntax
-     (8) [315]USING OTHER FILE TRANSFER PROTOCOLS
-     (9) [316]COMMAND-LINE OPTIONS
-         9.0. [317]Extended-Format Command-Line Options
-         9.1. [318]Command Line Personalities
-         9.2. [319]Built-in Help for Command Line Options
-         9.3. [320]New Command-Line Options
-    (10) [321]C-KERMIT AND G-KERMIT
-
-III. [322]APPENDICES
-
-III.1. [323]Character Set Tables
-III.1.1. [324]The Hewlett Packard Roman8 Character Set
-III.1.2. [325]Greek Character Sets
-III.1.2.1. [326]The ISO 8859-7 Latin / Greek Alphabet
-III.1.2.2. [327]The ELOT 927 Character Set
-III.1.2.3. [328]PC Code Page 869
-III.2. [329]Updated Country Codes
-
-IV. [330]ERRATA & CORRIGENDA: Corrections to "Using C-Kermit" 2nd Edition.
-V. [331]ADDITIONAL COPYRIGHT NOTICES
-     _________________________________________________________________
-
-I. C-KERMIT DOCUMENTATION
-
-   The user manual for C-Kermit is:
-
-     Frank da Cruz and Christine M. Gianone, [332]Using C-Kermit, Second
-     Edition, Digital Press / Butterworth-Heinemann, Woburn, MA, 1997,
-     622 pages, ISBN 1-55558-164-1.
-
-   [333]CLICK HERE for reviews.
-
-   The present document is a supplement to Using C-Kermit 2nd Ed, not a
-   replacement for it.
-
-   US single-copy price: $52.95; quantity discounts available. Available
-   in bookstores or directly from Columbia University:
-
-  The Kermit Project
-  Columbia University
-  612 West 115th Street
-  New York NY  10025-7799
-  USA
-  Telephone: +1 (212) 854-3703
-  Fax:       +1 (212) 662-6442
-
-   Domestic and overseas orders accepted. Price: US $44.95 (US, Canada,
-   and Mexico). Shipping: $4.00 within the USA; $15.00 to all other
-   countries. Orders may be paid by MasterCard or Visa, or prepaid by
-   check in US dollars. Add $65 bank fee for checks not drawn on a US
-   bank. Do not include sales tax. Inquire about quantity discounts.
-
-   You can also order by phone from the publisher, Digital Press /
-   [334]Butterworth-Heinemann, with MasterCard, Visa, or American
-   Express:
-
-  +1 800 366-2665   (Woburn, Massachusetts office for USA & Canada)
-  +44 1865 314627   (Oxford, England distribution centre for UK & Europe)
-  +61 03 9245 7111  (Melbourne, Vic, office for Australia & NZ)
-  +65 356-1968      (Singapore office for Asia)
-  +27 (31) 2683111  (Durban office for South Africa)
-
-   A [335]German-language edition of the First Edition is also available:
-
-     Frank da Cruz and Christine M. Gianone, C-Kermit - Einführung und
-     Referenz, Verlag Heinz Heise, Hannover, Germany (1994). ISBN
-     3-88229-023-4. Deutsch von Gisbert W. Selke. Price: DM 88,00.
-     Verlag Heinz Heise GmbH & Co. KG, Helstorfer Strasse 7, D-30625
-     Hannover. Tel. +49 (05 11) 53 52-0, Fax. +49 (05 11) 53 52-1 29.
-
-   The [336]Kermit file transfer protocol is specified in:
-
-     Frank da Cruz, Kermit, A File Transfer Protocol, Digital Press,
-     Bedford, MA, 1987, 379 pages, ISBN 0-932376-88-6. US single-copy
-     price: $39.95. Availability as above.
-
-   News and articles about Kermit software and protocol are published
-   periodically in the journal, [337]Kermit News. Subscriptions are free;
-   contact Columbia University at the address above.
-
-   Online news about Kermit is published in the
-   [338]comp.protocols.kermit.announce and
-   [339]comp.protocols.kermit.misc newsgroups.
-     _________________________________________________________________
-
-II. NEW FEATURES
-
-   Support for the Bell Labs Plan 9 operating system was added to version
-   6.0 too late to be mentioned in the book (although it does appear on
-   the cover).
-
-   Specific changes and additions are grouped together by major topic,
-   roughly corresponding to the chapters of [340]Using C-Kermit.
-     _________________________________________________________________
-
-  0. INCOMPATIBILITIES WITH PREVIOUS RELEASES
-
-    1. C-Kermit 7.0 uses FAST Kermit protocol settings by default. This
-       includes "unprefixing" of certain control characters. Because of
-       this, file transfers that worked with previous releases might not
-       work in the new release (but it is more likely that they will
-       work, and much faster). If a transfer fails, you'll get a
-       context-sensitive hint suggesting possible causes and cures.
-       Usually SET PREFIXING ALL does the trick.
-    2. C-Kermit 7.0 transfers files in BINARY mode by default. To restore
-       the previous behavior, put SET FILE TYPE TEXT in your C-Kermit
-       initialization file.
-    3. No matter whether FILE TYPE is BINARY or TEXT by default, C-Kermit
-       7.0 now switches between text and binary mode automatically on a
-       per-file basis according to various criteria, including (a) which
-       kind of platform is on the other end of the connection (if known),
-       (b) the version of Kermit on the other end, and (c) the file's
-       name (see [341]Section 4, especially [342]4.3). To disable this
-       automatic switching and restore the earlier behavior, put SET
-       TRANSFER MODE MANUAL in your C-Kermit initialization file. To
-       disable automatic switching for a particular transfer, include a
-       /TEXT or /BINARY switch with your SEND or GET command.
-    4. The RESEND and REGET commands automatically switch to binary mode;
-       previously if RESEND or REGET were attempted when FILE TYPE was
-       TEXT, these commands would fail immediately, with a message
-       telling you they work only when the FILE TYPE is BINARY. Now they
-       simply do this for you. See [343]Section 4.23 for additional
-       (important) information.
-    5. SET PREFIXING CAUTIOUS and MINIMAL now both prefix linefeed (10
-       and 138) in case rlogin, ssh, or cu are "in the middle", since
-       otherwise <LF>~ might appear in Kermit packets, and this would
-       cause rlogin, ssh, or cu to disconnect, suspend,escape back, or
-       otherwise wreck the file transfer. Xon and Xoff are now always
-       prefixed too, even when Xon/Xoff flow control is not in effect,
-       since unprefixing them has proven dangerous on TCP/IP connections.
-    6. In UNIX, VMS, Windows, and OS/2, the DIRECTORY command is built
-       into C-Kermit itself rather than implemented by running an
-       external command or program. The built-in command might not behave
-       the way the platform-specific external one did, but many options
-       are available for customization. Of course the underlying
-       platform-specific command can still be accessed with "!", "@", or
-       "RUN" wherever the installation does not forbid. In UNIX, the "ls"
-       command can be accessed directly as "ls" in C-Kermit. See
-       [344]Section 4.5.1 for details.
-    7. SEND ? prints a list of switches rather than a list of filenames.
-       If you want to see a list of filenames, use a (system-dependent)
-       construction such as SEND ./? (for UNIX, Windows, or OS/2), SEND
-       []? (VMS), etc. See [345]Sections 1.5 and [346]4.7.1.
-    8. In UNIX, OS-9, and Kermit 95, the wildcard characters in previous
-       versions were * and ?. In C-Kermit 7.0 they are *, ?, [, ], {, and
-       }, with dash used inside []'s to denote ranges and comma used
-       inside {} to separate list elements. If you need to include any of
-       these characters literally in a filename, precede each one with
-       backslash (\). See [347]Section 4.9.
-    9. SET QUIET { ON, OFF } is now on the command stack, just like SET
-       INPUT CASE, SET COUNT, SET MACRO ERROR, etc, as described on p.458
-       of [348]Using C-Kermit, 2nd Edition. This allows any macro or
-       command file to SET QUIET ON or OFF without worrying about saving
-       and restoring the global QUIET value. For example, this lets you
-       write a script that tries SET LINE on lots of devices until it
-       finds one free without spewing out loads of error messages, and
-       also without disturbing the global QUIET setting, whatever it was.
-   10. Because of the new "." operator (which introduces assignments),
-       macros whose names begin with "." can not be invoked "by name".
-       However, they still can be invoked with DO.
-   11. The syntax of the EVALUATE command has changed. See [349]Section
-       7.9.2. To restore the previous syntax, use SET EVALUATE OLD.
-   12. The \v(directory) variable now includes the trailing directory
-       separator; in previous releases it did not. This is to allow
-       constructions such as:
-  cd \v(dir)data.tmp
-       to work across platforms that might have different directory
-       notation, such as UNIX, Windows, and VMS.
-   13. Prior to C-Kermit 7.0, the FLOW-CONTROL setting was global and
-       sticky. In C-Kermit 7.0, there is an array of default flow-control
-       values for each kind of connection, that are applied automatically
-       at SET LINE/PORT/HOST time. Thus a SET FLOW command given before
-       SET LINE/PORT/HOST is likely to be undone. Therefore SET FLOW can
-       be guaranteed to have the desired effect only if given after the
-       SET LINE/PORT/HOST command.
-   14. Character-set translation works differently in the TRANSMIT
-       command when (a) the file character-set is not the same as the
-       local end of the terminal character-set, or (b) when the terminal
-       character-set is TRANSPARENT.
-     _________________________________________________________________
-
-  1. PROGRAM AND FILE MANAGEMENT AND COMMANDS
-
-  1.0. Bug Fixes
-
-   The following patches were issued to correct bugs in C-Kermit 6.0.
-   These are described in detail in the 6.0 PATCHES file. All of these
-   fixes have been incorporated in C-Kermit 6.1 (never released except as
-   K95 1.1.16-17) and 7.0.
-
- 0001   All UNIX         C-Kermit mishandles timestamps on files before 1970
- 0002   Solaris 2.5++    Compilation error on Solaris 2.5 with Pro C
- 0003   All VMS          CKERMIT.INI Fix for VMS
- 0004   VMS/VAX/UCX 2.0  C-Kermit 6.0 can't TELNET on VAX/VMS with UCX 2.0
- 0005   All              C-Kermit Might Send Packets Outside Window
- 0006   All              MOVE from SEND-LIST does not delete original files
- 0007   Solaris 2.5++    Higher serial speeds on Solaris 2.5
- 0008   All              C-Kermit application file name can't contain spaces
- 0009   AT&T 7300 UNIXPC setuid and hardware flow-control problems
- 0010   Linux on Alpha   Patch to make ckutio.c compile on Linux/Alpha
- 0011   OS-9/68000 2.4   Patch to make ck9con.c compile on OS-9/68000 2.4
- 0012   MW Coherent 4.2  Patches for successful build on Coherent 4.2
- 0013   SINIX-Y 5.43     "delay" variable conflicts with <sys/clock.h>
- 0014   VMS/VAX/CMU-IP   Subject: Patches for VAX/VMS 5.x + CMU-IP
- 0015   All              XECHO doesn't flush its output
- 0016   VMS              CD and other directory operations might not work
- 0017   Linux 1.2.x++    Use standard POSIX interface for high serial speeds
- 0018   UNIX             SET WILDCARD-EXPANSION SHELL dumps core
- 0019   All              Hayes V.34 modem init string problem
- 0020   All              READ command does not fail if file not open
- 0021   All              Problems with long function arguments
- 0022   All              Certain \function()s can misbehave
- 0023   All              X MOD 0 crashes program
- 0024   All              Internal bulletproofing for lower() function
- 0025   OpenBSD          Real OpenBSD support for C-Kermit 6.0
- 0026   All              Incorrect checks for macro/command-file nesting depth
- 0027   All              ANSWER doesn't automatically CONNECT
- 0028   All              Overzealous EXIT warning
- 0029   All              OUTPUT doesn't echo when DUPLEX is HALF
- 0030   All              Minor problems with REMOTE DIRECTORY/DELETE/etc
- 0031   All              CHECK command broken
- 0032   All              Problem with SET TRANSMIT ECHO
- 0033   UNIX, VMS, etc   HELP SET SERVER says too much
- 0034   All              READ and !READ too picky about line terminators
- 0035   All              END from inside SWITCH doesn't work
- 0036   All              Problem telnetting to multihomed hosts
- 0037   All              Redirection failures in REMOTE xxx > file
-
-   REDIRECT was missing in many UNIX C-Kermit implementations; in version
-   7.0, it should be available in all of them.
-     _________________________________________________________________
-
-  1.1. Command Continuation
-
-   Comments that start with ";" or "#" can no longer be continued. In:
-
-  ; this is a comment -
-  echo blah
-
-   the ECHO command will execute, rather than being taken as a
-   continuation of the preceding comment line. This allows easy
-   "commenting out" of commands from macro definitions.
-
-   However, the text of the COMMENT command can still be continued onto
-   subsequent lines:
-
-  comment this is a comment -
-  echo blah
-
-   As of version 6.0, backslash is no longer a valid continuation
-   character. Only hyphen should be used for command continuation. This
-   is to make it possible to issue commands like "cd a:\" on DOS-like
-   systems.
-
-   As of version 7.0:
-
-     * You can quote a final dash to prevent it from being a continuation
-       character:
-  echo foo\-
-       This prints "foo-". The command is not continued.
-     * You can enter commands such as:
-  echo foo - ; this is a comment
-       interactively and they are properly treated as continued commands.
-       Previously this worked only in command files.
-     _________________________________________________________________
-
-  1.2. Editor Interface
-
-   SET EDITOR name [ options ]
-          Lets you specify a text-editing program. The name can be a
-          fully specified pathname like /usr/local/bin/emacs19/emacs, or
-          it can be the name of any program in your PATH, e.g. "set
-          editor emacs". In VMS, it must be a DCL command like "edit",
-          "edit/tpu", "emacs", etc. If an environment variable EDITOR is
-          defined when Kermit starts, its value is the default editor.
-          You can also specify options to be included on the editor
-          command line. Returns to Kermit when the editor exits.
-
-   EDIT [ filename ]
-          If the EDIT command is given without a filename, then if a
-          previous filename had been given to an EDIT command, it is
-          used; if not, the editor is started without a file. If a
-          filename is given, the editor is started on that file, and the
-          filename is remembered for subsequent EDIT commands.
-
-   SHOW EDITOR
-          Displays the full pathname of your text editor, if any, along
-          with any command line options, and the file most recently
-          edited (and therefore the default filename for your next EDIT
-          command).
-
-   Related variables: \v(editor), \v(editopts), \v(editfile).
-     _________________________________________________________________
-
-  1.3. Web Browser and FTP Interface
-
-   C-Kermit includes an FTP command, which simply runs the FTP program;
-   C-Kermit does not include any built-in support for Internet File
-   Transfer Protocol, nor any method for interacting directly with an FTP
-   server. In version 7.0, however, C-Kermit lets you specify your FTP
-   client:
-
-   SET FTP-CLIENT [ name [ options ] ]
-          The name is the name of the FTP executable. In UNIX, Windows,
-          or OS/2, it can be the filename of any executable program in
-          your PATH (e.g. "ftp.exe" in Windows, "ftp" in UNIX); elsewhere
-          (or if you do not have a PATH definition), it must be the fully
-          specified pathname of the FTP program. If the name contains any
-          spaces, enclose it braces. Include any options after the
-          filename; these depend the particular ftp client.
-
-   The Web browser interface is covered in the following subsections.
-     _________________________________________________________________
-
-    1.3.1. Invoking your Browser from C-Kermit
-
-   BROWSE [ url ]
-          Starts your preferred Web browser on the URL, if one is given,
-          otherwise on the most recently given URL, if any. Returns to
-          Kermit when the browser exits.
-
-   SET BROWSER [ name [ options ] ]
-          Use this command to specify the name of your Web browser
-          program, for example: "set browser lynx". The name must be in
-          your PATH, or else it must be a fully specified filename; in
-          VMS it must be a DCL command.
-
-   SHOW BROWSER
-          Displays the current browser, options, and most recent URL.
-
-   Related variables: \v(browser), \v(browsopts), \v(browsurl).
-
-   Also see [350]Section 2.15: Contacting Web Servers with the HTTP
-   Command.
-     _________________________________________________________________
-
-    1.3.2. Invoking C-Kermit from your Browser
-
-   The method for doing this depends, of course, on your browser. Here
-   are some examples:
-
-   Netscape on UNIX (X-based)
-          In the Options->Applications section, set your Telnet
-          application to:
-
-  xterm -e /usr/local/bin/kermit/kermit -J %h %p
-
-          (replace "/usr/local/bin/kermit/kermit" by C-Kermit's actual
-          pathname). -J is C-Kermit's command-line option to "be like
-          Telnet"; %h and %p are Netscape placeholders for hostname and
-          port.
-
-   Lynx on UNIX
-          As far as we know, this can be done only at compile time. Add
-          the following line to the Lynx userdefs.h file before building
-          the Lynx binary:
-
-  #define TELNET_COMMAND "/opt/bin/kermit -J"
-
-          And then add lines like the following to the Lynx.cfg file:
-
-  DOWNLOADER:Kermit binary download:/opt/bin/kermit -i -V -s %s -a %s:TRUE
-  DOWNLOADER:Kermit text download:/opt/bin/kermit -s %s -a %s:TRUE
-
-  UPLOADER:Kermit binary upload:/opt/bin/kermit -i -r -a %s:TRUE
-  UPLOADER:Kermit text upload:/opt/bin/kermit -r -a %s:TRUE
-  UPLOADER:Kermit text get:/opt/bin/kermit -g %s:TRUE
-  UPLOADER:Kermit binary get:/opt/bin/kermit -ig %s:TRUE
-
-   But none of the above is necessary if you make C-Kermit your default
-   Telnet client, which you can do by making a symlink called 'telnet' to
-   the C-Kermit 7.0 binary. See [351]Section 9.1 for details.
-     _________________________________________________________________
-
-  1.4. Command Editing
-
-   Ctrl-W ("Word delete") was changed in 7.0 to delete back to the
-   previous non-alphanumeric, rather than all the way back to the
-   previous space.
-     _________________________________________________________________
-
-  1.5. Command Switches
-
-   As of version 7.0, C-Kermit's command parser supports a new type of
-   field, called a "switch". This is an optional command modifier.
-
-    1.5.1. General Switch Syntax
-
-   A switch is a keyword beginning with a slash (/). If it takes a value,
-   then the value is appended to it (with no intervening spaces),
-   separated by a colon (:) or equal sign (=). Depending on the switch,
-   the value may be a number, a keyword, a filename, a date/time, etc.
-   Examples:
-
-  send oofa.txt                              ; No switches
-  send /binary oofa.zip                      ; A switch without a value
-  send /protocol:zmodem oofa.zip             ; A switch with a value (:)
-  send /protocol=zmodem oofa.zip             ; A switch with a value (=)
-  send /text /delete /as-name:x.x oofa.txt   ; Several switches
-
-   Like other command fields, switches are separated from other fields,
-   and from each other, by whitespace, as shown in the examples just
-   above. You can not put them together like so:
-
-  send/text/delete/as-name:x.x oofa.txt
-
-   (as you might do in VMS or DOS, or as we might once have done in
-   TOPS-10 or TOPS0-20, or PIP). This is primarily due to ambiguity
-   between "/" as switch introducer versus "/" as UNIX directory
-   separator; e.g. in:
-
-  send /delete/as-name:foo/text oofa.txt
-
-   Does "foo/text" mean the filename is "foo" and the transfer is to be
-   in text mode, or does it mean the filename is "foo/text"? Therefore we
-   require whitespace between switches to resolve the ambiguity. (That's
-   only one of several possible ambiguities -- it is also conceivable
-   that a file called "text" exists in the path "/delete/as-name:foo/").
-
-   In general, if a switch can take a value, but you omit it, then either
-   a reasonable default value is supplied, or an error message is
-   printed:
-
-  send /print:-Plaserwriter oofa.txt         ; Value included = print options
-  send /print oofa.txt                       ; Value omitted, OK
-  send /mail:kermit@columbia.edu oofa.txt    ; Value included = address
-  send /mail oofa.txt                        ; Not OK - address required
-  ?Address required
-
-   Context-sensitive help (?) and completion (Esc or Tab) are available
-   in the normal manner:
-
-  C-Kermit> send /pr? Switch, one of the following:
-    /print /protocol
-  C-Kermit> send /pro<ESC>tocol:?  File-transfer protocol,
-   one of the following:
-    kermit   xmodem   ymodem   ymodem-g   zmodem
-  C-Kermit> send /protocol:k<TAB>ermit
-
-   If a switch takes a value and you use completion on it, a colon (:) is
-   printed at the end of its name to indicate this. If it does not take a
-   value, a space is printed.
-
-   Also, if you type ? in a switch field, switches that take values are
-   shown with a trailing colon; those that don't take values are shown
-   without one.
-     _________________________________________________________________
-
-    1.5.2. Order and Effect of Switches
-
-   The order of switches should not matter, except that they are
-   evaluated from left to right, so if you give two switches with
-   opposite effects, the rightmost one is used:
-
-  send /text /binary oofa.zip                ; Sends oofa.zip in binary mode.
-
-   Like other command fields, switches have no effect whatsoever until
-   the command is entered (by pressing the Return or Enter key). Even
-   then, switches affect only the command with which they are included;
-   they do not have global effect or side effects.
-     _________________________________________________________________
-
-    1.5.3. Distinguishing Switches from Other Fields
-
-   All switches are optional. A command that uses switches lets you give
-   any number of them, including none at all. Example:
-
-  send /binary oofa.zip
-  send /bin /delete oofa.zip
-  send /bin /as-name:mupeen.zip oofa.zip
-  send oofa.zip
-
-   But how does Kermit know when the first "non-switch" is given? It has
-   been told to look for both a switch and for something else, the data
-   type of the next field (filename, number, etc). In most cases, this
-   works well. But conflicts are not impossible. Suppose, for example, in
-   UNIX there was a file named "text" in the top-level directory. The
-   command to send it would be:
-
-  send /text
-
-   But C-Kermit would think this was the "/text" switch. To resolve the
-   conflict, use braces:
-
-  send {/text}
-
-   or other circumlocutions such as "send //text", "send /./text", etc.
-
-   The opposite problem can occur if you give an illegal switch that
-   happens to match a directory name. For example:
-
-  send /f oofa.txt
-
-   There is no "/f" switch (there are several switches that begin with
-   "/f", so "/f" is ambiguous). Now suppose there is an "f" directory in
-   the root directory; then this command would be interpreted as:
-
-     Send all the files in the "/f" directory, giving each one an
-     as-name of "oofa.txt".
-
-   This could be a mistake, or it could be exactly what you intended;
-   C-Kermit has no way of telling the difference. To avoid situations
-   like this, spell switches out in full until you are comfortable enough
-   with them to know the minimum abbreviation for each one. Hint: use ?
-   and completion while typing switches to obtain the necessary feedback.
-     _________________________________________________________________
-
-    1.5.4. Standard File Selection Switches
-
-   The following switches are used on different file-oriented commands
-   (such as SEND, DIRECTORY, DELETE, PURGE) to refine the selection of
-   files that match the given specification.
-
-   /AFTER:date-time
-          Select only those files having a date-time later than the one
-          given. See [352]Section 1.6 for date-time formats. Synonym:
-          /SINCE.
-
-   /NOT-AFTER:date-time
-          Select only those files having a date-time not later than (i.e.
-          earlier or equal to) the one given. Synonym: /NOT-SINCE.
-
-   /BEFORE:date-time
-          Select only those files having a date-time earlier than the one
-          given.
-
-   /NOT-BEFORE:date-time
-          Select only those files having a date-time not earlier than
-          (i.e. later or equal to) the one given.
-
-   /DOTFILES
-          UNIX and OS-9 only: The filespec is allowed to match files
-          whose names start with (dot) period. Normally these files are
-          not shown.
-
-   /NODOTFILES
-          (UNIX and OS-9 only) Don't show files whose names start with
-          dot (period). This is the opposite of /DOTFILES, and is the
-          default. Note that when a directory name starts with a period,
-          the directory and (in recursive operations) all its
-          subdirectories are skipped.
-
-   /LARGER-THAN:number
-          Only select files larger than the given number of bytes.
-
-   /SMALLER-THAN:number
-          Only select files smaller than the given number of bytes.
-
-   /EXCEPT:pattern
-          Specifies that any files whose names match the pattern, which
-          can be a regular filename, or may contain "*" and/or "?"
-          metacharacters (wildcards), are not to be selected. Example:
-
-  send /except:*.log *.*
-
-          sends all files in the current directory except those with a
-          filetype of ".log". Another:
-
-  send /except:*.~*~ *.*
-
-          sends all files except the ones that look like Kermit or EMACS
-          backup files (such as "oofa.txt.~17~") (of course you can also
-          use the /NOBACKUP switch for this).
-
-          The pattern matcher is the same one used by IF MATCH string
-          pattern ([353]Section 7.4), so you can test your patterns using
-          IF MATCH. If you need to match a literal * or ? (etc), precede
-          it by a backslash (\). If the pattern contains any spaces, it
-          must be enclosed in braces:
-
-  send /except:{Foo bar} *.*
-
-          The pattern can also be a list of up to 8 patterns. In this
-          case, the entire pattern must be enclosed in braces, and each
-          sub-pattern must also be enclosed in braces; this eliminates
-          the need for designating a separator character, which is likely
-          to also be a legal filename character on some platform or
-          other, and therefore a source of confusion. You may include
-          spaces between the subpatterns but they are not necessary. The
-          following two commands are equivalent:
-
-  send /except:{{ck*.o} {ck*.c}} ck*.?
-  send /except:{{ck*.o}{ck*.c}} ck*.?
-
-          If a pattern is to include a literal brace character, precede
-          it with "\". Also note the apparent conflict of this list
-          format and the string-list format described in [354]Section
-          4.9.1. In case you want to include a wildcard string-list with
-          braces on its outer ends as an /EXCEPT: argument, do it like
-          this:
-
-  send /except:{{{ckuusr.c,ckuus2.c,ckuus6.c}}} ckuus*.c
-     _________________________________________________________________
-
-    1.5.5. Setting Preferences for Different Commands
-
-   Certain oft-used commands offer lots of switches because different
-   people have different requirements or preferences. For example, some
-   people want to be able to delete files without having to watch a list
-   of the deleted files scroll past, while others want to be prompted for
-   permission to delete each file. Different people prefer different
-   directory-listing styles. And so on. Such commands can be tailored
-   with the SET OPTIONS command:
-
-   SET OPTIONS command [ switch [ switch [ ... ] ] ]
-          Sets each switch as the default for the given command,
-          replacing the "factory default". Of course you can also
-          override any defaults established by the SET OPTIONS command by
-          including the relevant switches in the affected command any
-          time you issue it.
-
-   SHOW OPTIONS
-          Lists the commands that allows option-setting, and the options
-          currently in effect, if any, for each. Switches that have
-          synonyms are shown under their primary name; for example. /LOG
-          and /VERBOSE are shown as /LIST.
-
-   Commands for which options may be set include DIRECTORY, DELETE,
-   PURGE, and TYPE. Examples:
-
-  SET OPTIONS DIRECTORY /PAGE /NOBACKUP /HEADING /SORT:DATE /REVERSE
-  SET OPTIONS DELETE /LIST /NOHEADING /NOPAGE /NOASK /NODOTFILES
-  SET OPTIONS TYPE /PAGE
-
-   Not necessarily all of a command's switches can be set as options. For
-   example, file selection switches, since these would normally be
-   different for each command.
-
-   Put the desired SET OPTIONS commands in your C-Kermit customization
-   file for each command whose default switches you want to change every
-   time you run C-Kermit.
-     _________________________________________________________________
-
-  1.6. Dates and Times
-
-   Some commands and switches take date-time values, such as:
-
-  send /after:{8-Feb-2000 10:28:01}
-
-   Various date-time formats are acceptable. The rules for the date are:
-
-     * The year must have 4 digits.
-     * If the year comes first, the second field is the month.
-     * The day, month, and year may be separated by spaces, /, -, or
-       underscore.
-     * The month may be numeric (1 = January) or spelled out or
-       abbreviated in English.
-
-   If the date-time string contains any spaces, it must be enclosed in
-   braces. Examples of legal dates:
-
-                           Interpretation:
-  2000-Feb-8                8 February 2000
-  {2000 Feb 8}              8 February 2000
-  2000/Feb/8                8 February 2000
-  2000_Feb_8                8 February 2000
-  2000-2-8                  8 February 2000
-  2000-02-08                8 February 2000
-  8-Feb-2000                8 February 2000
-  08-Feb-2000               8 February 2000
-  12/25/2000                25 December 2000
-  25/12/2000                25 December 2000
-
-   The last two examples show that when the year comes last, and the
-   month is given numerically, the order of the day and month doesn't
-   matter as long as the day is 13 or greater (mm/dd/yyyy is commonly
-   used in the USA, whereas dd/mm/yyyy is the norm in Europe). However:
-
-  08/02/2000                Is ambiguous and therefore not accepted.
-
-   If a date is given, the time is optional and defaults to 00:00:00. If
-   the time is given with a date, it must follow the date, separated by
-   space, /, -, or underscore, and with hours, minutes, and seconds
-   separated by colon (:). Example:
-
-  2000-Feb-8 10:28:01       Represents 8 February 2000, 10:28:01am
-
-   If a date is not given, the current date is used and a time is
-   required.
-
-   Time format is hh:mm:ss or hh:mm or hh in 24-hour format, or followed
-   by "am" or "pm" (or "AM" or "PM") to indicate morning or afternoon.
-   Examples of times that are acceptable:
-
-                           Interpretation:
-  3:23:56                    3:23:56am
-  3:23:56am                  3:23:56am
-  3:23:56pm                  3:23:56pm = 15:23:56
- 15:23:56                    3:23:56pm = 15:23:56
-  3:23pm                     3:23:00pm = 15:23:00
-  3:23PM                     3:23:00pm = 15:23:00
-  3pm                        3:00:00pm = 15:00:00
-
-   Examples of legal date-times:
-
-  send /after:{8 Feb 2000 10:28:01}
-  send /after:8_Feb_2000_10:28:01
-  send /after:8-Feb-2000/10:28:01
-  send /after:2000/02/08/10:28:01
-  send /after:2000/02/08_10:28:01
-  send /after:2000/02/08_10:28:01am
-  send /after:2000/02/08_10:28:01pm
-  send /after:2000/02/08_10:28pm
-  send /after:2000/02/08_10pm
-  send /after:10:00:00pm
-  send /after:10:00pm
-  send /after:10pm
-  send /after:22
-
-   Finally, there is a special all-numeric format you can use:
-
-  yyyymmdd hh:mm:ss
-
-   For example:
-
-  20000208 10:28:01
-
-   This is Kermit's standard date-time format (based on ISO 8601), and is
-   accepted (among other formats) by any command or switch that requires
-   a date-time, and is output by any function whose result is a calendar
-   date-time.
-
-   There are no optional parts to this format and it must be exactly 17
-   characters long, punctuated as shown (except you can substitute
-   underscore for space in contexts where a single "word" is required).
-   The time is in 24-hour format (23:00:00 is 11:00pm). This is the
-   format returned by \fdate(filename), so you can also use constructions
-   like this:
-
-  send /after:\fdate(oofa.txt)
-
-   which means "all files newer than oofa.txt".
-
-   Besides explicit dates, you can also use the any of the following
-   shortcuts:
-
-   TODAY
-          Stands for the current date at 00:00:00.
-
-   TODAY 12:34:56
-          Stands for the current date at the given time.
-
-   YESTERDAY
-          Stands for yesterday's date at 00:00:00. A time may also be
-          given.
-
-   TOMORROW
-          Stands for tomorrow's date at 00:00:00. A time may also be
-          given.
-
-   + number { DAYS, WEEKS, MONTHS, YEARS } [ time ]
-          Is replaced by the future date indicated, relative to the
-          current date. If the time is omitted, 00:00:00 is used.
-          Examples: +3days, +2weeks, +1year, +37months.
-
-   - number { DAYS, WEEKS, MONTHS, YEARS } [ time ]
-
-          Is replaced by the past date indicated, relative to the current
-          date. If the time is omitted, 00:00:00 is used.
-
-   The time can be separated from the date shortcut by any of the same
-   separators that are allowed for explicit date-times: space, hyphen,
-   slash, period, or underscore. In switches and other space-delimited
-   fields, use non-spaces to separate date/time fields, or enclose the
-   date-time in braces, e.g.:
-
-  purge /before:-4days_12:00:00
-  purge /before:{- 4 days 12:00:00}
-
-   Of course you can also use variables:
-
-  define \%n 43
-  purge /before:-\%ndays_12:00:00
-
-   Shortcut names can be abbreviated to any length that still
-   distinguishes them from any other name that can appear in the same
-   context, e.g. "TOD" for today, "Y" for yesterday. Also, the special
-   abbreviation "wks" is accepted for WEEKS, and "yrs" for "YEARS".
-
-   (To see how to specify dates relative to a specific date, rather than
-   the current one, see the [355]\fmjd() function description below.)
-
-   You can check date formats with the DATE command. DATE by itself
-   prints the current date and time in standard format: yyyymmdd
-   hh:mm:ss. DATE followed by a date and/or time (including shortcuts)
-   converts it to standard format if it can understand it, otherwise it
-   prints an error message.
-
-   The following variables and functions deal with dates and times; any
-   function argument designated as "date-time" can be in any of the
-   formats described above.
-
-   \v(day)
-          The first three letters of the English word for the current day
-          of the week, e.g. "Wed".
-
-   \fday(date-time)
-          The first three letters of the English word for day of the week
-          of the given date. If a time is included, it is ignored.
-          Example: \fday(8 Feb 1988) = "Mon".
-
-   \v(nday)
-          The numeric day of the week: 0 = Sunday, 1 = Monday, ..., 6 =
-          Saturday.
-
-   \fnday(date-time)
-          The numeric day of the week for the given date. If a time is
-          included, it is ignored. Example: \fnday(8 Feb 1988) = "1".
-
-   \v(date)
-          The current date as dd mmm yyyy, e.g. "08 Feb 2000" (as in this
-          example, a leading zero is supplied for day-of-month less than
-          10).
-
-   \v(ndate)
-          The current date in numeric format: yyyymmdd, e.g. "20000208".
-
-   \v(time)
-          The current time as hh:mm:ss, e.g. "15:27:14".
-
-   \ftime(time)
-          The given free-format date and/or time (e.g. "3pm") returns the
-          time (without the date) converted to hh:mm:ss 24-hour format,
-          e.g. "15:00:00" (the date, if given, is ignored).
-
-   \v(ntime)
-          The current time as seconds since midnight, e.g. "55634".
-
-   \v(tftime)
-          The elapsed time of the most recent file-transfer operation in
-          seconds.
-
-   \v(intime)
-          The elapsed time for the most recent INPUT command to complete,
-          in milliseconds.
-
-   \fntime(time)
-          The given free-format date and/or time is converted to seconds
-          since midnight (the date, if given, is ignored). This function
-          replaces \ftod2secs(), which is now a synonym for \fntime().
-          Unlike \ftod2secs(), \fntime() allows a date to be included,
-          and it allows the time to be in free format (like 3pm), and it
-          allows the amount of time to be more than 24 hours. E.g.
-          \fntime(48:00:00) = 172800. Example of use:
-
-  set alarm \fntime(48:00:00) ; set alarm 48 hours from now.
-
-   \fn2time(seconds)
-          The given number of seconds is converted to hh:mm:ss format.
-
-   \fdate(filename)
-          Returns the modification date-time of the given file in
-          standard format: yyyymmdd hh:mm:ss.
-
-   \fcvtdate(date-time)
-          Converts a free-format date and/or time to Kermit standard
-          format: yyyymmdd hh:mm:ss. If no argument is given, returns the
-          current date-time in standard format. If a date is given but no
-          time, the converted date is returned without a time. If a time
-          is given with no date, the current date is supplied. Examples:
-
-  \fcvtdate(4 Jul 2000 2:21:17pm) = 20000704 14:21:17
-  \fcvtdate() = 20000704 14:21:17 (on 4 Jul 2000 at 2:21:17pm).
-  \fcvtd(4 Jul 2000) = 20000704
-  \fcvtd(6pm) = 20000704 18:00:00 (on 4 Jul 2000 at 6:00pm).
-
-   \fdayofyear(date-time)
-   \fdoy(date-time)
-          Converts a free-format date and/or time to yyyyddd, where ddd
-          is the 3-digit day of the year, and 1 January is Day 1. If a
-          time is included with the date, it is returned in standard
-          format. If a date is included but no time, the date is returned
-          without a time. If a time is given with no date, the time is
-          converted and the current date is supplied. If no argument is
-          given, the current date-time is returned. Synonym: \fdoy().
-          Examples:
-
-  \fddayofyear(4 Jul 2000 2:21:17pm) = 2000185 14:21:17
-  \fdoy() = 2000185 14:21:17 (on 4 Jul 2000 at 2:21:17pm).
-  \fdoy(4 Jul 2000) = 2000185
-  \fdoy(6pm) = 2000185 18:00:00 (on 4 Jul 2000 at 6:00pm).
-
-   Note: The yyyyddd day-of-year format is often erroneously referred to
-   as a Julian date. However, a true Julian date is a simple counting
-   number, the number of days since a certain fixed day in the past.
-   [356]See \fmjd() below.
-
-   \fdoy2date(date-time)
-          Converts a date or date-time in day-of-year format to a
-          standard format date. A yyyyddd-format date must be supplied;
-          time is optional. The given date is converted to yyyymmdd
-          format. If a time is given, it is converted to 24-hour format.
-          Examples:
-
-  \fdoy2date(2000185) = 20000704
-  \fdoy2(2000185 3pm) = 20000704 15:00:00
-
-   \fmjd(date-time)
-          Converts free-format date and/or time to a Modified Julian Date
-          (MJD), the number of days since 17 Nov 1858 00:00:00. If a time
-          is given, it is ignored. Examples:
-
-  \fmjd(4 Jul 2000) = 50998
-  \fmjd(17 Nov 1858) = 0
-  \fmjd(16 Nov 1858) = -1
-
-   \fmjd2date(mjd)
-          Converts an MJD (integer) to standard date format, yyyymmdd:
-
-  \fmjd2(50998) = 4 Jul 1998
-  \fmjd2(0) = 17 Nov 1858
-  \fmjd2(-1) = 16 Nov 1858
-  \fmjd2(-365) = 17 Nov 1857
-
-   MJDs are normal integers and, unlike DOYs, may be added, subtracted,
-   etc, with each other or with other integers, to obtain meaningful
-   results. For example, to find out the date 212 days ago:
-
-  echo \fmjd2date(\fmjd()-212)
-
-   Constructions such as this can be used in any command where a
-   date-time is required, e.g.:
-
-  send /after:\fmjd2date(\fmjd()-212)
-
-   to send all files that are not older than 212 days (this is equivalent
-   to "send /after:-212days").
-
-   MJDs also have other regularities not exhibited by other date formats.
-   For example, \fmodulus(\fmjd(any-date),7) gives the day of the week
-   for any date (where 4=Sun, 5=Mon, ..., 3=Sat). (However, it is easier
-   to use \fnday() for this purpose, and it gives the more conventional
-   result of 0=Sun, 1=Mon, ..., 6=Sat).
-
-   Note that if MJDs are to be compared, they must be compared
-   numerically (IF <, =, >) and not lexically (IF LLT, EQUAL, LGT),
-   whereas DOYs must be compared lexically if they include a time (which
-   contains ":" characters); however, if DOYs do not include a time, they
-   may also be compared numerically.
-
-   In any case, lexical comparison of DOYs always produces the
-   appropriate result, as does numeric comparison of MJDs.
-
-   The same comments apply to sorting. Also note that DOYs are fixed
-   length, but MJDs can vary in length. However, all MJDs between 3 April
-   1886 and 30 Aug 2132 are 5 decimal digits long. (MJDs become 6 digits
-   long on 31 Aug 2132, and 7 digits long on 13 Oct 4596).
-     _________________________________________________________________
-
-  1.7. Partial Completion of Keywords
-
-   Partial completion of keywords was added in C-Kermit 7.0. In prior
-   versions, if completion was attempted (by pressing the Esc or Tab key)
-   on a string that matched different keywords, you'd just get a beep.
-   Now Kermit completes up to the first character where the possibly
-   matching keywords differ and then beeps. For example:
-
-  C-Kermit> send /n<Tab>
-
-   which matches /NOT-BEFORE and /NOT-AFTER, now completes up to the
-   dash:
-
-  C-Kermit> send /n<Tab>ot-<Beep>
-
-   Partial completion works for filenames too (as it has for some years).
-     _________________________________________________________________
-
-  1.8. Command Recall
-
-   C-Kermit has had a command history buffer for some time, which could
-   be scrolled interactively using control characters or (in Kermit 95
-   only) arrow keys. Version 7.0 adds a REDO command that allows the most
-   recent command matching a given pattern to be re-executed:
-
-   { REDO, RR, ^ } [ pattern ]
-          Search the command history list for the most recent command
-          that matches the given pattern, and if one is found, execute it
-          again.
-
-   The pattern can be a simple string (like "send"), in which case the
-   last SEND command is re-executed. Or it can contain wildcard
-   characters "*" and/or "?", which match any string and any single
-   character, respectively (note that "?" must be preceded by backslash
-   to override its normal function of giving help), and in most C-Kermit
-   versions may also include [] character lists and {} string lists (see
-   [357]Section 4.9).
-
-   The match works by appending "*" to the end of the given pattern (if
-   you didn't put one there yourself). Thus "redo *oofa" becomes "redo
-   *oofa*" and therefore matches the most recent command that contains
-   "oofa" anywhere within the command. If you want to inhibit the
-   application of the trailing "*", e.g. to force matching a string at
-   the end of a command, enclose the pattern in braces:
-
-  redo {*oofa}
-
-   matches the most recent command that ends with "oofa".
-
-   REDO commands themselves are not entered into the command history
-   list. If no pattern is given, the previous (non-REDO) command is
-   re-executed. The REDOne command is reinserted at the end of the
-   command history buffer, so the command scrollback character (Ctrl-P,
-   Ctrl-B, or Uparrow) can retrieve it.
-
-   Examples:
-
-  C-Kermit> echo foo
-  foo
-  C-Kermit> show alarm
-  (no alarm set)
-  C-Kermit> echo blah
-  blah
-  C-Kermit> redo          ; Most recent command
-  blah
-  C-Kermit> redo s        ; Most recent command starting with "s"
-  (no alarm set)
-  C-Kermit> redo echo f   ; Most recent command starting with "echo f"
-  foo
-  C-Kermit> redo *foo     ; Most recent command that has "foo" in it
-  foo
-  C-Kermit> <Ctrl-P>      ; Scroll back
-  C-Kermit> echo foo      ; The REDOne command is there
-  C-Kermit> redo {*foo}   ; Most recent command that ends with "foo"
-  foo
-  C-Kermit>
-
-   Since REDO, REDIAL, and REDIRECT all start the same way, and RED is
-   the designated non-unique abbreviation for REDIAL, REDO must be
-   spelled out in full. For convenience, RR is included as an invisible
-   easy-to-type synonym for REDO. You can also use the "^" character for
-   this:
-
-  C-Kermit> ^             ; Most recent command
-  C-Kermit> ^ s           ; Most recent command starting with "s"
-  C-Kermit> ^s            ; Ditto (space not required after "^").
-  C-Kermit> ^*foo         ; Most recent command that has "foo" in it.
-  C-Kermit> ^{*foo}       ; Most recent command ends with "foo".
-
-   Unlike the manual command-history-scrolling keys, the REDO command can
-   be used in a script, but it's not recommended (since the command to be
-   REDOne might not be found, so if the REDO command fails, you can't
-   tell whether it was because REDO failed to find the requested command,
-   or because the command was found but it failed).
-     _________________________________________________________________
-
-  1.9. EXIT Messages
-
-   The EXIT and QUIT commands now accept an optional message to be
-   printed. This makes the syntax of EXIT and QUIT just like END and
-   STOP:
-
-   { EXIT, QUIT, END, STOP } [ status-code [ message ] ]
-
-   where status-code is a number (0 indicating success, nonzero
-   indicating failure). This is handy in scripts that are never supposed
-   to enter interactive mode:
-
-  dial 7654321
-  if fail exit 1 Can't make connection - try again later.
-
-   Previously this could only be done in two steps:
-
-  dial 7654321
-  xif fail { echo Can't make connection - try again later, exit 1 }
-
-   A status code must be included in order to specify a message. In the
-   case of EXIT and QUIT, the default status code is contained in the
-   variable \v(exitstatus), and is set automatically by various events
-   (file transfer failures, etc; it can also be set explicitly with the
-   SET EXIT STATUS command). If you want to give an EXIT or QUIT command
-   with a message, but without changing the exit status from what it
-   normally would have been, use the \v(exitstatus) variable, e.g.:
-
-   exit \v(existatus) Goodbye from \v(cmdfile).
-
-   The EXIT status is returned to the system shell or whatever other
-   process invoked C-Kermit, e.g. in UNIX:
-
-  C-Kermit> exit 97 bye bye
-  bye bye
-  $ echo $?
-  97
-  $
-     _________________________________________________________________
-
-  1.10. Managing Keyboard Interruptions
-
-   When C-Kermit is in command or file-transfer mode (as opposed to
-   CONNECT mode), it can be interrupted with Ctrl-C. Version 7.0 adds the
-   ability to disarm the Ctrl-C interrupt:
-
-   SET COMMAND INTERRUPT { ON, OFF }
-          COMMAND INTERRUPT is ON by default, meaning the Ctrl-C can be
-          used to interrupt a command or a file transfer in progress. Use
-          OFF to disable these interruptions, and use it with great
-          caution for obvious reasons.
-
-   SET TRANSFER INTERRUPT { ON, OFF }
-          This can be used to disable keyboard interruption of file
-          transfer when C-Kermit is in local mode, or to re-enable it
-          after it has been disabled. This applies to the X, Z, E, and
-          similar keys as well as to the system interrupt character,
-          usually Ctrl-C. This is distinct from SET TRANSFER
-          CANCELLATION, which tells whether packet mode can be exited by
-          sending a special sequence of characters.
-
-   Several other commands can be interrupted by pressing any key while
-   they are active. Version 7.0 adds the ability to disable this form of
-   interruption also:
-
-   SET INPUT CANCELLATION { ON, OFF }
-          Whether an INPUT command in progress can be interrupted by
-          pressing a key. Normally ON. Setting INPUT CANCELLATION OFF
-          makes INPUT commands uninterruptible except by Ctrl-C (unless
-          COMMAND INTERRUPTION is also OFF).
-
-   SET SLEEP CANCELLATION { ON, OFF }
-          Whether a SLEEP, PAUSE, or WAIT command in progress can be
-          interrupted by pressing a key. Normally ON. Setting SLEEP
-          CANCELLATION OFF makes these commands uninterruptible except by
-          Ctrl-C (unless COMMAND INTERRUPTION is also OFF). Synonyms: SET
-          PAUSE CANCELLATION, SET WAIT CANCELLATION.
-
-   So to make certain a script is not interruptible by the user, include
-   these commands:
-
-  SET TRANSFER INTERRUPT OFF
-  SET SLEEP CANCELLATION OFF
-  SET INPUT CANCELLATION OFF
-  SET COMMAND INTERRUPTION OFF
-
-   Make sure to turn them back on afterwards if interruption is to be
-   re-enabled.
-
-   When a PAUSE, SLEEP, WAIT, or INPUT command is interrupted from the
-   keyboard, the new variable \v(kbchar) contains a copy of the (first)
-   character that was typed and caused the interruption, provided it was
-   not the command interrupt character (usually Ctrl-C). If these
-   commands complete successfully or time out without a keyboard
-   interruption, the \v(kbchar) variable is empty.
-
-   The \v(kbchar) variable (like any other variable) can be tested with:
-
-  if defined \v(kbchar) command
-
-   The command is executed if the variable is not empty.
-
-   The \v(kbchar) variable can be reset with WAIT 0 (PAUSE 0, SLEEP 0,
-   etc).
-     _________________________________________________________________
-
-  1.11. Taming The Wild Backslash -- Part Deux
-
-   [358]Using C-Kermit, 2nd Edition, contains a brief section, "Taming
-   the Wild Backslash", on page 48, which subsequent experience has shown
-   to be inadequate for Kermit users intent on writing scripts that deal
-   with Windows, DOS, and OS/2 filenames, in which backslash (\) is used
-   as the directory separator. This section fills in the blanks.
-
-    1.11.1. Background
-
-   The Kermit command language shares a certain unavoidable but annoying
-   characteristic with most other command languages that are capable of
-   string replacement, namely the necessity to "quote" certain characters
-   when you want them to be taken literally. This is a consequence of the
-   facts that:
-
-    1. One or more characters must be set aside to denote replacement,
-       rather than acting as literal text.
-    2. We have only 96 printable characters to work with in ASCII, which
-       is still the only universally portable character set.
-    3. There is no single printable character that is unused everywhere.
-    4. Variables are not restricted to certain contexts, as they are in
-       formal programming languages like C and Fortran, but can appear
-       anywhere at all within a command, and therefore require special
-       syntax.
-
-   Thus there can be conflicts. To illustrate, the standard UNIX shell
-   uses dollar sign ($) to introduce variables. So the shell command:
-
-  echo $TERM
-
-   displays the value of the TERM variable, e.g. vt320. But suppose you
-   want to display a real dollar sign:
-
-  echo The price is $10.20
-
-   This causes the shell to evaluate the variable "$1", which might or
-   might not exist, and substitute its value, e.g.:
-
-  The price is 0.20
-
-   (in this case the $1 variable had no value.) This is probably not what
-   you wanted. To force the dollar sign to be taken literally, you must
-   apply a "quoting rule", such as "precede a character by backslash (\)
-   to force the shell to take the character literally":
-
-  echo The price is \$10.20
-  The price is $10.20
-
-   But now suppose you want the backslash AND the dollar sign to be taken
-   literally:
-
-  echo The price is \\$10.20
-
-   This doesn't work, since the first backslash quotes the second one,
-   thereby leaving the dollar sign unquoted again:
-
-  The price is \0.20
-
-   Quoting the dollar sign requires addition of a third backslash:
-
-  echo The price is \\\$10.20
-  The price is \$10.20
-
-   The first backslash quotes the second one, and the third backslash
-   quotes the dollar sign.
-
-   Every command language -- all UNIX shells, VMS DCL, DOS Batch, AOS/VS
-   CLI, etc etc -- has similar rules. UNIX shell rules are probably the
-   most complicated, since many printable characters -- not just one --
-   are special there: dollar sign, single quote, double quote, backslash,
-   asterisk, accent grave, number sign, ampersand, question mark,
-   parentheses, brackets, braces, etc -- practically every
-   non-alphanumeric character needs some form of quoting if it is to be
-   taken literally. And to add to the confusion, the UNIX shell offers
-   many forms of quoting, and many alternative UNIX shells are available,
-   each using slightly different syntax.
-     _________________________________________________________________
-
-    1.11.2. Kermit's Quoting Rules
-
-   Kermit's basic quoting rules are simple by comparison (there are, of
-   course, additional syntax requirements for macro definitions, command
-   blocks, function calls, etc, but they are not relevant here).
-
-   The following characters are special in Kermit commands:
-
-   Backslash (\)
-          Introduces a variable, or the numeric representation of a
-          special character, or a function, or other item for
-          substitution. If the backslash is followed by a digit or by any
-          of the following characters:
-
-  x, o, d, m, s, f, v, $, %, &, :, {
-
-          this indicates a special substitution item; otherwise the
-          following character is to be taken literally (exceptions: \ at
-          end of line is taken literally; \n, \b, and \n are special
-          items in the OUTPUT command only).
-
-   Semicolon (;)
-          (Only when at the beginning of a line or preceded by at least
-          one space or tab) Introduces a comment.
-
-   Number sign (#)
-          (Only when at the beginning of a line or preceded by at least
-          one space or tab) Just like semicolon; introduces a comment.
-
-   Question mark (?)
-          (Only at the command prompt - not in command files or macros)
-          Requests context-sensitive help.
-
-   To force Kermit to take any of these characters literally, simply
-   precede it by a backslash (\).
-
-   Sounds easy! And it is, except when backslash also has a special
-   meaning to the underlying operating system, as it does in DOS,
-   Windows, and OS/2, where it serves as the directory separator in
-   filenames such as:
-
-  D:\K95\KEYMAPS\READ.ME
-
-   Using our rule, we would need to refer to this file in Kermit commands
-   as follows:
-
-  D:\\K95\\KEYMAPS\\READ.ME
-
-   But this would not be obvious to new users of Kermit software on DOS,
-   Windows, or OS/2, and it would be annoying to seasoned ones. Thus
-   MS-DOS Kermit and Kermit 95 go to rather extreme lengths to allow the
-   more natural notation, as in:
-
-  send d:\k95\keymaps\read.me
-
-   The reason this is tricky is that we also need to allow for variables
-   and other expressions introduced by backslash in the same command. For
-   example, suppose \%a is a variable whose value is "oofa" (without the
-   quotes). What does the following command do?
-
-  send d:\%a
-
-   Does it send the file named "oofa" in the current directory of the D:
-   disk, or does it send a file named "%a" in the root directory of the
-   D: disk? This is the kind of trouble we get into when we attempt to
-   bend the rules in the interest of user friendliness. (The answer is:
-   if the variable \%a has definition that is the name of an existing
-   file, that file is sent; if a file d:\%a exists, it is sent; otherwise
-   if both conditions are true, the variable takes precedence, and the
-   literal filename can be forced by quoting: \\%a.)
-
-   In Kermit 95 (but not MS-DOS Kermit), we also bend the rules another
-   way by allowing you to use forward slash (/) rather than backslash (\)
-   as the directory separator:
-
-  send d:/k95/keymaps/read.me
-
-   This looks more natural to UNIX users, and in fact is perfectly
-   acceptable to the Windows 95/98/NT and OS/2 operating systems on the
-   API level. BUT (there is always a "but") the Microsoft shell,
-   COMMAND.COM, for Windows 95/98 and NT does not allow this notation,
-   and therefore it can not be used in any Kermit command -- such as RUN
-   -- that invokes the Windows command shell AND your command shell is
-   COMMAND.COM or any other shell that does not allow forward slash as
-   directory separator (some alternative shells do allow this).
-
-     NOTE: There exists a wide variety of alternative shells from third
-     parties that do not have this restriction. If you are using a shell
-     that accepts forward slash as a directory separator, you can stop
-     reading right now -- UNLESS (there is always an "unless") you want
-     your scripts to be portable to systems that have other shells. Also
-     note that some Windows shells might actually REQUIRE forward
-     slashes (instead of backslashes) as directory separators; we do not
-     treat this situation below, but the treatment is obvious -- use
-     slash rather backslash as the directory separator.
-     _________________________________________________________________
-
-    1.11.3. Passing DOS Filenames from Kermit to Shell Commands
-
-   The following Kermit commands invoke the system command shell:
-
-  RUN (and its synonyms ! and @)
-  REDIRECT
-  PIPE
-
-   Each of these commands takes a shell command as an operand. These
-   shell commands are not, and can not be, parsed by Kermit since Kermit
-   does not know the syntax of shell commands, and so can't tell the
-   difference between a keyword, a filename, a variable, a switch, or
-   other item. Therefore the rules can not be bent since Kermit doesn't
-   know where or how to bend them. To illustrate (using the regular
-   Windows shell):
-
-  run c:\\windows\\command\\chkdsk.exe
-
-   works OK, but:
-
-  run c:/windows/command/chkdsk.exe
-
-   is not accepted by COMMAND.COM. But:
-
-  run c:\windows\command\chkdsk.exe
-
-   results in Kermit applying its quoting rules before sending the text
-   to the shell. Since "w" and "c" are not in the list of backslash-item
-   codes, the backslash means "take the following character literally".
-   Thus, by the time this filename gets to the Windows shell, it has
-   become:
-
-  c:windowscommandchkdsk.exe
-
-   which is probably not what you wanted. (If "w" and "c" were in the
-   list, the results could be even stranger.) Even more confusing is the
-   case where a directory or filename starts with one or more digits:
-
-  run c:\123\lotus.exe
-
-   in which "\123" is the Kermit notation for ASCII character 123, which
-   happens to be left brace ({), resulting in "c:{lotus.exe".
-
-   So when passing filenames to a Windows shell, always use double
-   backslashes as directory separators, to ensure that the shell gets
-   single backslashes:
-
-  run c:\\windows\\command\\chkdsk.exe
-  run c:\\123\\lotus.exe
-
-   Similar problems might occur with the built-in EDIT, BROWSE, and FTP
-   commands. These commands result in Kermit building a shell command
-   internally to invoke the associated helper program; the form of this
-   command might conflict with the form demanded by certain alternative
-   shells.
-     _________________________________________________________________
-
-    1.11.4. Using Variables to Hold DOS Filenames
-
-   Now to the next level. Suppose you want to write a script in which
-   filenames are parameters, and therefore are stored in variables.
-   Example:
-
-  define \%f c:\windows\command\chkdsk.exe
-  ...
-  run \%f
-
-   Obviously this won't work for the reasons just noted; the RUN command
-   requires directory separators be coded as double backslashes:
-
-  define \%f c:\\windows\\command\\chkdsk.exe
-  ...
-  run \%f
-
-   This will work; no surprises here. However, if you had used ASSIGN
-   rather than DEFINE, you might have been surprised after all; review
-   pages 348-349 of [359]Using C-Kermit (2nd Ed) for the difference
-   between DEFINE and ASSIGN.
-
-   We have said that any Kermit 95 or MS-DOS Kermit command that parses
-   filenames itself -- SEND, for example -- does not require double
-   backslashes since it knows it is parsing a filename. So since the
-   following works:
-
-  send c:\windows\command\chkdsk.exe
-
-   Should the following also work?
-
-  define \%f c:\windows\command\chkdsk.exe
-  ...
-  send \%f
-
-   Answer: No. Why? Because \%f is evaluated "recursively", to allow for
-   the possibility that its definition contains further variable
-   references. This is true of all "backslash-percent-letter" (or -digit)
-   variables, and also for array references. So \%f becomes
-   c:\windows\command\chkdsk.exe, which becomes
-   c:windowscommandchkdsk.exe.
-
-   The trick here is to use the "other" kind of variable, that is
-   evaluated only "one level deep" rather than recursively:
-
-  define filename c:\windows\command\chkdsk.exe
-  ...
-  send \m(filename)
-
-   Similarly if you want to prompt the user for a filename:
-
-  ask filename { Please type a filename: }
-   Please type a filename: c:\windows\command\chkdsk.exe
-  send \m(filename)
-     _________________________________________________________________
-
-    1.11.5. Passing DOS Filenames as Parameters to Macros
-
-   Suppose you want to pass a DOS filename containing backslashes as a
-   parameter to a Kermit macro. This raises two issues:
-
-    1. Parameters to macros are "just text" and so are fully evaluated
-       before they are passed to the macro.
-    2. Once inside the macro, the formal parameters \%1, \%2, ... \%9 are
-       the type of variable that is evaluated recursively.
-
-   Thus a DOS filename is ruined once in the act of parsing the macro
-   invocation, and again when referring to it from within the macro. To
-   illustrate, suppose "test" is a macro. Then in the invocation:
-
-  test c:\mydir\blah.txt
-
-   "c:mydirblah.txt" is assigned to \%1. However, if we double the
-   backslashes:
-
-  test c:\\mydir\\blah.txt
-
-   "c:\mydir\blah.txt" is assigned to \%1. But then when you refer to \%1
-   in the macro, it is evaluated recursively, resulting in
-   "c:mydirblah.txt". To illustrate:
-
-  define test echo \%1
-  test c:\mydir\blah.txt
-  c:mydirblah.txt
-  test c:\\mydir\\blah.txt
-  c:mydirblah.txt
-  test c:\\\\mydir\\\\blah.txt
-  c:\mydir\blah.txt
-
-   Let's address each part of the problem separately. First, inside the
-   macro. You can use the \fcontents() function to force a
-   backslash-percent variable (such as a macro argument) to be evaluated
-   one level deep instead of recursively, for example:
-
-  define test echo { The filename is "\fcontents(\%1)"}
-
-  test c:\mydir\blah.txt               ; We don't expect this to work
-   The filename is "c:mydirblah.txt"   ; and it doesn't.
-  test c:\\mydir\\blah.txt             ; But this does...
-   The filename is "c:\mydir\blah.txt"
-
-   Thus if the filename arrives inside the macro with single backslashes,
-   the backslashes are preserved if you always refer to the parameter
-   through the \fcontents() function.
-
-   Now how to ensure that backslashes are not stripped or misinterpreted
-   when passing a filename to a macro? This brings us back to what we
-   learned in earlier sections:
-
-    1. If it is a literal filename, either double the backslashes, or (if
-       the filename is to be used only within Kermit itself and not
-       passed to a DOS shell, or it is to be passed to an alternative
-       shell that accepts forward slash as a directory separator), use
-       forward slash instead of backslash as the directory separator.
-    2. If it is a variable that contains a filename, make sure you use a
-       macro-style variable name, rather than a
-       backslash-percent-character name.
-
-   Examples:
-
-  define test echo \fcontents(\%1)
-  define filename c:\mydir\blah.txt
-
-  test c:\\mydir\\blah.txt  ; Literal filename with double backslashes
-  c:\mydir\blah.txt
-
-  test c:/mydir/blah.txt    ; Literal filename with forward slashes
-  c:/mydir/blah.txt
-
-  test \m(filename)         ; Variable
-  c:\mydir\blah.txt
-
-   But what if you don't like these rules and you still want to pass a
-   literal filename containing single backslashes to a macro? This is
-   possible too, but a bit tricky: turn command quoting off before
-   invoking the macro, and then turn it back on inside the macro.
-   Example:
-
-  define test set command quoting on, echo \fcontents(\%1)
-
-  set command quoting off
-  test c:\mydir\blah.txt
-  c:\mydir\blah.txt
-
-   Upon return from the macro, command quoting is back on (since the
-   macro turned it on).
-
-   Obviously this trick can not be used if the filename is stored in a
-   variable, since it prevents the variable from being evaluated.
-     _________________________________________________________________
-
-    1.11.6. Passing DOS File Names from Macro Parameters to the DOS Shell
-
-   Now suppose you need to pass a DOS filename to a macro, and the macro
-   needs to pass it, in turn, to the Windows shell via (say) Kermit's RUN
-   command. This works too:
-
-  define xrun run \fcontents(\%1)
-  xrun c:\\windows\\command\\chkdsk.exe
-
-   (or you can use the SET COMMAND QUOTING OFF / ON technique described
-   above to avoid the double backslashes.) But..
-
-  xrun c:/windows/command/chkdsk.exe
-
-   does not work if the Windows shell does not recognize "/" as a
-   directory separator. If there is a chance that a filename might be
-   passed to the macro in this form, the macro will need to convert it to
-   a form acceptable to the shell:
-
-  define xrun run \freplace(\fcontents(\%1),/,\\)
-
-   Here we replace all occurrences (if any) of "/" in the argument with
-   "\" prior to issuing the RUN command. Of course, in order to specify
-   "\" as a literal character in the \freplace() argument list, we have
-   to double it.
-     _________________________________________________________________
-
-    1.11.7. Passing DOS Filenames to Kermit from the Shell
-
-   As noted in the manual, the \&@[] array contains Kermit's command-line
-   arguments. Suppose one of these arguments, say \&@[3], is a DOS
-   filename such as C:\FOO\BAR\BAZ\OOFA.TXT. (Note: In C-Kermit 7.0 and
-   K95 1.1.18 and later, command-line arguments after "=" or "--" are
-   also available in the top-level \%1..9 variables; see [360]Section
-   7.5.)
-
-   Of course you can eliminate any problems by using forward slashes
-   rather than backslashes in the filename, but sometimes this is not
-   possible, as when the Kermit command line is being generated by
-   another program than can only generate "native" format DOS filenames.
-
-   As noted in the manual, "\%x" variables and \&x[] arrays are always
-   evaluated "all the way" (recursively). If the contents of one of these
-   variables contains backslashes, this causes another level of
-   evaluation.
-
-   There is another kind of variable, which is evaluated only "one level
-   deep". You can use this to prevent interpretation of the backslashes
-   in the filenames. Example:
-
-  assign filename \fcontents(\&@[3])  ; Transfer contents
-  ...
-  send \m(filename)
-
-   Or, more simply:
-
-  send \fcontents(\&@[3])
-     _________________________________________________________________
-
-  1.12. Debugging
-
-   The debug log is produced when you give a "log debug" command. This is
-   normally done at the request of the Kermit help desk, for forwarding
-   to the Kermit developers for analysis as a last resort in
-   troubleshooting problems. (Last resort because it can grow quite huge
-   in a very short time.) In cases where timing information is critical
-   to understanding a problem, you can tell C-Kermit to put a timestamp
-   on each debug log line by giving the command:
-
-  SET DEBUG TIMESTAMP ON
-
-   At any time before or after activating the debug log (SET DEBUG
-   TIMESTAMP OFF turns off timestamping). Timestamps can be turned off
-   and on as desired while logging. Obviously, they increase the size and
-   growth rate of the log significantly, and so should be used sparingly.
-   Timestamps are of the form hh:mm:ss.xxx, where .xxx is thousands of a
-   second (but is included only on platforms that include this feature).
-     _________________________________________________________________
-
-  1.13. Logs
-
-   In UNIX C-Kermit and in K-95, you can now direct any log to a pipe.
-   This not only lets you send your logs to places other than disk files,
-   but also lets you customize them to any desired degree.
-
-   LOG { DEBUG, PACKETS, SESSION, TRANSACTION, CONNECTION } { file, pipe
-          } ...
-          A "pipe" is the name of a command, preceded by a vertical bar.
-          If the pipe contains any spaces, it must be enclosed in braces.
-
-   Here are some examples for UNIX (always remember the importance of
-   getting the UNIX shell quoting rules right):
-
-   LOG TRANSACTIONS |lpr
-          This sends the transaction log to the default UNIX printer,
-          rather than to a file (use "lp" rather than "lpr" if
-          necessary).
-
-   LOG TRANSACTIONS {| myfilter > t.log}
-          For those who don't like the format of the transaction log, or
-          want to extract certain information from it; write your own
-          output filter.
-
-   LOG SESSION {| lpr -Plaserwriter}
-          This sends the session log to a specific UNIX printer, rather
-          than to a file. Note the braces around the pipeline. These are
-          required because it contains spaces.
-
-   LOG DEBUG {| tail -100 > debug.log}
-          This causes the debug log file to contain only the final 100
-          lines. Suppose C-Kermit crashes under some unpredictable
-          circumstances, and you need a debug log to catch it in the act.
-          But the debug log can grow to huge proportions very quickly,
-          possibly filling up the disk. Piping the debug log through
-          "tail" results in keeping only the last 100 lines (or other
-          number of your choice).
-
-   LOG DEBUG {| grep "^TELNET" > debug.log}
-          This one shows how to log only Telnet negotiations. Piping the
-          debug log through grep or egrep lets you log only specific
-          information, rather than everything. "man grep" for further
-          info.
-
-   LOG DEBUG {| gzip -c > debug.log.gz}
-          Creates a full debug log, but compressed by gzip to save space.
-
-   LOG PACKETS {| tr "\\01" "X" | cut -c9- > packet.log}
-          This one writes the regular packet log, but translates the
-          Ctrl-A that starts each packet to the letter "X" and removes
-          the s-nn-nn- notation from the beginning of each line. Note the
-          double backslash (normal Kermit quoting rules). "man tr" and
-          "man cut" for further info.
-
-   See [361]Section 2.12 for information about the new connection log.
-     _________________________________________________________________
-
-  1.14. Automatic File-Transfer Packet Recognition at the Command Prompt
-
-   Beginning in version 7.0, C-Kermit can recognize Kermit (and in some
-   cases also Zmodem) file-transfer packets while at its command prompt.
-   This is convenient (for example), if you escaped back from a remote
-   Kermit program and told the local Kermit program to send a file, but
-   forgot to tell the remote Kermit program to receive it (and the local
-   Kermit did not have the "send a Kermit receive command" feature
-   available). This feature is controlled by the following command:
-
-   SET COMMAND AUTODOWNLOAD { ON, OFF }
-          When ON, which is the default, the command parser recognizes
-          Kermit packets when Kermit is in remote mode. An S packet makes
-          it go into receive mode, an I packet makes it go into server
-          mode. When OFF, packet recognition is disabled and the behavior
-          when a packet is received at the command prompt is as it was in
-          C-Kermit 6.1 and earlier (namely to print an error message).
-
-   COMMAND AUTODOWNLOAD is the command-mode equivalent of TERMINAL
-   AUTODOWNLOAD, which is effective during CONNECT mode.
-     _________________________________________________________________
-
-  1.15. The TYPE Command
-
-   The TYPE command now accepts a selection of optional switches
-   ([362]Section 1.5), and also sets several variables.
-
-   Syntax: TYPE [ switches... ] filename
-
-   Variables:
-
-   \v(ty_ln)
-          Line number of current line (during TYPE command; see /PREFIX)
-
-   \v(ty_lc)
-          Line count of file most recently TYPEd.
-
-   \v(ty_mc)
-          Match count of file most recently TYPEd (see /MATCH).
-
-   Switches:
-
-   /PAGE
-          If /PAGE is included, Kermit pauses at the end of each
-          screenful and issues a "more?" prompt. You may press the space
-          bar to view the next page (screenful), or press "q" or "n" to
-          return to the C-Kermit prompt. If this switch is given, it
-          overrides the COMMAND MORE-PROMPTING setting for this command
-          only. If it is not given, paging is according to COMMAND
-          MORE-PROMPTING.
-
-   /NOPAGE
-          Do not pause at the end of each screenful; show the whole file
-          (or all selected lines) at once. If this switch is given, it
-          overrides the COMMAND MORE-PROMPTING setting for this command
-          only. If it is not given, paging is according to COMMAND
-          MORE-PROMPTING.
-
-   /HEAD[:n]
-          Only show the first n lines of the file (where n is a number).
-          If n is omitted, 10 is used.
-
-   /TAIL[:n]
-          Only show the last n lines of the file (where n is a number).
-          If nis omitted, 10 is used. Note: /HEAD and /TAIL can't be
-          combined; if you give both switches, only the most recent one
-          is used.
-
-   /MATCH:pattern
-          Only type lines from the file that match the given pattern (see
-          [363]Section 4.9.1 for pattern notation). UNIX users familiar
-          with grep should note a significant difference: there is no
-          implied "*" at the beginning and end of the pattern. Thus:
-
-  TYPE /MATCH:foo    Lists lines whose entire contents are "foo".
-  TYPE /MATCH:foo*   Lists lines that start with "foo".
-  TYPE /MATCH:*foo   Lists lines that end with "foo".
-  TYPE /MATCH:*foo*  Lists lines that have "foo" anywhere in them.
-
-          /HEAD and /TAIL apply after /MATCH, so "type /tail:20
-          /match:x*" shows the last 20 lines in the file that start with
-          "x".
-
-   /PREFIX:string
-          Print the given string at the beginning of each line. The
-          string may be a constant, a variable, or a quoted variable. If
-          it's an unquoted variable, its value at the time the TYPE
-          command was given is used as a constant. If it is a quoted
-          variable, it is re-evaluated for each line; a useful variable
-          for this context is \v(ty_ln) (the line number of the current
-          line being typed). If the prefix is to include spaces, it must
-          be enclosed in braces. Examples:
-
-        type /prefix:{oofa.txt: } /match:*thing* oofa.txt
-                Prints all lines in oofa.txt that contain "thing" with
-                the filename itself as the prefix (similar to UNIX grep).
-
-        type /prefix:{\v(time). } oofa.txt
-                Prefixes each line of oofa.txt with the time at which the
-                TYPE command was given (one backslash)
-
-        type /prefix:{\\v(time). } oofa.txt
-                Prefixes each line of oofa.txt with the time at which
-                that line is being typed (two backslashes).
-
-        type /prefix:{\\v(ty_ln). } oofa.txt
-                Prefixes each line of oofa.txt with its line number.
-
-        type /prefix:{\\flpad(\\v(ty_ln),4). } oofa.txt
-                Same as the previous example, except the line number is
-                right-adjusted in a 4-column field.
-
-   /WIDTH[:n]
-          Truncates each line at column n (which must be a number) prior
-          to printing it. This option can be used for long lines when you
-          don't want them to wrap. If nis omitted, your current screen
-          width is used.
-
-   /COUNT
-          Counts lines and -- if /MATCH was included, matches -- but does
-          not print any lines from the file. The line and match count is
-          shown at the end, and the variables \v(ty_lc) and \v(ty_lm) are
-          set accordingly.
-
-   SET OPTIONS TYPE { /PAGE, /NOPAGE, /WIDTH:n }
-          Sets the paging default for TYPE commands, which can be
-          overridden in any particular TYPE command by including the
-          desired switch.
-
-   If a TYPE command is given with no switch, and no SET OPTIONS TYPE
-   selection is in effect, paging is according to your COMMAND
-   MORE-PROMPTING setting (SHOW COMMAND).
-     _________________________________________________________________
-
-  1.16. The RESET Command
-
-   The RESET command, added in 7.0, closes all open files and logs, but
-   does not affect the open connection (if any).
-     _________________________________________________________________
-
-  1.17. The COPY and RENAME Commands
-
-   As of C-Kermit 7.0, in the UNIX version only, the COPY and RENAME
-   commands are built in and do not call the underlying platform's COPY
-   or RENAME command. This allows them to work in "NOPUSH" versions and
-   other circumstances where it can't access system commands, and it
-   allows file copying and renaming to be done portably in scripts. The
-   characteristics of the built-in COPY or RENAME include:
-     * It fails if the source file is a directory or is wild or lacks
-       read access.
-     * It fails if the source file is the destination file.
-     * It allows the destination file to be a directory, in which case
-       the source file is copied (or renamed) into it with the same name.
-     * It overwrites an existing destination file if its permission
-       allows.
-     * It sets the new file's permission according to umask but also
-       carries forward the source file's execute permission bits if the
-       destination file did not already exist.
-     * It fails if interrupted by Ctrl-C.
-     * Upon error, it prints an appropriate message.
-     * It returns standardized error codes that can be tested by IF
-       SUCCESS / FAIL.
-
-   These commands now also accept the following switches:
-
-  /LIST (/LOG, /VERBOSE)    = Print "file1 => file2 (OK)" (or error message).
-  /NOLIST (/NOLOG, /QUIET)  = Don't print anything (except error messages).
-
-   /NOLIST is the default.
-
-   The same built-in code is used by the UNIX C-Kermit server to execute
-   REMOTE COPY commands (except in this case no switches are available).
-
-   The COPY command also accepts the following additional switches. When
-   any of these are given (and they can be used in any combination except
-   /SWAP and /APPEND), some of the checks listed above are relaxed, and
-   thus it might be possible to get into trouble in certain cases, e.g.
-   when the source and target files are the same file:
-
-  /APPEND                   = Append source file to destination file.
-  /SWAP-BYTES               = Swap bytes (see [364]Section 6.6.5).
-  /FROMB64                  = Decode the source file from Base64 encoding.
-  /TOB64                    = Encode the target file in Base64.
-
-   Base64 is the encoding commonly used for enclosures in Internet email.
-     _________________________________________________________________
-
-  1.18. The MANUAL Command
-
-   The MANUAL command can be used to access the appropriate Kermit manual
-   or other manual. The general syntax is:
-
-   MANUAL [ string ]
-          If the string is omitted, C-Kermit asks the underlying system
-          to access the C-Kermit manual using whatever method is
-          appropriate for the system.
-
-   The specific action depends on the system. In UNIX, a "man" command is
-   issued; "kermit" is the default argument but other manual topics may
-   be specified. If the "man" command allows index or string searching,
-   the appropriate syntax may be included.
-
-   In Kermit 95, the MANUAL command brings up the HTML online K95 manual.
-
-   In VMS and elsewhere, "man" is simply translated to "help", with a
-   default argument of "kermit"; other and/or additional arguments may be
-   included according to the definition of the system's "help" command.
-
-   Correct operation of the "man" command in C-Kermit depends on the
-   appropriate man page or help topic having been installed in the right
-   place with the right permissions and format.
-     _________________________________________________________________
-
-  1.19. String and Filename Matching Patterns
-
-   A pattern is a string that includes special notation for matching
-   classes or sequences of characters. C-Kermit 7.0 / K95 1.1.19 supports
-   patterns in several places:
-
-     * Filenames ([365]Section 4.9)
-     * SWITCH case labels ([366]Section 7.18)
-     * The new IF MATCH statement ([367]Section 7.4)
-     * TYPE /MATCH ([368]Section 1.15)
-     * SET FILE TEXT-PATTERNS and BINARY-PATTERNS ([369]Section 4.3)
-     * The \fsearch() and \farraylook() functions ([370]Sections 7.3 and
-       [371]7.10.7)
-     * The \fpattern() function used with [M,RE]INPUT ([372]Section 7.1)
-
-   Patterns are also called wildcards, especially when used for filename
-   matching. C-Kermit's pattern syntax is explained in [373]Section
-   4.9.1, and also by the HELP WILDCARDS command.
-     _________________________________________________________________
-
-  1.20. Multiple Commands on One Line
-
-   As of C-Kermit 7.0, commands can be grouped together on one line by
-   separating the commands with commas and enclosing the list in braces.
-   For example:
-
-  C-Kermit> { echo One, echo Two, echo Three }
-  C-Kermit> do { echo One, echo Two, echo Three }
-
-   Command lists can be nested:
-
-  [ do ] { echo One, echo Two, if true { echo A, echo B}, echo Three }
-
-   and the END command works as it does in macros:
-
-  [ do ] { echo One, echo Two, if true end, echo Three }
-
-   The "one line" stricture is, of course, pliant to line-continuation
-   conventions, namely that lines ending in hyphen (-) or left brace ({)
-   are to be continued. Thus the first example can also be rendered:
-
-  [ do ] {
-      echo One
-      echo Two
-      echo Three
-  }
-
-   (the "do" is optional).
-     _________________________________________________________________
-
-  1.21. What Do I Have?
-
-   C-Kermit can be built for hundreds of different platforms with
-   practically countless configuration options. Certain commands might
-   not be available in certain configurations, etc. Even on the same
-   platform, different builds are possible: "maximum functionality",
-   "minimum size", "maximum performance", and so on. You can find out a
-   lot about the configuration of your C-Kermit program with the SHOW
-   FEATURES command. Of course, a lot of what it says, especially in the
-   bottom part, might seem like gibberish, but can be deciphered with a
-   Rosetta Stone (such as the C-Kermit source or the [374]ckccfg.txt
-   file). In any case, the output from SHOW FEATURES might easily explain
-   why some expected feature is missing, or some buffer is smaller than
-   expected. Here's a sample of the bottom section for the SunOS version:
-
-C-Kermit 7.0.196, 1 Jan 2000
-
-Major optional features included:
- Network support (type SHOW NET for further info)
- Telnet Kermit Option
- Hardware flow control
- External XYZMODEM protocol support
- Latin-1 (West European) character-set translation
- Latin-2 (East European) character-set translation
- Cyrillic (Russian, Ukrainian, etc) character-set translation
- Greek character-set translation
- Hebrew character-set translation
- Japanese character-set translation
- Unicode character-set translation
- Pseudoterminal control
- REDIRECT command
- RESEND command
- Fullscreen file transfer display
- Control-character unprefixing
- Streaming
- Autodownload
-
-Major optional features not included:
- No Kerberos(TM) authentication
- No SRP(TM) (Secure Remote Password) protocol
- No Secure Sockets Layer (SSL) protocol
- No Transport Layer Security (TLS) protocol
- No encryption
- No X Windows forwarding
-
-Host info:
- Machine:    sun4m
- Model:      (unknown)
- OS:         SunOS
- OS Release: 4.1.3_U1
- OS Version: 4
-
-Target: sunos41gsc
-GCC version: 2.7.2
-Compiled Dec 31 1999 10:38:54, options:
- __GNUC__ __STDC__ _POSIX_JOB_CONTROL _SC_JOB_CONTROL ARRAYREFLEN=1024 BIGBUFOK
- BROWSER BSD4 CK_ANSIC CK_APC CK_AUTODL CK_CURSES CK_DNS_SRV CK_ENVIRONMENT
- CK_FAST CK_LOGIN CK_MKDIR CK_NAWS CK_PCT_BAR CK_PERMS CK_RECALL CK_RTSCTS
- CK_SPEED CK_TIMERS CK_TMPDIR CK_TTGWSIZ CK_TTYFD CK_WREFRESH CKEXEC
- CKFLOAT=double CKGHNLHOST ckmaxfiles=64 CKMAXOPEN=64 CKMAXPATH=1023 CKREALPATH
- CKREGEX CKSYSLOG CKTUNING CMDBL=32763 CMDDEP=64 CONGSPD DCMDBUF DIRENT DYNAMIC
- FNFLOAT FORDEPTH=32 GFTIMER HADDRLIST HDBUUCP IFDEBUG IKS_OPTION IKSDB
- IKSDCONF INBUFSIZE=32768 INPBUFSIZ=4096 MAC_MAX=16384 MACLEVEL=128 MAXDDIR=32
- MAXDNUMS=4095 MAXGETPATH=128 MAXTAKE=54 MAXWLD=102400 MSENDMAX=1024 NETCMD
- NETCONN NETPTY NOKVERBS NOSETBUF OBUFSIZE=32768 PARSENSE PATTERNS PIPESEND
- RENAME RLOGCODE SAVEDUID SELECT SIG_V SOL_SOCKET sparc STREAMING sun SUNOS4
- SYSTIMEH TCPSOCKET TIMEH TLOG TNCODE TTLEBUF TTSPDLIST UIDBUFLEN=256 UNIX
- UNPREFIXZERO USE_LSTAT USE_MEMCPY VNAML=4096 WHATAMI XFRCAN Z_MAXCHAN=46
- z_maxchan=46 ZXREWIND
-
- byte order: big endian
-
- sizeofs: int=4 long=4 short=2 char=1 char*=4 float=4 double=8
-
- floating-point: precision=16 rounding=1
-
-   Without going into detail about what all the notation means, notice a
-   couple things:
-
-     * The Options section shows symbols ("macros") in effect during
-       compilation, together with their values (for those that have
-       values). The options are listed in alphabetical order to make any
-       particular option easier to find.
-     * MAXWLD is the maximum number of files that a wildcard can expand
-       to.
-     * Anything starting with "NO" is a feature (or something other than
-       a feature) that has been deliberately "compiled out", or omitted.
-     * Important items for script writers include: CMDBL=32763 (the size
-       of the command buffer and therefore the maximum length for a macro
-       or variable definition; CMDDEP=64 (the limit on recursion depth);
-       FORDEPTH=32 (the nesting limit on FOR loops); INBUFSIZE=32768 (the
-       size of the INPUT command circular buffer); MAC_MAX=16384 (the
-       maximum number of macros), etc.
-
-   See the [375]ckccfg.txt file for details.
-     _________________________________________________________________
-
-  1.22. Generalized File Input and Output
-
-   C-Kermit 7.0 adds a new generalized I/O system for stream files,
-   augmenting (and to some extent, overlapping with) the older OPEN,
-   READ, WRITE, and CLOSE commands. In the new file i/o system, which can
-   be used simultaneously with the old one, all commands are grouped
-   together under the new FILE keyword, and some related functions and
-   variables are added.
-
-    1.22.1. Why Another I/O System?
-
-   The well-known LOG, OPEN, READ, WRITE, and CLOSE commands have the
-   following restrictions:
-
-    1. Only one READ file and one WRITE file can be open at a time.
-    2. The READ and WRITE commands are strictly line oriented.
-    3. These commands can not be used with binary files.
-    4. They do not support read/write access or random access.
-    5. The syntax is a bit counterintuitive for programmers.
-
-   The new file i/o system allows multiple files to be open at once, in
-   any desired combination of modes (read/write/append) supported by the
-   operating system, for line, block (record), or character i/o, for
-   sequential or random access, using consistent syntax and conventions.
-
-   The new system, however, does not replace the old one, since the old
-   system still must be used for:
-
-    1. The session, packet, debug, transaction, and connection logs.
-    2. Reading and writing commands rather than files.
-    3. Existing scripts.
-
-   The new system works only with regular files, not with commands or
-   pipes or mailboxes or pseudoterminals. No special provisions are made
-   in the FILE commands for handling devices or network connections, nor
-   for preventing you from trying to open them; if the underlying
-   operating system treats them like regular stream disk files, the FILE
-   commands (except, of course SEEK, REWIND, and COUNT) might work with
-   them. (In C programming terms, the FILE commands are, at present,
-   nothing more than a front end to fopen() / fread() / fwrite() /
-   fclose() and friends, which are a portable API to sequential files,
-   but this might change in the future for platforms like VMS and VOS
-   that have more complicated file systems.)
-
-   Definitions:
-
-   Channel
-          A number assigned to a file when it is opened, by which it must
-          be referred to in all input/output operations.
-
-   Read/Write Pointer
-          The current position in an open file, expressed as the 0-based
-          byte count from the beginning.
-     _________________________________________________________________
-
-    1.22.2. The FILE Command
-
-   FILE keyword [ switches ] channel [ data ]
-          The keyword specifies the function: FILE OPEN, FILE READ, FILE
-          WRITE, FILE CLOSE, etc. For convenience (and for familiarity to
-          C programmers), the two-word FILE commands can be shortened to
-          the single words FOPEN, FREAD, FWRITE, FCLOSE, and so on.
-          Switches are optional, and modify or amplify the requested file
-          function.
-
-   As in C, Fortran, and other programming languages, open files are
-   referred to by "channels", integers such as 0, 1, 2, 3, and so on. A
-   channel number is assigned when you open a file. The number of
-   available channels depends on the underlying operating system, and can
-   be seen in the variable:
-
-  \v(f_max)
-
-   or by giving the FILE LIST (FLIST) command. Channels are discussed in
-   greater detail in [376]Section 1.22.4.
-
-   FILE command errors can be caught with IF FAIL after the FILE command.
-   In addition, the \v(f_error) variable is set to the completion code of
-   the command: 0 if no error, or a negative number if there was an
-   error. The error codes are listed in [377]Section 1.22.5.
-
-   The command to open a file is:
-
-   FILE OPEN [ switches ] variable filename
-          Opens a file for the type of access specified by the switches,
-          or for read-only access if no switches are given. Upon success,
-          a channel number is assigned to this file and stored in the
-          given variable so you can refer to the open file in subsequent
-          i/o commands. If the file can not be opened, the FILE OPEN
-          command fails. Synonym: FOPEN.
-
-   The FILE OPEN switches are:
-
-   /READ
-          Open the file for read access. If no switches are given, /READ
-          is assumed. If the file does not exist or can't be opened for
-          read access, the FILE OPEN command fails.
-
-   /WRITE
-          Allow writing. If a file of the same name already exists, it is
-          overwritten unless /READ or /APPEND is also included. If a file
-          of the given name does not exist, it is created.
-
-   /APPEND
-          Equivalent to /WRITE, except that if the file exists, it is not
-          destroyed. The read/write pointer is set to the end of the
-          file, so unless you change it with FILE SEEK or REWIND (see
-          below), the first FILE WRITE command adds to the end of the
-          file, preserving what was there already. If /WRITE is also
-          given, it is ignored.
-
-   /BINARY
-          Open the file in "binary" mode, rather than text mode. This
-          switch is meaningless (but still can be used) in UNIX. In VMS,
-          Windows, and OS/2, it inhibits end-of-line processing and
-          conversion, and so should be used for binary files and/or files
-          that are to be accessed in record or character mode rather than
-          line by line.
-
-   The variable for the channel number can be any kind of variable: the
-   \%x kind, a macro name, or an array element. But it must be a
-   variable, not a number -- C-Kermit assigns the channel number; you
-   can't tell it what number to use.
-
-   Example:
-
-  FILE OPEN \%c oofa.txt                  ; Open oofa.txt for reading.
-  IF FAIL exit 1 Can't open oofa.txt      ; Always check to see if it worked.
-  ECHO oofa.txt: channel = \%c
-
-   If the file oofa.txt is opened successfully, a channel number is
-   assigned to the variable \%c. Here's another example using a macro
-   name for the channel number:
-
-  FILE OPEN channel oofa.txt              ; Open oofa.txt for reading.
-  IF SUCCESS ECHO oofa.txt: channel = \m(channel)
-
-   Switches can be combined when it makes sense and the underlying
-   operating system allows it. For example, to open a file in binary mode
-   for reading and writing (sometimes called "update"):
-
-  FILE OPEN /READ /WRITE /BINARY \%c budget.db
-
-   Some combinations might be allowed, others not. For example /READ
-   /APPEND will usually not be allowed. /WRITE /APPEND is treated as
-   /APPEND.
-
-   A major advantage of the new system over the older one is that you can
-   have multiple files open at once. Suppose, for example, that you want
-   to open all the files in a certain directory at once:
-
-  .\%n := \ffiles(/usr/olga*,&f)          ; Get file list into array.
-  if ( > \%n \v(f_max) ) {                ; Make sure there aren't too many.
-      exit 1 {\v(dir): \%n = Too many files}
-  }
-  declare \&c[\%n]                        ; Make array for channel numbers.
-  for \%i 1 \%n 1 {                       ; Loop to open every file...
-      file open \&c[\%i] \&f[\%i]         ; Try to open this one
-      if fail exit 1 Open error: \&f[\%i] ; Check for failure
-  }
-
-   If this loop completes successfully, the \&c[] array will contain \%n
-   channel numbers of open files in elements 1 through \%n.
-
-   Any file that you open with FILE OPEN stays open until Kermit exits,
-   or you close it explicitly. The command to close a file is:
-
-   FILE CLOSE { ALL, channel }
-          If a channel number is given and the channel refers to an open
-          file, the file is closed and the channel is freed for reuse; if
-          the channel does not refer to an open file, an error message is
-          printed and the command fails. If ALL is specified instead of a
-          specific channel, all files opened with FILE OPEN are closed
-          and if all open files were closed successfully (even if no
-          files were open), the command succeeds; if any open file could
-          not be closed, the command fails; however, all open files that
-          could be closed are still closed. Synonym: FCLOSE.
-
-   FILE CLOSE might fail because, for example, the disk filled up or a
-   quota was exceeded. Example:
-
-  fopen /write \%c new.txt                ; Open new.txt for writing.
-  if fail exit 1                          ; Check for error.
-  fclose \%c                              ; Close the file we just opened.
-
-   This creates a 0-length file called new.txt.
-
-   Note that FILE OPEN /WRITE (without /READ or /APPEND) always creates a
-   new file, and therefore destroys any file with the same name that
-   might already exist (assuming you have permission to delete it). To
-   avoid overwriting existing files, simply check first:
-
-  if exist new.txt exit 1 {Fatal - new.txt already exists}
-  fopen /write \%c new.txt
-  if fail ...
-
-   The next two commands give information about open files:
-
-   FILE STATUS channel
-          Tells the name of the file, if any, open on the given channel
-          and the switches it was opened with. The read/write pointer is
-          also shown; this is where the next read or write will occur;
-          "[EOF]" is shown if the current position in the open file is
-          the end -- i.e. the next read will fail if the file was opened
-          in /READ mode; the next write will add material to the end. The
-          current line number (0-based) is also shown if known. The FILE
-          STATUS command succeeds if the channel is open, and fails if
-          there is no open file on the given channel, or if the channel
-          number is invalid or out of range. Synonym: FSTATUS.
-
-   FILE LIST
-          Lists the channel number and name of each open file, along with
-          its OPEN modes (R, W, A, B, RW, etc) and its current read/write
-          pointer or "[EOF]" if it is at the end. Also tells the number
-          of files currently opened with FILE OPEN, plus the maximum
-          number of open files allowed by the system and the maximum
-          number allowed for FILE OPEN. Synonym: FLIST.
-
-   Next come the commands for reading and writing files:
-
-   FILE READ [ switches ] channel [ variable ]
-          Reads data from the file on the given channel number into the
-          variable, if one was given; if no variable was given, the
-          result is printed on the screen. IMPORTANT: The variable should
-          normally be a macro name rather than a \%x or \&x[] variable if
-          you want backslash characters in the file to be taken literally
-          (see pp.408-412 of [378]Using C-Kermit for an explanation; you
-          can also read into a \%x or \&x[] variable, but then you must
-          remember to protect future references to by \fcontents() if you
-          don't want C-Kermit to process any backslashes it might
-          contain). The desired amount of data (according to the
-          switches) is read from the file at the current read/write
-          pointer, and upon completion the read/write position is updated
-          to first byte after the data that was read, no matter what
-          switches were given. Synonym: FREAD.
-
-   FILE WRITE [ switches ] channel text
-          Writes the given text to the file on the given channel number.
-          The text, of course, can be literal text or a variable, or any
-          combination. If the text might contain leading or trailing
-          spaces, it must be enclosed in braces if you want to preserve
-          them. Synonym: FWRITE.
-
-   Before proceeding, a caution about the NUL character. C-Kermit is so
-   named because it is a Kermit program written in the C language. In C,
-   character strings are represented as a sequence of non-NUL bytes
-   terminated by a NUL byte (a byte in which all bits are 0). Thus a C
-   string can not contain NUL bytes; it always ends with the first NUL
-   byte. C-Kermit variables are implemented as C strings and therefore
-   can't contain NUL bytes either, so the FILE READ and FILE WRITE
-   commands do not handle files or strings that contain NUL bytes, except
-   when the /CHARACTER switch is included with the FILE READ or WRITE
-   command, or when /LPAD:0 or /RPAD:0 is given with the FILE WRITE
-   command; these switches are explained below.
-
-   Also note that Kermit can not be used read or write binary numbers in
-   the machine's internal format (integer or floating-point); in general,
-   numbers can be processed only when represented as numeric or
-   floating-point strings.
-
-   FILE READ switches are:
-
-   /LINE
-          Specifies that a line of text is to be read. A line is defined
-          according to the underlying operating system's text-file
-          format. For example, in UNIX a line is a sequence of characters
-          up to and including a linefeed, or the end of the file, which
-          ever comes first. The line terminator (if any) is removed
-          before assigning the text to the variable. If no switches are
-          included with the FILE READ command, /LINE is assumed. Normally
-          this switch should not be used with files opened in /BINARY
-          mode (but nothing prevents it either).
-
-   /SIZE:number
-          Specifies that the given number of bytes (characters) is to be
-          read. The actual number of bytes returned will be less if the
-          end of file is reached (or a NUL byte is encountered). For
-          example, if a file is 514 bytes long, FILE READ /SIZE:512
-          returns 512 bytes the first time and 2 bytes the second time.
-          FILE READ /SIZE provides a kind of "record i/o" for files that
-          do not necessarily contain lines. The resulting block of
-          characters is assigned to the variable without any editing.
-          Synonym: /BLOCK.
-
-   /CHARACTER
-          Equivalent to /SIZE:1. If FILE READ /CHAR succeeds but the
-          variable is empty, this indicates a NUL byte was read. Synonym:
-          BYTE.
-
-   FILE WRITE switches are:
-
-   /LINE
-          Specifies that an appropriate line terminator is to be added to
-          the end of the text. If no switches are included, /LINE is
-          assumed.
-
-   /SIZE:number
-          Specifies that the given number of bytes (characters) is to be
-          written. If the given text is longer than the requested size,
-          it is truncated; if is shorter, it is padded according /LPAD
-          and /RPAD switches. Synonym: /BLOCK.
-
-   /LPAD[:value]
-          If /SIZE was given, but the text is shorter than the requested
-          size, the text is padded on the left with sufficient copies of
-          the character whose ASCII value is given to write the given
-          length. If no value is specified, 32 (the code for Space) is
-          used. The value can also be 0 to write the indicated number of
-          NUL bytes. If /SIZE was not given, this switch is ignored.
-
-   /RPAD[:value]
-          Like LPAD, but pads on the right.
-
-   /CHARACTER
-          Specifies that one character should be written. If the text is
-          empty or not given, a NUL character is written; otherwise the
-          first character of text is given. Synonym: /BYTE.
-
-   /STRING
-          Specifies that the text is to be written as-is, with no
-          terminator added.
-
-   Here's an example in which we copy a text file line by line:
-
-  file open /read \%c oofa.txt            ; Open input file
-  if fail exit 1 Can't open input file    ; Check that it's open
-  file open /write \%d new.txt            ; Open output file
-  if fail exit 1 Can't open output file   ; Check
-  while true {                            ; Loop to copy lines
-      file read /line \%c line            ; Read a line
-      if fail break                       ; Assume failure = end of file
-      file write /line \%d {\m(line)}     ; Write the line to output file
-      if fail exit 1 Write failure        ; Failure here is fatal
-  }
-  file close \%c                          ; Close the two files
-  file close \%d
-
-   Note that since /LINE is the default for both FILE READ and FILE
-   WRITE, it can be omitted as in the following example, where we also
-   use the short names for the FILE commands.
-
-  fopen /read \%c oofa.txt                ; Open input file
-  if fail exit 1 Can't open input file    ; Check that it's open
-  fopen /write \%d new.txt                ; Open output file
-  if fail exit 1 Can't open output file   ; Check
-  while true {                            ; Loop to copy lines
-      fread \%c line                      ; Read a line
-      if fail break                       ; Assume failure = end of file
-      fwrite \%d {\m(line)}               ; Write the line to output file
-      if fail exit 1 Write failure        ; Failure here is fatal
-  }
-  fclose \%c                              ; Close the two files
-  fclose \%d
-
-   Here's the same example using "record i/o" (the open and close
-   sequences are are omitted since they are the same as above). The
-   result is the same, but execution is much faster:
-
-  while true {                            ; Loop to copy blocks
-      fread /size:512 \%c block           ; Read a block into \%a
-      if fail break                       ; Assume failure = end of file
-      fwrite /string \%d {\m(block)}      ; Write the block to output file
-      if fail exit 1 Write failure        ; Failure here is fatal
-  }
-
-   Although record i/o is faster, it should not be used in line-oriented
-   applications, since it returns arbitrary chunks of the file to your
-   script, rather than lines. In this example, FWRITE /STRING is used
-   rather than FWRITE /SIZE:512 to avoid the last output block being
-   padded beyond the original file's length.
-
-   A file can also be copied character by character, but this is much
-   slower than line i/o and VERY much slower than block i/o:
-
-  while true {                            ; Loop to copy blocks
-      fread /char \%c c                   ; Read a character into c
-      if fail break                       ; Assume failure = end of file
-      fwrite /char \%d {\m(c)}            ; Write character to output file
-      if fail exit 1 Write failure        ; Failure is fatal
-  }
-
-   Although character i/o is slow, it is the only way to process files
-   that contain NUL characters (i.e. bytes composed of only zero bits).
-   In the example above, when "fread /char \%c c" returns a NUL, the c
-   variable is empty. But since the FREAD /CHAR command did not fail, we
-   know the result was really a NUL. FWRITE /CHAR, when given an empty
-   variable (or no variable at all) writes a NUL. Thus the loop above
-   will copy any file at all (very slowly). In non-copying applications,
-   NULs are detected like this:
-
-  fread /char \%c c
-  if fail (do something)
-  if not def c (a NUL byte was read)
-
-   Finally some advanced file operations:
-
-   FILE FLUSH channel
-          For output files only: commits all previous writes to disk, in
-          case the computer was buffering them. Synonym: FFLUSH.
-
-   FILE COUNT [ { /BYTES, /LINES, /LIST, /NOLIST } ] channel
-          By default, or if the /BYTES switch is given, counts the bytes
-          in the file, if any, open on the given channel. If the /LINES
-          switch is given, counts lines in the file. If the /LIST switch
-          is given, the result is printed. If the /NOLIST switch is
-          given, the result is not printed. /QUIET is a synonym for
-          /NOLIST. If neither /LIST nor /NOLIST is given, the result is
-          printed if the command is given at top level, i.e. not from a
-          command file or macro. In all cases, the result of the most
-          recent FILE COUNT command is stored in the variable
-          \v(f_count). Note that FILE COUNT /LINE works (and can only
-          work) by reading the entire file; expect it to take some time
-          if the file is large. Synonym: FCOUNT.
-
-   FILE REWIND channel
-          Moves the read/write pointer to the beginning of the file.
-          Equivalent to FILE SEEK channel 0. Synonym: FREWIND.
-
-   FILE SEEK [ switches ] channel { [{+,-}]number, LAST, EOF }
-          Moves the read/write pointer for the file on this channel to
-          the given position, which may be a byte (character) number or a
-          line number, expressed in either absolute or relative terms.
-          Switches:
-
-        /BYTE
-                The number given is a byte number. Synonym: /CHARACTER.
-
-        /LINE
-                The number given is a line number.
-
-        /ABSOLUTE
-                The number given is absolute.
-
-        /RELATIVE
-                The number given is relative to the current position.
-
-          By default, or if the /BYTE switch is given, the number is a
-          byte number (0 = first byte). If /LINE is given, the number is
-          a line number (0 = first line). EOF means to move to the end of
-          the file. LAST means to move to the last line or character of
-          the file, depending on whether it's a line or character seek.
-
-          If neither the /RELATIVE nor the /ABSOLUTE switch is given,
-          then if a signed number is given, the motion is relative to the
-          current position. An expression that evaluates to a negative
-          number is not considered signed for this purpose; that is, a
-          sign (+ or -) must be included as the first character of the
-          number in the command itself to force a relative seek (in the
-          absence of /RELATIVE or /ABSOLUTE).
-
-          If the number has no sign, or if the /ABSOLUTE switch is given,
-          the number represents an absolute position (relative to the
-          beginning of the file). Subsequent FILE READs or WRITEs will
-          take place at the new position.
-
-          If the read/write pointer is placed after the end of the file,
-          a subsequent FILE READ will fail, but a FILE WRITE will succeed
-          (possibly creating a file with "holes"). If a FILE SEEK /BYTE
-          command is given, the current line becomes unknown (unless the
-          position is 0) and subsequent FILE SEEK /RELATIVE /LINE
-          commands will fail until the next non-relative FILE SEEK /LINE
-          command is given. Synonym: FSEEK.
-
-   An absolute FILE SEEK to a negative position fails silently, as does a
-   relative seek to a position before the beginning of the file.
-
-   A caution about relative SEEKs: remember that the number is relative
-   to the current position. Whenever you read or write, this changes the
-   position. In each of the following examples, assume the file open on
-   channel \%c is positioned at line n (the FREAD target variable is
-   omitted for lack of space):
-
-  { FREAD \%c, FSEEK /LINE \%c -1, FREAD \%c }  <-- Reads line n twice
-  { FREAD \%c, FSEEK /LINE \%c +0, FREAD \%c }  <-- Reads lines n and n+1
-  { FREAD \%c, FSEEK /LINE \%c +1, FREAD \%c }  <-- Reads lines n and n+2
-  { FREAD \%c, FSEEK /LINE \%c -2, FREAD \%c }  <-- Reads lines n and n-1
-  { FREAD \%c, FSEEK /LINE \%c -3, FREAD \%c }  <-- Reads lines n and n-2
-
-   Another caution: Using FSEEK and FREAD /SIZE to repeatedly read the
-   same disk block (e.g. when sampling a database record that is
-   frequently updated) might not give you updated disk blocks due to the
-   internal buffering and caching of the C library (this probably varies
-   from one platform/compiler combination to another). If necessary you
-   can force a fresh disk read with a close/open sequence:
-
-  FCLOS \%c
-  FOPEN \%c samefilename
-  FSEEK \%c samespot
-  FREAD /SIZE:howmanybytes \%c variable
-     _________________________________________________________________
-
-    1.22.3. FILE Command Examples
-
-   To read the last 10 lines of a text file into an array:
-
-  fopen /read \%c oofa.txt                ; Open the file
-  if fail exit 1 Can't open oofa.txt      ; Always check for failure
-  dcl \&a[10]                             ; Declare a 10-element array
-  fcount /line \%c                        ; Count lines in the file
-  fseek /line \%c \v(f_count)-10          ; Seek to 10 lines from the end
-  if fail exit 1 Can't seek               ; Check for failure
-  for \%i 1 10 1 { fread \%c \&a[\%i] }   ; Read the last 10 lines
-  fclose \%c                              ; Close the file
-
-   Note that blank lines show up as empty (undefined) array elements, for
-   example if you give a "show array a" command at this point. This is
-   normal. You can still use these elements; e.g.:
-
-  for \%i 1 10 1 { echo \%i. \&a[\%i] }   ; Display the 10 lines
-
-   Here is how to read the last line of a file (already open on channel
-   \%c):
-
-  fseek /line \%c last                    ; Seek directly to last line
-
-   Alternatively:
-
-  fseek /line \%c eof                     ; Seek to end of file
-  fseek /line \%c -1                      ; Seek to beginning of last line
-
-   Alternatively:
-
-  fcount /line \%c                        ; Count the file's lines
-  fseek /line \%c \v(f_count)-1           ; Seek to last line
-  fread \%c                               ; Read it
-
-   To read every other line from the file (using relative SEEK), skipping
-   the first line:
-
-  fopen /read \%c oofa.txt                ; Open the file
-  while ( success ) {                     ; Loop through lines
-      fseek /line \%c +1                  ; Skip a line
-      if success fread \%c                ; Read & display a line
-  }
-  fclose \%c                              ; Close the file
-
-   Here is how to read the lines of a file in reverse order:
-
-  fopen /read \%c oofa.txt                ; Open
-  if fail exit 1                          ; Check
-  fseek /line \%c last                    ; Seek to last line
-  while success {                         ; Loop
-      fread \%c                           ; Read line
-      fseek /line \%c -2                  ; Seek backwards two lines
-  }
-  fclose \%c                              ; Close the file
-
-   The loop works because a relative SEEK outside the file fails.
-
-   It is also possible to use block i/o to manage random-access files
-   with fixed-length records (as long as they don't contain NUL
-   characters). Suppose, for example, you have a file of "card image"
-   records with fixed-field information about customers, such as:
-
-  Name:     Columns  1-32  (column numbers are 1-based)
-  Address:  Columns 33-72
-  Balance:  Columns 73-80
-
-   The records are indexed by customer number, starting with 0. There are
-   no line terminators separating them. Therefore the record for customer
-   number n starts at position nx 80 (\%n*80).
-
-   Now suppose we received a payment from customer number 173 and want to
-   update the balance:
-
-  .\%n = 173                               ; Customer (record) number
-  .\%a = 12.72                             ; Amount
-  fopen /read /write \%c customer.db       ; Open the file
-  if fail stop 1 OPEN FAILED: \f_errmsg()  ; Check
-  fseek /byte \%c 80*\%n                   ; Seek to record
-  fread /size:80 \%c r                     ; Read the record
-  if fail stop 1 READ FAILED: \f_errmsg()  ; Check (IMPORTANT)
-  .\%b := \fright(\m(r),8)                 ; Extract the balance
-  .\%b := \ffpadd(\%b,\%a,2)               ; Add the new payment
-  if fail stop 1 ARITHMETIC ERROR: \%b/\%a ; Catch bad records
-  .r := {\fleft(\m(r),72)\flpad(\%b,8)}    ; Update the record
-  fseek /byte \%c 80*\%n                   ; Reposition to same spot
-  fwrite /size:80 \%c {\m(r)}              ; Replace the record
-  if fail stop 1 WRITE FAILED: \f_errmsg() ; Check
-  fclose \%c                               ; Close the file
-
-   REMEMBER: Using FILE SEEK to move beyond the end of file can result in
-   a file with holes when writing; when reading, an end-of-file error
-   will occur -- be sure to check for it.
-     _________________________________________________________________
-
-    1.22.4. Channel Numbers
-
-   C-Kermit's channel numbers are integers from 0 to some
-   platform-dependent limit, such as 46 or 1985 (the value of \v(f_max)).
-   This is the limit placed by the operating system on the number of
-   files that may be opened by one process or user or job, minus the
-   standard input, output, and error files, and minus the number of files
-   reserved by C-Kermit for logs, OPEN READ and WRITE, and file transfer
-   (and maybe some command files -- the \v(f_max) number can't be exact).
-
-   Although you must include a variable in the FILE OPEN command, to
-   which the channel number is assigned, you don't have to use a variable
-   in the other FILE commands if you know what the number is -- you can
-   just put the number. This saves you a few keystrokes when typing
-   commands at the prompt:
-
-  fopen \%c oofa.txt
-  flist
-  0. /usr/olga.oofa.txt (R) 0
-
-   This tells the channel number is 0 (the number on the left is the
-   channel file's channel number). Of course you can also find it by
-   echoing the variable:
-
-  echo \%c
-  0
-
-   Or with "fstatus \%c". Now you can type commands like:
-
-  fread 0
-
-   to read a line from the file. Obviously, however, using digits rather
-   than a variable for the channel number would be poor practice in a
-   script.
-
-   If in commands like:
-
-  fread \%c \%a
-
-   you have trouble remembering which variable is which, note that the
-   channel number is, indeed, a number. Anywhere C-Kermit accepts a
-   number it can also accept an expression, so you can put parentheses
-   around the channel number to remind you it's the channel number and
-   not the variable into which data is to be read:
-
-  fread (\%c) \%a
-
-   Normally channel numbers are assigned sequentially as 0, 1, 2, ... up
-   to the limit. However, once you start closing files, there can be
-   holes in the sequence. New channels are assigned to fill in the holes.
-   Thus you can't depend on channel numbers being in any particular
-   sequence.
-     _________________________________________________________________
-
-    1.22.5. FILE Command Errors
-
-   Each FILE command sets the variable \v(f_error) to one of the
-   following values:
-
-    0 = No error
-   -1 = System error
-   -2 = Attempt to read after end of file
-   -3 = Channel not open
-   -4 = Channel number out of range (negative or too large)
-   -5 = Numeric argument (size, ...) out of range
-   -6 = File not found
-   -7 = Bad or missing filename
-   -8 = Too many files are already open (FILE OPEN only)
-   -9 = Forbidden operation (e.g. write to a read-only file)
-  -10 = Access denied
-  -11 = Illegal combination of OPEN modes (FILE OPEN only)
-  -12 = Buffer overflow
-  -13 = Current line number unknown (for relative line seeks)
-  -14 through -98: Reserved.
-  -99 = Requested operation not implemented in this version of C-Kermit
- -999 = Unknown error
-
-   When \v(f_error) is -1, this means the FILE command failed because
-   because of a system error, in which case you can examine the following
-   variables:
-
-  \v(errno)     = System error number.
-  \v(errstring) = Error message corresponding to \v(errno).
-
-   A special function is available for translating the \v(f_error) code
-   to an error message string:
-
-\f_errmsg([code])
-  If the code is -1, returns error message of the most recent system
-  error; otherwise if the code is a valid \v(f_error) value, the associated
-  message is returned.  If the code is omitted, the status message
-  corresponding to the current \v(f_error) value is returned.
-
-   A FILE command that fails prints the appropriate error message
-   automatically, except when the command is READ or SEEK and the error
-   is -2 (end of file); in that case, the command still fails, but does
-   not print a message. This allows constructions such as:
-
-  fopen \%c oofa.txt
-  while success { fread \%c }
-  fclose \%c
-
-   to work as expected, i.e. without an annoying message when the end of
-   file is reached.
-     _________________________________________________________________
-
-    1.22.6. File I/O Variables
-
-   The variables associated with the file i/o package are:
-
-   \v(f_count)
-          Result of the most recent FILE COUNT (FCOUNT) command.
-
-   \v(f_error)
-          Numeric error code of most recent FILE command (0 = no error).
-
-   \v(f_max)
-          Maximum number of files open simultaneously.
-     _________________________________________________________________
-
-    1.22.7. File I/O Functions
-
-   Some of the FILE commands can also be issued as function calls, which
-   makes script writing a bit more convenient, especially for C
-   programmers. Also, several functions are provided that do not have
-   command equivalents. Each of these functions takes a channel number as
-   the first argument. These functions do not work for OPEN { READ,
-   !READ, WRITE, !WRITE, and APPEND } files.
-
-   \f_status(channel)
-          Returns 0 if the channel is not open, otherwise a number
-          between 1 and 15 which is the sum of the OPEN modes:
-
-  1 = /READ
-  2 = /WRITE
-  4 = /APPEND
-  8 = /BINARY
-
-   The remaining functions work only for open channels. Each of these
-   functions can fail for the applicable reasons listed in [379]Section
-   1.22.5. For instructions on handling function errors, see [380]Section
-   7.12.
-
-   \f_pos(channel)
-          Returns the file's current read/write pointer (0-based). There
-          is no FILE command equivalent.
-
-   \f_line(channel)
-          Returns the file's current line number (0-based), if known,
-          otherwise -1. There is no FILE command equivalent. The line
-          number is known as long as no character or block i/o has been
-          done on the channel.
-
-   \f_handle(channel)
-          Returns the "file handle" of the file. That is, it translates
-          the portable C-Kermit channel number into a system-specific
-          file handle or number that can be passed to other programs on
-          the same platform. In UNIX this is a file descriptor. There is
-          no FILE command equivalent.
-
-   \f_eof(channel)
-          Returns 1 if the read/write pointer of the file on the given
-          channel is at the end of the file, 0 otherwise. Convenient in
-          WHILE statements, e.g.:
-
-    while not \f_eof(\%c) { fread \%c }
-
-   \f_getchar(channel)
-          Equivalent to FREAD /CHAR. Returns the character actually read.
-          If \f_getchar() does not fail but the return value is empty,
-          this means a NULL character was read.
-
-   \f_getline(channel)
-          Equivalent to FREAD /LINE. Returns the line actually read, but
-          with the line terminator stripped. If \f_getline() does not
-          fail but the return value is empty, this normally means an
-          empty line was read.
-
-   \f_getblock(channel,n)
-          Equivalent to FREAD /SIZE:n. Returns the block of characters
-          actually read. If the returned block is smaller than n, it
-          indicates either that the end of file was reached or a NUL
-          character is in the block.
-
-   \f_putchar(channel,c)
-          Equivalent to FWRITE /CHARACTER. Writes the character c. If c
-          contains more than one character, only the first is written. If
-          c is empty a NUL is written. Returns the number of characters
-          written on success, or a negative error code upon failure.
-
-   \f_putline(channel,string)
-          Equivalent to FWRITE /LINE. Writes the string and adds the
-          appropriate line termination character or sequence. If the
-          string is empty or omitted, an empty line is written. Returns
-          the number of characters written on success, or a negative
-          error code upon failure.
-
-   \f_putblock(channel,string)
-          Equivalent to FWRITE /STRING. Writes the string as given. If
-          the string is empty or omitted, nothing is written. Returns the
-          number of characters written on success, or a negative error
-          code upon failure.
-     _________________________________________________________________
-
-    1.22.8. File I/O Function Examples
-
-  fopen /read \%c oofa.txt            ; Open our favorite file for reading
-  if failure exit 1                   ; Check that it's open
-  while not \f_eof(\%c) {             ; Loop until EOF
-      .line := \f_getline(\%c)        ; Get a line
-      if success echo {\m(line)}      ; Echo it
-  }
-  if not \f_eof(\%c) {                ; Check reason for loop exit
-      exit 1 File Error: \f_errmsg()  ; If not EOF say so.
-  }
-
-  frewind \%c                         ; Rewind the file
-  while not \f_eof(\%c) {             ; Same thing but with block i/o
-      .block := \f_getblock(\%c,256)  ; (much faster than line i/o)
-      if success xecho {\m(block)}
-  }
-
-  frewind \%c                         ; Rewind again
-  while not \f_eof(\%c) {             ; Same deal but with character i/o
-      .c := \f_getchar(\%c)           ; (much slower than line i/o)
-      if success xecho {\m(c)}
-  }
-  close \%c
-
-   To close all open files (equivalent to FCLOSE ALL):
-
-  for \%i 0 \v(f_max)-1 1 {
-      if \f_status(\%i) fclose \%i
-  }
-     _________________________________________________________________
-
-  1.23. The EXEC Command
-
-   The EXEC command is available only in UNIX.
-
-   EXEC [ /REDIRECT ] command [ arg1 [ arg2 [ ... ] ]
-          Runs the given command with the arguments in such a way that
-          the command replaces C-Kermit in memory, and C-Kermit ceases to
-          execute. EXEC is like RUN, except instead of returning to
-          C-Kermit when finished, the command returns to whatever process
-          invoked Kermit.
-
-   In the normal case, no files are closed, so the EXEC'd command
-   inherits the open files, read/write pointers, working directory,
-   process ID, user ID (unless command is SUID), group ID (unless command
-   is SGID), groups, etc. (In UNIX, the EXEC command is simply a front
-   end for execvp().)
-
-   If the /REDIRECT switch is included, then if a connection is open (SET
-   LINE or SET HOST), it becomes the standard input and output of the
-   EXEC'd program. If no connection is open, the /REDIRECT switch has no
-   effect. For example to use C-Kermit for PPP dialing in Linux:
-
-  set modem type usr          ; Specify the kind of modem you have
-  set line /dev/ttyS1         ; Specify the device it's connected to
-  set speed 57600             ; and the speed
-  set flow rts/cts            ; and flow control.
-  set dial retries 100        ; Try the dial sequence up to 100 times.
-  dial {{9-212-555-1212}{9-212-555-1213}{9-212-555-1214}{9-212-555-1215}}
-  if fail exit 1
-  for \%i 1 16 1 {            ; Try up to 16 times to get login prompt
-      input 10 Login:         ; Wait 10 sec for it to appear
-      if success break        ; Got it - proceed...
-      output \13              ; Send a carriage return and try again
-  }
-  if ( > \%i 16 ) stop 1 NO LOGIN PROMPT
-  lineout \(myuserid)         ; Send user ID
-  input 30 assword:           ; Wait for Password prompt
-  if fail stop 1 NO PASSWORD PROMPT
-  lineout \m(mypassword)      ; Send the password.
-  exec /redirect pppd         ; Replace ourselves with pppd.
-
-   In this example we assume that the script has already set up the
-   myuserid and mypassword variables -- normally the password should be
-   prompted for, rather than stored on disk. Notice the advantages over
-   the well-known "chat script":
-     * You don't have to control the modem itself with AT commands;
-       Kermit's DIAL command does this for you.
-     * You can have Kermit automatically redial as many times as you want
-       until it gets a connection (if this is legal in your country).
-     * You can have Kermit fetch the number or numbers from a dialing
-       directory.
-     * You can have Kermit cycle through a list of phone numbers (this is
-       new in C-Kermit 7.0; see [381]Section 2.1.16) without having to
-       enter the numbers in a dialing directory.
-     * Dialing is location-independent; you can use the same script to
-       dial from different areas or countries.
-     * Once the connection is made, the full power of Kermit's script
-       language is available to manage the dialog with the terminal
-       server or other device that answers the phone call.
-
-   NOTE: PPP and SLIP dialing are not available in Windows 95/98/NT/2000,
-   whose APIs do not provide a method for an application to hand over a
-   connection to the PPP or SLIP driver.
-     _________________________________________________________________
-
-  1.24. Getting Keyword Lists with '?'
-
-   Suppose you type "te" at the C-Kermit> 6.0 prompt and then Esc or Tab
-   to request keyword completion. Kermit beeps, indicating that more than
-   one command starts with "te". But if you type '?' to see what they
-   are, Kermit shows only "telnet". So why the beep? Because of invisible
-   keywords like "telopt", "terminal", and "text". Lots of keywords are
-   invisible because they are either synonyms for other keywords or else
-   esoteric options to be used only in special circumstances, so we don't
-   want them cluttering up the menus.
-
-   But then there is no way for you to discover them. So in C-Kermit 7.0,
-   if you type '?' AFTER the beginning of a keyword field, then invisible
-   keywords are shown too:
-
-  C-Kermit> te<Esc><BEEP>
-  C-Kermit> te? Command, one of the following:
-   telnet    telopt    terminal  text
-  C-Kermit>te
-
-   But if '?' is typed at the beginning of a field, only visible keywords
-   are shown, as before (so, in this example, if '?' is typed at the
-   C-Kermit> prompt, "telnet" is the only command shown that starts with
-   "te").
-     _________________________________________________________________
-
-  2. MAKING AND USING CONNECTIONS The SET LINE, SET HOST, and SET PORT (a
-  synonym for SET LINE) commands have new synonyms, in which the word SET is
-  replaced by the word OPEN: OPEN LINE, etc. There is no new functionality
-  here, but OPEN is a better verb, since SET generally takes no action, whereas
-  these commands actually try to open a connection. Furthermore, there is the
-  symmetry with CLOSE.
-    ________________________________________________________________________
-
-  2.0. SET LINE and SET HOST Command SwitchesThe SET LINE (SET PORT) and SET
-  HOST commands now allow switches before the device or host name, in most
-  cases, and under certain circumstances, also at the end. The new syntax is
-  backwards compatible with the previous syntax; thus SET LINE, SET PORT, and
-  SET HOST commands in command files written for C-Kermit 6.0 or earlier still
-  work. The expanded syntax is:
-
-  { OPEN, SET } { LINE, PORT, HOST } [ switches ] device-or-address [ switches
-  ]
-
-  The first group of switches is:
-
-   /NETWORK-TYPE:{TCP/IP,X.25,PIPE,PTY...}
-          When more than one network type is available, this lets you
-          specify the type of network to use for this connection without
-          affecting your global SET NETWORK TYPE. See [382]Section 2.7
-          about pipes and ptys.
-
-   /USERID:[string]
-          This switch is equivalent to SET LOGIN USERID. If a string is
-          given, it sent to host during Telnet negotiations; if this
-          switch is given but the string is omitted, no user ID is sent
-          to the host. If this switch is not given, your current LOGIN
-          USERID (\v(userid) value), if any, is sent. Unlike most other
-          switches, this one is "sticky", since the value must persist
-          throughout the session in case the server requests the ID
-          string at a later time.
-
-   /CONNECT
-          Enter CONNECT mode immediately and automatically after the
-          device or connection is open. On serial devices, however, when
-          CARRIER-WATCH is not OFF, wait up to 1 second for the Carrier
-          Detect signal to appear before trying to connect, to give the
-          device time to react DTR, which might have been off prior to
-          opening the device.
-
-   /SERVER
-          Enter server mode immediately and automatically after the
-          device or connection is open. Treatment of carrier is the same
-          as for /CONNECT.
-
-   /WAIT
-   /NOWAIT
-          For Telnet connections only: Like SET TELNET WAIT { ON, OFF },
-          but applies only to this connection, and in fact applies only
-          when OPENing this connection (which is usually the only place
-          it matters). Typically you would use TELNET /NOWAIT to make a
-          connection to a misbehaving Telnet server that does not reply
-          to negotiations as required by the Telnet protocol definition.
-
-   Note: /CONNECT and /SERVER switches are not available in the RLOGIN
-   and TELNET commands, since these commands already include an implicit
-   /CONNECT and preclude automatic entry into server mode.
-
-   The /CONNECT and /SERVER switches are especially useful with "set host
-   *" connections. For example, suppose you want to start a Kermit server
-   on socket 3000 of your TCP host. Normally you would have to give the
-   command:
-
-  set host * 3000
-
-   and then wait for a connection to come in, and only then could you
-   give the SERVER command (or else define a macro to do this, and then
-   execute the macro). Now you can do it in one step:
-
-  set host /server * 3000
-
-   This tells C-Kermit to wait for the connection and then enter server
-   mode once it comes in, no matter how long it takes. Similarly, "set
-   host /conn *" can be used to wait for a "chat" connection to come in.
-
-   Another set of switches is available in VMS only, for use only with
-   SET LINE:
-
-   /SHARE
-          Allows the SET LINE device to be opened in shared mode.
-          Normally it makes no sense to open a serial device in shared
-          mode, but it's necessary when C-Kermit is running in an
-          environment such as DECIntact, that opens your job's
-          controlling terminal in such a way that C-Kermit can't open it
-          too, unless it enables SHARE privilege. Note: SHARE privilege
-          is required.
-
-   /NOSHARE
-          Requires that the SET LINE device not be in use by any other
-          process in order for it to be successfully opened by C-Kermit.
-          If neither /SHARE nor /NOSHARE is specified, /NOSHARE is used.
-
-   The second group of switches is:
-
-   /NO-TELNET-INIT
-          Do not send initial Telnet negotiations even if this is a
-          Telnet port.
-
-   /RAW-SOCKET
-          This is a connection to a raw TCP socket ([383]Section 2.3.5).
-
-   /RLOGIN
-          Use Rlogin protocol even if this is not an Rlogin port.
-
-   /TELNET
-          Send initial Telnet negotiations even if this is not a Telnet
-          port.
-
-   As of C-Kermit 7.0 and K95 1.1.19, the TELNET command includes an
-   implicit /TELNET switch. So if you TELNET to a non-TELNET port, Kermit
-   sends initial Telnet negotiations. This makes sense, since that's what
-   "telnet" means.
-
-   If you want to make a connection to a non-Telnet port without sending
-   initial Telnet negotiations, use:
-
-  set host [ /connect ] name-or-address port
-
-   or:
-
-  telnet name-or-address port /no-telnet-init
-
-   Additional switches might be added in the future; type "set host ?" or
-   "set line ?" to see a current list.
-     _________________________________________________________________
-
-  2.1. Dialing
-
-   Automatic redialing is illegal or restricted in many countries, so
-   until C-Kermit 7.0, it was disabled by default, i.e. until a SET DIAL
-   RETRIES command was given. In C-Kermit 7.0, if no SET DIAL RETRIES
-   command has been given, a default is picked dynamically at DIAL time
-   based on the calling country code, if known. At this writing, the only
-   country code known to have no restrictions on automatic redialing is
-   1. So in this case a limit of 10 is chosen; otherwise 1. If you have
-   not given an explicit SET DIAL RETRIES command, SHOW DIAL shows the
-   value as "(auto)", and then the value actually used is shown when you
-   give the DIAL command.
-
-   As of C-Kermit 7.0, automatic redialing is automatically canceled if
-   the call could not be placed because no dialtone was detected.
-     _________________________________________________________________
-
-    2.1.1. The Dial Result Message
-
-   If DIAL DISPLAY is not ON, the "Call complete" message now shows the
-   modem's call result message, for example:
-
-  Dialing: ...
-  Call complete: "CONNECT 31200/ARQ/V32/LAPM/V42BIS"
-
-   The exact format and contents of this message, of course, depends on
-   the make, model, and configuration of your modem, so use your modem
-   manual to interpret it. The call result message is also available in
-   C-Kermit's \v(dialresult) variable.
-
-  C-Kermit> echo \v(dialresult)
-  CONNECT 31200/ARQ/V32/LAPM/V42BIS
-  C-Kermit> echo Speed = \fword(\v(dialresult),2)
-  Speed = 31200
-  C-Kermit>
-
-   Suppose your modem reports the modulation speed as shown above and you
-   want to ensure your call is completed at (say) 24000 bps or more. You
-   can use a little macro to do the job:
-
-define HSDIAL {                ; High Speed DIAL
-    local \%s
-    if < \v(argc) 1 if not def \v(dialnumber) end 1 Usage: \%0 number
-    set dial retries 100
-    set dial interval 1
-    while true {
-        dial \%*
-        if fail end 1 DIAL failed.
-        asg \%s \fword(\v(dialresult),2)
-        if def \%s if numeric \%s if not < \%s 24000 break
-    }
-}
-
-   (See [384]Section 7.5 about the \%* variable.)
-     _________________________________________________________________
-
-    2.1.2. Long-Distance Dialing Changes
-
-   Due to the glut of cell phones, pagers, fax machines, ISPs, etc, area
-   codes and dialing rules are changing all the time. In the North
-   American Numbering Plan (NANP) countries (USA, Canada, etc), area
-   codes are split or overlayed with increasing frequency, and 10- and
-   11-digit dialing is gradually becoming the norm for local calls.
-   Changes are occurring In Europe, too, partly for these reasons and
-   partly because of some new EC rules.
-
-   In France, effective 18 October 1996, all calls, even local ones, must
-   be dialed with an area code. French area codes are presently 1-digit
-   numbers, 1-6, and the long-distance dialing prefix is 0. All calls
-   within France are considered long distance and begin with 01, 02, ...,
-   06.
-
-   Effective 1 May 1997, all calls within the US state of Maryland, even
-   local ones, must be dialed with an area code but without the
-   long-distance prefix -- this is the now widely-known North American
-   phenomenon of "ten digit dialing". The same is happening elsewhere --
-   many cities in Florida adopted 10-digit dialing in 1998.
-
-   In Italy beginning 19 June 1998, all calls to fixed (as opposed to
-   mobile) numbers must be prefixed by 0. When calling into Italy from
-   outside, the 0 must follow the country code (39). Calls to cell
-   phones, however, must be placed without the 0. Then on 29 December
-   2000, the 0 will become a 4 (for calling fixed numbers) and a prefix
-   of 3 must used for calling mobile phones. More info at:
-   http://www.telecomitalia.it/npnn/.
-
-   In Spain, effective 4 April 1998, with hard cutover on 18 July 1998,
-   all calls within the country must be dialed with 9 digits, and all
-   calls from outside Spain must also be dialed with 9 digits (after the
-   country code, 34). The new 9-digit numbers all begin with "9". More
-   info at: [385]http://www.telefonica.es/cambiodenumeracion/
-
-   Several new dialing features and commands have been added in version
-   6.1 and 7.0 to address these changes.
-
-   C-Kermit 6.0 and Kermit 95 1.1.11 and earlier handle the French
-   situation via a reasonable subterfuge (setting the local area code to
-   a nonexistent one), but did not handle "ten-digit dialing" well at
-   all; the recommended technique was to change the long-distance dialing
-   prefix to nothing, but this defeated Kermit's "list numbers for one
-   name" feature when the numbers were in different locations. For
-   example:
-
-  set dial ld-prefix
-  dial onlineservice
-
-   where "onlineservice" is a dialing directory entry name corresponding
-   to entries that are in (say) Maryland as well as other states, would
-   not correctly dial the numbers not in Maryland.
-
-   A new command lets you specify a list of area codes to be considered
-   local, except that the area code must be dialed:
-
-   SET DIAL LC-AREA-CODES [ areacode [ areacode [ areacode [ ... ] ] ] ]
-          The list may include up to 32 area codes. If a number is called
-          whose area code is in this list, it is dialed WITHOUT the
-          long-distance prefix, but WITH the area code.
-
-   So in Maryland, which (last time we looked) has two area codes, 410
-   and 301, the setup would be:
-
-  SET DIAL LC-AREA-CODES 410 301
-
-   Example:
-
-  SET DIAL LD-PREFIX 1
-  SET DIAL AREA-CODE 301
-  SET DIAL LC-AREA-CODES 410 301 <-- Area codes in 10-digit dialing region
-  DIAL +1 (301) 765-4321         <-- Dials 3017654321  (local with area code)
-  DIAL +1 (410) 765-4321         <-- Dials 4107654321  (local with area code)
-  DIAL +1 (212) 765-4321         <-- Dials 12127654321 (long distance)
-
-   The SET DIAL LC-AREA-CODES command does not replace the SET DIAL
-   AREA-CODE command. The latter specifies the area code you are dialing
-   from. If the called number is in the same area code, then the area
-   code is dialed if it is also in the LC-AREA-CODES list, and it is not
-   dialed otherwise. So if "301" had not appeared in the LC-AREA-CODES
-   list in the previous example:
-
-  SET DIAL LD-PREFIX 1
-  SET DIAL AREA-CODE 301
-  SET DIAL LC-AREA-CODES 410     <-- Area codes in 10-digit dialing region
-  DIAL +1 (301) 765-4321         <-- Dials 7654321     (local)
-  DIAL +1 (410) 765-4321         <-- Dials 4107654321  (local with area code)
-  DIAL +1 (212) 765-4321         <-- Dials 12127654321 (long distance)
-
-   The new Kermit versions also add a Local Call Prefix and Local Call
-   Suffix, in case you have any need for it. These are added to the
-   beginning and of local phone numbers (i.e. numbers that are not
-   long-distance or international). Examples:
-
-  SET DIAL LD-PREFIX 1
-  SET DIAL LC-PREFIX 9
-  SET DIAL LC-SUFFIX *
-  SET DIAL LC-AREA-CODES 410     <-- Area codes in 10-digit dialing region
-  SET DIAL AREA-CODE 301
-  DIAL +1 (301) 765-4321         <-- Dials 97654321*     (local)
-  DIAL +1 (410) 765-4321         <-- Dials 94107654321*  (local with area code)
-  DIAL +1 (212) 765-4321         <-- Dials 12127654321   (long distance)
-     _________________________________________________________________
-
-    2.1.3. Forcing Long-Distance Dialing
-
-   Suppose a number is in your country and area, but for some reason you
-   need to dial it long-distance anyway (as is always the case in
-   France). There have always been various ways to handle this:
-
-    1. Temporarily set your area code to a different (or nonexistent or
-       impossible) one (but this required knowledge of which area codes
-       were nonexistent or impossible in each country).
-    2. Dial the number literally instead of using the portable format,
-       but this defeats the purpose of the portable dialing directory.
-
-   Now there is also a new command that, very simply, can force
-   long-distance dialing:
-
-   SET DIAL FORCE-LONG-DISTANCE { ON, OFF }
-          If a call is placed to a portable phone number within the same
-          country code as the calling number, it is dialed with the
-          long-distance prefix and the area code if FORCE-LONG-DISTANCE
-          is ON. If OFF, the regular rules and procedures apply.
-
-   Example (France):
-
-  SET DIAL COUNTRY-CODE 33
-  SET DIAL AREA-CODE 6
-  SET DIAL FORCE-LONG-DISTANCE ON
-
-   (In fact, SET DIAL COUNTRY-CODE 33 automatically sets DIAL
-   FORCE-LONG-DISTANCE ON...)
-
-   Example (USA, for a certain type of reverse-charge calling in which
-   the called number must always be fully specified):
-
-  SET DIAL PREFIX 18002666328$     ; 1-800-COLLECT
-  SET DIAL COUNTRY-CODE 1
-  SET DIAL AREA-CODE 212
-  SET DIAL FORCE-LONG-DISTANCE ON
-
-   Example (Toronto, where calls to exchange 976 within area code 416
-   must be dialed as long distance, even when you are dialing from area
-   code 416):
-
-  SET DIAL COUNTRY-CODE 1
-  SET DIAL AREA-CODE 416
-  SET DIAL FORCE-LONG-DISTANCE ON
-  DIAL +1 (416) 976-xxxx
-
-   If dialing methods were consistent and sensible, of course it would be
-   possible to always dial every domestic call as if it were long
-   distance. But in many locations this doesn't work or if it does, it
-   costs extra. The following macro can be used for dialing any given
-   number with forced long-distance format:
-
-  define LDIAL {
-      local \%x
-      set dial force-long-distance on
-      dial \%*
-      asg \%x \v(success)
-      set dial force-long-distance off
-      end \%x
-  }
-
-   (See [386]Section 7.5 about the \%* variable.)
-     _________________________________________________________________
-
-    2.1.4. Exchange-Specific Dialing Decisions
-
-   This applies mainly to the North American Numbering Plan (NANP). Refer
-   to the section "Alternative notations" in [387]Using C-Kermit 2nd
-   Edition, pages 106-107, and the story about Toronto on page 110. Using
-   the new LC-AREA-CODES list, we can address the problem by treating the
-   exchange as part of the area code:
-
-  SET DIAL LD-PREFIX 1
-  SET DIAL AREA-CODE 416
-  SET DIAL LC-AREA-CODES 905276
-  DIAL +1 416 765 4321               <-- 7654321      (local)
-  DIAL +1 905 276 4321               <-- 9052764321   (local with area code)
-  DIAL +1 905 528 4321               <-- 19055284321  (long distance)
-
-   The same technique can be used in Massachusetts (story at top of page
-   111) and in any other place where dialing to some exchanges within a
-   particular area code is local, but to others in the same area code is
-   long distance.
-     _________________________________________________________________
-
-    2.1.5. Cautions about Cheapest-First Dialing
-
-   Kermit does not maintain a knowledge base of telephony information; it
-   only provides the tools to let you enter a phone number in a standard
-   format and dial it correctly from any location in most cases.
-
-   In particular, Kermit does not differentiate the charging method from
-   the dialing method. If a call that is DIALED as long-distance (e.g.
-   from 212 to 718 in country code 1) is not CHARGED as long distance, we
-   have no way of knowing that without keeping a matrix of charging
-   information for every area-code combination within every country, and
-   any such matrix would be obsolete five minutes after it was
-   constructed. Thus, "cheapest-first" sorting is only as reliable as our
-   assumption that the charging method follows the dialing method. A good
-   illustration would be certain online services that have toll-free
-   dialup numbers which they charge you a premium (in your online service
-   bill) for using.
-     _________________________________________________________________
-
-    2.1.6. Blind Dialing (Dialing with No Dialtone)
-
-   C-Kermit's init string for Hayes-like modems generally includes an X4
-   command to enable as many result codes as possible, so that Kermit can
-   react appropriately to different failure reasons. One of the result
-   codes that X4 enables is "NO DIALTONE". A perhaps not obvious side
-   effect of enabling this result code that the modem must hear dialtone
-   before it will dial.
-
-   It is becoming increasingly necessary to force a modem to dial even
-   though it does not hear a dialtone on the phone line; for example,
-   with PBXs that have strange dialtones, or with phone systems in
-   different countries, or with ISDN phones, etc. This is called "blind
-   dialing".
-
-   C-Kermit 7.0 has two new commands to cope with this situation:
-
-   SET DIAL IGNORE-DIALTONE { ON, OFF }
-          OFF (the default) means to tell the modem to wait for dialtone
-          before dialing. ON means to enable "blind dialing", i.e. tell
-          the modem NOT to wait for dialtone before dialing. Generally
-          this is accomplished by sending ATX3 to the modem just prior to
-          dialing. SET MODEM TYPE xxx and then SHOW MODEM displays
-          Kermit's built-in "ignore dialtone" command.
-
-   SET DIAL COMMAND IGNORE-DIALTONE text
-          This lets you change the built-in ignore-dialtone command (such
-          as ATX3) to whatever you choose, in case the built-in one does
-          not work, or another command works better.
-
-   Notes:
-    1. The ignore-dialtone command is not sent unless SET DIAL
-       IGNORE-DIALTONE is ON.
-    2. The ATX3 command generally disables not only NO DIALTONE, but also
-       BUSY. So this will prevent Kermit from detecting when the line is
-       busy. This is a property of the modem, not of Kermit.
-     _________________________________________________________________
-
-    2.1.7. Trimming the Dialing Dialog
-
-   The command:
-
-  SET MODEM COMMAND action [ command ]
-
-   is used to override Kermit's built-in modem commands for each action,
-   for each kind of modem in its internal database. If you include a
-   command, this is used instead of the built-in one. If you omit the
-   command, this restores the original built-in command.
-
-   If you want to omit the command altogether, so Kermit doesn't send the
-   command at all, or wait for a response, use:
-
-  SET MODEM COMMAND action {}
-
-   That is, specify a pair of empty braces as the command, for example:
-
-  SET MODEM COMMAND ERROR-CORRECTION ON {}
-     _________________________________________________________________
-
-    2.1.8. Controlling the Dialing Speed
-
-   The rate at which characters are sent to the modem during dialing is
-   normally controlled by the built-in modem database. You might want to
-   override this if Kermit seems to be dialing too slowly, or it is
-   sending characters to the modem faster than the modem handle them. A
-   new command was added for this in C-Kermit 7.0:
-
-   SET DIAL PACING number
-          Specifies the number of milliseconds (thousandths of seconds)
-          to pause between each character when sending commands to the
-          modem during DIAL or ANSWER command execution. 0 means no pause
-          at all, -1 (the default) or any other negative number means to
-          use the value from the database. Any number greater than 0 is
-          the number of milliseconds to pause.
-
-   HINT: You might also need to control the rate at which the modem
-   generates Touch Tones during dialing, for example when sending a
-   numeric page. There are two ways to do this. One way is to insert
-   pause characters into the dialing string. For modems that use the AT
-   command set, the pause character is comma (,) and causes a 2-second
-   pause. On most modems, you can use the S8 register to change the pause
-   interval caused by comma in the dialing string. The other way is to
-   set your modem's tone generation interval, if it has a command for
-   that. Most AT-command-set modems use S11 for this; the value is in
-   milliseconds. For example on USR modems:
-
-  ATS11=200
-
-   selects an interval of 200 milliseconds to separate each dialing tone.
-
-   Hint: To add S-Register settings or other commands to your dialing
-   procedure, use the new SET MODEM COMMAND PREDIAL-INIT command
-   ([388]Section 2.2.2).
-     _________________________________________________________________
-
-    2.1.9. Pretesting Phone Number Conversions
-
-   The LOOKUP command now accepts telephone numbers as well as
-   directory-entry names, for example:
-
-  LOOKUP +1 (212) 7654321
-
-   When given a phone number, LOOKUP prints the result of converting the
-   phone number for dialing under the current dialing rules. For example,
-   if my country code is 1 and my area code is 212, and I am dialing out
-   from a PBX whose outside-line prefix is "93,":
-
-  C-Kermit> lookup +1 (212) 7654321
-  +1 (212) 7654321 => 93,7654321
-  C-Kermit>
-
-   You can also use the \fdialconvert(phone-number) function
-   ([389]Section 2.1.11) to do this programmatically:
-
-  C-Kermit> echo "\fdialconvert(+1 (212) 7654321)"
-  "93,7654321"
-  C-Kermit>
-
-   So the new LOOKUP behaves as follows:
-
-   LOOKUP portable-format-phone-number
-          Displays how the number would actually be dialed Sets FAILURE
-          if there was a conversion error, otherwise SUCCESS.
-
-   LOOKUP literal-format-phone-number
-          Displays the same literal-format-phone-number Always sets
-          SUCCESS.
-
-   LOOKUP dialing-directory-name
-          Displays all matching entries and converts portable phone
-          numbers. Sets SUCCESS if at least one entry was found,
-          otherwise FAILURE.
-
-   LOOKUP =anything
-          Displays "=anything" and sets SUCCESS.
-
-   There is, at present, no programmatic way to fetch numbers from the
-   dialing directory. This will be considered for a future release.
-     _________________________________________________________________
-
-    2.1.10. Greater Control over Partial Dialing
-
-   The following rules now apply to partial dialing:
-
-     * Phone number transformations based on country and area code,
-       application of prefixes, etc, are performed only on the first
-       PDIAL.
-     * Each PDIAL argument is looked up in the dialing directory, so it
-       is possible have directory entries for pieces of phone numbers or
-       other information.
-     * Suffixes are not applied automatically, since there is no way for
-       C-Kermit to know in which PDIAL segment you want them to be
-       applied.
-
-   However, the suffix that *would* have been applied, based on the
-   dialing rules that were invoked when processing the first PDIAL
-   command, is stored in the variable:
-
-  \v(dialsuffix)
-
-   which you can include in any subsequent PDIAL or DIAL commands.
-
-   Example:
-
-  pdial {\m(my_long_distance_pager_number_part_1)}
-  pdial {\m(my_long_distance_pager_number_part_2)}
-  pdial {\v(dialsuffix)}
-  pdial {\m(my_long_distance_pager_number_part_3)}
-  pdial {@\m(numeric_pager_code)#}
-     _________________________________________________________________
-
-    2.1.11. New DIAL-related Variables and Functions
-
-   \fdialconvert(s)
-          s is a phone number in either literal or portable format (not a
-          dialing directory entry name). The function returns the dial
-          string that would actually be used by the DIAL command when
-          dialing from the current location, after processing country
-          code, area code, and other SET DIAL values, and should be the
-          same as the result of LOOKUP when given a telephone number.
-
-   \v(dialsuffix)
-          Contains the suffix, if any, that was applied in the most
-          recent DIAL command, or the suffix that would have been applied
-          in the most recent PDIAL command. Use this variable to send the
-          dial suffix at any desired point in a PDIAL sequence.
-
-   \v(dialtype)
-          A number indicating the type of call that was most recently
-          placed. Can be used after a normal DIAL command, or after the
-          first PDIAL command in a PDIAL sequence. Values are:
-
-  -2: Unknown because TAPI handled the phone number translation.
-  -1: Unknown because some kind of error occured.
-   0: Internal within PBX.
-   1: Toll-free.
-   2: Local within calling area.
-   3: Unknown (e.g. because a literal-format phone number was given).
-   4: Long distance within country.
-   5: International
-
-   \v(dialcount)
-          The current value of the DIAL retry counter, for use in a DIAL
-          macro ([390]Section 2.1.13).
-
-   \v(d$px)
-          PBX Exchange (see [391]Section 2.1.12).
-
-   Other dial-related variables, already documented in [392]Using
-   C-Kermit (or other sections of this document, e.g. [393]Section
-   2.1.1), include \v(dialnumber), \v(dialstatus), etc. A convenient way
-   to display all of them is:
-
-  show variable dial  ; hint: abbreviate "sho var dial"
-
-   This shows the values of all the variables whose names start with
-   "dial". Also "show variable d$" (to show the \v(d$...) variables).
-     _________________________________________________________________
-
-    2.1.12. Increased Flexibility of PBX Dialing
-
-   Refer to [394]Using C-Kermit, 2nd Edition, pages 107-108. Recall that
-   three commands are needed to configure C-Kermit for dialing from a
-   PBX:
-
-  SET DIAL PBX-EXCHANGE number
-  SET DIAL PBX-INSIDE-PREFIX number
-  SET DIAL PBX-OUTSIDE-PREFIX number
-
-   Unfortunately, this model does not accommodate PBXs that have more
-   than one exchange. For example our PBX at Columbia University (which
-   must handle more than 10,000 phones) has 853-xxxx and 854-xxxx
-   exchanges.
-
-   Beginning in C-Kermit 7.0, the SET DIAL PBX-EXCHANGE command accepts a
-   list of exchanges, e.g.:
-
-  SET DIAL PBX-EXCHANGE 853 854
-
-   (multiple exchanges are separated by spaces, not commas).
-
-   So now when dialing a portable-format number that has the same country
-   and area codes as those of your dialing location, C-Kermit compares
-   the exchange of the dialed number with each number in the PBX Exchange
-   list (rather than with a single PBX Exchange number, as it did
-   formerly) to determine whether this is an internal PBX number or an
-   external call. If it is an external call, then the PBX Outside Prefix
-   is applied, and then the normal dialing rules for local or
-   long-distance calls.
-
-   If it is an inside call, the exchange is replaced by the PBX Inside
-   Prefix. But if the PBX has more than one exchange, a single fixed PBX
-   Inside Prefix is probably not sufficient. For example, at Columbia
-   University, we must dial 3-xxxx for an internal call to 853-xxxx, but
-   4-xxxx for a call to 854-xxxx. That is, the inside prefix is the final
-   digit of the exchange we are dialing. For this reason, C-Kermit 7.0
-   provides a method to determine the inside prefix dynamically at
-   dialing time, consisting of a new variable and new syntax for the SET
-   DIAL PBX-INSIDE-PREFIX command:
-
-   \v(d$px)
-          This variable contains the exchange that was matched when a PBX
-          internal call was detected. For example, if the PBX exchange
-          list is "853 854" and a call is placed to +1 (212) 854-9999,
-          \v(d$px) is set to 854.
-
-   SET DIAL PBX-INSIDE-PREFIX \fxxx(...)
-          If the PBX Inside Prefix is defined to be a function, its
-          evaluation is deferred until dialing time. Normally, this would
-          be a string function having \v(d$px) as an operand. Of course,
-          you can still specify a constant string, as before.
-
-   So given the following setup:
-
-  SET DIAL COUNTRY-CODE 1
-  SET DIAL AREA-CODE 212
-  SET DIAL PBX-OUTSIDE-PREFIX 93,
-  SET DIAL PBX-EXCHANGE 853 854
-  SET DIAL PBX-INSIDE-PREFIX \fright(\v(d$px),1)
-
-   The following numbers give the results indicated:
-
- Number                   Result
-  +1 (212) 854-9876        4-9876
-  +1 (212) 853-1234        3-1234
-  +1 (212) 765-4321        93,765-4321
-  +1 (333) 765-4321        93,1333765-4321
-
-   Furthermore, the K_PBX_XCH environment variable may now be set to a
-   list of exchanges to automatically initialize C-Kermit's PBX exchange
-   list, for example (in UNIX ksh or bash):
-
-  export K_PBX_XCH="853 854"
-
-   (Quotes required because of the space.) Of course, this variable can
-   also be set to a single exchange, as before:
-
-  export K_PBX_XCH=853
-     _________________________________________________________________
-
-    2.1.13. The DIAL macro - Last-Minute Phone Number Conversions
-
-   After a DIAL or LOOKUP command is given, a list of phone numbers is
-   assembled from the dialing directory (if any), with all
-   location-dependent conversion rules applied as described in Chapter 5
-   of [395]Using C-Kermit.
-
-   However, additional conversions might still be required at the last
-   minute based on local or ephemeral conditions. So that you can have
-   the final word on the exact format of the dial string, C-Kermit 7.0
-   lets you pass the converted string through a macro of your own design
-   for final processing before dialing. The relevant command is:
-
-   SET DIAL MACRO [ name ]
-          Specifies the name of a macro to be run on each phone number
-          after all built-in conversions have been applied, just before
-          the number is dialed. If no name is given, no macro is run. The
-          phone number, as it would have been dialed if there were no
-          dial macro, is passed to the macro.
-
-   The dial macro can do anything at all (except start a file transfer).
-   However, the normal use for the macro would be to modify the phone
-   number. For this reason the phone number is passed to the macro as
-   argument number 1 (\%1). To cause a modified number to be dialed, the
-   macro should terminate with a RETURN statement specifying a return
-   value. To leave the number alone, the macro should simply end.
-   Example:
-
-  define xxx return 10108889999$\%1
-  set dial macro xxx
-  dial xyzcorp
-
-   This defines a DIAL MACRO called xxx, which puts an access code on the
-   front of the number. Another example might be:
-
-  def xxx if equal "\v(modem)" "hayes-1200" return \freplace(\%1,$,{,,,,,})
-  set dial macro xxx
-  dial xyzcorp
-
-   which replaces any dollar-sign in the dial string by a series of five
-   commas, e.g. because this particular modem does not support the "wait
-   for bong" feature (remember that commas that are to be included
-   literally in function arguments must be enclosed in braces to
-   distinguish them from the commas that separate the arguments) and when
-   the IF condition is not satisfied, the macro does not return a value,
-   and so the number is not modified. Then when a DIAL command is given
-   referencing a dialing directory entry, "xyzcorp". The macro is
-   automatically applied to each matching number.
-
-   Numerous dial-, modem-, communications-, and time-related variables
-   are available for decision making your dial macro. Type SHOW VARIABLES
-   for a list. Of particular interest is the \v(dialcount) variable,
-   which tells how many times the DIAL command gone through its retry
-   loop: 1 on the first try, 2 on the second, 3 on the third, and so on,
-   and the \v(dialresult) and \v(dialstatus) variables.
-
-   Here are some other applications for the DIAL MACRO (from users):
-
-     * Phone numbers in the dialing directory are formatted with '-' for
-       readability, but some modems don't like the hyphens, so the DIAL
-       macro is used to remove them before dialing; e.g
-       0090-123-456-78-99 becomes 00901234567899: "def xxx return
-       \freplace(\%1,-)".
-     * To set some specific modem (or other) options depending on the
-       called customer or telephone number.
-     * Choosing the most appropriate provider based on (e.g.) time of
-       day, or cycling through a list of providers in case some providers
-       might be busy.
-
-   To illustrate the final item, suppose you have a choice among many
-   phone service providers; the provider is chosen by dialing an access
-   code before the number. Different providers might be better (e.g.
-   cheaper) for certain times of day or days of the week, or for dialing
-   certain locations; you can use the DIAL macro to add the access for
-   the most desirable provider.
-
-   Similarly, when the same number might be reached through multiple
-   providers, it's possible that one provider might not be able to
-   complete the call, but another one can. In that case, you can use the
-   DIAL macro to switch providers each time through the DIAL loop --
-   that's where the \v(dialcount) variable comes in handy.
-
-   The following command can be used to debug the DIAL macro:
-
-   SET DIAL TEST { ON, OFF }
-          Normally OFF, so the DIAL command actually dials. When ON, the
-          DIAL command performs all lookups and number conversions, and
-          then goes through the number list and retry loop, but instead
-          of actually dialing, lists the numbers it would have called if
-          none of the DIAL attempts succeeded (or more precisely, every
-          number was always busy).
-     _________________________________________________________________
-
-    2.1.14. Automatic Tone/Pulse Dialing Selection
-
-   SET DIAL METHOD { AUTO, DEFAULT, PULSE, TONE }
-          Chooses the dialing method for subsequent calls.
-
-   Prior to version 7.0, C-Kermit's DIAL METHOD was DEFAULT by default,
-   meaning it does not specify a dialing method to the modem, but relies
-   on the modem to have an appropriate default dialing method set. So,
-   for example, when using Hayes compatible modems, the dial string would
-   be something like ATD7654321, rather than ATDT7654321 or ATDP7654321.
-
-   In C-Kermit 7.0 and K95 1.1.19, the dial method can be set from the
-   environment variable:
-
-  K_DIAL_METHOD
-
-   when Kermit starts. The values can be TONE, PULSE, or DEFAULT, e.g.
-   (UNIX):
-
-  set K_DIAL_METHOD=TONE; export K_DIAL_METHOD
-
-   In the absence of a K_DIAL_METHOD definition, the new default SET DIAL
-   METHOD is AUTO rather than DEFAULT. When DIAL METHOD is AUTO and the
-   local country code is known, then if tone dialing is universally
-   available in the corresponding area, tone dialing is used; if dialing
-   from a location where pulse dialing is mandatory, pulse dialing is
-   used.
-
-   The "tone country" and "pulse country" lists are preloaded according
-   to our knowledge at the time of release. You can see their contents in
-   the SHOW DIAL listing. You can change the lists with:
-
-   SET DIAL TONE-COUNTRIES [ cc [ cc [ ... ] ] ]
-          Replaces the current TONE-COUNTRIES list with the one given.
-          Each cc is a country code; separate them with spaces (not
-          commas). Example:
-
-  set dial tone-countries 1 358 44 46 49
-
-          If no country codes are given, the current list, if any, is
-          removed, in which case SET DIAL METHOD AUTO is equivalent to
-          SET DIAL METHOD DEFAULT.
-
-   SET DIAL PULSE-COUNTRIES [ cc [ cc [ ... ] ] ]
-          Replaces the current PULSE-COUNTRIES list with the one give.
-          Syntax and operation is like SET DIAL TONE-COUNTRIES.
-
-   If the same country code appears in both lists, Pulse takes
-   precedence.
-
-   The SET DIAL TONE- and PULSE-COUNTRIES commands perform no
-   verification whatsoever on the cc's, since almost any syntax might be
-   legal in some settings. Furthermore, there is no facility to edit the
-   lists; you can only replace the whole list. However, since the only
-   purpose of these lists is to establish a basis for picking tone or
-   pulse dialing automatically, all you need to override the effect of
-   the list is to set a specific dialing method with SET DIAL METHOD TONE
-   or SET DIAL METHOD PULSE.
-     _________________________________________________________________
-
-    2.1.15. Dial-Modifier Variables
-
-   As of C-Kermit 7.0, dial modifiers are available in the following
-   variables:
-
- \v(dm_lp) Long pause
- \v(dm_sp) Short pause
- \v(dm_pd) Pulse dial
- \v(dm_td) Tone dial
- \v(dm_wa) Wait for answer
- \v(dm_wd) Wait for dialtone
- \v(dm_rc) Return to command mode
-
-   You can use these in your dial strings in place of hardwired modifiers
-   like "@", ",", etc, for increased portability of scripts. Example:
-
-  C-Kermit>set modem type usrobotics
-  C-Kermit>sho variables dm
-   \v(dm_lp) = ,
-   \v(dm_sp) = /
-   \v(dm_pd) = P
-   \v(dm_td) = T
-   \v(dm_wa) = @
-   \v(dm_wd) = W
-   \v(dm_rc) = ;
-  C-Kermit>exit
-     _________________________________________________________________
-
-    2.1.16. Giving Multiple Numbers to the DIAL Command
-
-   Prior to C-Kermit 7.0, the only way to give a DIAL command a list of
-   phone numbers to try until one answers was to create a dialing
-   directory that had multiple entries under the same name, and then use
-   that entry name in the DIAL command. Now a list of numbers can be
-   given to the DIAL command directly in the following format:
-
-  dial {{number1}{number2}{number3}...}
-
-   This is the same list format used by SEND /EXCEPT: and other commands
-   that allow a list where normally a single item is given. Restrictions
-   on this form of the DIAL command are:
-
-     * The first two braces must be adjacent; spacing is optional
-       thereafter.
-     * Each number must be an actual number to dial, not a dialing
-       directory entry.
-     * Dialing directory entries may not contain number lists in this
-       format.
-
-   In all other respects, the numbers are treated as if they had been
-   fetched from the dialing directory; they can be in literal or portable
-   format, etc. Example:
-
-  dial {{7654321} {+1 (212) 5551212} { 1-212-5556789 }}
-
-   The list can be any length at all, within reason.
-
-   This feature is especially handy for use with the K95 Dialer, allowing
-   a list of phone numbers to be specified in the Telephone Number box
-   without having to set up or reference a separate dialing directory.
-
-   You can also use it to add commonly-dialed sequences as variables in
-   your C-Kermit customization file, e.g.:
-
-  define work {{7654321}{7654322}{7654323}}
-
-   and then:
-
-  dial {\m(work)}
-
-   (the variable name must be enclosed in braces).
-
-   Or more simply:
-
-  define work dial {{7654321}{7654322}{7654323}}
-
-   and then:
-
-  work
-     _________________________________________________________________
-
-  2.2. Modems
-
-    2.2.1. New Modem Types
-
-   Since C-Kermit 6.0:
-
-  atlas-newcom-33600ifxC Atlas/Newcom 33600
-  att-keepintouch        AT&T KeepinTouch PCMCIA V.32bis Card Modem
-  att-1900-stu-iii       AT&T Secure Data STU-III Model 1900
-  att-1910-stu-iii       AT&T Secure Data STU-III Model 1910
-  bestdata               Best Data
-  cardinal               Cardinal V.34 MVP288X series.
-  compaq                 Compaq Data+Fax (e.g. in Presario)
-  fujitsu                Fujitsu Fax/Modem Adapter
-  generic-high-speed     Any modern error-correcting data-compressing modem
-  itu-t-v25ter/v250      ITU-T (CCITT) V.25ter (V.250) standard command set
-  megahertz-att-v34      Megahertz AT&T V.34
-  megahertz-xjack        Megahertz X-Jack
-  motorola-codex         Motorola Codex 326X Series
-  motorola-montana       Motorola Montana
-  mt5634zpx              Multitech MT5634ZPX
-  rockwell-v90           Rockwell V.90 56K
-  rolm-244pc             Siemens/Rolm 244PC (AT command set)
-  rolm-600-series        Siemens/Rolm 600 Series (AT command set)
-  spirit-ii              QuickComm Spirit II
-  suprasonic             SupraSonic V288+
-  supra-express-v90      Supra Express V.90
-
-   One of the new types, "generic-high-speed" needs a bit of explanation.
-   This type was added to easily handle other types that are not
-   explicitly covered, without going through the bother of adding a
-   complete user-defined modem type. This one works for modern modems
-   that use the AT command set, on the assumption that all the default
-   ("factory") settings of the modem (a) are appropriate for Kermit, (b)
-   include error correction, data compression, and speed buffering; and
-   (c) are recallable with the command AT&F.
-
-   If the command to recall your modem's profile is not AT&F, use the SET
-   MODEM COMMAND INIT-STRING command to specify the appropriate modem
-   command. The default init-string is AT&F\13 (that is, AT, ampersand,
-   F, and then carriage return); a survey of about 20 modern modem types
-   shows they all support this, but they might mean different things by
-   it. For example, the USR Sportster or Courier needs AT&F1 (not AT&F,
-   which is equivalent to AT&F0, which recalls an inappropriate profile),
-   so for USR modems:
-
-  set modem type generic-high-speed
-  set modem command init AT&F1\13
-
-   Of course, USR modems already have their own built-in modem type. But
-   if you use this one instead, it will dial faster because it has fewer
-   commands to give to the modem; in that sense "&F1" is like a macro
-   that bundles numerous commands into a single one. See your modem
-   manual for details about factory profiles and commands to recall them.
-
-   WARNING: Do not use the generic-high-speed modem type in operating
-   systems like VMS where hardware flow control is not available, at
-   least not unless you change the init string from AT&F\13 to something
-   else that enables local Xon/Xoff or other appropriate type of flow
-   control.
-
-   Also see [396]Section 2.1.7 for additional hints about making dialing
-   go faster.
-     _________________________________________________________________
-
-    2.2.2. New Modem Controls
-
-   SET MODEM CAPABILITIES list
-          In C-Kermit 7.0, this command automatically turns MODEM
-          SPEED-MATCHING OFF if SB (Speed Buffering) is in the list, and
-          turns it ON if SB is absent.
-
-   SET MODEM COMMAND PREDIAL-INIT [ text ]
-          Commands to be sent to the modem just prior to dialing.
-          Normally none.
-
-   SET MODEM SPEAKER { ON, OFF }
-          Determines whether modem speaker is on or off while call is
-          being placed. ON by default. Note: This command does not
-          provide fine-grained control over when the speaker is on or
-          off. Normally, ON means while the call is being placed, until
-          the point at which carrier is successfully established. If your
-          modem has a different speaker option that you want to choose,
-          then use the SET MODEM COMMAND SPEAKER ON text command to
-          specify this option.
-
-   SET MODEM COMMAND SPEAKER { ON, OFF } [ text ]
-          Specify or override the commands to turn your modem's speaker
-          on and off.
-
-   SET MODEM VOLUME { LOW, MEDIUM, HIGH }
-          When MODEM SPEAKER is on, select volume. Note: In some modems,
-          especially internal ones, these commands have no effect; this
-          is a limitation of the particular modem, not of Kermit.
-
-   SET MODEM COMMAND VOLUME { LOW, MEDIUM, HIGH } [ text ]
-          Specify or override the commands to set your modem's speaker
-          volume.
-
-   SET MODEM COMMAND IGNORE-DIALTONE [ text ]
-          The command to enable blind dialing ([397]Section 2.1.6).
-
-   SET MODEM ESCAPE-CHARACTER code
-          Has been augmented to allow codes of 0 or less: < 0 means the
-          escape mechanism is disabled. = 0 means to use (restore) the
-          default value from the modem database. > 0 and < 128 is a
-          literal value to be used instead of the default one. > 127
-          means the escape mechanism is disabled. This affects "modem
-          hangup". When the escape mechanism is disabled, but SET MODEM
-          HANGUP-METHOD is MODEM-COMMAND, it sends the hangup command
-          immediately, without the <pause>+++<pause> business first. This
-          is useful (for example) when sending lots of numeric pages, a
-          process in which never we go online, and so never need to
-          escape back. Eliminating the unnecessary pauses and escape
-          sequence allows a lot more pages to be sent per unit time.
-
-   Recall that C-Kermit can dial modems to which it is connected via
-   TCP/IP (Telnet or Rlogin) as described on page 126 of [398]Using
-   C-Kermit, 2nd Ed. In this case the MODEM HANGUP-METHOD should be
-   MODEM-COMMAND, since RS-232 signals don't work over TCP/IP
-   connections. As noted in the manual, such connections are set up by
-   the following sequence:
-
-  set host host [ port ]
-  set modem type name
-  dial number
-
-   But this can cause complications when you use Kermit to switch between
-   serial and TCP/IP connections. In the following sequence:
-
-  set host name
-  set modem type name
-  set port name
-
-   the first two commands obey the rules for dialing out over Telnet.
-   However, the SET PORT command requires that Kermit close its current
-   (Telnet) connection before it can open the serial port (since Kermit
-   can only have one connection open at a time). But since a modem type
-   was set after the "set host" command was given, Kermit assumes it is a
-   Telnet dialout connection and so sends the modem's hangup sequence is
-   sent to the Telnet host. To avoid this, close the network connection
-   explicitly before opening the serial one:
-
-  set host name
-  close
-  set modem type name
-  set port name
-     _________________________________________________________________
-
-  2.3. TELNET and RLOGIN
-
-   For additional background, please also read the [399]TELNET.TXT file,
-   also available on the Web in [400]HTML format.
-
-   Cautions:
-
-     * If making a Telnet connection with C-Kermit takes a very long
-       time, like over a minute, whereas the system Telnet program makes
-       the same connection immediately, try including the /NOWAIT switch:
-  C-Kermit> telnet /nowait hostname
-       See [401]TELNET.TXT or [402]TELNET.HTM for details. If it also
-       takes a very long time to make a Telnet connection with system
-       Telnet, then the delay is most likely caused by reverse DNS
-       lookups when your host is not properly registered in DNS.
-     * When supplying numeric IP addresses to C-Kermit or to any other
-       application (regular Telnet, Rlogin, etc), do not include leading
-       0's in any fields unless you intend for those fields to be
-       interpreted as octal (or hex) numbers. The description of the
-       Internet address interpreter (the sockets library inet_addr()
-       routine) includes these words:
-
-     All numbers supplied as "parts" in a "." notation may be decimal,
-     octal, or hexadecimal, as specified in the C language (that is, a
-     leading 0x or 0X implies hexadecimal; otherwise, a leading 0
-     implies octal; otherwise, the number is interpreted as decimal).
-       To illustrate, 128.59.39.2 and 128.059.039.002 are not the same
-       host! Even though most of the fields contain non-octal digits.
-       Using system Telnet (not Kermit):
-  $ telnet 128.059.039.002
-  Trying 128.49.33.2 ...
-       Of course the same thing happens with Kermit because it uses (as
-       it must) the same system service for resolving network addresses
-       that Telnet, FTP, and all other TCP/IP applications use.
-     * The RLOGIN section on page 123 does not make it clear that you can
-       use the SET TELNET TERMINAL-TYPE command to govern the terminal
-       type that is reported by C-Kermit to the RLOGIN server.
-     * Note that the SET TCP commands described on pages 122-123 might be
-       absent; some platforms that support TCP/IP do not support these
-       particular controls.
-
-   New commands:
-
-   TELOPT { AO, AYT, BREAK, CANCEL, EC, EL, EOF, EOR, GA, IP, DMARK,
-          DO, DONT, NOP, SB, SE, SUSP, WILL, WONT }
-          This command was available previously, but supported only DO,
-          DONT, WILL, and WONT. Now it lets you send all the Telnet
-          protocol commands. Note that certain commands do not require a
-          response, and therefore can be used as nondestructive "probes"
-          to see if the Telnet session is still open; e.g.:
-
-  set host xyzcorp.com
-  ...
-  telopt nop
-  if fail stop 1 Connection lost
-
-   SET TCP ADDRESS [ ip-address ]
-          Specifies the IP address of the computer that C-Kermit is
-          running on. Normally this is not necessary. The exception would
-          be if your machine has multiple network adapters (physical or
-          virtual) with a different address for each adapter AND you want
-          C-Kermit to use a specific address when making outgoing
-          connections or accepting incoming connections.
-
-   SET TCP DNS-SERVICE-RECORDS { ON, OFF }
-          Tells C-Kermit whether to try to use DNS SRV records to
-          determine the host and port number upon which to find an
-          advertised service. For example, if a host wants regular Telnet
-          connections redirected to some port other than 23, this feature
-          allows C-Kermit to ask the host which port it should use. Since
-          not all domain servers are set up to answer such requests, this
-          feature is OFF by default.
-
-   SET TCP REVERSE-DNS-LOOKUP { ON, OFF, AUTO }
-          Tells Kermit whether to perform a reverse DNS lookup on TCP/IP
-          connections. This allows Kermit to determine the actual
-          hostname of the host it is connected to, which is useful for
-          connections to host pools, and is required for Kerberos
-          connections to host pools and for incoming connections. If the
-          other host does not have a DNS entry, the reverse lookup could
-          take a long time (minutes) to fail, but the connection will
-          still be made. Turn this option OFF for speedier connections if
-          you do not need to know exactly which host you are connected to
-          and you are not using Kerberos. AUTO, the default, means the
-          lookup is done on hostnames, but not on numeric IP addresses.
-
-   SET TELNET WAIT-FOR-NEGOTIATIONS { ON, OFF }
-          Each Telnet option must be fully negotiated either On or Off
-          before the session can continue. This is especially true with
-          options that require sub-negotiations such as Authentication,
-          Encryption, and Kermit; for proper support of these options
-          Kermit must wait for the negotiations to complete. Of course,
-          Kermit has no way of knowing whether a reply is delayed or not
-          coming at all, and so will wait a minute or more for required
-          replies before continuing the session. If you know that
-          Kermit's Telnet partner will not be sending the required
-          replies, you can set this option of OFF to avoid the long
-          timeouts. Or you can instruct Kermit to REFUSE specific options
-          with the SET TELOPT command.
-
-   SET TELOPT [ { /CLIENT, /SERVER } ] option
-          { ACCEPTED, REFUSED, REQUESTED, REQUIRED }
-          [ { ACCEPTED, REFUSED, REQUESTED, REQUIRED } ]
-          SET TELOPT lets you specify policy requirements for Kermit's
-          handling of Telnet option negotiations. Setting an option is
-          REQUIRED causes Kermit to offer the option to the peer and
-          disconnect if the option is refused. REQUESTED causes Kermit to
-          offer an option to the peer. ACCEPTED results in no offer but
-          Kermit will attempt to negotiate the option if it is requested.
-          REFUSED instructs Kermit to refuse the option if it is
-          requested by the peer.
-
-          Some options are negotiated in two directions and accept
-          separate policies for each direction; the first keyword applies
-          to Kermit itself, the second applies to Kermit's Telnet
-          partner; if the second keyword is omitted, an appropriate
-          (option-specific) default is applied. You can also include a
-          /CLIENT or /SERVER switch to indicate whether the given
-          policies apply when Kermit is the Telnet client or the Telnet
-          server; if no switch is given, the command applies to the
-          client.
-
-          Note that some of Kermit's Telnet partners fail to refuse
-          options that they do not recognize and instead do not respond
-          at all. In this case it is possible to use SET TELOPT to
-          instruct Kermit to REFUSE the option before connecting to the
-          problem host, thus skipping the problematic negotiation.
-
-          Use SHOW TELOPT to view current Telnet Option negotiation
-          settings. SHOW TELNET displays current Telnet settings.
-     _________________________________________________________________
-
-    2.3.0. Bug Fixes
-
-   If "set host nonexistent-host" was given (and it properly failed),
-   followed by certain commands like SEND, the original line and modem
-   type were not restored and C-Kermit thought that it still had a
-   network hostname; fixed in 7.0.
-
-    2.3.1. Telnet Binary Mode Bug Adjustments
-
-   SET TELNET BUG BINARY-ME-MEANS-U-TOO { ON, OFF } was added to edit 192
-   after the book was printed. Also SET TELNET BUG BINARY-U-MEANS-ME-TOO.
-   The default for both is OFF. ON should be used when communicating with
-   a Telnet partner (client or server) that mistakenly believes that
-   telling C-Kermit to enter Telnet binary mode also means that it, too,
-   is in binary mode, contrary to the Telnet specification, which says
-   that binary mode must be negotiated in each direction separately.
-
-    2.3.2. VMS UCX Telnet Port Bug Adjustment
-
-   A new command, SET TCP UCX-PORT-BUG, was added for VMS versions with
-   UCX (DEC TCP/IP), applying only to early versions of UCX, like 2.2 or
-   earlier. If you try to use VMS C-Kermit to make a Telnet connection
-   using a port name (like "telnet", which is used by default), the
-   underlying UCX getservbyname() function might return the service
-   number with its bytes swapped and the connection will fail. If "telnet
-   hostname 23" works, then your version of UCX has this bug and you can
-   put "set tcp ucx-port-bug on" in your CKERMIT.INI file to get around
-   it.
-
-    2.3.3. Telnet New Environment Option
-
-   The TELNET NEW-ENVIRONMENT option ([403]RFC 1572) is supported as 7.0.
-   This option allows the C-Kermit Telnet client to send certain
-   well-known variables to the Telnet server, including USER, PRINTER,
-   DISPLAY, and several others. This feature is enabled by default in
-   Windows and OS/2, disabled by default elsewhere. The command to enable
-   and disable it is:
-
-  SET TELNET ENVIRONMENT { ON, OFF }
-
-   When ON, and you Telnet to another computer, you might (or might not)
-   notice that the "login:" or "Username:" prompt does not appear --
-   that's because your username was sent ahead, in which case the remote
-   system might prompt you only for your password (similar to Rlogin).
-   Use "set telnet environment off" to defeat this feature, particularly
-   in scripts where the dialog must be predictable. You can also use this
-   command to specify or override specific well-known environment
-   variable values:
-
- SET TELNET ENVIRONMENT { ACCT,DISPLAY,JOB,PRINTER,SYSTEMTYPE,USER } [ text ]
-
-    2.3.4. Telnet Location Option
-
-   The TELNET LOCATION option ([404]RFC 779) is supported in 7.0. This
-   option allows the C-Kermit Telnet client to send a location string to
-   the server if the server indicates its willingness to accept one. If
-   an environment variable named LOCATION exists at the time C-Kermit
-   starts, its value is used as the location string. If you want to
-   change it, use:
-
-  SET TELNET LOCATION text
-
-   If you omit the text from this command, the Telnet location feature is
-   disabled.
-
-   SET TELNET ENVIRONMENT DISPLAY is used to set the DISPLAY variable
-   that is sent to the host, as well as the the XDISPLAY location.
-
-    2.3.5. Connecting to Raw TCP Sockets
-
-   The SET HOST and TELNET commands now accept an optional switch,
-   /RAW-SOCKET, at the end, only if you first give a host and a port.
-   Example:
-
-  set host xyzcorp.com 23 /raw-socket
-  set host 128.49.39.2:2000 /raw-socket
-  telnet xyzcorp.com 3000 /raw
-
-   Without this switch, C-Kermit behaves as a Telnet client when (a) the
-   port is 23 or 1649, or (b) the port is not 513 and the server sent
-   what appeared to be Telnet negotiations -- that is, messages starting
-   with 0xFF (IAC). With this switch, Kermit should treat all incoming
-   bytes as raw data, and will not engage in any Telnet negotiations or
-   NVT CRLF manipulations. This allows transparent operation through
-   (e.g.) raw TCP ports on Cisco terminal servers, through the 'modemd'
-   modem server, etc.
-
-    2.3.6. Incoming TCP Connections
-
-   Accomplished via SET HOST * port, were introduced in C-Kermit 6.0, but
-   for UNIX only. In Version 7.0, they are also available for VMS.
-     _________________________________________________________________
-
-  2.4. The EIGHTBIT Command
-
-   EIGHTBIT is simply a shorthand for: SET PARITY NONE, SET TERMINAL
-   BYTESIZE 8, SET COMMAND BYTESIZE 8; that is, a way to set up an 8-bit
-   clean connection in a single command.
-     _________________________________________________________________
-
-  2.5. The Services Directory
-
-   Chapter 7 of [405]Using C-Kermit does not mention the ULOGIN macro,
-   which is used by our sample services directory, CKERMIT.KND. Unlike
-   UNIXLOGIN, VMSLOGIN, etc, this one is for use with systems that
-   require a user ID but no password. Therefore it doesn't prompt for a
-   password or wait for a password prompt from the remote service.
-
-   In version 7.0, the CALL macro was changed to not execute a SET MODEM
-   TYPE command if the given modem type was the same as the current one;
-   otherwise the new SET MODEM TYPE command would overwrite any
-   customizations that the user had made to the modem settings. Ditto for
-   SET LINE / SET PORT and SET SPEED.
-     _________________________________________________________________
-
-  2.6. Closing Connections
-
-   Until version 7.0, there was never an obvious and general way to close
-   a connection. If a serial connection was open, it could be closed by
-   "set line" or "set port" (giving no device name); if a network
-   connection was open, it could be closed by "set host" (no host name).
-
-   In version 7.0, a new command closes the connection in an obvious and
-   straightforward way, no matter what the connection type:
-
-  CLOSE [ CONNECTION ]
-
-   The CLOSE command was already present, and required an operand such as
-   DEBUG-LOG, WRITE-FILE, etc, and so could never be given by itself. The
-   new CONNECTION operand is now the default operand for CLOSE, so CLOSE
-   by itself closes the connection, if one is open, just as you would
-   expect, especially if you are a Telnet or Ftp user.
-
-   Also see the description of the new SET CLOSE-ON-DISCONNECT command in
-   [406]Section 2.10.
-     _________________________________________________________________
-
-  2.7. Using C-Kermit with External Communication Programs
-
-   C-Kermit 7.0 includes a new ability to create and conduct sessions
-   through other communications programs. Two methods are available:
-
-    1. Pty (pseudoterminal): The external program is run on a
-       "pseudoterminal", which is controlled by Kermit. This method works
-       with practically any external program, but it is not portable. At
-       this writing, it works only on some (not all) UNIX versions, and
-       not on any non-UNIX platforms.
-    2. Pipe: The external program's standard input and output are
-       redirected through a "pipe" controlled by Kermit. This method is
-       relatively portable -- it should work across all UNIX versions,
-       and it also works in Windows and OS/2 -- but it is effective only
-       when the external program actually uses standard i/o (and many
-       don't).
-
-   The two methods are started differently but are used the same way
-   thereafter.
-
-   The purpose of this feature is to let you use C-Kermit services like
-   file transfer, character-set translation, scripting, automatic
-   dialing, etc, on connections that Kermit can't otherwise make itself.
-
-   This feature is the opposite of the REDIRECT feature, in which
-   C-Kermit makes the connection, and redirects an external (local)
-   command or program over this connection. In a pty or pipe connection,
-   C-Kermit runs and controls a local command or program, which makes the
-   connection. (The same method can be used to simply to control a local
-   program without making a connection; see [407]Section 2.8.)
-
-   To find out if your version of Kermit includes PTY support, type "show
-   features" and look for NETPTY in the alphabetical list of options. For
-   pipes, look for NETCMD.
-
-   The commands are:
-
-   SET NETWORK TYPE PTY or SET NETWORK TYPE PIPE
-   SET HOST command
-          where command is any interactive command. If the command does
-          not use standard i/o, you must use SET NETWORK TYPE PTY.
-
-   Notes:
-
-     * COMMAND is an invisible synonym for PIPE.
-     * The command and its arguments are case-sensitive in UNIX.
-
-   The SET NETWORK TYPE, SET HOST sequence sets the given network type
-   for all subsequent SET HOST commands until another SET NETWORK TYPE
-   command is given to change it.
-
-   You can also use the new /NETWORK-TYPE:PTY or /NETWORK-TYPE:PIPE (or
-   simply /PIPE or /PTY) switches on the SET HOST command itself:
-
-  SET HOST /NETWORK-TYPE:PIPE command  ; These two are the same
-  SET HOST /PIPE command
-
-  SET HOST /NETWORK-TYPE:PTY command   ; Ditto
-  SET HOST /PTY command
-
-   These are like SET NETWORK TYPE followed by SET HOST, except they
-   apply only to the connection being made and do not change the global
-   network type setting (see [408]Section 1.5 about the difference
-   between switches and SET commands).
-
-   Include any command-line options with the command that might be
-   needed, as in this example where C-Kermit uses another copy of itself
-   as the communications program:
-
-  SET HOST /PIPE /CONNECT kermit -YQJ xyzcorp.com
-
-   As usual, if you include the /CONNECT switch, SET HOST enters CONNECT
-   mode immediately upon successful execution of the given command.
-   Therefore new commands are available as a shorthand for SET HOST
-   /CONNECT /PTY and /PIPE:
-
-   PTY [ command ]
-   PIPE [ command ]
-          The PTY and PIPE commands work like the TELNET and RLOGIN
-          commands: they set up the connection (in this case, using the
-          given command) and then enter CONNECT mode automatically (if
-          the PIPE or PTY command is given without a command, it
-          continues the current session if one is active; otherwise it
-          gives an error message).
-
-   The PIPE command is named after the mechanism by which C-Kermit
-   communicates with the command: UNIX pipes. C-Kermit's i/o is "piped"
-   through the given command. Here is a typical example:
-
-  PIPE rlogin -8 xyzcorp.com
-
-   This is equivalent to:
-
-  SET HOST /PIPE rlogin -8 xyzcorp.com
-  CONNECT
-
-   and to:
-
-  SET HOST /PIPE /CONNECT rlogin -8 xyzcorp.com
-
-   IMPORTANT:
-          If you are writing a script, do not use the PIPE, PTY, TELNET,
-          or RLOGIN command unless you really want C-Kermit to enter
-          CONNECT mode at that point. Normally SET HOST is used in
-          scripts to allow the login and other dialogs to be controlled
-          by the script itself, rather than by an actively participating
-          human at the keyboard.
-
-   Throughput of pty and pipe connections is limited by the performance
-   of the chosen command or program and by the interprocess communication
-   (IPC) method used and/or buffering capacity of the pipe or pty, which
-   in turn depends on the underlying operating system.
-
-   In one trial (on SunOS 4.1.3), we observed file transfer rates over an
-   rlogin connection proceeding at 200Kcps for downloads, but only 10Kcps
-   for uploads on the same connection with the same settings (similar
-   disparities were noted in HP-UX). Examination of the logs revealed
-   that a write to the pipe could take as long as 5 seconds, whereas
-   reads were practically instantaneous. On the other hand, using Telnet
-   as the external program rather than rlogin, downloads and uploads were
-   better matched at about 177K each.
-
-   Most external communication programs, like C-Kermit itself, have
-   escape characters or sequences. Normally these begin with (or consist
-   entirely of) a control character. You must be sure that this control
-   character is not "unprefixed" when uploading files, otherwise the
-   external program will "escape back" to its prompt, or close the
-   connection, or take some other unwanted action. When in CONNECT mode,
-   observe the program's normal interaction rules. Of course C-Kermit's
-   own escape character (normally Ctrl-\) is active too, unless you have
-   taken some action to disable it.
-
-   On PTY connections, the underlying PTY driver is not guaranteed to be
-   transparent to control characters -- for example, it might expand
-   tabs, translate carriage returns, generate signals if it sees an
-   interrupt character, and so on. Similar things might happen on a PIPE
-   connection. For this reason, if you plan to transfer files over a PTY
-   or PIPE connection, tell the file sender to:
-
-   SET PREFIXING ALL
-          This causes all control characters to be prefixed and
-          transmitted as printable ASCII characters.
-
-   If the external connection program is not 8-bit clean, you should
-   also:
-
-   SET PARITY SPACE
-          This causes 8-bit data to be encoded in 7 bits using single
-          and/or locking shifts.
-
-   And if it does not make a reliable connection (such as those made by
-   Telnet, Rlogin, Ssh, etc), you should:
-
-   SET STREAMING OFF
-          This forces C-Kermit to treat the connection as unreliable and
-          to engage in its normal ACK/NAK protocol for error detection
-          and correction, rather than "streaming" its packets, as it
-          normally does on a network connection ([409]Section 4.20).
-
-   In some cases, buffer sizes might be restricted, so you might also
-   need to reduce the Kermit packet length to fit; this is a
-   trial-and-error affair. For example, if transfers always fail with
-   4000-byte packets, try 2000. If that fails too, try 1000, and so on.
-   The commands are:
-
-   SET RECEIVE PACKET-LENGTH number
-          This tells the file receiver to tell the file sender the
-          longest packet length it can accept.
-
-   SET SEND PACKET-LENGTH number
-          This tells the file sender not to send packets longer than the
-          given length, even if the receiver says longer ones are OK. Of
-          course, if the receiver's length is shorter, the shorter length
-          is used.
-
-   If none of this seems to help, try falling back to the bare minimum,
-   lowest-common-denominator protocol settings:
-
-   ROBUST
-          No sliding windows, no streaming, no control-character
-          unprefixing, packet length 90.
-
-   And then work your way back up by trial and error to get greater
-   throughput.
-
-   Note that when starting a PIPE connection, and the connection program
-   (such as telnet or rlogin) prints some greeting or information
-   messages before starting the connection, these are quite likely to be
-   printed with a stairstep effect (linefeed without carriage return).
-   This is because the program is not connected with the UNIX terminal
-   driver; there's not much Kermit can do about it. Once the connection
-   is made, everything should go back to normal. This shouldn't happen on
-   a PTY connection because a PTY is, indeed, a terminal.
-
-   On a similar note, some connection programs (like Solaris 2.5 rlogin)
-   might print lots of error messages like "ioctl TIOCGETP: invalid
-   argument" when used through a pipe. They are annoying but usually
-   harmless. If you want to avoid these messages, and your shell allows
-   redirection of stderr, you can redirect stderr in your pipe command,
-   as in this example where the user's shell is bash:
-
-  PIPE rlogin xyzcorp.com 2> /dev/null
-
-   Or use PTY rather than PIPE, since PTY is available on Solaris.
-     _________________________________________________________________
-
-    2.7.0. C-Kermit over tn3270 and tn5250
-
-   Now you can make a connection from C-Kermit "directly" to an IBM
-   mainframe and transfer files with it, assuming it has Kermit-370
-   installed. Because tn3270 is neither 8-bit clean nor transparent to
-   control characters, you must give these commands:
-
-  SET PREFIXING ALL   ; Prefix all control characters
-  SET PARITY SPACE    ; Telnet connections are usually not 8-bit clean
-
-   and then:
-
-  SET HOST /PTY /CONNECT tn3270 abccorp.com
-
-   or simply:
-
-  pty tn3270 abccorp.com
-
-   SET HOST /PIPE does not work in this case, at least not for file
-   transfer. File transfer does work, however, with SET HOST /PTY,
-   provided you use the default packet length of 90 bytes; anything
-   longer seems to kill the session.
-
-   You can also make connections to IBM AS/400 computers if you have a
-   tn5250 program installed:
-
-  pty tn5250 hostname
-
-   In this case, however, file transfer is probably not in the cards
-   since nobody has ever succeeded in writing a Kermit program for the
-   AS/400. Hint:
-
-  define tn3270 {
-      check pty
-      if fail end 1 Sorry - no PTY support...
-      pty tn3270 \%*
-  }
-
-   Similarly for tn5250. Note that CHECK PTY and CHECK PIPE can be used
-   in macros and scripts to test whether PTY or PIPE support is
-   available.
-     _________________________________________________________________
-
-    2.7.1. C-Kermit over Telnet
-
-   Although C-Kermit includes its own Telnet implementation, you might
-   need to use an external Telnet program to make certain connections;
-   perhaps because it has access or security features not available in
-   C-Kermit itself. As noted above, the only precautions necessary are
-   usually:
-
-  SET PREFIXING ALL   ; Prefix all control characters
-  SET PARITY SPACE    ; Telnet connections might not be 8-bit clean
-
-   and then:
-
-  SET HOST /PTY (or /PIPE) /CONNECT telnet abccorp.com
-
-   or, equivalently:
-
-  PTY (or PIPE) telnet abccorp.com
-     _________________________________________________________________
-
-    2.7.2. C-Kermit over Rlogin
-
-   C-Kermit includes its own Rlogin client, but this can normally be used
-   only if you are root, since the rlogin TCP port is privileged. But
-   ptys and pipes let you make rlogin connections with C-Kermit through
-   your computer's external rlogin program, which is normally installed
-   as a privileged program:
-
-  SET PREFIXING ALL
-
-   and then:
-
-  SET HOST /PTY (or /PIPE) /CONNECT rlogin -8 abccorp.com
-
-   or, equivalently:
-
-  PTY (or PIPE) rlogin -8 abccorp.com
-
-   The "-8" option to rlogin enables transmission of 8-bit data. If this
-   is not available, then include SET PARITY SPACE if you intend to
-   transfer files.
-
-   Note that the normal escape sequence for rlogin is Carriage Return
-   followed by Tilde (~), but only when the tilde is followed by certain
-   other characters; the exact behavior depends on your rlogin client, so
-   read its documentation.
-     _________________________________________________________________
-
-    2.7.3. C-Kermit over Serial Communication Programs
-
-   Ptys and pipes also let you use programs that make serial connections,
-   such as cu or tip. For example, C-Kermit can be used through cu to
-   make connections that otherwise might not be allowed, e.g. because
-   C-Kermit is not installed with the required write permissions to the
-   dialout device and the UUCP lockfile directory.
-
-   Suppose your UUCP Devices file contains an entry for a serial device
-   tty04 to be used for direct connections, but this device is protected
-   against you (and Kermit when you run it). In this case you can:
-
-  SET CONTROL PREFIX ALL
-  PTY (or PIPE) cu -l tty04
-
-   (Similarly for dialout devices, except then you also need to include
-   the phone number in the "cu" command.)
-
-   As with other communication programs, watch out for cu's escape
-   sequence, which is the same as the rlogin program's: Carriage Return
-   followed by Tilde (followed by another character to specify an action,
-   like "." for closing the connection and exiting from cu).
-     _________________________________________________________________
-
-    2.7.4. C-Kermit over Secure Network Clients
-
-     DISCLAIMER: There are laws in the USA and other countries regarding
-     use, import, and/or export of encryption and/or decryption or other
-     forms of security software, algorithms, technology, and
-     intellectual property. The Kermit Project attempts to follow all
-     known statutes, and neither intends nor suggests that Kermit
-     software can or should be used in any way, in any location, that
-     circumvents any regulations, laws, treaties, covenants, or other
-     legitimate canons or instruments of law, international relations,
-     trade, ethics, or propriety.
-
-   For secure connections or connections through firewalls, C-Kermit 7.0
-   can be a Kerberos, SRP, and/or SOCKS client when built with the
-   appropriate options and libraries. But other application-level
-   security acronyms and methods -- SSH, SSL, SRP, TLS -- pop up at an
-   alarming rate and are (a) impossible to keep up with, (b) usually
-   mutually incompatible, and (c) have restrictions on export or
-   redistribution and so cannot be included in C-Kermit itself.
-
-   However, if you have a secure text-based Telnet (or other) client that
-   employs one of these security methods, you can use C-Kermit "through"
-   it via a pty or pipe.
-     _________________________________________________________________
-
-    2.7.4.1. SSH
-
-   C-Kermit does not and can not incorporate SSH due to licensing,
-   patent, and USA export law restrictions.
-
-   The UNIX SSH client does not use standard input/output, and therefore
-   can be used only by Kermit's PTY interface, if one is present. The
-   cautions about file transfer, etc, are the same as for Rlogin.
-   Example:
-
-  SET PREFIXING ALL
-  PTY ssh XYZCORP.COM
-
-   Or, for a scripted session:
-
-  SET PREFIXING ALL
-  SET HOST /PTY ssh XYZCORP.COM
-
-   Hint:
-
-  define ssh {
-      check pty
-      if fail end 1 Sorry - no PTY support...
-      pty ssh \%*
-  }
-     _________________________________________________________________
-
-    2.7.4.2. SSL
-
-   Secure Sockets Layer (SSL) is another TCP/IP security overlay, this
-   one designed by and for Netscape. An SSL Telnet client is available
-   for UNIX from the University of Queensland. More info at:
-
-  [410]http://www.psy.uq.oz.au/~ftp/Crypto/
-
-   Interoperability with C-Kermit is unknown. C-Kermit also includes its
-   own built-in SSL/TLS support, but it is not exportable; [411]CLICK
-   HERE file for details.
-     _________________________________________________________________
-
-    2.7.4.3. SRP
-
-   SRP(TM) is Stanford University's Secure Remote Password protocol. An
-   SRP Telnet client is available from Stanford:
-
-  [412]http://srp.stanford.edu/srp/
-
-   Stanford's SRP Telnet client for UNIX has been tested on SunOS and
-   works fine with C-Kermit, as described in [413]Section 2.7.1, e.g.
-
-  SET PREFIX ALL
-  PTY (or PIPE) srp-telnet xenon.stanford.edu
-
-   C-Kermit itself can be built as an SRP Telnet client on systems that
-   have libsrp.a installed; the C-Kermit support code, however, may not
-   be exported outside the USA or Canada.
-     _________________________________________________________________
-
-    2.7.4.4. SOCKS
-
-   C-Kermit can be built as a SOCKS-aware client on systems that have a
-   SOCKS library. See section 8.1.1 of the [414]ckccfg.txt file.
-
-   C-Kermit 7.0 can also be run over SOCKSified Telnet or rlogin clients
-   with SET NETWORK TYPE COMMAND. Suppose the Telnet program on your
-   system is SOCKS enabled but C-Kermit is not. Make Kermit connections
-   like this:
-
-  SET PREFIX ALL
-  PTY (or PIPE) telnet zzz.com
-     _________________________________________________________________
-
-    2.7.4.5. Kerberos
-
-   UNIX C-Kermit can be built with MIT Kerberos IV or V authentication
-   and encryption. Instructions are available in a [415]separate
-   document. Additional modules are required that can not be exported
-   from the USA to any country except Canada, by US law.
-
-   If you have Kerberos installed but you don't have a Kerberized version
-   of C-Kermit, you can use ktelnet as C-Kermit's external communications
-   program to make secure connections without giving up C-Kermit's
-   services:
-
-  SET PREFIX ALL
-  PTY (or PIPE) ktelnet cia.gov
-     _________________________________________________________________
-
-  2.8. Scripting Local Programs
-
-   If your version of Kermit has PTY support built in, then any
-   text-based program can be invoked with SET HOST /PTY or equivalent
-   command and controlled using the normal sequence of OUTPUT, INPUT, IF
-   SUCCESS commands (this is the same service that is provided by the
-   'expect' program, but controlled by the Kermit script language rather
-   than Tcl).
-
-   When PTY service is not available, then any program that uses standard
-   input and output can be invoked with SET HOST /PIPE.
-
-   Here's an example in which we start an external Kermit program, wait
-   for its prompt, give it a VERSION command, and then extract the
-   numeric version number from its response:
-
-  set host /pty kermit -Y
-  if fail stop 1 {Can't start external command}
-  input 10 C-Kermit>
-  if fail stop 1 {No C-Kermit> prompt}
-  output version\13
-  input 10 {Numeric: }
-  if fail stop 1 {No match for "Numeric:"}
-  clear input
-  input 10 \10
-  echo VERSION = "\fsubstr(\v(input),1,6)"
-  output exit\13
-
-   This technique could be used to control any other interactive program,
-   even those that do screen formatting (like Emacs or Vi), if you can
-   figure out the sequence of events. If your Kermit program doesn't have
-   PTY support, then the commands are restricted to those using standard
-   i/o, including certain shells, interactive text-mode "hardcopy"
-   editors like ex, and so on.
-
-   If you are using the PTY interface, you should be aware that it runs
-   the given program or command directly on the pty, without any
-   intervening shell to interpret metacharacters, redirectors, etc. If
-   you need this sort of thing, include the appropriate shell invocation
-   as part of your command; for example:
-
-  pty echo *
-
-   just echoes "*"; whereas:
-
-  pty ksh -c "echo *"
-
-   echoes all the filenames that ksh finds matching "*".
-
-   Similarly for redirection:
-
-  set host /pty ksh -c "cat > foo"  ; Note: use shell quoting rules here
-  set transmit eof \4
-  transmit bar
-
-   And for that matter, for built-in shell commands:
-
-  set host /pty ksh -c "for i in *; do echo $i; done"
-
-   The PIPE interface, on the other hand, invokes the shell
-   automatically, so:
-
-  pipe echo *
-
-   prints filenames, not "*".
-     _________________________________________________________________
-
-  2.9. X.25 Networking
-
-   X.25 networking is documented in [416]Using C-Kermit, 2nd Edition.
-   When the book was published, X.25 was available only in SunOS,
-   Solaris, and Stratus VOS. Unlike TCP/IP, X.25 APIs are not
-   standardized; each vendor's X.25 libraries and services (if they have
-   them at all) are unique.
-
-   This section describes new additions.
-     _________________________________________________________________
-
-    2.9.1. IBM AIXLink/X.25 Network Provider Interface for AIX
-
-   Support for X.25 was added via IBM's Network Provider Interface (NPI),
-   AIXLink/X.25 1.1, to the AIX 4.x version of C-Kermit 7.0.
-   Unfortunately, AIXLink/X.25 is a rather bare-bones facility, lacking
-   in particular any form of PAD support (X.3, X.28, X.29). Thus, the AIX
-   version of C-Kermit, when built to include X.25 networking, has
-   neither a PAD command, nor a SET PAD command. The same is true for the
-   underlying AIX system: no PAD support. Thus it is not possible to have
-   an interactive shell session over an X.25 connection into an AIX
-   system (as far as we know), even from X.25-capable Kermit versions
-   (such as Solaris or VOS) that do include PAD support.
-
-   Thus the X.25 capabilities in AIX C-Kermit are limited to peer-to-peer
-   connections, e.g. from a C-Kermit client to a C-Kermit server. Unlike
-   the Solaris, SunOS, and VOS versions, the AIX version can accept
-   incoming X.25 connections:
-
-  set network type x.25
-  if fail stop 1 Sorry - no X.25 support
-  ; Put any desired DISABLE or ENABLE or SET commands here.
-  set host /server *
-  if fail stop 1 X.25 "set host *" failed
-
-   And then access it from the client as follows:
-
-  set network type x.25
-  if fail stop 1 Sorry - no X.25 support
-  set host xxxxxxx ; Specify the X.25/X.121 address
-  if fail stop 1 Can't open connection
-
-   And at this point the client can use the full range of client
-   commands: SEND, GET, REMOTE xxx, FINISH, BYE.
-
-   The AIX version also adds two new variables:
-
-   \v(x25local_nua)
-          The local X.25 address.
-
-   \v(x25remote_nua)
-          The X.25 address of the host on the other end of the
-          connection.
-
-   C-Kermit's AIX X.25 client has not been tested against anything other
-   than a C-Kermit X.25 server on AIX. It is not known if it will
-   interoperate with C-Kermit servers on Solaris, SunOS, or VOS.
-
-   To make an X.25 connection from AIX C-Kermit, you must:
-
-  set x25 call-user-data xxxx
-
-   where xxxx can be any even-length string of hexadecimal digits, e.g.
-   123ABC.
-     _________________________________________________________________
-
-    2.9.2. HP-UX X.25
-
-   Although C-Kermit presently does not include built-in support for
-   HP-UX X.25, it can still be used to make X.25 connections as follows:
-   start Kermit and tell it to:
-
-  set prefixing all
-  set parity space
-  pty padem address
-
-   This should work in HP-UX 9.00 and later (see [417]Section 2.7). If
-   you have an earlier HP-UX version, or the PTY interface doesn't work
-   or isn't available, try:
-
-  set prefixing all
-  set parity space
-  pipe padem address
-
-   Failing that, use Kermit to telnet to localhost and then after logging
-   back in, start padem as you would normally do to connect over X.25.
-     _________________________________________________________________
-
-  2.10. Additional Serial Port Controls
-
-   C-Kermit 7.0 adds the following commands for greater control over
-   serial ports. These commands are available only in C-Kermit versions
-   whose underlying operating systems provide the corresponding services
-   (such as POSIX and UNIX System V), and even then their successful
-   operation depends on the capabilities of the specific device and
-   driver.
-
-   SET DISCONNECT { ON, OFF }
-          On a SET LINE or SET PORT connection with SET CARRIER ON or
-          AUTO, if the carrier signal drops during the connection,
-          indicating that the connection has been lost, and C-Kermit
-          notices it, this setting governs what happens next. With SET
-          DISCONNECT OFF, which is consistent with previous behavior, and
-          therefore the default, C-Kermit continues to keep the device
-          open and allocated. With SET DISCONNECT ON, C-Kermit
-          automatically closes and releases the device when it senses a
-          carrier on-to-off transition, thus allowing others to use it.
-          However, it remains the default device for i/o (DIAL, REDIAL,
-          INPUT, SEND, CONNECT, etc), so if a subsequent i/o command is
-          given, the device is reopened if it is still available. When it
-          has been automatically closed in this manner, SHOW
-          COMMUNICATIONS puts "(closed)" after its name, and in UNIX, the
-          lockfile disappears -- both from SHOW COMM and from the
-          lockfile directory itself. Synonym: SET CLOSE-ON-DISCONNECT.
-
-   SET EXIT ON-DISCONNECT { ON, OFF }
-          Like DISCONNECT, but makes the program exit if a connection
-          drops.
-
-   Note that SET CLOSE-ON-DISCONNECT and SET EXIT ON-DISCONNECT apply
-   only to connections that drop; they do not apply to connections that
-   can't be made in the first place. For example, they have no effect
-   when a SET LINE, SET HOST, TELNET, or DIAL command fails.
-
-   HANGUP
-          If [CLOSE-ON-]DISCONNECT is ON, and the HANGUP command is given
-          on a serial device, and the carrier signal is no longer present
-          after the HANGUP command, the device is closed and released.
-
-   SET PARITY HARDWARE { EVEN, ODD }
-          Unlike SET PARITY { EVEN, ODD, MARK, SPACE }, which selects 7
-          data bits plus the indicated kind of parity (to be done in
-          software by Kermit itself), SET PARITY HARDWARE selects 8 data
-          bits plus even or odd parity, to be done by the underlying
-          hardware, operating system, or device driver. This command is
-          effective only with a SET LINE or SET PORT device. That is, it
-          has no effect in remote mode, nor on network connections. There
-          is presently no method for selecting 8 data bits plus mark or
-          space parity. If hardware parity is in effect, the variable
-          \v(hwparity) is set to "even" or "odd". Note: some platforms
-          might also support settings of SPACE, MARK, or NONE.
-
-   SET STOP-BITS { 1, 2 }
-          This tells the number of 1-bits to insert after an outbound
-          character's data and parity bits, to separate it from the next
-          character. Normally 1. Choosing 2 stop bits should do no harm,
-          but will slow down serial transmission by approximately 10
-          percent. Historically, 2 stop bits were used with Teletypes (at
-          110 bps or below) for print-head recovery time. There is
-          presently no method for choosing any number of stop bits
-          besides 1 and 2.
-
-   SET SERIAL [ dps ]
-          dps stands for Data-bits, Parity, Stop-bits. This is the
-          notation familiar to many people for serial port configuration:
-          7E1, 8N1, 7O2, etc. The data bits number also becomes the
-          TERMINAL BYTESIZE setting. The second character is E for Even,
-          O for Odd, M for Mark, S for Space, or N for None. The list of
-          available options depends on the capabilities of the specific
-          platform. If dps is omitted, 8N1 is used. Type "set serial ?"
-          for a list of available choices. Examples:
-
-        SET SERIAL 7E1
-                Equivalent to SET PARITY EVEN, SET STOP-BITS 1, SET TERM
-                BYTE 7.
-
-        SET SERIAL 8N1
-                Equivalent to SET PARITY NONE, SET STOP-BITS 1, SET TERM
-                BYTE 8.
-
-        SET SERIAL 7E2
-                Equivalent to SET PARITY EVEN and SET STOP-BITS 2, SET
-                TERM BYTE 7.
-
-        SET SERIAL 8E2
-                Same as SET PARITY HARDWARE EVEN, SET STOP-BITS 2, SET
-                TERM BYTE 8.
-
-        SET SERIAL
-                Same as SET PARITY NONE and SET STOP-BITS 1, SET TERM
-                BYTE 8.
-
-   Notes:
-
-     * The SET SERIAL xx2 options are available only in Kermit versions
-       where the SET PARITY HARDWARE command is also available. (SHOW
-       FEATURES includes "HWPARITY" in its options list.)
-     * The SET SERIAL 7xx and 8N1 options affect the software parity
-       setting, even for network connections.
-     * As noted in the manual, selecting 8 data bits does not give you
-       8-bit terminal sessions in CONNECT mode unless you also SET
-       TERMINAL BYTESIZE 8. The default terminal bytesize remains 7, to
-       protect against the situation where the remote host is generating
-       parity but you don't know about it. If the terminal bytesize was 8
-       by default and you CONNECTed to such a host, you would see only
-       garbage on your screen.
-     * If you do not give a SET STOP-BITS or SET SET SERIAL command,
-       C-Kermit does not attempt to set the device's stop bits; instead,
-       it uses whatever setting the device uses when not given explicit
-       instructions about stop bits.
-
-   SHOW COMMUNICATIONS displays the current settings. Stop bits and
-   hardware parity are shown only for SET PORT / SET LINE (serial)
-   devices, since they do not apply to network connections or to remote
-   mode. STOP-BITS is shown as "(default)" if you have not given an
-   explicit SET STOP-BITS or SET SERIAL command.
-
-   The \v(serial) variable shows the SET SERIAL setting (8N1, 7E1, etc).
-     _________________________________________________________________
-
-  2.11. Getting Access to the Dialout Device
-
-     This section is for UNIX only; note the special words about QNX at
-     the end. Also see [418]Section 2.0 for SET LINE switches,
-     particularly the /SHARE switch for VMS only.
-
-   C-Kermit does its best to obey the UUCP lockfile conventions of each
-   platform (machine, operating system, OS version) where it runs, if
-   that platform uses UUCP.
-
-   But simply obeying the conventions is often not good enough, due to
-   the increasing likelihood that a particular serial device might have
-   more than one name (e.g. /dev/tty00 and /dev/term/00 are the same
-   device in Unixware 7; /dev/cua and /dev/cufa are the same device in
-   NeXTSTEP), plus the increasingly widespread use of symlinks for device
-   names, such as /dev/modem.
-
-   C-Kermit 7.0 goes to greater lengths than previous versions to
-   successfully interlock with other communications program (and other
-   instances of Kermit itself); for example, by:
-
-     * Creation of dual lockfiles whenever a symlink is used; one for the
-       link name and one for the real name.
-     * Creation of dual lockfiles in HP-UX according to HP rules.
-     * Creation of dual uppercase/lowercase lockfile names in SCO
-       UNIX/ODT/OSR5.
-     * The use of ttylock() in versions of AIX where it works.
-     * The use, wherever possible, of lockfile names based on
-       inode/major/minor device number rather than device name.
-
-   See the [419]ckuins.txt and [420]ckubwr.txt files for details.
-
-   QNX is almost unique among UNIX varieties in having no UUCP programs
-   nor UUCP-oriented dialout-device locking conventions. QNX does,
-   however, allow a program to get the device open count. This can not be
-   a reliable form of locking unless all applications do it (and they
-   don't), so by default, Kermit uses this information only for printing
-   a warning message such as:
-
-  C-Kermit>set line /dev/ser1
-  WARNING - "/dev/ser1" looks busy...
-
-   However, if you want to use it as a lock, you can do so with:
-
-  SET QNX-PORT-LOCK { ON, OFF }
-
-   QNX-PORT-LOCK is OFF by default; if you set in ON, C-Kermit fails to
-   open any dialout device when its open count indicates that another
-   process has it open. SHOW COMM (in QNX only) displays the setting, and
-   if you have a port open, it also shows the current open count (with
-   C-Kermit's own access always counting as 1).
-     _________________________________________________________________
-
-  2.12. The Connection Log
-
-   C-Kermit 7.0 adds the ability to log connections, so you can see where
-   you've been and have a record of calls you've made. A connection is
-   defined as any communications session that is begun by SET LINE, SET
-   PORT, DIAL, SET HOST, TELNET, or RLOGIN. Connections are not logged
-   unless you request it; the command is:
-
-   LOG CX [ filename [ { NEW, APPEND } ] ]
-          Enables logging of connections in the given file. If the
-          trailing { NEW, APPEND } keyword is omitted, the file is opened
-          for appending; i.e. new records are written to the end. If NEW
-          is specified, a new file is created; if a file of the same name
-          already existed, it is overwritten. If the filename is omitted,
-          CX.LOG in your home (login) directory is used (note:
-          uppercase). To accept all defaults, just use "log connections"
-          (or "l c" for short). Synonym: LOG CONNECTIONS.
-
-   CLOSE CX-LOG
-          This closes the connection log if it was open. (Note, the CLOSE
-          CONNECTION command closes the connection itself).
-
-   SHOW CX
-          This shows your current connection, if any, including the
-          elapsed time (since you opened it). Synonym: SHOW CONNECTION.
-
-   \v(cx_time)
-          This variable shows the elapsed time of your current
-          connection, or if there is no current connection, of your most
-          recent connection, of if there have been no connections, 0.
-
-   The connection contains one line per connection, of the form:
-
-  yyyymmdd hh:mm:ss username pid p=v [ p=v [ ... ] ]
-
-   where the timestamp (in columns 1-18) shows when the connection was
-   made; username is the login identity of the person who made the
-   connection; pid is Kermit's process ID when it made the connection.
-   The p's are parameters that depend on the type of connection, and the
-   v's are their values:
-
-  T = Connection Type (TCP, SERIAL, DIAL, DECNET, etc).
-  H = The name of the Host from which the connection was made.
-  N = Destination phone Number or Network host name or address.
-  D = Serial connections only: Device name.
-  O = Dialed calls only: Originating country code & area code if known.
-  E = Elapsed time in hh:mm:ss format (or hhh:mm:ss, etc).
-
-   If you always want to keep a connection log, simply add:
-
-  log connections
-
-   to your C-Kermit customization file. Note, however, that if you make a
-   lot of connections, your CX.LOG will grow and grow. You can handle
-   this by adding a "logrotate" procedure like the following to your
-   customization file, before the "log connections" command:
-
-  define LOGROTATE {                    ; Define LOGROTATE macro
-      local \%i \%m \%d \%n \%f MAX
-      def MAX 4                         ; How many months to keep
-      if not def \%1 -                  ; No argument given
-        end 1 \%0: No filename given
-      if not = 1 \ffiles(\%1) -         ; Exactly 1 file must match
-        end 1 \%0: \%1 - File not found
-      .\%d := \fsubstr(\fdate(\%1),1,6) ; Arg OK - get file year & month
-      if = \%d -                        ; Compare file year & month
-        \fsubstr(\v(ndate),1,6) -       ; with current year & month
-          end 0                         ; Same year & month - done
-      rename \%1 \%1.\%d                ; Different - rename file
-      .\%n := \ffiles(\%1.*)            ; How many old files
-      if < \%n \m(MAX) end 0            ; Not enough to rotate
-      .\%m := \%1.999999                ; Initial compare string
-      for \%i 1 \%n 1 {                 ; Loop thru old logs
-         .\%f := \fnextfile()           ; Get next file name
-         if llt \%f \%m .\%m := \%f     ; If this one older remember it
-      }
-      delete \%m                        ; Delete the oldest one
-  }
-  log connections                       ; Now open the (possibly new) log
-  logrotate \v(home)CX.LOG              ; Run the LOGROTATE macro
-
-   As you can see, this compares the yyyymm portion of the modification
-   date (\fdate()) of the given file (\%1) with the current yyyymm. If
-   they differ, the current file has the yyyymm suffix (from its most
-   recent modification date) appended to its name. Then we search through
-   all other such files, find the oldest one, and delete it. Thus the
-   current log, plus the logs from the most recent four months, are kept.
-   This is all done automatically every time you start C-Kermit.
-
-   On multiuser systems, it is possible to keep a single, shared,
-   system-wide connection log, but this is not recommended since (a) it
-   requires you keep a publicly write-accessible logfile (a glaring
-   target for mischief), and (b) it would require each user to log to
-   that file and not disable logging. A better method for logging
-   connections, in UNIX at least, is syslogging (see [421]ckuins.txt
-   Section 15 and [422]Section 4.2 of the [423]IKSD Administration Guide
-   for details).
-     _________________________________________________________________
-
-  2.13. Automatic Connection-Specific Flow Control Selection
-
-   Beginning in C-Kermit 7.0, the appropriate flow-control method for
-   each connection type is kept in a table, for example:
-
-  Remote:           NONE
-  Modem:            RTS/CTS
-  Direct-Serial:    NONE
-  TCPIP:            NONE
-
-   The size of the table and values for each connection type can vary
-   from platform to platform. Type "set flow ?" for a list of available
-   flow-control types.
-
-   The table is used to automatically select the appropriate kind of flow
-   control whenever you make a connection. You can display the table
-   with:
-
-  SHOW FLOW-CONTROL
-
-   The defaults are as follows:
-
-   Remote:
-          NONE or XON/XOFF. This is because C-Kermit is not allowed to
-          find out what type of connection the incoming user has (*). No
-          kind of flow control will work on every kind of connection,
-          including (unexpectedly) KEEP, which we would have liked to
-          use, but not turning off flow control at the remote end during
-          file transfer on TCP/IP connections is fatal to the transfer
-          (except in VMS and HP-UX, where it must be set to Xon/Xoff!)
-          Therefore if you are dialing in to a serial port on a server
-          (UNIX or VMS) where C-Kermit is running, you will need to tell
-          C-Kermit to "set flow keep" before transferring files (assuming
-          the modem and port are configured correctly by the system
-          administrator; otherwise you'll need to give a specific kind of
-          flow control, e.g. "set flow xon/xoff"), so in this case
-          C-Kermit will not disable flow control, as it must do when you
-          are coming via Telnet (directly or through a terminal server,
-          except on VMS and HP-UX).
-
-   Modem:
-          This applies when you dial out with a modem. In this case, the
-          MODEM FLOW-CONTROL setting takes affect after the SET FLOW
-          setting, so it can pick the most appropriate flow control for
-          the combination of the particular modem and the
-          computer/port/driver that is dialing.
-
-   Direct-Serial:
-          The default here is NONE because C-Kermit has no way of knowing
-          what kind of flow control, if any, is or can be done by the
-          device at the other end of the connection. RTS/CTS would be a
-          bad choice here, because if the CTS signal is not asserted, the
-          connection will hang. And since direct connections are often
-          made with 3-wire cables, there is a good chance the CTS signal
-          will not be received.
-
-   TCPIP:
-          NONE, since TCP and IP provide their own flow control
-          transparently to the application, except in VMS, where Xon/Xoff
-          is the default due to the requirements of the VMS TCP/IP
-          products.
-
-   Other networks:
-          NONE, since networks should provide their flow control
-          transparently to the application.
-
-   (*) This is possibly the worst feature of UNIX, VMS, and other
-   platforms where C-Kermit runs. If C-Kermit was able to ask the
-   operating system what kind of connection it had to the user, it could
-   set up many things for you automatically.
-
-   You can modify the default-flow-control table with:
-
-  SET FLOW-CONTROL /xxx { NONE, KEEP, RTS/CTS, XON/XOFF, ... }
-
-   where "xxx" is the connection type, e.g.
-
-  SET FLOW /REMOTE NONE
-  SET FLOW /DIRECT RTS/CTS
-
-   If you leave out the switch, SET FLOW works as before, choosing the
-   flow control method to be used on the current connection:
-
-  SET FLOW XON/XOFF
-
-   Thus, whenever you make a connection with SET PORT, SET LINE, DIAL,
-   SET HOST, TELNET, RLOGIN, etc, an appropriate form of flow control is
-   selected automatically. You can override the automatic selection with
-   a subsequent SET FLOW command, such as SET FLOW NONE (no switch
-   included).
-
-   The flow control is changed automatically too when you give a SET
-   MODEM TYPE command. For example, suppose your operating system (say
-   Linux) supports hardware flow control (RTS/CTS). Now suppose you give
-   the following commands:
-
-  set line /dev/ttyS2    ; Automatically sets flow to NONE
-  set modem type usr     ; Automatically sets flow to RTS/CTS
-  set modem type rolm    ; Doesn't support RTS/CTS so now flow is XON/XOFF
-
-   IMPORTANT: This new feature tends to make the order of SET LINE/HOST
-   and SET FLOW commands matter, where it didn't before. For example, in
-   VMS:
-
-  SET FLOW KEEP
-  SET LINE TTA0:
-
-   the SET LINE undoes the SET FLOW KEEP command; the sequence now must
-   be:
-
-  SET FLOW /DIRECT KEEP
-  SET LINE TTA0:
-
-   or:
-
-  SET LINE TTA0:
-  SET FLOW KEEP
-     _________________________________________________________________
-
-  2.14. Trapping Connection Establishment and Loss
-
-   If you define a macro called ON_OPEN, it is executed any time that a
-   SET LINE, SET PORT, SET HOST, TELNET, RLOGIN or similar command
-   succeeds in opening a connection. The argument is the host or device
-   name (as shown by SHOW COMMUNICATIONS, and the same as \v(line)). This
-   macro can be used for all sorts of things, like automatically setting
-   connection- or host-specific parameters when the connection is opened.
-   Example:
-
-  def ON_OPEN {
-      switch \%1 {
-        :abccorp.com, set reliable off, break
-        :xyzcorp.com, set receive packet-length 1000, break
-        etc etc...
-      }
-  }
-
-   If you define a macro called ON_CLOSE, it will be executed any time
-   that a SET LINE, SET PORT, SET HOST, TELNET, RLOGIN or any other kind
-   of connection that C-Kermit has made is closed, either by the remote
-   or by a local CLOSE, HANGUP, or EXIT command or other local action,
-   such as when a new connection is opened before an old one was
-   explicitly closed.
-
-   As soon as C-Kermit notices the connection has been closed, the
-   ON_CLOSE macro is invoked at (a) the top of the command parsing loop,
-   or (b) when a connection is closed implicitly by a command such as SET
-   LINE that closes any open connection prior to making a new connection,
-   or (c) when C-Kermit closes an open connection in the act of exiting.
-
-   The ON_CLOSE macro was inspired by the neverending quest to unite
-   Kermit and SSH. In this case using the "tunnel" mechanism:
-
-  def TUNNEL {                                ; \%1 = host to tunnel to
-      local \%p
-      if not def \%1 stop 1
-      assign tunnelhost \%1                   ; Make global copy
-      undef on_close
-      set macro error off
-      close connection                        ; Ignore any error
-      open !read tunnel start \%1
-      read \%p                                ; Get port number
-      if fail stop 1 Tunnel failure: \%1
-      close read
-      if fail stop 1 Tunnel failure: \%1      ; See [424]Section 4.2.8.1
-      assign on_close {                       ; Set up close handler
-          echo Closing tunnel: \m(tunnelhost)
-          !tunnel stop \m(tunnelhost)
-          undef on_close
-      }
-      set host localhost:\%p /telnet
-      if success end 0
-      undef on_close
-      stop 1 Connection failure: \%1
-  }
-
-   In this case, when the connection stops, we also need to shut down the
-   tunnel, even if it is at a later time after TUNNEL has finished
-   executing. This way we can escape back, reconnect, transfer files, and
-   so on until the connection is broken by logging out from the remote,
-   or by explicitly closing it, or by EXITing from C-Kermit, at which
-   time the tunnel is shut down.
-
-   When the connection is closed, no matter how, the ON_CLOSE macro
-   executes and then undefines (destroys) itself, since we don't want to
-   be closing tunnels in the future when we close subsequent connections.
-
-   Other such tricks can be imagined, including ending ON_CLOSE with a
-   STOP command to force the command stack to be peeled all the way back
-   to the top, for example in a deeply nested script that depends on the
-   connection being open:
-
-  def on_close { stop 1 CONNECTION LOST }
-
-   When C-Kermit invokes the ON_CLOSE macro, it supplies one argument
-   (\%1): the reason the connection was closed as a number, one of the
-   following:
-
-  2 - Fatal failure to negotiate a required item on a network connection.
-  1 - Closed by C-Kermit command.
-  0 - All others (normally closed by remote).
-
-   which may be used for any purpose; for example, to add a comment to
-   the connection log:
-
-  def on_close {
-      local \%m
-      if not open cx end 0
-      switch \%1 {
-        :0, .\%m = Closed by remote, break
-        :1, .\%m = Closed by me, break
-        :2, .\%m = Network protocol negotiation failure, break
-      }
-      if def \%m writeln cx {# \%m}
-  }
-     _________________________________________________________________
-
-  2.15. Contacting Web Servers with the HTTP Command
-
-   C-Kermit 7.0 (at this writing, the UNIX version only) supports direct
-   contact and interaction with Web servers via HTTP 1.0 protocol. To
-   make a connection, use Kermit's normal method for making a TCP/IP
-   connection, but specify the HTTP port:
-
-  SET HOST host http [ switches ]
-
-   where host is the IP hostname or address, and http is the name of the
-   TCP port for the Web server. Relevant switches include:
-
-   /RAW
-          Treat the connection as a transparent binary pipe. This switch
-          may be required if a port other than 'http' is used.
-
-   /SSL
-          Make an secure private connection with SSL (only if SSL support
-          is included in your version of Kermit). In this case the port
-          name might need to be https rather than http, e.g. "set host
-          secureserver.xyxcorp.com https /ssl".
-
-   /TLS
-          Make an secure private connection with TLS (only if TLS support
-          is included in your version of Kermit). In this case the port
-          name would be https rather than http.
-
-   Then you can issue an HTTP command. In most cases, the server closes
-   the connection when the command is complete. Example:
-
-  SET HOST www.columbia.edu http
-  IF FAIL EXIT 1 Can't contact server
-  HTTP GET kermit/index.html
-
-   At this point the connection is closed, since that's how HTTP 1.0
-   works. If you want to perform additional operations, you must
-   establish a new connection with another SET HOST command.
-
-   The HTTP command acts as a client to the Web server, except instead of
-   displaying the results like a Web browser would, it stores them. Any
-   HTTP command can (but need not) include any or all of the following
-   switches:
-
-   /AGENT:user-agent
-          Identifies the client to the server; "C-Kermit" or "Kermit-95"
-          by default.
-
-   /HEADER:header-line
-          Used for specifying any optional headers. A list of headers is
-          provided using braces for grouping:
-
-  /HEADER:{{tag:value}{tag:value}...}
-
-          For a listing of valid tag value and value formats see [425]RFC
-          1945: Hypertext Transfer Protocol -- HTTP/1.0. A maximum of
-          eight headers may be specified.
-
-   /USER:name
-          In case a page requires a username for access.
-
-   /PASSWORD:password
-          In case a page requires a password for access.
-
-   /ARRAY:arrayname
-          Tells Kermit to store the response headers in the given array,
-          one line per element. The array need not be declared in
-          advance. Example:
-
-  C-Kermit? http /array:c get kermit/index.html
-  C-Kermit? show array c
-  Dimension = 9
-  1. Date: Fri, 26 Nov 1999 23:12:22 GMT
-  2. Server: Apache/1.3.4 (Unix)
-  3. Last-Modified: Mon, 06 Sep 1999 22:35:58 GMT
-  4. ETag: "bc049-f72-37d441ce"
-  5. Accept-Ranges: bytes
-  6. Content-Length: 3954
-  7. Connection: close
-  8. Content-Type: text/html
-
-   As you can see, the header lines are like MIME e-mail header lines:
-   identifier, colon, value. The /ARRAY switch is the only method
-   available to a script to process the server responses for a POST or
-   PUT command.
-
-   The HTTP commands are:
-
-   HTTP [ switches ] GET remote-filename [ local-filename ]
-          Retrieves the named file. If a local-filename is given, the
-          file is stored locally under that name; otherwise it is stored
-          with its own name.
-
-   HTTP [ switches ] HEAD remote-filename local-filename
-          Like GET except without actually getting the file; instead it
-          gets only the headers, storing them into the given file, whose
-          name must be given, one line per header item, as shown above in
-          the /ARRAY: switch description.
-
-   HTTP [ switches ] INDEX remote-directory [ local-filename ]
-          Retrieves the file listing for the given server directory.
-          NOTE: This command is not supported by most Web servers.
-
-   HTTP [ switches ] POST [ /MIME-TYPE:type ] local-file remote-file
-          Used to send a response as if it were sent from a form. The
-          data to be posted must be read from a file.
-
-   HTTP [ switches ] PUT [ /MIME-TYPE:type ] local-file remote-file
-          Uploads a local file to a server file.
-
-   HTTP [ switches ] DELETE remote-filename
-          Instructs the server to delete the specified filename.
-     _________________________________________________________________
-
-  3. TERMINAL CONNECTION
-
-  3.1. CONNECT Command Switches
-
-   The following switches (see [426]Section 1.5) were added to the
-   CONNECT command in 7.0:
-
-   /QUIETLY
-          Don't print the "Connecting to..." or "Back at..." messages. CQ
-          is an invisible command synonym for CONNECT /QUIETLY.
-
-   /TRIGGER:string
-          Specify a trigger or triggers ([427]Section 3.2) effective for
-          this CONNECT command only, temporarily overriding any current
-          SET TERMINAL TRIGGER values ([428]Section 3.2).
-
-   Note: Other switches might also be available; type "connect ?" for a
-   list, "help connect" for a description of each.
-     _________________________________________________________________
-
-  3.2. Triggers
-
-   Triggers were added for UNIX, VMS, AOS/VS, and K95 in C-Kermit 7.0.
-
-   SET TERMINAL TRIGGER string
-          Tells C-Kermit to look for the given string during all
-          subsequent CONNECT sessions, and if seen, to return to command
-          mode automatically, as if you had escaped back manually. If the
-          string includes any spaces, you must enclose it in braces.
-          Example:
-
-  set terminal trigger {NO CARRIER}
-
-   Comparisons are made after character-set translation.
-
-   If a string is to include a literal brace character, precede it with a
-   backslash:
-
-  ; My modem always makes this noise when the connection is lost:
-  set terminal trigger |||ppp\{\{\{\{UUUUUUU
-
-   If you want Kermit to look for more than one string simultaneously,
-   use the following syntax:
-
-  set terminal trigger {{string1}{string2}...{stringn}}
-
-   In this case, C-Kermit will return to command mode automatically if
-   any of the given strings is encountered. Up to 8 strings may be
-   specified.
-
-   If the most recent return to command mode was caused by a trigger, the
-   new variable, \v(trigger), shows the trigger value; otherwise
-   \v(trigger) is empty.
-
-   The SHOW TRIGGER command displays the SET TERMINAL TRIGGER values as
-   well as the \v(trigger) value.
-     _________________________________________________________________
-
-  3.3. Transparent Printing
-
-   As noted in the manual, C-Kermit's CONNECT command on UNIX is not a
-   terminal emulator, but rather a "semitransparent pipe" between the
-   terminal or emulator you are using to access C-Kermit, and the remote
-   host to which C-Kermit is connected. The "semitransparent" qualifier
-   is because of character-set translation as well as several actions
-   taken by the emulator in response to the characters or strings that
-   pass through it, such as APCs, Kermit packets (autodownload),
-   triggers, etc.
-
-   The UNIX version of C-Kermit 7.0 adds another such action: Transparent
-   printing, also called Controller printing (as distinct from Autoprint
-   or line or screen print). It is intended mainly for use on UNIX
-   workstation consoles (as opposed to remote logins), but with some care
-   can also be used when accessing C-Kermit remotely.
-
-   Transparent printing is related to APC by sharing C-Kermit's built-in
-   ANSI escape-sequence parser to detect "printer on" and "printer off"
-   sequences from the host. When the printer-on sequence is received, all
-   subsequent arriving characters -- including NUL, control characters,
-   and escape sequences -- are sent to the SET PRINTER device instead of
-   to your screen until the printer-off sequence is received, or you
-   escape back, whichever happens first. These bytes are not translated
-   or modified or filtered in any way by Kermit (except for possibly
-   stripping of the 8th bit, as noted below), but if filtering or
-   translation is desired, this can be accomplished by your SET PRINTER
-   selection (e.g. by choosing a pipeline of filters).
-
-   By default, your SET PRINTER device is your default UNIX printer, but
-   it can also be a file, a command, or the null device (which causes all
-   printer material to be discarded). See [429]Using C-Kermit, 2nd Ed.,
-   p.41 for details.
-
-   Transparent printing is controlled by the command:
-
-   SET TERMINAL PRINT { ON, OFF }
-          When ON, transparent-print sequences are obeyed, and printing
-          occurs on the system where C-Kermit is running. When OFF,
-          transparent print sequences are ignored and passed through to
-          your actual terminal or emulator, along with the data they
-          enclose. OFF is the default, for compatibility with earlier
-          C-Kermit releases. As noted in the manual, when the current SET
-          PRINTER device is a file, transparent-print material is
-          appended to it; the file is not overwritten.
-
-   SET TERMINAL BYTESIZE { 7, 8 }
-   SET PARITY { EVEN, ODD, MARK, SPACE, NONE }
-          If the terminal bytesize is 7, or PARITY is not NONE, the 8th
-          bit of each byte is stripped prior to printing.
-
-   The transparent-print escape sequences are:
-
-   <ESC>[5i
-          Printer On. Send all subsequent incoming bytes to the printer
-          without any kind of filtering, translation, or alteration.
-          Note: <ESC> stands for ASCII character number 27 (decimal),
-          Escape.
-
-   <ESC>[4i
-          Printer Off. Resume displaying incoming bytes on the screen.
-
-   These are the same sequences used by DEC VT100 and higher terminals
-   and other ANSI X3.64 and ISO 6429 compatible terminals. There is no
-   provision for selecting other printer-control sequences.
-
-   Restrictions:
-
-    1. You must SET TERM TRANSPARENT-PRINT ON before you can use this
-       feature.
-    2. Only the 7-bit forms of the escape sequences are supported. The
-       8-bit CSI C1 control is not recognized.
-    3. Autoprint is not supported, since this requires a full-fledged
-       terminal emulator with direct access to the screen.
-    4. The start-print and stop-print sequences pass through to the
-       screen (there is no way to avoid this without causing unacceptable
-       delays or deadlocks in CONNECT mode). Thus if your terminal or
-       emulator also supports transparent printing via these same
-       sequences, an empty file will be sent to its printer. Normally
-       this has no effect.
-
-   Point (4) is similar to the situation with autodownload and APC --
-   when you have several Kermit clients in a chain, you should take care
-   that these features are enabled in only one of them.
-
-   Example 1:
-
-  set printer {|lpr -Plaser}  ; Specify the printer (if not default).
-  set term print on           ; Enable transparent printing.
-  set term byte 8             ; Enable 8-bit characters.
-  connect                     ; Enter CONNECT mode.
-
-   Example 2:
-
-  set printer /home/users/olga/printer.log  ; Send printer material to a file.
-
-   Example 3:
-
-  set printer {| grep -v ^Received | lpr}   ; Filter out some lines
-
-   Then use "pcprint" or "vtprint" commands on the host to initiate
-   transparent print operations. See [430]Using C-Kermit, 2nd Ed., p.406
-   for details.
-
-   Here is a sample "pcprint" shell script for UNIX:
-
-  #!/bin/sh
-  echo -n '<ESC>[5i'
-  if [ $# -eq 0 ]; then
-    cat
-  else
-    cat $*
-  fi
-  echo -n '<FF><ESC>[4i'
-  # (end)
-
-   (Replace "<ESC>" by the actual ASCII Escape character and "<FF>" by
-   the ASCII Formfeed character).
-
-   If you always want transparent printing enabled, put "set term print
-   on" in your C-Kermit customization file (~/.mykermrc in UNIX). The
-   "set term bytesize" selection, however, is a property of each separate
-   connection.
-     _________________________________________________________________
-
-  3.4. Binary and Text Session Logs
-
-   C-Kermit 7.0 corrects an oversight in earlier releases, in which
-   binary session logs (SET SESSION-LOG BINARY) translated character sets
-   and performed various formatting transformations (e.g. "newline mode")
-   before writing characters to the session log. In C-Kermit 7.0,
-   binary-mode session logging writes characters as they come in, before
-   anything (other that parity-bit stripping) is done to them. Text-mode
-   session logging records the characters after processing.
-     _________________________________________________________________
-
-  4. FILE TRANSFER
-
-   Every file is transferred either in text mode (which implies
-   record-format and character-set translation) or binary mode (in which
-   each byte is sent literally without any kind of conversion). The mode
-   in which a file is transferred is controlled by (a) the default mode,
-   in the absence of any other indications; (b) the SET FILE TYPE
-   command; (c) various automatic mechanisms based on client/server
-   negotiations, directory information or filename patterns, etc.
-
-   The default FILE TYPE was changed from TEXT to BINARY in C-Kermit 7.0
-   because:
-
-     * Transferring a text file in binary mode does less damage than
-       transferring a binary file in text mode.
-     * Only binary-mode transfers can be recovered from the point of
-       failure.
-     * The automatic transfer-mode mechanisms switch to text mode on a
-       per-file basis anyway, so only those files that are not covered by
-       the automatic mechanisms are affected.
-     * All file transfers on the Web are done in binary mode, so people
-       are accustomed to it and expect it.
-     _________________________________________________________________
-
-  4.0. BUG FIXES, MINOR CHANGES, AND CLARIFICATIONS
-
-    4.0.0. Filenames with Spaces
-
-   Filenames that contain spaces are a major nuisance to a program like
-   Kermit, whose command language is line- and word-oriented, in which
-   words are separated by spaces and a filename is assumed to be a
-   "word". In general (unless noted otherwise in the description of a
-   particular command), there is only one way to refer to such files in
-   Kermit commands, and that is to enclose the name in braces:
-
-  send {this file}
-
-   Tells Kermit to send the file whose name is "this file" (two words, no
-   quotes). Of course, various circumlocutions are also possible, such
-   as:
-
-  define \%a this file
-  send \%a
-
-   BUT, perhaps contrary to expectation, you can't use "\32" to represent
-   the space:
-
-  send this\32file
-
-   does not work. Why? Because the Kermit parser, which must work on many
-   operating systems including Windows, has no way of knowing what you
-   mean by "this\32file". Do you mean a file whose name is "this file" in
-   the current directory? Or do you mean a file whose name is "32file" in
-   the "this" subdirectory of the current directory? Guessing won't do
-   here; Kermit must behave consistently and deterministically in all
-   cases on all platforms.
-
-   Note that you can't use Esc or Tab within {...} for filename
-   completion, or question mark to get a filename list. However, you can
-   include wildcards; for example:
-
-  send {* *}
-
-   sends all files whose name contains a space.
-
-   All things considered, it is best to avoid spaces in file and
-   directory names if you can. Also see [431]Section 5.4 on this topic.
-     _________________________________________________________________
-
-    4.0.1. Packet out of Window
-
-   C-Kermit 6.0 could send packets "out of window" if the window size was
-   greater than 1 and ACKs had arrived out of order. Fixed in 6.1.
-     _________________________________________________________________
-
-    4.0.2. MOVE after ADD SEND-LIST
-
-   ADD SEND-LIST followed by MOVE did not delete original files; fixed in
-   6.1. Carrier loss was not detected during transfer; in 7.0 C-Kermit
-   checks for this (but results can not be guaranteed). In any case, the
-   protocol will eventually time out if the connection is lost.
-     _________________________________________________________________
-
-    4.0.3. GET and RECEIVE As-Names
-
-   In 5A(190) through 6.0.192, the GET and RECEIVE as-name did not
-   properly override the RECEIVE PATHNAMES setting. In 7.0 it does.
-     _________________________________________________________________
-
-    4.0.4. New Brief Statistics Listing
-
-   Version 7.0 adds a /BRIEF switch to the STATISTICS command, to display
-   a short file-transfer statistics report. /BRIEF is now the default.
-   Use /VERBOSE to see the full display, which is about 25 lines long.
-     _________________________________________________________________
-
-    4.0.5. Improved FAST Command
-
-   The preinstalled definition of the FAST macro did not take enough
-   factors into account. Now it sets packet lengths and window sizes
-   appropriate to the configuration. Furthermore, in IRIX only, it might
-   restrict the SEND packet length to 4000, to work around a bug in the
-   IRIX Telnet server, depending on the IRIX version (see
-   [432]ckubwr.txt, IRIX section). To see the built-in definition of the
-   FAST macro, type "show macro fast". To change it, simply define it to
-   be whatever you want -- it's just a macro, like any other.
-     _________________________________________________________________
-
-    4.0.6. The SET SEND BACKUP Command
-
-   Version 7.0 adds SET SEND BACKUP { ON, OFF }. This tells whether
-   backup files should be sent. Backup files are the ones created by
-   Kermit (and EMACS, and possibly other applications) to preserve old
-   copies of files when creating new ones with the same name. Kermit does
-   this when receiving a file and its FILE COLLISION setting is BACKUP
-   (or RENAME, in which case it the new file gets the backup name). On
-   most platforms, the backup name is formed by adding:
-
-  .~n~
-
-   to the end of the filename, where "n" is a number. For example, if the
-   original file is oofa.txt, a backup file might be called:
-
-  oofa.txt.~1~
-
-   (or oofa.txt.~2~, etc). If you SET SEND BACKUP OFF, this tells Kermit
-   not to send files that have backup names. Normally, SET SEND BACKUP is
-   ON (as shown by SHOW PROTOCOL), and backup files are sent if their
-   names match the SEND file specification.
-
-   Also see PURGE, SET FILE COLLISION, SEND /NOBACKUP, DIRECTORY
-   /[NO]BACKUP.
-     _________________________________________________________________
-
-    4.0.7. The SET { SEND, RECEIVE } VERSION-NUMBERS Command
-
-   VMS Only. Normally when sending files, VMS C-Kermit strips the version
-   number. For example, if the file is FOO.BAR;34, the name is sent as
-   FOO.BAR (without the ";34"). If you want to keep version numbers on
-   when sending files, use SET SEND VERSION-NUMBERS ON. The effect
-   depends on the receiver.
-
-   Normally when receiving files, and an incoming filename includes a
-   VMS-style version number (such as FOO.BAR;34) VMS C-Kermit strips it
-   before trying to create the new file; this way the new file receives
-   the next highest version number in the customary manner for VMS. If
-   you want version numbers on incoming filenames to be used in creating
-   the new files, use SET RECEIVE VERSION-NUMBERS ON.
-
-   Normally these commands would be effective only when VMS C-Kermit is
-   exchanging files with a non-VMS Kermit program, since VMS-to-VMS
-   transfers use labeled mode unless you have gone out of your way to
-   defeat it.
-
-   Example: You want to send all versions of all files in the current
-   directory from a VMS C-Kermit client to a UNIX C-Kermit server. Use:
-
-  set send version-numbers on
-  send *.*;*
-
-   The resulting Unix files will have VMS-style version numbers as part
-   of their name, for example "foo.bar;1", "foo.bar;2", etc.
-
-   Now suppose you want to send these files from Unix to another VMS
-   system and preserve the version numbers. Again we have a Unix C-Kermit
-   server and VMS C-Kermit client. Give these commands to the client:
-
-  set receive version-numbers on
-  get *
-     _________________________________________________________________
-
-    4.0.8. The SET { SEND, RECEIVE } { MOVE-TO, RENAME-TO } Commands
-
-   These commands are persistent global versions of the /MOVE-TO: and
-   /RENAME-TO: switches of the SEND, GET, and RECEIVE commands. They
-   should normally be used only when setting up a dedicated
-   transaction-processing application, in which each file is to be moved
-   or renamed immediately after, and only if, it is transferred
-   successfully, so that (for example) an independent, concurrent process
-   can notice when new files appear and process them immediately without
-   having to guess whether they are complete.
-     _________________________________________________________________
-
-    4.0.9. SET FILE INCOMPLETE AUTO
-
-   SET FILE INCOMPLETE { KEEP, DISCARD }, which tells whether to keep or
-   discard incompletely received files, has a new option, AUTO, which is
-   also the default. It means KEEP the incomplete file if the transfer is
-   in binary mode, otherwise DISCARD it. This reduces the chances that a
-   subsequent recovery operation (RESEND, REGET, etc) could produce a
-   corrupt file, since recovery works only for binary-mode transfers.
-     _________________________________________________________________
-
-  4.1. FILE-TRANSFER FILENAME TEMPLATES
-
-   File-transfer filename templates allow files to be renamed
-   automatically by the file sender, the receiver, or both, during
-   transfer of groups of files.
-
-    4.1.1. Templates in the As-Name
-
-   Prior to C-Kermit 6.1 and Kermit 95 1.1.12 the only options that could
-   be used to affect the names of files being transferred were SET
-   FILENAMES { LITERAL, CONVERTED } and SET { SEND, RECEIVE } PATHNAMES {
-   ON, OFF }, plus the "as-name" feature of the SEND (MOVE, etc) and
-   RECEIVE commands.
-
-   Previously, the as-name could be used only for a single file. For
-   example:
-
-  SEND FOO BAR
-
-   would send the file FOO under the name BAR, but:
-
-  SEND *.TXT anything
-
-   was not allowed, since it would give the same name to each file that
-   was sent. When receiving:
-
-  RECEIVE FOO
-
-   would rename the first incoming file to FOO before storing it on the
-   disk, but subsequent files would not be renamed to FOO, since this
-   would result in overwriting the same file repeatedly. Instead, they
-   were stored under the names they arrived with.
-
-   Beginning in C-Kermit 6.1 and Kermit 95 1.1.12, it is possible to
-   specify as-names in SEND, RECEIVE, and related commands even for file
-   groups. This is accomplished by using replacement variables in the
-   as-name, along with optional material such character-string functions
-   and/or constant strings. An as-name containing replacement variables
-   is called a filename template.
-
-   The key to filename templates is the new variable:
-
-  \v(filename)
-
-   During file transfer it is replaced by the name of each file currently
-   being transferred (after transfer, it is the name of the last file
-   transferred).
-
-   So, for example:
-
-  send *.txt \v(filename).new
-
-   sends each file with its own name, but with ".new" appended to it. Of
-   course if the name already contains periods, this could confuse the
-   file receiver, so you can also achieve fancier effects with
-   constructions like:
-
-  send *.txt \freplace(\v(filename),.,_).new
-
-   which replaces all periods in the original filename by underscores,
-   and then appends ".new" to the result. So, for example, oofa.txt would
-   be sent as oofa_txt.new.
-
-   Another new variable that is useful in this regard is \v(filenumber),
-   which is the ordinal number of the current file in the file group, so
-   you can also:
-
-  send *.txt FILE\flpad(\v(filenum),2,0)
-
-   resulting in a series of files called FILE00, FILE01, FILE02, etc. (At
-   the end of the transfer, \v(filenum) tells the number of files that
-   were transferred).
-
-   If you specify a constant as-name when sending a file group:
-
-  send *.txt thisnameonly
-
-   Kermit complains and asks you to include replacement variables in the
-   as-name. You should generally use \v(filename) or \v(filenumber) for
-   this purpose, since other variables (with the possible exception of
-   date/time related variables) do not change from one file to the next.
-   But Kermit accepts any as-name at all that contains any kind of
-   variables for file group, even if the variable will not change. So:
-
-  send *.txt \%a
-
-   is accepted, but all files are sent with the same name (the value of
-   \%a, if it has one and it is constant). If the variable has no value
-   at all, the files are sent under their own names.
-
-   Of course, the value of \%a in the previous example need not be
-   constant:
-
-  define \%a FILE\flpad(\v(filenum),2,0)_at_\v(time)
-  send *.txt \%a
-
-   The RECEIVE command, when given without an as-name, behaves as always,
-   storing all incoming files under the names they arrive with, subject
-   to SET FILE NAME and SET RECEIVE PATHNAMES modifications ([433]Section
-   4.10).
-
-   However, when an as-name is given in the RECEIVE command, it is
-   applied to all incoming files rather than to just the first. If it
-   does not contain replacement variables, then the current FILE
-   COLLISION setting governs the result. For example:
-
-  receive foo
-
-   will result in incoming files named foo, foo.~1~, foo.~2~, and so on,
-   with the default FILE COLLISION setting of BACKUP. If it does contain
-   replacement variables, of course they are used.
-
-   When receiving files, the \v(filename) variable refers to the name
-   that was received in the incoming file-header packet, BEFORE any
-   processing by SET FILE NAMES or SET RECEIVE PATHNAMES. Since the
-   filenames in file-header packets are usually in uppercase, you would
-   need to convert them explicitly if you want them in lowercase, e.g.:
-
-  receive \flower(\v(filename)).new
-     _________________________________________________________________
-
-    4.1.2. Templates on the Command Line
-
-   On the command-line, use templates as shown above as the -a option
-   argument, bearing in mind the propensity of UNIX and perhaps other
-   shells to treat backslash as a shell escape character. So in UNIX (for
-   example):
-
-  kermit -s oofa.* -a x.\\v(filenum)
-
-   By the way, this represents a change from 6.0 and earlier releases in
-   which the as-name (-a argument or otherwise) was not evaluated by the
-   command parser. Thus, for example, in VMS (where the shell does not
-   care about backslashes), it was possible to:
-
-  kermit -s oofa.txt -a c:\tmp\oofa.txt
-
-   Now backslashes in the as-name must be quoted not only for the shell
-   (if necessary) but also for Kermit itself:
-
-  kermit -s oofa.txt -a c:\\tmp\\oofa.txt      ; Kermit only
-  kermit -s oofa.txt -a c:\\\\tmp\\\\oofa.txt  ; Shell and Kermit
-
-   You can also use the \fliteral() function for this:
-
-  kermit -s oofa.txt -a \fliteral(c:\tmp\oofa.txt)      ; Kermit only
-  kermit -s oofa.txt -a \\fliteral(c:\\tmp\\oofa.txt)   ; Shell and Kermit
-     _________________________________________________________________
-
-    4.1.3. Post-Transfer Renaming
-
-   Filename templates are now also useful in SET { SEND, RECEIVE }
-   RENAME-TO and in the /RENAME-TO: switch, that can be given to the
-   SEND, GET, or RECEIVE commands; this is similar to an as-name, but is
-   effective on a per-file basis if and only if the file was transferred
-   successfully.
-
-   MOVE-TO and RENAME-TO address a requirement commonly stated for
-   transaction processing and similar systems. Suppose, for example, a
-   central system "X" accepts connections from multiple clients
-   simultaneously; a process on X waits for a file to appear and then
-   processes the file. This process must have a way of knowing when the
-   file has been completely and successfully transferred before it starts
-   to process it. This can be accomplished easily using C-Kermit's SET {
-   SEND, RECEIVE } { MOVE-TO, RENAME-TO } command or /MOVE-TO: or
-   /RENAME-TO: switches, described in [434]Sections 4.7.1 through
-   [435]4.7.3.
-
-   Here's an example for the client side, in which files to be sent are
-   placed in a certain directory (/usr/olga/tosend in this example) by
-   another process when they are ready to go. This might be in a hospital
-   or big doctor's office, where medical insurance claims are entered at
-   a number of workstations, and then deposited in the "tosend"
-   directory, from which they are sent to a claims clearinghouse. We
-   assume the connection is already made and a Kermit server is on the
-   other end.
-
-  local srcdir findir              ; Declare local (automatic) variables
-  assign srcdir /usr/olga/tosend   ; Local source directory (files to send)
-  assign findir /usr/olga/sent     ; Where to move files after they are sent
-  log transactions                 ; Keep a log of transfers
-  cd \m(srcdir)                    ; Change to the source directory
-  while true {                     ; Loop forever...
-      send /move-to:\m(findir) *   ; Send all files
-      sleep 60                     ; Sleep a minute
-  }                                ; Go back and do it again
-
-   Note how simple this is. Once each file is sent, it is moved so it
-   won't be sent again (you could also use SEND /RENAME-TO: or even SEND
-   /DELETE). If a transfer fails, the file is not moved and so we try
-   again to send it next time around. If there are no files to send, the
-   SEND command does nothing but a message is printed; you can avoid the
-   message by checking first to see if any files are in the directory:
-
-  while true {                     ; Loop forever...
-      if > \ffiles(*) 0 -          ; If there are any files
-        send /move-to:\m(findir) * ; send them.
-      sleep 60                     ; Sleep a minute.
-  }                                ; Go back and do it again.
-
-   It's even simpler on the server side (here again we assume the
-   connection is already in place):
-
-  local rcvdir findir              ; Declare local (automatic) variables
-  assign rcvdir /usr/ivan/tmp      ; Temporary receiving directory
-  assign findir /usr/ivan/new      ; Where to move files after reception
-  log transactions                 ; Keep a log of transfers
-  cd \m(rcvdir)                    ; Change to the source directory
-  set receive move-to \m(findir)   ; Declare move-to directory.
-  server                           ; Enter server mode.
-
-   A separate process (e.g. the medical claim-form decoder) can look for
-   files appearing in the /usr/ivan/new directory and process them with
-   every confidence that they have been completely received.
-
-   Note that the use of MOVE-TO can result in moved files overwriting one
-   another (the application would normally avoid this by assigning each
-   transaction a unique, e.g. based on customer number and claim number).
-   But if filename collisions are a possibility in your application,
-   RENAME-TO might be a better choice; you can use any variables you like
-   in the template to ensure uniqueness of the RENAME-TO filename; for
-   example:
-
-  SET RECEIVE RENAME-TO \v(filename)_\v(ndate)_\v(ntime)_\v(userid)_\v(pid)
-     _________________________________________________________________
-
-  4.2. FILE-TRANSFER PIPES AND FILTERS
-
-    4.2.1. INTRODUCTION
-
-   Beginning in C-Kermit 6.1 and Kermit 95 1.1.12, it is possible to send
-   from a command, or "pipe", as well as from a file, and to receive to a
-   pipe or command. In a typical example, we might want to transfer an
-   entire directory tree from one UNIX system to another (but without
-   using the methods described in [436]Sections 4.3 , [437]4.10,
-   [438]4.11, and [439]4.15). We could do this in multiple steps as
-   follows:
-
-  1. Create a tar archive of the desired directory tree
-  2. Compress the tar archive
-  3. Transfer it in binary mode to the other computer
-  4. Decompress it
-  5. Extract the directory tree from the tar archive
-
-   But this is inconvenient and it requires a temporary file, which might
-   be larger than we have room for.
-
-   The new pipe-transfer feature lets you do such things in a single
-   step, and without intermediate files.
-
-   Additional new features, also discussed here, let you specify pre- and
-   post- processing filters for outbound and incoming files, and give you
-   a way to insert the output from shell or system commands into C-Kermit
-   commands.
-
-   The file-transfer related features are available only with Kermit
-   protocol, not with any external protocols, nor with K95's built-in
-   XYZMODEM protocols (because XYZMODEM recovers from transmission errors
-   by rewinding the source file, and you can't rewind a pipe).
-
-   This section begins by discussing the simple and straightforward use
-   of these features in UNIX, in which pipes and input/output redirection
-   are a fundamental component and therefore "just work", and then goes
-   on to discuss their operation in Windows and OS/2, where matters are
-   much more complicated.
-     _________________________________________________________________
-
-    4.2.1.1. TERMINOLOGY
-
-   Standard Input
-          This is a precise technical term denoting the normal source of
-          input for a command or program, which is the keyboard of your
-          terminal by default, but which can be redirected to a file or
-          pipe.
-
-   Stdin
-          Abbreviation for Standard Input.
-
-   Standard Output
-          A precise technical term denoting the normal destination for
-          output from a command or program, which is your terminal screen
-          by default, but which can be redirected to a file.
-
-   Stdout
-          Abbreviation for Standard Output.
-
-   Stdio
-          Abbreviation for Standard Input / Standard Output.
-
-   I/O
-          Abbreviation for Input / Output.
-
-   Shell
-          Text-based system command processor, such as the UNIX shell,
-          DOS COMMAND.COM, etc.
-
-   Pipe
-          A mechanism by which the standard output of one program is sent
-          to the standard input of another.
-
-   Pipeline
-          A series of programs connected by pipes.
-     _________________________________________________________________
-
-    4.2.1.2. NOTATION
-
-   In command descriptions, "command" is replaced by a shell or system
-   command or pipeline. The command names specified in these commands are
-   interpreted by your shell, just as if you were typing them at the
-   shell prompt, and so if they are in your PATH, they will be found in
-   the expected manner. Therefore you don't have to specify complete
-   pathnames for commands that are programs (but it shouldn't hurt if you
-   do).
-
-   The normal notation for I/O redirection is as follows:
-
-  <  Read Stdin from the given file.
-  >  Send Stdout to the given file.
-  |  Send Stdout from the command on the left to the command on the right.
-
-   Examples:
-
-   sort < foo > bar
-          Sorts the lines in file "foo" and writes the results to file
-          "bar"
-
-   grep -c "some text" *.txt | grep -v ":0" | sort | pr -3 | lpr
-          This is a command pipeline composed of 5 commands:
-
-   grep -c "some text" *.txt
-          Looks in all files whose names end with ".txt" for the string
-          "some text" and writes to Stdout the names of each file
-          followed by a colon and the number of occurrences in each.
-
-   grep -v ":0"
-          Prints to Stdout the lines from Stdin that do NOT contain the
-          string ":0", in this case, it removes the names of files that
-          do not contain "some text".
-
-   sort
-          Sorts the lines from Stdin alphabetically to Stdout.
-
-   pr -3
-          Arranges the lines from Stdin in three columns.
-
-   lpr
-          Prints its Stdin on the default printer.
-
-   Note that the Kermit features described here work only with commands
-   that use Stdio. If you attempt to use them with commands whose input
-   and output can not be redirected, Kermit will most likely get stuck.
-   Kermit has no way of telling how an external command works, nor what
-   the syntax of the shell is, so it's up to you to make sure you use
-   these features only with redirectable commands.
-
-   The quoting rules of your shell apply to the command. Thus in UNIX,
-   where C-Kermit tries to use your preferred shell for running commands,
-   shell "metacharacters" within commands must be escaped if they are to
-   be taken literally, using the methods normal for your shell. For
-   example, the UNIX tr (translate) command must have its arguments in
-   quotes:
-
-  tr "[a-z]" "[A-Z]"
-
-   otherwise the shell is likely to replace them by all filenames that
-   match, which is probably not what you want. This is also true when
-   using your shell directly, and has nothing to do with Kermit.
-     _________________________________________________________________
-
-    4.2.1.3. SECURITY
-
-   Some sites might not wish to allow access to system commands or
-   external programs from within Kermit. Such access, including all the
-   features described here, can be disabled in various ways:
-
-    1. When building from source code, include -DNOPUSH among the CFLAGS.
-    2. At runtime, give the NOPUSH command.
-    3. For server mode, give the DISABLE HOST command.
-    4. Implicit use of pipes can be disabled as described in [440]Section
-       4.2.4.
-
-   Note: 3 and 4 are not necessary if you have done 1 or 2.
-     _________________________________________________________________
-
-    4.2.2. Commands for Transferring from and to Pipes
-
-   SEND /COMMAND sends data from a command or command pipeline, and
-   RECEIVE /COMMENT writes data to a command or pipeline. The GET
-   /COMMAND command asks a server to send material, and then writes the
-   incoming material to a command or pipeline. These features, along with
-   switches (like "/COMMAND", described in [441]Section 4.7) are new to
-   C-Kermit 6.1. The following synonyms are also provided:
-
-  CSEND    = SEND /COMMAND
-  CRECEIVE = RECEIVE /COMMAND
-  CGET     = GET /COMMAND
-
-   None of these commands can be used if a SEND or RECEIVE FILTER
-   (respectively, [442]Section 4.2.3) is in effect, or if a NOPUSH
-   command ([443]Section 4.2.1.3) has been given, or if the current
-   protocol is not Kermit.
-     _________________________________________________________________
-
-    4.2.2.1. Sending from a Command
-
-   SEND /COMMAND command [ as-name ]
-   SEND /AS-NAME:as-name /COMMAND command
-   CSEND command [ as-name ]
-          These three forms are the same. They work like the SEND
-          command, but instead of sending a file, it sends the standard
-          output of the given command, either under the command's own
-          name, or else with the given as-name. If the command contains
-          spaces, it must be enclosed in braces. Braces should also be
-          used for the as-name if it contains spaces. If braces are
-          included around either the command or the as-name, they are
-          removed after parsing but before use. As with SEND, the
-          transfer is in text or binary mode according the current FILE
-          TYPE setting, unless you override the global transfer mode by
-          including a /TEXT or /BINARY switch. The command must require
-          no input.
-
-   When sending from a command or pipeline, C-Kermit has no way of
-   knowing in advance how much data will be sent, and so it can not send
-   the size to the other Kermit in the Attribute packet, and so the
-   receiving Kermit has no way of displaying "percent done" or a progress
-   bar (thermometer).
-
-   Examples that make sense in text mode (illustrated by common UNIX
-   commands):
-
-   SEND /COMMAND finger
-   CSEND finger
-          sends the current "finger" listing (who's logged in) under the
-          name "finger". The two forms "send /command" and "csend" are
-          equivalent; we won't bother showing them both in the rest of
-          the examples.
-
-   SEND /COMMAND:{finger}
-   CSEND {finger}
-          Same as previous example (braces are removed from "{finger}").
-
-   SEND /COMMAND:{ finger }
-   CSEND { finger }
-          Same as previous example, but note that the spaces are kept.
-          This does not prevent the shell from running the "finger"
-          program, but its output is sent under the name " finger " (with
-          a leading and trailing space).
-
-   SEND /COMMAND:finger /AS-NAME:userlist
-   CSEND finger userlist
-          sends the current finger listing under the name "userlist".
-
-   SEND /COMMAND:{finger | sort -r} /AS-NAME:userlist
-   CSEND {finger | sort -r} userlist
-          sends the current finger listing, sorted in reverse order,
-          under the name "userlist". The braces are needed to distinguish
-          the command from the as-name.
-
-   SEND /COMMAND:{finger | sort -r} /AS-NAME:{userlist}
-   CSEND {finger | sort -r} {userlist}
-          Same as previous example (braces are removed from
-          "{userlist}").
-
-   SEND /COMMAND:{finger | sort -r}
-          /AS-NAME:{\freplace(\v(filename),\32,_)}
-
-   CSEND {finger | sort -r} {\freplace(\v(filename),\32,_)}
-          Like the previous example, but sends the output of the command
-          under the name of the command, but with all spaces (\32)
-          replaced by underscores, so the as-name is "finger_|_sort_-r".
-
-   Examples that make sense in binary mode (three equivalent forms are
-   shown):
-
-   SEND /COMMAND /BINARY {tar cf - . | gzip -c} mydir.tar.gz
-   SEND /COMMAND /BINARY /AS-NAME:mydir.tar.gz {tar cf - . | gzip -c}
-   CSEND /BINARY {tar cf - . | gzip -c} mydir.tar.gz
-          Makes a tar archive of the current directory, compresses it
-          with the GNU gzip program, and sends it as "mydir.tar.gz". The
-          other Kermit can, of course, just store it as a file, or it can
-          use CRECEIVE to uncompress and dearchive it as part of the
-          transfer process.
-
-   When using a "pipeline" of commands in the command field, obviously,
-   the first command must not require any input, and the last command
-   should produce some output, and all intermediate commands should get
-   some input and produce some output.
-     _________________________________________________________________
-
-    4.2.2.2. Receiving to a Command
-
-   RECEIVE /COMMAND command
-   CRECEIVE command
-          This is like RECEIVE, except incoming material is written to
-          the standard input of the given command, in text or binary mode
-          according to the normal rules for file reception. Be sure to
-          include a redirector to a file (if the command normally writes
-          to standard output), or the output of the command won't go
-          anywhere. The command may contain spaces; braces are not
-          needed, but they are removed if used.
-
-   WARNING: C-Kermit has no way of knowing anything about the command, or
-   even whether it is a command. Thus this command will always cause
-   C-Kermit to enter protocol mode, as long as some text is specified in
-   the command field. However, if the text does not correspond to a
-   command, the transfer will eventually fail with a message such as
-   "Error writing data" or "Failure to close file".
-
-   Examples for text mode (in UNIX):
-
-   RECEIVE /COMMAND sort -r > reverse.txt
-   CRECEIVE sort -r > reverse.txt
-          The text that is received is sorted in reverse order and stored
-          in the file "reverse.txt". The two forms shown are equivalent.
-
-   RECEIVE /COMMAND {sort -r > reverse.txt}
-   CRECEIVE {sort -r > reverse.txt}
-          The same as the previous example; if braces are included, they
-          are simply removed.
-
-   RECEIVE /COMMAND {sort -r > \flower(\v(filename)).reverse}
-   CRECEIVE {sort -r > \flower(\v(filename)).reverse}
-          Same but stores result under the incoming filename, lowercased,
-          and with ".reverse" appended to it.
-
-   RECEIVE /COMMAND sort
-   CRECEIVE sort
-          Does nothing useful, since the output of sort has nowhere to
-          go.
-
-   RECEIVE /COMMAND sort -r | pr -3 | lpr -Plaserjet
-   CRECEIVE sort -r | pr -3 | lpr -Plaserjet
-          The text that is received is sorted in reverse order, arranged
-          into three columns, and sent to the "laserjet" printer.
-
-   Examples for binary mode:
-
-   RECEIVE /COMMAND:{gunzip -c | tar xf -}
-   CRECEIVE {gunzip -c | tar xf -}
-          Assuming the data that is received is a compressed tar archive,
-          uncompresses the archive and passes it to tar for extraction.
-          In this case the braces are needed because otherwise the final
-          "-" would be taken as a command continuation character (see
-          [444]Using C-Kermit, 2nd Edition, p.33).
-
-   GET /COMMAND remote-file command
-   GET /COMMAND /AS-NAME:command remote-file
-   CGET remote-file command
-          This command tells the Kermit client to send a GET request for
-          the given remote file to a Kermit server. Unlike GET, however,
-          the incoming material is written to a command, rather than to a
-          file. If the remote-file or the command contain spaces, they
-          must be enclosed in braces. The same cautions about the command
-          apply as for CRECEIVE.
-
-   Examples (for UNIX):
-
-   GET /COMMAND oofa.txt sort -r > oofa.new
-   GET /COMMAND {oofa.txt} {sort -r > oofa.new}
-   CGET oofa.txt sort -r > oofa.new
-   CGET {oofa.txt} {sort -r > oofa.new}
-          These four are equivalent. Each of them requests the server to
-          send its "oofa.txt" file, and as it arrives, it is sorted in
-          reverse order and written to "oofa.new".
-
-   GET /COMMAND {profile exec a} lpr
-   GET /COMMAND {profile exec a} {lpr}
-   GET /COMMAND /AS-NAME:lpr {profile exec a}
-   GET /COMMAND /AS-NAME:{lpr} {profile exec a}
-   GET /COMMAND /AS:lpr {profile exec a}
-   CGET {profile exec a} lpr
-   CGET {profile exec a} {lpr}
-          Here the remote filename contains spaces so it MUST be enclosed
-          in braces. As it arrives it is sent to the lpr program for
-          printing. Braces are optional around "lpr" since it contains no
-          spaces.
-
-   GET /COMMAND *.txt {cat >> new.txt}
-   GET /AS-NAME:{cat >> new.txt} /COMMAND *.txt
-   CGET *.txt {cat >> new.txt}
-          This gets all the ".txt" files from the server and concatenates
-          them all into a single "new.txt" file on the client.
-
-   GET /COMMAND *.txt {echo \v(filename)>>new.txt;cat>>new.txt}
-   CGET *.txt {echo \v(filename)>>new.txt;cat>>new.txt}
-          As above, but inserts each file's name before its contents.
-     _________________________________________________________________
-
-    4.2.3. Using File-Transfer Filters
-
-   The commands described in [445]Section 4.2.2 let you send the output
-   of a command, or receive data into a command. But what if you want to
-   specify preprocessing for files that you send, or postprocessing of
-   files that you receive, even when multiple files are involved? For
-   this you need a way to specify send and receive filters. The commands
-   are SET SEND FILTER and SET RECEIVE FILTER; SHOW PROTOCOL displays the
-   current settings.
-
-    4.2.3.1. The SEND Filter
-
-   SET SEND FILTER [ command ]
-          This command specifies a command to be run on any file that you
-          SEND (or MOVE, MSEND, etc). It also applies to files sent when
-          in server mode, in response to GET commands, but not to the
-          results of REMOTE commands like REMOTE DIRECTORY, REMOTE TYPE,
-          REMOTE HOST, etc. The command may be, but need not be, enclosed
-          in braces; if it is, the braces are stripped before use. The
-          output of this command is sent, rather than the file itself.
-          The current FILE TYPE setting (TEXT or BINARY) applies to the
-          output of the command. The command must contain at least one
-          instance of \v(filename), for which the name of the actual file
-          is substituted. If the command is omitted, the send filter is
-          removed and files are sent in the normal manner.
-
-   The SET SEND FILTER sets up a "global" filter -- that is, one that
-   applies to all subsequent file-sending commands until you change or
-   remove it. You can also specify a "local" filter to be used in a
-   specific file-sending command by using the /FILTER switch (see
-   [446]Section 1.5); for example:
-
-  SEND /FILTER:command [ other-switches ] filename
-
-   Besides \v(filename), you can include any other script programming
-   notation in the send filter: variable names, array references, calls
-   to built-in string or other functions, and so on. These are evaluated
-   during file transfer, NOT during parsing, and they are evaluated
-   separately for each file.
-
-   When the SEND or MOVE (SEND /DELETE) command is used with a send
-   filter, the output from the filter is sent under the file's original
-   name unless you specify an "as-name" or template. The Attribute packet
-   (if any) contains the original file's attributes (size, creation date,
-   etc). So (for example) if the filter changes the file's size, the
-   progress thermometer might be wrong. (We can't send the size of the
-   output from the filter, because it is not known until the transfer is
-   finished.) If you prefer that the size not be sent, use "set
-   attributes size off".
-
-   You can not use send filters with RESEND (SEND /RECOVER) or PSEND
-   (SEND /START).
-
-   Examples for text mode:
-
-   SET SEND FILTER sort -r \v(filename) ; Braces may be omitted
-   SET SEND FILTER {sort -r \v(filename)} ; Braces may be included
-   SEND *.txt
-          This sends every file in the current directory whose name ends
-          with ".txt" under its own name, but with its lines sorted in
-          reverse order.
-
-   SEND /FILTER:{sort -r \v(filename)} *.txt
-          Same as above, but the filter applies only to this SEND
-          command. Braces are required in this case.
-
-   SET SEND FILTER {sort -r \v(filename)}
-   SEND oofa.txt reverse.txt
-          Sends the oofa.txt file with its lines sorted in reverse order
-          under the name "reverse.txt".
-
-   SET SEND FILTER {sort -r \v(filename)}
-   SEND oofa.* \v(filename).reverse
-          Sends all the oofa.* files with their lines sorted in reverse
-          order; each file is sent under its own name but with ".reverse"
-          appended to it.
-
-   SET SEND FILTER {tr "[a-z]" "[A-Z]" < \v(filename)}
-   SEND *.txt
-          Sends all ".txt" files under their own names, but uppercasing
-          their contents.
-
-   Note that the SEND FILTER applies not only to files that are sent with
-   SEND, MOVE, MSEND, etc, but also to files sent by the C-Kermit server
-   in response to GET requests.
-
-   Examples for binary mode:
-
-   SET SEND FILTER {gzip -c \v(filename)}
-   SEND /BINARY oofa.txt oofa.txt.gz
-          Sends the oofa.txt file, compressed by gzip, as oofa.txt.gz.
-
-   SEND /BINARY /FILTER:{gzip -c \v(filename)} oofa.txt oofa.txt.gz
-          As above, but the filter applies only to this SEND command.
-
-   SET SEND FILTER {gzip -c \v(filename)}
-   SEND /BINARY oofa.* \fupper(\replace(\v(filename),.,_)).GZ
-          Sends all the oofa.* files, compressed by gzip, each under its
-          own name, but with the name uppercased, all periods within the
-          name converted to underscores, and ".GZ" appended to it. So,
-          for example, "oofa.txt" is sent as "OOFA_TXT.GZ".
-
-   In the gzip examples, note that the amount of data that is sent is
-   normally less than the original file size because gzip compresses the
-   file. But Kermit sends the original file size ahead in the attribute
-   packet anyway (unless you tell it not too). Thus the transfer will
-   probably appear to terminate early, e.g. when the receiver's
-   file-transfer display thermometer is only at 40%. If this annoys you,
-   tell Kermit to "set attribute length off". On the other hand, you can
-   use the final position of the thermometer as a measure of the
-   effectiveness of compression.
-     _________________________________________________________________
-
-    4.2.3.2. The RECEIVE Filter
-
-   SET RECEIVE FILTER [ command ]
-          This command specifies that the given command will be run on
-          any file that is received before it is written to disk. The
-          command may be, but need not be, enclosed in braces; if it is
-          the braces are stripped before use. The following two commands
-          are equivalent:
-
-  SET RECEIVE FILTER sort -r > \v(filename)
-  SET RECEIVE FILTER {sort -r > \v(filename)}
-
-   The RECEIVE filter command may contain a "\v(filename)" sequence to be
-   replaced by the incoming filename from the file header packet, but it
-   is not required. However you must use it whenever your filter would
-   normally write to Stdout, otherwise its output will be lost.
-
-   The RECEIVE filter command may contain one or more "\v(filename)"
-   sequence to be replaced by the incoming filename from the file header
-   packet, but it is not required. However you must use it whenever your
-   filter would normally write to Stdout, otherwise its output will be
-   lost.
-
-   RECEIVE /FILTER:command and GET /FILTER:command can also be used to
-   specify a filter to be used for only one file-transfer operation.
-
-   UNIX examples for text mode:
-
-   SET RECEIVE FILTER lpr
-   RECEIVE
-          All the files that are received are sent to the default UNIX
-          print spooler.
-
-   RECEIVE /FILTER:lpr
-          Same as above, except the lpr filter is used only with this
-          RECEIVE command.
-
-   RECEIVE lpr
-          This is probably not what you want; it creates a file called
-          lpr.
-
-   SET RECEIVE FILTER {sort -r > \v(filename)}
-   RECEIVE
-          Stores each incoming file with its lines sorted in reverse
-          order, under its own name.
-
-   RECEIVE /FILTER:{sort -r > \v(filename)}
-          As above, but the filter is used only for this RECEIVE command.
-
-   SET RECEIVE FILTER sort -r > \v(filename)
-   RECEIVE reverse.txt
-          Stores each incoming file with its lines sorted in reverse
-          order, under the name "reverse.txt". The actual result depends
-          on the FILE COLLISION setting. If it is OVERWRITE and multiple
-          files arrive, then each incoming file destroys the previous
-          one. If it is BACKUP (the default), filename conflicts are
-          resolve by adding "version numbers" to the filenames:
-          reverse.txt, reverse.txt.~1~, reverse.txt.~2~, etc.
-
-   SET RECEIVE FILTER sort -r > \v(filename)
-   RECEIVE \v(filename).reverse
-          Stores each incoming file with its lines sorted in reverse
-          order, under the name it arrived with, but with ".reverse"
-          appended to it.
-
-   SET RECEIVE FILTER sort -r > \v(filename)
-   RECEIVE \flower(\v(filename)).reverse
-          Like the previous example, but ensures that the filename is
-          lowercase.
-
-          Examples for binary mode:
-
-   SET RECEIVE FILTER gunzip -c > \v(filename)
-   RECEIVE
-          This receives one or more presumably compressed file and
-          uncompresses each one into a file having the same name it was
-          sent with. For example, if the file is sent with the name
-          OOFA.TXT.GZ, it is stored with that name, even after
-          decompression.
-
-   SET RECEIVE FILTER gunzip -c > \v(filename)
-   RECEIVE \flower(\fsubstring(\v(filename),1,\flength(\v(filename))-3))
-          Like the previous example, but the resulting filename has its
-          rightmost three characters removed from it and the remainder is
-          lowercased. So if the incoming filename is OOFA.TXT.GZ, it is
-          stored as oofa.txt after decompression.
-
-   Of course you don't want to type such long hideous commands, so we
-   have also introduced several new functions:
-
-   \fstripx(string[,character])
-          This function removes the rightmost segment of the string that
-          starts with the given character. If no character is given,
-          period (.) is used. Thus it is most conveniently used for
-          stripping the extension from a filename (or the decimal portion
-          from a floating-point number written in US/UK style). Examples:
-
-   \fstripx(OOFA.TXT.GZ)             => OOFA.TXT
-   \fstripx(OOFA.TXT.GZ,.)           => OOFA.TXT
-   \fstripx(OOFA.TXT.GZ,X)           => OOFA.T
-   \fstripx(\fstripx(OOFA.TXT.GZ))   => OOFA
-   \fstripx($100.00)                 => $100
-
-   \fstripn(string,number)
-          Removes the rightmost number characters from the string.
-          Examples:
-
-   \fstripn(OOFA.TXT.GZ)             => OOFA.TXT.GZ
-   \fstripn(OOFA.TXT.GZ,3)           => OOFA.TXT
-   \fstripn(OOFA.TXT.GZ,7)           => OOFA
-
-   \fstripb(string[,c1[,c2]])
-          Strips enclosing matching braces, brackets, parentheses, or
-          quotes from the string. The second argument, c1, specifies
-          which kind of enclosure to look for; if not specified, any
-          enclosing (), [], <>, {}, "", '', or `' are removed. If c1 is
-          specified and c2 is not, then if c1 is an opening brace,
-          bracket, or parenthesis, the matching closing one is supplied
-          automatically as c2. If both c1 and c2 are specified, then to
-          be stripped the string must begin with c1 and end with c2. If
-          the string is not enclosed in the indicated manner, the result
-          is the original string. Examples:
-
-   \fstripb("abc")                   => abc
-   \fstripb([abc])                   => abc
-   \fstripb([abc)                    => [abc
-   \fstripb(<abc>)                   => abc
-   \fstripb(<abc>,[)                 => <abc>
-   \fstripb((abc))                   => abc
-   \fstripb((abc),[)                 => (abc)
-   \fstripb((abc),{(})               => abc
-   \fstripb(+abc+)                   => +abc+
-   \fstripb(+abc+,+)                 => abc
-   \fstripb(+abc+,+,^)               => +abc+
-   \fstripb(+abc^,+,^)               => abc
-   \fstripb('abc')                   => abc
-   \fstripb(`abc')                   => abc
-   \fstripb(``abc'')                 => `abc'
-   \fstripb(\fstripb(``abc''))       => abc
-
-          Notice the special syntax required for including a literal
-          parenthesis in the argument list. As the last two examples
-          illustrate, \fstripb() strips only one level at at a time;
-          nesting can be used to strip a small fixed number of levels;
-          loops can be used to strip larger or indeterminate numbers of
-          levels.
-
-   \flop(string[,char])
-          Removes the leftmost segment of the string that ends with the
-          given character. If no character is given, period (.) is used.
-          Examples:
-
-  \flop(OOFA.TXT.GZ)               => TXT.GZ
-  \flop(OOFA.TXT.GZ,.)             => TXT.GZ
-  \flop(OOFA.TXT.GZ,X)             => T.GZ
-
-          To remove the leftmost number characters, just use
-          \fsubstring(s,number+1). To return the rightmost number
-          characters, use \fright(s,number).
-
-   So the hideous example:
-
-  receive \flower(\fsubstring(\v(filename),1,\flength(\v(filename))-3))
-
-   can now be written as:
-
-  receive \flower(\fstripx(\v(filename)))
-
-   That is, the filename stripped of its extension and then lowercased.
-   This is not only shorter and less hideous, but also does not depend on
-   the length of the extension being 3.
-
-   Note that when a receive filter is in effect, this overrides your FILE
-   COLLISION setting, since Kermit has no way of knowing what the final
-   destination filename will be (because it does not know, and can not be
-   expected to know, the syntax of every version of every command shell
-   on every platform on the planet).
-     _________________________________________________________________
-
-    4.2.4. Implicit Use of Pipes
-
-   If you wish, C-Kermit can also examine incoming filenames to see if
-   they start with "!", and if so, the subsequent text is treated as a
-   command to read from or write to. For example, if a Kermit client is
-   given the following command:
-
-  get {!finger | sort}
-
-   the server on the other end, if it supports this feature, will run the
-   "finger" program, pipe its standard output to the "sort" program, and
-   send sort's standard output back to you. Similarly, if you:
-
-  send oofa.txt !sort -r > oofa.new
-
-   or, equivalently:
-
-  send oofa.txt {!sort -r > oofa.new}
-
-   or:
-
-  send /as-name:{!sort -r > oofa.new} oofa.txt
-
-   this has the receiver send the contents of the incoming oofa.txt file
-   to the sort program, which sorts the text in reverse order and stores
-   the result in oofa.new.
-
-   This use of the exclamation mark should be familiar to UNIX users as
-   the "bang" feature that lets you run an external application or
-   command from within another application.
-
-   Kermit's "bang" feature is disabled by default, since it is not
-   unheard for filenames to actually begin with "!". So if you want to
-   use this feature, you must enable it with the following command:
-
-   SET TRANSFER PIPES { ON, OFF }
-          ON enables the recognition of "!" notation in incoming
-          filenames during file transfer as an indicator that the
-          remaining text is the name of a command. OFF, the default,
-          disables this feature and uses the text as a filename in the
-          normal fashion. This command does NOT affect SEND /COMMAND, GET
-          /COMMAND, CSEND, etc.
-
-   So using a combination of CSEND (SEND /COMMAND) and the "bang"
-   feature, you can transfer a directory tree all in one command
-   (assuming the remote Kermit supports pipe transfers and has them
-   enabled):
-
-  CSEND {tar cf - . | gzip -c} {!gunzip -c | tar xf -}
-
-   or:
-
-  SEND /COMMAND:{tar cf - . | gzip -c} /as:{!gunzip -c | tar xf -}
-
-   Pay close attention to the syntax. Braces are needed around the
-   command because it contains spaces; braces are needed around the
-   as-name because it ends with "-". The as-name must begin with "!" or
-   receiving Kermit will not recognize it as a command. The CSEND command
-   must NOT begin with "!" unless you are running a command whose name
-   really does start that character.
-
-   Similarly, you have a Kermit server send a directory tree to be
-   unpacked on the client end:
-
-  CGET {!tar cf - . | gzip -c} {gunzip -c | tar xf -}
-
-   or:
-
-  GET /COMMAND {!tar cf - . | gzip -c} /as:{gunzip -c | tar xf -}
-
-   Notice how, in this case, the bang is required in the remote command,
-   to distinguish it from a filename, but not in the local command, since
-   by definition of CGET (or GET /COMMAND), it is known to be a command.
-
-   SEND and RECEIVE FILTERs supersede the bang feature. For example, if a
-   file arrives under the name "!gunzip -c | tar xf -", but the receiving
-   Kermit also has been given a command like:
-
-  set receive filter sort -r > \v(filename)
-
-   then the incoming data will be sorted rather than gunzipped.
-
-   Finally, if SET TRANSFER PIPES is ON (and in this case, this must be
-   done in your C-Kermit initialization file), you can send from a pipe
-   on the C-Kermit command line:
-
-  kermit -s "!finger | sort -r" -a userlist
-
-   In this case the "filename" contains spaces and so must be quoting
-   using your shell's quoting rules.
-     _________________________________________________________________
-
-    4.2.5. Success and Failure of Piped Commands
-
-   Commands or programs started by Kermit as a result of CSEND or
-   CRECEIVE commands, CGET, SEND /COMMAND, REDIRECT commands (see
-   [447]Section 4.2.8.2), implicit use of pipes, RUN commands, and so
-   forth, should return their exit status codes to the Kermit command
-   that caused them to be run, and therefore IF SUCCESS and IF FAILURE
-   tests after these commands should work as expected. For example:
-
-  CSEND blah < filename
-
-   should fail if there is no command called "blah" or if there is no
-   file called "filename". However, this is not foolproof and sometimes
-   C-Kermit might think a command succeeded when it failed, or vice
-   versa. This is most likely to happen when the highly system-dependent
-   methods that Kermit must use to determine a command's exit status code
-   do not supply the right information.
-
-   It can also happen because some commands might define success and
-   failure differently from what you expect, or because you are using a
-   pipeline composed of many commands, and one of them fails to pass
-   failing exit status codes up the chain. The most likely culprit is the
-   shell itself, which in most cases must be interposed between Kermit
-   and any external program to be run.
-
-   In any case, you can examine the following variable to find out the
-   exit status code returned to Kermit by the process most recently run
-   by any command that runs external commands or programs, including
-   CSEND, CRECEIVE, REDIRECT, RUN, etc:
-
-  \v(pexitstat)
-
-   In UNIX, Windows and OS/2, the value should be -2 if no command has
-   been run yet, 0 if the most recent command succeeded, -1, -3, or -4 if
-   there was an internal error, and a positive number returned by the
-   command itself if the command failed. If the number is in the range
-   1-127, this is the program's exit status code. If it is 128 or
-   greater, this is supposed to indicate that the command or program was
-   interrupted or terminated from outside itself.
-
-   In Windows 95 and 98, the return values of the default shell are
-   unreliable; various third-party shells can be used to work around this
-   deficiency.
-
-   In VMS, it is the actual exit status code of the command that was run.
-   This is an odd number if the command succeeded, and an even number if
-   it failed. You can see the associated message as follows:
-
-  run write sys$output f$message(\v(pexitstat))
-
-   Or, more conveniently, use the new Kermit function:
-
-  echo \ferrstring(\v(pexitstat))
-
-   which converts a system error code (number) to the corresponding
-   message.
-     _________________________________________________________________
-
-    4.2.6. Cautions about Using Pipes to Transfer Directory Trees
-
-   Although utilities such as tar and zip/unzip might be available on
-   different platforms (such as UNIX and Windows), this does not
-   necessarily mean you can use them successfully to transfer directory
-   trees between unlike platforms. For example:
-
-  CSEND {tar cf - . | gzip -c} {!gunzip -c | tar xf -}
-
-   when used from UNIX to Windows will have satisfactory results for
-   binary files, but not for text files. UNIX text files have lines
-   ending with Linefeed (LF) only, whereas Windows text files have lines
-   ending in Carriage Return and Linefeed (CRLF). Thus any text files
-   that were in the archive formed by the first tar command will be
-   unpacked by the second tar command in their original form, and will
-   display and print incorrectly in Windows (except in applications that
-   have been explicitly coded to handle UNIX-format text files). On the
-   other hand if you told gzip to use "text mode" to do record format
-   conversion (assuming there was a way to tell it, as there is with most
-   "zip" programs), this would destroy any binary files in the archive.
-
-   Furthermore, if the archive contains text files that are written in
-   languages other than English, the "special" (accented and/or
-   non-Roman) characters are NOT translated, and are therefore likely
-   show up as gibberish on the target system. For example, West European
-   languages are usually encoded in ISO Latin Alphabet 1 in UNIX, but in
-   PC code page 850 on the PC. Capital A with acute accent is code point
-   193 (decimal) Latin-1, but 181 in CP850. So A-acute in the UNIX file
-   becomes Middle Box Bottom on the PC, and similarly for all the other
-   special characters, and for all other languages -- Greek, Russian,
-   Hebrew, Japanese, etc.
-
-   So when transferring text files between unlike platforms, you should
-   use direct Kermit file transfers so Kermit can apply the needed
-   record-format and character-set transformations. Use pipelines
-   containing archivers like tar or zip only if all the files are binary
-   or the two systems use the same record format and character set for
-   text files.
-
-   Also see [448]Sections 4.3, [449]4.10, [450]4.11, and [451]4.15 for
-   how to transfer directory trees between both like and unlike systems
-   directly with Kermit.
-     _________________________________________________________________
-
-    4.2.7. Pipes and Encryption
-
-   Of course pipelines could be used for encrypted file transfers,
-   assuming proper precautions could be taken concerning the transmission
-   of the key. But there is rarely a good way to do this. To illustrate
-   using UNIX crypt:
-
-  csend {crypt key < filename} {!crypt key > filename}
-
-   Or, more ambitiously:
-
-  csend {tar cf - . | gzip -c | crypt key} {!crypt key | gunzip -c | tar xf -}
-
-   transmits the key in the file header packet as part of the
-   (clear-text) remote command, defeating the entire purpose of
-   encrypting the file data.
-
-   But if you are connected in terminal mode to the remote computer and
-   type:
-
-  creceive {crypt key > filename}
-
-   at the remote Kermit prompt, you have also transmitted the key in
-   clear text over the communications link.
-
-   At present, the only secure way to use CSEND and CRECEIVE with an
-   encryption filter is to have a human operator at both ends, so the key
-   does not have to be transmitted.
-
-   Theoretically it would be possible to use PGP software (Pretty Good
-   Privacy, by Phil Zimmerman, Phil's Pretty Good Software) to avoid key
-   transmission (since PGP uses separate public and private key and "lets
-   you communicate securely with people you've never met, with no secure
-   channels needed for prior exchange of keys"), but the specific method
-   has yet to be worked out.
-
-     HINT: See the PGP User's Guide, e.g. at:
-     [452]http://www.telstra.com.au/docs/PGP/
-     Especially the topic "Using PGP as a UNIX-Style Filter":
-     [453]http://www.telstra.com.au/docs/PGP/pgpdoc2/pgpdoc2_17.html
-
-   In any case, better and more convenient security options are now
-   available: Kerberos authentication and encryption ([454]CLICK HERE for
-   details) and the new ability to run C-Kermit "though" other
-   communication programs, described in [455]Section 2.7.
-     _________________________________________________________________
-
-    4.2.8. Commands and Functions Related to Pipes
-
-    4.2.8.1. The OPEN !READ and OPEN !WRITE Commands
-
-   These are described in [456]Using C-Kermit, and are generally useful
-   with reading output from commands that produce more than one line on
-   their standard output, or writing multiple lines into commands that
-   accept them on their standard input.
-
-   In C-Kermit 7.0 CLOSE !READ is accepted as a synonym for CLOSE READ,
-   and CLOSE !WRITE for CLOSE WRITE.
-
-   Testing the success and failure of these commands, however, can be a
-   bit tricky. Consider:
-
-  open !read lalaskjfsldkfjsldkfj
-
-   (where "lalaskjfsldkfjsldkfj" is neither a valid command nor the name
-   of a program or script that can be run). OPEN !READ, in UNIX at least,
-   translates this into execl(shellpath,shellname,"-c",command). This
-   means it starts your preferred shell (e.g. from the SHELL environment
-   variable) and asks it to execute the given command. It must be this
-   way, because your command can be a either an internal shell command
-   (which only your shell can execute) or an external command, which only
-   your shell knows how to find (it knows your PATH and interprets, etc).
-   Therefore unless OPEN !READ can't start your shell, it always
-   succeeds.
-
-   Continuing with the nonexistent-command example:
-
-  C-Kermit> open !read lalaskjfsldkfjsldkfj
-  C-Kermit> status
-   SUCCESS
-  C-Kermit> read line
-  C-Kermit> status
-   SUCCESS
-  C-Kermit> echo "\m(line)"
-  "bash: lalaskjfsldkfjsldkfj: command not found"
-  C-Kermit> close read
-  C-Kermit> status
-   FAILURE
-  C-Kermit>
-
-   In other words, the failure can not be detected on OPEN, since the
-   OPEN command succeeds if it can start your shell. It can't be detected
-   on READ, since all this does is read output from the shell, which in
-   this case happens to be an error message. However, failure IS detected
-   upon close, since this is the occasion upon which the shell gives
-   Kermit its exit status code.
-
-   For an illustration of this situation, see [457]Section 2.14.
-     _________________________________________________________________
-
-    4.2.8.2. The REDIRECT Command
-
-   A second method of I/O redirection is offered by the REDIRECT command.
-   This is a rather advanced and tricky feature that is presently
-   supported only in UNIX C-Kermit, in OS-9 C-Kermit, and in Kermit 95.
-   Syntax:
-
-   REDIRECT command
-          Runs the given command, sending its standard output to the
-          current communications channel (SET LINE, SET PORT, or SET HOST
-          connection), and reading its standard input from the same
-          connection. Works only in local mode -- i.e. a connection is
-          required -- and then only if the given command uses Standard
-          I/O.
-
-   Example:
-
-  redirect finger
-
-   runs the local "finger" command and sends its output over the
-   connection as plain text, where presumably there is a process set up
-   to read it. Another example:
-
-  redirect finger | sort -r
-
-   shows the use of a pipeline.
-
-   Note: REDIRECT differs from CSEND/CRECEIVE in two important ways: (1)
-   it does not use the Kermit protocol, and (2) it uses a bidirectional
-   pipe rather than a one-way pipe.
-
-   The primary use of the REDIRECT command is to run external protocols,
-   such as sz/rz in UNIX for ZMODEM, when they work over Standard I/O(*).
-   Example:
-
-  set host xyzcorp.com
-  (login, etc)
-  redirect sz oofa.zip
-
-   lets you make a Telnet connection with C-Kermit and then do a ZMODEM
-   transfer over it. ZMODEM protocol messages go both ways over the same
-   connection simultaneously.
-
-   It is possible to use C-Kermit on UNIX as your PPP dialer and then to
-   REDIRECT the connection to the PPP software, but C-Kermit 7.0 offers a
-   better approach to PPP dialing in its new EXEC command ([458]Section
-   1.23).
-
-   In theory, you can also redirect an interactive process. For example,
-   suppose you tell Kermit 95 to wait for an incoming TCP/IP connection:
-
-  set host * 3000
-
-   and then tell C-Kermit on UNIX to:
-
-  set host kermit95hostname 3000
-  redirect ksh
-
-   and then tell Kermit 95 to CONNECT: now you are talking to the UNIX
-   K-shell; you can give commands (pwd, ls, etc) and see the results. In
-   practice, the K-shell's terminal modes are messed up because (a) it is
-   not going through the Unix terminal driver, and (b) it is "smart" and
-   knows it is being redirected, and so acts in a decidedly inhospitable
-   manner (other applications like EMACS, vi, etc, simply refuse to run
-   if their standard i/o has been redirected).
-
-     (*) The publicly-distributed sz/rz programs do not work as clients.
-     However, Omen Technology does offer an up-to-date redirectable
-     client XYZMODEM program called crzsz.
-     _________________________________________________________________
-
-    4.2.8.3. Receiving Mail and Print Jobs
-
-   As of 7.0, and in UNIX only, files that are sent to C-Kermit as mail
-   (when the other Kermit uses a MAIL or SEND /MAIL command) or to be
-   printed (via REMOTE PRINT or SEND /PRINT) are now piped directly to
-   the mail or print program, rather than written to temporary files and
-   then mailed or printed and then deleted. This has the advantages of
-   (a) not requiring a temporary file, and (b) allowing mail to have a
-   proper subject in place of the filename. Temporary files were bad not
-   only because they required (a) space, and (b) writeability of the
-   current directory, but also because using them could result in wiping
-   out an existing file. See [459]Section 4.7 for more about SEND /MAIL
-   and SEND /PRINT.
-     _________________________________________________________________
-
-    4.2.8.4. Pipe-Related Functions
-
-   The \fcommand(command) function runs the given shell or system command
-   and returns the command's standard output as its value (with any
-   newline characters stripped from the end), unless the result is too
-   long, in which case it returns the empty string. The maximum length
-   for the result is at least 1022 bytes, and it might be longer on some
-   platforms. Examples (UNIX):
-
-  C-Kermit> echo "\fcommand(date)"
-  "Fri Apr 18 13:31:42 1997"
-  C-Kermit> echo "\fcommand(finger | wc -l)" ; how many users logged in?
-  "      83"
-  C-Kermit> evaluate \fcommand(finger | wc -l) * 2
-  166
-  C-Kermit> echo Welcome to \fcommand(tty) on \fcommand(date)
-  Welcome to /dev/ttyre on Fri Apr 18 13:31:42 1997
-  C-Kermit> echo "\fcommand(ls oofa.*)"
-  "oofa.c
-  oofa.h
-  oofa.o"
-  C-Kermit> cd /directory-with-thousands-of-files
-  C-Kermit> echo "\fcommand(ls -l)" ; This would be too long
-  ""
-  C-Kermit>
-
-   If a command's output would be too long, you can use the other, more
-   laborious method of reading from a command: OPEN !READ command, READ
-   each line, CLOSE !READ.
-
-   The \frawcommand(command) function is identical to \fcommand(command),
-   except it does not remove trailing newline characters:
-
-  C-Kermit> echo "\frawcommand(date)"
-  "Fri Apr 18 13:31:42 1997
-  "
-  C-Kermit> echo "\frawcommand(ls oofa.*)"
-  "oofa.c
-  oofa.h
-  oofa.o
-  "
-  C-Kermit>
-
-   Use \frawcommand() if you want to retain the final line terminators,
-   or if the command's output is "binary". But remember that if the
-   result of this (or any other) function contains any NUL (ASCII code 0)
-   characters, the first NUL will terminate the result string because
-   this is how C strings work (it's "C-Kermit", remember?).
-
-   These functions are useful not only locally, but also in the
-   client/server arena. If you need to get the results from a system
-   command on the server end into a variable on the client end, just do:
-
-  [ remote ] query kermit command(date)
-
-   The result is in the local \v(query) variable; see [460]Using
-   C-Kermit, 2nd Ed., pp.359-360 for details.
-     _________________________________________________________________
-
-  4.3. Automatic Per-File Text/Binary Mode Switching
-
-   When transferring files between like systems (e.g. UNIX-to-UNIX),
-   binary mode can be used for all files unless character-set translation
-   is needed, and in fact Kermit programs of recent vintage recognize
-   each others' platforms and switch to binary mode automatically when it
-   is appropriate (e.g. DOS to OS/2, or UNIX to UNIX). (Exception:
-   LABELED mode is chosen for VMS-to-VMS and OS/2-to-OS/2 transfers so
-   complex file formats can be preserved.)
-
-   On a client/server connection between like systems, the transfer mode
-   is currently determined by the file sender, rather than always by the
-   client. If the client is sending, it controls the transfer mode. If a
-   GET command is sent to the server, the server sends all files in
-   binary mode if its TRANSFER CHARACTER-SET is TRANSPARENT; otherwise it
-   uses text mode for text files (according to its text-pattern list) and
-   binary mode for binary files. Of course, the client can control the
-   server's transfer character-set with the REMOTE SET TRANSFER
-   CHARACTER-SET command.
-
-   When transferring files between unlike systems, however, (e.g.
-   UNIX-to-DOS), some files (such as executable program images) must be
-   transferred in binary mode but others (such as plain-text files) must
-   be transferred in text mode so their record format and character sets
-   can be appropriately converted. If a binary file is transferred in
-   text mode, it is ruined. If a text file is transferred in binary mode,
-   then at the very least, its format can be incorrect; at worst it is
-   also corrupted because its character set was not converted (in extreme
-   cases the corruption is total, e.g. because one system is ASCII-based
-   and the other EBCDIC).
-     _________________________________________________________________
-
-    4.3.1. Exceptions
-
-   VMS C-Kermit, when sending files to a non-VMS system, switches to text
-   or binary mode automatically for each file, based on the record format
-   in the file's directory entry; thus the mechanisms described in this
-   section do not apply to VMS C-Kermit, yet the effect is the same:
-   automatic text/binary mode switching when VMS C-Kermit is sending
-   files. See the VMS Appendix of [461]Using C-Kermit for details.
-
-   Kermit versions that support LABELED or IMAGE transfer mode are
-   likewise not affected by this feature when one of those modes is
-   selected (normally used only when transferring between like systems).
-
-   Kermit versions that support file-transfer pipes and filters are not
-   affected by this feature when pipes or filters are used, since the
-   output of a pipe or filter (such as gzip) is likely to require
-   transfer in a different mode than the original file.
-
-   Finally, SEND /TEXT or SEND /BINARY will force files to be sent in the
-   indicated mode, overriding all automatic transfer-mode-choosing
-   mechanisms.
-     _________________________________________________________________
-
-    4.3.2. Overview
-
-   Suppose you give C-Kermit a command like:
-
-  SEND *.*
-
-   And suppose the pattern *.* matches a mixture of text files (such as
-   program source code) and binary files (such os object modules or
-   executable programs).
-
-   C-Kermit 6.0 and earlier (except on VMS) send all files in the same
-   mode: whatever you said in your most recent SET FILE TYPE command, or
-   else whatever mode was chosen automatically according to the rules on
-   page 236 of Using C-Kermit, 2nd Ed.
-
-   But when text and binary files are mixed in the same group, and the
-   files are being transferred to an unlike system (e.g. UNIX to IBM
-   Mainframe), this results in corruption of either all the text files or
-   all the binary files.
-
-   Stream-oriented file systems such as in UNIX and DOS do not record any
-   information about the file to tell us whether the file should be
-   transferred in binary or text mode, making it impossible to select the
-   transfer mode for each file in a group automatically with any
-   certainty.
-
-   However, we can use some fairly-well established file naming
-   conventions for this purpose. C-Kermit 7.0 lets you provide lists of
-   filename patterns that are used to separately determine the file type
-   for each individual file being transfered. A pattern is a string,
-   possibly containing the special characters "*" (asterisk, which
-   matches any string of zero of more characters) and/or "?" (question
-   mark, which matches any single character). For example "a*b" matches
-   all files whose names start with "a" and end with "b", such as "ab",
-   "arb", "ababababab", etc, but not "abba". And "a?b" matches any file
-   whose name starts with "a", ends with "b", and is exactly 3 characters
-   long.
-
-     NOTE: When typing commands at the C-Kermit prompt, you must prefix
-     "?" with \ to override its normal function of giving help.
-
-   (Also see [462]Section 4.9 for additional pattern-matching notations
-   that might be available in your version of C-Kermit.)
-
-   When you have specified filename recognition patterns, C-Kermit can
-   transfer the ones whose names match any of the binary-mode patterns in
-   binary mode, and those with names that match any of the text-mode
-   patterns in text mode, and those whose names match neither in the
-   prevailing mode you have chosen, or that was chosen automatically via
-   peer recognition.
-     _________________________________________________________________
-
-    4.3.3. Commands
-
-   SET FILE PATTERNS { ON, OFF, AUTO }
-          This tells Kermit whether to do per-file filename
-          pattern-matching to determine text or binary mode. The normal
-          and default setting is AUTO, which means to use pattern lists
-          to switch transfer mode only when it is certain that the other
-          Kermit program supports automatic notification of transfer mode
-          (via Attribute packets) on a per-file basis (this information
-          is obtained automatically during protocol startup negotiation).
-          ON means to always determine the transfer mode from the
-          filename and pattern list when sending files. Use OFF to
-          disable this feature (without resetting your pattern lists).
-          Also note that if you have selected LABELED file transfer (SET
-          FILE TYPE LABELED), this takes precedence over
-          filename-matching patterns and all files are sent in labeled
-          mode.
-
-   SET TRANSFER MODE MANUAL
-          Disables the use of filename patterns, no matter what the FILE
-          PATTERNS setting.
-
-   REMOTE SET TRANSFER MODE MANUAL
-          Client command to disable automatic transfer mode, and
-          therefore also filename patterns, in the server. Synonym:
-          REMOTE SET XFER MODE MANUAL.
-
-   { GET, SEND, etc } { /BINARY, /TEXT }
-          Including a /BINARY or /TEXT (or, where supported, /IMAGE or
-          /LABELED) switch with a file-transfer command changes the
-          transfer mode to manual for that command only, and therefore
-          disables patterns that that command.
-
-   SET FILE BINARY-PATTERNS [ pattern [ pattern [ pattern ... ] ] ]
-          A list of zero or more patterns, separated by spaces (not
-          commas). Letters in a pattern are case-sensitive if the
-          underlying filenames are case sensitive (as in UNIX), and
-          case-insensitive otherwise (as in Windows). If a file's name is
-          matched by any pattern in the list and SET FILE PATTERNS is ON,
-          the file is sent in binary mode. Examples:
-
-  SET FILE BINARY-PATTERNS *.gz *.Z *.tar *.zip *.o *.so *.a *.out ; UNIX
-  SET FILE BINARY-PATTERNS *.EXE *.ZIP *.OBJ *.COM ; DOS or OS/2 or Windows
-
-          If a pattern contains spaces, enclose it in braces.
-
-   SET FILE TEXT-PATTERNS [ pattern [ pattern [ pattern ... ] ] ]
-          Like SET FILE BINARY-PATTERNS, but the patterns choose text
-          files rather than binary ones. Examples:
-
-  SET FILE TEXT-PATTERNS *.TXT *.KSC *.HTM* *.BAT ; DOS, Windows, OS/2
-
-   ADD BINARY-PATTERNS [ pattern [ pattern [ pattern ... ] ] ]
-          Adds one or more patterns to the BINARY-PATTERN list.
-
-   ADD TEXT-PATTERNS [ pattern [ pattern [ pattern ... ] ] ]
-          Adds one or more patterns to the TEXT-PATTERN list.
-
-   REMOVE BINARY-PATTERNS [ pattern [ pattern [ pattern ... ] ] ]
-          Removes one or more patterns from the BINARY-PATTERN list. The
-          given patterns are matched with the ones in the BINARY-PATTERNS
-          list with case sensitivity if the underlying file system has
-          case-sensitive names (as do UNIX and OS-9), otherwise with case
-          independence.
-
-   REMOVE TEXT-PATTERNS [ pattern [ pattern [ pattern ... ] ] ]
-          Removes one or more patterns from the TEXT-PATTERN list.
-
-   SHOW PATTERNS
-          Displays the current pattern selections.
-
-   Whenever you give a SET FILE BINARY-PATTERNS or SET FILE TEXT-PATTERNS
-   command, the previous list is replaced. If you give one of these
-   commands without a pattern list, the previous list is removed.
-
-   When patterns are active and files are being sent, text patterns (if
-   any) are applied first (but only if not RESENDing and not sending in
-   LABELED mode), then binary patterns, so if the same pattern appears in
-   both lists, binary mode is chosen.
-     _________________________________________________________________
-
-    4.3.4. Examples
-
-   Here's an example that might be used when sending files from UNIX:
-
-  set file type binary
-  set file text-patterns *.c *.h *.w *.txt makefile
-  set file binary-patterns *.o
-  msend makefile wermit wart ck*.[cwho] ck*.txt
-
-   Note that "wermit" and "wart" do not match any patterns so they are
-   sent in the prevailing mode, which is binary. Also note the use of
-   "makefile" as a pattern that does not contain any wildcard characters
-   (there is no other convention to distinguish among "wermit" and
-   "wart", which are binary executables, and "makefile", which is a text
-   file, purely by their names).
-
-   Most C-Kermit implementations have a default pattern list built in,
-   which includes patterns that are almost certain to succeed in picking
-   the right transfer mode. Others are omitted due to ambiguity. For
-   example ".hlp", and ".ini" are generally binary types in Windows but
-   text types everywhere else.
-
-     NOTE: ".doc", used for decades to denote plain-text documentation
-     files, now more often than not denotes a Microsoft Word Document,
-     so ".doc" is now considered a binary type since it does less harm
-     to transfer a plain-text document in binary mode than it does to
-     transfer an MS Word file in text mode (except when IBM mainframes
-     are involved!)
-
-     ANOTHER NOTE: ".com" files are binary in DOS-like operating
-     systems, but they are text (DCL command procedures) in VMS. VMS
-     C-Kermit sends .COM files in text mode; K95 sends them in binary
-     mode. If you download a .COM file from VMS to DOS or Windows, and
-     then upload it to another VMS system, be sure to use SEND /TEXT to
-     preserve its textness.
-
-   You can see the default pattern list by starting C-Kermit without its
-   initialization file (e.g. "kermit -Y") and using the SHOW PATTERNS
-   command. If you will be depending on this feature, be sure to examine
-   the list carefully in conjunction with the applications that you use.
-
-   The default pattern list does not take "backup files" into account
-   because (a) people usually don't want to transfer them; and (b) it
-   would make the pattern lists more than twice as long. For example, we
-   would need to include both *.txt and *.txt.~[0-9]*~ for ".txt" files,
-   and similarly for all the others. Instead, you can use SEND /NOBACKUP
-   (or SET SEND BACKUP OFF) to skip over all backup files.
-
-   Put your most commonly-used safe pattern declarations in your C-Kermit
-   customization file (ckermod.ini, .mykermrc, k95custom.ini, etc).
-
-   As noted, SET FILE PATTERNS is ON by default. Sometimes, however, it
-   is desirable, or necessary, to force files to be sent in a particular
-   mode, and often this must be done from the command line (e.g. when
-   using Kermit as a download helper in a Web browser like Lynx). The -V
-   command-line options is equivalent to SET FILE PATTERNS OFF and SET
-   TRANSFER MODE MANUAL. Example:
-
-  kermit -Vis oofa.txt
-
-   forces oofa.txt to be sent in binary mode, even though ".txt" might
-   match a text pattern.
-     _________________________________________________________________
-
-  4.4. File Permissions
-
-   "Permissions" refers to a code associated with a file that specifies
-   who is allowed to access it, and in what manner. For example, the
-   owner, the members of one or more groups, the system administrator,
-   and everybody else, might be allowed various combinations of Read,
-   Write, Append, Execute, or Listing access.
-
-   The permission code goes by different names on different platforms. In
-   UNIX, it might be called the filemode. In VMS, it is called the file
-   protection (or protection mask).
-
-   The comments in this section presently apply only to the UNIX and VMS
-   versions of C-Kermit, to which these features were added in version
-   7.0; the DOS, Windows, and OS/2 file systems embody no notions of
-   protection, and so MS-DOS Kermit and Kermit 95 do not send file
-   permissions, and ignore them when received.
-
-   The permissions for a received file are determined by a combination of
-   the file transfer mode (VMS-to-VMS transfers only), whether a file of
-   the same name exists already, whether permissions of the file are
-   received in the file attribute packet, and the setting of ATTRIBUTES
-   PROTECTION.
-
-   The default for ATTRIBUTES PROTECTION is ON. If no attributes are
-   received, the effect is the same as if attributes PROTECTION were OFF.
-
-   For VMS-to-VMS transfers, the default LABELED mode simply copies the
-   protection code from source to destination.
-     _________________________________________________________________
-
-    4.4.1. When ATTRIBUTES PROTECTION is OFF
-
-   If no file of the same name exists, system defaults determine the
-   permissions of the new file. Otherwise, the actions taken depend on
-   the current FILE COLLISION setting: BACKUP, OVERWRITE, RENAME, etc, as
-   documented in [463]Using C-Kermit. But now the new file (if it is
-   created at all) automatically inherits the permissions (mode bits) of
-   the existing file in a way that is appropriate for the platform.
-
-    4.4.1.1. Unix
-
-   All mode bits are inherited except the directory bit, since the
-   incoming file can not possibly be a directory. (In any case, it is not
-   possible to receive a file that has the same name as an existing
-   directory unless FILE COLLISION is set to RENAME).
-
-    4.4.1.2. VMS
-
-   Files with the same name as an existing file, transferred in modes
-   other than LABELED between VMS systems, inherit the protection of the
-   prior version.
-     _________________________________________________________________
-
-    4.4.2 When ATTRIBUTES PROTECTION is ON
-
-   File permissions can be conveyed as part of the file transfer process,
-   in accordance with the Kermit protocol definition. If the file sender
-   puts system-dependent and/or system-independent versions of the file
-   protection (permissions) into the Attribute (A) packet, the file
-   receiver can set the new file's permissions from them. Otherwise, the
-   permissions are set the same as for ATTRIBUTES PROTECTION OFF.
-
-   When the incoming A packet contains system-dependent permissions, the
-   file receiver checks to see if the sender has the same system ID (e.g.
-   both the sending and receiving systems are UNIX, or both are VMS); if
-   so, it decodes and uses the system-dependent permissions; otherwise it
-   uses the generic ones (if any) and applies them to the owner field,
-   setting the other fields appropriately as described in the following
-   sections.
-
-   Setting the incoming file's protection from the A packet is controlled
-   by SET ATTRIBUTES PROTECTION (or PERMISSION), which is ON by default,
-   and its status is displayed by SHOW ATTRIBUTES.
-
-   The main benefit of this feature is to not have to "chmod +x" an
-   executable file after transfer from UNIX to UNIX. Its cross-platform
-   benefits are less evident, perhaps to retain the status of the Unix
-   'x' bit on a VMS system, for subsequent transfer back to a Unix
-   system.
-     _________________________________________________________________
-
-    4.4.2.1. System-Specific Permissions
-
-   System-specific file permissions are used when the two Kermit programs
-   recognize each other as running on the same type of system. For
-   example, both are running under some form of UNIX (it doesn't matter
-   which UNIX variation -- HP-UX, Solaris, AIX, etc -- all use the same
-   scheme for file permissions); or both are running under VMS (even if
-   one is on an Alpha and the other on a VAX, and/or one is old and the
-   other is new).
-
-    4.4.2.1.1. UNIX
-
-   UNIX supports three categories of users, File Owner, Group, and World,
-   and three types of file access permission: Read, Write, and Execute.
-   Thus, a UNIX file's permissions are expressed in 9 bits.
-
-   The system-dependent permission string for UNIX is a 3-digit octal
-   string, the low-order 9 bits of the st_mode member of the stat struct;
-   we deliberately chop off the "file format" bits because they are not
-   permissions, nor do we convey the setuid/setgid bits, lock bit, sticky
-   bit, etc.
-
-    4.4.2.1.2. VMS
-
-   VMS supports four categories of users, System, File Owner, Group, and
-   World, and four types of file access permission: Read, Write, Execute,
-   and Delete. Thus, a VMS file's permissions are expressed in 16 bits.
-
-   The system-dependent protection string for VMS is a 4-digit
-   hexadecimal string, corresponding to the internal-format protection
-   word of the file (RWED for each of World,Group,Owner,System). A new
-   file normally gets all 16 protection bits from the original file of
-   the same name.
-
-   Note: VMS-to-VMS transfers take place in LABELED mode when the two
-   C-Kermits recognize each other's platform as VMS (unless you have
-   disabled LABELED-mode transfers). In this case, all of a file's
-   attributes are preserved in the transfer and the protection mask (and
-   other information) is taken from the file's internal information, and
-   this takes precedence over any information in the Attribute packets.
-   You can defeat the automatic switching into LABELED mode (if you want
-   to) with SET TRANSFER MODE MANUAL.
-     _________________________________________________________________
-
-    4.4.2.2. System-Independent Permissions
-
-   The system-independent ("generic") protection is used when the system
-   IDs of the two Kermit programs do not agree (e.g. one is UNIX, the
-   other is VMS). The generic protection attribute includes the following
-   permissions (not all are applicable to every file system): Read,
-   Write, Append, Execute, Delete, Search. The generic permissions are
-   derived from the owner permissions of the source file, thus, a Unix
-   'w' permission becomes VMS Write,Delete.
-
-   The Owner field of the new file's permissions is set from the incoming
-   generic protection attribute.
-
-   In UNIX, the Group and World permissions are set according to your
-   umask, except that execute permission is NOT set in these fields if it
-   was not also set in the generic protection (and consequently, is set
-   in the Owner field).
-
-   In VMS, the System, Group, and World permissions are set according to
-   the process default file permission (as shown in VMS by SHOW
-   PROTECTION), except that no permissions are allowed in these fields
-   that are not included in the generic permissions.
-
-   Note that the VMS and UNIX interpretations of Execute permission are
-   not identical. In UNIX, a file (binary executable, shell script, etc)
-   may not be executed unless it has Execute permission, and normally
-   files that are not intended for execution do not have Execute
-   permission. In VMS, Read permission implicitly supplies Execute
-   capability. Generally files that have Read permission also have
-   explicit Execute permission, but files (binary executables, DCL
-   command procedures) that have Read permission and not Execute
-   permission can still be executed.
-     _________________________________________________________________
-
-  4.5. File Management Commands
-
-    4.5.1. The DIRECTORY Command
-
-   Prior to C-Kermit 7.0, the DIRECTORY command always ran an external
-   system command (such as "ls" on UNIX) or program to product the
-   directory listing. This had certain advantages, mostly that you could
-   include system-dependent options for customized listings, e.g. on
-   UNIX:
-
-  dir -lt c* | more
-
-   or in VMS:
-
-  directory /size/date/protection/except=*.obj oofa.*;0
-
-   This approach, however, carries some disadvantages: C-Kermit can't
-   return SUCCESS or FAILURE status for (e.g.) "dir foo" according to
-   whether the file "foo" exists; and it runs an inferior process, which
-   might be a problem in some environments for resource and/or security
-   reasons, and won't work at all in a "nopush" environment (e.g. one in
-   which C-Kermit is configured to forbid access to exterior commands and
-   programs, e.g. in a VMS "captive account").
-
-   In C-Kermit 7.0 on VMS and UNIX, and in K95 1.1.19 and later, the
-   DIRECTORY command is internal to Kermit. It can be run in a "nopush"
-   environment and returns SUCCESS or FAILURE status appropriately. In
-   UNIX it prints all dates and times in a consistent way (unlike ls). In
-   VMS it prints precise file sizes, rather than "blocks". It offers
-   several formatting and other options, but it is not necessarily more
-   flexible than the corresponding external commands or programs (the
-   UNIX "ls" program, the VMS "directory" command). The syntax is:
-
-   DIRECTORY [ switch [ switch [ ... ] ] ] [ filespec ]
-
-   If no filespec is given, all files in the current directory are
-   listed.
-
-   Optional switches include all the standard file-selection switches
-   presented in [464]Section 1.5.4, plus:
-
-   /ALL
-          Show both regular files and directories; this is the default.
-
-   /ARRAY:x
-          Instead of displaying a directory listing, put the files that
-          would have been shown (based on the filespec and other
-          selection switches) in the given array. The array need not (and
-          should not) be predeclared; if the array already exists, it is
-          destroyed and reused. The array name can be a single letter,
-          like "a", or any fuller form, such as "&a", "\&a", "\&a[]",
-          etc. If the /ARRAY switch is included, the following other
-          switches are ignored: /BRIEF, /VERBOSE, /HEADING, /PAGE,
-          /ENGLISHDATE, /ISODATE, /XFERMODE, /MESSAGE, /SORT, /REVERSE,
-          /ASCENDING. In other words, only file selection switches are
-          meaningful with /ARRAY: /FILES, /DIRECTORIES, /ALL, /DOTFILES,
-          /NOBACKUP, /RECURSIVE, /SMALLER, /LARGER, /AFTER, /BEFORE,
-          /EXCEPT, etc. The resulting array has the number of files (n)
-          as its 0th element, and the filenames in elements 1 through n
-          Example:
-
-  dir /array:&a /files /nobackup /after:19990101 /larger:10000 [ab]*
-  show array &a
-
-   /FILES
-          Only show regular files.
-
-   /DIRECTORIES
-          Only show directories.
-
-   /BACKUP
-          In UNIX, OS-9, K-95, and other versions that support SET FILE
-          COLLISION BACKUP and create backup files by appending .~n~ to
-          the filename (where "n" is a number), /BACKUP means to include
-          these files in directory listings. This is the default.
-
-   /NOBACKUP
-          This is the opposite of /BACKUP: that is, do not include backup
-          files in the listing.
-
-   /BRIEF
-          List filenames only; use a compact format, as many filenames as
-          will fit across the screen (based on the longest name). A brief
-          listing is always sorted alphabetically.
-
-   /VERBOSE
-          List one file per line, and include date, size, and (in UNIX
-          only) permissions of each file. This is the opposite of /BRIEF,
-          and is the default.
-
-   /PAGE
-          Pause at the end of each screenful and give a "more?" prompt,
-          even if SET COMMAND MORE-PROMPTING is OFF.
-
-   /NOPAGE
-          Don't pause at the end of each screenful and give a "more?"
-          prompt, even if SET COMMAND MORE-PROMPTING is ON. If neither
-          /PAGE or /NOPAGE is given, paging is according to the
-          prevailing COMMAND MORE-PROMPTING setting (which can be
-          displayed with SHOW COMMAND).
-
-   /ENGLISHDATE
-          Show dates in dd-mmm-yyyy format; mmm is the first three
-          letters of the English month name.
-
-   /ISODATE
-          Show dates in yyyy-mm-dd format; mm is the month number, 1-12.
-          This is the opposite of /ENGLISHDATE, and is the default.
-
-   /HEADINGS
-          Print a heading before the listing and a summary at the end.
-
-   /NOHEADINGS
-          Don't print a heading before the listing or a summary at the
-          end. This is the opposite of /HEADINGS, and is the default.
-
-   /XFERMODE
-          Only in Kermit programs that support SET FILE PATTERNS. If this
-          switch is included, and the filename matches any FILE
-          BINARY-PATTERN ([465]Section 4.3), "(B)" is printed after the
-          filename; otherwise, if it matches a FILE TEXT-PATTERN, "(T)"
-          is printed.
-
-   /NOXFERMODE
-          Don't display transfer-mode indicators. This is the opposite of
-          /XFERMODE and is the default.
-
-   /RECURSIVE
-          Show files not only in the given directory, but also in its
-          subdirectories (if any), their subdirectories, etc.
-
-   /NORECURSIVE
-          Don't show files in subdirectories. This is the opposite of
-          /RECURSIVE, and is the default.
-
-   /MESSAGE:text
-          This lets you specify a short text string to be appended to the
-          end of each directory listing line (a space is supplied
-          automatically). If the text contains any spaces, enclose it in
-          braces, e.g. /MESSAGE:{two words}.
-
-   /NOMESSAGE
-          Don't append any message to the end of each directory listing
-          line (default).
-
-   /SORT:[{NAME,SIZE,DATE}]
-          Sort the listing by name, size, or date. If the /SORT switch is
-          given but the "sort-by" keyword is omitted, the listing is
-          sorted by name. /SORT:NAME /ASCENDING (alphabetic sort by name)
-          is the default.
-
-   /NOSORT
-          Don't sort the listing. Files are listed in whatever order they
-          are supplied by the operating system, e.g. inode order in UNIX.
-
-   /REVERSE
-          If the /SORT switch is given, reverse the order of the sort.
-          Synonym: /DESCENDING.
-
-   /ASCENDING
-          If the /SORT switch is given, sort the listing in normal order.
-          This is the opposite of /REVERSE and is the default.
-
-   Note that most of the DIRECTORY-specific switches come in pairs, in
-   which one member of a pair (e.g. /NOHEADINGS) is the opposite of the
-   other (e.g. /HEADINGS).
-
-   If you always want to use certain options, you can set them with the
-   SET OPTIONS DIRECTORY command ([466]Section 1.5.5). Use SHOW OPTIONS
-   to list the options currently in effect. To make the desired options
-   apply every time you run C-Kermit, put a SET OPTIONS DIRECTORY command
-   in your C-Kermit customization file, specifying the desired options.
-   Options set in this manner apply to every subsequent DIRECTORY
-   command. Of course, if you include switches in a DIRECTORY command,
-   these override any defaults, built-in or custom. Example:
-
-  DIRECTORY            ; Use "factory defaults"
-  SET OPTIONS DIRECTORY /SORT:SIZE /REVERSE /HEADINGS  ; Customize defaults
-  DIRECTORY            ; Use customized defaults
-  DIR /SORT:NAME       ; Override customized default SORT key
-  SET OPT DIR /RECURS  ; Add /RECURSIVE to customized defaults
-  DIR /ASCEND          ; Override customized default SORT order
-
-   Notes:
-
-     * Only a single sort key is supported; there is presently no way to
-       have multiple sort keys.
-     * If the /BRIEF switch is given, all other switches (except
-       /[NO]RECURSIVE, /[NO]DOTFILES, /DIRECTORIES, /FILES, and /ALL) are
-       ignored.
-     * /SORT:anything gives incorrect results if any files have lengths
-       greater than 10 digits (i.e. that are more than 9999999999 bytes
-       long, i.e. if they are 10GB or more in size) because the overlong
-       length field causes the date and name fields to be misaligned.
-     * /SORT:NAME is redundant in VMS since VMS returns filenames in
-       alphabetic order anyway.
-     * /SORT:NAME ignores alphabetic case on platforms where case does
-       not matter in filenames, but this works only for unaccented Roman
-       letters A-Z.
-     * /SORT:NAME is currently based on code values, and so works fine
-       for ASCII, but will probably produce unexpected results for files
-       with non-ASCII or 8-bit characters in their names. (Locale-based
-       sorting raises rather significant issues of portability, size,
-       performance, etc.)
-     * /SORT:DATE works right only for ISO-format dates, not English
-       ones.
-     * /SORT:SIZE sorts the size field lexically. On some platforms (e.g.
-       Windows), the size of a directory file is listed as "<DIR>" rather
-       than as a number; in this case, the "<DIR>" files are gathered at
-       the end (or beginning, depending on the sort order) of the
-       listing.
-     * /RECURSIVE is accepted but ignored in AOS/VS. Use the normal
-       system-specific filespec notation, e.g. "dir #.txt".
-     * /RECURSIVE has no affect when a full, absolute pathname is given;
-       e.g. "dir /recursive /tmp/foo" (where "foo" is a regular file)
-       only shows the "/tmp/foo" file. If you want to see all "foo" files
-       in the /tmp tree, do "cd /tmp" and then "dir /recursive foo".
-     * If a file size of -1 is shown, or date-time of 0000-00-00
-       00:00:00, this means the file was located, but access to
-       information about the file was denied to C-Kermit.
-     * In VMS, if FOO.DIR;1 is a directory within your current directory,
-       "directory foo" and "directory [.foo]" list the files in the
-       [.FOO] subdirectory, but "directory foo.dir" lists the directory
-       file itself; similarly for "*.dir" versus "[.*]", etc.
-     * In UNIX, if "foo" is a directory within your current directory,
-       "directory foo" lists the files in the foo directory. If you want
-       to list the foo directory file itself, put an asterisk at the end:
-       "dir foo*".
-
-   Hint: How to find the biggest files in a directory tree:
-
-  cd xxx ; (root of tree)
-  directory /sort:size /recursive /reverse /dotfiles /page
-
-   Another hint: If you often use several different directory-listing
-   formats, define macro shortcuts for them:
-
-  DEFINE WD DIRECTORY /SORT:DATE /REVERSE \%*  ; Reverse chronological order
-  DEFINE SD DIRECTORY /SORT:SIZE /REVERSE \%*  ; Reverse order of size
-  DEFINE ND DIRECTORY /SORT:NAME /ASCEND \%*   ; Alphabetical by name
-  DEFINE DL DIR /DIR /SORT:NAME /ASCEND \%*    ; Alphabetical directory list
-
-   Put these definitions in your C-Kermit customization file. Note that
-   "\%*" ([467]Section 7.5) in these definitions lets you include other
-   switches in your macro invocations, e.g.:
-
-  wd /headings *.txt
-
-   Of course you can still access your external directory listing program
-   by using RUN or "!", e.g. in VMS:
-
-  run directory /size/date/protection/except=*.obj oofa.*;0
-
-   or:
-
-  !dir /size/date/prot/exc=*.obj oofa.*;0
-
-   In UNIX, use "!ls" or just "ls" (which is a special synonym for
-   "!ls").
-     _________________________________________________________________
-
-    4.5.2. The CD and BACK Commands
-
-   In C-Kermit 7.0, the CD command has a new friend, the BACK command.
-   BACK means "CD to my previous current directory". A second BACK brings
-   you back to where you were before the first one; thus successive BACK
-   commands switch back and forth between two directories.
-
-    4.5.2.1. Parsing Improvements
-
-   The CD command, as well as other commands that parse a directory name,
-   were changed in 7.0 to provide all the expected functions: completion
-   on Tab or Esc, directory-name lists on ?, etc. Other affected commands
-   include SET SERVER GET-PATH, SET TEMP-DIRECTORY, SET FILE
-   DOWNLOAD-DIRECTORY, and SPACE. CD and REMOTE CD also now work with
-   logical names.
-
-   In VMS, the situation is a bit complicated since a directory name can
-   look like "DEV:", "[FOO.BAR]", "DEV:[FOO.BAR]", "[FOO]BAR.DIR;1", etc.
-   Completion and ?-help might not always work, but they do in many
-   cases. Examples:
-
-  cd ?           Lists all subdirectories of the current directory
-  cd []?         Ditto
-  cd k?          Ditto, but only those starting with K
-  cd [foo]?      Lists all subdirectories of the [FOO] directory
-  cd [-]?        Lists all subdirectories of the superior directory
-  cd [--]?       Lists all subdirectories of the directory 2 levels up
-  cd [...]?      Lists all directories below the current one
-  cd [foo.?      Does not work.
-
-   C-Kermit allows all of the following in VMS:
-
-  cd bar         CD to subdirectory BAR of the current directory
-  cd .bar        Ditto
-  cd [.bar]      Ditto
-  cd bar.dir     etc...
-  cd bar.dir;
-  cd bar.dir;1
-  cd [foo.bar]
-  cd bar.baz     This can go more than 1 level deep...
-  cd dir:        (where logical name DIR is defined as [FOO.BAR])
-
-   As well as the following:
-
-  cd ..          Go up one level as in UNIX
-  cd .           The current directory
-  cd             My login directory
-
-   Note that "cd -" (go up one level) does not work as expected, because
-   "-" is Kermit's command continuation character. However, "cd [-]", and
-   "
-   cd {-}" have the desired effect (and so does "cd ..", which is easier
-   to type).
-     _________________________________________________________________
-
-    4.5.2.2. The CDPATH
-
-   The CD command in the UNIX, Windows, OS/2, and VMS versions of
-   C-Kermit, as of version 6.1 / 1.1.12, searches the CDPATH for the
-   given directory, if it is not absolute and if a CDPATH environment
-   variable is defined. Example (in UNIX ksh or bash):
-
-  $ export CDPATH=$HOME:$HOME/kermit:/tmp
-
-   Now if you give a "cd xxx" command, no matter what your current
-   directory is, if the "xxx" directory is not a subdirectory of your
-   current directory, then the xxx subdirectory of your home directory is
-   used or if that does not exist, then the xxx subdirectory of the
-   kermit subdirectory of your home directory is used or if that does not
-   exist, then /tmp/xxx is used. This is how the ksh "cd" command works,
-   and now the C-Kermit CD command works the same way.
-
-   In VMS, you can define CDPATH to be a list of directories that contain
-   actual directory delimiters, and/or logical names representing
-   directories, using commas to separate them, e.g.:
-
-  $ define cdpath [HOME],[SOMEOTHERDIR],[HOME.MISC]
-  $ define cdpath SYS$LOGIN:,DISK1:[HOME],DISK2:[SCRATCH.IVAN]
-
-   Example:
-
-  $ define cdpath SYS$LOGIN:,[IVAN],[OLAF],[OLGA.MISC]
-  $ kermit
-  DISK1:[OLGA] C-Kermit> cd blah
-
-   tries the BLAH subdirectory of the user's login directory, then
-   [OLGA.BLAH], [IVAN.BLAH], [OLAF.BLAH], and [OLGA.MISC.BLAH], in that
-   order, using the first one it finds, failing if it finds none.
-
-   In C-Kermit 7.0, you may also set the CDPATH from the Kermit prompt:
-
-   SET CD PATH path
-          Allows the CD PATH to be set from within C-Kermit.
-
-   SHOW CD shows the CD path and all other information relevant to the CD
-   command.
-     _________________________________________________________________
-
-    4.5.2.3. CD Messages
-
-   Whenever you change directory, you can have C-Kermit display a "Read
-   Me" file from the new directory automatically. The commands are:
-
-   SET CD MESSAGE { ON, OFF, FILE list }
-          ON enables this feature; OFF (the default) disables it. File
-          lets you specify the name of the "Read Me" file. A list of
-          names to look for can be given in the following format:
-
-  {{name1}{name2}{name3}{...}}
-
-          e.g.:
-
-  SET SERVER CD-MESSAGE FILE {{./.readme}{README.TXT}{READ.ME}}
-
-          The default list of CD-message files is system dependent.
-
-   SHOW CD shows your current directory, previous directory, CD path, and
-   CD message info.
-     _________________________________________________________________
-
-    4.5.3. Creating and Removing Directories
-
-   The MKDIR command now allows you to create multiple directories at
-   once:
-
-  C-Kermit> mkdir a/b/c/d
-
-   creates the directory a in the current directory (if it doesn't exist
-   already), and then creates subdirectory b in the a directory (if it
-   didn't exist already), and so on.
-
-   If you use MKDIR to try to create a directory that already exists,
-   C-Kermit will print a warning ("?Directory already exists"), but the
-   MKDIR command will still succeed. If you want to avoid the warning
-   message, use IF DIRECTORY first to check if the directory already
-   exists.
-
-   The RMDIR command, however, will not remove more than one directory,
-   nor will it remove a directory that contains any files. (There is, as
-   yet, no RMDIR /RECURSIVE command, although one might be added later.)
-
-   In VMS, these commands (like CD) are more forgiving of your syntax
-   than is the DCL command shell; "mkdir oofa" is equivalent to "mkdir
-   [.oofa]" and so on. Also in VMS, you'll find that C-Kermit's RMDIR
-   command is easier than deleting a directory in DCL, since it
-   automatically first gives it owner delete permission if you are the
-   owner.
-     _________________________________________________________________
-
-    4.5.4. The DELETE and PURGE Commands
-
-   The DELETE command now offers a selection of switches, and has a new
-   companion, the PURGE command. First, DELETE:
-
-   DELETE [ switches... ] filespec
-          Deletes the file or files that match the filespec, which may
-          contain wildcards ([468]Section 4.9).
-
-   Optional switches include the standard file-selection switches
-   presented in [469]Section 1.5.4, plus:
-
-   /ASK
-          Before deleting each file, ask permission interactively.
-          Answers are Yes or OK (delete the file), No (don't delete it),
-          or Quit (stop executing the DELETE command).
-
-   /NOASK
-          Don't ask permission to delete each file.
-
-   /LIST
-          List each file and show whether it was deleted. Synonyms: /LOG,
-          /VERBOSE.
-
-   /NOLIST
-          Don't list files while deleting them. Synonyms: /NOLOG, /QUIET.
-
-   /HEADING
-          Print a heading and summary line.
-
-   /NOHEADING
-          Don't print a heading and summary line.
-
-   /PAGE
-          When listing, pause at the end of each screenful and give the
-          "More?" prompt. If you reply "n" (no), the DELETE command
-          terminates.
-
-   /SIMULATE
-          Do everything implied by the given switches and filespec,
-          except do not actually delete any files. This lets you preview
-          which files would be deleted; implies /LIST.
-
-   Now the PURGE command:
-
-   PURGE [ switches... ] [ filespec ]
-          (VMS only) Runs the DCL PURGE command. Switches and filespec,
-          if any, are passed directly to DCL without parsing or
-          verification. Deletes excess versions of the given (or all)
-          files. The rest of this section does not apply to VMS.
-
-   PURGE [ switches... ] [ filespec ]
-          (UNIX only) Deletes "backup files" that match the filespec,
-          which may contain wildcards ([470]Section 4.9). If no filespec
-          is given, all backup files in the current directory are
-          selected (subject to modification by any switches). Do not
-          include backup notation in the filespec.
-
-   Explanation:
-
-   To avoid destroying preexisting files when a new file arrives that has
-   the same name, C-Kermit backs up the old file by appending a "backup
-   number" to its name. In UNIX, the backup suffix consists of a period,
-   a tilde, a number, and another tilde. For example, if a file called
-   oofa.txt exists and a new oofa.txt file arrives, the original is
-   renamed to oofa.txt.~1~. If another oofa.txt file arrives, the
-   existing one is renamed to oofa.txt.~2~. And so on. This system is
-   compatible with the one used by EMACS. Thus over time, if you receive
-   a lot of files with C-Kermit or edit them with EMACS, backup files can
-   build up. The new PURGE command lets you clean out accumulated backup
-   files:
-
-   Optional switches include the standard file-selection switches
-   presented in [471]Section 1.5.4, plus all the switches listed above
-   for the DELETE command, plus:
-
-   /KEEP:n
-          Retains the n most recent (highest-numbered) backup files for
-          each file. For example, if oofa.txt, oofa.txt.~1~,
-          oofa.txt.~2~, oofa.txt.~10~, oofa.txt.~12~, and oofa.txt.~100~
-          exist, "purge /keep:2 oofa.txt" deletes oofa.txt.~1~,
-          oofa.txt.~2~, and oofa.txt.~10~, and keeps oofa.txt,
-          oofa.txt.~12~, and oofa.txt.~100~. If /KEEP is given without a
-          number, one (the highest numbered) backup file is kept.
-
-   CAUTION: The PURGE command should be used only when *.~*~ files truly
-   are backup files. This is the case for EMACS, and it is the DEFAULT
-   for C-Kermit. However, if C-Kermit's FILE COLLISION has been set to
-   RENAME, newly received files will look like backup files. In that
-   case, don't use the PURGE command or you'll be removing new files
-   rather than old ones. (Use SHOW FILE to find the FILE COLLISION
-   setting.)
-
-   The PURGE command is presently available only in UNIX. The command
-   succeeds if it deleted any files, or if it deleted no files but there
-   were no errors. It fails if it deleted no files and there were errors
-   (i.e. deletion was attempted but failed). In VMS, backup file versions
-   are handled automatically by the OS, and a PURGE command can be used
-   at the VMS prompt to clean them up.
-
-   If you want certain switches to be supplied automatically with each
-   DELETE or PURGE command, you can set them with SET OPTIONS
-   ([472]Section 1.5.5) and you can display any such settings with SHOW
-   OPTIONS. Of course you can override them on a per-command basis by
-   including switches in your PURGE or DELETE command.
-
-   Also see SET FILE COLLISION, SHOW FILE, SEND /NOBACKUP, SET SEND
-   BACKUP, and DIRECTORY /[NO]BACKUP.
-     _________________________________________________________________
-
-  4.6. Starting the Remote Kermit Server Automatically
-
-   As noted on pages 275-276 of [473]Using C-Kermit 2nd edition, you can
-   have Kermit send "kermit receive" commands automatically when it is in
-   local mode and you give a SEND or similar command, to start the remote
-   Kermit receiver in case it is not already started. The "kermit
-   receive" commands are specified by:
-
-  SET PROTOCOL KERMIT binary-receive-command text-receive-command
-
-   As of version 7.0, a Kermit protocol option has been added to send a
-   string to the host in advance of any Kermit packets when you give a
-   GET-class or REMOTE command. This will switch the remote C-Kermit into
-   the appropriate mode or, if the remote system is at a system command
-   (shell) prompt, execute the string on the remote system. The new
-   syntax of the SET PROTOCOL KERMIT command is:
-
-  SET PROTOCOL KERMIT [ s1 [ s2 [ s3 ] ] ]
-
-   where:
-
-       Default         Meaning
-  s1  {kermit -ir}     Remote "kermit receive in binary mode" command.
-  s2  {kermit -r}      Remote "kermit receive in text mode" command.
-  s3  {kermit -x}      Remote "start kermit server" command.
-
-   NOTE: If the remote Kermit is 6.0, the following are recommended for
-   fast startup and high-performance file transfer (see Appendix I in
-   [474]Using C-Kermit, second Edition, for command-line options):
-
-  s1   kermit -YQir   (Kermit receive binary, skip init file, fast.)
-  s2   kermit -YQTr   (Kermit receive text, skip init file, fast.)
-  s3   kermit -YQx    (Kermit server, skip init file, fast.)
-
-   If the remote is C-Kermit 7.0 or later, change the -x option (enter
-   server mode) to -O (uppercase letter O), which means "enter server
-   mode for One transaction only); this way, it is not stuck in server
-   after the transfer. Also note that the Q is redundant in version 7.0,
-   since fast Kermit protocol settings are now the default.
-
-   Note that in case the C-Kermit executable is called "wermit" or
-   "ckermit" you can change "kermit" in the strings above to "wermit" or
-   "ckermit" and C-Kermit 7.0 or later will recognize these as synonyms
-   for "kermit", in case it is at its command prompt when one of these
-   strings is sent to it.
-     _________________________________________________________________
-
-  4.7. File-Transfer Command Switches
-
-   Over the years, various new methods of transferring a file have
-   accumulated, until we had, in addition to the SEND command, also MOVE
-   (send and then delete), MAIL (send as email), REMOTE PRINT (send to be
-   printed), CSEND (send the output of a command), PSEND (send a part of
-   a file), BSEND (send in binary mode), RESEND (resume an interrupted
-   SEND), etc etc. Similarly: GET, REGET, CGET, RETRIEVE, and so on.
-
-   Not only is it confusing to have different names for these commands,
-   many of which are not real words, but this also does not allow all
-   combinations, like "send a file as mail, then delete it".
-
-   In C-Kermit 7.0, the SEND, GET, and RECEIVE commands were restructured
-   to accept modifier switches (switches are explained in [475]Section
-   1.5).
-     _________________________________________________________________
-
-    4.7.1. SEND Command Switches
-
-   Without switches, the SEND command still works exactly as before:
-
-  send oofa.txt      ; send a single file
-  send oofa.*        ; send multiple files
-  send oofa.txt x.x  ; send oofa.txt as x.x (tell receiver its name is x.x)
-  send               ; send from SEND-LIST
-
-   But now the following modifier switches may be included between "send"
-   and the filename. Zero, one, two, or more switches may be included in
-   any combination that makes sense. Switch names (such as /BINARY) can
-   be abbreviated, just like any other keywords. Most of these switches
-   work only when using Kermit protocol (/TEXT and /BINARY are the
-   exceptions).
-
-   /AFTER:date-time
-          Specifies that only those files modified (or, in VMS, created)
-          after the given date-time (see [476]Section 1.6) are to be
-          sent. Examples:
-
-  send /text /after:{2-Feb-1997 10:28:30} *.txt
-  send /text /after:\fdate(oofa.txt) *.txt
-
-          Synonym: /SINCE.
-
-   /ARRAY:arrayname
-          Specifies that instead of sending a file, C-Kermit is to send
-          the contents of the given array. Since an array does not have a
-          filename, you should include an /AS-NAME switch to specify the
-          name under which the array is to be sent (if you do not, the
-          name "_array_x_" is used, where 'x' is replaced by the array
-          designator). See [477]section 7.10 for array-name syntax. As
-          noted in that section, you can also include a range to have a
-          segment of the array sent, rather than the whole thing; for
-          example: "send /array:&a[100:199]". It is strongly recommended
-          that you accompany the /ARRAY switch with a /TEXT or /BINARY
-          switch to force the desired transfer mode, since otherwise the
-          various automatic mechanisms might switch to binary mode when
-          you really wanted text, or vice versa. In text mode a line
-          terminator is added to the end of each array element, but not
-          in binary mode. For details and examples see [478]Section
-          7.10.11.
-
-   /AS-NAME:text
-          Specifies "text" as the name to send the file under. You can
-          also still specify the as-name as the second filename on the
-          SEND command line. The following two commands are equivalent:
-
-  send oofa.txt oofa.new
-  send /as:oofa.new oofa.txt
-
-   /BEFORE:date-time
-          Specifies that only those files modified (or, in VMS, created)
-          before the given date-time ([479]Section 1.6) are to be sent.
-
-   /BINARY
-          Performs this transfer in binary mode without affecting the
-          global transfer mode, overriding not only the FILE TYPE and
-          TRANSFER MODE settings, but also the FILE PATTERN setting, but
-          for this SEND command only. In other words, SEND /BINARY means
-          what it says: send the file in binary mode, regardless of any
-          other settings. Example:
-
-  set file type text      ; Set global transfer mode to text
-  send /binary oofa.zip   ; Send a file in binary
-  send oofa.txt           ; This one is sent in text mode
-
-   /COMMAND
-          SEND /COMMAND is equivalent to CSEND ([480]Section 4.2.2) -- it
-          says to send the output from a command, rather than the
-          contents of a file. The first "filename" on the SEND command
-          line is interpreted as the name of a command; the second (if
-          any) is the as-name. Examples:
-
-  send /command {grep Sunday oofa.txt} sunday.txt
-  send /as-name:sunday.txt /command {grep Sunday oofa.txt}
-  send /bin /command {tar cf - . | gzip -c} {!gunzip -c | tar xf -}
-
-   /DELETE
-          Deletes the file (or each file in the group) after it has been
-          sent successfully (but does not delete it if it was not sent
-          successfully). SEND /DELETE is equivalent to MOVE. Has no
-          effect when used with /COMMAND. Example:
-
-  send /delete *.log
-
-   /DOTFILES
-          (UNIX and OS-9 only) Normally files whose names begin with "."
-          are skipped when matching wildcards that do not also beging
-          with ".". Include /DOTFILES to force these files to be included
-          too.
-
-   /RECURSIVE
-          Descend the through the directory tree when locating files to
-          send. Automatically sets /PATHNAMES:RELATIVE. Explained in
-          [481]Section 4.11 .
-
-   /EXCEPT:pattern
-          See [482]Section 1.5.4.
-
-   /NOBACKUP
-          This means to skip backup files when sending, even if they
-          match the SEND file specification. This is equivalent to using
-          SEND /EXCEPT and including *.~[0-9]*~ in the exception list (or
-          *.~*~ if Kermit was built without pattern-matching support; see
-          [483]Section 4.9.1). Including this switch is equivalent to
-          giving SET SEND BACKUP OFF ([484]Section 4.0.6) prior to SEND,
-          except its effect is local to the SEND command with which it
-          was given.
-
-   /NODOTFILES
-          The opposite of /DOTFILES (q.v.)
-
-   /FILENAMES:{CONVERTED,LITERAL}
-          Use this switch to override the current global SET FILE NAMES
-          setting for this transfer only.
-
-   /FILTER:command
-          This specifies a filter to pass the file through before sending
-          it. See the [485]section on file-transfer pipes and filters.
-          The /FILTER switch applies only to the file-transfer command it
-          is given with; it does not affect the global SEND FILTER
-          setting, if any.
-
-   /IMAGE
-          VMS: Sends in image mode. Non-VMS: same as /BINARY.
-
-   /LABELED
-          VMS and OS/2 only: Sends in labeled mode.
-
-   /LARGER-THAN:number
-          Specifies that only those files that are longer than the given
-          number of bytes are to be sent.
-
-   /LISTFILE:filename
-          Specifies that the files to be sent are listed in a file with
-          the given filename. The file contains one filename per line.
-          These filenames are not checked in any way; each filename is
-          taken and does not use or depend on any Kermit-specific syntax.
-          In particular, backslashes are not treated specially, leading
-          and trailing spaces are not stripped, etc. However, if a
-          filename contains wildcards, they are expanded. Example: If a
-          file named files.txt contains the following lines:
-
-  blah.txt
-  oofa*
-  x.x
-
-          (but without leading or trailing spaces), then the C-Kermit
-          command "send /listfile:files.txt" will send the files
-          blah.txt, x.x, and all files whose names start with "oofa",
-          assuming the files exist and are readable. The /LISTFILE
-          switch, can, of course, be used with other switches when it
-          makes sense, for example, /EXCEPT, /BINARY, /AFTER, /SMALLER,
-          /MOVE-TO, /DELETE, /AS-NAME with a template, etc.
-
-   /MAIL:address
-          Sends the file as e-mail to the given address or addresses.
-          "send /mail:address filename" is equivalent to "mail filename
-          address". You can include multiple addresses separated by
-          commas. Examples:
-
-  send /mail:kermit-support@columbia.edu packet.log
-  send /mail:cmg,fdc,jrd oofa.txt
-
-          As with any switch argument, if the address or address list
-          contains any spaces, you must enclose it in braces. The format
-          of the addresses must agree with that understood by the
-          mail-sending program on the receiver's computer.
-
-   /MOVE-TO:directory-name
-          Specifies that after each (or the only) source file is sent
-          successfully, and ONLY if it is sent successfully, it should be
-          moved to the named directory. If the directory name contains
-          spaces, enclose it in braces. If the directory does not exist,
-          it is created if possible; if it can't be created, the command
-          fails and an error message is printed. Example:
-
-  send /text /move-to:/users/olga/backup/ *.txt
-
-   /NOT-AFTER:date-time
-          Specifies that only those files modified at or before the given
-          date and time are to be sent.
-
-   /NOT-BEFORE:date-time
-          Specifies that only those files modified at or after the given
-          date and time are to be sent.
-
-   /PATHNAMES:{OFF,ABSOLUTE,RELATIVE}
-          Use this switch to override the current global SET SEND
-          PATHNAMES setting for this transfer only. /PATHNAMES:ABSOLUTE
-          or RELATIVE also sets /FILENAMES:LITERAL (also for this
-          transfer only) since pathnames are not sent otherwise.
-
-   /RENAME-TO:text
-          Specifies that after the (or each) source file is sent
-          successfully, and ONLY if it is sent successfully, it should be
-          renamed to the name given. If the name contains spaces, enclose
-          it in braces. If a file group is being sent, then the "text"
-          must contain a variable reference such as \v(filename) (see
-          [486]Section 4.1). Example:
-
-  send /rename-to:ok_\v(filename) *.*
-
-          This sends each file in the current directory and if it was
-          sent successfully, changes its name to begin with "ok_".
-
-   /SMALLER-THAN:number
-          Specifies that only those files that are smaller than the given
-          number of bytes are to be sent.
-
-   /SUBJECT:text
-          Subject for email. Actually, this is just a synonym for
-          /AS-NAME. If the text includes spaces, you must enclose it in
-          braces. If you don't specify a subject (or as-name), the name
-          of the file is used as the subject. Example:
-
-  send /mail:kermit-support@columbia.edu /subj:{As requested} packet.log
-
-   /PRINT:options
-          Sends the file to be printed, optionally specifying options for
-          the printer. Equivalent to REMOTE PRINT filename options.
-          Examples:
-
-  send /print oofa.txt              ; No options.
-  send /print:/copies=3 oofa.txt    ; "/copies=3" is a VMS PRINT switch.
-  send /print:-#3 oofa.txt          ; "-#3" is a UNIX lpr switch.
-
-   /PROTOCOL:name
-          Uses the given protocol to send the file (Kermit, Zmodem, etc)
-          for this transfer without changing global protocol. Only
-          available in Kermit 95, UNIX, and OS-9. Example:
-
-  set protocol kermit               ; Set global protocol
-  send /proto:zmodem /bin oofa.zip  ; Send just this file with Zmodem
-  send oofa.txt                     ; This file is sent with Kermit
-
-   /QUIET
-          When sending in local mode, this suppresses the file-transfer
-          display.
-
-   /RECOVER
-          Used to recover from a previously interrupted transfer; SEND
-          /RECOVER is equivalent to RESEND. Recovery only works in binary
-          mode; SEND /RECOVER and RESEND include an implied /BINARY
-          switch. Even then, recovery will successful only if (a) the
-          original (interrupted) transfer was also in binary mode, or (b)
-          if it was in text mode, the two Kermit programs run on
-          platforms where text-mode transfers are not length-changing.
-
-   /STARTING:number
-          Starts sending the file from the given byte position. SEND
-          /STARTING:n filename is equivalent to PSEND filename n.
-
-   /TEXT
-          Performs this transfer in text mode without affecting the
-          global transfer mode, overriding not only the FILE TYPE and
-          TRANSFER MODE settings, but also the FILE PATTERN setting, for
-          this SEND command only. In other words, SEND /TEXT really send
-          the file in text mode, regardless of any other settings or
-          negotiations.
-
-   About mail... Refer to [487]Section 4.7.1. The same rules apply as for
-   file transfer. If you are mailing multiple files, you can't use an
-   as-name (in this case, a subject) unless it contains replacement
-   variables like \v(filenum). For example, if you:
-
-  send /mail:somebody@xyz.com *.txt
-
-   Then each file will arrive as a separate email message with its name
-   as the subject. But if you:
-
-  send /mail:somebody@xyz.com /subject:{Here is a file} *.txt
-
-   Then each file message will have the same subject, which is probably
-   not what you want. You can get around this with constructions like:
-
-  send /mail:somebody@xyz.com /subject:{Here is \v(filename)} *.txt
-
-   which embed the filename in the subject.
-
-   The MOVE, CSEND, MAIL, and RESEND commands now also accept the same
-   switches. And the switches are also operative when sending from a
-   SEND-LIST (see [488]Using C-Kermit, 2nd Ed, pp.191-192), so, for
-   example, it is now possible to SEND /PRINT or SEND /MAIL from a
-   SEND-LIST.
-
-   The MSEND and MMOVE commands also take switches, but not all of them.
-   With these commands, which take an arbitrary list of filespecs, you
-   can use /BINARY, /DELETE, /MAIL, /PRINT, /PROTOCOL, /QUIET, /RECOVER,
-   and /TEXT (and /IMAGE or /LABELED, depending on the platform). MMOVE
-   is equivalent to MSEND /DELETE. (If you want to send a group of files,
-   but in mixed transfer modes with per-file as-names, use ADD SEND-LIST
-   and then SEND.)
-
-   The MSEND/MMOVE switches come before the filenames, and apply to all
-   of them:
-
-  msend /print /text *.log oofa.txt /etc/motd
-
-   If you type any of these commands (SEND, CSEND, MSEND, etc) followed
-   by a question mark (?), you will see a list of the switches you can
-   use. If you want to see a list of filenames, you'll need to type
-   something like "send ./?" (UNIX, OS/2, Windows, etc), or "send []?"
-   (VMS), etc. Of course, you can also type pieces of a filename
-   (anything that does not start with "/") and then "?" to get a list of
-   filenames that start that way; e.g. "send x.?" still works as before.
-
-   In UNIX, where "/" is also the directory separator, there is usually
-   no ambiguity between a fully-specified pathname and a switch, except
-   when a file in the root directory has the same name as a switch (as
-   noted in [489]Section 1.5):
-
-  send /etc/motd                        ; Works as expected
-  send /command                         ; ???
-
-   The second example interprets "/command" as a switch, not a filename.
-   To send a file actually called "command" in the root directory, use:
-
-  send {/command}
-
-   or other system-dependent forms such as //command, /./command,
-   c:/command, etc, or cd to / and then "send command".
-     _________________________________________________________________
-
-    4.7.2. GET Command Switches
-
-   Without switches, the GET command still works about the same as
-   before:
-
-  get oofa.txt                          ; GET a single file
-  get oofa.*                            ; GET multiple files
-
-   However, the mechanism for including an "as-name" has changed.
-   Previously, in order to include an as-name, you were required to use
-   the "multiline" form of GET:
-
-  get
-  remote-filespec
-  local-name
-
-   This was because the remote filespec might contain spaces, and so
-   there would be no good way of telling where it ended and where the
-   local name began, e.g:
-
-  get profile exec a foo
-
-   But now since we can use {braces} for grouping, we don't need the
-   multiline GET form any more, and in fact, support for it has been
-   removed. If you give a GET command by itself on a line, it fails and
-   an error message is printed. The new form is:
-
-   GET [ switches... ] remote-name [ local-name ]
-          Ask the server to send the file whose name is remote-name. If
-          the optional local-name is given, store it locally under this
-          name. If the remote-name or local-name contains spaces, they
-          must be enclosed in braces:
-
-  get {profile exec a} foo
-  get oofa.txt {~/My Files/Oofa text}
-
-   If you want to give a list of remote file specifications, use the MGET
-   command:
-
-   MGET [ switches... ] remote-name [ remote-name [ remote-name ... ] ]
-          Ask the server to send the files whose names are given.
-
-   Now you can also include modifier switches between GET or MGET and the
-   remote-name; most of the same switches as SEND:
-
-   /AS-NAME:text
-          Specifies "text" as the name to store the incoming file under.
-          (This switch is not available for MGET.) You can also still
-          specify the as-name as the second filename on the GET command
-          line. The following two commands are equivalent:
-
-  get oofa.txt oofa.new
-  get /as:oofa.new oofa.txt
-
-   /BINARY
-          Tells the server to send the given file(s) in binary mode
-          without affecting the global transfer mode. Example:
-
-  set file type text      ; Set global transfer mode to text
-  get /binary oofa.zip    ; get a file in binary mode
-  get oofa.txt            ; This one is transferred in text mode
-
-          Or, perhaps more to the point:
-
-  get /binary foo.txt     ; where "*.txt" is a text-pattern
-
-          This has the expected effect only if the server is C-Kermit 7.0
-          or later or K95 1.1.19 or later.
-
-   /COMMAND
-          GET /COMMAND is equivalent to CGET ([490]Section 4.2.2) -- it
-          says to receive the file into the standard input of a command,
-          rather than saving it on disk. The /AS-NAME or the second
-          "filename" on the GET command line is interpreted as the name
-          of a command. Examples:
-
-  get /command sunday.txt {grep Sunday oofa.txt}
-  get /command /as-name:{grep Sunday oofa.txt} sunday.txt
-  get /bin /command {!gunzip -c | tar xf -} {tar cf - . | gzip -c}
-
-   /DELETE
-          Asks the Kermit server to delete the file (or each file in the
-          group) after it has been transferred successfully (but not to
-          delete it if it was not sent successfully). GET /DELETE is
-          equivalent to RETRIEVE. Example:
-
-  get /delete *.log
-
-   /EXCEPT:pattern
-          Specifies that any files whose names match the pattern, which
-          can be a regular filename, or may contain "*" and/or "?"
-          metacharacters, are to be refused upon arrival. To specify
-          multiple patterns (up to 8), use outer braces around the group,
-          and inner braces around each pattern:
-
-  /EXCEPT:{{pattern1}{pattern2}...}
-
-          See the description of SEND /EXCEPT in [491]Section 4.7.1 for
-          examples, etc. Refusal is accomplished using the Attribute
-          Rejection mechanism (reason "name"), which works only when
-          Attribute packets have been successfully negotiated.
-
-   /FILENAMES:{CONVERTED,LITERAL}
-          Use this switch to override the current global SET FILE NAMES
-          setting for this transfer only.
-
-   /FILTER:command
-          This specifies a filter to pass the incoming file through
-          before writing to disk. See the [492]section on file-transfer
-          pipes and filters. The /FILTER switch applies only to the
-          file-transfer command it is given with; it does not affect the
-          global RECEIVE FILTER setting, if any.
-
-   /IMAGE
-          VMS: Transfer in image mode. Non-VMS: same as /BINARY.
-
-   /LABELED
-          VMS and OS/2 only: Specifies labeled transfer mode.
-
-   /MOVE-TO:directory
-          This tells C-Kermit to move each file that is successfully
-          received to the given directory. Files that are not
-          successfully received are not moved. By default, files are not
-          moved.
-
-   /PATHNAMES:{OFF,ABSOLUTE,RELATIVE,AUTO}
-          Use this switch to override the current global SET RECEIVE
-          PATHNAMES setting for this transfer only. /PATHNAMES:ABSOLUTE
-          or RELATIVE also sets /FILENAMES:LITERAL (also for this
-          transfer only) since incoming pathnames would not be treated as
-          pathnames otherwise. See [493]Section 4.10.
-
-   /QUIET
-          When sending in local mode, this suppresses the file-transfer
-          display.
-
-   /RECOVER
-          Used to recover from a previously interrupted transfer; GET
-          /RECOVER is equivalent to REGET. Recovery only works in binary
-          mode; SEND /RECOVER and RESEND include an implied /BINARY
-          switch. Even then, recovery will successful only if (a) the
-          original (interrupted) transfer was also in binary mode, or (b)
-          if it was in text mode, the two Kermit programs run on
-          platforms where text-mode transfers are not length-changing.
-
-   /RECURSIVE
-          Tells the server that the GET file specification applies
-          recursively. This switch also automatically sets
-          /PATHNAMES:RELATIVE in both the server AND the client. When
-          used in conjunction with /DELETE, this "moves" a directory tree
-          from the server's computer to the client's computer (except
-          that only regular files are deleted from the server's computer,
-          not directories; thus the original directories will be left,
-          but will contain no files). Note that all servers that support
-          /RECURSIVE do not necessarily do so in combination with other
-          switches, such as /RECOVER. (Servers that do include C-Kermit
-          7.0 and later, K95 1.1.19 and later.)
-
-   /RENAME-TO:string
-          This tells C-Kermit to rename each file that is successfully
-          received to the given string. Files that are not successfully
-          received are not renamed. By default, files are not renamed.
-          The string can be a literal string, which is appropriate when
-          only one file is being received, or it can contain one or more
-          variables that are to be evaluated at the time each file is
-          received, such as \v(filename), \v(filenumber), \v(ntime),
-          \v(pid), \v(user), etc. WARNING: if you give a literal string
-          and more than one file arrives, each incoming file will be
-          given the same name (but SET FILE COLLISION BACKUP or RENAME
-          can be used to keep the incoming files from overwriting each
-          other).
-
-   /TEXT
-          Tells the server to perform this transfer in text mode without
-          affecting its global transfer mode. See /BINARY for additional
-          info.
-
-   The /MAIL and /PRINT options are not available (as they are for SEND),
-   but you can use /COMMAND to achieve the same effect, as in these UNIX
-   examples:
-
-  get /command oofa.txt {mail kermit@columbia.edu}
-  get /command oofa.txt lpr
-
-   In OS/2 or Windows, you can GET and print like this:
-
-  get oofa.txt prn
-
-   The CGET, REGET, RETRIEVE commands also accept the same switches as
-   GET. CGET automatically sets /COMMAND; REGET automatically sets
-   /RECOVER and /BINARY, and RETRIEVE automatically sets /DELETE.
-     _________________________________________________________________
-
-    4.7.3. RECEIVE Command Switches
-
-   Without switches, the RECEIVE command still works as before:
-
-  receive            ; Receives files under their own names
-  receive /tmp       ; Ditto, but into the /tmp directory
-  r                  ; Same as "receive"
-  receive foo.txt    ; Receives a file and renames to foo.txt
-
-   Now you can also include modifier switches may be included between
-   "receive" and the as-name; most of the same switches as GET:
-
-   /AS-NAME:text
-          Specifies "text" as the name to store the incoming file under.
-          You can also still specify the as-name as a filename on the
-          command line. The following two commands are equivalent:
-
-  r oofa.new
-  r /as:oofa.new
-
-   /BINARY
-          Performs this transfer in binary mode without affecting the
-          global transfer mode. NOTE: This does not override the incoming
-          filetype (as it does with GET), so this switch is useful only
-          if ATTRIBUTE TYPE is OFF, or if the other Kermit does not send
-          a TYPE (text or binary) attribute. In any case, it has no
-          affect whatsoever on the file sender.
-
-   /COMMAND
-          RECEIVE /COMMAND is equivalent to CRECEIVE ([494]Section 4.2.2)
-          -- it says to receive the file into the standard input of a
-          command, rather than saving it on disk. The /AS-NAME or the
-          "filename" on the RECEIVE command line is interpreted as the
-          name of a command.
-
-  r /command {grep Sunday oofa.txt}
-  r /command /as-name:{grep Sunday oofa.txt}
-  r /bin /command {tar cf - . | gzip -c}
-
-   /EXCEPT:pattern
-          Specifies that any files whose names match the pattern, which
-          can be a regular filename, or may contain "*" and/or "?"
-          metacharacters, are to be refused upon arrival. To specify
-          multiple patterns (up to 8), use outer braces around the group,
-          and inner braces around each pattern:
-
-  /EXCEPT:{{pattern1}{pattern2}...}
-
-          See the description of SEND /EXCEPT in [495]Section 4.7.1 for
-          examples, etc. Refusal is accomplished using the Attribute
-          Rejection mechanism (reason "name"), which works only when
-          Attribute packets have been successfully negotiated.
-
-   /FILENAMES:{CONVERTED,LITERAL}
-          Use this switch to override the current global SET FILE NAMES
-          setting for this transfer only.
-
-   /FILTER:command
-          This specifies a filter to pass the incoming file through
-          before writing to disk. See the [496]section on file-transfer
-          pipes and filters. The /FILTER switch applies only to the
-          file-transfer command it is given with; it does not affect the
-          global RECEIVE FILTER setting, if any.
-
-   /IMAGE
-          VMS: Transfer in image mode. Non-VMS: same as /BINARY. See
-          comments under RECEIVE /BINARY.
-
-   /LABELED
-          VMS and OS/2 only: Specifies labeled transfer mode. See
-          comments under RECEIVE /BINARY.
-
-   /MOVE-TO:directory
-          This tells C-Kermit to move each file that is successfully
-          received to the given directory. Files that are not
-          successfully received are not moved. By default, files are not
-          moved.
-
-   /PATHNAMES:{ABSOLUTE,RELATIVE,OFF,AUTO}
-          Use this switch to override the current global SET RECEIVE
-          PATHNAMES setting for this transfer only. See [497]Section
-          4.10.
-
-   /RECURSIVE
-          When used with the RECEIVE command, /RECURSIVE is simply a
-          synonym for /PATHNAMES:RELATIVE.
-
-   /RENAME-TO:string
-          This tells C-Kermit to rename each file that is successfully
-          received to the given string. Files that are not successfully
-          received are not renamed. By default, files are not renamed.
-          The string can be a literal string, which is appropriate when
-          only one file is being received, or it can contain one or more
-          variables that are to be evaluated at the time each file is
-          received, such as \v(filename), \v(filenumber), \v(ntime),
-          \v(pid), \v(user), etc. WARNING: if you give a literal string
-          and more than one file arrives, each incoming file will be
-          given the same name (but SET FILE COLLISION BACKUP or RENAME
-          can be used to keep the incoming files from overwriting each
-          other).
-
-   /QUIET
-          When receiving in local mode, this suppresses the file-transfer
-          display.
-
-   /TEXT
-          Receives in text mode without affecting the global transfer
-          mode. See comments under RECEIVE /BINARY.
-
-   The /MAIL and /PRINT options are not available, but you can use
-   /COMMAND to achieve the same effect, as in these UNIX examples:
-
-  r /command {mail kermit@columbia.edu}
-  r /command lpr
-
-   In OS/2 or Windows, you can RECEIVE and print like this:
-
-  receive prn
-
-   The CRECEIVE command now also accepts the same switches.
-     _________________________________________________________________
-
-  4.8. Minor Kermit Protocol Improvements
-
-    4.8.1. Multiple Attribute Packets
-
-   C-Kermit 7.0 now sends more than one Attribute packet if a file's
-   attributes do not fit into a single packet of the negotiated length.
-   If a particular attribute (such as file creation date-time) does not
-   fit within the negotiated length (which will only happen when the
-   negotiated length is around 20 or less), that attribute is not sent at
-   all.
-
-    4.8.2. Very Short Packets
-
-   There are certain situations where extremely short packets must be
-   used; 20 or 30 bytes at most. This can happen when one or more devices
-   along the communication path have very small buffers and lack an
-   effective means of flow control. Examples are sometimes cited
-   involving radio modems.
-
-   When the maximum packet length is shorter than certain packets that
-   would be sent, those packets are either truncated or else broken up
-   into multiple packets. Specifically:
-
-    1. Parameter negotiation packets (I, S, and their ACKs) are truncated
-       to the negotiated length. Any parameters that do not fit are reset
-       to their default values. There is no provision in the Kermit
-       protocol for fragmentation and reassembly of parameter strings.
-    2. File header packets (containing the filename) are simply
-       truncated. There is no provision in the Kermit protocol for
-       fragmentation and reassembly of filenames.
-    3. Attribute packets are fragmented and reassembled as described in
-       4.8.1 without loss of data, except in case a field will not fit at
-       all in the negotiated length (the longest attribute is usually the
-       date and time of file creation/modification) because of the rule
-       that attributes may not be broken across packets.
-    4. Data packets and other packets are unaffected -- they can be as
-       short as they need to be, within reason.
-     _________________________________________________________________
-
-  4.9. Wildcard / File Group Expansion
-
-   "Wildcard" refers to the notation used in filenames to specify a group
-   of files by pattern matching.
-
-    4.9.1. In UNIX C-Kermit
-
-   Prior to C-Kermit 7.0, C-Kermit was capable of expanding wildcard
-   strings containing only the "metacharacters" '*' and '?':
-
-   *
-          Matches any sequence of zero or more characters. For example:
-          "ck*.c" matches all files whose names start with "ck" and end
-          with ".c", including "ck.c".
-
-   ?
-          Matches any single character. For example, "ck?.c" matches all
-          files whose names are exactly 5 characters long and start with
-          "ck" and end with ".c". When typing commands at the prompt, you
-          must precede any question mark to be used for matching by a
-          backslash (\) to override the normal function of question mark,
-          which is providing menus and file lists.
-
-   C-Kermit 7.0 adds the additional features that users of ksh, csh, and
-   bash are accustomed to:
-
-   [abc]
-          Square brackets enclosing a list of characters matches any
-          single character in the list. Example: ckuusr.[ch] matches
-          ckuusr.c and ckuusr.h.
-
-   [a-z]
-          Square brackets enclosing a range of characters; the hyphen
-          separates the low and high elements of the range. For example,
-          [a-z] matches any character from a to z.
-
-   [acdm-z]
-          Lists and ranges may be combined. This example matches a, c, d,
-          or m through z.
-
-   {string1,string2,...}
-          Braces enclose a list of strings to be matched. For example:
-          ck{ufio,vcon,cmai}.c matches ckufio.c, ckvcon.c, or ckcmai.c.
-          The strings may themselves contain metacharacters, bracket
-          lists, or indeed, other lists of strings, but (when matching
-          filenames) they may not contain directory separators.
-
-          Thus, the metacharacters in filenames (and in any other field
-          that can be a pattern, such as the IF MATCH pattern, SEND or
-          GET exception lists, etc) are:
-
- * ? [ {
-
-          And within braces only, comma (,) is a metacharacter.
-
-   To include a metacharacter in a pattern literally, precede it with a
-   backslash '\' (or two if you are passing the pattern to a macro).
-   Examples:
-
-  send a*b      ; Send all files whose names start with 'a' and end with 'b'.
-  send a?b      ; Ditto, but the name must be exactly three characters long.
-  send a[a-z]b  ; Ditto, but the second character must be a lowercase letter.
-  send a[x\-z]b ; Ditto, except the second character must be 'x', '-', or 'y'.
-  send a[ghi]b  ; Ditto, except the second character must be 'g', 'h', or 'i'.
-  send a[?*]b   ; Ditto, except the second character must be '?' or '*'.
-  send a[\?\*]b ; Same as previous.
-  send *?[a-z]* ; All files with names containing at least one character
-                ; that is followed by a lowercase letter.
-
-   Or, more practically:
-
-  send ck[cuw]*.[cwh]  ; Send the UNIX C-Kermit source files.
-
-   To refer to the C-Kermit sources files and makefile all in one
-   filespec:
-
-  {{makefile,ck[cuw]*.[cwh]}}
-
-   (NOTE: if the entire pattern is a {stringlist}, you must enclose it it
-   TWO pairs of braces, since the SEND command strips the outer brace
-   pair, because of the "enclose in braces if the filename contains
-   spaces" rule).
-
-   If the makefile is called ckuker.mak:
-
-  ck[cuw]*.{[cwh],mak}
-
-   (NOTE: double braces are not needed here since the pattern does not
-   both begin and end with a brace.)
-
-   To add in all the C-Kermit text files:
-
-  ck[cuw]*.{[cwh],mak,txt}
-
-   All of these features can be used anywhere you would type a filename
-   that is allowed to contain wildcards.
-
-   When you are typing at the command prompt, an extra level of quoting
-   is required for the '?' character to defeat its regular function of
-   producing a list of files that match what you have typed so far, for
-   example:
-
-  send ck[cu]?
-
-   lists all the files whose names start with ckc and cku. If you quote
-   the question mark, it is used as a pattern-matching character, for
-   example:
-
-  send ck\?[ft]io.c
-
-   sends all the file and communications i/o modules for all the
-   platforms: ckufio.c, ckutio.c, ckvfio.c, ckvtio.c, etc.
-
-   If, however, a filename actually contains a question mark and you need
-   to refer to it on the command line, you must use three (3)
-   backslashes. For example, if the file is actually called ck?fio.c, you
-   would use:
-
-  send ck\\\?fio.c
-
-   Further notes on quoting:
-
-     * A single backslash is sufficient for quoting a special character
-       at the command prompt or in a command file. However, when passing
-       patterns to macros you'll need double backslashes, and when
-       referring to these patterns within the macro, you'll need to use
-       \fcontents(\%1) (see [498]Section 1.11.5). You should enclose
-       macro argument references in braces in case grouped arguments were
-       passed. Example:
- define ismatch {
-     if match {\fcont(\%1)} {\fcont(\%2)} {
-         end 0 MATCH
-     } else {
-         end 1 NO MATCH
-     }
- }
- ismatch ab*yz a*\\**z           ; Backslash must be doubled
- ismatch {abc def xyz} *b*e*y*   ; Braces must be used for grouping
-     * Watch out for possible conflicts between {} in filename patterns
-       and {} used for grouping multiple words into a single field, when
-       the pattern has outer braces. For example, in:
-     if match {abc xyz} {a* *z} echo THEY MATCH
-       braces must be used to group "abc xyz" into a single string.
-       Kermit strips off the braces before comparing the string with the
-       pattern. Therefore:
- if match makefile {makefile,Makefile} echo THEY MATCH
-       does not work, but:
- if match makefile {{makefile,Makefile}} echo THEY MATCH
-       does.
-     * If you use a pattern that has outer braces, like {*.txt,*.doc}, in
-       a field that accepts a pattern list (like SEND /EXCEPT:xxx),
-       you'll need to add two extra sets of outer braces:
- send /except:{{{*.txt,*.doc}}} *.*
-
-   C-Kermit's new pattern matching capabilities are also used when
-   C-Kermit is in server mode, so now you can send requests such as:
-
-  get ck[cuw]*.[cwh]
-
-   to a C-Kermit server without having to tell it to SET WILD SHELL
-   first. Previously this would have required:
-
-  mget ckc*.c ckc*.w ckc*.h cku*.c cku*.w cku*.h ckw*.c ckw*.w ckw*.h
-
-   The new pattern matching features make SET WILD SHELL redundant, and
-   barring any objections, it will eventually be phased out. (One
-   possible reason for retaining it would be as an escape mechanism when
-   Kermit does not understand the underlying file system.)
-
-   By the way, patterns such as these are sometimes referred to as
-   "regular expressions", but they are not quite the same. In a true
-   regular expression (for example), "*" means "zero or more repetitions
-   of the previous item", so (for example), "([0-9]*)" would match zero
-   or more digits in parentheses. In Kermit (and in most shells), this
-   matches one digit followed by zero or more characters, within
-   parentheses. Here are some hints:
-
-     * Although you can't match any sequence of digits (or letters, etc),
-       you can match (say) 1, 2, or 3 of them in row. For example, the
-       following pattern matches Kermit backup files (with backup numbers
-       from 1 to 999):
- *.~{[1-9],[1-9][0-9],[1-9][0-9][0-9]}~
-     * There is presently no NOT operator, so no way to match any
-       character or string EXCEPT the one(s) shown.
-
-   In other wildcarding news...
-
-     * You may now "send xxx" where "xxx" is a directory name, and this
-       will send all the files from the directory xxx, as if you had
-       typed "send xxx/*". You can also use the special shorthand "send
-       ." to send all the files from the current directory.
-     * To easily skip over backup files (the ones whose names end like
-       .~22~) when sending, you can use SEND /NOBACKUP (see [499]Section
-       4.0.6 for details).
-     * When choosing Kermit to expand wildcards, rather than the shell,
-       you can choose whether "dot files" -- files whose names begin with
-       ".", which are normally "invisible" -- should be matched:
- SET WILD KERMIT /NO-MATCH-DOT-FILES (this is the default)
- SET WILD KERMIT /MATCH-DOT-FILES    (this allows matching of "." files)
-       or include the /DOTFILES or /NODOTFILES switch on the command you
-       are using, such as SEND or DIRECTORY.
-     * Commands such as DIRECTORY and SEND allow recursive directory
-       traversal. There are also new functions for this to use in
-       scripts. See [500]Section 4.11 for details.
-
-   When building file lists in UNIX, C-Kermit follows symbolic links.
-   Because of this, you might encounter any or all of the following
-   phenomena:
-
-     * Multiple copies of the same file; e.g. one from its real directory
-       and others from links to its real directory, if both the real
-       directory and the links to it are in the wildcard expansion list.
-     * A command might unexpectedly "hang" for a long time because an NFS
-       link might not be responding, or the directory you are looking at
-       contains a link to a huge directory tree (example: "directory
-       /recursive /etc" when /etc/spool is a symlink to /var/spool, which
-       is a large organization's incoming email directory, containing
-       tens of thousands of subdirectories).
-
-   The size of the file list that Kermit can build is limited in most
-   C-Kermit implementations. The limit, if any, depends on the
-   implementation. Use the SHOW FEATURES command and look in the
-   alphabetized options list for MAXWLD to see the value.
-
-    4.9.2. In Kermit 95
-
-   Kermit 95 1.1.19 and later uses the same pattern matching syntax as in
-   UNIX, but (as always) you will encounter numerous difficulties if you
-   use backslash (\) as the directory separator. In any command where K95
-   parses filenames itself (that is, practically any file-oriented
-   command except RUN), you can use forward slash (/) as the directory
-   separator to avoid all the nasty conflicts.
-
-    4.9.3. In VMS, AOS/VS, OS-9, VOS, etc.
-
-   Platforms other than UNIX, Windows 95/98/NT, and OS/2 have their own
-   filename matching capabilities that are, in general, different from
-   Kermit's built-in ones and in any case might conflict with them. For
-   example, [] encloses directory names in VMS.
-
-   Nevertheless you can still use all the pattern-matching capabilities
-   described in [501]Section 4.9.1 by loading a file list into an array
-   (e.g. with \ffiles(*,&a), see [502]Section 4.11.3) and then using IF
-   MATCH on the members.
-     _________________________________________________________________
-
-  4.10. Additional Pathname Controls
-
-   In version 6.0 and earlier, C-Kermit's SET { SEND, RECEIVE } PATHNAMES
-   command had only ON and OFF as options. In version 7.0, there are more
-   choices:
-
-   SET SEND PATHNAMES OFF
-          When sending a file, strip all disk/directory information from
-          the name. Example: "send /usr/olga/letters/oofa.txt" sends the
-          file as "oofa.txt". This applies to actual filenames, not to
-          any as-name you might specify.
-
-   SET SEND PATHNAMES RELATIVE
-          When sending a file, leave the pathname on as given. For
-          example, if your current directory is /usr/olga, "send
-          letters/oofa.txt" sends the file as "letters/oofa.txt", not
-          "/usr/olga/letters/oofa.txt" or "letters.txt".
-
-   SET SEND PATHNAMES ABSOLUTE
-          When sending a file, convert its name to the full, absolute
-          local pathname. For example, if your current directory is
-          /usr/olga, "send letters/oofa.txt" sends the file as
-          "/usr/olga/letters/oofa.txt". NOTE: Even with this setting,
-          device and/or node names are not included. For example, in VMS,
-          any node or device name is stripped; in Windows or OS/2, any
-          disk letter is stripped.
-
-   SET RECEIVE PATHNAMES OFF
-          When receiving a file, strip all disk/directory information
-          from the name before attempting to store it. This applies to
-          incoming filename, not to any as-name you might specify.
-          Example: If a file arrives under the name
-          "/usr/olga/letters/oofa.txt" it is stored simply as "oofa.txt"
-          in your download directory or, if no download directory has
-          been specified, in your current directory.
-
-   SET RECEIVE PATHNAMES RELATIVE
-          When receiving a file, leave the pathname on as it appears in
-          the incoming name, but if the incoming name appears to be
-          absolute, make it relative to your current or download
-          directory. Examples:
-
-          + "oofa.txt" is stored as "oofa.txt".
-          + "letters/oofa.txt" is stored as "letters/oofa.txt"; the
-            "letters" subdirectory is created if it does not already
-            exist.
-          + "/usr/olga/letters/oofa.txt" is stored as
-            "usr/olga/letters/oofa.txt" in your current or download
-            directory, and the "usr", "usr/olga", etc, directories are
-            created if they do not exist.
-
-   SET RECEIVE PATHNAMES ABSOLUTE
-          The incoming filename is used as given. Thus it cannot be
-          stored unless the given path (if any) already exists or can be
-          created. In this case, node, device, or disk designations are
-          NOT stripped, since they most likely were given explicitly by
-          the user as an as-name, meant to be used as given.
-
-   SET RECEIVE PATHNAMES AUTO
-          This is the default, and means RELATIVE if the sender tells me
-          it is a recursive transfer, OFF otherwise.
-
-   Set FILE NAMES CONVERTED now also affects pathnames too. When
-   PATHNAMES are RELATIVE or ABSOLUTE and FILE NAMES are CONVERTED, the
-   file sender converts its native directory-name format to UNIX format,
-   and the file receiver converts from UNIX format to its native one;
-   thus UNIX format is the common intermediate representation for
-   directory hierarchies, as it is in the ZIP/UNZIP programs (which is
-   why ZIP archives are transportable among, UNIX, DOS, and VMS).
-
-   Here's an example in which a file is sent from Windows to UNIX with
-   relative pathnames and FILE NAMES CONVERTED:
-
-  Source name                Intermediate name      Destination Name
-  C:\K95\TMP\OOFA.TXT        K95/TMP/OOFA.TXT       k95/tmp/oofa.txt
-
-   In a more complicated example, we send the same file from Windows to
-   VMS:
-
-  Source name                Intermediate name      Destination Name
-  C:\K95\TMP\OOFA.TXT        K95/TMP/OOFA.TXT       [.K95.TMP]OOFA.TXT
-
-   (Note that disk letters and device designations are always stripped
-   when pathnames are relative).
-
-   As you can imagine, as more and more directory formats are considered,
-   this approach keeps matters simple: on each platform, Kermit must know
-   only its own local format and the common intermediate one. In most
-   cases, the receiver can detect which format is used automatically.
-     _________________________________________________________________
-
-  4.11. Recursive SEND and GET: Transferring Directory Trees
-
-   C-Kermit 7.0 in selected versions (UNIX, VMS, VOS, AOS/VS, Windows,
-   and OS/2 at this writing) now permits the SEND command to traverse
-   directories "recursively" if you ask it to; that is, to send files
-   from the current or specified directory and all of its subdirectories
-   too, and their subdirectories, etc. (Some other commands can do this
-   too, including DIRECTORY.)
-
-   This feature is new to UNIX, Windows, VOS, and OS/2. VMS and AOS/VS
-   have always included "wildcard" or "template" characters that allow
-   this, and in this case, recursive directory traversal could happen
-   behind Kermit's back, i.e. Kermit does not have to do it itself (in
-   VMS, the notation is "[...]" or "[directory...]"; in AOS/VS is "#").
-   In C-Kermit 7.0, however, SEND /RECURSIVE is supported by C-Kermit
-   itself for VMS.
-     _________________________________________________________________
-
-    4.11.1. Command-Line Options
-
-   To descend a directory tree when sending files, use the -L
-   command-line option to indicate that the send operation is to be
-   recursive, and include a name or pattern to be sent. When giving a
-   pattern, you should enclose it in quotes to prevent the shell from
-   expanding it. Examples:
-
-  $ kermit -Ls "/usr/olga/*" # send all of Olga's files in all her directories
-  $ kermit -Ls foo.txt       # send all foo.txt files in this directory tree
-  $ kermit -Ls "*.txt"       # send all .txt files in this directory tree
-  $ kermit -Ls "letters/*"   # send all files in the letters directory tree
-  $ kermit -Ls letters       # send all files in the letters directory tree
-  $ kermit -Ls "*"           # send all files in this directory tree
-  $ kermit -Ls .             # UNIX only: send all files in this directory tree
-  $ kermit -s .              # UNIX only: a filename of . implies -L
-
-   If you let the shell expand wildcards, Kermit only sends files whose
-   names match files in the current or given directory, because the shell
-   replaces an unquoted wildcard expression with the list of matching
-   files -- and the shell does not build recursive lists. Note that the
-   "." notation for the tree rooted at the current directory is allowed
-   only in UNIX, since in Windows and OS/2, it means "*.*"
-   (nonrecursive).
-     _________________________________________________________________
-
-    4.11.2. The SEND /RECURSIVE Command
-
-   If you include the /RECURSIVE switch in a SEND (or MOVE, or similar)
-   command, it means to descend the current or specified directory tree
-   searching for files whose names match the given name or pattern. Since
-   this is not terribly useful unless you also include pathnames with the
-   outbound files, the /RECURSIVE switch also includes an implicit
-   /PATHNAMES:RELATIVE switch (which you can undo by including an
-   explicit /PATHNAMES switch after the /RECURSIVE switch).
-
-   Examples:
-
-   SEND /RECURSIVE *
-          Sends all of the files in the current directory and all the
-          files in all of its subdirectories, and all of their
-          subdirectories, etc, including their relative pathnames. Empty
-          directories are not sent.
-
-   SEND /RECURSIVE /PATHNAMES:ABSOLUTE *
-          Sends all of the files in the current directory and all the
-          files in all of its subdirectories, and all of their
-          subdirectories, etc, including their absolute pathnames.
-
-   SEND /RECURSIVE /PATHNAMES:OFF *
-          Sends all of the files in the current directory and all the
-          files in all of its subdirectories, and all of their
-          subdirectories, etc, without pathnames.
-
-   SEND /RECURSIVE /usr/olga/*
-          Sends all of the files in the /usr/olga directory and all the
-          files in all of its subdirectories, and all of their
-          subdirectories, etc.
-
-   SEND /RECURSIVE /usr/olga (or /usr/olga/)
-          Same as above. If the name is a directory name (with or without
-          a trailing slash), its files are sent, and those of its
-          subdirectories, and their subdirectories, etc (see [503]Section
-          4.9).
-
-   SEND /RECURSIVE /TEXT /usr/olga/*.txt
-          As above, but only files whose names end with ".txt" are sent,
-          and they are sent in text mode (as they would be by default
-          anyway if SET FILE PATTERNS is ON or AUTO).
-
-   SEND .
-          UNIX only: Send all the files in the current directory.
-
-   SEND /RECURSIVE .
-          UNIX only: Sends all of the files in the current directory and
-          all of its subdirectories, etc ([504]Section 4.9).
-
-   The /RECURSIVE switch is different from most other switches in that
-   its effect is immediate (but still local to the command in which it is
-   given), because it determines how filenames are to be parsed. For
-   example, "send *.txt" fails with a parse error ("No files match") if
-   there are no *.txt files in the current directory, but "send
-   /recursive *.txt" succeeds if there are ".txt" files anywhere in the
-   tree rooted at the current directory.
-
-   The /RECURSIVE switch also affects the file lists displayed if you
-   type "?" in a filename field. "send ./?" lists the regular files in
-   the current directory, but "send /recursive ./?" lists the entire
-   directory tree rooted at the current directory.
-     _________________________________________________________________
-
-    4.11.3. The GET /RECURSIVE Command
-
-   In a client/server setting, the client can also request a recursive
-   transfer with:
-
-   GET /RECURSIVE [ other switches ] remote-filespec [ local-spec ]
-
-   In which remote file specification can be a directory name, a
-   filename, a wildcard, or any combination. If the local-spec is not
-   given (and PATHNAMES are RELATIVE), incoming files and directories go
-   into the current local directory. If local-spec is given and is a
-   directory, it becomes the root of the tree into which the incoming
-   files and directories are placed. If local-spec has the syntax of a
-   directory name (e.g. in UNIX it ends with /), C-Kermit creates the
-   directory and then places the incoming files into it. If local-spec is
-   a filename (not recommended), then all incoming files are stored with
-   that name with collisions handled according to the FILE COLLISION
-   setting.
-
-   Again, the normal method for transferring directory trees uses
-   relative pathnames, and this is the default when the sender has been
-   given the /RECURSIVE switch. The action at the receiver depends on its
-   RECEIVE PATHNAMES setting. The default is AUTO, meaning that if the
-   sender tells it to expect a recursive transfer, then it should
-   automatically switch to relative pathnames for this transfer only;
-   otherwise it obeys the RECEIVE PATHNAMES setting of OFF, ABSOLUTE, or
-   RELATIVE.
-
-   What happens if a file arrives that has an absolute pathname, when the
-   receiver has been told to use only relative pathnames? As a security
-   precaution, in this case the receiver treats the name as if it was
-   relative. For example, if a file arrives as:
-
-  /usr/olga/oofa.txt
-
-   The receiver creates a "usr" subdirectory in its current directory,
-   and then an "olga" subdirectory under the "usr" subdirectory in which
-   to store the incoming file.
-
-   Suppose, however there is a sequence of directories:
-
-  /usr/olga/a/b/c/d/
-
-   in which "a" contains nothing but a subdirectory "b", which in turn
-   contains nothing but a subdirectory "c", which in turn contains
-   nothing but a subdirectory "d", which contains nothing at all. Thus
-   there are no files in the "/usr/olga/a/" tree, and so it is not sent,
-   and therefore it is not reproduced on the target computer.
-     _________________________________________________________________
-
-    4.11.4. New and Changed File Functions
-
-   C-Kermit 7.0 adds the following functions:
-
-   \ffiles(pattern[,&a])
-          This function has been changed to match only regular files in
-          the current or given directory, and to take an optional array
-          name as a second argument (explained below).
-
-   \fdirectories(pattern[,&a])
-          Returns the number of directories that match the given pattern.
-          If the pattern does not include a directory, then the search is
-          performed in the current directory.
-
-   \frfiles(pattern[,&a])
-          Returns the number of files in the current or given directory
-          and all of its subdirectories, and their subdirectories, etc,
-          that match the given pattern. Warning -- this one can take
-          quite some time if performed at the root of a large directory
-          tree.
-
-   \frdirectories(pattern[,&a])
-          Returns the number of directories in the current or given
-          directory and all of its subdirectories, and their
-          subdirectories, etc, that match the given pattern.
-
-   Each of these functions builds up a list of files to be returned by
-   the \fnextfile() function, just as \ffiles() always has done. (This
-   can also be done with the /ARRAY switch of the DIRECTORY command; see
-   [505]Sections 4.5.1 and [506]7.10).
-
-   Each of these functions can be given an array name as an optional
-   second argument. If an array name is supplied, the array will contain
-   the number of files as its 0th element, and the filenames in elements
-   1 through last. If the array already existed, its previous contents
-   are lost. For example, if the current directory contains two files,
-   oofa.txt and foo.bar, then "\ffiles(*,&a)" creates an array \&a[] with
-   a dimension of 2, containing the following elements:
-
- \&a[0] = 2
- \&a[1] = oofa.txt
- \&a[2] = foo.bar
-
-   If no files match the specification given in the first argument, the
-   array gets a dimension of 0, which is the same as undeclaring the
-   array.
-
-   Note that the order in which the array is filled (and in which
-   \fnextfile() returns filenames) is indeterminate (but see [507]Section
-   7.10.5).
-
-   Here's an example that builds and prints a list of all the file whose
-   names end in .txt in the current directory and all its descendents:
-
-  asg \%n \frfiles(*.txt)
-  declare \&a[\%n]
-  for \%i 1 \%n 1 {
-      asg \&a[\%i] \fnextfile()
-      echo \flpad(\%i,4). "\&a[\%i]"
-  }
-
-   Alternatively, using the array method, and then printing the filenames
-   in alphabetic order (see [508]Section 7.10.3 and [509]7.10.5):
-
-  asg \%n \frfiles(*.txt,&a)
-  sort &a
-  for \%i 1 \%n 1 {
-      echo \flpad(\%i,4). "\&a[\%i]"
-  }
-
-   Or even more simply:
-
-  asg \%n \frfiles(*.txt,&a)
-  sort &a
-  show array &a
-
-   As noted elsewhere, the file lists built by \ffiles(), \frfiles(),
-   etc, are now "safe" in the sense that SEND and other file-related
-   commands can reference \fnextfile() without resetting the list:
-
-  set send pathnames relative
-  for \%i 1 \frfiles(*.txt) 1 {
-      asg \%a \fnextfile()
-      echo Sending \%a...
-      send \%a
-      if fail break
-  }
-
-   Copying to an array (as shown on p.398 of [510]Using C-Kermit 2nd Ed)
-   is no longer necessary.
-     _________________________________________________________________
-
-    4.11.5. Moving Directory Trees Between Like Systems
-
-    4.11.5.1. UNIX to UNIX
-
-   Transferring a directory tree from one computer to another replicates
-   the file sender's arrangement of files and directories on the file
-   receiver's computer. Normally this is done using relative pathnames,
-   since the user IDs might not be identical on the two computers. Let's
-   say both computers are UNIX based, running C-Kermit 7.0 or later. On
-   the sending computer (leaving out the connection details, etc):
-
-  C-Kermit> cd /usr/olga
-  C-Kermit> send /recursive .
-
-   The /RECURSIVE switch tells C-Kermit to descend through the directory
-   tree and to include relative pathnames on outbound filenames.
-
-   On the receiving computer:
-
-  C-Kermit> mkdir olgas-files           ; Make a new directory.
-  C-Kermit> cd olgas-files              ; CD to it.
-  C-Kermit> receive /recursive          ; = /PATHNAMES:RELATIVE
-
-   Each Kermit program recognizes that the other is running under UNIX
-   and switches to binary mode and literal filenames automatically.
-   Directories are automatically created on the receiving system as
-   needed. File dates and permissions are automatically reproduced from
-   source to destination.
-
-    4.11.5.2. VMS to VMS
-
-   To send recursively from VMS, simply include the /RECURSIVE switch,
-   for example at the sender:
-
-  $ kermit
-  C-Kermit> cd [olga]
-  C-Kermit> send /recursive *.*;0
-
-   And at the receiver:
-
-  C-Kermit> cd [.olga]
-  C-Kermit> receive /recursive
-
-   The notation "..." within directory brackets in VMS means "this
-   directory and all directories below it"; the /RECURSIVE switch, when
-   given to the sender, implies the use of "..." in the file
-   specification so you don't have to include "..."; but it makes no
-   difference if you do:
-
-  $ kermit
-  C-Kermit> send /recursive [olga...]*.*;0
-
-   And at the receiver:
-
-  C-Kermit> cd [.olga]
-  C-Kermit> receive /recursive
-
-   In either case, since both systems recognize each other as VMS, they
-   switch into LABELED transfer mode automatically.
-     _________________________________________________________________
-
-    4.11.6. Moving Directory Trees Between Unlike Systems
-
-   There are several difficulties with recursive transfers between unlike
-   systems:
-
-     * File formats can be different, especially text files character
-       sets and record formats. This can now be handled by using SET FILE
-       PATTERN, SET FILE TEXT-PATTERNS, and SET FILE BINARY-PATTERNS
-       ([511]Section 4.3).
-     * File naming conventions are different. For example, one system
-       might allow (and use) longer filenames than the other. You can
-       tell Kermit how to handle file names with the normal "set file
-       names" and "set file collision" mechanisms. Most modern Kermits
-       are fairly tolerant of illegal filenames and should not fail
-       simply because of an incoming filename; rather, it will do its
-       best to convert it to a recognizable and unique legal filename.
-     * Directory notations can be different, e.g. backslashes instead of
-       slashes, brackets, parentheses, spaces, etc. But this is now
-       handled by converting pathnames to a standard format during
-       transfer ([512]Section 4.10).
-
-   So now, for the first time, it is possible to send directory trees
-   among any combination of UNIX, DOS, Windows, OS/2, VMS, AOS/VS, etc.
-   Here's an example sending files from an HP-UX system (where text files
-   are encoded in the HP Roman8 character set) to a PC with K95 (where
-   text files are encoded in CP850):
-
- Sender:
-  cd xxx                           ; CD to root of source tree
-  set file type binary             ; Default transfer mode
-  set file character-set hp-roman8 ; Local character set for text files
-  set xfer character-set latin1    ; Transfer character set
-  set file patterns on             ; Enable automatic file-type switching...
-  set file binary-patterns *.Z *.gz *.o  ; based on these patterns...
-  set file text-patterns *.txt *.c *.h   ; for binary and text files.
-  send /recursive *                ; Send all the file in this directory tree
-
- Receiver:
-  cd yyy                           ; CD to root of destination tree
-  set file character-set cp850     ; Local character set for text files
-  receive /pathnames:relative      ; Receive with pathnames
-
-   Notes:
-     * Replace "xxx" and "yyy" with the desired directories.
-     * Replace the file character sets appropriately.
-     * Change the patterns as needed (or just use the built-in default
-       lists).
-     * SEND /RECURSIVE also implies /PATHNAMES:RELATIVE.
-     * The file sender tells the file receiver the transfer mode of each
-       file.
-     * The file sender tells the file receiver the transfer character
-       set.
-     * By default, destination file dates will be the same as on the
-       source.
-     * Many of the settings shown might already be set by default.
-     * See [513]Sections 4.3, [514]4.10, and [515]4.15 for additional
-       explanation.
-
-   If you are refreshing an existing directory on the destination
-   computer, use "set file collision update" or other appropriate file
-   collision option to handle filename collisions.
-     _________________________________________________________________
-
-  4.12. Where Did My File Go?
-
-   Now that Kermit can be started by clicking on desktop icons (thus
-   obscuring the concept of "current directory"), and can have a download
-   directory, and can create directories for incoming files on the fly,
-   etc, sometimes it is easy to lose a file after transfer. Of course, if
-   you keep a transaction log:
-
-  LOG TRANSACTIONS
-
-   it will record the fate and final resting place of each file. But in
-   case you did not keep a log, the new command:
-
-  WHERE
-
-   added in C-Kermit 7.0, gives you as much information as it has about
-   the location of the last files transferred, including the pathname
-   reported by the receiving Kermit, if any, when C-Kermit is the sender.
-   This information was also added to SHOW FILE in somewhat less detail.
-     _________________________________________________________________
-
-  4.13. File Output Buffer Control
-
-   (UNIX only). The new command SET FILE OUTPUT lets you control how
-   incoming files are written to disk:
-
-   SET FILE OUTPUT BUFFERED [ size ]
-          Chooses buffered file output; this is the default. UNIX does
-          its normal sort of disk buffering. The optional size specifies
-          Kermit's own file output buffer size, and therefore the
-          frequency of disk accesses (write() system calls) -- the bigger
-          the size, the fewer the disk accesses.
-
-   SET FILE OUTPUT UNBUFFERED [ size ]
-          This forces each file output write() call to actually commit
-          the data to disk immediately. Choosing this option will usually
-          slow file reception down.
-
-   SET FILE OUTPUT BLOCKING
-          Write() calls should not return until they are complete. This
-          is the normal setting, and it lets Kermit detect disk-write
-          errors immediately.
-
-   SET FILE OUTPUT NONBLOCKING
-          Write() calls should return immediately. This can speed up file
-          reception, but also delay the detection of disk-write errors.
-
-   Experimentation with these parameters should be harmless, and might
-   (or might not) have a perceptible, even dramatic, effect on
-   performance.
-     _________________________________________________________________
-
-  4.14. Improved Responsiveness
-
-   In version 7.0, C-Kermit's file-transfer protocol engine has been
-   tuned for additional speed and responsiveness.
-
-     * Binary-mode transfers over 8-bit connections, a very common case,
-       are now handled in a special way that minimizes overhead.
-     * SET TRANSFER CRC-CALCULATION is now OFF by default, rather than
-       ON. (This affects only the overall per-transfer CRC, \v(crc16),
-       not the per-packet CRCs)
-     * Connection loss during file transfer is now detected immediately
-       in most cases on Internet connections and on serial connections
-       when CARRIER-WATCH is not set to OFF.
-     _________________________________________________________________
-
-  4.15. Doubling and Ignoring Characters for Transparency
-
-   The following commands were added in 7.0, primarily to allow
-   successful file transfer through ARPAnet TACs and with Honeywell DPS6
-   systems, but can be used in any setting where they might be needed:
-
-   SET SEND DOUBLE-CHAR { [ char [ char [ ... ] ] ], NONE }
-          Tells C-Kermit to double the specified characters (use decimal
-          notation) in packets that it sends. For example, if you are
-          sending files through a device that uses @ as an escape
-          character, but allows you to send a single copy of @ through by
-          doubling it, use "set send double 64".
-
-   SET RECEIVE IGNORE-CHAR [ char [ char [ ... ] ] ]
-          Tells C-Kermit to ignore the specified character(s) in incoming
-          packets. Use this, for example, when something between the
-          sender and receiver is inserting linefeeds for wrapping, NULs
-          for padding, etc.
-     _________________________________________________________________
-
-  4.16. New File-Transfer Display Formats
-
-   SET TRANSFER DISPLAY { BRIEF, CRT, FULLSCREEN, NONE, SERIAL }
-          Selects the file-transfer display format.
-
-   BRIEF is the new one. This writes one line to the screen per file,
-   showing the file's name, transfer mode, size, the status of the
-   transfer, and when the transfer is successful, the effective data rate
-   in characters per second (CPS). Example:
-
-  SEND ckcfn3.o (binary) (59216 bytes): OK (0.104 sec, 570206 cps)
-  SEND ckcfns.o (binary) (114436 bytes): OK (0.148 sec, 772006 cps)
-  SEND ckcmai.c (text) (79147 bytes): OK (0.180 sec, 438543 cps)
-  SEND ckcmai.o (binary) (35396 bytes): OK (0.060 sec, 587494 cps)
-  SEND ckcnet.o (binary) (62772 bytes): REFUSED
-  SEND ckcpro.o (binary) (121448 bytes): OK (0.173 sec, 703928 cps)
-  SEND ckcpro.w (text) (63687 bytes): OK (0.141 sec, 453059 cps)
-  SEND makefile (text) (186636 bytes): OK (0.444 sec, 420471 cps)
-  SEND wermit (binary) (1064960 bytes): OK (2.207 sec, 482477 cps)
-
-   Note that transfer times are now obtained in fractional seconds,
-   rather than whole seconds, so the CPS figures are more accurate (the
-   display shows 3 decimal places, but internally the figure is generally
-   precise to the microsecond).
-     _________________________________________________________________
-
-  4.17. New Transaction Log Formats
-
-   The new command:
-
-  SET TRANSACTION-LOG { VERBOSE, FTP, BRIEF [ separator ] }
-
-   lets you choose the format of the transaction log. VERBOSE (the
-   default) indicates the traditional format described in the book. BRIEF
-   and FTP are new. This command must be given prior to the LOG
-   TRANSACTION command if a non-VERBOSE type is desired.
-
-    4.17.1. The BRIEF Format
-
-   BRIEF chooses a one-line per file format suitable for direct
-   importation into databases like Informix, Oracle, or Sybase, in which:
-
-     * Each record has 8 fields.
-     * Fields are separated by a non-alphanumeric separator character.
-     * The default separator character is comma (,).
-     * Any field containing the separator character is enclosed in
-       doublequotes.
-     * The final field is enclosed in doublequotes.
-
-   The fields are:
-
-    1. Date in yyyymmdd format
-    2. Time in hh:mm:ss format
-    3. Action: SEND or RECV
-    4. The local filename
-    5. The size of the file
-    6. The transfer mode (text, binary, image, labeled)
-    7. The status of the transfer: OK or FAILED
-    8. Additional status-dependent info, in doublequotes.
-
-   Examples:
-
-  20000208,12:08:52,RECV,/u/olga/oofa.txt,5246,text,OK,"0.284sec 18443cps"
-  20000208,12:09:31,SEND,/u/olga/oofa.exe,32768,binary,OK,"1.243sec 26362cps"
-  20000208,12:10:02,SEND,"/u/olga/a,b",10130,text,FAILED,"Refused: date"
-
-   Note how the filename is enclosed in doublequotes in the final
-   example, because it contains a comma.
-
-   To obtain BRIEF format, you must give the SET TRANSACTION-LOG BRIEF
-   command before the LOG TRANSACTIONS command. (If you give them in the
-   opposite order, a heading is written to the log by the LOG command.)
-     _________________________________________________________________
-
-    4.17.2. The FTP Format
-
-   SET TRANSACTION-LOG FTP (available only in UNIX) chooses a format that
-   is compatible with the WU-FTPD (Washington University FTP daemon) log,
-   and so can be processed by any software that processes the WU-FTPD
-   log. It logs only transfers in and out, both successful and failed
-   (but success or failure is not indicated, due to lack of a field in
-   the WU-FTPD log format for this purpose). Non-transfer events are not
-   recorded.
-
-   Unlike other logs, the FTP-format transaction log is opened in append
-   mode by default. This allows you to easily keep a record of all your
-   kermit transfers, and it also allows the same log to be shared by
-   multiple simultaneous Kermit processes or (permissions permitting)
-   users. You can, of course, force creation of a new logfile by
-   specifying the NEW keyword after the filename, e.g.
-
-  log transactions oofa.log new
-
-   All records in the FTP-style log are in a consistent format. The first
-   field is fixed-length and contains spaces; subsequent fields are
-   variable length, contain no spaces, and are separated by one or more
-   spaces. The fields are:
-
-   Timestamp
-          This is an asctime-style timestamp, example: "Wed Sep 16
-          20:19:05 1999" It is always exactly 24 characters long, and the
-          subfields are always in fixed positions.
-
-   Elapsed time
-          The whole number of seconds required to transfer the file, as a
-          string of decimal digits, e.g. "24".
-
-   Connection
-          The name of the network host to which C-Kermit is connected, or
-          the name of the serial device through which it has dialed (or
-          has a direct connection), or "/dev/tty" for transfers in remote
-          mode.
-
-   Bytes transferred
-          The number of bytes transferred, decimal digits, e.g.
-          "1537904".
-
-   Filename
-          The name of the file that was transferred, e.g.
-          "/pub/ftp/kermit/a/README.TXT". If the filename contains any
-          spaces or control characters, each such character is replaced
-          by an underscore ('_') character.
-
-   Mode
-          The letter 'b' if the file was transferred in binary mode, or
-          'a' if it was transferred in text (ASCII) mode.
-
-   Options
-          This field always contains an underscore ('_') character.
-
-   Direction
-          The letter 'o' if the file was transferred Out, and 'i' if the
-          file was transferred In.
-
-   User class
-          The letter 'r' indicates the file was transferred by a Real
-          user.
-
-   User identification
-          The ID of the user who transferred the file.
-
-   Server identification
-          The string "kermit". This distinguishes a Kermit transfer log
-          record from a WU-FTPD record, which contains "ftp" in this
-          field.
-
-   Authentication class
-          The digit '1' if we know the user's ID on the client system,
-          otherwise '0'. Currently, always '0'.
-
-   Authenticated user
-          If the authentication class is '1', this is the user's ID on
-          the client system. Otherwise it is an asterisk ('*'). Currently
-          it is always an asterisk.
-
-   Examples:
-
-  Thu Oct 22 17:42:48 1998 0 * 94 /usr/olga/new.x a _ i r olga kermit 0 *
-  Thu Oct 22 17:51:29 1998 1 * 147899 /usr/olga/test.c a _ o r olga kermit 0 *
-  Thu Oct 22 17:51:44 1998 1 * 235 /usr/olga/test.o b _ i r olga kermit 0 *
-  Fri Oct 23 12:10:25 1998 0 * 235 /usr/olga/x.ksc a _ o r olga kermit 0 *
-
-   Note that an ftp-format transaction log can also be selected on the
-   Kermit command line as follows:
-
-  kermit --xferfile:filespec
-
-   This is equivalent to:
-
-  SET TRANSACTION-LOG FTP
-  LOG TRANSACTIONS filespec APPEND
-
-   Conceivably it could be possible to have a system-wide shared Kermit
-   log, except that UNIX lacks any notion of an append-only file; thus
-   any user who could append to the log could also delete it (or alter
-   it). This problem could be worked around using setuid/setgid tricks,
-   but these would most likely interfere with the other setuid/setgid
-   tricks C-Kermit must use for getting at dialout devices and UUCP
-   logfiles.
-     _________________________________________________________________
-
-  4.18. Unprefixing NUL
-
-   As of 6.1.193 Alpha.10, C-Kermit can finally send and receive
-   file-transfer packets in which NUL (ASCII 0) is unprefixed (no more
-   NUL-terminated packets!). NUL is, of course, extremely prevalent in
-   binary files such as executables, and this has been a significant
-   source of packet overhead. For example, when transferring itself (the
-   SunOS C-Kermit executable) with minimal prefixing and 9000-byte
-   packets, we see:
-
-  File size:                       1064960
-  Packet chars with 0 prefixed:    1199629  overhead = 12.65%
-  Packet chars with 0 unprefixed:  1062393  overhead = -0.03%
-
-   Transfer rates go up accordingly, not only because of the reduced
-   amount of i/o, but also because less computation is required on each
-   end.
-     _________________________________________________________________
-
-  4.19. Clear-Channel Protocol
-
-   Now that C-Kermit itself is capable of sending and receiving any byte
-   at all on a clear channel ([516]Section 4.18), it is, for the first
-   time, in a position to negotiate a clear channel with the other
-   Kermit, giving it permission (but not requiring it) to unprefix any
-   and all characters that it knows are safe. In general this means all
-   but the Kermit start-of-packet character (normally Ctrl-A), Carriage
-   Return (not only Kermit's end-of-packet character, but also treated
-   specially on Telnet NVT links), and IAC (255, also special to Telnet).
-
-   By default, C-Kermit will say it has a clear channel only if it has
-   opened a TCP socket. Since the Kermit program on the far end of a
-   TCP/IP connection generally does not know it has a TCP/IP connection,
-   it will not announce a clear channel unless it has been told to do so.
-   The command is:
-
-   SET CLEAR-CHANNEL { ON, OFF, AUTO }
-
-   AUTO is the default, meaning that the clear-channel status is
-   determined automatically from the type of connection. ON means to
-   announce a clear channel, OFF means not to announce it. Use SHOW
-   STREAMING ([517]Section 4.20) to see the current CLEAR-CHANNEL status.
-   Synonym: SET CLEARCHANNEL.
-
-   CLEAR-CHANNEL is also set if you start C-Kermit with the -I switch
-   (see [518]Section 4.20).
-
-   Whenever a clear channel is negotiated, the resulting
-   control-character unprefixing is "sticky"; that is, it remains in
-   effect after the transfer so you can use SHOW CONTROL to see what was
-   negotiated.
-
-   You can also see whether a clear channel was negotiated in the
-   STATISTICS /VERBOSE Display.
-
-   The advantage of the clear channel feature is that it can make file
-   transfers go faster automatically. The disadvantage would be
-   file-transfer failures if the channel is not truly clear, for example
-   if C-Kermit made a Telnet connection to a terminal server, and then
-   dialed out from there; or if C-Kermit made an Rlogin connection to
-   host and then made a Telnet connection from there to another host. If
-   a file transfer fails on a TCP/IP connection, use SHOW CONTROL to
-   check whether control characters became unprefixed as a result of
-   protocol negotiations, and/or SHOW STREAMING ([519]Section 4.20) to
-   see if "clear-channel" was negotiated. If this happened, use SET
-   CLEAR-CHANNEL OFF and SET PREFIXING CAUTIOUS (or whatever) to prevent
-   it from happening again.
-     _________________________________________________________________
-
-  4.20. Streaming Protocol
-
-   A new Kermit protocol option called "streaming" was added in C-Kermit
-   7.0. The idea is that if the two Kermit partners have a reliable
-   transport (such as TCP/IP or X.25) between them, then there is no need
-   to send ACKs for Data packets, or NAKs, since a reliable transport
-   will, by definition, deliver all packets in order and undamaged. On
-   such a connection, streaming cuts down not only on Kermit program
-   overhead (switching back and forth between reading and sending
-   packets), but also tends to make the underlying transport use itself
-   more efficiently (e.g. by defeating the Nagle algorithm and/or Delayed
-   ACK stratagem of the TCP layer). Furthermore, it allows transfers to
-   work smoothly on extremely slow network congestions that would
-   otherwise cause timeouts and retransmissions, and even failure when
-   the retry limit was exceeded.
-
-   The trick is knowing when we can stream:
-
-    1. If C-Kermit has opened a TCP socket or X.25 connection, it offers
-       stream.
-    2. If C-Kermit has been started with the -I (uppercase) option, or if
-       it has been told to SET RELIABLE ON, it offers to stream.
-    3. If C-Kermit is in remote mode, and has been told to SET RELIABLE
-       AUTO (or ON), it always offers to stream, and also always agrees
-       to stream, if the other Kermit offers. Unless you take explicit
-       actions to override the defaults, this allows the local Kermit
-       (the one that made the connection, and so knows whether it's
-       reliable) to control streaming.
-
-   (Note that an offer to stream also results in a Clear-Channel
-   announcement if CLEAR-CHANNEL is set to AUTO; see [520]Section 4.19.)
-
-   When BOTH Kermits offer to stream, then they stream; otherwise they
-   don't. Thus streaming-capable Kermit programs interoperate
-   automatically and transparently with nonstreaming ones. If the two
-   Kermits do agree to stream, you'll see the word "STREAMING" on the
-   fullscreen file-transfer display in the Window Slots field. You can
-   also find out afterwards with the STATISTICS or SHOW STREAMING
-   commands.
-
-     WARNING: Automatic choice of streaming is based on the assumption
-     of a "direct" end-to-end network connection; for example, a Telnet
-     or Rlogin connection from host A to host B, and transferring files
-     between A and B. However, if your connection has additional
-     components -- something "in the middle" (B) that you have made a
-     network connection to, which makes a separate connection to the
-     destination host (C), then you don't really have a reliable
-     connection, but C-Kermit has no way of knowing this; transferring
-     files between A and C will probably fail. In such cases, you'll
-     need to tell the *local* C-Kermit to "set reliable off" before
-     transferring files (it does no good to give this command to the
-     remote Kermit since the local one controls the RELIABLE setting).
-
-   Streaming is like using an infinite window size, with no timeouts and
-   no tolerance for transmission errors (since there shouldn't be any).
-   It relies on the underlying transport for flow control, error
-   correction, timeouts, and retransmission. Thus it is very suitable for
-   use on TCP/IP connections, especially slow or bursty ones, since
-   Kermit's packet timeouts won't interfere with the transfer -- each
-   packet takes as long to reach its destination as it takes TCP to
-   deliver it. If TCP can't deliver the packet within its own timeout
-   period (over which Kermit has no control), it signals a fatal error.
-   Just like FTP.
-
-   Streaming goes much faster than non-streaming when a relatively small
-   packet length is used, and it tends to go faster than non-streaming
-   with even the longest packet lengths. The Kermit window size is
-   irrelevant to streaming protocol, but still might affect performance
-   in small ways since it can result in different paths through the code.
-
-   The definition of "reliable transport" does not necessarily demand
-   8-bit and control-character transparency. Streaming can work with
-   parity and/or control-character prefixing just as well (but not as
-   fast) as without them; in such cases you can leave RELIABLE set to ON,
-   but set CLEARCHANNEL and/or PARITY appropriately.
-
-   Maximum performance -- comparable to and often exceeding FTP -- is
-   achieved on socket-to-socket connections (in which the considerable
-   overhead of the terminal driver and Telnet or Rlogin server is
-   eliminated) with long packets and the new "brief" file-transfer
-   display ([521]Section 4.16).
-     _________________________________________________________________
-
-    4.20.1. Commands for Streaming
-
-   SET RELIABLE { ON, OFF, AUTO }
-          SET RELIABLE ON tells Kermit that it has a reliable transport.
-          SET RELIABLE OFF tells Kermit the transport is not reliable.
-          SET RELIABLE AUTO tells Kermit that it should SET RELIABLE ON
-          whenever it makes a reliable connection (e.g. TELNET or SET
-          HOST on a TCP/IP or X.25 network), and when in remote mode it
-          should believe the transport is reliable if the other Kermit
-          says it is during Kermit protocol negotiation.
-
-   AUTO is the default; the Kermit program that makes the connection
-   knows whether it is reliable, and tells the remote Kermit.
-
-   The RELIABLE setting has several effects, including:
-
-     * It can affect the timeouts used during normal ACK/NAK protocol.
-     * It can affect the clear-channel announcement.
-     * It can affect streaming.
-
-   If you TELNET or SET HOST somewhere, this includes an implicit SET
-   RELIABLE ON command. The -I command-line option is equivalent to SET
-   RELIABLE ON.
-
-   Since SET RELIABLE ON (and -I) also implies SET CLEAR CHANNEL ON, you
-   might find that in certain cases you need to tell Kermit that even
-   though the connection is reliable, it doesn't have a clear channel
-   after all:
-
-  SET CLEAR-CHANNEL OFF
-  SET PREFIXING CAUTIOUS ; or whatever...
-
-   You can control streaming without affecting the other items with:
-
-  SET STREAMING { ON, OFF, AUTO }
-
-   AUTO is the default, meaning streaming will occur if Kermit has made a
-   TCP/IP connection or if RELIABLE is ON (or it was started with the -I
-   command line option). OFF means don't stream; ON means offer to stream
-   no matter what.
-     _________________________________________________________________
-
-    4.20.2. Examples of Streaming
-
-   Here we look at the use and behavior of streaming on several different
-   kinds of connections, and compare its performance with non-streaming
-   transfers.
-
-    4.20.2.1. Streaming on Socket-to-Socket Connections
-
-   Here we get streaming automatically when both Kermit programs are
-   capable of it, since they both make socket connections. For example,
-   on the far end:
-
-  C-Kermit> set host * 3000
-  C-Kermit> server
-
-   and on the near end:
-
-  C-Kermit> set host foo.bar.xyz.com 3000
-  (now give SEND and GET command)
-
-   All subsequent file transfers use streaming automatically.
-
-   Here are the results from 84 trials, run on a production network,
-   disk-to-disk, in which a 1-MB binary file (the SunOS C-Kermit Sparc
-   executable) was sent from a Sun Sparc-10 with SunOS 4.1.3 to an IBM
-   Power Server 850 with AIX 4.1, socket-to-socket, over a 10Mbps 10BaseT
-   Ethernet, using minimal control-character unprefixing, window sizes
-   from 10 to 32, and packet sizes from 1450 to 9010:
-
-                Streaming    Nonstreaming
-  Max CPS         748955        683354
-  Min CPS         221522        172491
-  Mean CPS        646134        558680
-  Median CPS      678043        595874
-  Std Dev         101424        111493
-
-   Correlations:
-
-  CPS and window size:   -0.036
-  CPS and packet length:  0.254
-  CPS and streaming:      0.382
-
-   Note that the relationship between streaming and throughput is
-   significantly stronger than that between CPS and window size or packet
-   length.
-
-   Also note that this and all other performance measurements in this
-   section are snapshots in time; the results could be much different at
-   other times when the load on the systems and/or the network is higher
-   or lower.
-
-   In a similar socket-to-socket trial, but this time over a wide-area
-   TCP/IP connection (from New York City to Logan, Utah, about 2000
-   miles), the following results were obtained:
-
-                Streaming    Nonstreaming
-  Max CPS         338226        318203
-  Min CPS         191659        132314
-  Mean CPS        293744        259240
-  Median CPS      300845        273271
-  Std Dev          41914         52351
-
-   Correlations:
-
-  CPS and window size:    0.164
-  CPS and packet length:  0.123
-  CPS and streaming:      0.346
-     _________________________________________________________________
-
-    4.20.2.2. Streaming on Telnet Connections
-
-   In this case the local copy of Kermit is told to TELNET or SET HOST,
-   and so it knows it has a reliable connection and -- unless it has been
-   told not to -- will offer to stream, and the other Kermit program,
-   since it has STREAMING set to AUTO, agrees.
-
-   Since we have a reliable connection, we'll also get control-character
-   unprefixing automatically because of the new clear-channel protocol
-   ([522]Section 4.19).
-
-   Any errors that occur during streaming are fatal to the transfer. The
-   message is "Transmission error on reliable link". Should this happen:
-
-    1. Check the remote Kermit's flow control setting (SHOW
-       COMMUNICATIONS). If it is NONE, change it to XON/XOFF, or vice
-       versa. If it is XON/XOFF (or you just changed it to XOFF/XOFF),
-       make sure the file sender is prefixing the XON and XOFF
-       characters. In the most drastic case, use "set prefix all" to
-       force prefixing of all control characters.
-    2. The remote Telnet server might chop off the 8th bit. In that case,
-       tell C-Kermit to "set parity space". Or, you might be able to
-       force the Telnet to allow eight-bit data by telling C-Kermit to
-       "set telopt binary request accept" -- that is, request the Telnet
-       server to enter binary mode, and accept binary-mode bids from the
-       server.
-    3. The remote Telnet server might have a buffering limitation. If a
-       and b don't cure the problem, tell the file receiver to "set
-       receive packet-length 1000" (or other number -- use the largest
-       one that works). This too, is no different from the non-streaming
-       case (more about this in [523]Section 4.20.2.3).
-
-   And remember you can continue interrupted binary-mode transfers where
-   they left off with the RESEND (= SEND /RECOVER) command.
-
-   Here are the figures for the same 84 trials between the same Sun and
-   IBM hosts as in 4.20.2.1, on the same network, but over a Telnet
-   connection rather than socket-to-socket:
-
-                  Streaming    Nonstreaming
-  Max CPS         350088        322523
-  Min CPS          95547        173152
-  Mean CPS        321372        281830
-  Median CPS      342604        291469
-  Std Dev          40503         29948
-
-   Correlations:
-
-  CPS and window size:    0.001
-  CPS and packet length:  0.152
-  CPS and streaming:      0.128
-
-   Here the effect is not as emphatic as in the socket-to-socket case,
-   yet on the whole streaming tends to be beneficial.
-
-   Additional measurements on HP-UX using C-Kermit 7.0 Beta.06:
-
-                  Windowing     Streaming
-  HP-UX 8->8      not tested       14Kcps
-  HP-UX 8->9      not tested       76Kcps
-  HP-UX 8->10      36Kcps          66Kcps
-  HP-UX 9->9      not tested      190Kcps
-  HP-UX 9->10     160Kcps         378Kcps
-     _________________________________________________________________
-
-    4.20.2.3. Streaming with Limited Packet Length
-
-   The IRIX telnet server (at least the ones observed in IRIX 5.3 and
-   6.2) does not allow Kermit to send packets longer than 4096 bytes.
-   Thus when sending from IRIX C-Kermit when it is on the remote end of a
-   Telnet connection, the packet length must be 4K or less. Trials in
-   this case (in which packet lengths range from 1450 to 4000) show a
-   strong advantage for streaming, which would be evident in any other
-   case where the packet length is restricted, and stronger the shorter
-   the maximum packet length.
-
-                  Streaming    Nonstreaming
-  Max CPS         426187        366870
-  Min CPS         407500        276517
-  Mean CPS        415226        339168
-  Median CPS      414139        343803
-  Std Dev           6094         25851
-
-   Correlations:
-
-  CPS and window size:    0.116
-  CPS and packet length:  0.241
-  CPS and streaming:      0.901
-     _________________________________________________________________
-
-    4.20.2.4. Streaming on Dialup Connections
-
-   Here "dialup" refers to a "direct" dialup connection, not a SLIP or
-   PPP connection, which is only a particular kind of TCP/IP connection.
-
-   Attempt this at your own risk, and then only if (a) you have
-   error-correcting modems, and (b) the connections between the modems
-   and computers are also error-free, perfectly flow-controlled, and free
-   of interrupt conflicts. Streaming can be used effectively and to
-   fairly good advantage on such connections, but remember that the
-   transfer is fatal if even one error is detected (also remember that
-   should a binary-mode transfer fail, it can be recovered from the point
-   of failure with RESEND).
-
-   To use streaming on an unreliable connection, you must tell both
-   Kermits that the connection is reliable:
-
-  kermit -I
-
-   or:
-
-  C-Kermit> set reliable on
-
-   In this case, it will probably be necessary to prefix some control
-   characters, for example if your connection is through a terminal
-   server that has an escape character. Most Cisco terminal servers, for
-   example, require Ctrl-^ (30, as well as its high-bit equivalent, 158)
-   to be prefixed. To unprefix these, you'll need to defeat the "clear
-   channel" feature:
-
-  C-Kermit> set reliable on
-  C-Kermit> set clear-channel off
-  C-Kermit> set prefixing none
-  C-Kermit> set control prefix 1 13 30 158 ; and whatever else is necessary
-
-   Dialup trials were done using fixed large window and packet sizes.
-   They compare uploading and downloading of two common types of files,
-   with and without streaming. Configuration:
-
-     HP-9000/715/33 -- 57600bps, RTS/CTS -- USR Courier V.34 --
-     V.34+V.42, 31200bps -- USR V.34+ Rackmount -- 57600bps, RTS/CTS --
-     Cisco terminal server -- Solaris 2.5.1. Packet size = 8000, Window
-     Size = 30, Control Character Unprefixing Minimal (but including the
-     Cisco escape character).
-
-   Since this is not a truly reliable connection, a few trials failed
-   when a bad packet was received (most likely due to UART overruns); the
-   failure was graceful and immediate, and the message was informative.
-   The results of ten successful trials uploading and downloading the two
-   files with and without streaming are:
-
-            Streaming..
-            Off    On
-   Upload   5194   5565   txt (= C source code, 78K)
-            3135   3406   gz  (= gzip file, compressed, 85K)
- Download   5194   5565   txt
-            3041   3406   gz
-
-   Each CPS figure is the mean of 10 results.
-
-   A brief test was also performed on a LAT-based dialout connection from
-   a VAX 3100 with VMS 5.5 to a USR Courier V.34 connected to a DECserver
-   700 at 19200 bps. The 1-MB Sparc executable downloaded from a Sun to
-   the VAX at 1100cps without streaming and 1900cps with streaming, using
-   8000-byte packets, 30 window slots, and minimal prefixing in both
-   cases.
-     _________________________________________________________________
-
-    4.20.2.5. Streaming on X.25 Connections
-
-   We have only limited access to X.25 networks. One trial was performed
-   in which the 1MB Solaris 2.4 Sparc executable was transferred over a
-   SunLink X.25 connection; nothing is known about the actual physical
-   connection. With a packet length of 8000 and a window size of 30, the
-   file transferred at 6400 cps (using a maximum of 6 window slots). With
-   the same packet length, but with streaming, it transferred without
-   mishap at 6710 cps, about 5% faster.
-     _________________________________________________________________
-
-    4.20.3. Streaming - Preliminary Conclusions
-
-   The results vary with the particular connection, but are good overall.
-   Although numerous lower-level tricks can be used to improve
-   performance on specific platforms or connection methods, streaming
-   occurs at a high, system-independent level of the Kermit protocol and
-   therefore can apply to all types of platforms and (reliable)
-   connections transparently.
-     _________________________________________________________________
-
-  4.21. The TRANSMIT Command
-
-   Prior to C-Kermit 7.0, the TRANSMIT command transmitted in text or
-   binary mode according to SET FILE TYPE { TEXT, BINARY }. But now that
-   binary mode is likely to be the default for protocol transfers, it is
-   evident that this not also an appropriate default for TRANSMIT, since
-   binary-mode TRANSMIT is a rather specialized and tricky operation.
-   Therefore, TRANSMIT defaults to text mode always, regardless of the
-   FILE TYPE setting.
-
-   C-Kermit 7.0 expands the capabilities of the TRANSMIT command by
-   adding the following switches (see [524]Section 1.5). The new syntax
-   is:
-
-  TRANSMIT [ switches... ] filename
-
-   Zero or more switches may be included:
-
-   /PIPE
-          When /PIPE is included, "filename" is interpreted as a system
-          command or program whose output is to be sent. Synonym:
-          /COMMAND. Example:
-
-  transmit /pipe finger
-
-          You may enclose the command in braces, but you don't have to:
-
-  xmit /pipe {ls -l | sort -r +0.22 -0.32 | head}
-
-   /BINARY
-          Transmits the file (or pipe output) in binary mode.
-
-   /TEXT
-          Transmits the file (or pipe output) in line-oriented text mode.
-          Current FILE CHARACTER-SET and TERMINAL CHARACTER-SET
-          selections govern translation. Default.
-
-   /TRANSPARENT
-          Specifies text mode without character-set translation, no
-          matter what the FILE and TERMINAL CHARACTER-SET selections are.
-
-   /NOWAIT
-          This is equivalent to SET TRANSMIT PROMPT 0, but for this
-          TRANSMIT command only. Applies only to text mode; it means to
-          not wait for any kind of echo or turnaround character after
-          sending a line before sending the next line. (Normally Kermit
-          waits for a linefeed.)
-
-   When TRANSMIT ECHO is ON, C-Kermit tries to read back the echo of each
-   character that is sent. Prior to C-Kermit 7.0, 1 second was allowed
-   for each echo to appear; if it didn't show up in a second, the
-   TRANSMIT command would fail. Similarly for the TRANSMIT PROMPT
-   character. However, with today's congested Internet connections, etc,
-   more time is often needed:
-
-   SET TRANSMIT TIMEOUT number
-   Specifies the number of seconds to wait for an echo or the prompt
-   character when TRANSMIT PROMPT is nonzero; the default wait is 1
-   second. If you specify 0, the wait is indefinite. When a timeout
-   interval of 0 is specified, and a desired echo or prompt does not show
-   up, the TRANSMIT command will not terminate until or unless you
-   interrupt it with Ctrl-C; use SET TRANSMIT TIMEOUT 0 with caution.
-
-   Note: to blast a file out the communications connection without any
-   kind of synchronization or timeouts or other manner of checking, use:
-
-  SET TRANSMIT ECHO OFF
-  SET TRANSMIT PROMPT 0 (or include the /NOWAIT switch)
-  SET TRANSMIT PAUSE 0
-  TRANSMIT [ switches ] filename
-
-   In this case, text-file transmission is not-line oriented and large
-   blocks can be sent, resulting in a significant performance improvement
-   over line-at-at-time transmission. Successful operation depends (even
-   more than usual for the TRANSMIT command!) on a clean connection with
-   effective flow control.
-
-   For details on TRANSMIT and character sets, see [525]Section 6.6.5.4.
-     _________________________________________________________________
-
-  4.22. Coping with Faulty Kermit Implementations
-
-   Kermit protocol has been implemented in quite a few third-party
-   commercial, shareware, and freeware software packages, with varying
-   degrees of success. In most cases operation is satisfactory but slow
-   -- only the bare minimum subset of the protocol is available -- short
-   packets, no sliding windows, no attributes, etc. In other cases, the
-   implementation is incorrect, resulting in failures at the initial
-   negotiation stage or corrupted files.
-
-   C-Kermit 7.0 and Kermit 95 1.1.19 include some new defense mechanisms
-   to help cope with the most common situations. However, bear in mind
-   there is only so much we can do in such cases -- the responsibility
-   for fixing the problem lies with the maker of the faulty software.
-     _________________________________________________________________
-
-    4.22.1. Failure to Accept Modern Negotiation Strings
-
-   The published Kermit protocol specification states that new fields can
-   be added to the parameter negotiation string. These are to be ignored
-   by any Kermit implementation that does not understand them; this is
-   what makes the Kermit protocol extensible. Unfortunately, some Kermit
-   implementations become confused (or worse) when receiving a
-   negotiation string longer than the one they expect. You can try
-   working around such problems by telling Kermit to shorten its
-   negotiation string (and thus disable the corresponding new features):
-
-  SET SEND NEGOTIATION-STRING-MAX-LENGTH number
-
-   Try a number like 10. If that doesn't work, try 9, 8, 7, 6, and so on.
-     _________________________________________________________________
-
-    4.22.2. Failure to Negotiate 8th-bit Prefixing
-
-   The published Kermit protocol specification states that 8th-bit
-   prefixing (which allows transfer of 8-bit data over a 7-bit
-   connection) occurs if the file sender puts a valid prefix character
-   (normally "&") in the 8th-bit-prefix field of the negotiation string,
-   and the receiver puts either a letter "Y" or the same prefix
-   character. At least one faulty Kermit implementation exists that does
-   not accept the letter "Y". To force C-Kermit / K-95 to reply with the
-   other Kermit's prefix character rather than a "Y", give the following
-   (invisible) command:
-
-  SET Q8FLAG ON
-
-   Use SET Q8FLAG OFF to restore the normal behavior.
-     _________________________________________________________________
-
-    4.22.3. Corrupt Files
-
-   Refer to [526]Section 4.22.2. Some Kermit implementations mistakenly
-   interpret the "Y" as a prefix character. Then, whenever a letter Y
-   appears in the data, the Y and the character that follows it are
-   replaced by a garbage character. At this writing, we are not sure if
-   there is any solution, but try "set send negotiation-string-max-length
-   6" and/or "set q8flag on".
-
-   File corruption can also occur when control characters within the file
-   data are sent without prefixing, as at least some are by default in
-   C-Kermit 7.0 and K-95. Some Kermit implementations do not handle
-   incoming "bare" control characters. To work around, "set prefixing
-   all".
-     _________________________________________________________________
-
-    4.22.4. Spurious Cancellations
-
-   The Kermit protocol specification states that if an ACK to a Data
-   packet contains X in its data field, the transfer of the current file
-   is canceled, and if it contains a Z, the entire transfer is canceled.
-   At least one overzealous Kermit implementation applies this rule to
-   non-Data packets as well, the typical symptom being that any attempt
-   to transfer a file whose name begins with X or Z results in
-   cancellation. This is because the file receiver typically sends back
-   the name under which it stored the file (which might not be the same
-   as the name it was sent with) in the ACK to the File Header packet.
-   This is information only and should not cause cancellation. To work
-   around the problem, use:
-
-  SET F-ACK-BUG { ON, OFF }
-
-   ON tells Kermit not to send back the filename in the ACK to the file
-   header packet as it normally would do (OFF puts Kermit back to normal
-   after using ON).
-
-   A variation on the this bug occurs in an obscure Kermit program for
-   MUMPS: When this Kermit program sends a file called (say) FOO.BAR, it
-   requires that the ACK to its F packet contain exactly the same name,
-   FOO.BAR. However, C-Kermit likes to send back the full pathname,
-   causing the MUMPS Kermit to fail. SET F-ACK-BUG ON doesn't help here.
-   So a separate command has been added to handle this situation:
-
-  SET F-ACK-PATH { ON, OFF }
-
-   Normally it is ON (regardless of the SET SEND PATHNAMES setting). Use
-   SET F-ACK-PATH OFF to instruct Kermit to send back only the filename
-   without the path in the ACK to the F packet.
-     _________________________________________________________________
-
-    4.22.5. Spurious Refusals
-
-   Some Kermit implementations, notably PDP-11 Kermit 3.60 and earlier,
-   have bugs in their handling of Attribute packets that can cause
-   unwarranted refusal of incoming files, e.g. based on date or size.
-   This can be worked around by telling one or both of the Kermit
-   partners to:
-
-  SET ATTRIBUTES OFF
-     _________________________________________________________________
-
-    4.22.6. Failures during the Data Transfer Phase
-
-   This can be caused by control-character unprefixing ([527]Section
-   4.22.3 ), and fixed by:
-
-  SET PREFIXING ALL
-
-   It can also have numerous other causes, explained in Chapter 10 of
-   [528]Using C-Kermit: the connection is not 8-bit transparent (so use
-   "set parity space" or somesuch), inadequate flow control, etc. Consult
-   the manual.
-     _________________________________________________________________
-
-    4.22.7. Fractured Filenames
-
-   At least one well-known PC-based communications package negotiates
-   data compression, which (according to the protocol specification)
-   applies to both the filename and the file data, but then fails to
-   decompress the filename. Example: C-Kermit sends a file called
-   R000101.DAT (where 000101 might be non-Y2K-wise YYMMDD notation), and
-   the package in question stores the files as R~#0101.DAT. Workaround:
-   Tell C-Kermit to SET REPEAT COUNTS OFF.
-     _________________________________________________________________
-
-    4.22.8. Bad File Dates
-
-   At least one well-known PC-based communications package negotiates the
-   passing of file timestamps from sender to receiver, but when it is
-   sending files, it always gives them a timestamp of 1 February 1970.
-   Workaround: tell C-Kermit to SET ATTRIBUTE DATE OFF. You don't get the
-   file's real date, but you also don't get 1 Feb 1970; instead the file
-   gets the current date and time.
-     _________________________________________________________________
-
-  4.23. File Transfer Recovery
-
-   Prior to C-Kermit 7.0, RESEND (SEND /RECOVER) and REGET (GET /RECOVER)
-   refused to work if FILE TYPE was not BINARY or the /BINARY switch was
-   not included. Now these commands include an implied /BINARY switch,
-   meaning they set the file type to binary for the duration of the
-   command automatically.
-
-   In the client/server arrangement, this also forces the server into
-   binary mode (if it is C-Kermit 7.0 or greater, or K95 1.1.19 or
-   greater) so the recovery operation proceeds, just as you asked and
-   expected.
-
-   BUT... Just as before, the results are correct only under the
-   following conditions:
-
-     * If the prior interrupted transfer was also in binary mode; or:
-     * If the prior transfer was in text mode and the other computer was
-       a "like platform" (e.g. UNIX-to-UNIX, Windows-to-Windows,
-       DOS-to-Windows) AND there was no character-set translation (i.e.
-       TRANSFER CHARACTER-SET was TRANSPARENT).
-
-   Note that these circumstances are more likely to obtain in C-Kermit
-   7.0, in which:
-
-     * The default FILE TYPE in C-Kermit 7.0 is BINARY.
-     * The default FILE INCOMPLETE setting is AUTO, which means KEEP if
-       the transfer is in binary mode, DISCARD otherwise.
-     * C-Kermit 7.0, Kermit 95 1.1.17, and MS-DOS Kermit 3.15 and later
-       can recognize "like platforms" and switch into binary mode
-       automatically. Transfers between like platforms are always binary
-       unless character-set translation has been requested, and then is
-       still binary for all files whose names match a binary pattern,
-       unless the automatic mechanisms have been disabled (with a /TEXT
-       switch, or with SET TRANSFER MODE MANUAL).
-     * SEND /BINARY and GET /BINARY always force binary-mode transfers,
-       even when FILE TYPE is TEXT, even when TRANSFER MODE is AUTOMATIC,
-       even when PATTERNS are ON and the file's name matches a text
-       pattern.
-
-   But also note that the automatic client/server transfer-mode
-   adjustments do not work with versions of C-Kermit prior to 7.0 or K95
-   prior to 1.1.16.
-
-   If the prior transfer was in text mode:
-
-     * If text-mode transfers between the two platforms are
-       "length-changing" (as they are between UNIX -- which terminates
-       text lines with LF -- and DOS or Windows -- which terminates text
-       lines with CRLF), the recovered file will be corrupt.
-     * If text-mode transfers between the two platforms are not
-       length-changing, but character-set translation was active in the
-       prior transfer, the result will be a file in which the first part
-       has translated characters and the second part does not.
-
-   But in C-Kermit 7.0 and K95 1.1.19 and later, incompletely transferred
-   text files are not kept unless you change the default. But if you have
-   done this, and you have an incompletely transferred text file, you'll
-   need to:
-
-     * Transfer the whole file again in text mode, or:
-     * Use SEND /STARTING-AT: to recover the transfer at the correct
-       point; but you have to find out what that point is, as described
-       in the manual.
-
-   Kermit has no way of knowing whether the previous transfer was in text
-   or binary mode so it is your responsibility to choose the appropriate
-   recovery method.
-
-   If you use C-Kermit to maintain parallel directories on different
-   computers, using SET FILE COLLISION to transfer only those files that
-   changed since last time, and the files are big enough (or the
-   connection slow enough) to require SEND /RECOVER to resume interrupted
-   transfers, you should remember that SEND /RECOVER (RESEND) overrides
-   all FILE COLLISION settings. Therefore you should use SEND /RECOVER
-   (RESEND) only on the file that was interrupted, not the file group.
-   For example, if the original transfer was initiated with:
-
-  SEND *
-
-   and was interrupted, then after reestablishing your connection and
-   starting the Kermit receiver with SET FILE COLLISION UPDATE on the
-   remote end, use the following sequence at the sender to resume the
-   transfer:
-
-  SEND /RECOVER name-of-interrupted-file
-
-   and then:
-
-  SEND *
-
-   (In C-Kermit 7.0 and later, \v(filename) contains the name of the file
-   most recently transferred, as long you have not EXITed from Kermit or
-   changed directory, etc.
-     _________________________________________________________________
-
-  4.24. FILE COLLISION UPDATE Clarification
-
-   In UNIX, file modification dates are used when comparing the file date
-   with the date in the attribute packet. In VMS, however, the file
-   creation date is used. These two policies reflect the preferences of
-   the two user communities.
-
-   Also, remember that the file date/time given in the attribute packet
-   is the local time at the file sender. At present, no timezone
-   conversions are defined in or performed by the Kermit protocol. This
-   is primarily because this feature was designed at a time when many of
-   the systems where Kermit runs had no concept of timezone, and
-   therefore would be unable to convert (say, to/from GMT or UTC or Zulu
-   time).
-
-   As a consequence, some unexpected results might occur when
-   transferring files across timezones; e.g. commands on the target
-   system that are sensitive to file dates might work (UNIX "make",
-   backups, etc).
-
-   Timezone handling is deferred for a future release.
-     _________________________________________________________________
-
-  4.25. Autodownload Improvements
-
-   Refer to pages 164-165 of [529]Using C-Kermit about the hazards of
-   autodownload when C-Kermit is "in the middle". As of C-Kermit 7.0, no
-   more hazards. If C-Kermit has TERMINAL AUTODOWNLOAD ON and it detects
-   a packet of the current protocol type (Kermit or Zmodem), it "erases"
-   the visual aspect of the packet that would be seen by the terminal
-   (or, more to the point, the emulator, such as K95). This way, only
-   C-Kermit goes into RECEIVE mode, and not also the terminal emulator
-   through which C-Kermit is accessed. And therefore, it is no longer
-   necessary to SET TERMINAL AUTODOWNLOAD OFF to prevent multiple Kermits
-   from going into receive mode at once, but of course it is still
-   necessary to ensure that, when you have multiple Kermits in a chain,
-   that the desired one receives the autodownload.
-
-   The defaults have not been changed; Kermit 95 still has autodownload
-   ON by default, and C-Kermit has it OFF by default.
-     _________________________________________________________________
-
-  5. CLIENT/SERVER
-
-  5.0. Hints
-
-   If you use SET SERVER GET-PATH to set up your server, and the GET-PATH
-   does not include the server's current directory, clients can become
-   quite confused. For example, "remote dir oofa.txt" shows a file named
-   oofa.txt, but "get oofa.txt" fails. In this situation, you should
-   either DISABLE DIR or make your GET-PATH include the current
-   directory.
-     _________________________________________________________________
-
-  5.1. New Command-Line Options
-
-   The -G command-line option is like -g (GET), except the incoming file
-   is sent to standard output rather than written to disk.
-
-   The -I option ("Internet") is used to tell a remote C-Kermit program
-   that you are coming in via Internet Telnet or Rlogin and therefore
-   have a reliable connection. The -I option is equivalent to SET
-   RELIABLE ON and SET FLOW NONE.
-
-   The -O option ("Only One") tells C-Kermit to enter server mode but
-   then exit after the first client operation.
-
-   See [530]Section 9.3 for details.
-     _________________________________________________________________
-
-  5.2. New Client Commands
-
-   BYE and FINISH no longer try to do anything if a connection is not
-   active. Thus a sequence like "hangup" followed by "bye" or "finish"
-   will no longer get stuck in a long timeout-and-retransmission cycle,
-   nor will it try to open a new connection.
-
-   REMOTE EXIT
-          Similar to FINISH, except it ensures that the Kermit server
-          program exits back to the operating system or shell prompt.
-          (FINISH would return it to its interactive prompt if it was
-          started in interactive mode, and would cause it to exit if it
-          entered server mode via command-line option.) When C-Kermit is
-          to be the server, you can use { ENABLE, DISABLE } EXIT to
-          control the client's access to this feature.
-
-   REMOTE MKDIR directory-name
-          Tells the client to ask the server to create a directory with
-          the given name, which can be absolute or relative. The syntax
-          of the directory name depends on the Kermit server (see
-          [531]next section); in all cases, it can be in the syntax of
-          the system where the server is running (UNIX, VMS, DOS, etc)
-          but newer servers also accept UNIX syntax, no matter what the
-          underlying platform. The server will not execute this command
-          if (a) it does not understand it, (b) a DISABLE MKDIR command
-          has been given, or (c) a DISABLE CWD command has been given;
-          otherwise, the command is executed, but will fail if the
-          directory can not be created, in which cases most servers will
-          attempt to return a message giving the reason for failure. The
-          REMOTE MKDIR command succeeds if the remote directory is
-          created, or if it already exists and therefore does not need to
-          be created, and fails otherwise.
-
-   REMOTE RMDIR directory-name
-          Tells the client to ask the server to remove (delete) a
-          directory with the given name. The same considerations apply as
-          for REMOTE MKDIR.
-
-   REMOTE SET FILE INCOMPLETE { DISCARD, KEEP, AUTO }
-          Previously this was only available in its earlier form, REMOTE
-          SET INCOMPLETE (no FILE). The earlier form is still available,
-          but invisible. Also, AUTO was added, meaning KEEP if in binary
-          mode, DISCARD otherwise.
-
-   REMOTE SET TRANSFER MODE { AUTOMATIC, MANUAL }
-          Tells the client to ask the server to set the given
-          file-transfer mode. Automatic means (roughly): if the client
-          and the server are running on the same kind of computer (e.g.
-          both are on UNIX), then use binary mode automatically; if the
-          system types are different, use some other method to
-          automatically determine text or binary mode, such as filename
-          pattern matching. MANUAL means, in this context, obey the
-          client's FILE TYPE setting (TEXT or BINARY). Synonym: REMOTE
-          SET XFER MODE.
-
-   [ REMOTE ] QUERY KERMIT function(args...)
-          Prior to C-Kermit 7.0, the arguments were not evaluated
-          locally. Thus it was not possible to have the server run the
-          function with client-side variables as arguments. Now:
-
-  define \%a oofa.*
-  remote query kermit files(\%a)    ; Client's \%a
-  remote query kermit files(\\%a)   ; Server's \%a
-
-   [ REMOTE ] LOGIN [ user [ password ] ]
-          LOGIN is now a synonym for REMOTE LOGIN.
-
-   LOGOUT
-          This command, when given in local mode, is equivalent to REMOTE
-          LOGOUT. When given at the IKSD prompt, it logs out the IKSD.
-          When given at the C-Kermit prompt when it has no connection, it
-          does nothing.
-
-   Note that in C-Kermit 7.0, the REMOTE (or R) prefix is not required
-   for QUERY, since there is no local QUERY command. The new top-level
-   QUERY command does exactly what REMOTE QUERY (RQUERY) does.
-
-   All REMOTE commands now have single-word shortcuts:
-
- Shortcut   Full Form
-  RASG       REMOTE ASSIGN
-  RCD        REMOTE CD
-  RCOPY      REMOTE COPY
-  RDEL       REMOTE DELETE
-  RDIR       REMOTE DIRECTORY
-  REXIT      REMOTE EXIT
-  RHELP      REMOTE HELP
-  RHOST      REMOTE HOST
-  RPWD       REMOTE PWD
-  RSET       REMOTE SET
-  etc.
-
-   The R prefix is not applied to LOGIN because there is already an
-   RLOGIN command with a different meaning. It is not applied to LOGOUT
-   either, since LOGOUT knows what to do in each case, and for symmetry
-   with LOGIN.
-     _________________________________________________________________
-
-    5.2.1. Remote Procedure Definitions and Calls
-
-   This is nothing new, but it might not be obvious... REMOTE ASSIGN and
-   REMOTE QUERY may be used to achieve remote procedure execution. The
-   remote procedure can be defined locally or remotely.
-
-   A remote procedure call is accomplished as noted in the previous
-   section:
-
-  [ remote ] query kermit function-name(args...)
-
-   This invokes any function that is built in to the Kermit server, e.g.:
-
-  [ remote ] query kermit size(foo.bar)
-
-   returns the size of the remote file, foo.bar.
-
-   Now note that C-Kermit includes an \fexecute() function, allowing it
-   to execute any macro as if it were a built-in function. So suppose
-   MYMACRO is the name of a macro defined in the server. You can execute
-   it from the client as follows (the redundant "remote" prefix is
-   omitted in the remaining examples):
-
-  query kermit execute(mymacro arg1 arg2...)
-
-   The return value, if any, is the value of the RETURN command that
-   terminated execution of the macro, for example:
-
-  define addtwonumbers return \feval(\%1+\%2)
-
-   The client invocation would be:
-
-  query kermit execute(addtwonumbers 3 4)
-  7
-
-   The result ("7" in this case) is also assigned to the client's
-   \v(query) variable.
-
-   To execute a remote system command or command procedure (shell script,
-   etc) use:
-
-  query kermit command(name args...)
-
-   Finally, suppose you want the client to send a macro to the server to
-   be executed on the server end. This is done as follows:
-
-  remote assign macroname definition
-  query kermit execute(macroname arg1 arg2...)
-
-   Quoting is required if the definition contains formal parameters.
-     _________________________________________________________________
-
-  5.3. New Server Capabilities
-
-    5.3.1. Creating and Removing Directories
-
-   The C-Kermit 7.0 server responds to REMOTE MKDIR and REMOTE RMDIR
-   commands. The directory name may be in either the native format of the
-   server's computer, or in UNIX format. For example, a server running on
-   VMS with a current directory of [IVAN] can accept commands from the
-   client like:
-
-  remote mkdir olga         ; Makes [IVAN.OLGA] (nonspecific format)
-  remote mkdir .olga        ; Makes [IVAN.OLGA] (VMS format without brackets)
-  remote mkdir olga/        ; Makes [IVAN.OLGA] (UNIX relative format)
-  remote mkdir /ivan/olga   ; Makes [IVAN.OLGA] (UNIX absolute format)
-  remote mkdir [ivan.olga]  ; Makes [IVAN.OLGA] (VMS absolute format)
-  remote mkdir [.olga]      ; Makes [IVAN.OLGA] (VMS relative format)
-
-    5.3.1.1. Creating Directories
-
-   If a directory name is given that contains more than one segment that
-   does not exist, the server attempts to create all the segments. For
-   example, if the client says:
-
-  REMOTE MKDIR letters/angry
-
-   a "letters" subdirectory is created in the server's current directory
-   if it does not already exist, and then an "angry" subdirectory is
-   created beneath it, if it does not already have one. This can repeated
-   to any reasonable depth:
-
-  REMOTE MKDIR a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/z/y/z
-
-    5.3.1.2. Removing Directories
-
-   When attempting to execute a REMOTE RMDIR, the server can remove only
-   a single directory, not an entire sequence or tree. The system service
-   that is called to remove the directory generally requires not only
-   that the server process has write delete access, but also that the
-   directory contain no files.
-
-   In the future, a REMOTE RMDIR /RECURSIVE command (and the accompanying
-   protocol) might be added. For now, use the equivalent REMOTE HOST
-   command(s), if any.
-     _________________________________________________________________
-
-    5.3.2. Directory Listings
-
-   Directory listings are generated by C-Kermit itself, rather than by
-   running the underlying system's directory command. Some control over
-   the listing format can be obtained with the SET OPTIONS DIRECTORY
-   command ([532]Section 4.5.1). The following options affect listings
-   sent by the server: /[NO]HEADING, /[NO]DOTFILES, and /[NO]BACKUP. In
-   UNIX and VMS, the listing is always sorted by filename. There is, at
-   present, no protocol defined for the client to request listing options
-   of the server; this might be added in the future.
-
-   The server's directory listings are in the following format:
-
-   Protection or permissions:
-          In UNIX and OS-9, this is a 10-character field, left adjusted.
-          In VMS it is a 22-character field, left-adjusted. In each case,
-          the protection / permission codes are shown in the server
-          platform's native format. In other operating systems, this
-          field is not shown.
-
-   Size in bytes:
-          This is always a 10-character field. The file's size is shown
-          as a decimal number, right adjusted in the field. If the file
-          is a directory and its size can not be obtained, the size is
-          shown as "<DIR>". Two blanks follow this field.
-
-   Date:
-          Always in yyyy-mm-dd hh:mm:ss numeric format, and therefore 19
-          characters long. If the file's date/time can't be obtained,
-          zeros (0) are shown for all the digits. This field is followed
-          by two blanks.
-
-   Filename:
-          This field extends to the end of the line. Filenames are shown
-          relative to the server's current directory. In UNIX, symbolic
-          links are shown as they are in an "ls -l" listing as "linkname
-          -> filename".
-
-   In UNIX and VMS, listings are returned by the server in alphabetical
-   order of filename. There are presently no other sort or selection
-   options.
-
-   However, since these are fixed-field listings, all fields can be used
-   as sort keys by external sort programs. Note, in particular, that the
-   format used for the date allows a normal lexical on that field to
-   achieve the date ordering. For example, let's assume we have a UNIX
-   client and a UNIX server. In this case, the server's listing has the
-   date in columns 22-40, and thus could be sorted by the UNIX sort
-   program using "sort +0.22 -0.40" or in reverse order by "sort +0.22
-   -0.40r".
-
-   Since the UNIX client can pipe responses to REMOTE commands through
-   filters, any desired sorting can be accomplished this way, for
-   example:
-
-C-Kermit> remote directory | sort +0.22 -0.40
-
-   You can also sort by size:
-
-  C-Kermit> remote directory | sort +0.11 -0.19
-
-   You can use sort options to select reverse or ascending order. "man
-   sort" (in UNIX) for more information. And of course, you can pipe
-   these listings through any other filter of your choice, such as grep
-   to skip unwanted lines.
-     _________________________________________________________________
-
-  5.4. Syntax for Remote Filenames with Embedded Spaces
-
-   C-Kermit and K95, when in server mode, assume that any spaces in the
-   file specification in an incoming GET command are filename separators.
-   Thus if the client gives a command like:
-
-  get {oofa.txt oofa.bin}
-
-   or, equivalently:
-
-  mget oofa.txt oofa.bin
-
-   the server tries to send the two files, oofa.txt and oofa.bin. But
-   what if you want the server to send you a file named, say:
-
-  D:\HP OfficeJet 500\Images\My Pretty Picture Dot PCL
-
-   How does the server know this is supposed to be one file and not
-   seven? In this case, you need to the send file name to the server
-   enclosed in either curly braces:
-
-  {D:\HP OfficeJet 500\Images\My Pretty Picture Dot PCL}
-
-   or ASCII doublequotes:
-
-  "D:\HP OfficeJet 500\Images\My Pretty Picture Dot PCL"
-
-   The method for doing this depends on your client. If your client is
-   C-Kermit 7.0, any recent version of Kermit 95, or MS-DOS Kermit 3.16,
-   then you have to enclose the name in braces just so the client can
-   parse it, so to send braces or doublequotes to the server, you must
-   put them inside the first, outside pair of braces. And you also need
-   to double the backslashes to prevent them from being interpreted:
-
-  get {{D:\\HP OfficeJet 500\\Images\\My Pretty Picture Dot PCL}}
-  get {"D:\\HP OfficeJet 500\\Images\\My Pretty Picture Dot PCL"}
-
-   To get around the requirement to double backslashes in literal
-   filenames, of course you can also use:
-
-  set command quoting off
-  get {{D:\HP OfficeJet 500\Images\My Pretty Picture Dot PCL}}
-  get {"D:\HP OfficeJet 500\Images\My Pretty Picture Dot PCL"}
-  set command quoting on
-
-   If you are giving a "kermit" command to the UNIX shell, you have to
-   observe the shell's quoting rules, something like this:
-
-  kermit -ig "{D:\HP OfficeJet 500\Images\My Pretty Picture Dot PCL}"
-
-   Here, the quotes go on the outside so UNIX will pass the entire
-   filename, spaces, braces, and all, as a single argument to Kermit, and
-   the backslashes are not doubled because (a) the UNIX shell ignores
-   them since they are in a quoted string, and (b) Kermit ignores them
-   since the interactive command parser is not activated in this case.
-     _________________________________________________________________
-
-  5.5. Automatic Orientation Messages upon Directory Change
-
-   C-Kermit 7.0, when acting as a server, can send an orientation message
-   to the client whenever the server directory changes. For example, when
-   the client gives a REMOTE CD command, the server sends the contents of
-   the new directory's "Read Me" file to the client's screen. The
-   following commands govern this feature:
-
-   SET SERVER CD-MESSAGE FILE name
-          Given to the servr, allows the message-file name to be
-          specified at runtime. A list of names to look for can be given
-          in the following format:
-
-  {{name1}{name2}{name3}{...}}
-
-          e.g. SET SERVER CD-MESSAGE FILE
-          {{./.readme}{README.TXT}{READ.ME}}
-
-   REMOTE SET SERVER CD-MESSAGE { ON, OFF }
-          Given to the client, lets the client control whether the server
-          sends automatic CD messages.
-
-   SHOW SERVER
-          Given to server, includes CD-Message status.
-
-   The default CD message file name is system dependent. SHOW CD or SHOW
-   SERVER displays the list. Also see [533]Section 4.5.2.
-     _________________________________________________________________
-
-  5.6. New Server Controls
-
-   DISABLE ENABLE
-          Allows the server to configured such that DISABLEd features can
-          not be re-enabled by any means -- e.g. if the client is somehow
-          able to get the server into command mode. Once DISABLEd, ENABLE
-          can not be re-ENABLEd.
-
-   SET SERVER IDLE-TIMEOUT seconds
-          This was available previously in Kermit 95 only. Now it can be
-          used in C-Kermit also to specify a maximum number of seconds
-          the server is allowed to be idle before exiting server mode. 0
-          seconds means no idle timeout. In C-Kermit (but not K-95), SET
-          SERVER TIMEOUT and SET SERVER IDLE-TIMEOUT are mutually
-          exclusive -- you can have one or the other (or neither), but
-          not both. (Server timeouts are for the benefit of primitive
-          Kermit clients that are not capable of timing out on their own;
-          to our knowledge, no such clients are still in circulation.)
-
-   SET SERVER KEEPALIVE { ON, OFF }
-          (See next section).
-     _________________________________________________________________
-
-  5.7. Timeouts during REMOTE HOST Command Execution
-
-   Prior to C-Kermit 7.0, the C-Kermit server would block waiting for
-   output from a system command invoked via REMOTE HOST from the client.
-   If the system command took a long time to execute, the client would
-   time out and send NAK packets. If the command took too long, the
-   client would reach its retry limit and give up. Even if it didn't, the
-   NAKs would cause unnecessary retransmissions.
-
-   In version 7.0, the C-Kermit server (VMS and select()-capable UNIX
-   versions only), sends "keepalive packets" (empty data packets) once
-   per second while waiting for the system command to complete. This
-   procedure should be entirely transparent to the Kermit client, and
-   should prevent the unwanted timeouts and NAKs. When C-Kermit 7.0
-   itself (or K95 1.1.19) is the client, it prints dots to show the
-   keepalive packets.
-
-   The keepalive feature can be turned off and on with:
-
-  SET SERVER KEEPALIVE { ON, OFF }
-
-   Normally it should be on. Turn it off it if causes trouble with the
-   client, or if it seems to slow down the server (as it might on some
-   platforms under certain circumstances).
-     _________________________________________________________________
-
-  6. INTERNATIONAL CHARACTER SETS
-
-   Support for several new single-byte character sets was added in
-   C-Kermit 7.0. Unicode / ISO 10646 is not yet supported, but is a high
-   priority for forthcoming releases.
-
-  6.0. ISO 8859-15 Latin Alphabet 9
-
-   To accommodate the Euro currency symbol, and to correct several other
-   longstanding problems with ISO Latin Alphabet 1, ISO 8859-15 Latin
-   Alphabet 9 was issued in May 1998. It is supported by C-Kermit 7.0 as
-   a transfer character set, a file character set, and a terminal
-   character set. Translations that preserve the new characters are
-   available between Latin-9 and several other sets including:
-
-  PC Code Page 858         (Western European languages, similar to CP850)
-  Windows Code Page 1252   (Western European languages, similar to Latin-1)
-  Windows Code Page 1250   (Eastern European languages, similar to Latin-2)
-
-   The Latin-9 transfer character set also allows for the OE digraph
-   character, used primarily in French, to be preserved in transfers
-   involving the DEC MCS or NeXT character sets.
-
-   The Euro character is also present in the Universal Character Set,
-   described in [534]Section 6.6.
-
-  6.1. The HP-Roman8 Character Set
-
-   The HP-Roman8 character set is supported in C-Kermit 6.0 and later but
-   was omitted from Table VII-4 in the 2nd Edition of Using C-Kermit due
-   to lack of space. It is listed in [535]Appendix III.
-
-  6.2. Greek Character Sets
-
-   Greek character sets were added in 6.1:
-
-  SET FILE CHARACTER-SET { CP869, ELOT927, GREEK-ISO }
-  SET TRANSFER CHARACTER-SET { GREEK-ISO }
-
-   GREEK-ISO is ISO 8859-7, which the same as ELOT 928.
-
-   The new Greek character sets are listed in [536]Appendix III.
-
-  6.3. Additional Latin-2 Character Sets
-
-   The following have been added as FILE and TERMINAL CHARACTER-SETs:
-
-   MAZOVIA-PC
-          A PC code page used in Poland, equivalent to CP437, but with 18
-          substitutions needed for Polish.
-
-   CP1250
-          The Windows Latin 2 Code Page. Equivalent to ISO 8859-2, but
-          with different encoding.
-
-  6.4. Additional Cyrillic Character Sets
-
-   The following have been added as FILE and TERMINAL CHARACTER-SETs:
-
-   BULGARIA-PC
-          This is the Cyrillic PC code page used in Bulgaria, where it is
-          called Code Page 856. It is attributed to a company called
-          DATEC, Inc, but CP856 is not a proper designation, since it
-          refers to a Hebrew Code Page (see the IBM Registry).
-
-   CP855
-          This PC Code Page contains all the Cyrillic letters that are
-          also in ISO 8859-5, and is therefore useful for non-Russian
-          Cyrillic text (Ukrainian, Belorussian, etc), unlike CP866,
-          which has a smaller repertoire of Cyrillic letters.
-
-   CP1251
-          The Windows Cyrillic Code Page. Equivalent to CP855, but with
-          different encoding.
-
-   KOI8R
-          An extension to "Old KOI-8" that adds upper and lower case
-          Cyrillic letter Io (looks like Roman E with diaeresis) plus a
-          selection of box-drawing characters to columns 8 through 11,
-          which are vacant in original Old KOI-8. KOI8-R is used for the
-          Russian language. It is specified in [537]RFC 1489.
-
-   KOI8U
-          A similar extension of Old KOI-8, but for Ukrainian. It is
-          specified in [538]RFC 2319.
-     _________________________________________________________________
-
-  6.5. Automatic Character-Set Switching
-
-   Prior to version 7.0, C-Kermit's file character-set always had to be
-   set explicitly. In 7.0 and later, it is set automatically when:
-
-    1. This feature is enabled (as it is unless you disable it).
-    2. An incoming text-mode transfer includes a transfer-character-set
-       announcer and you have not previously given a SET FILE
-       CHARACTER-SET command. In this case, C-Kermit switches to an
-       appropriate file character set. For example, on an HP-UX
-       workstation, an incoming Latin-1 file automatically selects
-       HP-Roman8 for the local copy of the file; in Data General AOS/VS,
-       it would select DG International.
-    3. You give a SET TRANSFER CHARACTER-SET command without having
-       previously specified a FILE CHARACTER-SET. An appropriate file
-       character-set is chosen automatically.
-
-   In addition, when you give a SET FILE CHARACTER-SET command, the
-   appropriate transfer character-set is automatically chosen, to be used
-   when you are sending files (but this does not override the one
-   announced by the sender when you are receiving files).
-
-   You might not agree about what is "appropriate", so of course you can
-   disable or change all of the above actions.
-
-   You can disable (or re-enable) the new automatic character-set
-   switching feature in each direction separately:
-
-   SET RECEIVE CHARACTER-SET-SELECTION { AUTOMATIC, MANUAL }
-          AUTOMATIC is the default, causing the behavior described above
-          when an incoming file arrives. Choose MANUAL to defeat this
-          behavior and force your current FILE CHARACTER-SET setting to
-          be used, no matter what it is. Note that SET RECEIVE
-          CHARACTER-SET MANUAL does not disable recognition of the
-          incoming transfer character-set announcer, and translation from
-          the corresponding character-set to your current file
-          character-set. To disable that, use SET ATTRIBUTE CHARACTER-SET
-          OFF.
-
-   SET SEND CHARACTER-SET-SELECTION { AUTOMATIC, MANUAL }
-          Again AUTOMATIC is the default, causing the behavior described
-          above when you give a SET { FILE, TRANSFER } CHARACTER-SET
-          command. Use MANUAL to allow you to specify the transfer and
-          file character-sets independently.
-
-   SHOW CHARACTER-SETS
-          Tells settings of { SEND, RECEIVE } CHARACTER-SET-SELECTION.
-
-   Normally, however, it is more convenient to leave automatic switching
-   active, and change any associations that are not appropriate for your
-   application, area, or country. The commands are:
-
-   SHOW ASSOCIATIONS
-          This command lists all the associations in each direction: for
-          each possible transfer character-set, it lists the associated
-          file character-set, and vice versa. These are two separate and
-          independent lists.
-
-   ASSOCIATE TRANSFER-CHARACTER-SET name1 [ name2 ]
-          Changes the association for the transfer character-set name1 to
-          be the file character-set name2. If name2 is omitted, automatic
-          switching is disabled for this transfer character-set only.
-
-   ASSOCIATE FILE-CHARACTER-SET name1 [ name2 ]
-          Changes the association for the file character-set name1 to be
-          the transfer character-set name2. If name2 is omitted,
-          automatic switching is disabled for this file character-set
-          only.
-     _________________________________________________________________
-
-  6.6. UNICODE
-
-   C-Kermit 7.0 adds support for Unicode, the Universal Character Set,
-   for:
-
-     * File Transfer (SEND, RECEIVE, GET, etc)
-     * Terminal connection (CONNECT)
-     * Unguarded file capture (LOG SESSION)
-     * Unguarded file transmission (TRANSMIT)
-     * Local file character-set conversion (TRANSLATE)
-
-   C-Kermit is not, however, a "Unicode application" in the sense that
-   its commands, messages, or user interface are Unicode. Rather, it is
-   "Unicode aware" in its ability to handle and convert Unicode text in
-   the course of file transfer and terminal connection, and you can also
-   use Kermit to convert local files between Unicode and other character
-   sets. TLA's:
-
-  BMP - Base Multilingual Plane
-  BOM - Byte Order Mark
-  CJK - Chinese, Japanese, and Korean
-  ISO - International Standards Organization
-  TLA - Three-Letter Acronym
-  UCS - Universal Character Set
-  UTF - UCS Transformation Format
-
-   Unicode and ISO 10646 are the coordinated and compatible corporate and
-   international standards for the Universal Character Set (UCS). Unlike
-   single-byte and even most multibyte character sets, the UCS can
-   represent all characters in every existing writing system. A flat
-   plain-text file encoded in some form of UCS can contain any mixture of
-   English, Spanish, Italian, German, Hebrew, Arabic, Greek, Russian,
-   Armenian, Georgian, Japanese, Chinese, Korean, Vietnamese, Tibetan,
-   Hindi, Bengali, Tamil, Thai, Ethiopic, and so on, plus scientific and
-   mathematical notation, as well as texts in Runes, Ogham, Glagolitic,
-   and other historic scripts.
-
-   The UCS already covers these scripts and many more, but it's an
-   evolving standard with efforts underway to accommodate even more
-   languages and writing systems. Support is growing for native UCS use
-   on many platforms and in many applications. The goal of the framers of
-   the UCS is for it to replace ASCII, the ISO Latin Alphabets, ISCII,
-   VISCII, the Chinese, Japanese, and Korean (CJK) multibyte sets, etc,
-   as well as the many private character sets in use today, in other
-   words to become *the* Universal Character Set.
-
-   Until that time, however, conversions between existing sets and the
-   UCS will be necessary when moving text between platforms and
-   applications. Now Kermit can help.
-     _________________________________________________________________
-
-    6.6.1. Overview of Unicode
-
-   For a more complete picture, please visit:
-
-  [539]http://www.unicode.org/
-
-   and access the various online introductions, FAQs, technical reports,
-   and other information. For greater depth, order the latest version of
-   the published Unicode Standard. The following overview contains a
-   great many oversimplifications and perhaps an opinion or two.
-
-   At present, the UCS is a 16-bit (2-byte) character set, but with
-   provisions to grow to a 4-byte set. UCS-2 refers to the two-byte set,
-   also called the Base Multilingual Plane (BMP), in which each character
-   has 16 bits, and therefore there are 2^16 = 65536 possible characters.
-   The first 128 characters are the same as US ASCII (C0 control
-   characters and DEL included), the next 32 are the C1 control
-   characters of ISO 6429, and the next 96 are the Right Half of ISO
-   8859-1 Latin Alphabet 1. The remaining tens of thousands of characters
-   are arranged newly for the UCS, usually (but not always) in sections
-   corresponding to existing standards, such as ISO Latin/Cyrillic, often
-   plus additional characters not appearing in the existing standards due
-   to lack of space (or other reasons).
-
-   ISO 10646 allows for additional planes, e.g. for Egyptian
-   hieroglyphics or ancient (or other esoteric) CJK characters, but these
-   planes are not yet defined and so we will say nothing more about them
-   here, except that their use will require the 4-byte form of UCS,
-   called UCS-4, in some form (more about "forms" in [540]Section 6.6.2).
-
-   Unicode and ISO 10646 are constantly under revision, mainly to add new
-   characters. The Unicode revision is denoted by a version number, such
-   as 1.0, 1.1, 2.0, 3.0. The ISO 10646 standard revision is identified
-   by Edition (such as ISO 10646-1 1993), plus reference to any
-   amendments. The first versions of these standards included encodings
-   for Korean Hangul syllables (Jamos); these encodings were changed in
-   version 1.1 of Unicode and by Amendment 5 to ISO 10646-1. The Unicode
-   Technical Committee and the ISO acknowledge that this was a bad thing
-   to do, and promise never change encodings or character names again,
-   since this poses serious problems for conformance and data
-   interchange.
-
-   A UCS-2 value is customarily written like this:
-
-  U+xxxx
-
-   where "xxxx" represents four hexadecimal digits, 0-9 and A-F. For
-   example, U+0041 is "A", U+00C1 is A-acute, U+042F is uppercase
-   Cyrillic "Ya", U+FB4F is Hebrew Ligature Alef Lamed, and U+FFFD is the
-   special character that means "not a character".
-
-   Most characters from widely-used alphabetic writing systems such as
-   the West European ones, Cyrillic, Greek, Hebrew, Vietnamese, etc, are
-   available in "precomposed" form; for example Uppercase Latin Letter A
-   with Acute Accent is a single character (as it is in Latin-1).
-   However, the UCS also permits composition of a base character with one
-   or more nonspacing diacritics. This means the same character can be
-   represented in more than one way, which can present problems in many
-   application areas, including transfer and character-set conversion of
-   text.
-
-   Conversion from ASCII or Latin-1 to UCS-2 text is "trivial": simply
-   insert a NUL (0) byte before each ASCII or Latin-1 byte. Converting in
-   the reverse direction (provided the UCS-2 file contains only U+0000 to
-   U+00FF) is equally simple (if we ignore the issue of composition):
-   remove every second (NUL) byte. Conversion of other character sets to
-   and from UCS, however, requires tables or algorithms specific to each
-   set. Nevertheless, the relatively transparent upwards compatibility
-   from ASCII and Latin-1, in which a very large share of the world's
-   textual data is encoded, gives the UCS an entree onto existing
-   platforms.
-
-   But the 2-byte format and the preponderance of NUL and other control
-   bytes in UCS-2 text pose problems for current applications and
-   transmission methods. And to make matters worse, different hardware
-   platforms store UCS-2 characters in different byte order. Thus a UCS-2
-   file transferred by FTP (or accessed via NFS, etc) between two
-   computers with different architecture might have its bytes in the
-   wrong order (or worse; see [541]Section 6.6.5.1 ).
-     _________________________________________________________________
-
-    6.6.2. UCS Byte Order
-
-   Consider the number 1. In an 8-bit byte, this would be represented by
-   the following series of 0- and 1-bits:
-
-  +-----------------+
-  | 0 0 0 0 0 0 0 1 |
-  +-----------------+
-
-   Therefore in a 16-bit "word" the representation might be:
-
-  +-----------------+-----------------+
-  | 0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 1 |
-  +-----------------+-----------------+
-
-   Now consider the number 256, which is 2 to the 8th power. The binary
-   representation is 100000000 (1 followed by 8 zeros). 256 would go into
-   a 16-bit word like this:
-
-  +-----------------+-----------------+
-  | 0 0 0 0 0 0 0 1 | 0 0 0 0 0 0 0 0 |
-  +-----------------+-----------------+
-
-   When a computer works this way, it is said to be Big Endian, meaning
-   it puts the most significant (biggest) byte first (on the "left") in a
-   16-bit word, and the least significant byte second (on the right).
-
-   However, some other computers have the opposite arrangement, called
-   Little Endian, in which 1 is:
-
-  +-----------------+-----------------+
-  | 0 0 0 0 0 0 0 1 | 0 0 0 0 0 0 0 0 |
-  +-----------------+-----------------+
-
-   and 256 is:
-
-  +-----------------+-----------------+
-  | 0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 1 |
-  +-----------------+-----------------+
-
-   Computers such as Sparc, MIPS, PA-RISC, and PowerPC are Big Endian,
-   whereas the PC and the Alpha are Little Endian. Endianness has never
-   been an issue with 7- or 8-bit characters, but it is with UCS
-   characters. It can be a tricky business to share or transfer a UCS-2
-   file between two different kinds of computers.
-
-   To alleviate (but not entirely solve) the problem, UCS-2 files are
-   supposed to begin with the Unicode character U+FEFF, Zero-Width
-   No-Break Space (ZWNBS). This is a kind of "no-op" (note: any such
-   assertion must normally be qualified with many "but ifs" and "excepts"
-   which are omitted here in the interest of brevity). If the bytes are
-   reversed the ZWNBS becomes U+FFFE, which is not (and never will be) a
-   defined UCS character. U+FEFF at the beginning of a UCS file is
-   therefore called a Byte Order Mark, or BOM.
-
-   Any application that creates a UCS-2 (or UTF-16, or UCS-4) file should
-   include a BOM, and any application that reads one should test for a
-   BOM, and if one is found, infer the byte order from it. This is a
-   convention, however -- not a standard or a requirement -- and
-   applications vary in their ability to handle BOMs and "backwards"
-   UCS-2 files.
-
-   Note that a BOM is useful only at the beginning of a file. If you
-   append one UCS-2 file to another, and both have BOMs, the internal BOM
-   is no longer a BOM. And if the byte orders of the two files differ,
-   then either the first part or the second will be backwards. (Various
-   other undesirable effects might also occur, not discussed here.)
-     _________________________________________________________________
-
-    6.6.2. UCS Transformation Formats
-
-   UCS textual data can be modified in various ways for transmission or
-   storage. Any officially sanctioned method of doing this is called a
-   UCS Transformation Format, or UTF. One such method, called UTF-16, is
-   essentially identical with UCS-2 except that it designates certain
-   code values as "escape sequences" (called surrogate pairs) to access
-   characters in other planes without having to use full UCS-4. We won't
-   discuss UTF-16 further here, since at the moment there are no other
-   planes. Several other UTF's (such as UTF-1, UTF-2, and UTF-7) have
-   fallen into disuse and are not discussed here. The most important
-   transformation format today is UTF-8.
-
-   UTF-8, so called because it "serializes" UCS-2 data into a stream of
-   8-bit bytes, is designed to allow the UCS to work with present-day
-   communications gear, computers, and software. The most important
-   properties of UTF-8 are that byte order is constant (no byte swapping)
-   and all (7-bit) ASCII characters represent themselves. Therefore
-   conversion between ASCII and UTF-8 is no conversion at all, and
-   applications or platforms (such as Plan 9 from Bell Labs) that use
-   UTF-8 "for everything" can still run traditional ASCII-only
-   applications and be accessed from them. In particular, unlike UCS-2,
-   ASCII characters are not padded with NUL bytes. But also unlike UCS-2,
-   there is no transparency for Latin-1 or any other non-ASCII character
-   set. Every non-ASCII UCS-2 character is represented by a sequence of 2
-   or 3 UTF-8 bytes. Thus UTF-8 is more compact than UCS-2 for text
-   containing a preponderance of ABC's (or other ASCII characters), about
-   the same as UCS-2 for other alphabetic scripts (Cyrillic, Roman,
-   Greek, etc), and larger than UCS-2 for Chinese, Japanese, and Korean.
-
-   The UTF-8 uncoding of the UCS has been adopted by the Internet as the
-   preferred character set for new applications, and is gradually being
-   retrofitted into traditional applications like FTP ([542]RFC 2640).
-     _________________________________________________________________
-
-    6.6.3. Conformance Levels
-
-   Although the Unicode and ISO 10646 standards both describe the same
-   character set, these standards differ in many ways, including their
-   stated requirements for conformance and their classification of
-   conformance levels.
-
-   Kermit has always abided by ISO character-set standards, including ISO
-   character-set designation and invocation methods. In adapting Unicode,
-   therefore, we had to choose from among the available ISO designations
-   which, in turn, correspond with ISO 10646 conformance levels. At
-   present, Kermit claims the lowest conformance level, 1, meaning
-   (roughly) that it does not handle combining forms and it does not
-   handle Korean Hangul Jamos (just as, at present, it does not handle
-   Korean in general). Note that ISO 10646 Conformance Levels 1 and 2
-   sidestep the issue of the code changes for Korean Hangul by announcing
-   non-support for Hangul regardless of encoding.
-
-   ISO 10646 Conformance Level 1 is approximately equivalent to Unicode
-   Normalization Form C (described in Unicode Technical Report 15,
-   incorporated into Unicode 3.0).
-
-   As noted in [543]Section 6.6.2, Kermit does not claim to support
-   UTF-16 at the present time, hence the UCS-2 nomenclature. Kermit
-   treats surrogates just as if they were any other UCS-2 characters,
-   rather than as escapes to other planes, which means that (except when
-   converting between UCS-2 and UTF-8) they are translated to "error"
-   characters, since (a) no other planes are defined yet (and if they
-   were, no other character sets supported by Kermit would encode their
-   characters), and (b) no valid surrogate character corresponds to any
-   other UCS-2 character.
-
-   A minor yet significant aspect of Unicode 3.0 and some recent
-   perturbation of ISO 10646-1 (probably Amendment 18, "Symbols and Other
-   Characters") is the addition of the Euro Sign at U+20AC. As noted in
-   [544]Section 6.0, Kermit's "Euro compliance" includes conversion
-   between Latin Alphabet 9 and various PC code pages. Text can also be
-   converted between UCS-2 or UTF-8 and any other Euro-compliant
-   character set (Latin-9, CP858, CP1250, CP1252) without loss of the
-   Euro Sign.
-     _________________________________________________________________
-
-    6.6.4. Relationship of Unicode with Kermit's Other Character Sets
-
-   Kermit's character sets are divided into two groups: single-byte sets
-   (such as Roman, Hebrew, Cyrillic, Greek) and multibyte (various
-   Japanese sets). The two groups are distinct since one normally would
-   not expect to convert Kanji ideograms to Roman (or other) letters, or
-   vice versa.
-
-   Unicode character-set conversion works with both groups, but obviously
-   the result depends on the repertoires of the source and destination
-   character-sets both including the characters in the file. For example,
-   you can translate a Hungarian text file between Latin-2 and Unicode,
-   but not between (say) Unicode and Latin/Greek. By the same token you
-   can convert Japanese text from Shift-JIS or EUC or JIS-7 to Unicode
-   and back, but you can't convert the same file to (say) Latin-1 if it
-   contains Japanese characters.
-
-     JIS-7 is equivalent to DEC Kanji and ISO-2022-JP except that the
-     latter two do not support halfwidth Katakana. Kermit treats all
-     three of these sets the same way, i.e. as JIS-7.
-
-   As noted, Kermit presently does not handle combining diacritics, and
-   so will not correctly convert UCS files that use them into a
-   single-byte character set. For example, if a UCS file contains Latin
-   Capital Letter A (U+0041) followed by Combining Acute Accent (U+0301),
-   the result will be a two-character sequence, A followed by another
-   character. This is what is meant by Conformance Level 1. (The
-   situation grows worse with multiple diacritics, since they can occur
-   in any order.)
-
-   A higher level of conformance is possible, in which "canonical
-   equivalences" are handled via algorithms and databases, at some
-   (perhaps considerable) cost in performance, since a fair amount of
-   additional code must be executed for every character during data
-   transfer (database lookup, sorting of combining sequences into
-   canonical order, etc). This can be added in future releases if there
-   is a need (but in many cases, pre- and postpostprocessing might be a
-   better option).
-
-   Within these constraints, Kermit converts between the UCS and its
-   other character sets. For example, a mixture of Russian and English
-   (and/or Dutch, or Latin) text can bet converted between the UCS and
-   ISO Latin/Cyrillic or KOI-8. But since Kermit does not presently
-   support Arabic character-set conversion, the new availability of UCS
-   conversion does not mean that Kermit can convert from Arabic UCS text
-   to some other character set, because Kermit does not support any other
-   character set that includes Arabic. Ditto for Thai, Armenian,
-   Georgian, Tibetan, Chinese, Korean, etc. However, Kermit CAN convert
-   Arabic (or any other script) between UCS-2 and UTF-8.
-
-   Considering Cyrillic more carefully, note that the UCS also contains
-   numerous Cyrillic characters not found in any of the Cyrillic sets
-   (ISO Latin/Cyrillic, KOI8, CP866, etc) that Kermit supports;
-   characters needed for Abkhasian, Yakut, Tatar, Bashkir, Altaic, Old
-   Church Slavonic, etc; UCS text containing any of these historic or
-   "extended" Cyrillic characters can not be converted to any of Kermit's
-   current single-byte Cyrillic sets without loss. The situation is
-   similar for Greek, Hebrew, etc, and even worse for Japanese since
-   Unicode contains thousands of Kanjis that are lacking from the
-   Japanese character sets based on JIS X 0208, such as EUC-JP, JIS-7,
-   and Shift-JIS.
-
-   In general, when converting from UCS to a single-byte set, there is
-   always the possibility of data loss, just as there is when converting
-   from any larger set to a smaller one. For example, if a UCS file
-   contains Devanagari characters, these characters will be lost when
-   converting to (say) Latin-1, just as Roman vowels with acute accents
-   are lost when converting from Latin-1 (an 8-bit set) to German ISO 646
-   (a 7-bit set).
-     _________________________________________________________________
-
-    6.6.5. Kermit's Unicode Features
-
-   C-Kermit can convert between UCS-2 or UTF-8 and any of its other
-   character sets, and also between UCS-2 and UTF-8. When converting
-   between UCS-2 or UTF-8 and a non-Unicode character set (such as
-   Latin-1), the UCS Line Separator (LS, U+2028) and Paragraph Separator
-   (PS, U+2029) characters are converted to the appropriate line
-   terminator (CR, LF, or CRLF). When converting from a non-Unicode set
-   to UCS-2 or UTF-8, however, line terminators are not converted to LS
-   or PS. This is in accordance with the recommendations of Unicode
-   Technical Report #13.
-
-   When C-Kermit starts, it tests the native byte order of the computer.
-   You can see the result in the SHOW FEATURES or SHOW FILE display. It's
-   also available in the variable \v(byteorder): 0 means Big Endian, 1
-   means Little Endian.
-
-   When UCS-2 is involved in file transfer or translation, the following
-   commands tell C-Kermit what to do about byte order:
-
-   SET FILE UCS BYTE-ORDER { BIG-ENDIAN, LITTLE-ENDIAN }
-          This is for reading UCS-2 files that don't have a BOM, and also
-          for writing UCS-2 files. If this command is not given, the
-          machine's native byte order is used when writing UCS-2 files,
-          and also when reading UCS-2 files that don't have a BOM.
-
-   SET FILE UCS BOM { ON, OFF }
-          This setting is used when creating UCS-2 files. A BOM is added
-          at the beginning by default. Use OFF to not add the BOM. This
-          command has no affect when writing files.
-
-   COPY /SWAP-BYTES sourcefile destinationfile
-          Use this for fixing a UCS-2 file whose bytes are in the wrong
-          order.
-
-   Use SHOW FILE to display the FILE UCS settings.
-
-   Please note, again, that C-Kermit's user interface, including its
-   script language, is not internationalized in any way. String
-   comparisons, case conversion, and so on, work only for US ASCII
-   (comparisons for equality work with other sets, but not
-   lexically-greater-or-less-than or caseless comparisons; even
-   comparisons for equality can fail when composed characters or byte
-   order are involved). String functions such as \findex() and
-   \fsubstring() that reference byte positions do just that; they won't
-   work with UTF-8 text that contains any non-ASCII characters, and they
-   will not work with UCS-2 text at all since they use C strings
-   internally, which are NUL-terminated. These are just a few examples to
-   illustrate that neither Unicode nor any other character-set beyond
-   ASCII is supported at the user-interface, command, or scripting level
-   in this version of C-Kermit.
-     _________________________________________________________________
-
-    6.6.5.1. File Transfer
-
-   Kermit supports both UCS-2 and UTF-8 as file and transfer character
-   sets in text-mode file transfer.
-
-   To select UCS-2 or UTF-8 as a file character-set, use:
-
-  SET FILE CHARACTER-SET { UCS2, UTF8 }
-
-   If you want to send a UCS-2 text file (or save an incoming file in
-   UCS-2 format), tell Kermit to:
-
-  SET FILE CHARACTER-SET UCS2
-
-   and if you want to send a UTF-8 text file (or store an incoming file
-   in UTF-8 format), tell Kermit to:
-
-  SET FILE CHARACTER-SET UTF8
-
-   When sending UCS-2 files, Kermit determines the byte order from the
-   BOM, if there is one (and if there is a BOM, it is stripped, i.e. not
-   sent). If there is no BOM, the byte order is the one specified in the
-   most recent SET FILE UCS BYTE-ORDER command, if any, otherwise the
-   computer's native byte order is assumed. When storing incoming files
-   as UCS-2, the byte order is according SET FILE UCS BYTE-ORDER, if
-   given, otherwise the native one; a BOM is written according to SET
-   FILE UCS BOM.
-
-   A transfer character-set should be chosen that includes all of the
-   characters in the source file. So, for example, if you are sending a
-   UCS-2 file containing only German-language text, your transfer
-   character-set can be Latin-1, Latin-2, Latin-9, UCS-2, or UTF-8. But
-   if you are sending a file that contains a combination of Hebrew and
-   Greek, your transfer character-set must be UCS-2 or UTF-8 if you don't
-   want to lose one script or the other. Furthermore, the transfer
-   character-set must be one that is supported by the receiving Kermit
-   program. Since UCS support is new, it is possible that the other
-   Kermit program (if it supports character sets at all) does not support
-   it, but does support single-byte sets such as Latin-1, Latin/Cyrillic,
-   etc.
-
-   To select UCS-2 or UTF-8 as a transfer character-set, use:
-
-  SET TRANSFER CHARACTER-SET { UCS2, UTF8 }
-
-   It is up to the receiving Kermit program to convert the transfer
-   format to its own local format, if necessary. If it does not
-   understand the UTF-8 or UCS-2 transfer character-set, and your file
-   can not be adequately represented by any single-byte transfer
-   character-set (such as Latin-1 or Latin/Cyrillic) then, if UTF-8
-   format is acceptable on the receiving computer, use UTF-8 as the
-   transfer character-set, with the receiver told to "set unknown-char
-   keep", or with the sender told to "set attribute char off". If you
-   want the file to be stored in UCS-2 format at the receiver, send it it
-   binary mode if the source file is also UCS-2, or else use the
-   TRANSLATE command (next section) to convert it to UCS-2 first, then
-   send it in binary mode. You should not use UCS-2 as a transfer
-   character-set in text-mode transfers to Kermit programs that don't
-   support it, because they are likely to corrupt the result the same way
-   FTP would (see the final paragraph of this section).
-
-   When UCS-2 is the transfer character set, it always goes into Kermit
-   packets in Big Endian format, with no BOM. As always, the transfer
-   character-set is announced by the sender to the receiver. The
-   announcement for UCS-2 is "I162" (ISO Registration 162 = UCS-2 Level
-   1) and by definition it is Big Endian (the standards say that when
-   UCS-2 is serialized into bytes, the order must be Big Endian). The
-   announcement for UTF-8 is "I190" (UTF-8 Level 1).
-
-   When receiving a file whose transfer character-set is UCS-2 or UTF-8,
-   you must choose the appropriate file character set for the result.
-   There is no way Kermit can do this for you automatically, since UCS
-   data can be in any script at all, or any combination.
-
-   In general, UTF-8 or UCS-2 should be chosen as a transfer
-   character-set if the source file is also encoded in some form of UCS
-   and it contains more than one script. But there are other situations
-   where where UTF-8 or UCS-2 offer advantages. For example, suppose the
-   source file is on a NeXTstation and the destination file is on VMS.
-   Both the NeXT and the DEC Multinational character sets include the
-   French OE digraph, but Latin-1 does not. Therefore French words
-   containing this character might not arrive intact when Latin-1 is the
-   transfer character-set, but will with UTF-8 or UCS-2, since the UCS
-   includes the OE digraph (but so does Latin-9).
-
-   UCS-2 should be chosen as a transfer character-set only for Japanese
-   text files that contain a large preponderance of Kanji, since in this
-   case (and only this case) UCS-2 (two bytes per Kanji) is more
-   efficient than UTF-8 (three bytes per Kanji). The same will be true
-   for Chinese and Korean when they are supported by Kermit. UCS-2 should
-   never be used as a transfer character-set with a transfer partner that
-   does not support UCS-2 since this can cause file corruption (see last
-   paragraph in this section).
-
-   Note that Kermit's repeat-count compression is 100% ineffective for
-   UCS-2, and is also ineffective for multibyte characters in UTF-8 and
-   EUC-JP; this is because repeat-compression is a transport-level
-   mechanism that operates on a per-byte basis; it has no knowledge of
-   the distinction between a byte and a character.
-
-   When C-Kermit starts, it sets up associations ([545]Section 6.5) for
-   incoming files whose transfer character sets are UCS-2 or UTF-8
-   appropriately for the platform so that the file character-set for the
-   incoming file is UCS-2 in Windows and UTF-8 elsewhere. Otherwise,
-   C-Kermit does not make any default associations for UCS-2 or UTF-8,
-   but of course you may add or change associations to suit your needs
-   and preferences by including the appropriate ASSOCIATE commands in
-   your Kermit startup file. For example, if you are a PC user and deal
-   only with text written in Greek and English, you can:
-
-  ASSOCIATE TRANSFER-CHARACTER-SET UTF8 CP869
-  ASSOCIATE TRANSFER-CHARACTER-SET UCS2 CP869
-  ASSOCIATE FILE-CHARACTER-SET CP869 UTF8
-
-   Note that when file transfer involves conversion between a single-byte
-   character set and UCS-2 or UTF-8, the file-transfer thermometer and
-   estimated time left might be inaccurate, since they are based on the
-   source file size, not the transfer encoding. This is purely a cosmetic
-   issue and does not effect the final result. (And is not, strictly
-   speaking, a bug; Kermit protocol presently includes no method for the
-   sender to furnish an "estimated transfer size" to the receiver, and in
-   any case any such guess could be as far off as the file size, given
-   the many other factors that come into play, such as compression and
-   prefixing).
-
-   A caution about FTP and UCS-2. As noted previously, if you transfer a
-   UCS-2 file with FTP in binary mode between two computers with opposite
-   Endianness, the result will have its bytes in the wrong order.
-   However, if you use FTP to transfer a UCS-2 file in "ascii" (text)
-   mode to ANY computer, even if it is identical to yours, the result
-   will be corrupted because FTP's line-terminator conversions do not
-   account for UCS-2. The same holds when sending from a UCS-aware Kermit
-   program to an older Kermit program in text mode with a transfer
-   character-set of UCS-2. So use UCS-2 as a transfer character-set ONLY
-   with a UCS-2-aware Kermit partner.
-     _________________________________________________________________
-
-    6.6.5.2. The TRANSLATE Command
-
-   In Kermit versions that have Unicode support included, TRANSLATE now
-   always goes through Unicode; that is, the source set is converted to
-   UCS-2 and thence to the target set. This is a major improvement, since
-   in prior releases, C-Kermit had to pick the "most appropriate"
-   transfer character-set as the intermediate set, and this would result
-   in the loss of any characters that the source and target sets had in
-   common but were lacking from the intermediate set (for example the OE
-   digraph when translating from NeXT to DEC MCS through Latin-1). This
-   never happens when Unicode is the intermediate set because Unicode is
-   a superset of all other character sets supported by Kermit. A more
-   dramatic example would be translation between Cyrillic PC code page
-   866 and KOI8-R ([546]Section 6.4); formerly all the line- and
-   box-drawing characters would be lost (since ISO 8859-5 does not have
-   any); now the ones that these two sets have in common are preserved.
-
-   UCS-2 and UTF-8 are now both supported as source-file and
-   destination-file character sets by C-Kermit's TRANSLATE command, for
-   example:
-
-  translate oofa.txt ucs2 latin1 oofa-l1.txt
-
-   translates oofa.txt from UCS-2 to Latin-1, storing the result as
-   oofa-l1.txt. Similarly:
-
-  translate oofa.txt utf8 latin1 oofa-l1.txt
-  translate oofa.txt latin1 ucs2 oofa-ucs2.txt
-  translate oofa.txt latin1 utf8 oofa-utf8.txt
-  translate oofa.txt ucs2 utf8 oofa-utf8.txt
-  translate oofa.txt utf8 ucs2 oofa-ucs2.txt
-
-   Treatment of the UCS-2 BOM is exactly the same as for file transfer.
-   Note that if a UCS-2 source file is in the "wrong" byte order and
-   lacks a BOM, and you don't tell Kermit about it with SET FILE UCS
-   BYTE-ORDER, the result of the translation is total gibberish. Recall
-   that you can use COPY /SWAP-BYTES to switch the byte order of an
-   errant UCS-2 file (or any other file for that matter, if you can think
-   of a reason to). Also note that:
-
-  translate oofa.txt ucs2 ucs2 new.txt
-
-   Produces a result in the native (or SET FILE UCS) byte-order as long
-   as oofa.txt has a BOM.
-
-   As a side benefit of the Unicode work, the TRANSLATE command now works
-   for the first time also for all Japanese character sets that Kermit
-   supports. In other words, if you have a Japanese text file in any of
-   the following encodings:
-
-  EUC-JP
-  Shift-JIS
-  JIS-7
-  UCS-2
-  UTF-8
-
-   You can use the TRANSLATE command to convert to any other encoding
-   from the same list.
-     _________________________________________________________________
-
-    6.6.5.3. Terminal Connection
-
-   The CONNECT command now allows UTF-8 as a local or remote terminal
-   character-set:
-
-  SET TERMINAL CHARACTER-SET { ..., UTF8 } { ..., UTF8 }
-  SET TERMINAL REMOTE-CHARACTER-SET { ..., UTF8 }
-  SET TERMINAL LOCAL-CHARACTER-SET { ..., UTF8 }
-
-   (Recall that Kermit's terminal character-set has two "ends" -- the set
-   used on the host to which Kermit is connected, and the set used on the
-   local keyboard and screen.)
-
-   UCS-2 is not supported as a terminal character-set (either end) since
-   (a) it is not used that way anywhere to our knowledge, and (b) the
-   problems of Endianness and the high likelihood of loss of
-   synchronization make it impractical. (Telecommunications is
-   byte-oriented; if one byte, or any odd number of bytes, is lost
-   because of buffer overruns, circuit resets, etc (or likewise if a
-   burst of noise appears that takes the guise of an odd number of
-   bytes), the byte order of the subsequent data stream will be
-   backwards; unlike UTF-8 and traditional byte-based character sets,
-   UCS-2 is not "self synchronizing".)
-
-   UTF-8 does not have byte-order or synchronization problems and is
-   growing in popularity as a terminal character set as well as in other
-   application areas. It allows a single terminal session to use multiple
-   scripts (Roman, Cyrillic, Greek, etc) without ISO 2022 character-set
-   switching (which terminal emulators like Kermit 95 can handle but few
-   host applications understand or use), and meshes nicely with the
-   Unicode screen fonts that are beginning to appear.
-
-   UTF-8 was first used in Plan 9 and soon will be available in Linux. It
-   will probably spread from there (Unicode in some form is, of course,
-   also used in Windows NT, but only internally -- not for access from
-   outside).
-
-   To use UTF-8 or any other character set that uses 8-bit bytes in your
-   terminal session, be sure to tell C-Kermit to:
-
-  SET TERMINAL BYTESIZE 8
-  SET COMMAND BYTESIZE 8
-  SET PARITY NONE
-
-   (or use the shortcut command, EIGHTBIT, which does all three at once).
-
-   In a setup where your local Kermit program uses a single-byte
-   character set such as PC Code Page 850 and the remote host uses UTF-8:
-
-  SET TERM CHAR UTF8 CP850
-
-   or:
-
-  SET TERM REMOTE CHAR UTF8
-  SET TERM LOCAL CHAR CP850
-
-   all works as expected. UTF-8 text on the remote displays correctly on
-   your screen, and when you type CP850 characters, they are translated
-   to UTF-8 sequences for transmission, and the echo from the host is
-   translated from UTF-8 back to CP850. Telnet negotiations and
-   autodownload take place before any character-set translation and work
-   as before. The session log (if text mode was selected for it) contains
-   only the local terminal character-set. And so on.
-
-   Kermit merely supplies translations from UTF-8 to your local terminal
-   character-set (this includes treating UTF-8 Line Separator and
-   Paragraph separator as CRLF). However, Kermit does does not, at
-   present, perform "canonicalization" of composed sequences, nor does it
-   automatically execute bidirectionality algorithms for display of
-   mixed-direction text (e.g. Hebrew and English). Such presentation
-   issues, like all others in the terminal-host regime, are left to the
-   host.
-
-   By the way, C-Kermit also allows UTF-8 to be the local end of the
-   terminal character-set, but so far this code is not tested, since we
-   don't have a UTF-8 console or terminal to work with. However, it can
-   be stated without doubt that C-Kermit's key mapping will not work for
-   UTF-8 values, since (a) the key map is indexed by 8-bit byte values
-   and (b) C-Kermit reads keystrokes a byte at a time (these comments do
-   not apply to K95, which has direct access to the keyboard and can read
-   "wide" keycodes and uses them to index a "wide" keymap).
-
-   Restrictions: As noted, the CONNECT command does not support UCS-2 as
-   a REMOTE TERMINAL character-set. Neither does it support the Japanese
-   sets EUC-JP, JIS-7, and Shift-JIS. Support for the Japanese sets (and
-   possibly Chinese and Korean too) might be added in a future release.
-   Since the TRANSMIT command (next section) uses the same REMOTE
-   TERMINAL character-sets as the CONNECT command, it has the same
-   restrictions.
-     _________________________________________________________________
-
-    6.6.5.4. The TRANSMIT Command
-
-   As described in Chapter 15 of [547]Using C-Kermit and [548]Section
-   4.21 of this document, the TRANSMIT command can be used to upload a
-   file without protocol, more or less as if you were typing it on your
-   keyboard while connected to the host. When TRANSMITting in text mode,
-   the file's character set is converted to the host's unless you have
-   SET TERMINAL CHARACTER-SET TRANSPARENT, or you include the new
-   TRANSMIT switch, /TRANSPARENT.
-
-   Before C-Kermit 7.0, the file character-set was assumed to be the same
-   as the local end of the terminal character-set, and the TRANSMIT
-   command used the same translations as the CONNECT command, ignoring
-   the file character-set.
-
-   In C-Kermit 7.0, that assumption (a poor one to begin with) can no
-   longer be made, since UCS-2 can be a file character-set but not a
-   terminal character-set. So now the file's character-set is given by
-   your most recent SET FILE CHARACTER-SET command. The host's character
-   set is the remote end of your most recent SET TERMINAL CHARACTER-SET
-   command:
-
-  SET TERMINAL CHARACTER-SET remote-set [ local-set ]
-
-   or:
-
-  SET TERMINAL REMOTE-CHARACTER-SET remote-set
-
-   The TRANSMIT command converts each source-file character from the FILE
-   character-set to the REMOTE TERMINAL character-set, and then transmits
-   the translated characters according to your SET TRANSMIT preferences
-   (Chapter 15).
-
-   If you have SET TRANSMIT ECHO ON, and the host is echoing the
-   transmitted characters, the echos are converted from the remote
-   terminal character-set to the local terminal character-set.
-
-  [ A picture would help... ]
-
-   Confused? Let's work through an example. Suppose your local computer
-   is a NeXTstation, on which text files are encoded in the NeXT
-   character set, and that the remote computer is a Data General AViiON,
-   which uses the Data General International character set. Further
-   suppose that you are logged in to the NeXT from a VT220 terminal which
-   uses the DEC Multinational character set.
-
-   You need to convert the file from NeXT encoding to DG encoding and
-   convert the echoes from DG encoding to DEC encoding. So on the NeXT,
-   tell C-Kermit to:
-
-  eightbit
-  set file character-set next
-  set term character-set dg-international dec-mcs
-  transmit /text nextdata.txt
-
-   (This assumes you have some sort of collection process already set up
-   on the Data General, such as a text editor or the venerable "cat >
-   foo". The EIGHTBIT command is equivalent to SET TERMINAL BYTESIZE 8,
-   SET COMMAND BYTESIZE 8, SET PARITY NONE.)
-
-   To further complicate matters, suppose your local terminal character
-   set is the same as the remote one, so you don't need terminal
-   character-set translation, but you need to TRANSMIT a file that is in
-   a different character set and you want it translated to the host set.
-   In this case, use SET TERM CHARACTER-SET to actually specify the
-   character set used on each end, rather than specifying TRANSPARENT:
-
-  eightbit
-  set file character-set ucs2
-  set term character-set latin1 latin1
-  transmit /text ucs2data.txt
-
-   The distinction between:
-
-  SET TERMINAL CHARACTER-SET xxx yyy
-
-   (where xxx and yyy are the same set) and:
-
-  SET TERMINAL CHARACTER-SET TRANSPARENT
-
-   is new to C-Kermit 7.0, but affects only the TRANSMIT command.
-
-   The TRANSMIT command currently does nothing special with UCS-2/UTF-8
-   Line and Paragraph Separator characters; more experience is required
-   to find out how these behave in a genuine Unicode terminal-host
-   setting.
-
-   Restrictions: As noted, the TRANSMIT command translates from the FILE
-   character-set to the REMOTE TERMINAL character-set. This rules out
-   translations to any character set that is not supported as a REMOTE
-   TERMINAL character-set, such as UCS-2, EUC-JP, JIS-7, and Shift-JIS.
-     _________________________________________________________________
-
-    6.6.5.5. Summary of Kermit Unicode Commands
-
-   Specifying file character-set and byte order:
-          SET FILE CHARACTER-SET { ..., UCS2, UTF8 }
-          REMOTE SET FILE CHARACTER-SET { ..., UCS2, UTF8 } (See next
-          section)
-          SET FILE UCS BOM { ON, OFF }
-          SET FILE UCS BYTE-ORDER { BIG-ENDIAN, LITTLE-ENDIAN }
-
-   Specifying the transfer character-set:
-          SET TRANSFER CHARACTER-SET { ..., UCS-2, UTF-8 }
-          REMOTE SET TRANSFER CHARACTER-SET { ..., UCS-2, UTF-8 }
-
-   Specifying the terminal character-set:
-          SET TERMINAL CHARACTER-SET { ..., UTF8 } { ..., UTF8 }
-          SET TERMINAL REMOTE-CHARACTER-SET { ..., UTF8 }
-          SET TERMINAL LOCAL-CHARACTER-SET { ..., UTF8 }
-
-   Displaying settings:
-          SHOW FILE
-          SHOW TRANSFER
-          SHOW TERMINAL
-          SHOW CHARACTER-SETS
-
-   Commands that use these settings include:
-          SEND, RECEIVE, GET, etc.
-          CONNECT
-          TRANSMIT
-          LOG SESSION
-
-   Converting files:
-          TRANSLATE infile { ..., UCS-2, UTF-8 } { ..., UCS-2, UTF-8 }
-          outfile
-          COPY /SWAP-BYTES infile outfile
-     _________________________________________________________________
-
-  6.7. Client/Server Character-Set Switching
-
-   A simple mechanism has been added to allow the client to change the
-   server's FILE CHARACTER-SET:
-
-   REMOTE SET FILE CHARACTER-SET name
-          The client asks the server to change its file character-set to
-          the one given. The name must match one of the server's file
-          character-set names. For convenience, C-Kermit uses its own
-          file character-set keyword list for parsing this command so you
-          can use ? for help and Tab or Esc for completion. However,
-          since the server might have a different repertoire (or even use
-          different names for the same sets), C-Kermit accepts any string
-          you supply and sends it to the server. The server, if it
-          supports this command (C-Kermit 7.0 and K95 1.1.19 do), sets
-          its file character-set as requested, and also disables
-          automatic character-set switching ([549]Section 6.5). If the
-          server does not support this command or if it does not support
-          the given character set, the REMOTE SET FILE CHARACTER-SET
-          command fails.
-
-   Here's an example that sends a Japanese text file encoded in Shift-JIS
-   to a server using every combination of Kermit's Japanese-capable file
-   and transfer character sets:
-
-  dcl \&x[] = euc ucs2 utf8             ; transfer character-sets
-  dcl \&y[] = eu uc ut                  ; 2-letter abbreviations for them
-  dcl \&f[] = shift euc jis7 ucs2 utf8  ; file character-sets
-  dcl \&g[] = sj eu j7 uc ut            ; 2-letter abbreviations
-
-  set file char shift-jis               ; local file character-set is Shift-JIS
-  for \%i 1 \fdim(&x) 1 {               ; for each transfer character-set...
-      set xfer char \&x[\%i]            ; set it
-      for \%j 1 \fdim(&f) 1 {           ; for each remote file character-set...
-          remote set file char \&f[\%j] ; set it
-          if fail exit 1 SERVER REJECTED CHARSET
-          send /text meibo-sj.html meibo-sj-\&y[\%i]-\&g[\%j].txt ; send the fi
-le
-          if fail exit 1 TRANSFER FAILED
-      }
-  }
-
-   The Kermit-370 server does not support REMOTE SET FILE CHARACTER-SET,
-   but since it supports REMOTE KERMIT commands, you can get the same
-   effect with REMOTE KERMIT SET FILE CHARACTER-SET name.
-     _________________________________________________________________
-
-  7. SCRIPT PROGRAMMING
-
-   (Also see [550]Section 2.8, Scripting Local Programs.)
-
-  7.0. Bug Fixes
-
-   The following script programming bugs were fixed in C-Kermit 7.0:
-
-     * IF EXIST and IF DIRECTORY were fixed to properly strip braces from
-       around their arguments, so "if directory {C:\Program Files}", etc,
-       would work as expected. However, this means that if the file or
-       directory name is actually enclosed in braces, the braces must be
-       doubled.
-     * The READ command did not fail if the READ file wasn't open; now it
-       does.
-     * The READ command refused to read the last or only line of a file
-       if it did not end with a proper line terminator; now it does.
-     * The END command, when given from within a SWITCH statement, did
-       not exit from the current macro or command file; instead it just
-       terminated the SWITCH.
-     _________________________________________________________________
-
-  7.1. The INPUT Command
-
-   7.1.1. INPUT Timeouts
-
-   The description of the INPUT command on page 422 fails to mention the
-   following two points about the timeout (which apply to C-Kermit 6.0
-   and later):
-
-    1. "INPUT -1 text" (or "INPUT \%x text", where \%x is any variable
-       whose value is -1 or less) means "wait forever". This form of the
-       INPUT command fails only if it is interrupted, since it will never
-       time out.
-    2. INPUT 0 performs a nonblocking read of material that has already
-       arrived but has not yet been read, and succeeds immediately if the
-       target string is found, or fails immediately if it is not found.
-
-   The same points apply to MINPUT. REINPUT ignores its timeout
-   parameter.
-     _________________________________________________________________
-
-    7.1.2. New INPUT Controls
-
-   The following new INPUT controls were added in version 7.0:
-
-   SET INPUT AUTODOWNLOAD { ON, OFF }
-          Explained in [551]Section 7.7.
-
-   SET INPUT CANCELLATION { ON, OFF }
-          This governs whether an INPUT command can be canceled by
-          "pressing any key" on the keyboard. Normally it can be, in
-          which case the INPUT command fails immediately and \v(instatus)
-          is set to 2, indicating interruption. SET INPUT CANCELLATION
-          OFF disables keyboard cancellations; thus if the search text is
-          not encountered, the INPUT command will run for its entire
-          timeout interval. SET INPUT CANCELLATION OFF does not disable
-          interruption by Ctrl-C, however; every command needs an
-          emergency exit. (If you really want to disable interruption by
-          Ctrl-C, use SET COMMAND INTERRUPTION OFF.)
-
-   Also see [552]Section 7.2 for any new variables related to INPUT.
-     _________________________________________________________________
-
-    7.1.3. INPUT with Pattern Matching
-
-   C-Kermit 7.0 allows INPUT, MINPUT, and REINPUT targets to be a pattern
-   (explained in [553]Sections 1.19 and [554]4.9). This solves a
-   long-standing problem illustrated by the following scenario: a certain
-   company has a bank of TCP/IP modem servers, with hostnames server1,
-   server2, server3, and so on. Each server's prompt is its name,
-   followed by a colon (:), for example "Server72:". Without INPUT
-   patterns, it would be rather difficult to wait for the prompt. The
-   brute force approach:
-
-  minput 20 Server1: Server2: Server3: ... (enumerating each one)
-
-   is subject to failure whenever a new server is added. A more subtle
-   approach:
-
-  input 20 Server
-  if fail ...
-  input 2 :
-
-   is liable to false positives, e.g. "Welcome to the XYZ Corp Modem
-   Server. Please read the following message:"...
-
-   With patterns, you can match the prompt with "Server*:" (which doesn't
-   solve the "false positives" problem, but certainly is more compact
-   than the brute force method), or with more specific patterns such as
-   "Server[1-9]:" and "Server[1-9][0-9]:", or equivalently:
-
-  Server{[1-9],[1-9][0-9]}:
-
-   meaning the word "Server" followed by a single digit (1-9) or by two
-   digits representing a number from 1 to 99, followed by a colon.
-
-   INPUT pattern matching has been added in a way that does not interfere
-   with existing scripts. No new commands or switches are used. The
-   simple rule is: if an INPUT search target is the argument of the (new)
-   \fpattern() function, it is a pattern. Otherwise it is taken
-   literally, as before. For example:
-
-  input 5 a*b
-
-   searches for an 'a' followed by an asterisk ('*'), followed by a 'b'.
-   But:
-
-  input 5 \fpattern(a*b)
-
-   searches for an 'a' followed by anything at all up to and including
-   the first 'b'. This means that any search target to INPUT, MINPUT, or
-   REINPUT can be a pattern or a literal string, and in particular that
-   MINPUT can accommodate any mixture of patterns and literal strings.
-
-   In selecting patterns, note that:
-
-     * A leading '*' is always implied so there is no need to include
-       one.
-     * A trailing '*' is meaningless and ignored.
-     * A '*' by itself matches the first character that arrives.
-
-   A syntax note: If your pattern is a selection list, meaning a list of
-   alternatives separated by commas and enclosed in braces, then the
-   outer braces will be stripped by various levels of parsers, so you
-   must include three of each:
-
-  input 10 \fpattern({{{abc,mno,xyz}}})
-
-   Note that this is equivalent to:
-
-  minput 10 abc mno xyz
-
-   except for the setting of the \v(minput) variable.
-
-   And a caution: INPUT pattern matching has a limitation that you
-   probably never noticed with literal-string matching, namely that there
-   is a limit on the size of the match. For example, if the pattern is
-   "a*b", the match will succeed if the 'a' and 'b' are not separated by
-   more than (say) 8K bytes, but will fail if they are farther apart than
-   that. In such cases, it better to use two INPUTs (e.g. "input 10 a"
-   and then "input 100 b").
-     _________________________________________________________________
-
-    7.1.4. The INPUT Match Result
-
-   The result of any INPUT, MINPUT, or REINPUT command, no matter whether
-   the search targets are patterns or literal strings, is available in
-   the new \v(inmatch) variable. For example:
-
-  minput 10 cat \fpattern([dh]og)
-  if success echo MINPUT matched "\v(inmatch)"
-
-   This is especially useful when a pattern was matched, since it makes
-   the string that matched the pattern available to Kermit; there would
-   be no way to get it otherwise.
-
-   After an INPUT command, you can view all the INPUT-related variables
-   by typing "show variables in" (abbreviate as "sho var in"), which
-   shows the values of all built-in variables whose names start with
-   "in".
-     _________________________________________________________________
-
-  7.2. New or Improved Built-In Variables
-
-   \v(blockcheck)
-          Current BLOCK-CHECK setting, 1, 2, 3, or 4. 4 is the code for
-          BLANK-FREE-2.
-
-   \v(byteorder)
-          The machine's byte order: 0 = Big Endian, 1 = Little Endian.
-
-   \v(cmdbufsize)
-          The length of the command buffer, which is the maximum size for
-          a macro, a command, a variable, or anything else in C-Kermit's
-          script language.
-
-   \v(ctty)
-          The device name of C-Kermit's controlling (login) terminal.
-
-   \v(filename)
-          Described in [555]Sections 4.1 and [556]4.2.
-
-   \v(filenumber)
-          Described in [557]Sections 4.1 and [558]4.2.
-
-   \v(filespec)
-          As of C-Kermit 7.0, contains fully qualified filenames rather
-          than (usually) relative ones.
-
-   \v(return)
-          Now holds the END n value of the macro that most recently
-          returned, in case END was used rather than RETURN.
-
-   \v(editor)
-          Pathname of preferred text editor
-
-   \v(editopts)
-          Command-line options for editor
-
-   \v(editfile)
-          File most recently edited
-
-   \v(browser)
-          Pathname of preferred Web browser
-
-   \v(browsopts)
-          Command-line options for Web browser
-
-   \v(browsurl)
-          URL most recently given to Web browser
-
-   \v(dialtype)
-          Type of call most recently placed (see [559]Section 2.1.11).
-
-   \v(kbchar)
-          The character, if any, that was typed at the keyboard to to
-          interrupt the most recent PAUSE, SLEEP, WAIT, MSLEEP, or INPUT
-          command; empty if the most recent such command was not
-          interrupted from the keyboard.
-
-   \v(lockdir)
-          UNIX only - The name of the UUCP lockfile directory, if known,
-          otherwise "(unknown)".
-
-   \v(lockpid)
-          UNIX only - PID of process that owns the communication port
-          that you tried to open with a SET LINE command that failed
-          because the port was in use, otherwise empty. This variable is
-          set with every SET LINE command.
-
-   \v(cx_time)
-          If no connection (SET HOST, SET LINE, DIAL, TELNET, etc) is
-          active, this is 0. If a connection is active, this is the
-          number of seconds since the connection was made.
-
-   \v(hwparity)
-          If hardware parity is in effect, this variable gives its value,
-          such as "even" or "odd" (in which case, the \v(parity) variable
-          will be "none"). Otherwise this variable is empty.
-
-   \v(serial)
-          Current serial port settings in 8N1 format ([560]Section 2.10).
-
-   \v(errno)
-          In UNIX, the current value of the C runtime errno variable,
-          which is quite volatile (meaning that often an "interesting"
-          error code can be overwritten by some other library call or
-          system service that sets errno before you have a chance to look
-          at it). In VMS, the error code returned by the system or
-          library call that most recently failed (success codes are not
-          saved). Not available in other operating systems.
-
-   \v(errstring)
-          The UNIX or VMS system error message that corresponds to
-          \v(errno). Not available in all OS's. Also see
-          [561]\ferrstring().
-
-   \v(setlinemsg)
-          The error message, if any, from the most recent SET LINE, SET
-          PORT, SET HOST, TELNET, or other connection-making command.
-          This is not necessarily the same as \v(errstring) since these
-          commands might fail without generating a system error code, for
-          example (in UNIX) because a lockfile existed indicating the
-          device was assigned by another user.
-
-   \v(exitstatus)
-          The exit status C-Kermit would return if it exited now.
-
-   \v(pexitstat)
-          The exit status of the inferior process most recently invoked
-          by C-Kermit (by RUN, !, REDIRECT, SEND /COMMAND, etc). In VMS,
-          this code can be given to \ferrstring() to get the
-          corresponding error message (in UNIX, program/command return
-          codes are not the same as system error codes). Not available in
-          operating systems other than UNIX and VMS. See [562]Section
-          4.2.5 for details.
-
-   \v(inmatch)
-          The incoming string of characters, if any, that matched the
-          most recent INPUT, REINPUT, or MINPUT command.
-
-   \v(intime)
-          The number of milliseconds (thousandths of seconds) it took for
-          the most recent INPUT command to find its match, or -1 if no
-          INPUT command has been given yet. If the INPUT command timed
-          out, the value is approximately equal to 1000 times the INPUT
-          timeout. If INPUT failed for some other reason, the value is
-          undefined (\v(instatus) gives INPUT completion status). If your
-          version of C-Kermit is built without high-precision
-          floating-point timers, this number will always be a multiple of
-          1000.
-
-   \v(inwait)
-          The number of seconds specified as the timeout in the most
-          recent INPUT command.
-
-   \v(dialsuffix)
-          Dialing suffix for use during PDIAL sequence; see [563]Section
-          2.1.10.
-
-   \v(pid)
-          UNIX, VMS, and K95 only. C-Kermit's primary process ID,
-          numeric, decimal. If you want to show it in hex, use
-          \fn2hex(\v(pid)) If you want to show it in octal, use
-          \fn2octal(\v(pid)).
-
-   \v(printer)
-          Current printer name or SET PRINTER value.
-
-   \v(p_ctl)
-          Control prefix char \v(p_8bit) 8-bit prefix char (if parity not
-          none)
-
-   \v(p_rpt)
-          Repeat prefix char (if repeat compression enabled)
-
-   \v(herald)
-          Kermit's version herald
-
-   \v(test)
-          Kermit's test version, if any, or 0 if this is not a test
-          version. Typical values for test versions are "Alpha.03" or
-          "Beta.14".
-
-   \v(sendlist)
-          The number of entries in the SEND-LIST, 0 if none. Note:
-          entries do not necessarily correspond to files, since an entry
-          might contain wildcards. Also note that the value does not go
-          back to 0 after the files in the list are sent. To reset this
-          variable, use CLEAR SEND-LIST. The purpose of this variable is
-          to determine if a SEND command, when given without any
-          filenames, will be legal. Example:
-
-  xif \v(sendlist) { send } else { send oofa.txt }
-
-   \v(trigger)
-          If the most recent CONNECT session was terminated automatically
-          by a trigger, this variable contains the trigger value.
-
-   \v(ty_ln)
-          TYPE line number (during TYPE)
-
-   \v(ty_lc)
-          TYPE line count (after TYPE)
-
-   \v(ty_mc)
-          TYPE match count (after TYPE)
-
-   \v(xferstat)
-          Status of most recent file transfer:
-
--1: No transfer yet
- 0: Succeeded
- 1: Failed
-
-   \v(xfermsg)
-          If the most recent file transfer failed, this is the reason. If
-          it succeeded, \v(xfermsg) is an empty string.
-
-   \v(tftime)
-          Total elapsed time of most recent file transfer operation, in
-          seconds.
-
-   \v(textdir)
-          Directory that holds (or is supposed to hold) Kermit text files
-          such as installation instructions, release notes, update notes,
-          read-me files, "beware" files, etc.
-
-   \v(name)
-          The name with which the Kermit program was invoked, e.g.
-          "kermit", "wermit", "k95", "k2", etc (see [564]Section 9.1).
-
-   \v(osname)
-          Name of operating system on computer where C-Kermit is running,
-          obtained at runtime (from uname or equivalent).
-
-   \v(osversion)
-          Version of operating system on computer where C-Kermit is
-          running, obtained at runtime (from uname or equivalent).
-
-   \v(osrelease)
-          Release of operating system on computer where C-Kermit is
-          running, obtained at runtime (from uname or equivalent).
-
-   \v(model)
-          The specific hardware model of the computer where C-Kermit is
-          running, if known.
-
-   \v(math_pi)
-          The value of Pi (see [565]Section 7.23)
-
-   \v(math_e)
-          The value of e (see [566]Section 7.23)
-
-   \v(math_precision)
-          How many significant digits in a floating-point number.
-
-   \v(f_count)
-          Result of the most recent FILE COUNT (FCOUNT) command.
-
-   \v(f_error)
-          Numeric error code of most recent FILE command.
-
-   \v(f_max)
-          Maximum number of files open simultaneously.
-
-   The math constants are given in the precision of underlying computer's
-   floating-point arithmetic.
-
-   Note the distinction between \v(osname), \v(osversion), and
-   \v(platform); the latter refers to the platform for which and/or upon
-   which C-Kermit was built, as opposed to the one on which it is
-   actually running. Also note that each operating system can, and
-   probably will, interpret and fill in the os* variables differently, or
-   not at all.
-
-   The SHOW VARIABLES command now accepts a variable name, prefix, or
-   pattern:
-
-  show variables         Shows all variables.
-  show variables t       Shows all variables that start with "t".
-  show variables *ver*   Shows all variables whose names contain "ver".
-  show variables *ver    Ditto (an implied "*" is appended).
-     _________________________________________________________________
-
-  7.3. New or Improved Built-In Functions
-
-   The following new file-i/o functions are explained in [567]Section
-   1.22.
-
-  \f_status(channel)           Status of file open on channel
-  \f_pos(channel)              Read/write (byte) pointer of given file
-  \f_line(channel)             Current line of file
-  \f_handle(channel)           Handle of file
-  \f_eof(channel)              Whether given file is at EOF
-  \f_getchar(channel)          Read a char from given file
-  \f_getline(channel)          Read a line from given file
-  \f_getblock(channel,n)       Read a block from given file
-  \f_putchar(channel,c)        Write a char to given file
-  \f_putline(channel,string)   Write a line to given file
-  \f_putblock(channel,string)  Write a block to given file
-
-   The following new date-time-related functions are explained in
-   [568]Section 1.6:
-
-  \fday()                Returns day of week of given date
-  \fnday()               Returns numeric day of week of given date
-  \ftime()               Returns time portion of given date-time
-  \fntime()              Converts time to seconds since midnight
-  \fn2time()             Converts seconds since midnight to hh:mm:ss
-  \fcvtdate(date-time)   Converts free-format date to yyyymmdd hh:mm:ss
-  \fdayofyear(date-time) Converts date to yyyyddd (day-of-year) format
-  \fdoy(date-time)       Synonym for \fdayofyear()
-  \fdoy2date(dayofyear)  Converts yyyyddd to yyyymmdd
-  \fmjd(date-time)       Converts free-format date to Modified Julian Date
-  \fmjd2date(mjd)        Converts modified Julian date to yyyymmdd
-
-   The new floating-point arithmetic functions are explained in
-   [569]Section 7.23. f1 and f2 are floating-point (real) numbers; d is
-   the number of decimal places to show:
-
-  \ffpabsolute(f1,d)     Absolute value of f1
-  \ffpadd(f1,f2,d)       f1 + f1
-  \ffpcosine(f1,d)       Cosine of f1
-  \ffpdivide(f1,f2,d)    f1 divided by f2
-  \ffpexp(f1,d)          e to the f1 power
-  \ffpint(f1)            Integer part of f1
-  \ffplog10(f1,d)        Log base 10 of f1
-  \ffplogn(f1,d)         Natural log of f1
-  \ffpmaximum(f1,f2,d)   Maximum of f1 and f2
-  \ffpminimum(f1,f2,d)   Minimum of f1 and f2
-  \ffpmodulus(f1,f2,d)   Modulus of f1 and f2
-  \ffpmultiply(f1,f2,d)  Product of f1 and f2
-  \ffpraise(f1,f2,d)     Raise f1 to power f2
-  \ffpround(f1,d)        Round f1 to d places
-  \ffpsine(f1,d)         Sine of f1
-  \ffpsqrt(f1,d)         Square root of f1
-  \ffpsubtract(f1,f2,d)  f2 - f1
-  \ffptangent(f1,d)      Tangent of f1
-
-   Integer number functions:
-
-   \fabsolute(n)
-          Absolute value of integer n.
-
-   \frandom(n)
-          Returns a random integer between 0 and n-1.
-
-   \fradix(s,n1,n2)
-          If the string s is an integer in radix n1, the result is the
-          same number expressed in radix n2, where n1 and n2 may be any
-          number from 2 through 36, expressed as decimal numbers, or
-          variables (etc) that evaluate to decimal numbers. For the
-          source and result, the digits of any radix, r, are the first r
-          characters in the sequence 0-9,a-z (case doesn't matter for the
-          letters). The string s may have a sign, + or -; if it starts
-          with a minus (-) sign, the result also has a minus sign.
-
-   The \fradix() function does not work with floating-point numbers. It
-   does not reveal the internal storage format of a number; for example,
-   \fradix(-1,10,16) is -1, not something like FFFFFFFFFF. If all three
-   arguments are not given, or if n1 or n2 are not numbers between 2 and
-   36 inclusive, or s is not a number in radix n1, an error occurs and
-   the empty string is returned. \fradix() also does not offer
-   extended-precision arithmetic; number values are limited to those
-   expressed as a long integer in the architecture of the underlying
-   computer, usually 32 or 64 bits. If you give it an argument whose
-   absolute value is larger than can be held in an unsigned long, the
-   result is -1.
-
-   The next four are shorthand functions for decimal/hexadecimal and
-   decimal/octal number conversion:
-
-   \fn2hex(n)
-          Returns the hexadecimal (base 16) representation of the integer
-          n. This is different from \fhexify(s), which treats its
-          argument as a string rather than a number. The result is always
-          left-padded with 0's to make its length even. Examples:
-
-  \n2hex(0)   = "00"                    \fhexify(0)   = "30"
-  \n2hex(255) = "ff"                    \fhexify(255) = "323535"
-  \n2hex(256) = "0100"                  \fhexify(256) = "323536"
-
-   \fhex2n(x)
-          Converts hexadecimal number x to decimal equivalent decimal
-          number. This is the inverse of \fn2hex(). Equivalent to
-          \fradix(s,16,10).
-
-   \fn2octal(n)
-          Returns the octal (base 8) representation of the number n.
-          Examples:
-
-  \n2octal(0) = "0"
-  \n2oct(255) = "377"
-  \n2oct(256) = "400"
-  Equivalent to \fradix(n,10,8).
-
-   \foct2n(n)
-          Returns the decimal representation of the given octal number,
-          n. The inverse of \fn2octal(). Equivalent to \fradix(n,8,10).
-
-   String functions:
-
-   \s(name[n:m])
-          Equivalent to \fsubstring(\m(name),n,m) ([570]Section 7.24).
-
-   \:(name[n:m])
-          Equivalent to \fsubstring(name,n,m) (where "name" is any
-          \-quantity) ([571]Section 7.24).
-
-   \fleft(s,n)
-          The leftmost ncharacters of string s; equivalent to
-          \fsubstring(s,1,n).
-
-   \fstripx(string,char)
-          Returns the part of the string up to the rightmost occurrence,
-          if any, of the given character. The default character is period
-          (.) Examples:
-
-  \fstripx(foo/bar,/)                 = "foo"
-  \fstripx(foo/bar/baz,/)             = "foo/bar"
-  \fstripx(autoexec.bat,.)            = "autoexec"
-  \fstripx(autoexec.bat)              = "autoexec"
-  \fstripx(fstripx(foo/bar/baz,/),/)  = "foo"
-
-   \flop(string,character)
-          Returns the portion of the string starting after the first
-          occurrence of the given character. The default character is
-          period (.) Examples:
-
-  \flop(autoexec.bat)                 = "bat"
-  \flop(baz.foo/bar)                  = "foo/bar"
-  \flop(baz.foo/bar,/)                = "bar
-
-   \fstripn(string,n)
-          Returns the string with ncharacters removed from the end.
-          Example:
-
-  \fstripn(12345678,3)                = "12345"
-
-          (For more discussion of \fstripx(), \fstripn(), and \flop() see
-          [572]Section 4.2.3).
-
-   \fb64encode(s)
-          Returns the Base-64 encoding of the string s.
-
-   \fb64decode(s)
-          Returns the decoding of the Base-64 string s. Fails if s is not
-          a Base-64 string, or if its length is not a multiple of 4. Note
-          that if any of the result bytes are null (0), the result string
-          stops there. There is no way to represent strings that contain
-          null bytes in C-Kermit (the same is true for \funhexify()).
-
-   \fword(s1,n,s2,s3)
-          Extracts word number nfrom string s1. By default, a "word" is
-          any sequence of ASCII letters or digits; nis 1-based. If nis
-          omitted, "1" is used. Examples:
-
-  \fword(one two three)    = "one"
-  \fword(one two three,1)  = "one"
-  \fword(one two three,2)  = "two"
-  \fword(one two three,3)  = "three"
-
-          and:
-
-    \fword(\v(dialresult),2) = "31200"
-
-          is "31200" if \v(dialresult) is (e.g.) "CONNECT
-          31200/ARQ/V32/LAPM/V42BIS".
-
-          If you include s2, this replaces the default break set. For
-          example, suppose you have a string \%a whose value is:
-
-  $150.00 $300.00 $39.95
-
-          and you want each dollar amount to be a word; use:
-
-  \fword(\%a,\%n,{ })
-
-          This returns dollar amount number \%n, e.g. "$300.00" for \%n =
-          2. "{ }" denotes a space (you must enclose it in braces,
-          otherwise it is squeezed out). Note that ASCII control
-          characters are always included in the break set; you don't have
-          to specify them (and you can't not specify them).
-
-          The optional s3 argument lists characters (even control
-          characters) that normally would be considered separators that
-          you want included in words. So the dollars-and-cents example
-          could also be handled this way:
-
-  \fword(\%a,\%n,,$.)
-
-          in other words, use the default separator list, but remove "$"
-          and "." from it so they will be considered part of a word.
-
-   \fsplit(s1,&a,s2,s3)
-          This is like \fword(), except instead of extracting and
-          returning a particular word from string s1, it counts the words
-          and optionally assigns them to the array whose identifying
-          letter, a-z, is given after the "&" in the second argument,
-          with the first word going into element 1, the second into
-          element 2, and so on. The rules regarding break and include
-          lists (s2 and s3) are exactly the same as for \fword().
-          \fsplit() returns the number of words that were assigned, which
-          is either the number of words in the string, or the dimension
-          of the array, whichever is less. If the array is not declared,
-          \fsplit() creates it and returns a number which is both the
-          number of words in s1 and the dimension of the new array.
-          Examples:
-
-  declare \&w[20]        ; (Optional.)
-  ...
-  read \%s               ; \%s is "This is a sentence with seven words."
-  ...
-  echo "\fsplit(\%s)"    ; This would print "7".
-  echo "\fsplit(\%s,&w)" ; Ditto, and also assigns them to array \&w[].
-
-  echo "\&w[7]"          ; This would print "words".
-
-          If the line contained fields that were delimited by colon (:),
-          you would use \fsplit(\%s,&w,:). If the fields were delimited
-          by comma, then you would use \fsplit(\%s,&w,{,}); in this case
-          the literal comma must be enclosed in braces to distinguish it
-          from the comma that separates function arguments. To get a word
-          count without loading an array, but still specify break and/or
-          include lists, leave the array argument empty:
-
-   echo "\fsplit(\%s,,:)" ; Use colon as the separator.
-
-          WARNINGS:
-
-         1. If you use the same array repeatedly, \fsplit() leaves any
-            trailing members undisturbed. For example:
-  dcl \&w[10]
-  \fsplit(1 2 3 4 5,&w) ; Sets \&w[1] thru \&w[5].
-  \fsplit(a b c,&w)     ; Sets \&w[1]-[3] leaving [4]-[5] as they were.
-         2. If you allow \fsplit to create the array (by not declaring it
-            first), it is dimensioned to the number of elements it was
-            created with:
-  \fsplit(1 2 3,&x)     ; Creates an array \&x[] with 3 elements.
-  \fsplit(a b c d e,&x) ; This overflows the array.
-
-          Thus if you want to use \fsplit() repeatedly on the same array,
-          either dimension it in advance to the maximum expected size
-          (and then some -- more efficient), or else destroy it after
-          each use (to allow for unexpectedly large arguments). Example
-          using a dynamic array:
-
-  fopen /read \%c some-file
-  if fail ...
-  set function error on    ; See [573]Section 7.12
-  while true {
-      dcl \&w[]            ; Destroy \&[w] each time thru the loop
-      fread /line \%c \%a
-      if fail break
-      asg \%x \fsplit(\%a,&w)
-      if fail ...
-      ; (do what you want with \&w[] here...)
-  }
-  fclose \%c
-
-   \frindex(s1,s2,n)
-          The "n" argument to \frindex() now works consistently (in
-          mirror image) with the corresponding \findex() argument. In
-          each case, the (n-1)-most characters of s2 are ignored in the
-          search; for findex, this means the starting position of the
-          search is n (the default nis 1, and 0 is treated like 1). For
-          \frindex() it means the default starting point is:
-
-  length(s2) - length(s1) - n (with the same defaults for n).
-
-   \fsearch(pattern,string[,position])
-          Exactly like \findex(), except with a pattern (see [574]Section
-          7.9) rather than a literal string.
-
-   \frsearch(pattern,string[,position])
-          Exactly like \frindex(), except with a pattern rather than a
-          literal string.
-
-          File Functions:
-
-   \ffiles(), \fnextfile()
-          It is no longer necessary to copy the file list to an array
-          before use, as shown on p.398 of [575]Using C-Kermit 2nd
-          Edition. \ffiles() and friends now make their own safe copies
-          of the file list. Thus constructions like the following are now
-          possible:
-
-  for \%i 1 \ffiles(*.txt) 1 { send \fnextfile() }
-
-          The same is true for the new function \frfiles(),
-          \fdirectories(), and \frdirectories(), described in
-          [576]Section 4.11.3.
-
-          But note that each reference to \fnextfile() still gets you the
-          next file. So "if newer \fnextfile() foo.txt send \fnextfile()"
-          compares one file's age with that of foo.txt, and then sends an
-          entirely different file. If you're going to refer to the same
-          file more than once, assign it to a variable:
-
-  asg \%f \fnextfile()
-  if newer \%f foo.txt send \%f
-
-          (note: assign, not define).
-
-          Also note that \ffiles(), \frfiles(), \fdirectories(), and
-          \frdirectories() all now accept on optional 2nd argument: the
-          name of an array to load with the resulting file or directory
-          list, explained in [577]Section 4.11.3. So you can also load an
-          array with the filelist when you need to refer to the same file
-          more than once:
-
-  for \%i 1 \ffiles(*,&a) 1 { if newer \&a[\%i] foo.txt send \&a[\%i] }
-
-   \fpermissions(file)
-          Returns the platform-specific permissions string for the file,
-          such as "-rw-rw-r--" in UNIX or "(RWE,RWE,RE,E)" in VMS.
-
-   \fdirname(f)
-          Given a file specification f, this function returns the
-          complete pathname of directory the file is in.
-
-   Array Functions:
-
-   \fdimension(&a)
-          Returns the dimension declared for the array whose identifying
-          letter, a-z, or special character "_" or "@", is given after
-          the "&" in the argument. If the array is not declared, 0 is
-          returned. Note that when used with the macro argument vector
-          array, \&_[] (see [578]Section 7.5), the value of this function
-          is one less than \v(argc), and when used with the C-Kermit
-          command-line argument vector array, \&@[], it is equal to the
-          \v(args) variable. Examples:
-
-  echo \fdimension(&a)       ; Not declared.
-  0
-  declare \&a[12]            ; Now it's declared.
-  echo \fdim(&a)
-  12
-
-   \farraylook(pattern,arrayname)
-          Looks in the given array for the pattern and returns the index
-          of the first element that matches, if any, or -1 if none match.
-          The arrayname can include a range specifier to restrict to
-          search to a segment of the array, e.g.
-          \farraylook(*xyz*,&a[32:63]). For greater detail see
-          [579]Section 7.10.7.
-
-   \ftablelook(keyword,arrayname[,delimiter])
-          Looks in the given "table", which must be sorted, for the given
-          keyword. Returns the index of the table element that uniquely
-          matches the given keyword, or -1 if none match, or -2 if more
-          than 1 match. For greater detail see [580]Section 7.10.7.
-
-   Other new functions:
-
-   \fip2hex(s)
-          Converts a dotted decimal IP address to an 8-digit hexadecimal
-          number. \fip2hex(128.59.39.2) = 803b2702.
-
-   \fhex2ip(x)
-          Converts an 8-digit hexadecimal IP address to dotted decimal
-          form, e.g. \fhex2ip(803b2702) = 128.59.39.2. The inverse of
-          \fip2hex().
-
-   \fcommand()
-   \frawcommand()
-          These run an external command and return its output; see
-          [581]Section 4.2.8.4.
-
-   \fdialconvert(s)
-          s is a phone number in either literal or portable format (not a
-          dialing directory entry name). The function returns the dial
-          string that would actually be used when dialing from the
-          current location (after processing country code, area code, and
-          other SET DIAL values).
-
-   \ferrstring(n)
-          Returns the system error message associated with the (numeric)
-          error code n. UNIX and VMS only. Use in conjunction with
-          \v(errno) or \v(pexitstat). See [582]Section 4.2.5 for a usage
-          example. Note: This function doesn't work in Windows because
-          there is not a consistent error-code-to-message mapping; error
-          code "x" means something completely different depending on
-          whether it comes from the C runtime library, Winsock, a
-          Windows-32 API, TAPI, etc,
-
-   \fpattern(s)
-          Used in INPUT, REINPUT, and MINPUT commands to denote search
-          strings that are to be treated as patterns rather than
-          literally.
-
-   Also see [583]Section 7.8 on built-in help for functions.
-     _________________________________________________________________
-
-  7.4. New IF Conditions
-
-   IF AVAILABLE feature command
-          Executes the command if the given feature is available.
-          Presently used only to determine if specific authentication and
-          encryption options are available. Type "if available ?" to see
-          which features may be tested.
-
-   IF FLOAT f1 command
-          Executes command if f1 is a legal floating point number (which
-          includes integers). Use this to preverify arguments for the
-          \ffp...() floating-point arithmetic functions, e.g. "if float
-          \%1 echo \ffpint(\%1)".
-
-   IF == n1 n2 command
-          Synonym for "if =" (numeric equality). Note that as of C-Kermit
-          7.0, this and all other numeric comparison operators also work
-          for floating-point numbers.
-
-   IF != n1 n2 command
-          Executes the command if n1 and n2 are both numbers or variables
-          containing numbers and the value of n1 is not equal to the
-          value of n2. This is equivalent to "if not = n1 n2".
-
-   IF <= n1 n2 command
-          Executes the command if n1 and n2 are both numbers or variables
-          containing numbers and the value of n1 is less than or equal to
-          the value of n2. This is equivalent to "if not > n1 n2".
-
-   IF >= n1 n2 command
-          Executes the command if n1 and n2 are both numbers or variables
-          containing numbers and the value of n1 is greater than or equal
-          to the value of n2. Equivalent to "if not < n1 n2".
-
-   IF COMMAND word command
-          Executes the command if word is a built-in C-Kermit command.
-          Example:
-
-  if not command copy define { copy run copy \%1 \%2 }".
-
-          This defines a COPY macro that runs an external COPY command if
-          COPY is not already a built-in command.
-
-   IF LOCAL command
-          Executes the command if Kermit is in local mode, i.e. if it has
-          a SET LINE, SET PORT, or SET HOST (TELNET, RLOGIN, etc) device
-          or connection open. Does not execute the command if in remote
-          mode.
-
-   IF MATCH string pattern command
-          Executes the command if the string matches the pattern. For a
-          description of the syntax for the pattern, see [584]Section
-          4.9.1. If you want to test if the string contains pattern, use
-          IF \fsearch(pattern,string).
-
-   IF OPEN { DEBUG-LOG, SESSION-LOG, TRANSACTION-LOG, ... } command
-          Executes the command if the given file is open, fails if it is
-          not open. Type IF OPEN ? for a complete list of files that can
-          be checked (all the files that can be opened with the OPEN or
-          LOG commands).
-
-   IF QUIET command
-          Executes the command if SET QUIET is ON, and does not execute
-          it if SET QUIET is OFF. Example: IF NOT QUIET ECHO { This is a
-          message.}.
-
-   IF READABLE name
-          Succeeds if name is the name of an existing file or directory
-          that is readable.
-
-   IF WRITEABLE name
-          Succeeds if name is the name of an existing file or directory
-          that is writeable, e.g.:
-
-  if not writeable \v(lockdir) echo Please read installation instructions!
-
-   IF FLAG command
-          This tests a user-settable condition, which can mean anything
-          you like. SET FLAG ON causes subsequent IF FLAG commands to
-          succeed; SET FLAG OFF causes them to fail. One way to use it
-          would be for debugging your scripts; precede any debugging
-          statements with IF FLAG. Then SET FLAG on to debug your script,
-          SET FLAG OFF to run it without debugging. Another common use is
-          for causing an inner loop to cause an outer loop to exit.
-
-   IF C-KERMIT command
-          C-Kermit, but not Kermit 95 or MS-DOS Kermit, executes the
-          command.
-
-   IF K-95 command
-          Kermit 95, but not C-Kermit or MS-DOS Kermit, executes the
-          command.
-
-   IF MS-KERMIT command
-          MS-DOS Kermit, but not C-Kermit or Kermit 95, executes the
-          command.
-     _________________________________________________________________
-
-  7.5. Using More than Ten Macro Arguments
-
-   The \v(argc) variable now gives the actual number of arguments, even
-   if the number is greater than 9:
-
-  C-Kermit> define xx echo \v(argc)
-  C-Kermit> xx a b c d e f g h i j k l m n o p q r s t u v w x y z
-  27
-
-   Remember that \v(argc) includes the name of the macro itself, so it is
-   always at least 1, and is always 1 greater than the actual number of
-   arguments. As in versions 6.0 and earlier, if more than 9 arguments
-   are given, only the first nine are assigned to the variables \%1..\%9.
-
-   The \&_[] array, discussed on page 353 of [585]Using C-Kermit, 2nd ed,
-   now holds all the arguments, up to some implementation-dependent limit
-   (64 or greater), rather than only the first 9. To illustrate: the
-   following macro tells the number of arguments it was called with and
-   then prints them:
-
-  define show_all_args {
-      local \%i
-      echo \&_[0] - Number of arguments: \feval(\v(argc)-1)
-      for \%i 1 \v(argc)-1 1 { echo \flpad(\%i,3). "\&_[\%i]" }
-  }
-
-   Within a macro \&_[0], like \%0, contains the name of the macro.
-
-   At top level, the \&_[] array is filled as follows:
-
-     * If the first argument on the C-Kermit command line was a filename,
-       or C-Kermit was invoked from a "Kerbang" script ([586]Section
-       7.19), element 0 contains the filename, and elements 1 through
-       \v(argc)-1 hold the remaining command-line arguments.
-     * Otherwise the program name goes in element 0, and elements 1
-       through \v(argc)-1 hold any arguments that were included after
-       "--" or "="
-
-   The new \%* variable, when used within a macro, is replaced by the
-   text that followed the macro name in the macro invocation. If no
-   arguments were given, \%* is replaced by the empty string. Examples:
-
-  C-Kermit> define xx echo [\%*]
-  C-Kermit> define \%a oofa
-  C-Kermit> xx
-  []
-  C-Kermit> xx \%a
-  [oofa]
-  C-Kermit> xx a
-  [a]
-  C-Kermit> xx a b
-  [a b]
-  C-Kermit> xx a b c
-  [a b c]
-  C-Kermit> xx a b c d e f g h i j k l m n o p q r s t u v w x y z
-  [a b c d e f g h i j k l m n o p q r s t u v w x y z]
-
-   Note that \%* can not be used at top level, since Kermit does not have
-   access to the raw command line (only to its elements separately, after
-   they have been processed by the shell and the C library).
-
-   C-Kermit 7.0 also adds a SHIFT command:
-
-   SHIFT [ number ]
-          Shifts the macro arguments (except argument 0) the given number
-          of places to the left and adjusts \v(argc) accordingly. The
-          default number is 1.
-
-   To illustrate, suppose macro XXX is invoked as follows:
-
-  xxx arg1 arg2 arg3
-
-   Then inside XXX, \%1 is "arg1", \%2 is "arg2", and \%3 is "arg3".
-   After a SHIFT command is given inside XXX, then \%1 is "arg2", \%2 is
-   "arg3", and \%3 is empty. \%0 (the name of the macro) remains
-   unchanged.
-
-   If more than 9 arguments were given, then arguments are shifted into
-   the \%1..9 variables from the argument vector array.
-
-   At top level, the SHIFT command operates on the \&_[] array and \%1..9
-   variables; the \&@[] array is not affected. See [587]Section 7.16 for
-   details.
-
-   The \%* variable is not affected by the SHIFT command.
-     _________________________________________________________________
-
-  7.6. Clarification of Function Call Syntax
-
-   Spaces are normally stripped from the front and back of each function
-   argument; to prevent this enclose the argument in braces:
-
-  \fsplit(\%a,&a,{ })
-
-   However, function calls that contain spaces can make trouble when the
-   function is to be used in a "word" field, since space separates words.
-   For example:
-
-  for \%i 1 \fsplit(\%a,&a,{ }) 1 {
-    echo \%i. "\&a[\%i]"
-  }
-
-   In most cases, the trouble can be averted by enclosing the function
-   reference in braces:
-
-  for \%i 1 {\fsplit(\%a,&a,{ })} 1 {
-    echo \%i. "\&a[\%i]"
-  }
-
-   or by replacing spaces with \32 (the ASCII code for space):
-
-  for \%i 1 \fsplit(\%a,&a,\32) 1 {
-    echo \%i. "\&a[\%i]"
-  }
-
-   Braces are also used in function calls to indicate grouping. For
-   example:
-
-  \fsubstring(abcd,2,2) = "bc"
-
-   But suppose "abcd" needed to contain a comma:
-
-  \fsubstring(ab,cd,2,2)
-
-   This would cause an error, since "cd" appears to be the second
-   argument, when really you want the first "2" to be the second
-   argument. Braces to the rescue:
-
-  \fsubstring({ab,cd},2,2) = "b,"
-
-   Similarly, leading and trailing spaces are stripped from each
-   argument, so:
-
-  \fsubstring( abcd ,2,2) = "bc"
-
-   but braces preserve them:
-
-  \fsubstring({ abcd },2,2) = "ab"
-
-   Given these special uses for braces, there is no way to pass literal
-   braces to the function itself. For example:
-
-  \fsubstring(ab{cd,2,2)
-
-   causes an error.
-
-   So if you need a function to include braces, define a variable
-   containing the string that has braces. Example:
-
-  define \%a ab{cd
-  \fsubstring(\%a,2,2) = "b{"
-
-   If the string is to start with a leading brace and end with a closing
-   brace, then double braces must appear around the string (which itself
-   is enclosed in braces):
-
-  define \%a {{{foo}}}
-  \fsubstring(\%a) = "{foo}"
-
-   This also works for any other kind of string:
-
-  define \%a {{ab{cd}}
-  echo \fsubstring(\%a) = "ab{cd"
-     _________________________________________________________________
-
-  7.7. Autodownload during INPUT Command Execution
-
-   As of 6.1 / 1.1.12, C-Kermit can be told to look for incoming Kermit
-   (or Zmodem) packets during execution of an INPUT command. By default
-   (for consistency with earlier releases), this is not done. You can
-   enable this feature with:
-
-  SET INPUT AUTODOWNLOAD ON
-
-   (and disable it again with OFF.)
-
-   One possible use for this feature is as a server mode with a time
-   limit:
-
-  INPUT 3600 secret-string-to-end-the-INPUT-command
-
-   In this example, any GET, SEND, or REMOTE commands received within one
-   hour (3600 seconds) of when the INPUT command was issued will be
-   executed. Here's another example, in which we want to stay open until
-   11:30pm, or until interrupted by seven consecutive Ctrl-C (\3)
-   characters:
-
-  INPUT 23:30:00 \3\3\3\3\3\3\3
-
-   The INPUT AUTODOWNLOAD setting is displayed by SHOW SCRIPTS or SHOW
-   INPUT.
-     _________________________________________________________________
-
-  7.8. Built-in Help for Functions.
-
-   Beginning in C-Kermit 7.0, you may obtain a description of the calling
-   conventions and return values of any built-in function, such as
-   \fsubstring(), with the new HELP FUNCTION command; give the function's
-   name without the leading "\f", e.g. "help func substring". You can use
-   ?, completion, and abbreviation in the normal manner.
-     _________________________________________________________________
-
-  7.9. Variable Assignments
-
-    7.9.1. Assignment Operators
-
-   Programmers accustomed to languages such as C or Fortran might find
-   Kermit's method of assigning values to variables unnatural or awkward.
-   Beginning in C-Kermit 7.0, you can use the following alternative
-   notation:
-
- .name = value    is equivalent to   DEFINE name value
- .name := value   is equivalent to   ASSIGN name value
- .name ::= value  is equivalent to   ASSIGN name \feval(value)
-
-   When the command begins with a period (.), this indicates an
-   assignment. The name can be a macro name, a \%{digit,letter} variable,
-   or an array element. There can be space(s) between "." and the name.
-   Examples:
-
-  .\%a = This is a string  ; Same as "define \%a This is a string"
-  echo \%a
-  This is a string
-
-  .xxx = \%a               ; Same as "define xxx \%a"
-  echo \m(xxx)
-  \%a
-
-  .xxx := \%a              ; Same as "assign xxx \%a"
-  echo \m(xxx)
-  This is a string
-
-  declare \&a[2]           ; Use with arrays...
-  define \%i 2
-  .\&a[1] = first
-  .\&a[\%i] = second
-
-   The following sequence illustrates the differences among three levels
-   of evaluation:
-
-  .\%x = 2          ; Define a variable to have a numeric value
-  .\%y = (3 + \%x)  ; Define another variable as an arithmetic expression
-
-  .xxx = 4 * \%y    ; "=" simply copies the right-hand side.
-  echo \m(xxx)
-  4 * \%y
-
-  .xxx := 4 * \%y   ; ":=" evaluates the variables first, then copies.
-  echo \m(xxx)
-  4 * (3 + 2)
-
-  .xxx ::= 4 * \%y  ; "::=" evaluates the expression, then copies.
-  echo \m(xxx)
-  20
-
-   You can also use this syntax to clear (undefine) a variable:
-
-  .\%a = oofa       ; Define the variable
-  echo "\%a"
-  "oofa"
-  .\%a              ; Clear the variable
-  echo "\%a"
-  ""
-
-   Extra credit: Can you guess what happens below when the file "abc"
-   does not exist?
-
-  fopen /read \%c abc
-  if fail ...
-     _________________________________________________________________
-
-    7.9.2. New Assignment Commands
-
-   Recall the DEFINE and ASSIGN commands, and their hidden counterparts,
-   _DEFINE and _ASSIGN. The former take the variable name literally, the
-   latter evaluate the variable-name field to form the variable name
-   dynamically. Examples:
-
-  DEFINE \%x foo    ; Sets the value of the variable \%x to "foo".
-  DEFINE \%a \%x    ; Sets the value of the variable \%a to "\%x".
-  _DEFINE x_\%a \%x ; Sets the value of the variable x_foo to "\%x".
-  ASSIGN \%a \%x    ; Sets the value of the variable \%a to the "foo".
-  _ASSIGN x_\%a \%x ; Sets the value of the variable x_foo to "foo".
-
-   This concept has been carried over to the remaining
-   variable-assignment commands: EVALUATE, INCREMENT, and DECREMENT:
-
-   EVALUATE variablename expression
-          Evaluates the arithmetic expression and assigns its value to
-          the variable whose name is given. Example: "eval \%a 1+1"
-          assigns "2" to \%a.
-
-   _EVALUATE metaname expression
-          Evaluates the arithmetic expression and assigns its value to
-          the variable whose name is computed from the given metaname.
-          Example: "eval foo<\%a>::\%1 \%2 * (\%3 + \%4)" assigns the
-          value of "\%2 * (\%3 + \%4)" to the variable whose name is
-          computed from "foo<\%a>::\%1".
-
-   INCREMENT variablename [ expression ]
-          Evaluates the arithmetic expression and adds its value to the
-          value of the variable whose name is given. Example: "increment
-          \%a".
-
-   _INCREMENT metaname [ expression ]
-          Evaluates the arithmetic expression and adds its value to the
-          value of the variable whose name is computed from the given
-          metaname. Example: "_increment Words::\%1.count[\%2]".
-
-   DECREMENT variablename [ expression ]
-          Evaluates the arithmetic expression and subtracts its value
-          from the value of the variable whose name is given.
-
-   _DECREMENT metaname [ expression ]
-          Evaluates the arithmetic expression and subtracts its value
-          from the value of the variable whose name is computed from the
-          given metaname.
-
-   WARNING: The syntax of the EVALUATE command has changed since C-Kermit
-   6.0 and K95 1.1.17. Previously, it did not include a variable name,
-   only an expression. To restore the old behavior, use SET EVALUATE OLD.
-   To return to the new behavior after restoring the old behavior, use
-   SET EVALUATE NEW.
-
-   NOTE: There are no analogs to the "_" commands for the operators
-   described in [588]Section 7.9.1; those operators can not be used to
-   assign values to variables whose names must be computed.
-     _________________________________________________________________
-
-  7.10. Arrays
-
-   C-Kermit 7.0 adds lots of new array-related features, and groups them
-   together under the NEW ARRAY command:
-
-   ARRAY { CLEAR, COPY, DECLARE, DESTROY, RESIZE, SHOW, SORT }
-
-   In each of the ARRAY commands, wherever an array name is expected,
-   "short forms" may be used. For example, all of the following are
-   acceptable:
-
-  array show \&a[]  (or SHOW ARRAY...)
-  array show &a[]
-  array show a[]
-  array show &a
-  array show a
-
-   In addition, ranges are accepted in the ARRAY COPY, ARRAY CLEAR, ARRAY
-   SET, ARRAY SHOW, and ARRAY SORT commands:
-
-  array clear \&a[16]     ; Clears 16 thru end
-  array clear &a[16]      ; Ditto
-  array clear a[16]       ; Ditto
-
-  array clear \&a[16:32]  ; Clears 16 thru 32
-  array clear &a[16:32]   ; Ditto
-  array clear a[16:32]    ; Ditto
-
-   When using array names as function arguments, you must omit the "\"
-   and you must include the "&". You may optionally include empty
-   brackets. Examples:
-
-  \fsplit(\%a,a)          ; Bad
-  \fsplit(\%a,\&a)        ; Bad
-  \fsplit(\%a,&a[3])      ; Bad
-
-  \fsplit(\%a,&a)         ; Good
-  \fsplit(\%a,&a[])       ; Good
-     _________________________________________________________________
-
-    7.10.1. Array Initializers
-
-   Beginning in C-Kermit 7.0, you may initialize an array -- in whole or
-   in part -- in its declaration:
-
-   [ ARRAY ] DECLARE array-name[size] [ = ] [ value1 [ value2 [...] ] ]
-
-   For compatibility with versions 5A and 6.0, the ARRAY keyword is
-   optional. DECLARE can also be spelled DCL.
-
-   Initializers are (a) optional, (b) start with element 1, (c) must be
-   enclosed in braces if they contain spaces, and (d) are evaluated
-   according to normal rules by the DECLARE command prior to assignment.
-   Thus the assignments made here are the same as those made by the
-   ASSIGN command. This allows you to initialize array elements from the
-   values of other variables. If you actually want to initialize an array
-   element to variable's name, as opposed to its value, use double
-   backslashes (as in "\\&a", "\\v(time)", etc).
-
-   The size (dimension) of the array is optional. If the size is omitted,
-   as in "\&a[]", then the array sizes itself to the number of
-   initializers; if there are no initializers the array is not declared
-   or, if it was declared previously, it is destroyed. If a size is
-   given, any extra elements in the initialization list are discarded and
-   ignored.
-
-   NOTE: Unlike in C, the list of initializers is NOT enclosed in braces.
-   Instead, braces are used to group multiple words together. So:
-
-  ARRAY DECLARE \&a[] = { one two three }
-
-   would create an array with two elements (0 and 1), with element 1
-   having the value " one two three ".
-
-   Examples:
-
-   ARRAY DECLARE \&a[16]
-          Declares the array \&a with 17 elements (0 through 16), in
-          which all elements are initially empty. If the array \&a[]
-          existed before, the earlier copy is destroyed.
-
-   ARRAY DECLARE &a[16]
-   ARRAY DECLARE a[16]
-   ARRAY DCL \&a[16]
-   ARRAY DCL &a[16]
-   ARRAY DCL a[16]
-   DECLARE \&a[16]
-   DECLARE &a[16]
-   DECLARE a[16]
-   DCL \&a[16]
-   DCL &a[16]
-   DCL a[16]
-          All of the above are the same as the first example.
-
-   ARRAY DECLARE \&a[16] = alpha beta {gamma delta}
-          Declares the array \&a with 17 elements (0 through 16),
-          initializing \&a[1] to "alpha", \&a[2] to "beta", and \&a[3] to
-          "gamma delta". The remaining elements are empty.
-
-   ARRAY DECLARE \&a[] = alpha beta {gamma delta}
-          Same as the previous example, but the array is automatically
-          dimensioned to 3.
-
-   ARRAY DECLARE \&a[3] = alpha beta {gamma delta} epsilon zeta
-          Too many initializers; only the first three are kept.
-
-   ARRAY DECLARE \&a[0]
-   ARRAY DECLARE \&a[]
-   ARRAY DECLARE &a[]
-   ARRAY DECLARE &a
-   ARRAY DECLARE a
-   DECLARE \&[0]
-   DECLARE a
-   DCL a
-          All of these are equivalent. Each destroys \&a[] if it exists.
-          Declaring an array with a dimension of 0 is the same as ARRAY
-          DESTROY arrayname.
-
-   ARRAY DECLARE \&a[] = \%1 \%2 \%3
-          Declares the array \&a with 3 elements (0 through 3),
-          initializing \&a[1] to the value of \%1, \&a[2] to the value of
-          \%2, and \&a[3] to the value of \%3. In this case, any
-          reference to one of these array elements is replaced by the
-          value of the corresponding \%n variable at the time the
-          declaration was executed (immediate evaluation; the array
-          element's value does not change if the initializer variable's
-          value changes).
-
-   ARRAY DECLARE \&a[] = \\%1 \\%2 \\%3
-          Declares the array \&a with 3 elements (0 through 3),
-          initializing \&a[1] to the string "\%1", \&a[2] to "\%2", and
-          \&a[3] to "\%3". In this case any reference to one of these
-          array elements is replaced by the CURRENT value of the
-          corresponding \%n variable (deferred evaluation -- the array
-          element's value follows the value of the initializer variable).
-
-   The equal sign (=) preceding the initializer list is optional, but is
-   recommended for clarity. If you need to initialize element 1 to a
-   literal equal sign, use two of them, separated by a space, as in this
-   example:
-
-  ARRAY DECLARE \&a[] = = + - * /
-
-   Remember, element 0 is not initialized by the DECLARE command. To
-   initialize element 0, use a regular DEFINE or ASSIGN command:
-
-  ARRAY DECLARE \&a[] one two three four five six seven eight nine
-  DEFINE \&a[0] zero
-
-   Finally, remember that every command level has its own local array,
-   \&_[], containing all the macro arguments (\%0, \%1, ...) for that
-   level. See [589]Section 7.5 for details.
-     _________________________________________________________________
-
-    7.10.2. Turning a String into an Array of Words
-
-   The \fsplit(s1,&a,s2,s3) function assigns the words of string s1 to
-   successive elements of the array (beginning with element 1) whose
-   identifying letter, a-z, is given after the "&" in the second
-   argument, using break and include characters given in s2 and s3. See
-   [590]Section 7.3 for details.
-     _________________________________________________________________
-
-    7.10.3. Arrays of Filenames
-
-   See [591]Section 4.11.3 for news about how \ffiles() and related
-   functions can assign a list of filenames to an array. To recapitulate
-   briefly here:
-
-  \ffiles(*,&a)
-
-   assigns all files that match the first argument to the array denoted
-   by the second argument. If the array has not been declared, it is
-   declared automatically, with exactly the number of elements needed to
-   hold the file list; if it was previously declared, it is destroyed and
-   reused. The filenames are assigned starting at array element 1.
-   Element 0 holds the number of files in the list.
-
-   The DIRECTORY command ([592]Section 4.5.1) can also create filename
-   arrays if you give it the /ARRAY: switch; this allows selection
-   criteria beyond whether the filename matches the given pattern.
-
-   All functions and commands that create filename arrays store the
-   number of filenames, n, as element 0 of the array, and the filenames
-   as elements 1 through n.
-     _________________________________________________________________
-
-    7.10.4. Automatic Arrays
-
-   In a command file or macro, you can now have local (automatic) arrays.
-   Just give the name followed by empty subscript brackets (no spaces
-   inside the brackets please) in a LOCAL command, and then declare the
-   array:
-
-  LOCAL \%a \&a[] oofa
-  ARRAY DECLARE \&a[32] = value1 value2 value3 ...
-
-   This declares the scalar variable \%a, the array \&a[], and the macro
-   name "oofa" to be local, and then declares the new local copy of \&a[]
-   with 32 elements, perhaps assigning some initial values. When C-Kermit
-   exits from the command file or macro containing these command, the
-   previous \&a[] array is restored (and if there was no \&a[] at any
-   higher level, this will still be true). The process can be repeated to
-   any level. Thus it is now safe to write scripts or macros containing
-   arrays without danger of interfering with global arrays of the same
-   name.
-
-   Just as scalars are inherited by lower command levels, so are arrays.
-   So, for example, if \&a[] is declared at top level, all lower levels
-   will see it unless they include a "local \&a[]" statement, in which
-   case all levels at and beneath the level where the LOCAL statement was
-   executed will see the local copy. This too can be repeated to any
-   level.
-
-   On the other hand, if you DECLARE an array at a lower command level
-   without also making it LOCAL, this replaces the copy that was declared
-   at the lowest command level above this one.
-     _________________________________________________________________
-
-    7.10.5. Sorting Arrays
-
-   Although arrays can be sorted using FOR loops as shown on page 383 of
-   Using C-Kermit, 2nd Ed., this involves quite a bit of repetitive
-   interpretation by the command parser, and so can be slow for large
-   arrays. For this reason, C-Kermit 7.0 adds a built-in SORT command:
-
-   ARRAY SORT [ switches ] array [ array2 ]
-          Sorts the given array in place. Sorting is strictly lexical
-          (string based). The array name can be given fully, e.g.
-          "\&a[]", or the "\" and/or "&" and/or brackets can be omitted,
-          e.g. "array sort \&a[]", "sort &a", "sort a". Also, a range can
-          be indicated in the brackets as noted in [593]Section 7.10, to
-          restrict the sort to a range of elements (equivalent to the
-          /RANGE switch, described just below), e.g. "array sort
-          &a[20:30]".
-
-   A second array may be specified. If it is, and if it is at least as
-   big as the first array, it is sorted according to the first array. For
-   a sample application, see [594]Section 7.10.10.
-
-   See [595]Section 1.5 for an explanation of switches. The optional
-   switches are:
-
-   /CASE:{ON,OFF}
-          /CASE:ON means that alphabetic case is significant in
-          comparisons; uppercase letters are sorted before lowercase
-          ones. /CASE:OFF means case is ignored, e.g. "A" is the same as
-          "a". If this switch is not given, sorting is according the
-          current SET CASE setting.
-
-   /KEY:n
-          Comparison begins at position n(1-based) in each string. If no
-          key is given, the entire strings are compared. Only one key can
-          be given. If an array element is shorter than the key value, n,
-          that element is considered empty for comparison purposes, and
-          therefore lexically less than any element at least ncharacters
-          long.
-
-   /NUMERIC
-          If this switch is included, it means sorting should be numeric,
-          rather than lexical. The sort key is the string starting at the
-          key position, skipping any leading blanks or tabs, and then as
-          much of the string from that point on that fits the definition
-          of "numeric", terminating at the first character that does not
-          qualify. A numeric string has an optional sign (+ or -)
-          followed by one or more digits, and (if your version of Kermit
-          was built with floating-point support; see [596]Section 7.23 )
-          zero or one decimal point (period). If both /CASE and /NUMERIC
-          are given, /NUMERIC takes precedence.
-
-   /RANGE:n[:m]
-          Sort elements nthrough m of the array. By default, the entire
-          array from element 1 to its dimensioned size is sorted, which
-          might produce surprising results if the array is not full; see
-          example in [597]Section 7.10.7. If ":m" is omitted from the
-          range, the dimensioned size is used. Thus, to sort an entire
-          array, \&a[], including its 0th element, use "sort /range:0
-          &a". You can also sort any desired section of an array, e.g.
-          "sort /range:10:20 &a" or "sort /range:\%i:\%j-1 &b". As noted
-          above, you can also specify a range in the array-name brackets.
-          If you specify a range in the array-name brackets AND with a
-          /RANGE switch, the ones in the brackets take precedence.
-
-   /REVERSE
-          Sort in reverse order. If this switch is not given, the array
-          is sorted in ascending order.
-
-   Remember that numeric switch arguments can be numbers, arithmetic
-   expressions, or variables whose values are numbers or expressions, as
-   illustrated in the /RANGE examples above.
-
-   A typical sorting application might be to list students' test scores
-   in descending order. Suppose you had the following records:
-
-  olaf      65
-  olga      98
-  ivan      83
-  xena     100
-
-   (and so on) stored in array \&s[] (e.g. by reading them from a file as
-   illustrated in [598]section 7.10.7). In these records, the student's
-   name is in columns 1-9 and the score in 10-12. So to rearrange the
-   list in descending order of score:
-
-  sort /key:10 /reverse &s
-
-   Then to list your top five students:
-
-  for \%i 1 5 1 { echo \&s[\%i] }
-
-   Or more simply (see next section):
-
-  show array a[1:5]
-
-   To illustrate the difference between a lexical and a numeric sort,
-   suppose you have the following records (the lines that are numbered,
-   starting at column 1) in array \&a[]:
-
-    Column   1         2
-    12345678901234567890
-
-   1. Ivan 10.0 2. Olaf 9.95 3. Olga 101.5
-
-   ARRAY SORT /KEY:10 &a[] would order them 3,1,2, but ARRAY SORT /KEY:10
-   /NUMERIC &a[] would order them 2,1,3.
-     _________________________________________________________________
-
-    7.10.6. Displaying Arrays
-
-   The SHOW ARRAY command (or ARRAY SHOW) now accepts an optional
-   array-name argument:
-
-  SHOW ARRAY \&a[]
-
-   (you can leave off the \, the \&, and/or the []'s if you like; "show
-   array a" is equivalent to "show array \&a[]"). When an array is
-   specified, its dimension is shown and all defined (non-empty) elements
-   are listed.
-
-   Example:
-
-  assign \%n \ffiles(*,&a)  ; Fill an array with filenames ([599]Section 4.11.3
-)
-  show array \&a[]          ; Show the array we just read
-  array show \&a[]          ; Same as previous
-  array sort \&a[]          ; Sort the array
-  array show \&a[]          ; Show it after sorting
-  array show \&a            ; Show it again
-  array show &a             ; Show it again
-  array show a              ; Show it again
-
-   (The final four commands demonstrate the alternative forms that are
-   accepted for the array name.)
-
-   If you SHOW ARRAY without giving an array name, all defined arrays are
-   listed by name and dimension, but their contents are not shown.
-
-   You can also show a piece of an array by including a subscript or
-   range within the array brackets:
-
-  array show \&a[5]         ; Shows \&a[5]
-  array show &a[3:8]        ; Shows \&a[3] through \&a[8]
-  array show a[:\%n-1]      ; Shows \&a[0] through \&a[\%n-1]
-     _________________________________________________________________
-
-    7.10.7. Other Array Operations
-
-   ARRAY DESTROY arrayname
-          Destroys and undeclares the named array. Subscripts or ranges
-          are not accepted in this command.
-
-   ARRAY COPY array1 array2
-          Copies the first array to the second array. If the target array
-          has not been declared, it is created automatically with the
-          same size as the first. If it has been declared, it will be
-          used as declared; if the source array is larger, only as much
-          of it as will fit is copied to the target array. Syntax for
-          array1 and array2 is as in ARRAY SHOW (SHOW ARRAY). Example:
-
-  .\%n := \ffiles(*,&a)  ; Create and load array A with a file list.
-  array copy &a &b       ; Copy array A to array B.
-
-          The ARRAY COPY command also lets you copy pieces of arrays by
-          including range specifiers, as in these examples:
-
-        ARRAY COPY \&a[4:27] \&b
-                This copies \&a[] elements 4-27 to \&b[] elements 1-23,
-                creating \&b[] if necessary or, if \&b[] is already
-                declared, stopping early if its size is less than 23.
-
-        ARRAY COPY \&a[4:27] \&b[12]
-                This copies \&a[] elements 4-27 to \&b[] elements 12-35,
-                creating \&b[] if necessary or, if \&b[] is already
-                declared, stopping early if its size is less than 35.
-
-        ARRAY COPY \&a[4:27] \&b[12:14]
-                This copies \&a[] elements 4-6 to \&b[] elements 12-14,
-                creating \&b[] if necessary or, if \&b[] is already
-                declared, stopping early if its size is less than 14.
-
-        ARRAY COPY \&a[17] \&b
-                This copies all the elements of \&a[] starting with 17
-                until the last to \&b[], creating \&b[] if necessary or,
-                if \&b[] is already declared, stopping early if \&b[] is
-                not big enough.
-
-   ARRAY CLEAR arrayname
-          Sets all the elements of the array to the empty value. You may
-          also include a range specifier to clear only a selected portion
-          of the array; for example "array clear \&a[37:214]". If the
-          range is out of bounds, only the part of the array that is in
-          bounds is cleared.
-
-   ARRAY SET arrayname [ value ]
-          Sets all the elements of the array to the given value. If no
-          value is given, the array is cleared. You may also include a
-          range specifier to set only a selected portion of the array;
-          for example "array set \&a[1:9] -1". If the range is out of
-          bounds, only the part of the array that is in bounds is set.
-
-   ARRAY RESIZE arrayname size
-          Resizes the given array. If the size is greater than the
-          array's current dimension, new empty elements are added to the
-          end. If the size is less than the current dimension, the extra
-          elements are discarded. Note: If you have stored the array size
-          in element 0, ARRAY RESIZE does not change this value.
-          Alternative notation: ARRAY RESIZE arrayname[size]. For a
-          practical example, see [600]Section 7.10.11.
-
-   \farraylook(pattern,arrayname)
-          This function returns the index of the first element of the
-          given array that matches the given pattern (for details about
-          pattern syntax, see [601]section 4.9). The array name can
-          include a range specification to restrict the search to a given
-          segment of the array. If no elements match the pattern, -1 is
-          returned.
-
-   \ftablelook(keyword,arrayname[,delimiter])
-          Looks in the given "table", which must be sorted, for the given
-          keyword. The keyword need not be spelled out in full.
-          Pattern-matching characters should not be included as part of
-          the keyword. The function returns the index of the table
-          element that uniquely matches the given keyword, or -1 if none
-          match, or -2 if more than 1 match.
-
-   A "table" is an array that is sorted in lexical order; each of its
-   elements may contain multiple fields, delimited by the given delimiter
-   character or, if no delimiter is specified, a colon (:).
-
-   The \farraylook() function does exactly what you tell it. If you give
-   it a pattern that does not include wildcard characters (such as *, ?,
-   etc), it requires an exact match. For example:
-
-  \farraylook(oofa,&a)
-
-   searches for the first element of \&a[] whose value is "oofa". But:
-
-  \farraylook(oofa*,&a)
-
-   finds the first element whose value starts with "oofa", and;
-
-  \farraylook(*oofa,&a)
-
-   finds the first element whose value ends with "oofa", and;
-
-  \farraylook(*oofa*,&a)
-
-   finds the first element whose value contains "oofa".
-
-   Here's a simple demonstration of looking up patterns in arrays:
-
-  local \&a[] \%x \%n
-  declare \&a[] = zero one two three four five six seven eight nine ten
-  while true {
-      .\%x = 1
-      .\%n = 0
-      ask \%a { Pattern? }
-      if not def \%a exit 0 Done.
-      while <= \%x \fdim(&a) {
-          .\%x := \farraylook(\%a,&a[\%x])
-          if ( < \%x 0 ) break
-          echo \flpad(\%x,3). \&a[\%x]
-          increment \%x
-          increment \%n
-      }
-      if ( < \%n 1 ) echo Pattern not found - "\%a"
-  }
-
-   The array need not be sorted. When a pattern is given, a search is
-   performed; if there is a match, the matching element's index and the
-   element itself are printed, and the search begins again at the next
-   element. Thus each matching element is printed. If none match, the
-   "Pattern not found" message is printed. The process repeats for as
-   many patterns as the user wants to type, and terminates when the user
-   types an empty pattern.
-
-   Now let's build a little command parser, consisting of a keyword
-   table, and a loop to look up the user's commands in it with
-   \ftablelook(). In this case the array elements have "fields" separated
-   by colon (:) -- a keyword and a value. Keyword tables must be sorted
-   if \tablelook() is to work right, so after declaring and initializing
-   the table array, we sort it.
-
-  local \&k[] \%a \%i \%n
-
-  array declare \&k[] = drive:9 do:8 discuss:7 live:6 spend:5 help:4 quit:0
-
-  array sort &k                             ; Make sure array is sorted
-  echo Type "help" for help.                ; Print greeting & instructions
-
-  while true {                              ; Loop to get commands
-      undefine \%a
-      while not defined \%a {               ; Get a command
-          ask \%a { Command? }
-      }
-      .\%n := \ftablelook(\%a,&k)           ; Look up the command
-      switch \%n {                          ; Handle errors
-        :-1, echo Not found - "\%a"         ; Doesn't match
-             continue
-        :-2, echo Ambiguous - "\%a"         ; Matches too many
-             continue
-      }
-      switch \fword(\&k[\%n],2) {           ; Dispatch according to value
-         :9, echo Driving..., break
-         :8, echo Doing..., break
-         :7, echo Discussing..., break
-         :6, echo Living..., break
-         :5, echo Spending..., break
-         :4, echo { Commands (may be abbreviated):}
-             for \%i 1 \fdim(&k) 1 {
-                echo {  \%i. \fword(\&k[\%i],1) }
-             }
-             break
-         :0, exit 0 Bye!
-         :default, stop 1 Internal error
-      }
-  }
-
-   In this example, keywords are "drive", "do", "discuss", etc, and their
-   values are unique numbers (values need not be numbers, and there need
-   not be only one value -- there can be 0, 1, 2, or more of them). The
-   user types a command, which can be the whole word (like "help") or any
-   abbreviation (like "hel", "he", or just "h"). If this does not match
-   any keywords, \ftablelook() returns -1; if it matches more than one
-   (as would "d"), it returns -2. Otherwise the array index is returned,
-   1 or higher.
-
-   Given the array index \%n, we can get the table values as follows:
-
-  \fword(\&k[\%n],1) is the keyword (first field)
-  \fword(\&k[\%n],2) is the value (second field, in this case a number)
-
-   In our example, we use the value (number) as the SWITCH variable. As
-   noted, \fablelook() expects the array elements to contain multiple
-   fields separated by colon (:) (or other character that you specify,
-   e.g. \ftablelook(\%a,&a,^)) and when matching the keyword, ignores the
-   first delimiter and everything after it.
-     _________________________________________________________________
-
-    7.10.8. Hints for Using Arrays
-
-   C programmers are accustomed to out-of-bounds array references causing
-   core dumps or worse. In C-Kermit:
-
-     * A reference to an an out-of-bounds array element returns the empty
-       string.
-     * An attempt to set the value of an array element that is out of
-       bounds or that has not been declared simply fails.
-
-   C programmers expect an array of size nto have elements 0 through n-1.
-   Fortran programmers expect the same array to have elements 1 through
-   n. C-Kermit accommodates both styles; when you declare an array of
-   size n, it has n=1 elements, 0 through n, and you can use the array in
-   your accustomed manner, 0-based or 1-based.
-
-   However, note that C-Kermit has certain biases towards 1-based arrays:
-
-     * Assignment of file lists starts with element 1 ([602]Section
-       7.10.3).
-     * Assignment by \fsplit() starts with element 1 ([603]Section 7.3).
-     * Array initialization skips the 0th element. To initialize a
-       0-based array, use something like this:
-  declare \&a[3] = one two three
-  .\&a[0] = zero
-     * The ARRAY SORT command skips the 0th element unless you include
-       /RANGE:0
-     * The SHIFT command ignores element 0 of the \&_[] array.
-
-   The distinction between an array's dimensioned size and the number of
-   elements in the array is important when sorting. To illustrate:
-
-  declare \&a[100]                  ; Declare array &a with 100 elements
-  fopen /read \%c oofa.txt          ; Open a file
-  if fail...
-  for \%i 1 \fdim(&a) 1 {           ; Read the file into the array
-      fread \%c \&a[\%i]
-      if fail break
-  }
-  fclose \%c
-  if > \%i \fdim(&a) end 1 File has too many lines for array.
-  .\%n ::= \%i - 1
-  echo File has \%n line(s).
-
-   Let's say the file had 95 lines. This leaves elements 96-100 of the
-   array empty. Now suppose you sort the array and write out the result:
-
-  sort &a                           ; Sort the whole array
-  fopen /write \%o oofa.txt.sorted  ; Open an output file
-  if fail ...
-  for \%i 1 \%n 1 {                 ; Write out 95 records
-      fwrite /line \%o \&a[\%i]
-      if fail end 1 Write error
-  }
-  close write
-
-   You might be surprised at the contents of "oofa.txt.sorted" -- five
-   empty elements, 96-100, floated to the top of the array in the sort,
-   and since your write loop only had 95 iterations, the final 5 lines of
-   the sorted file are lost.
-
-   Therefore, when dealing with partially filled arrays -- especially
-   when sorting them -- remember to specify the number of elements. A
-   handy way of recording an array's "true" size is to put it in the 0th
-   element. That way, it "travels with the array". To illustrate
-   (continuing the previous example at the "close read" statement):
-
-  close read
-  if > \%i \fdim(&a) end 1 File has too many lines for array.
-  .\&a[0] ::= \%i - 1     ; Assign number of lines to \&a[0].
-  echo File has \&a[0] line(s).
-  sort /range:1:\&a[0] &a
-  open write oofa.txt.sorted
-  if fail ...
-  for \%i 1 \&a[0] 1 {
-      writeln file \&a[\%j]
-      if fail end 1 Write error
-  }
-  close write
-
-   Note the SORT switch, /RANGE:1:\&a[0]. This keeps the sort 1-based,
-   and uses element 0 of the array as its size indicator.
-
-   Finally, note that even though some commands or functions might put a
-   size in array element 0, no built-in functions or commands depend on a
-   size actually being there. Thus you are perfectly free to replace the
-   size with something else and treat the array as 0-based.
-     _________________________________________________________________
-
-    7.10.9. Do-It-Yourself Arrays
-
-   Kermit's \&x[] arrays are nice because of the accompanying built-in
-   functionality -- ARRAY commands, built-in functions that load and
-   search arrays, automatic evaluation of arithmetic expressions within
-   the subscript brackets, and so on. Yet they also have certain
-   limitations:
-
-    1. Except when created by dynamic loading (e.g. by \ffiles()) they
-       must be declared and dimensioned in advance.
-    2. Indices must be numeric, positive, and in range.
-    3. There can be only one dimension. Matrices or other
-       higher-dimensioned arrays are not available.
-
-   But none of this is to say you can't invent any kind of data structure
-   you like. In [604]Section 7.9.2 you can see some examples. Here's
-   another (courtesy of Dat Thuc Nguyen), in which a pair of matrices is
-   created and then added: no dimensioning necessary.
-
-  .row = 4
-  .col = 9
-
-  ; MACRO TO PRINT A MATRIX
-  define PMATRIX {
-      echo Matrix \%1:
-      for \%r 1 \m(row) 1 {
-          for \%c 1 \m(col) 1 {
-              xecho \flpad(\m(\%1[\%r][\%c]),4)
-          }
-          echo
-      }
-      echo
-  }
-  ; CREATE MATRICES A AND B
-  for \%r 1 \m(row) 1 {
-      for \%c 1 \m(col) 1 {
-          _eval A[\%r][\%c] \%r + \%c
-          _eval B[\%r][\%c] \%r * \%c
-      }
-  }
-  ; CREATE MATRIX C = SUM OF MATRIX A AND MATRIX B
-  for \%r 1 \m(row) 1 {
-      for \%c 1 \m(col) 1 {
-          _eval C[\%r][\%c] \m(A[\%r][\%c]) + \m(B[\%r][\%c])
-      }
-  }
-  pmatrix A  ; Print Matrix A
-  pmatrix B  ; Print Matrix B
-  pmatrix C  ; Print Matrix C
-
-   In the example, we use matrix-like notation to create macros with
-   names like "A[1][1]", "B[3][7]", and so on.
-     _________________________________________________________________
-
-    7.10.10. Associative Arrays
-
-   An associative array is a special kind of Do-It-Yourself array. It
-   differs from a regular array in that its indices need not be numbers
-   -- they can be anything at all -- words, filenames, names of months,
-   any character string at all, and that it doesn't have to be (and in
-   fact can't be) declared. An associative array element is simply a
-   macro whose name ends with an index enclosed in angle brackets, for
-   example:
-
-  file<oofa.txt>
-
-   More formally:
-
-  basename<index>
-
-   An associative array is a collection of all associative array elements
-   that have the same basename. Any number of associative arrays, each
-   with any number of elements, can exist at the same time.
-
-   An associative array element can be assigned a value, such as "1",
-   just like any other macro:
-
-  define file<oofa.txt> 1     ; Give "file<oofa.txt>" the value "1".
-
-   or:
-
-  assign file<oofa.txt> \%a   ; Give it the value of the variable \%a.
-
-   However, since an associative array element is a macro, it may not
-   have an empty (null) value, since assigning an empty value to a macro
-   undefines the macro.
-
-   You can refer to the value of an associative array element using the
-   familiar notation for macro values:
-
-  echo \m(file<oofa.txt>)     ; Echo the value of "file<oofa.txt>".
-
-   Associative arrays are most useful, however, when the value of the
-   index is a variable. In that case, you must use the "hidden" forms of
-   the DEFINE or ASSIGN commands that evaluate the macro name before
-   making the assignment (see [605]Using C-Kermit, page 457). Example:
-
-  define \%f oofa.txt
-  _define file<\%f> 1
-  echo file<\%f> = \m(file<\%f>)
-
-   prints:
-
-  file<oofa.txt> = 1
-
-   and then:
-
-  _increment file<\%f>
-  echo file<\%f> = \m(file<\%f>)
-
-   prints:
-
-  file<oofa.txt> = 2
-
-   What are associative arrays good for? The classic example is "word
-   counts": finding the number of times each word is used in a text
-   without knowing in advance what the words are. Without associative
-   arrays, your program would have to build a table of some kind, and
-   every time a word was encountered, look it up in the table to find its
-   position and counter, or add it to the table if it wasn't found -- a
-   time-consuming and laborious process. Associative arrays, however, let
-   you use the word itself as the table index and therefore sidestep all
-   the table building and lookups.
-
-   Let's work through a practical example. Suppose you have a
-   file-transfer log in which each line is composed of a number of
-   blank-separated fields, and the 9th field is a filename (which happens
-   to be the format of certain FTP server logs, as well as of C-Kermit's
-   new FTP-format transaction log, described in [606]Section 4.17.2), for
-   example:
-
-  Wed Jul 14 09:35:31 1999 22 xx.mit.edu 13412 /pub/ftp/mm/intro.txt ....
-
-   and you want to find out how many times each file was transferred. The
-   following code builds an associative array, file<>, containing the
-   counts for each file:
-
-  local name line max \%c \%n          ; Declare local variables
-  fopen /read \%c /var/log/ftpd.log    ; Open the log file ([607]Section 1.22)
-  if fail exit 1 Can't open log        ; Check
-  while true {                         ; Loop for each record
-      fread /line \%c line             ; Read a line
-      if fail break                    ; Check for end of file
-      .name := \fword(\m(line),9,{ })  ; Get 9th field = filename (Sec 7.3)
-      _increment file<\m(name)>        ; Increment its counter (Sec 7.9.2)
-  }
-  fclose \%c                           ; Close file when done.
-
-   Note that _INCREMENT (and INCREMENT, and [_]DECREMENT) treat an empty
-   (i.e. nonexistent) variable as having a value of 0, and therefore
-   creates the variable with a value of 1.
-
-   At this point, if you told Kermit to "show macro file<", it would list
-   the associative array. But since you don't necessarily know the names
-   of the files in the array, or even how many elements are in the array,
-   how can you use it in a script program?
-
-   The idea of creating macro names that include character-string indices
-   enclosed in angle brackets is perfectly arbitrary and doesn't depend
-   on any Kermit features that weren't already there -- we could just as
-   easily have used some other notation, such as "file[index]",
-   "file:index", or "file.index", and the code above would have worked
-   just as well (with the corresponding syntax adjustments). But to be
-   able to use an associative array in a program after the array is
-   built, we need a method of accessing all its elements without knowing
-   in advance what they are. That's where the chosen notation comes in.
-
-   First of all, any macro name that ends with "<xxx>" (where "xxx" is
-   any string) is case sensitive, unlike all other macro names, which are
-   case independent. To illustrate, "file<oofa.txt>" and "file<OOFA.TXT>"
-   are two distinct macros, whereas "OOFA", "Oofa", and "oofa", when used
-   as macro names, are all the same.
-
-   Second, the new \faaconvert() function converts an associative array
-   (that is, all macros with names of the form "base<index>" that have
-   the same "base" part) into a pair of regular arrays and returns the
-   number of elements:
-
-  \faaconvert(name,&a[,&b])
-
-   "name" is the name of the associative array, without the angle
-   brackets or index ("file" in our example).
-
-   The second argument is the name of a regular array in which to store
-   the indices of the associative array (filenames in our example); if an
-   array of this name already exists, it is destroyed unless the array is
-   LOCAL. The third argument is the name of another regular array in
-   which to store the values (the counts in our example), with the same
-   rules about array name collisions. If you care only about the indices
-   and not the values, you can omit the third argument to \faaconvert().
-   In any case, the associative array is converted, not copied: its
-   elements are moved to the specified regular arrays, so after
-   conversion the original associative array is gone.
-
-   As with other array-loading functions, \faaconvert() sets element 0 of
-   each array to the number of elements in the array.
-
-   To continue our example:
-
-  .max := 0                                   ; Maximum count
-  .\%n := \faaconvert(file,&a,&b)             ; Convert
-  for \%i 1 \%n 1 {                           ; Loop through values
-      echo \flpad(\%i,3). \&a[\%i]: \&b[\%i]  ; Echo this pair
-      if ( > \&b[\%i] \m(max) ) {             ; Check for new maximum
-          .name := \&a[\%i]
-          .max  := \&b[\%i]
-      }
-  }
-  echo Most popular file: \m(name), accesses: \m(max)
-
-   This lists the files and counts and then announces which file has the
-   highest count.
-
-   Now suppose you want to sort the array pair created from an
-   associative array. In our example, \&a[] contains filenames, and \&b[]
-   contains the associated counts. Here we take advantage of the ARRAY
-   SORT command's ability to sort a second array according to the first
-   one:
-
-  array sort /reverse /numeric &b &a          ; Descending sort by count
-
-   Now to see the top five files and their counts:
-
-  echo The top 5 files are:
-  for \%i 1 5 1 {                             ; Loop through top 5 values
-      echo \flpad(\%i,3). \&a[\%i]: \&b[\%i]  ; Echo this pair
-  }
-     _________________________________________________________________
-
-    7.10.11. Transferring Array Contents to Other Computers
-
-   The SEND /ARRAY:arrayname command ([608]Section 4.7.1) allows you to
-   send the contents of any array, or any contiguous segment of it, in
-   either text or binary mode to another computer, using Kermit protocol.
-   When used in conjunction with C-Kermit's other features (the array
-   features described in this section; the file i/o package from
-   [609]Section 1.22; its decision-making, pattern-matching, and string
-   manipulation capabilities, and so on) the possibilities are endless:
-   extracts of large files, remote database queries, ..., all without
-   recourse to system-dependent mechanisms such UNIX pipes and filters,
-   thus ensuring cross-platform portability of scripts that use these
-   features.
-
-   When sending an array in text mode, Kermit appends a line terminator
-   to each array element, even empty ones, and it also converts the
-   character set from your current FILE character-set to your current
-   TRANSFER character-set, if any. No conversions are made or line
-   terminations added in binary mode. For example, the following array:
-
-  dcl \&a[] = One Two Three Four Five Six
-
-   is sent as six lines, one word per line, in text mode, and as the bare
-   unterminated string "OneTwoThreeFourFiveSix" in binary mode.
-
-   You should always include a /TEXT or /BINARY switch in any SEND /ARRAY
-   command to force the desired transfer mode, otherwise you're likely to
-   be surprised by the effects described in [610]Section 4.3.
-
-   Here are some examples:
-
-   send /text /array:\&a[]
-          Sends the entire contents of the array \&a[] in text mode.
-          Since an as-name is not included, the receiver is told the
-          filename is _array_a_.
-
-   send /text /array:&a[]
-   send /text /array:a[]
-   send /text /array:&a
-   send /text /array:a
-          These are all equivalent to the previous example.
-
-   send /text /array:&a /as-name:foo.bar
-          As above, but the array is sent under the name foo.bar.
-
-   send /text /array:&a[100:199] /as:foo.bar
-          As above, but only the elements from 100 through 199 are sent.
-
-   In text-mode transfers, character sets are translated according to
-   your current settings, just as for text files. In binary mode, of
-   course, there is no character-set translation or other conversion of
-   any kind. But remember that array elements can not contain the NUL
-   (ASCII 0) character, since they are implemented as NUL-terminated
-   strings.
-
-   Here's an example that shows how to send all the lines (up to 1000 of
-   them) from a file animals.txt that contain the words "cat", "dog", or
-   "hog" (see [611]Section 4.9 about pattern matching):
-
-  declare \&a[1000]
-  fopen /read \%c animals.txt
-  if fail exit 1
-  .\%i = 0
-  while true {
-      fread \%c line
-      if fail break
-      if match {\m(line)} {*{cat,[dh]og}*} {
-          increment \%i
-          if ( > \%i \fdim(&a) ) break
-          .\&a[\%i] := \m(line)
-      }
-  }
-  fclose \%c
-  send /array:a[1:\%i] /text
-
-   Note that we are careful to send only the part of the array that was
-   filled, not the entire array, because there are likely to be lots of
-   unused elements at the end, and these would be sent as blank lines
-   otherwise.
-
-   This example raises an interesting question: what if we want to send
-   ALL the matching lines, even if there are more than 1000 of them, but
-   we don't know the number in advance? Clearly the problem is limited by
-   Kermit's (and the computer's) memory. If there are a thousand trillion
-   matching lines, they most likely will not fit in memory, and in this
-   case the only solution is to write them first to a temporary file on
-   mass storage and then send the temporary file and delete it
-   afterwards.
-
-   However, when the selection is likely to fit in memory, the
-   once-familiar technique of initial allocation with extents can be
-   used:
-
-  if match {\m(line)} {*{cat,[dh]og}*} {
-      increment \%i
-      if ( > \%i \fdim(&a) ) {
-          array resize a \fdim(&a)+100
-          if fail stop 1 MEMORY FULL
-          echo NEW DIMENSION: \fdim(&a)
-      }
-      .\&a[\%i] := \m(line)
-  }
-
-   This grows the array in chunks of 100 as needed.
-     _________________________________________________________________
-
-  7.11. OUTPUT Command Improvements
-
-   LINEOUT [ text ]
-          This command is exactly like OUTPUT, except it supplies a
-          carriage return at the end of the text. "lineout exit" is
-          exactly the same as "output exit\13".
-
-   SET OUTPUT SPECIAL-ESCAPES { ON, OFF }
-          This command lets you tell C-Kermit whether to process \N, \L,
-          and \B specially in an OUTPUT command, as distinct from other \
-          sequences (such as \%a, \13, \v(time), etc). Normally the
-          special escapes are handled. Use SET OUTPUT SPECIAL-ESCAPES OFF
-          to disable them.
-
-   Disabling special escapes is necessary in situations when you need to
-   transmit lines of data and you have no control over what is in the
-   lines. For example, a file oofa.txt that contains:
-
-  This is a file
-  It has \%a variables in it
-  And it has \B in it.
-  And it has \L in it.
-  And it has \N in it.
-  And this is the last line.
-
-   can be sent like this:
-
-  local line
-  set output special-escapes off
-  fopen /read \%c oofa.txt
-  if fail stop 1 Can't open oofa.txt
-  while success {
-      fread \%c line
-      if fail break
-      ; Add filtering or processing commands here...
-      output \m(line)\13
-  }
-     _________________________________________________________________
-
-  7.12. Function and Variable Diagnostics
-
-   In C-Kermit 6.0 and earlier, the only diagnostic returned by a failing
-   function call was an empty value, which (a) could not be distinguished
-   from an empty value returned by a successful function call; (b) did
-   not give any indication of the cause of failure; and (c) did not cause
-   the enclosing statement to fail. C-Kermit 7.0 corrects these
-   deficiencies.
-
-   SET FUNCTION DIAGNOSTICS { ON, OFF }
-          when ON, allows built-in functions to return diagnostic
-          messages when improperly referenced, instead of an empty
-          string. FUNCTION DIAGNOSTICS are ON by default. When OFF,
-          improperly referenced functions continue to return an empty
-          string. This command also affects built-in variables; in this
-          case, an error message is returned only if the variable does
-          not exist. When FUNCTION DIAGNOSTICS are ON, the error message
-          is also printed.
-
-   For variables, the only message is:
-
-  <ERROR:NO_SUCH_VARIABLE:\v(name)>
-
-   where "name" is the name of the nonexistent variable.
-
-   For functions, the diagnostic message is:
-
-  <ERROR:message:\fname()>
-
-   where "message" is replaced by a message, and "name" is replaced by
-   the function name, e.g. <ERROR:ARG_NOT_NUMERIC:\fmod()>. Messages
-   include:
-
-  ARG_BAD_ARRAY       An argument contains a malformed array reference.
-  ARG_BAD_DATE        An argument contains a malformed date and/or time.
-  ARG_BAD_PHONENUM    An argument contains a malformed telephone number.
-  ARG_BAD_VARIABLE    An argument contains a malformed \%x variable.
-  ARG_INCOMPLETE      An argument is incomplete (e.g. a broken Base64 string).
-  ARG_EVAL_FAILURE    An argument could not be evaluated (internal error).
-  ARG_NOT_ARRAY       An argument references an array that is not declared.
-  ARG_NOT_NUMERIC     An argument that must be integer contains non-digits.
-  ARG_NOT_FLOAT       An argument has bad floating-point number format.
-  ARG_NOT_VARIABLE    An argument that must be a variable is not a variable.
-  ARG_OUT_OF_RANGE    An argument's numeric value is too big or too small,
-                      or an argument contains illegal characters (e.g. a hex
-                      or Base-64 string).
-  ARG_TOO_LONG        An argument's value is too long.
-  ARRAY_FAILURE       Failure to create an array.
-  DIVIDE_BY_ZERO      Execution of the function would cause division by zero.
-  FLOATING_POINT_OP   Execution error in a floating-point operation.
-  FILE_NOT_FOUND      Filename argument names a file that can't be found.
-  FILE_NOT_READABLE   Filename argument is not a regular file.
-  FILE_NOT_ACCESSIBLE Filename argument names a file that is read-protected.
-  FILE_ERROR          Other error with filename argument.
-  FILE_NOT_OPEN       A file function was given a channel that is not open.
-  FILE_ERROR_-n       A file function got error -n ([612]Section 1.22).
-  LOOKUP_FAILURE      Error looking up function (shouldn't happen).
-  MALLOC_FAILURE      Failure to allocate needed memory (shouldn't happen).
-  NAME_AMBIGUOUS      The function is not uniquely identified.
-  MISSING_ARG         A required argument is missing.
-  NO_SUCH_FUNCTION    An argument references a function that is not defined.
-  NO_SUCH_MACRO       An argument references a macro that is not defined.
-  RESULT_TOO_LONG     The result of a function is too long.
-  UNKNOWN_FUNCTION    Internal error locating function (shouldn't happen).
-
-   Examples:
-
-  assign \%m \fmod()
-  ?<ERROR:MISSING_ARG:\fmod()>
-  echo "\fcontents(\%m)"
-  "<ERROR:MISSING_ARG:\fmod()>"
-  echo \fmod(3,x)
-  ?<ERROR:ARG_NOT_NUMERIC:\fmod()>
-  echo \fmod(3,4-2*2)
-  ?<ERROR:DIVIDE_BY_ZERO:\fmod()>
-
-   Notice the use of \fcontents() in echoing the value of a variable that
-   contains a returned error message. That's because the error message
-   includes the name of the variable or function that failed, so you must
-   use \fcontents() to prevent it from being evaluated again -- otherwise
-   the same error will occur.
-
-   The handling of function and variable errors is controlled by:
-
-   SET FUNCTION ERROR { ON, OFF }
-          Tells whether invalid function calls or variable references
-          should cause command errors. FUNCTION ERROR is ON by default.
-          When ON, and an error is diagnosed in a built-in function or
-          variable, the command that includes the function call or
-          variable reference fails. The failing command can be handled in
-          the normal way with IF FAILURE / IF SUCCESS, SET TAKE ERROR, or
-          SET MACRO ERROR.
-
-   When FUNCTION DIAGNOSTICS is OFF, there is no error message.
-
-   SHOW SCRIPTS displays the current FUNCTION DIAGNOSTICS and ERROR
-   settings.
-     _________________________________________________________________
-
-  7.13. Return Value of Macros
-
-   In C-Kermit 5A and 6.0, there are two ways to return one level from a
-   macro: RETURN value and END number text. When RETURN is used, the
-   value, which can be a number or a text string, is assigned to
-   \v(return). When END was used, however, \v(return) was not set.
-   SUCCESS/FAILURE was set according to whether the number was zero, and
-   the text was printed, but the actual value of the number was lost.
-
-   In C-Kermit 7.0, the END number is available in the \v(return)
-   variable.
-     _________________________________________________________________
-
-  7.14. The ASSERT, FAIL, and SUCCEED Commands.
-
-   The ASSERT command is just like the IF command, but without a command
-   to execute. It simply succeeds or fails, and this can be tested by a
-   subsequent IF SUCCESS or IF FAILURE command. Example:
-
-  ASSERT = 1 1
-  IF SUCCESS echo 1 = 1.
-
-   The FAIL command does nothing, but always fails. The SUCCEED command
-   does nothing, but always succeeds.
-
-   These commands are handy in debugging scripts when you want to induce
-   a failure (or success) that normally would not occur, e.g. for testing
-   blocks of code that normally are not executed.
-     _________________________________________________________________
-
-  7.15. Using Alarms
-
-   Alarms may be set in two ways:
-
-   SET ALARM number
-          Sets an alarm for the given number of seconds "from now", i.e.
-          in the future, relative to when the SET ALARM command was
-          given. Examples:
-
-  set alarm 60        ; 60 seconds from now
-  set alarm +60       ; The same as "60"
-  set alarm -60       ; Not legal - you can't set an alarm in the past.
-  set alarm 60*60     ; 60 minutes from now.
-  set alarm \%a+10    ; You can use variables, etc.
-
-   SET ALARM hh:mm:ss
-          Sets an alarm for the specified time. If the given time is
-          earlier than the current time, the alarm is set for the given
-          time in the next day. You may give the time in various formats:
-
-  set alarm 15:00:00  ; 3:00:00pm
-  set alarm 3:00:00pm ; 3:00:00pm
-  set alarm 3:00pm    ; 3:00:00pm
-  set alarm 3pm       ; 3:00:00pm
-
-   SHOW ALARM
-          Displays the current alarm, if any, in standard date-time
-          format (see [613]Section 1.6): yyyymmdd hh:mm:ss.
-
-   IF ALARM command
-          Executes the command if an alarm has been set and the alarm
-          time has passed.
-
-   IF ALARM { command-list } [ ELSE { command-list } ]
-          Executes the command-list if an alarm has been set and the
-          alarm time has passed. Otherwise, if an ELSE part is given, its
-          command-list is executed.
-
-   CLEAR ALARM
-          Clears the alarm.
-
-   Only one alarm may be set at a time.
-
-   Example: Suppose you have a script that is always running, and that
-   transfers files periodically, and that keeps a transaction log.
-   Suppose you want to start a new transaction log each day:
-
-  log transactions \v(date).log
-  set alarm 00:00:00                     ; Set an alarm for midnight
-  while true {                           ; Main script loop
-      xif alarm {                        ; If the alarm time is past...
-          close transactions             ; Close current log
-          log transactions \v(date).log  ; Start new one
-          pause 1                        ; To make sure 00:00:00 is past
-          set alarm 00:00:00             ; Set a new alarm
-      }
-      ; put the rest of the script here...
-  }
-
-   Note that IF ALARM -- no matter whether it succeeds or fails -- does
-   NOT clear an expired alarm. Thus, once an alarm has expired, every IF
-   ALARM will succeed until the alarm is cleared (with the CLEAR ALARM
-   command) or reset with a new SET ALARM command.
-     _________________________________________________________________
-
-  7.16. Passing Arguments to Command Files
-
-   Beginning in version 7.0, C-Kermit accepts arguments on the TAKE
-   command line, for example:
-
-  C-Kermit> take oofa.ksc one two {this is three} four
-
-   This automatically sets the variables \%1 through \%9 to the
-   arguments, and \%0 to the name of the file, in this case:
-
-  \%0 = /usr/olga/oofa.ksc
-  \%1 = one
-  \%2 = two
-  \%3 = this is three
-  \%4 = four
-
-   and \%5..\%9 are undefined (empty). Arguments past the ninth are
-   available in the \&_[] argument-vector array ( [614]Section 7.5).
-
-   The variables are those at the current macro level. Thus, if the TAKE
-   command is executed from within a macro, the macro's arguments are
-   replaced by those given on the TAKE command line (but only if at least
-   one argument is given). The command shown above is exactly equivalent
-   to:
-
-  assign \%0 /usr/olga/oofa.ksc
-  assign \%1 one
-  assign \%2 two
-  assign \%3 this is three
-  assign \%4 four
-  assign \%5
-  assign \%6
-  assign \%7
-  assign \%8
-  assign \%9
-  take oofa.ksc
-
-   Remember, the variables \%0..\%9 are on the macro call stack, and
-   command files are independent of the macro stack. Thus, if a command
-   file TAKEs another command file and passes arguments to it, the
-   variables are changed from that point on for both files, and so forth
-   for all levels of nested command files without intervening macro
-   invocations.
-
-   It would have been possible to change C-Kermit to use the overall
-   command stack, rather than the macro stack, for arguments -- this
-   would have made TAKE work exactly like DO, which is "nicer", but it
-   would also have broken countless existing scripts. However, the new
-   SHIFT command ([615]Section 7.5) makes it possible to create an
-   alternative TAKE command that does indeed save and restore the
-   argument variables at its own level around execution of a command
-   file:
-
-  define mtake {
-     local \%f
-     assign \%f \fcontents(\%1)
-     shift
-     take \%f
-  }
-
-   C-Kermit 7.0 also supports a new, easier way to pass arguments to
-   scripts from the system command line:
-
-  kermit filename arg1 arg2 arg3 ...
-
-   in which arg1, arg2, arg3 (etc) are arguments for the script (whose
-   filename is given), and are assigned to \%1, \%2, ... \%9. The
-   filename is assigned to \%0. This applies equally to "Kerbang" scripts
-   in UNIX ([616]Section 7.19). For example, suppose you have a file
-   called "showargs" containing the following lines:
-
-  #!/usr/local/bin/kermit +
-  echo Hello from \%0
-  show args
-  exit
-
-   (except not indented, since the "#!" line must be on the left margin).
-   If you give this file execute permission:
-
-  chmod +x showargs
-
-   then you can run it exactly as you would run a UNIX shell script,
-   e.g.:
-
-  $ showargs one two three
-  Hello from /usr/olga/showargs
-  Top-level arguments (\v(argc) = 4):
-   \&_[0] = /usr/olga/showargs
-   \&_[1] = one
-   \&_[2] = two
-   \&_[3] = three
-
-   Furthermore, the \&_[] array now contains the filename, if one was
-   given as the first command line argument, or it is a "Kerbang" script,
-   in element 0.
-
-   Otherwise element 0 is program name, and elements 1 through \v(argc)-1
-   contain the command-line arguments, if any, that appear after "--" or
-   "=", if any. This array is saved and restored around macro calls;
-   recall that inside macros it contains the macro argument vector
-   (allowing you to access arguments programmatically, and to have more
-   than 9 of them).
-
-   At top level, notice the difference between the \&@[] and \&_[]
-   arrays. The former includes C-Kermit options; the latter omits them.
-     _________________________________________________________________
-
-  7.17. Dialogs with Timed Responses
-
-   The ASK, ASKQ, GETOK, and GETC commands (let's call them the
-   "ASK-class commands") let you write scripts that carry on dialogs with
-   the user, asking them for text, a Yes/No answer, or a character,
-   respectively. Prior to C-Kermit 7.0, these questions would always wait
-   forever for an answer. In C-Kermit 7.0, you may specify a time limit
-   for them with the new command:
-
-   SET ASK-TIMER number
-          Sets a time-limit on ASK-CLASS commands to the given number of
-          seconds. If the number is 0 or less, there is no time limit and
-          these commands wait forever for a response. Any timer that is
-          established by this command remains in effect for all future
-          ASK-class commands until another SET ASK-TIMER command is given
-          (e.g. with a value of 0 to disable ASK timeouts).
-
-   IF ASKTIMEOUT command
-          An ASK-class command that times out returns a failure status.
-          You can test explicitly for a timeout with:
-     _________________________________________________________________
-
-  7.18. Increased Flexibility of SWITCH Case Labels
-
-   Prior to C-Kermit 7.0 / K95 1.1.19, the case labels in SWITCH
-   statements were string constants.
-
-   Now case labels can be variables, function calls, or any mixture of
-   these with each other and/or with regular characters.
-
-   Furthermore, after the case label is evaluated, it is treated not as a
-   string constant, but as a pattern against which the SWITCH variable is
-   matched ([617]Section 4.9.1).
-
-   This introduces a possible incompatibility with previous releases,
-   since the following characters in case labels are no longer taken
-   literally:
-
-  \ * ? [ {
-
-   Any scripts that previously included any of these characters in case
-   labels must now quote them with backslash (\).
-     _________________________________________________________________
-
-  7.19. "Kerbang" Scripts
-
-   In UNIX only, Kermit scripts can be stored in files and run
-   "directly", without starting Kermit first (as noted on page 467 of the
-   manual), just as a shell script can be "run" as if it were a program.
-   This section amplifies on that idea a bit, and presents some new
-   aspects of version 7.0 that make it easier to write and run Kermit
-   scripts directly.
-
-     NOTE: On non-UNIX platforms, such as VMS or Windows, Kerbang
-     scripts can be run as "kermit + scriptfilename arg1 arg2 arg3 ...".
-     Windows 95/98/NT file associations do not allow for the passing of
-     parameters. In VMS, however, you can achieve the Kerbang effect by
-     defining a symbol, as in this example:
-
-  $ autotelnet :== "$SYS$TOOLS:KERMIT.EXE + AUTOTELNET.KSC"
-
-     and then running the script like any other command:
-
-  $ autotelnet xyzcorp.com myuserid
-
-     See [618]Section 9.3 for an explanation of the "+" symbol.
-
-   UNIX shell scripts can specify which shell should run them by
-   including a "shebang" line at the top, e.g.:
-
-  #!/bin/sh
-
-   (but not indented; the shebang line must be on the left margin). The
-   term "shebang" is a contraction of "shell" and "bang". "Bang" is a
-   slang word for the exclamation mark ("!"); "shebang" itself is an
-   American slang word used in in the phrase "the whole shebang".
-
-   We can run Kermit scripts directly too, by including a "shebang" line
-   that names Kermit as the "shell"; thus we call these "Kerbang"
-   scripts. This mechanism has been considerably simplified in C-Kermit
-   7.0 to facilitate C-Kermit's use a scripting tool just like any of the
-   UNIX shells or scripting languages. The rules are the same as for
-   shell scripts:
-
-    1. The first line of the Kermit script must begin with "#!"
-       immediately followed by the full pathname of the program that will
-       execute the script (in this case, C-Kermit rather than a UNIX
-       shell), followed by any Kermit command-line options. To suppress
-       execution of the C-Kermit initialization file and to make command
-       line arguments available to the script, the final option should be
-       "+":
-  #!/usr/local/bin/kermit +
-       Some users have reported that in some circumstances a space might
-       be necessary after the plus sign; this depends on your shell -- it
-       has nothing to do with Kermit. In most cases, no space is needed.
-    2. The file must have execute permission (granted via "chmod +x
-       filename").
-
-   When C-Kermit is invoked from a Kerbang script (or from the system
-   prompt with a "+" command-line argument, which amounts to the same
-   thing), the following special rules apply:
-
-    1. The C-Kermit initialization file is NOT executed automatically. If
-       you want it to be executed, include a TAKE command for it in the
-       script, e.g. "take \v(home).kermrc". (In previous releases, the
-       initialization file was always executed, with no way to prevent it
-       except for the user to include Kermit-specific command line
-       options which had nothing to do with the script). Many scripts
-       have no need for the standard Kermit initialization file, which is
-       quite lengthy and not only delays startup of the script, but also
-       spews forth numerous messages that are most likely unrelated to
-       the script.
-    2. If the initialization file is not executed, neither is your
-       customization file, since the initialization file is the command
-       file from which the customization file is TAKEn. Again, you can
-       include a TAKE command for the initialization file if desired, or
-       for the customization file by itself, or for any other file.
-    3. C-Kermit does not process command-line arguments at all. Instead,
-       it passes all words on the command line after the "+" to the
-       script as \%0 (the script name), \%1..\%9 (the first nine
-       arguments), as well as in the argument vector array \&_[]. The
-       variable \v(argc) is set to the total number of "words" (as passed
-       by the shell to Kermit) including the script name. Quoting and
-       grouping rules are those of the shell.
-    4. At any point where the script terminates, it must include an EXIT
-       command if you want it to exit back to the shell; otherwise
-       C-Kermit enters interactive prompting mode when the script
-       terminates. The EXIT command can include a numeric status to be
-       returned to the shell (0, 1, etc), plus an optional message.
-
-   Here is a simple Kerbang script that prints its arguments:
-
-  #/usr/local/bin/kermit +
-  echo Hello from \%0
-  for \%i 0 \v(argc)-1 1 {
-      echo \%i. "\&_[\%i]"
-  }
-  exit 0
-
-   Save this file as (say) "showargs", then give it execute permission
-   and run it (the \&_[] array is the same as \%0..\%9, but allows you to
-   refer to argument variables programmatically; see [619]Section 7.5).
-   (Yes, you could substitute SHOW ARGUMENTS for the loop.)
-
-  $ chmod +x showargs
-  $ ./showargs one "this is two" three
-
-   The script displays its arguments:
-
-  Hello from /usr/olga/showargs
-  0. "/usr/olga/showargs"
-  1. "one"
-  2. "this is two"
-  3. "three"
-  $
-
-   Notice that no banners or greetings are printed and that startup is
-   instantaneous, just like a shell script. Also notice that grouping of
-   arguments is determined by *shell* quoting rules, not Kermit ones,
-   since the command line is parsed by the shell before Kermit ever sees
-   it.
-
-   Of course you can put any commands at all into a Kerbang script. It
-   can read and write files, make connections, transfer files, anything
-   that Kermit can do -- because it *is* Kermit. And of course, Kerbang
-   scripts can also be executed from the Kermit prompt (or from another
-   script) with a TAKE command; the Kerbang line is ignored since it
-   starts with "#", which is a comment introducer to Kermit just as it is
-   to the UNIX shell. In VMS and other non-UNIX platforms, the Kerbang
-   line has no effect and can be omitted.
-
-   It might be desireable for a script to know whether it has been
-   invoked directly from the shell (as a Kerbang script) or by a TAKE
-   command given to the Kermit prompt or in a Kermit command file or
-   macro. This can be done as in this example:
-
-  #!/usr/local/bin/kermit +
-  assign \%m \fbasename(\%0)
-  define usage { exit 1 {usage: \%m phonenumber message} }
-  define apage { (definition of APAGE...) } ; (See [620]book pp.454-456)
-  xif equal "\%0" "\v(cmdfil)" {
-      if not def \%1 usage
-      if not def \%2 usage
-      apage {\%1} {\%2}
-      exit \v(status)
-  }
-
-   In a Kerbang script, \%0 and \v(cmdfile) are the same; both of them
-   are the name of the script. When a script is invoked by a Kermit TAKE
-   command, \%0 is the name of the Kermit program, but \v(cmdfile) is the
-   name of the script. In the example above, a macro called APAGE is
-   defined. If the script was invoked directly, the APAGE macro is also
-   executed. Otherwise, it is available for subsequent and perhaps
-   repeated use later in the Kermit session.
-
-   An especially handy use for Kerbang scripts is to have the
-   initialization file itself be one. Since the standard initialization
-   file is rather long and time-consuming to execute, it is often
-   overkill if you want to start Kermit just to transfer a file. Of
-   course there are command-line switches to suppress initialization-file
-   execution, etc, but another approach is to "run" the initialization
-   file when you want its features (notably the services directory), and
-   run C-Kermit directly when you don't. A setup like this requires that
-   (a) the C-Kermit initialization file is configured as a Kerbang script
-   (has #!/path.../kermit as first line), has execute permission, and is
-   in your PATH; and (b) that you don't have a .kermrc file in your login
-   directory.
-     _________________________________________________________________
-
-  7.20. IF and XIF Statement Syntax
-
-   The IF command has been improved in two significant ways in C-Kermit
-   7.0, described in the following subsections. All changes are backwards
-   compatible.
-
-    7.20.1. The IF/XIF Distinction
-
-   The distinction between IF and XIF is no longer important as of
-   C-Kermit 7.0. You should be able to use IF in all cases (and of
-   course, also XIF for backwards compatibility). In the past, IF was
-   used for single-command THEN parts, followed optionally by a separate
-   ELSE command:
-
-  IF condition command1    ; THEN part
-  ELSE command2            ; ELSE part
-
-   whereas XIF was required if either part had multiple commands:
-
-  XIF condition { command, command, ... } ELSE { command, command, ... }
-
-   The syntactic differences were primarily that IF / ELSE was two
-   commands on two separate lines, whereas XIF was one command on one
-   line, and that XIF allowed (and in fact required) braces around its
-   command lists, whereas IF did not allow them.
-
-   Furthermore, the chaining or nesting of parts and conditions was
-   inconsistent. For example, the IF command could be used like this:
-
-  IF condition command
-  ELSE IF condition command
-  ELSE IF condition command
-  ELSE IF condition command
-  ...
-
-   but XIF could not. C-Kermit 7.0 accepts the old syntax and executes it
-   the same as previous versions, but also accepts a new unified and more
-   convenient syntax:
-
-   IF condition command-list [ ELSE command-list ]
-
-   or:
-
-IF condition command-list
-ELSE command-list
-
-   in which the ELSE part is optional, and where command-list can be a
-   single command (with or without braces around it) or a list of
-   commands enclosed in braces. Examples:
-
-   Example 1:
-
-  IF condition { command1, command2 } ELSE { command3, command4 }
-
-   Example 2 (same as Example 1):
-
-  IF condition {
-     command1
-     command2
-  } ELSE {
-     command3
-     command4
-  }
-
-   Example 3 (same as 1 and 2):
-
-  IF condition {
-     command1
-     command2
-  }
-  ELSE { command3, command4 }
-
-   Example 4 (same as 1-3):
-
-  IF condition {
-     command1
-     command2
-  }
-  ELSE {
-     command3
-     command4
-  }
-
-   Example 5 (ELSE can be followed by another command):
-
-  IF condition {
-     command1
-     command2
-  } ELSE IF condition {
-     command3
-     command4
-  } ELSE {
-     command5
-     command6
-  }
-
-   Example 5 suggests other possibilities:
-
-  IF condition {
-     command1
-     command2
-  } ELSE FOR variable initial final increment {
-     command3
-     command4
-  }
-
-   And this too is possible, except for some non-obvious quoting
-   considerations:
-
-  dcl \&a[6] = one two three four five six
-
-  IF < \%n 3 {
-      echo \\%n is too small: \%n
-  } ELSE FOR \\%i 1 \\%n 1 {
-      echo \\%i. \\&a[\\%i]
-  }
-
-   (The loop variable must be quoted in this context to prevent premature
-   evaluation.)
-     _________________________________________________________________
-
-    7.20.2. Boolean Expressions (The IF/WHILE Condition)
-
-   Prior to C-Kermit 7.0, the IF and WHILE commands accepted only a
-   single Boolean ("true or false") assertion, e.g. "if > \%m 0 command"
-   or "if exist filename command". There was no way to form Boolean
-   expressions and, in particular, nothing that approached a Boolean OR
-   function (AND could be simulated by concatenating IF statements: "if
-   condition1 if condition2..").
-
-   C-Kermit 7.0 (and K95 1.1.19) allow grouping of Boolean assertions
-   using parentheses and combining them using AND (or &&) and OR (or ||).
-   Each of these operators -- including the parentheses -- is a field and
-   must be set off by spaces. AND has higher precedence than OR, NOT has
-   higher precedence than AND, but parentheses can be used to force any
-   desired order of evaluation. The old syntax is still accepted.
-
-   Here are some examples:
-
-  define \%z 0                          ; Define some variables
-  define \%n 1                          ; for use in the examples.
-
-  if > \%n \%z echo \%n is greater.     ; Original format - still accepted.
-  if ( > \%n \%z ) echo \%n is greater. ; Parentheses may be used in 7.0.
-  if ( > \%n \%z && not = \%z 0 ) ...   ; Two assertions combined with AND.
-  if ( > \%n \%z and not = \%z 0 ) ...  ; Same as previous ("and" = "&&").
-  if ( > \%n \%z || not = \%z 0 ) ...   ; Two assertions combined with OR.
-  if ( > \%n \%z or not = \%z 0 ) ...   ; Same as previous ("or" = "||").
-  if ( > \%n \%z || != \%z 0 ) ...      ; Ditto ("!=" = "not =").
-  while ( 1 ) { ... }                   ; Just like C.
-
-   Notice the spaces around all operators including the parentheses --
-   these are required. The following examples show how parentheses can be
-   used to alter the precedence of the AND and OR operators:
-
-  if ( false || false && false || true ) ,..         ; True
-  if ( false || ( false && false ) || true ) ...     ; Same as previous
-  if ( ( false || false ) && ( false || true ) ) ... ; False
-
-   Similarly for NOT:
-
-  if ( not true && false ) ...          ; False (NOT binds to TRUE only)
-  if ( ( not true ) && false ) ...      ; Same as previous
-  if ( not ( true && false ) ) ...      ; True (NOT binds to (TRUE && FALSE))
-
-   Notes:
-
-    1. The syntax of the Boolean expression itself has not changed; each
-       expression begins with a keyword or token such as "EXIST", ">", or
-       "=", etc; operators such as "<", "=", and ">" do not go between
-       their operands but precede them as before; this might be called
-       "reverse reverse Polish notation"; it allows deterministic
-       on-the-fly parsing of these expressions at the C-Kermit> prompt as
-       well as in scripts, and allows ?-help to be given for each item
-       when IF or WHILE commands are typed at the prompt.
-    2. Parentheses are required when there is more than one Boolean
-       assertion.
-    3. Parentheses are not required, but are allowed, when there is only
-       one Boolean assertion.
-    4. Evaluation of Boolean assertions occurs left to right, but the
-       resulting Boolean expression is evaluated afterwards according to
-       the rules of precedence. All Boolean assertions are always
-       evaluated; there is no "early stopping" property and therefore no
-       question about when or if side effects will occur -- if any
-       Boolean assertion has side effects, they will always occur.
-
-   Constructions of arbitrary complexity are possible, within reason.
-
-   Also see [621]Section 7.4 for new IF / WHILE conditions.
-     _________________________________________________________________
-
-  7.21. Screen Formatting and Cursor Control
-
-   C-Kermit 7.0 adds a simple way to create formatted screens, the SCREEN
-   command:
-
-   SCREEN { CLEAR, CLEOL, MOVE-TO row [ column ] }
-          Performs screen-formatting actions. Correct operation of these
-          commands depends on proper terminal setup on both ends of the
-          connection -- mainly that the host terminal type is set to
-          agree with the kind of terminal or the emulation you are
-          viewing C-Kermit through. The UNIX version uses terminfo or
-          termcap (not curses); the VMS version uses SMG; K-95 uses its
-          built in screen manager.
-
-   SCREEN CLEAR
-          Moves the cursor to home position and clears the entire screen.
-          Synonyms: CLEAR COMMAND-SCREEN ALL (K-95 only), CLS, CLEAR
-          SCREEN.
-
-   SCREEN CLEOL
-          Clears from the current cursor position to the end of the line.
-          Synonym: CLEAR COMMAND-SCREEN EOL (K-95 only)
-
-   SCREEN MOVE-TO row column
-          Moves the cursor to the indicated row and column. The row and
-          column numbers are 1-based, so on a 24x80 screen the home
-          position is 1 1 and the lower right corner is 24 80. If a row
-          or column number is given that too large for what Kermit or the
-          operating system thinks is your screen size, the appropriate
-          number is substituted.
-
-   These escape sequences used by these commands depends on the platform.
-   In UNIX, your TERM environment variable is used to query the
-   terminfo/termcap database; if the query fails, ANSI/VT100 sequences
-   are used. In VMS, the SMG library is used, which sends sequences based
-   on your VMS terminal type. K95 does its own screen control. On other
-   platforms (such as AOS/VS, VOS, etc), screen formatting is not
-   supported, and the SCREEN command does nothing.
-
-   The three SCREEN actions can be used in scripts to produce menus,
-   formatted screens, dynamic displays, etc. Related variables include:
-
-  \v(terminal)     The type terminal C-Kermit thinks you have.
-  \v(rows)         The number of rows C-Kermit thinks your terminal has.
-  \v(columns)      The number of columns C-Kermit thinks your terminal has.
-
-   And functions:
-
-  \fscrncurx()     The current X coordinate of the cursor (K-95 only).
-  \fscrncury()     The current Y coordinate of the cursor (K-95 only).
-  \fscrnstr(x,y,n) The string of length nat position (x,y) (K-95 only).
-
-   And commands:
-
-  ECHO string      Writes string + CRLF at the current cursor position.
-  XECHO string     Writes string at current cursor position; CRLF not supplied.
-  GETC v prompt    Issues prompt, reads one character into variable v, no echo.
-
-   And special characters:
-
-  Ctrl-L           At the C-Kermit> command prompt, or in a C-Kermit command,
-                   works like Return or Enter, but also clears the screen
-
-   Example 1: A macro that prints a message \%1 at cursor position
-   (\%2,\%3):
-
-  define MSG {
-      if not def \%3 def \%3 0             ; Default column to 0
-      if > \v(argc) 2 screen move \%2 \%3  ; Move to given row/col (if any)
-      screen cleol                         ; Clear to end of line
-      if def \%1 xecho \fcontents(\%1)     ; Print message (if any)
-  }
-
-   Example 2: A macro put the cursor on the bottom screen line, left
-   margin:
-
-  define BOT {
-      screen move \v(rows) 0
-  }
-
-   Example 3: A macro to center message \%1 on line \%2.
-
-  define CENTER {
-      if not def \%2 def \%2 1
-      .\%x ::= (\v(cols)-\flen(\%1))/2
-      msg {\%1} {\%2} {\%x}
-  }
-
-   Example 4: A simple menu (building on Examples 1-3):
-
-  def \%c 0                             ; Menu choice variable
-  screen clear                          ; Clear the screen
-  center {Welcome to This Menu} 2       ; Display the menu
-  msg {Choices:} 4
-  msg { 1. File} 6
-  msg { 2. Edit} 7
-  msg { 3. Exit} 8
-  while ( != \%c 3 ) {                  ; Read and verify choice
-      while true {                      ; Keep trying till we get a good one
-          screen move 10                ; Move to line 10
-          screen cleol                  ; Clear this line
-          getc \%c {Your choice: }      ; Prompt and get and echo 1 character
-          xecho \%c
-          if ( not numeric \%c ) { msg {Not numeric - "\%c"} 12, continue }
-          if ( >= \%c 1 && <= \%c 3 ) break
-          msg {Out of range - "\%c"} 12
-      }
-      switch \%c {                      ; Valid choice - execute it.
-        :1, msg {Filing... } 12, break
-        :2, msg {Editing...} 12, break
-        :3, msg {Exiting...} 12, break
-      }
-  }
-  echo Bye                              ; Exit chosen - say goodbye.
-  bot                                   ; Leave cursor at screen bottom.
-  exit                                  ; And exit.
-
-   Similar scripts can work over the communication connection; substitute
-   INPUT and OUTPUT for GETC and ECHO/XECHO.
-     _________________________________________________________________
-
-  7.22. Evaluating Arithmetic Expressions
-
-   A new arithmetic operator was added to the list recognized by the
-   EVALUATE command, the \feval() function, and which can also be used
-   anywhere else arithmetic expressions are accepted (numeric command
-   fields, array subscripts, etc):
-
-   Prefix "!"
-          This operator inverts the "truth value" of the number or
-          arithmetic expression that follows. If the value of the operand
-          is 0, the result is 1. If the value is nonzero, the result is
-          0.
-
-   Examples:
-
-  set eval old
-  evaluate 0
-  0
-
-  evaluate !0
-  1
-
-  evaluate !3
-  0
-
-  evaluate !(-3)
-  0
-
-  .\%a = 1
-  .\%b = 0
-  evaluate !(\%a|\%b)
-  0
-
-  evaluate !(\%a&\%b)
-  1
-
-  evaluate !(!(\%a&\%b))
-  0
-
-   Note the distinction between Prefix ! (invert truth value) and Suffix
-   ! (factorial). Also the distinction between Prefix ! and Prefix ~
-   (which inverts all the bits in its operand). Also note that prefix
-   operators (!, -, and ~) can not be adjacent unless you use parentheses
-   to separate them, as shown in the final example above.
-     _________________________________________________________________
-
-  7.23. Floating-Point Arithmetic
-
-   C-Kermit 7.0 adds limited support for floating-point numbers (numbers
-   that have fractional parts, like 3.141592653). This support is
-   provided through a small repertoire of functions and in Boolean
-   expressions that compare numbers, but does not apply to number parsing
-   in general, or to expression evaluation, array subscripts, the
-   INCREMENT and DECREMENT commands, or in any context other than those
-   listed in this section.
-
-   A floating point number has an optional sign (+ or -), followed by a
-   series of decimal digits containing either zero or one period (.)
-   character, which is the decimal point. The use of comma or any other
-   character besides period as a decimal point is not supported.
-   Scientific notation is not supported either. Examples of legal
-   floating-point numbers:
-
-  0                Integers can be used
-  1                Ditto
-  2.               A decimal point without decimal digits
-  3.0              A decimal point with decimal digits
-  3.141592653      Ditto
- -4.0              A negative sign can be included
- +5.0              A positive sign can be included
-
-   Examples of notations that are not accepted:
-
-  1,000,000        Separators can not be used
-  1.000.000        Ditto (or multiple decimal points)
-  6.022137E23      No scientific notation
-  6.62606868e-34   Ditto
-  12.5+6.25        No "bare" expressions
-
-   You can use IF FLOAT test a string or variable to see if it's in
-   acceptable floating-point format. Example:
-
-  ask \%f { Type a number: }
-  if not def \%f .\%f = 0.0
-  if not float \%f stop 1 Invalid floating-point number: "\%f"
-
-   C-Kermit's floating-point support, like its support for whole numbers
-   (integers), relies on the capabilities of the underlying computer.
-   Your computer has only a limited amount of precision for numbers,
-   depending on its architecture. Thus floating-point numbers that have
-   too many digits will not be accurate; adding a very small number to a
-   very large one might have no effect at all; and so on. For details,
-   read a text on numerical analysis. Example:
-
-  .\%a = 11111111111111111111  ; A long number
-  .\%b = 22222222222222222222  ; Another one
-  echo \ffpadd(\%a,\%b)        ; Add them - the result should be all 3's
-  33333333333333330000.0       ; See the result
-
-   In this example, the computer has 16 digits of precision; after that,
-   the (low-order) digits are set to 0, since the computer doesn't know
-   what they really are. In fact, the computer returns random digits, but
-   Kermit sets all digits beyond the computer's precision to 0.
-
-   C-Kermit's floating-point functions have names of the form
-   "\ffpxxx(args)" ("\f" for function, "fp" for floating-point), where
-   "xxx" is replaced by the name of the function, such as "sqrt", and
-   "args" is the argument list, consisting of one or two floating-point
-   numbers (depending on the function), and an optional "d" argument that
-   says now many decimal places should be shown in the result. Example:
-
-  \ffpdiv(10,3,1) returns "3.3"
-  \ffpdiv(10,3,2) returns "3.33"
-  \ffpdiv(10,3,3) returns "3.333"
-
-   and so on, up to the precision of the computer. If the decimal-places
-   argument is less than zero, the fractional part of the result is
-   truncated:
-
-  \ffpdiv(10,3,-1) returns "3".
-
-   If the decimal-places argument is 0, or is omitted, C-Kermit returns
-   as many decimal places as are meaningful in the computer's
-   floating-point precision, truncating any extraneous trailing 0's:
-
-  \ffpdiv(10,8) returns "1.25".
-  \ffpdiv(10,4) returns "2.5".
-  \ffpdiv(10,2) returns "5.0".
-  \ffpdiv(10,3) returns "3.333333333333333" (for 16-digit precision).
-
-   There is no way to request that a floating-point function return a
-   decimal point but no decimal places. However, this is easy enough to
-   accomplish in other ways, for example by supplying it outside the
-   function call:
-
-  echo \ffpadd(\%a,\%b,-1).
-
-   Kermit's floating-point functions always round the result for the
-   requested number of decimal places when the "d" argument is given and
-   has a value greater than 0 (see the description of \ffpround() just
-   below).
-
-   Floating-point arguments can be constants in floating-point format or
-   variables whose values are floating-point numbers. If a floating-point
-   argument is omitted, or is a variable with no value, 0.0 is supplied
-   automatically. Example:
-
-  def \%x 999.999
-  undef \%y
-  echo \ffpmin(\%x,\%y)
-  0.0
-
-   Or equivalently:
-
-  echo \ffpmin(999.999)
-  0.0
-
-   The floating-point functions are:
-
-   \ffpround(f1,d)
-          Returns f1 rounded to d decimal places. For this function only,
-          d = 0 (or d omitted) has a special meaning: return the integer
-          part of f1 rounded according to the fractional part. Examples:
-
-  \ffpround(2.74653,-1) returns "2" (fraction truncated, no rounding).
-  \ffpround(2.74653,0)  returns "3" (integer part is rounded).
-  \ffpround(2.74653)    returns "3" (d omitted same as d = 0).
-  \ffpround(2.74653,1)  returns "2.7".
-  \ffpround(2.74653,2)  returns "2.75".
-  \ffpround(2.74653,3)  returns "2.747".
-  \ffpround(2.74653,4)  returns "2.7465", etc.
-
-   \ffpadd(f1,f2,d)
-          Returns the sum of f1 and f2.
-
-   \ffpsubtract(f1,f2,d)
-          Subtracts f2 from f1 and returns the result.
-
-   \ffpmultiply(f1,f2,d)
-          Returns the product of f1 and f2.
-
-   \ffpdivide(f1,f2,d)
-          If f2 is not 0, divides f1 by f2 and returns the quotient.
-          If f2 is 0, a DIVIDE_BY_ZERO error occurs.
-
-   \ffpraise(f1,f2,d)
-          If f1 = 0 and f2 <= 0, or if f1 < 0 and f2 has a fractional
-          part, an ARG_OUT_OF_RANGE error occurs; otherwise f1 raised to
-          the f2 power is returned.
-
-   \ffpsqrt(f1,d)
-          If f1 >= 0, returns the square root of f1; otherwise
-          ARG_OUT_OF_RANGE.
-
-   \ffpabsolute(f1,d)
-          Returns the absolute value of f1 (i.e. f1 without a sign). This
-          is the floating-point analog of \fabsolute(n1).
-
-   \ffpint(f1)
-          Returns the integer part of f1. Equivalent to \ffpround(f1,-1).
-
-   \ffpexp(f1,d)
-          The base of natural logarithms, e (2.718282...), raised to the
-          f1 power.
-
-   \ffplogn(f1,d)
-          The natural logarithm of f1 (the power to which e must be
-          raised to obtain f1).
-
-   \ffplog10(f1,d)
-          The base-10 logarithm of f1 (the power to which 10 must be
-          raised to obtain f1).
-
-   \ffpmodulus(f1,f2,d)
-          If f2 is not 0, the remainder after dividing f1 by f2.
-          If f2 is 0, a DIVIDE_BY_ZERO error occurs.
-          This is the floating-point analog of \fmod(n1,n2).
-
-   \ffpmaximum(f1,f2,d)
-          Returns the maximum of f1 and f2. This is the floating-point
-          analog of \fmax(n1,n2).
-
-   \ffpminimum(f1,f2,d)
-          Returns the minimum of f1 and f2. This is the floating-point
-          analog of \fmin(n1,n2).
-
-   \ffpsine(f1,d)
-          Returns the sine of f1 radians.
-
-   \ffpcosine(f1,d)
-          Returns the cosine of f1 radians.
-
-   \ffptangent(f1,d)
-          Returns the tangent of f1 radians.
-
-   Note that all of these functions can be used with integer arguments.
-   If you want an integer result, specify d = -1 (to truncate) or feed
-   the result to \ffpround(xxx,0) (to round).
-
-   Floating-point numbers (or variables or functions that return them)
-   can be used in Boolean expressions (see [622]Section 7.20.2) that
-   compare numbers:
-
-  = x y
-  != x y
-  < x y
-  > x y
-  <= x y
-  >= x y
-
-   In these examples, x and y can be either integers or floating-point
-   numbers in any combination. In an arithmetic comparison of an integer
-   and a floating-point number, the integer is converted to
-   floating-point before the comparison is made. Examples:
-
-  .\%t = 3.000000000
-  .\%f = 3.141592653
-  .\%i = 3
-
-  if > \%f \%i echo Pi is greater.
-  if = \%t \%i echo "\%i" = "\%t".
-
-   A floating-point number can also be used in:
-
-  IF number command
-
-   where the command is executed if the number is nonzero. If the number
-   is floating-point, the command is not executed if the number is 0.0,
-   and is executed otherwise.
-
-   Floating-point numbers can be sorted using ARRAY SORT /NUMERIC (see
-   [623]Section 7.10.5 ).
-
-   Two floating-point constants are provided:
-
-  \v(math_pi) = Pi (3.141592653...)
-  \v(math_e)  = e, the base of natural logarithms (2.71828...)
-
-   These are given to the computer's precision, e.g. 16 digits. This
-   number itself is available in a variable:
-
-   \v(math_precision)
-          How many significant digits in a floating-point number.
-     _________________________________________________________________
-
-  7.24. Tracing Script Execution
-
-   The TRACE command is handy for debugging scripts.
-
-   TRACE [ { /ON, /OFF } ] [ { ASSIGNMENTS, COMMAND-LEVEL, ALL } ]
-          Selects tracing of the given object.
-
-   Optional switches are /ON and /OFF. If no switch is given, /ON is
-   implied. The trace objects are ASSIGNMENTS, COMMAND-LEVEL, and ALL.
-   The default object is ALL, meaning to select all trace objects
-   (besides ALL). Thus TRACE by itself selects tracing of everything, as
-   does TRACE /ON, and TRACE /OFF turns off all tracing.
-
-   When tracing of ASSIGNMENTS is on, every time the value of any
-   user-defined variable or macro changes, C-Kermit prints one of the
-   following:
-
-   >>> name: "value"
-          The name of the variable or macro followed by the new value in
-          quotes. This includes implicit macro-parameter assignments
-          during macro invocation.
-
-   >>> name: (undef)
-          This indicates that the variable or macro has been undefined.
-
-   <<< name: "value"
-          For RETURN statements: the name of the macro and the return
-          value.
-
-   <<< name: (null)
-          For RETURN statements that include no value or an empty value.
-
-   When tracing of COMMAND-LEVEL is on, C-Kermit prints:
-
-   [n] +F: "name"
-          Whenever a command file is entered, where "n" is the command
-          level (0 = top); the name of the command file is shown in
-          quotes.
-
-   [n] +M: "name"
-          Whenever a macro is entered; "n" is the command level. The name
-          of the macro is shown in quotes.
-
-   [n] -F: "name"
-          Whenever a command file is reentered from below, when a macro
-          or command file that it has invoked has returned.
-
-   [n] -M: "name"
-          Whenever a macro is reentered from below.
-
-   For other debugging tools, see SHOW ARGS, SHOW STACK, SET TAKE, SET
-   MACRO, and of course, ECHO.
-     _________________________________________________________________
-
-  7.25. Compact Substring Notation
-
-   It is often desirable to extract a substring from a string which is
-   stored in a variable, and for this we have the \fsubstring() function,
-   which is used like this:
-
-  define \%a 1234567890
-  echo \fsubstring(\%a,3,4) ; substring from 3rd character length 4
-  3456
-
-   or like this with macro-named variables:
-
-  define string 1234567890
-  echo \fsubstring(\m(string),3,4)
-  3456
-
-   C-Kermit 7.0 adds a pair of alternative compact notations:
-
-\:(variablename[start:length])  <-- Substring of variable's value
-\s(macroname[start:length])     <-- Substring of macro's definition
-
-   These are exactly equivalent to using \fsubstring(), except more
-   compact to write and also faster since evaluation is in one step
-   instead of two.
-
-   The "\:()" notation can be used with any Kermit variable, that is,
-   almost anything that starts with a backslash:
-
-  \:(\%a[2:6])      <-- equivalent to \fsubstring(\%a,2,6)
-  \:(\&x[1][2:6])   <-- equivalent to \fsubstring(\&x[1],2,6)
-  \:(\m(foo)[2:6])  <-- equivalent to \fsubstring(\m(foo),2,6)
-  \:(\v(time)[2:6]) <-- equivalent to \fsubstring(\v(time),2,6)
-  \:(\$(TERM)[2:6]) <-- equivalent to \fsubstring(\$(TERM),2,6)
-  \:(ABCDEFGH[2:6]) <-- equivalent to \fsubstring(ABCDEFGH,2,6)
-
-   Whatever appears between the left parenthesis and the left bracket is
-   evaluated and then the indicated substring of the result is returned.
-
-   The "\s()" notation is the same, except after evaluating the variable,
-   the result is treated as a macro name and is looked up in the macro
-   table. Then the indicated substring of the macro definition is
-   returned. Example:
-
-  define testing abcdefghijklmnopqrstuvwxyz
-  define \%a testing
-
-  \s(testing[2:6])  -->  bcdefg
-  \:(testing[2:6])  -->  esting
-  \:(\%a[2:6])      -->  esting
-  \s(\%a[2:6])      -->  bcdefg
-
-   Note that the following two examples are equivalent:
-
-  \:(\m(foo)[2:6])
-  \s(foo[2:6])
-
-   The first number in the brackets is the 1-based starting position. If
-   it is omitted, or less than 1, it is treated as 1. If it is greater
-   than the length of the string, an empty string is returned.
-
-   The second number is the length of the desired substring. If the
-   second number is omitted, is less than 0, or would be past the end of
-   the string, then "through the end of the string" is assumed. If it is
-   0, the empty string is returned.
-
-   If the brackets are empty or omitted, the original string is returned.
-
-   The starting position and length need not be literal numbers; they can
-   also be variables, functions, arithmetic expressions, or even other
-   \s() or \:() quantities; anything that evaluates to a number, for
-   example:
-
-  \s(block[1025:\fhex2n(\s(block[\%b:\%n+4]))/2])
-
-   Syntactically, \m(name) and \s(name) differ only in that the sequence
-   [*] at the end of the name (where * is any sequence of 0 or more
-   characters) is treated as substring notation in \s(name), but is
-   considered part of the name in \m(name) (to see why, see [624]Section
-   7.10.9).
-     _________________________________________________________________
-
-  7.26. New WAIT Command Options
-
-   The WAIT command has been extended to allow waiting for different
-   kinds of things (formerly it only waited for modem signals). Now it
-   also can wait for file events.
-
-    7.26.1. Waiting for Modem Signals
-
-   The previous syntax:
-
-  WAIT time { CD, DSR, RTS, RI, ... }
-
-   has changed to:
-
-  WAIT time MODEM-SIGNALS { CD, DSR, RTS, RI, ... }
-
-   However, the previous syntax is still accepted. The behavior is the
-   same in either case.
-     _________________________________________________________________
-
-    7.26.2. Waiting for File Events
-
-   The new WAIT option:
-
-  WAIT time FILE { CREATION, DELETION, MODIFICATION } filename
-
-   lets you tell Kermit to wait the given amount of time (or until the
-   given time of day) for a file whose name is filename to be created,
-   deleted, or modified, respectively. The filename may not contain
-   wildcards. If the specified event does not occur within the time
-   limit, or if WAIT CANCELLATION is ON and you interrupt from the
-   keyboard before the time is up, the WAIT command fails. If the event
-   is MODIFICATION and the file does not exist, the command fails.
-   Otherwise, if the given event occurs within the time limit, the
-   command succeeds. Examples:
-
-   WAIT 600 FILE DELETION oofa.tmp
-          Wait up to 10 minutes for file oofa.tmp to disappear.
-
-   WAIT 23:59:59 FILE MOD orders.db
-          Wait until just before midnight for the orders.db file to be
-          changed.
-
-   Example: Suppose you want to have the current copy of /etc/motd on
-   your screen at all times, and you want to hear a bell whenever it
-   changes:
-
-  def \%f /etc/motd                      ; The file of interest.
-  while 1 {                              ; Loop forever...
-      cls                                ; Clear the screen.
-      echo \%f: \v(date) \v(time)...     ; Print 2-line heading...
-      echo
-      if ( not exist \%f ) {             ; If file doesn't exist,
-          echo \%f does not exist...     ; print message,
-          wait 600 file creat \%f        ; and wait for it to appear.
-          continue
-      }
-      beep                               ; Something new - beep.
-      type /head:\v(rows-2) \%f          ; Display the file
-      if fail exit 1 \%f: \ferrstring()  ; (checking for errors).
-      wait 999 file mod \%f              ; Wait for it to change.
-  }
-
-   This notices when the file is created, deleted, or modified, and acts
-   only then (or when you interrupt it with); the time shown in the
-   heading is the time of the most recent event (including when the
-   program started).
-
-   See [625]Section 1.10, where the \v(kbchar) variable is explained.
-   This lets you modify a loop like the one above to also accept
-   single-character commands, which interrupt the WAIT, and dispatch
-   accordingly. For example:
-
-  wait 999 file mod \%f              ; Wait for the file to change.
-  if defined \v(kbchar) {            ; Interrupted from keyboard?
-      switch \v(kbchar) {            ; Handle the keystroke...
-        :q, exit                     ; Q to Quit
-        :h, echo blah blah, break    ; H for Help
-        :default, beep, continue     ; Anything else beep and ignore
-      }
-  }
-
-   This lets you write event-driven applications that wait for up to
-   three events at once: a file or modem event, a timeout, and a
-   keystroke.
-     _________________________________________________________________
-
-  7.27. Relaxed FOR and SWITCH Syntax
-
-   For consistency with the extended IF and WHILE syntax, the FOR and
-   SWITCH control lists may (but need not be) enclosed in parentheses:
-
-  FOR ( \%i 1 \%n 1 ) { command-list... }
-  SWITCH ( \%c ) { command-list... }
-
-   In the FOR command, the increment item can be omitted if the control
-   list is enclosed in parentheses, in which case the increment defaults
-   appropriately to 1 or -1, depending on the values of the first two
-   variables.
-
-   As with IF, the parentheses around the FOR-command control list must
-   be set off by spaces (in the SWITCH command, the spaces are not
-   required since the SWITCH expression is a single arithmetic
-   expression).
-
-   Also, outer braces around the command list are supplied automatically
-   if you omit them, e.g.:
-
-  FOR ( \%i 1 %n 1 ) echo \%i
-     _________________________________________________________________
-
-  8. USING OTHER FILE TRANSFER PROTOCOLS
-
-   In C-Kermit 7.0, alternative protocols can be selected using switches.
-   Switches are described in [626]Section 1.5; the use of
-   protocol-selection switches is described in [627]Section 4.7.1.
-   Example:
-
-  send /binary /protocol:zmodem x.tar.gz
-
-   Note that file transfer recovery works only with Kermit and Zmodem
-   protocols. With Zmodem, recovery can be initiated only by the sender.
-
-   Only pre-1988 versions of the publicly-distributed sz/rz programs use
-   Standard I/O; those released later than that do not use Standard I/O
-   and therefore do not work with REDIRECT. However, Omen Technology does
-   offer an up-to-date redirectable version called crzsz, which must be
-   licensed for use:
-
-     "Unix Crz and Csz support XMODEM, YMODEM, and ZMODEM transfers when
-     called by dial-out programs such as Kermit and certain versions of
-     cu(1). They are clients designed for this use.
-
-     "Crz and Csz are Copyrighted shareware programs. Use of these
-     programs beyond a brief evaluation period requires registration.
-     Please print the "mailer.rz" file, fill out the form and return
-     same with your registration."
-
-   To use the crzsz programs as your external XYZMODEM programs in
-   C-Kermit, follow the instructions in the book, but put a "c" before
-   each command, e.g.:
-
-  set protocol zmodem {csz %s} {csz -a %s} crz crz crz crz
-
-   To use Zmodem protocol over Telnet or other non-transparent
-   connections, you might need to add the -e (Escape) option:
-
-  set protocol zmodem {csz -e %s} {csz -e -a %s} crz crz crz crz
-     _________________________________________________________________
-
-  9. COMMAND-LINE OPTIONS
-
-  9.0. Extended-Format Command-Line Options
-
-   Standard UNIX command line options are a single letter. C-Kermit has
-   run out of letters, so new options are in a new extended format:
-
- --word[:arg]
-
-   where a keyword (rather than a single letter) specifies the function,
-   and if an argument is to be included, it is separated by a colon (or
-   equal sign). Most of the new extended-format command-line options are
-   only for use with the Internet Kermit Service Daemon; see the
-   [628]IKSD Administration Guide for details. However, several of them
-   are also general in nature:
-
-   --nointerrupts
-          Disables keyboard interrupts that are normally enabled, which
-          are usually Ctrl-C (to interrupt a command) and Ctrl-Z (UNIX
-          only, to suspend C-Kermit).
-
-   --help
-          Lists the extended command-line options that are available in
-          your version of C-Kermit. If any options seem to be missing,
-          that is because your copy of C-Kermit was built with
-          compile-time options to deselect them.
-
-   --helpfile:filename
-          Specifies the name of a file to be displayed if the user types
-          HELP (not followed by a specific command or topic), in place of
-          the built-in top-level help text. The file need not fit on one
-          screen; more-prompting is used if the file is more than one
-          screen long if COMMAND MORE-PROMPTING is ON, as it is by
-          default.
-
-   --bannerfile:filename
-          The name of a file containing a message to be printed after the
-          user logs in, in place of the normal message (Copyright notice,
-          "Type HELP or ? for help", "Default transfer mode is...", etc).
-
-   --cdmessage:{on,off,0,1,2}
-          For use in the Server-Side Server configuration; whenever the
-          client tells the server to change directory, the server sends
-          the contents of a "read me" file to the client's screen. This
-          feature is On by default, and operates only in client/server
-          mode when ON or 1. If set to 2 or higher, it also operates when
-          the CD command is given at the IKSD> prompt. Synonym: --cdmsg.
-
-   --cdfile:filename
-          When cdmessage is on, this is the name of the "read me" file to
-          be sent. Normally you would specify a relative (not absolute)
-          name, since the file is opened using the literal name you
-          specified, after changing to the new directory. Example:
-
-  --cdfile:READ.ME
-
-          You can also give a list of up to 8 filenames by (a) enclosing
-          each filename in braces, and (b) enclosing the entire list in
-          braces. Example:
-          --cdfile:{{./.readme}{READ.ME}{aaareadme.txt}{README}{read-this
-          -first}} When a list is given, it is searched from left to
-          right and the first file found is displayed. The default list
-          for UNIX is:
-
-  {{./.readme}{README.TXT}{READ.ME}}
-     _________________________________________________________________
-
-  9.1. Command Line Personalities
-
-   Beginning in version 7.0, if the C-Kermit binary is renamed to
-   "telnet" (or TELNET.EXE, telnet.pr, etc, depending on the platform),
-   it accepts the Telnet command line:
-
-  telnet [ host [ port ] ]
-
-   In Unix, you can achieve the same effect with a symlink:
-
-  cd /usr/bin
-  mv telnet oldtelnet
-  ln -ls /usr/local/bin/kermit telnet
-
-   When installed in this manner, C-Kermit always reads its
-   initialization file. If no host (and therefore no port) is given,
-   C-Kermit starts in interactive prompting mode. If a host is given as
-   the first command-line argument, C-Kermit makes a connection to it.
-   The host argument can be an IP host name or address, or the name of a
-   TCP/IP entry in your C-Kermit network directory.
-
-   If a port is given, it is used. If a port is not given, then if the
-   hostname was found in your network directory and port was also listed
-   there, then that port is used. Otherwise port 23 (the Telnet port) is
-   used.
-
-   When C-Kermit is called "telnet" and it is invoked with a hostname on
-   the command line, it exits automatically when the connection is
-   closed. While the connection is open, however, you may escape back and
-   forth as many times as you like, transfer files, etc.
-
-   An rlogin personality is also available, but it is less useful, at
-   least in UNIX and VMS, where the Rlogin TCP port is privileged.
-
-   The new variable \v(name) indicates the name with which C-Kermit was
-   invoked ("kermit", "wermit", "k95", "telnet", etc).
-     _________________________________________________________________
-
-  9.2. Built-in Help for Command Line Options
-
-   "kermit -h", given from the system prompt, lists as many command-line
-   options as will fit on a standard 24x80 screen. For more comprehensive
-   help, use the interactive HELP OPTIONS command that was added in
-   C-Kermit 7.0:
-
-   HELP OPTIONS
-   Explains how command-line options work, their syntax, etc.
-
-   HELP OPTIONS ALL
-   Lists all command-line options and gives brief help about each one.
-
-   HELP OPTION x
-   Gives brief help about option "x".
-
-   HELP EXTENDED-OPTIONS
-   Lists the available extended-format command-line options.
-
-   HELP EXTENDED-OPTION xxx
-   Gives help for the specified extended option.
-     _________________________________________________________________
-
-  9.3. New Command-Line Options
-
-   Command-line options added since C-Kermit 6.0 are:
-
-   +
-          (plus sign by itself): The next argument is the name of a
-          script to execute; all subsequent arguments are ignored by
-          C-Kermit itself, but passed to the script as top-level copies
-          of \%1, \%2, etc; the \&_[] is also set accordingly. \%0 and
-          \&_[0] become the name of the script file, rather than the
-          pathname of the C-Kermit program, which is its normal value.
-          Primarily for use in the top line of "Kerbang" scripts in UNIX
-          (see [629]Section 7.19). Example from UNIX command line:
-
-  $ kermit [ regular kermit args ] + filename
-
-          Sample first line of Kerbang script:
-
-  #!/usr/local/bin/kermit +
-
-   --
-          (two hyphens surrounded by whitespace) Equivalent to "=", for
-          compatibility with UNIX getopt(1,3).
-
-   -G
-          GET (like -g), but send the incoming file to standard output.
-          Example: "kermit -G oofa.txt | lpr" retrieves a file from your
-          local computer (providing it is running a Kermit program that
-          supports the autodownload feature and has it enabled) and
-          prints it.
-
-   -O
-          equivalent to -x (start up in server mode), but exits after the
-          first client command has been executed (mnemonic: O = Only
-          One). This one is handy replacing "kermit -x" in the
-          "automatically start Kermit on the other end" string:
-
-  set protocol kermit {kermit -ir} {kermit -r} {kermit -x}
-
-          since -x leaves the remote Kermit in server mode after the
-          transfer, which can be confusing, whereas -O makes it go away
-          automatically after the transfer.
-
-   -L
-          Recursive, when used in combination with -s (mnemonic: L =
-          Levels). In UNIX or other environments where the shell expands
-          wildcards itself, the -s argument, if it contains wildcards,
-          must be quoted to prevent this, e.g.:
-
-  kermit -L -s "*.c"
-
-          In UNIX only, "kermit -L -s ." means to send the current
-          directory tree. See [630]Sections 4.10 and [631]4.11 about
-          recursive file transfer.
-
-   -V
-          Equivalent to SET FILE PATTERNS OFF ([632]Section 4.3) and SET
-          TRANSFER MODE MANUAL. In other words, take the FILE TYPE
-          setting literally. For example, "kermit -VT oofa.bin" means
-          send the file in Text mode, no matter what its name is and no
-          matter whether a kindred spirit is recognized at the other end
-          of the connection.
-
-   -0
-          (digit zero) means "be 100% transparent in CONNECT mode". This
-          is equivalent to the following series of commands: SET PARITY
-          NONE, SET COMMAND BYTESIZE 8, SET TERMINAL BYTESIZE 8, SET FLOW
-          NONE, SET TERM ESCAPE DISABLED, SET TERM CHAR TRANSPARENT, SET
-          TERM AUTODOWNLOAD OFF, SET TERM APC OFF, SET TELOPT KERMIT
-          REFUSE REFUSE.
-     _________________________________________________________________
-
-  10. C-KERMIT AND G-KERMIT
-
-   Every multifunctioned and long-lived software program grows in
-   complexity and size over time to meet the needs and requests of its
-   users and the demands of the underlying technology as it changes.
-
-   Eventually users begin to notice how big the application has grown,
-   how much disk space it occupies, how long it takes to load, and they
-   start to long for the good old days when it was lean and mean. Not
-   long after that they begin asking for a "light" version that only does
-   the basics with no frills.
-
-   And so it is with C-Kermit. A "light" version of Kermit was released
-   (for UNIX only) in December 1999 under the GNU General Public License;
-   thus it is called G-Kermit (for GNU Kermit). All it does is send and
-   receive files, period. You can find it at:
-
-  [633]http://www.columbia.edu/kermit/gkermit.html
-
-   Where the C-Kermit 7.0 binary might be anywhere from 1 to 3 million
-   bytes in size, the G-Kermit binary ranges from 30K to 100K, depending
-   on the underlying architecture (RISC vs CISC, etc).
-
-   G-Kermit and C-Kermit may reside side-by-side on the same computer.
-   G-Kermit does not make connections; it does not have a script
-   language; it does not translate character sets. G-Kermit may be used
-   instead of C-Kermit when:
-
-     * It is on the remote end.
-     * Files are to be transferred in binary mode or in text mode without
-       character-set translation.
-     * File timestamps don't need to be preserved.
-
-   In such cases G-Kermit might be preferred since it generally starts up
-   faster, and yet transfers files just as fast on most (but not
-   necessarily all) kinds of connections; for example, it supports
-   streaming ([634]Section 4.20).
-
-   G-Kermit is also handy for bootstrapping. It is easier to load on a
-   new computer than C-Kermit -- it fits on a floppy diskette with plenty
-   of room to spare. Thus if you have (say) an old PC running (say) SCO
-   Xenix and no network connection, you can download the Xenix version of
-   G-Kermit to (say) a DOS or Windows PC, copy it to diskette, read the
-   diskette on Xenix with "dosread", and then use G-Kermit to receive
-   C-Kermit (which does not fit on a diskette). If diskettes aren't an
-   option, other bootstrapping methods are possible too -- see the
-   [635]G-Kermit web page for details.
-     _________________________________________________________________
-
-III. APPENDICES
-
-  III.1. Character Set Tables
-
-    III.1.1. The Hewlett Packard Roman8 Character Set
-
-dec col/row oct hex  description
-160  10/00  240  A0  (Undefined)
-161  10/01  241  A1  A grave
-162  10/02  242  A2  A circumflex
-163  10/03  243  A3  E grave
-164  10/04  244  A4  E circumflex
-165  10/05  245  A5  E diaeresis
-166  10/06  246  A6  I circumflex
-167  10/07  247  A7  I diaeresis
-168  10/08  250  A8  Acute accent
-169  10/09  251  A9  Grave accent
-170  10/10  252  AA  Circumflex accent
-171  10/11  253  AB  Diaeresis
-172  10/12  254  AC  Tilde accent
-173  10/13  255  AD  U grave
-174  10/14  256  AE  U circumflex
-175  10/15  257  AF  Lira symbol
-176  11/00  260  B0  Top bar (macron)
-177  11/01  261  B1  Y acute
-178  11/02  262  B2  y acute
-179  11/03  263  B3  Degree Sign
-180  11/04  264  B4  C cedilla
-181  11/05  265  B5  c cedilla
-182  11/06  266  B6  N tilde
-183  11/07  267  B7  n tilde
-184  11/08  270  B8  Inverted exclamation mark
-185  11/09  271  B9  Inverted question mark
-186  11/10  272  BA  Currency symbol
-187  11/11  273  BB  Pound sterling symbol
-188  11/12  274  BC  Yen symbol
-189  11/13  275  BD  Paragraph
-190  11/14  276  BE  Florin (Guilder) symbol
-191  11/15  277  BF  Cent symbol
-192  12/00  300  C0  a circumflex
-193  12/01  301  C1  e circumflex
-194  12/02  302  C2  o circumflex
-195  12/03  303  C3  u circumflex
-196  12/04  304  C4  a acute
-197  12/05  305  C5  e acute
-198  12/06  306  C6  o acute
-199  12/07  307  C7  u acute
-200  12/08  310  C8  a grave
-201  12/09  311  C9  e grave
-202  12/10  312  CA  o grave
-203  12/11  313  CB  u grave
-204  12/12  314  CC  a diaeresis
-205  12/13  315  CD  e diaeresis
-206  12/14  316  CE  o diaeresis
-207  12/15  317  CF  u diaeresis
-208  13/00  320  D0  A ring
-209  13/01  321  D1  i circumflex
-210  13/02  322  D2  O with stroke
-211  13/03  323  D3  AE digraph
-212  13/04  324  D4  a ring
-213  13/05  325  D5  i acute
-214  13/06  326  D6  o with stroke
-215  13/07  327  D7  ae digraph
-216  13/08  330  D8  A diaeresis
-217  13/09  331  D9  i grave
-218  13/10  332  DA  O diaeresis
-219  13/11  333  DB  U diaeresis
-220  13/12  334  DC  E acute
-221  13/13  335  DD  i diaeresis
-222  13/14  336  DE  German sharp s
-223  13/15  337  DF  O circumflex
-224  14/00  340  E0  A acute
-225  14/01  341  E1  A tilde
-226  14/02  342  E2  a tilde
-227  14/03  343  E3  Icelandic Eth
-228  14/04  344  E4  Icelandic eth
-229  14/05  345  E5  I acute
-230  14/06  346  E6  I grave
-231  14/07  347  E7  O acute
-232  14/08  350  E8  O grave
-233  14/09  351  E9  O tilde
-234  14/10  352  EA  o tilde
-235  14/11  353  EB  S caron
-236  14/12  354  EC  s caron
-237  14/13  355  ED  U acute
-238  14/14  356  EE  Y diaeresis
-239  14/15  357  EF  y diaeresis
-240  15/00  360  F0  Icelandic Thorn
-241  15/01  361  F1  Icelandic thorn
-242  15/02  362  F2  Middle dot
-243  15/03  363  F3  Greek mu
-244  15/04  364  F4  Pilcrow sign
-245  15/05  365  F5  Fraction 3/4
-246  15/06  366  F6  Long dash, horizontal bar
-247  15/07  367  F7  Fraction 1/4
-248  15/08  370  F8  Fraction 1/2
-249  15/09  371  F9  Feminine ordinal
-250  15/10  372  FA  Masculine ordinal
-251  15/11  373  FB  Left guillemot
-252  15/12  374  FC  Solid box
-253  15/13  375  FD  Right guillemot
-254  15/14  376  FE  Plus or minus sign
-255  15/15  377  FF  (Undefined)
-     _________________________________________________________________
-
-    III.1.2. Greek Character Sets
-
-    III.1.2.1. The ISO 8859-7 Latin / Greek Alphabet = ELOT 928
-
-dec col/row oct hex  description
-160  10/00  240  A0  No-break space
-161  10/01  241  A1  Left single quotation mark
-162  10/02  242  A2  right single quotation mark
-163  10/03  243  A3  Pound sign
-164  10/04  244  A4  (UNUSED)
-165  10/05  245  A5  (UNUSED)
-166  10/06  246  A6  Broken bar
-167  10/07  247  A7  Paragraph sign
-168  10/08  250  A8  Diaeresis (Dialytika)
-169  10/09  251  A9  Copyright sign
-170  10/10  252  AA  (UNUSED)
-171  10/11  253  AB  Left angle quotation
-172  10/12  254  AC  Not sign
-173  10/13  255  AD  Soft hyphen
-174  10/14  256  AE  (UNUSED)
-175  10/15  257  AF  Horizontal bar (Parenthetiki pavla)
-176  11/00  260  B0  Degree sign
-177  11/01  261  B1  Plus-minus sign
-178  11/02  262  B2  Superscript two
-179  11/03  263  B3  Superscript three
-180  11/04  264  B4  Accent (tonos)
-181  11/05  265  B5  Diaeresis and accent (Dialytika and Tonos)
-182  11/06  266  B6  Alpha with accent
-183  11/07  267  B7  Middle dot (Ano Teleia)
-184  11/08  270  B8  Epsilon with accent
-185  11/09  271  B9  Eta with accent
-186  11/10  272  BA  Iota with accent
-187  11/11  273  BB  Right angle quotation
-188  11/12  274  BC  Omicron with accent
-189  11/13  275  BD  One half
-190  11/14  276  BE  Upsilon with accent
-191  11/15  277  BF  Omega with accent
-192  12/00  300  C0  iota with diaeresis and accent
-193  12/01  301  C1  Alpha
-194  12/02  302  C2  Beta
-195  12/03  303  C3  Gamma
-196  12/04  304  C4  Delta
-197  12/05  305  C5  Epsilon
-198  12/06  306  C6  Zeta
-199  12/07  307  C7  Eta
-200  12/08  310  C8  Theta
-201  12/09  311  C9  Iota
-202  12/10  312  CA  Kappa
-203  12/11  313  CB  Lamda
-204  12/12  314  CC  Mu
-205  12/13  315  CD  Nu
-206  12/14  316  CE  Ksi
-207  12/15  317  CF  Omicron
-208  13/00  320  D0  Pi
-209  13/01  321  D1  Rho
-210  13/02  322  D2  (UNUSED)
-211  13/03  323  D3  Sigma
-212  13/04  324  D4  Tau
-213  13/05  325  D5  Upsilon
-214  13/06  326  D6  Phi
-215  13/07  327  D7  Khi
-216  13/08  330  D8  Psi
-217  13/09  331  D9  Omega
-218  13/10  332  DA  Iota with diaeresis
-219  13/11  333  DB  Upsilon with diaeresis
-220  13/12  334  DC  alpha with accent
-221  13/13  335  DD  epsilon with accent
-222  13/14  336  DE  eta with accent
-223  13/15  337  DF  iota with accent
-224  14/00  340  E0  upsilon with diaeresis and accent
-225  14/01  341  E1  alpha
-226  14/02  342  E2  beta
-227  14/03  343  E3  gamma
-228  14/04  344  E4  delta
-229  14/05  345  E5  epsilon
-230  14/06  346  E6  zeta
-231  14/07  347  E7  eta
-232  14/08  350  E8  theta
-233  14/09  351  E9  iota
-234  14/10  352  EA  kappa
-235  14/11  353  EB  lamda
-236  14/12  354  EC  mu
-237  14/13  355  ED  nu
-238  14/14  356  EE  ksi
-239  14/15  357  EF  omicron
-240  15/00  360  F0  pi
-241  15/01  361  F1  rho
-242  15/02  362  F2  terminal sigma
-243  15/03  363  F3  sigma
-244  15/04  364  F4  tau
-245  15/05  365  F5  upsilon
-246  15/06  366  F6  phi
-247  15/07  367  F7  khi
-248  15/08  370  F8  psi
-249  15/09  371  F9  omega
-250  15/10  372  FA  iota with diaeresis
-251  15/11  373  FB  upsilon with diaeresis
-252  15/12  374  FC  omicron with diaeresis
-253  15/13  375  FD  upsilon with accent
-254  15/14  376  FE  omega with accent
-255  15/15  377  FF  (UNUSED)
-     _________________________________________________________________
-
-    III.1.2.2. The ELOT 927 Character Set
-
-dec col/row oct hex  description
- 32  02/00   40  20  SPACE
- 33  02/01   41  21  EXCLAMATION MARK
- 34  02/02   42  22  QUOTATION MARK
- 35  02/03   43  23  NUMBER SIGN
- 36  02/04   44  24  DOLLAR SIGN
- 37  02/05   45  25  PERCENT SIGN
- 38  02/06   46  26  AMPERSAND
- 39  02/07   47  27  APOSTROPHE
- 40  02/08   50  28  LEFT PARENTHESIS
- 41  02/09   51  29  RIGHT PARENTHESIS
- 42  02/10   52  2A  ASTERISK
- 43  02/11   53  2B  PLUS SIGN
- 44  02/12   54  2C  COMMA
- 45  02/13   55  2D  HYPHEN, MINUS SIGN
- 46  02/14   56  2E  PERIOD, FULL STOP
- 47  02/15   57  2F  SOLIDUS, SLASH
- 48  03/00   60  30  DIGIT ZERO
- 49  03/01   61  31  DIGIT ONE
- 50  03/02   62  32  DIGIT TWO
- 51  03/03   63  33  DIGIT THREE
- 52  03/04   64  34  DIGIT FOUR
- 53  03/05   65  35  DIGIT FIVE
- 54  03/06   66  36  DIGIT SIX
- 55  03/07   67  37  DIGIT SEVEN
- 56  03/08   70  38  DIGIT EIGHT
- 57  03/09   71  39  DIGIT NINE
- 58  03/10   72  3A  COLON
- 59  03/11   73  3B  SEMICOLON
- 60  03/12   74  3C  LESS-THAN SIGN, LEFT ANGLE BRACKET
- 61  03/13   75  3D  EQUALS SIGN
- 62  03/14   76  3E  GREATER-THAN SIGN, RIGHT ANGLE BRACKET
- 63  03/15   77  3F  QUESTION MARK
- 64  04/00  100  40  COMMERCIAL AT SIGN
- 65  04/01  101  41  CAPITAL LETTER A
- 66  04/02  102  42  CAPITAL LETTER B
- 67  04/03  103  43  CAPITAL LETTER C
- 68  04/04  104  44  CAPITAL LETTER D
- 69  04/05  105  45  CAPITAL LETTER E
- 70  04/06  106  46  CAPITAL LETTER F
- 71  04/07  107  47  CAPITAL LETTER G
- 72  04/08  110  48  CAPITAL LETTER H
- 73  04/09  111  49  CAPITAL LETTER I
- 74  04/10  112  4A  CAPITAL LETTER J
- 75  04/11  113  4B  CAPITAL LETTER K
- 76  04/12  114  4C  CAPITAL LETTER L
- 77  04/13  115  4D  CAPITAL LETTER M
- 78  04/14  116  4E  CAPITAL LETTER N
- 79  04/15  117  4F  CAPITAL LETTER O
- 80  05/00  120  50  CAPITAL LETTER P
- 81  05/01  121  51  CAPITAL LETTER Q
- 82  05/02  122  52  CAPITAL LETTER R
- 83  05/03  123  53  CAPITAL LETTER S
- 84  05/04  124  54  CAPITAL LETTER T
- 85  05/05  125  55  CAPITAL LETTER U
- 86  05/06  126  56  CAPITAL LETTER V
- 87  05/07  127  57  CAPITAL LETTER W
- 88  05/08  130  58  CAPITAL LETTER X
- 89  05/09  131  59  CAPITAL LETTER Y
- 90  05/10  132  5A  CAPITAL LETTER Z
- 91  05/11  133  5B  LEFT SQUARE BRACKET
- 92  05/12  134  5C  REVERSE SOLIDUS, BACKSLASH
- 93  05/13  135  5D  RIGHT SQUARE BRACKET
- 94  05/14  136  5E  CIRCUMFLEX ACCENT
- 95  05/15  137  5F  UNDERSCORE
- 96  06/00  140  60  ACCENT GRAVE
- 97  06/01  141  61  GREEK LETTER ALPHA
- 98  06/02  142  62  GREEK LETTER BETA
- 99  06/03  143  63  GREEK LETTER GAMMA
-100  06/04  144  64  GREEK LETTER DELTA
-101  06/05  145  65  GREEK LETTER EPSILON
-102  06/06  146  66  GREEK LETTER ZETA
-103  06/07  147  67  GREEK LETTER ETA
-104  06/08  150  68  GREEK LETTER THETA
-105  06/09  151  69  GREEK LETTER IOTA
-106  06/10  152  6A  GREEK LETTER KAPPA
-107  06/11  153  6B  GREEK LETTER LAMDA
-108  06/12  154  6C  GREEK LETTER MU
-109  06/13  155  6D  GREEK LETTER NU
-110  06/14  156  6E  GREEK LETTER KSI
-111  06/15  157  6F  GREEK LETTER OMICRON
-112  07/00  160  70  GREEK LETTER PI
-113  07/01  161  71  GREEK LETTER RHO
-114  07/02  162  72  GREEK LETTER SIGMA
-115  07/03  163  73  GREEK LETTER TAU
-116  07/04  164  74  GREEK LETTER UPSILON
-117  07/05  165  75  GREEK LETTER FI
-118  07/06  166  76  GREEK LETTER XI
-119  07/07  167  77  GREEK LETTER PSI
-120  07/08  170  78  GREEK LETTER OMEGA
-121  07/09  171  79  SPACE
-122  07/10  172  7A  SPACE
-123  07/11  173  7B  LEFT CURLY BRACKET, LEFT BRACE
-124  07/12  174  7C  VERTICAL LINE, VERTICAL BAR
-125  07/13  175  7D  RIGHT CURLY BRACKET, RIGHT BRACE
-126  07/14  176  7E  TILDE
-127  07/15  177  7F  RUBOUT, DELETE
-     _________________________________________________________________
-
-    III.1.2.3. PC Code Page 869
-
-   (to be filled in...)
-     _________________________________________________________________
-
-    III.2. Updated Country Codes
-
-   Date: Mon, 7 Apr 1997 23:23:49 EDT
-   From: Dave Leibold <dleibold@else.net>
-   Newsgroups: comp.dcom.telecom
-   Subject: Ex-USSR Country Codes Profile
-   Organization: TELECOM Digest
-
-   Ex-USSR Country Codes Profile
-   4 April 1997
-
-   Below is a summary of the country codes that have formed in the wake
-   of the USSR dissolution, along with some updated findings and reports.
-   Additional or corrected information on any of these nations would be
-   welcome (c/o dleibold@else.net).
-     * Kyrgyz Republic country code 996 will take effect, at least in
-       Canada, effective 1 May 1997, according to CRTC Telecom Order
-       97-464, based on Stentor Tariff Notice 433. There is no indication
-       whether there will be a permissive dialing period involved or for
-       how long such a permissive operation would remain.
-     * Country code 992 was reported as a recent assignment for
-       Tajikistan, which will be moving from country code 7 at some
-       unknown time.
-     * Uzbekistan has its own country code assignment, but I have no
-       information if this is in service yet or what implementation dates
-       have been set.
-     * Kazakstan does not have a known separate country code assignment
-       at present. It remains in country code 7 for the time being.
-     * Russia seems destined to keep country code 7.
-     * Recent news reports speak of some agreements forming between
-       Russia and Belarus. While there is no outright reunification yet,
-       there is expected to be much closer ties between the two nations.
-       Whether this will lead to a reunification of telephone codes
-       remains to be seen.
-
-   In the table, "Effective" means the date at which the country code
-   began service (which could vary according to the nation). "Mandatory"
-   means the date at which the country code 7 is invalid for calls to
-   that nation. There are a number of question marks since exact dates
-   have not been collected in all cases.
-
-CC  Nation            Effective     Mandatory    Notes
-
-370 Lithuania         1993?         ???          Announced Jan 1993
-371 Latvia            1993?         ???
-372 Estonia           1 Feb 1993?   March 1993?
-373 Moldova           1993?         ???          Announced Jan 1993
-374 Armenia           1 May 1995    1 July 1995  Announced Jan 1995 (ITU)
-375 Belarus           16 Apr 1995   1997?
-380 Ukraine           16 Apr 1995   Oct 1995?
-7   Kazakstan         (no known changes)
-7   Russia            (presumably not changing)
-992 Tajikistan        ???           ???          Announced 1996-7?
-993 Turkmenistan      3 Jan 1997    3 Apr 1997   Canada as of 29 Nov 1996
-994 Azerbaijan        Sept 1994?    ???          Announced 1992
-995 Georgia           1994?         ???          ref: Telecom Digest Oct 1994
-996 Kyrgyz Republic   1 May 1997    ???          ref: Stentor Canada/CRTC
-998 Uzbekistan        ???           ???          Announced 1996? (ITU)
-
-   Details courtesy Toby Nixon, ITU, Stentor (Canada), CRTC (Canada),
-   TELECOM Digest (including information collected for the country code
-   listings).
-     _________________________________________________________________
-
-IV. ERRATA & CORRIGENDA
-
-   The following errors in [636]Using C-Kermit, Second Edition, first
-   printing, have been noted.
-
-   First, some missing acknowledgements for C-Kermit 6.0: JE Jones of
-   Microware for help with OS-9, Nigel Roles for his help with Plan 9,
-   Lucas Hart for help with VMS and Digital UNIX, Igor Kovalenko for his
-   help with QNX. And later, to Susan Kleinmann for her help with Debian
-   Linux packaging; Patrick Volkerding for his help with Slackware Linux
-   packaging; Jim Knoble for his help with Red Hat Linux packaging; and
-   to dozens of others for sending individual C-Kermit binaries for
-   varied and diverse platforms.
-
-   Thanks to James Spath for both binaries and reporting many of the
-   typos noted below. Also to Dat Thuc Nguyen for spotting several typos.
-
-PAGE    REMARKS
-COVER   "COS" is a misprint.  There is no COS.  Pretend it says "SCO" or "VOS".
-        (This is fixed in the second printing.)
- xxi    Second line: Fred Smith's affiliation should be Computrition.
- 83     Change "commands other" to "commands as other" (1st paragraph)
- 87     Change "The the" to "The" (2nd paragraph)
- 92     "set modem-type user-defined supra" should be "set modem type ..."
- 95     Change "VI" to "vi" (1st paragraph)
- 96     Change "it it" to "it is" (1st paragraph)
- 97     Change "advantage a literal" to "advantage of a literal" (2nd
-        paragraph)
-102     The call-waiting example would be better as SET DIAL PREFIX *70W
-        (rather than "*70,") because the former will not cause an incorrect
-        call to be placed with pulse dialing.
-123     Third paragraph from bottom: "..otherwise if a your local username.."
-        should be "..otherwise your local username..".
-160     Delete the "it" between "and" and "to" (2nd paragraph)
-185     In "When TRANSFER DISPLAY is OFF, C-Kermit skips the display...",
-        "OFF" should be "NONE".
-187     The last paragraph says the "A command" is ignored, should be "S".
-194     Change "it known" to "it is known" (4th paragraph).
-235     In C-Kermit 7.0, the syntax of the GET command changed.  MGET now
-        must be used to get a list of files and there is no more multiline
-        GET command.
-268     Last paragraph: "effect" should be "affect".
-275     In the SET PROTOCOL KERMIT description, the following sentence is
-        incorrect and should be removed: 'If you omit the commands, the
-        default ones are restored: "kermit -ir" and "kermit -r" respectively".
-        The correct information is given at the bottom of page 281.
-279     9th line.  The decimal value of ST is 156, not 155.
-295     In the stepping stones, skip ahead to Chapter 17 on p. 327.
-298     Table 16-2, Portuguese entry.  Column 4/00 should show section sign,
-        not acute accent.
-316     Other languages written in the Hebrew alphabet include Karaim (a Turkic
-        language spoken in Lithuania and Poland), Judeo-Kurdish, and Judeo-
-        Georgian.
-332     UNDEFINE definition, change "This just" to "This is just".
-344     It might be necessary to set the modem's pulse generation rate when
-        sending numeric pages; most Hayes compatible modems use the S11
-        register for this.
-350     Delete "is" from between "It" and "ceases" (4th paragraph)
-351     Top - both occurrences of "print \%a" should be "echo \%a".
-364     \v(input) and \v(query) out of alphabetical order.
-378     In the MYSEND macro, "if not \m(rc) goto bad" should be:
-        "if \m(rc) goto bad" (remove the "not").
-382-383 It should be stated that the loop control variable must be of the \%a
-        type, or else an array element; macro names can not be used for this.
-383     In line 3, "\%f[\%i]" should be "\&f[\%i]".
-383     In the sort example, it should be stated that the array is 1-based.
-387     Change "You can list" to "You can get a list" (5th paragraph)
-393     \Fverify() description.  The 3rd sentence could be stated more clearly
-        as "If all characters in string2 are also in string1, 0 is returned."
-398     Copying \ffiles() results to an array before is not required as of
-        C-Kermit 7.0 (see [637]Section 7.3).
-403     In "(\%a + 3) * (\%b  5)", a minus sign is missing between b and 5.
-407     C-Kermit 7.0 no longer supports multiline GET.  Change
-        "get, \%1, \%2" to "get {\%1} {\%2}" or "get /as:{\%2} {\%1}".
-409     READ example while loop should be:
-        while success { echo \m(line), read line }
-409     "WRITE file" should be "WRITE keyword" (you can't put a filename there)
-        (The same applies to WRITE-LINE / WRITELN).
-414     \Funhexify() missing from Table 18-3.
-425     MINPUT definition, change 2nd "text2" to "text3".
-436     Several lines are missing from the UNIXLOGIN macro listing.
-        After the "xif fail" block, insert:
-
-          out \%1\13                    ; Send username, carriage return
-          inp 5 Password:               ; Wait 5 sec for this prompt
-          if fail end 1 No password prompt
-          pause                         ; Wait a sec
-          out \%2\13                    ; Send password
-
-440     Change "set terminal byteszie" to "set terminal bytesize".
-        Change "input Password:" to "input 10 Password".
-448     Franchise script: "access line" should be "access \m(line)".
-453     There are two incorrectly coded IF statements in the DELIVER macro
-        definition.  Replace both occurrences of "if > \%1 \%3 {" with
-        "xif > \%i \%3 {" (replace "if" by "xif" and "\%1" with "\%i").
-453     "the the" (last paragraph) should be "the".
-454     EOT (last paragraph) is End of Transmission, not End of Text.
-457     _DEFINE definition: "name constructed" should be "name is constructed".
-457     "macro for and" (last paragraph) should be "macro and".
-459     Should explain that \v(user) is a legal abbreviation of \v(userid).
-480     Figure II-2 is backwards; the least-significant bit is transmitted
-        first, then up to the highest, and the parity bit last.
-534     The VMS Appendix section on Odd Record Lengths no longer applies;
-        C-Kermit 7.0 handles odd record lengths as well as even ones.
-559     Table VIII-3, Portuguese entry.  Column 4/00 should show section sign,
-        not acute accent.
-560-563 HP-Roman8 missing from Table VII-4; there wasn't room to squeeze it in.
-        It is listed in section II(6).
-565     "d stroke" in Table VII-5 has the wrong appearance; the stem should
-        be upright.  The letter shown in the table is actually a lowercase
-        Icelandic eth, which has a curved stem.
-601-604 BeBox, BeOS, Plan 9, and probably others not listed in trademarks.
-604     The words "SCRIBE TEXT FORMATTER" appear at the end of the last
-        sentence of the first paragraph of the Colophon.  They should have
-        been in the Index.
-Index:  Missing entries: SET { SEND, RECEIVE } PATHNAMES, Call waiting, ...
-        \F()            Page 605, add also 413-414
-        \Fbreak         389
-        \Fcapitalize    390
-        \Fchecksum      414
-        \Fcrc16         414
-        \Fexecute       414
-        \Fhexify        390
-        \Fltrim         391
-        \Frepeat        392
-        \Fspawn         392
-        \Ftod2secs      399
-        \v() built_in   Page 606, add also 361-364
-        \v(_line)       354, 361
-        \v(apcactive)   361
-        \v(charset)     362
-        \v(cpu)         362
-        \v(crc16)       357, 362
-        \v(d$xxx)       add page 362
-        \v(dialnumber)  362
-        \v(dialresult)  362
-        \v(errno)       362
-        \v(errstring)   362
-        \v(exedir)      362
-        \v(inidir)      363
-        \v(ipaddress)   363
-        \v(keyboard)    363
-        \v(macro)       363
-        \v(minput)      363
-        \v(m_xxx)       94, 363
-        \v(password)    364
-        \v(query)       364
-        \v(prompt)      364
-        \v(speed)       356, 364
-        \v(startup)     364
-        \v(status)      364
-        \v(sysid)       364
-        \v(system)      364
-        \v(fsize)       at lower half page 606 should read \v(tfsize)
-        \v(xversion)    364
-        BEEP Command    40
-        SET FLOW        62, 212
-
-   Figure II-5 on page 493. The pin assignments of the Mini Din-8
-   connector are not described anywhere. As noted in the text, these tend
-   to vary from vendor to vendor. One common arrangement is:
-
-  1. HSKout (Handshake out -- definition depends on software)
-  2. HSKin  (Handshake in or external clock)
-  3. TxD-
-  4. Not used
-  5. RxD-
-  6. TxD+
-  7. Not used
-  8. RxD+
-
-   Note the "balanced pairs" for Receive Data (RxD) and Transmit Data
-   (TxD), and the utter lack of modem signals. These connectors follow
-   the RS-423 standard, rather than RS-232. In some arrangements, Pin 1
-   is used for DTR and Pin 2 for CD; in others Pin 1 is RTS and Pin 2 is
-   CTS.
-
-   Please send reports of other errors to the authors, as well as
-   suggestions for improvements, additional index entries, and any other
-   comments:
-
-   [638]kermit@columbia.edu
-     _________________________________________________________________
-
-APPENDIX V. ADDITIONAL COPYRIGHT NOTICES
-
-   The following copyrights cover some of the source code used in the
-   development of C-Kermit, Kermit 95, or Kermit 95 support libraries.
-
-/*****************************************************************************/
-/*                                                                           */
-/*              Copyright (c) 1995 by Oy Online Solutions Ltd.               */
-/*                                                                           */
-/*   Distribution of this source code is strictly forbbidden. Use of this    */
-/*   source code is granted to the University of Columbia C-Kermit project   */
-/*   to be distributed in binary format only. Please familiarize yourself    */
-/*   with the accompanying LICENSE.P file.                                   */
-/*                                                                           */
-/*****************************************************************************/
-
-   used for Xmodem, Ymodem, and Zmodem protocol in Kermit 95 (p95.dll,
-   p2.dll)
-     _________________________________________________________________
-
-   Copyright (c) 1997 Stanford University
-
-   The use of this software for revenue-generating purposes may require a
-   license from the owners of the underlying intellectual property.
-   Specifically, the SRP-3 protocol may not be used for
-   revenue-generating purposes without a license.
-
-   Within that constraint, permission to use, copy, modify, and
-   distribute this software and its documentation for any purpose is
-   hereby granted without fee, provided that the above copyright notices
-   and this permission notice appear in all copies of the software and
-   related documentation.
-
-   THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
-   EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
-   WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
-
-   IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
-   INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT
-   ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY,
-   ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-   SOFTWARE.
-
-   Used for Secure Remote Password (TM) protocol (SRP) in C-Kermit,
-   Kermit 95 (k95.exe, k2.exe, k95crypt.dll, k2crypt.dll)
-     _________________________________________________________________
-
-   Copyright 1990 by the Massachusetts Institute of Technology. All
-   Rights Reserved.
-
-   Export of this software from the United States of America may require
-   a specific license from the United States Government. It is the
-   responsibility of any person or organization contemplating export to
-   obtain such a license before exporting.
-
-   WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
-   distribute this software and its documentation for any purpose and
-   without fee is hereby granted, provided that the above copyright
-   notice appear in all copies and that both that copyright notice and
-   this permission notice appear in supporting documentation, and that
-   the name of M.I.T. not be used in advertising or publicity pertaining
-   to distribution of the software without specific, written prior
-   permission. M.I.T. makes no representations about the suitability of
-   this software for any purpose. It is provided "as is" without express
-   or implied warranty.
-
-   Used for Telnet Authentication Option, Telnet Encryption Option, and
-   Kerberos (TM) authentication in C-Kermit, Kermit 95 (k95.exe, k2.exe,
-   k95crypt.dll, k2crypt.dll)
-     _________________________________________________________________
-
-   Copyright (c) 1991, 1993 The Regents of the University of California.
-   All rights reserved.
-
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions are
-   met:
-    1. Redistributions of source code must retain the above copyright
-       notice, this list of conditions and the following disclaimer.
-    2. Redistributions in binary form must reproduce the above copyright
-       notice, this list of conditions and the following disclaimer in
-       the documentation and/or other materials provided with the
-       distribution.
-    3. All advertising materials mentioning features or use of this
-       software must display the following acknowledgement:
-
-     This product includes software developed by the University of
-     California, Berkeley and its contributors.
-    4. Neither the name of the University nor the names of its
-       contributors may be used to endorse or promote products derived
-       from this software without specific prior written permission.
-
-   THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
-   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-   THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-   PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS
-   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-   OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-   Used for Telnet Authentication Option, Telnet Encryption Option, and
-   Kerberos (TM) authentication in C-Kermit, Kermit 95 (k95.exe, k2.exe,
-   k95crypt.dll, k2crypt.dll)
-     _________________________________________________________________
-
-   Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) All rights
-   reserved.
-
-   This package is an DES implementation written by Eric Young
-   (eay@cryptsoft.com). The implementation was written so as to conform
-   with MIT's libdes.
-
-   This library is free for commercial and non-commercial use as long as
-   the following conditions are aheared to. The following conditions
-   apply to all code found in this distribution.
-
-   Copyright remains Eric Young's, and as such any Copyright notices in
-   the code are not to be removed. If this package is used in a product,
-   Eric Young should be given attribution as the author of that the SSL
-   library. This can be in the form of a textual message at program
-   startup or in documentation (online or textual) provided with the
-   package.
-
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions are
-   met:
-    1. Redistributions of source code must retain the copyright notice,
-       this list of conditions and the following disclaimer.
-    2. Redistributions in binary form must reproduce the above copyright
-       notice, this list of conditions and the following disclaimer in
-       the documentation and/or other materials provided with the
-       distribution.
-    3. All advertising materials mentioning features or use of this
-       software must display the following acknowledgement: This product
-       includes software developed by Eric Young (eay@cryptsoft.com)
-
-   THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND ANY EXPRESS OR
-   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-   DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
-   ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
-   IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-   The license and distribution terms for any publically available
-   version or derivative of this code cannot be changed. i.e. this code
-   cannot simply be copied and put under another distrubution license
-   [including the GNU Public License.]
-
-   The reason behind this being stated in this direct manner is past
-   experience in code simply being copied and the attribution removed
-   from it and then being distributed as part of other packages. This
-   implementation was a non-trivial and unpaid effort.
-
-   Used DES encryption in Kermit 95 (k95crypt.dll, k2crypt.dll)
-     _________________________________________________________________
-
- * This is version 1.1 of CryptoLib
- *
- * The authors of this software are Jack Lacy, Don Mitchell and Matt Blaze
- *              Copyright (c) 1991, 1992, 1993, 1994, 1995 by AT&T.
- * Permission to use, copy, and modify this software without fee
- * is hereby granted, provided that this entire notice is included in
- * all copies of any software which is or includes a copy or
- * modification of this software and in all copies of the supporting
- * documentation for such software.
- *
- * NOTE:
- * Some of the algorithms in cryptolib may be covered by patents.
- * It is the responsibility of the user to ensure that any required
- * licenses are obtained.
- *
- *
- * SOME PARTS OF CRYPTOLIB MAY BE RESTRICTED UNDER UNITED STATES EXPORT
- * REGULATIONS.
- *
- *
- * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY
- * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
- * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
-
-   Used for Big Number library in Kermit 95 (k95crypt.dll, k2crypt.dll).
-
-   [ [639]Top ] [ [640]C-Kermit ] [ [641]Kermit Home ]
-     _________________________________________________________________
-
-   CKERMIT70.HTM / The Kermit Project / Columbia University / 8 Feb 2000
-
-References
-
-   1. http://www.columbia.edu/kermit/ckermit70.html#contents
-   2. http://www.columbia.edu/kermit/ckermit.html
-   3. http://www.columbia.edu/kermit/index.htm
-   4. mailto:kermit-support@columbia.edu
-   5. http://www.columbia.edu/kermit/
-   6. http://www.kermit-project.org/
-   7. http://www.columbia.nyc.ny.us/kermit/
-   8. ftp://kermit.columbia.edu/kermit/f/COPYING.TXT
-   9. ftp://kermit.columbia.edu/kermit/f/ckcmai.c
-  10. http://www.columbia.edu/kermit/ckermit70.html#xv
-  11. http://www.columbia.edu/kermit/ckb2.htm
-  12. ftp://kermit.columbia.edu/kermit/f/ckcbwr.txt
-  13. ftp://kermit.columbia.edu/kermit/f/ckubwr.txt
-  14. ftp://kermit.columbia.edu/kermit/f/ckvbwr.txt
-  15. ftp://kermit.columbia.edu/kermit/f/ckubwr.txt
-  16. ftp://kermit.columbia.edu/kermit/f/ckermit70.txt
-  17. ftp://kermit.columbia.edu/kermit/f/security.txt
-  18. http://www.columbia.edu/kermit/security.htm
-  19. ftp://kermit.columbia.edu/kermit/f/iksd.txt
-  20. http://www.columbia.edu/kermit/iksd.htm
-  21. http://www.columbia.edu/kermit/cuiksd.htm
-  22. ftp://kermit.columbia.edu/kermit/f/telnet.txt
-  23. http://www.columbia.edu/kermit/telnet.htm
-  24. ftp://kermit.columbia.edu/kermit/f/COPYING.TXT
-  25. http://www.columbia.edu/kermit/k95.html
-  26. http://www.opensource.org/
-  27. http://www.columbia.edu/kermit/ckb2.htm
-  28. http://www.columbia.edu/kermit/ckermit70.html#xi
-  29. http://www.columbia.edu/kermit/ckermit70.html#xii
-  30. http://www.columbia.edu/kermit/ckermit70.html#x0
-  31. http://www.columbia.edu/kermit/ckermit70.html#x1
-  32. http://www.columbia.edu/kermit/ckermit70.html#x1.0
-  33. http://www.columbia.edu/kermit/ckermit70.html#x1.1
-  34. http://www.columbia.edu/kermit/ckermit70.html#x1.2
-  35. http://www.columbia.edu/kermit/ckermit70.html#x1.3
-  36. http://www.columbia.edu/kermit/ckermit70.html#x1.4
-  37. http://www.columbia.edu/kermit/ckermit70.html#x1.5
-  38. http://www.columbia.edu/kermit/ckermit70.html#x1.5.1
-  39. http://www.columbia.edu/kermit/ckermit70.html#x1.5.2
-  40. http://www.columbia.edu/kermit/ckermit70.html#x1.5.3
-  41. http://www.columbia.edu/kermit/ckermit70.html#x1.5.4
-  42. http://www.columbia.edu/kermit/ckermit70.html#x1.5.5
-  43. http://www.columbia.edu/kermit/ckermit70.html#x1.6
-  44. http://www.columbia.edu/kermit/ckermit70.html#x1.7
-  45. http://www.columbia.edu/kermit/ckermit70.html#x1.8
-  46. http://www.columbia.edu/kermit/ckermit70.html#x1.9
-  47. http://www.columbia.edu/kermit/ckermit70.html#x1.10
-  48. http://www.columbia.edu/kermit/ckermit70.html#x1.11
-  49. http://www.columbia.edu/kermit/ckermit70.html#x1.11.1
-  50. http://www.columbia.edu/kermit/ckermit70.html#x1.11.2
-  51. http://www.columbia.edu/kermit/ckermit70.html#x1.11.3
-  52. http://www.columbia.edu/kermit/ckermit70.html#x1.11.4
-  53. http://www.columbia.edu/kermit/ckermit70.html#x1.11.5
-  54. http://www.columbia.edu/kermit/ckermit70.html#x1.11.6
-  55. http://www.columbia.edu/kermit/ckermit70.html#x1.11.7
-  56. http://www.columbia.edu/kermit/ckermit70.html#x1.12
-  57. http://www.columbia.edu/kermit/ckermit70.html#x1.13
-  58. http://www.columbia.edu/kermit/ckermit70.html#x1.14
-  59. http://www.columbia.edu/kermit/ckermit70.html#x1.15
-  60. http://www.columbia.edu/kermit/ckermit70.html#x1.16
-  61. http://www.columbia.edu/kermit/ckermit70.html#x1.17
-  62. http://www.columbia.edu/kermit/ckermit70.html#x1.18
-  63. http://www.columbia.edu/kermit/ckermit70.html#x1.19
-  64. http://www.columbia.edu/kermit/ckermit70.html#x1.20
-  65. http://www.columbia.edu/kermit/ckermit70.html#x1.21
-  66. http://www.columbia.edu/kermit/ckermit70.html#x1.22
-  67. http://www.columbia.edu/kermit/ckermit70.html#x1.22.1
-  68. http://www.columbia.edu/kermit/ckermit70.html#x1.22.2
-  69. http://www.columbia.edu/kermit/ckermit70.html#x1.22.3
-  70. http://www.columbia.edu/kermit/ckermit70.html#x1.22.4
-  71. http://www.columbia.edu/kermit/ckermit70.html#x1.22.5
-  72. http://www.columbia.edu/kermit/ckermit70.html#x1.22.6
-  73. http://www.columbia.edu/kermit/ckermit70.html#x1.22.7
-  74. http://www.columbia.edu/kermit/ckermit70.html#x1.22.8
-  75. http://www.columbia.edu/kermit/ckermit70.html#x1.23
-  76. http://www.columbia.edu/kermit/ckermit70.html#x1.24
-  77. http://www.columbia.edu/kermit/ckermit70.html#x2
-  78. http://www.columbia.edu/kermit/ckermit70.html#x2.0
-  79. http://www.columbia.edu/kermit/ckermit70.html#x2.1
-  80. http://www.columbia.edu/kermit/ckermit70.html#x2.1.1
-  81. http://www.columbia.edu/kermit/ckermit70.html#x2.1.2
-  82. http://www.columbia.edu/kermit/ckermit70.html#x2.1.3
-  83. http://www.columbia.edu/kermit/ckermit70.html#x2.1.4
-  84. http://www.columbia.edu/kermit/ckermit70.html#x2.1.5
-  85. http://www.columbia.edu/kermit/ckermit70.html#x2.1.6
-  86. http://www.columbia.edu/kermit/ckermit70.html#x2.1.7
-  87. http://www.columbia.edu/kermit/ckermit70.html#x2.1.8
-  88. http://www.columbia.edu/kermit/ckermit70.html#x2.1.9
-  89. http://www.columbia.edu/kermit/ckermit70.html#x2.1.10
-  90. http://www.columbia.edu/kermit/ckermit70.html#x2.1.11
-  91. http://www.columbia.edu/kermit/ckermit70.html#x2.1.12
-  92. http://www.columbia.edu/kermit/ckermit70.html#x2.1.13
-  93. http://www.columbia.edu/kermit/ckermit70.html#x2.1.14
-  94. http://www.columbia.edu/kermit/ckermit70.html#x2.1.15
-  95. http://www.columbia.edu/kermit/ckermit70.html#x2.1.16
-  96. http://www.columbia.edu/kermit/ckermit70.html#x2.2
-  97. http://www.columbia.edu/kermit/ckermit70.html#x2.2.1
-  98. http://www.columbia.edu/kermit/ckermit70.html#x2.2.2
-  99. http://www.columbia.edu/kermit/ckermit70.html#x2.3
- 100. http://www.columbia.edu/kermit/ckermit70.html#x2.3.0
- 101. http://www.columbia.edu/kermit/ckermit70.html#x2.3.1
- 102. http://www.columbia.edu/kermit/ckermit70.html#x2.3.2
- 103. http://www.columbia.edu/kermit/ckermit70.html#x2.3.3
- 104. http://www.columbia.edu/kermit/ckermit70.html#x2.3.4
- 105. http://www.columbia.edu/kermit/ckermit70.html#x2.3.5
- 106. http://www.columbia.edu/kermit/ckermit70.html#x2.3.6
- 107. http://www.columbia.edu/kermit/ckermit70.html#x2.4
- 108. http://www.columbia.edu/kermit/ckermit70.html#x2.5
- 109. http://www.columbia.edu/kermit/ckermit70.html#x2.6
- 110. http://www.columbia.edu/kermit/ckermit70.html#x2.7
- 111. http://www.columbia.edu/kermit/ckermit70.html#x2.7.0
- 112. http://www.columbia.edu/kermit/ckermit70.html#x2.7.1
- 113. http://www.columbia.edu/kermit/ckermit70.html#x2.7.2
- 114. http://www.columbia.edu/kermit/ckermit70.html#x2.7.3
- 115. http://www.columbia.edu/kermit/ckermit70.html#x2.7.4
- 116. http://www.columbia.edu/kermit/ckermit70.html#x2.7.4.1
- 117. http://www.columbia.edu/kermit/ckermit70.html#x2.7.4.2
- 118. http://www.columbia.edu/kermit/ckermit70.html#x2.7.4.3
- 119. http://www.columbia.edu/kermit/ckermit70.html#x2.7.4.4
- 120. http://www.columbia.edu/kermit/ckermit70.html#x2.7.4.5
- 121. http://www.columbia.edu/kermit/ckermit70.html#x2.8
- 122. http://www.columbia.edu/kermit/ckermit70.html#x2.9
- 123. http://www.columbia.edu/kermit/ckermit70.html#x2.9.1
- 124. http://www.columbia.edu/kermit/ckermit70.html#x2.9.2
- 125. http://www.columbia.edu/kermit/ckermit70.html#x2.10
- 126. http://www.columbia.edu/kermit/ckermit70.html#x2.11
- 127. http://www.columbia.edu/kermit/ckermit70.html#x2.12
- 128. http://www.columbia.edu/kermit/ckermit70.html#x2.13
- 129. http://www.columbia.edu/kermit/ckermit70.html#x2.14
- 130. http://www.columbia.edu/kermit/ckermit70.html#x2.15
- 131. http://www.columbia.edu/kermit/ckermit70.html#x3
- 132. http://www.columbia.edu/kermit/ckermit70.html#x3.1
- 133. http://www.columbia.edu/kermit/ckermit70.html#x3.2
- 134. http://www.columbia.edu/kermit/ckermit70.html#x3.3
- 135. http://www.columbia.edu/kermit/ckermit70.html#x3.4
- 136. http://www.columbia.edu/kermit/ckermit70.html#x4
- 137. http://www.columbia.edu/kermit/ckermit70.html#x4.0
- 138. http://www.columbia.edu/kermit/ckermit70.html#x4.1
- 139. http://www.columbia.edu/kermit/ckermit70.html#x4.1.1
- 140. http://www.columbia.edu/kermit/ckermit70.html#x4.1.2
- 141. http://www.columbia.edu/kermit/ckermit70.html#x4.1.3
- 142. http://www.columbia.edu/kermit/ckermit70.html#x4.2
- 143. http://www.columbia.edu/kermit/ckermit70.html#x4.2.1
- 144. http://www.columbia.edu/kermit/ckermit70.html#x4.2.1.1
- 145. http://www.columbia.edu/kermit/ckermit70.html#x4.2.1.2
- 146. http://www.columbia.edu/kermit/ckermit70.html#x4.2.1.3
- 147. http://www.columbia.edu/kermit/ckermit70.html#x4.2.2
- 148. http://www.columbia.edu/kermit/ckermit70.html#x4.2.2.1
- 149. http://www.columbia.edu/kermit/ckermit70.html#x4.2.2.2
- 150. http://www.columbia.edu/kermit/ckermit70.html#x4.2.3
- 151. http://www.columbia.edu/kermit/ckermit70.html#x4.2.3.1
- 152. http://www.columbia.edu/kermit/ckermit70.html#x4.2.3.2
- 153. http://www.columbia.edu/kermit/ckermit70.html#x4.2.4
- 154. http://www.columbia.edu/kermit/ckermit70.html#x4.2.5
- 155. http://www.columbia.edu/kermit/ckermit70.html#x4.2.6
- 156. http://www.columbia.edu/kermit/ckermit70.html#x4.2.7
- 157. http://www.columbia.edu/kermit/ckermit70.html#x4.2.8
- 158. http://www.columbia.edu/kermit/ckermit70.html#x4.2.8.1
- 159. http://www.columbia.edu/kermit/ckermit70.html#x4.2.8.2
- 160. http://www.columbia.edu/kermit/ckermit70.html#x4.2.8.3
- 161. http://www.columbia.edu/kermit/ckermit70.html#x4.2.8.4
- 162. http://www.columbia.edu/kermit/ckermit70.html#x4.3
- 163. http://www.columbia.edu/kermit/ckermit70.html#x4.3.1
- 164. http://www.columbia.edu/kermit/ckermit70.html#x4.3.2
- 165. http://www.columbia.edu/kermit/ckermit70.html#x4.3.3
- 166. http://www.columbia.edu/kermit/ckermit70.html#x4.3.4
- 167. http://www.columbia.edu/kermit/ckermit70.html#x4.4
- 168. http://www.columbia.edu/kermit/ckermit70.html#x4.4.1
- 169. http://www.columbia.edu/kermit/ckermit70.html#x4.4.1.1
- 170. http://www.columbia.edu/kermit/ckermit70.html#x4.4.1.2
- 171. http://www.columbia.edu/kermit/ckermit70.html#x4.4.2
- 172. http://www.columbia.edu/kermit/ckermit70.html#x4.4.2.1
- 173. http://www.columbia.edu/kermit/ckermit70.html#x4.4.2.1.1
- 174. http://www.columbia.edu/kermit/ckermit70.html#x4.4.2.1.2
- 175. http://www.columbia.edu/kermit/ckermit70.html#x4.4.2.2
- 176. http://www.columbia.edu/kermit/ckermit70.html#x4.5
- 177. http://www.columbia.edu/kermit/ckermit70.html#x4.5.1
- 178. http://www.columbia.edu/kermit/ckermit70.html#x4.5.2
- 179. http://www.columbia.edu/kermit/ckermit70.html#x4.5.2.1
- 180. http://www.columbia.edu/kermit/ckermit70.html#x4.5.2.2
- 181. http://www.columbia.edu/kermit/ckermit70.html#x4.5.3
- 182. http://www.columbia.edu/kermit/ckermit70.html#x4.5.4
- 183. http://www.columbia.edu/kermit/ckermit70.html#x4.6
- 184. http://www.columbia.edu/kermit/ckermit70.html#x4.7
- 185. http://www.columbia.edu/kermit/ckermit70.html#x4.7.1
- 186. http://www.columbia.edu/kermit/ckermit70.html#x4.7.2
- 187. http://www.columbia.edu/kermit/ckermit70.html#x4.7.3
- 188. http://www.columbia.edu/kermit/ckermit70.html#x4.8
- 189. http://www.columbia.edu/kermit/ckermit70.html#x4.8.1
- 190. http://www.columbia.edu/kermit/ckermit70.html#x4.8.2
- 191. http://www.columbia.edu/kermit/ckermit70.html#x4.9
- 192. http://www.columbia.edu/kermit/ckermit70.html#x4.9.1
- 193. http://www.columbia.edu/kermit/ckermit70.html#x4.9.2
- 194. http://www.columbia.edu/kermit/ckermit70.html#x4.9.3
- 195. http://www.columbia.edu/kermit/ckermit70.html#x4.10
- 196. http://www.columbia.edu/kermit/ckermit70.html#x4.11
- 197. http://www.columbia.edu/kermit/ckermit70.html#x4.11.1
- 198. http://www.columbia.edu/kermit/ckermit70.html#x4.11.2
- 199. http://www.columbia.edu/kermit/ckermit70.html#x4.11.3
- 200. http://www.columbia.edu/kermit/ckermit70.html#x4.11.4
- 201. http://www.columbia.edu/kermit/ckermit70.html#x4.11.5
- 202. http://www.columbia.edu/kermit/ckermit70.html#x4.11.6
- 203. http://www.columbia.edu/kermit/ckermit70.html#x4.12
- 204. http://www.columbia.edu/kermit/ckermit70.html#x4.13
- 205. http://www.columbia.edu/kermit/ckermit70.html#x4.14
- 206. http://www.columbia.edu/kermit/ckermit70.html#x4.15
- 207. http://www.columbia.edu/kermit/ckermit70.html#x4.16
- 208. http://www.columbia.edu/kermit/ckermit70.html#x4.17
- 209. http://www.columbia.edu/kermit/ckermit70.html#x4.17.1
- 210. http://www.columbia.edu/kermit/ckermit70.html#x4.17.2
- 211. http://www.columbia.edu/kermit/ckermit70.html#x4.18
- 212. http://www.columbia.edu/kermit/ckermit70.html#x4.19
- 213. http://www.columbia.edu/kermit/ckermit70.html#x4.20
- 214. http://www.columbia.edu/kermit/ckermit70.html#x4.20.1
- 215. http://www.columbia.edu/kermit/ckermit70.html#x4.20.2
- 216. http://www.columbia.edu/kermit/ckermit70.html#x4.20.2.1
- 217. http://www.columbia.edu/kermit/ckermit70.html#x4.20.2.2
- 218. http://www.columbia.edu/kermit/ckermit70.html#x4.20.2.3
- 219. http://www.columbia.edu/kermit/ckermit70.html#x4.20.2.4
- 220. http://www.columbia.edu/kermit/ckermit70.html#x4.20.2.5
- 221. http://www.columbia.edu/kermit/ckermit70.html#x4.20.3
- 222. http://www.columbia.edu/kermit/ckermit70.html#x4.21
- 223. http://www.columbia.edu/kermit/ckermit70.html#x4.22
- 224. http://www.columbia.edu/kermit/ckermit70.html#x4.22.1
- 225. http://www.columbia.edu/kermit/ckermit70.html#x4.22.2
- 226. http://www.columbia.edu/kermit/ckermit70.html#x4.22.3
- 227. http://www.columbia.edu/kermit/ckermit70.html#x4.22.4
- 228. http://www.columbia.edu/kermit/ckermit70.html#x4.22.5
- 229. http://www.columbia.edu/kermit/ckermit70.html#x4.22.6
- 230. http://www.columbia.edu/kermit/ckermit70.html#x4.22.7
- 231. http://www.columbia.edu/kermit/ckermit70.html#x4.22.8
- 232. http://www.columbia.edu/kermit/ckermit70.html#x4.23
- 233. http://www.columbia.edu/kermit/ckermit70.html#x4.24
- 234. http://www.columbia.edu/kermit/ckermit70.html#x4.25
- 235. http://www.columbia.edu/kermit/ckermit70.html#x5
- 236. http://www.columbia.edu/kermit/ckermit70.html#x5.0
- 237. http://www.columbia.edu/kermit/ckermit70.html#x5.1
- 238. http://www.columbia.edu/kermit/ckermit70.html#x5.2
- 239. http://www.columbia.edu/kermit/ckermit70.html#x5.3
- 240. http://www.columbia.edu/kermit/ckermit70.html#x5.3.1
- 241. http://www.columbia.edu/kermit/ckermit70.html#x5.3.2
- 242. http://www.columbia.edu/kermit/ckermit70.html#x5.4
- 243. http://www.columbia.edu/kermit/ckermit70.html#x5.5
- 244. http://www.columbia.edu/kermit/ckermit70.html#x5.6
- 245. http://www.columbia.edu/kermit/ckermit70.html#x5.7
- 246. http://www.columbia.edu/kermit/ckermit70.html#x6
- 247. http://www.columbia.edu/kermit/ckermit70.html#x6.0
- 248. http://www.columbia.edu/kermit/ckermit70.html#x6.1
- 249. http://www.columbia.edu/kermit/ckermit70.html#x6.2
- 250. http://www.columbia.edu/kermit/ckermit70.html#x6.3
- 251. http://www.columbia.edu/kermit/ckermit70.html#x6.4
- 252. http://www.columbia.edu/kermit/ckermit70.html#x6.5
- 253. http://www.columbia.edu/kermit/ckermit70.html#x6.6
- 254. http://www.columbia.edu/kermit/ckermit70.html#x6.6.1
- 255. http://www.columbia.edu/kermit/ckermit70.html#x6.6.2
- 256. http://www.columbia.edu/kermit/ckermit70.html#x6.6.2
- 257. http://www.columbia.edu/kermit/ckermit70.html#x6.6.3
- 258. http://www.columbia.edu/kermit/ckermit70.html#x6.6.4
- 259. http://www.columbia.edu/kermit/ckermit70.html#x6.6.5
- 260. http://www.columbia.edu/kermit/ckermit70.html#x6.6.5.1
- 261. http://www.columbia.edu/kermit/ckermit70.html#x6.6.5.2
- 262. http://www.columbia.edu/kermit/ckermit70.html#x6.6.5.3
- 263. http://www.columbia.edu/kermit/ckermit70.html#x6.6.5.4
- 264. http://www.columbia.edu/kermit/ckermit70.html#x6.6.5.5
- 265. http://www.columbia.edu/kermit/ckermit70.html#x6.7
- 266. http://www.columbia.edu/kermit/ckermit70.html#x7
- 267. http://www.columbia.edu/kermit/ckermit70.html#x7.0
- 268. http://www.columbia.edu/kermit/ckermit70.html#x7.1
- 269. http://www.columbia.edu/kermit/ckermit70.html#x7.1.1
- 270. http://www.columbia.edu/kermit/ckermit70.html#x7.1.2
- 271. http://www.columbia.edu/kermit/ckermit70.html#x7.1.3
- 272. http://www.columbia.edu/kermit/ckermit70.html#x7.1.4
- 273. http://www.columbia.edu/kermit/ckermit70.html#x7.2
- 274. http://www.columbia.edu/kermit/ckermit70.html#x7.3
- 275. http://www.columbia.edu/kermit/ckermit70.html#x7.4
- 276. http://www.columbia.edu/kermit/ckermit70.html#x7.5
- 277. http://www.columbia.edu/kermit/ckermit70.html#x7.6
- 278. http://www.columbia.edu/kermit/ckermit70.html#x7.7
- 279. http://www.columbia.edu/kermit/ckermit70.html#x7.8
- 280. http://www.columbia.edu/kermit/ckermit70.html#x7.9
- 281. http://www.columbia.edu/kermit/ckermit70.html#x7.9.1
- 282. http://www.columbia.edu/kermit/ckermit70.html#x7.9.2
- 283. http://www.columbia.edu/kermit/ckermit70.html#x7.10
- 284. http://www.columbia.edu/kermit/ckermit70.html#x7.10.1
- 285. http://www.columbia.edu/kermit/ckermit70.html#x7.10.2
- 286. http://www.columbia.edu/kermit/ckermit70.html#x7.10.3
- 287. http://www.columbia.edu/kermit/ckermit70.html#x7.10.4
- 288. http://www.columbia.edu/kermit/ckermit70.html#x7.10.5
- 289. http://www.columbia.edu/kermit/ckermit70.html#x7.10.6
- 290. http://www.columbia.edu/kermit/ckermit70.html#x7.10.7
- 291. http://www.columbia.edu/kermit/ckermit70.html#x7.10.8
- 292. http://www.columbia.edu/kermit/ckermit70.html#x7.10.9
- 293. http://www.columbia.edu/kermit/ckermit70.html#x7.10.10
- 294. http://www.columbia.edu/kermit/ckermit70.html#x7.11
- 295. http://www.columbia.edu/kermit/ckermit70.html#x7.12
- 296. http://www.columbia.edu/kermit/ckermit70.html#x7.13
- 297. http://www.columbia.edu/kermit/ckermit70.html#x7.14
- 298. http://www.columbia.edu/kermit/ckermit70.html#x7.15
- 299. http://www.columbia.edu/kermit/ckermit70.html#x7.16
- 300. http://www.columbia.edu/kermit/ckermit70.html#x7.17
- 301. http://www.columbia.edu/kermit/ckermit70.html#x7.18
- 302. http://www.columbia.edu/kermit/ckermit70.html#x7.19
- 303. http://www.columbia.edu/kermit/ckermit70.html#x7.20
- 304. http://www.columbia.edu/kermit/ckermit70.html#x7.20.1
- 305. http://www.columbia.edu/kermit/ckermit70.html#x7.20.2
- 306. http://www.columbia.edu/kermit/ckermit70.html#x7.21
- 307. http://www.columbia.edu/kermit/ckermit70.html#x7.22
- 308. http://www.columbia.edu/kermit/ckermit70.html#x7.23
- 309. http://www.columbia.edu/kermit/ckermit70.html#x7.24
- 310. http://www.columbia.edu/kermit/ckermit70.html#x7.25
- 311. http://www.columbia.edu/kermit/ckermit70.html#x7.26
- 312. http://www.columbia.edu/kermit/ckermit70.html#x7.26.1
- 313. http://www.columbia.edu/kermit/ckermit70.html#x7.26.2
- 314. http://www.columbia.edu/kermit/ckermit70.html#x7.27
- 315. http://www.columbia.edu/kermit/ckermit70.html#x8
- 316. http://www.columbia.edu/kermit/ckermit70.html#x9
- 317. http://www.columbia.edu/kermit/ckermit70.html#x9.0
- 318. http://www.columbia.edu/kermit/ckermit70.html#x9.1
- 319. http://www.columbia.edu/kermit/ckermit70.html#x9.2
- 320. http://www.columbia.edu/kermit/ckermit70.html#x9.3
- 321. http://www.columbia.edu/kermit/ckermit70.html#x10
- 322. http://www.columbia.edu/kermit/ckermit70.html#xiii
- 323. http://www.columbia.edu/kermit/ckermit70.html#xiii.1
- 324. http://www.columbia.edu/kermit/ckermit70.html#xiii.1.1
- 325. http://www.columbia.edu/kermit/ckermit70.html#xiii.1.2
- 326. http://www.columbia.edu/kermit/ckermit70.html#xiii.1.2.1
- 327. http://www.columbia.edu/kermit/ckermit70.html#xiii.1.2.2
- 328. http://www.columbia.edu/kermit/ckermit70.html#xiii.1.2.3
- 329. http://www.columbia.edu/kermit/ckermit70.html#xiii.2
- 330. http://www.columbia.edu/kermit/ckermit70.html#xiv
- 331. http://www.columbia.edu/kermit/ckermit70.html#xv
- 332. http://www.columbia.edu/kermit/ckb2.htm
- 333. http://www.columbia.edu/kermit/ckbreviews.html
- 334. http://www.bhusa.com/
- 335. http://www.columbia.edu/kermit/manuals.html#ckde
- 336. http://www.columbia.edu/kermit/manuals.html#ktb
- 337. http://www.columbia.edu/kermit/news.html
- 338. news:comp.protocols.kermit.announce
- 339. news:comp.protocols.kermit.misc
- 340. http://www.columbia.edu/kermit/ckb2.htm
- 341. http://www.columbia.edu/kermit/ckermit70.html#x4
- 342. http://www.columbia.edu/kermit/ckermit70.html#x4.3
- 343. http://www.columbia.edu/kermit/ckermit70.html#x4.23
- 344. http://www.columbia.edu/kermit/ckermit70.html#x4.5.1
- 345. http://www.columbia.edu/kermit/ckermit70.html#x1.5
- 346. http://www.columbia.edu/kermit/ckermit70.html#x4.7.1
- 347. http://www.columbia.edu/kermit/ckermit70.html#x4.9.
- 348. http://www.columbia.edu/kermit/ckb2.htm
- 349. http://www.columbia.edu/kermit/ckermit70.html#x7.9.2
- 350. http://www.columbia.edu/kermit/ckermit70.html#x2.15
- 351. http://www.columbia.edu/kermit/ckermit70.html#x9.1
- 352. http://www.columbia.edu/kermit/ckermit70.html#x1.6
- 353. http://www.columbia.edu/kermit/ckermit70.html#x7.4
- 354. http://www.columbia.edu/kermit/ckermit70.html#x4.9.1
- 355. http://www.columbia.edu/kermit/ckermit70.html#mjd
- 356. http://www.columbia.edu/kermit/ckermit70.html#mjd
- 357. http://www.columbia.edu/kermit/ckermit70.html#x4.9
- 358. http://www.columbia.edu/kermit/ckb2.htm
- 359. http://www.columbia.edu/kermit/ckb2.htm
- 360. http://www.columbia.edu/kermit/ckermit70.html#x7.5
- 361. http://www.columbia.edu/kermit/ckermit70.html#x2.12
- 362. http://www.columbia.edu/kermit/ckermit70.html#x1.5
- 363. http://www.columbia.edu/kermit/ckermit70.html#x4.9.1
- 364. http://www.columbia.edu/kermit/ckermit70.html#x6.6.5
- 365. http://www.columbia.edu/kermit/ckermit70.html#x4.9
- 366. http://www.columbia.edu/kermit/ckermit70.html#x7.18
- 367. http://www.columbia.edu/kermit/ckermit70.html#x7.4
- 368. http://www.columbia.edu/kermit/ckermit70.html#x1.15
- 369. http://www.columbia.edu/kermit/ckermit70.html#x4.3
- 370. http://www.columbia.edu/kermit/ckermit70.html#x7.3
- 371. http://www.columbia.edu/kermit/ckermit70.html#x7.10.7
- 372. http://www.columbia.edu/kermit/ckermit70.html#x7.1
- 373. http://www.columbia.edu/kermit/ckermit70.html#x4.9.1
- 374. ftp://kermit.columbia.edu/kermit/f/ckccfg.txt
- 375. ftp://kermit.columbia.edu/kermit/f/ckccfg.txt
- 376. http://www.columbia.edu/kermit/ckermit70.html#x1.22.4
- 377. http://www.columbia.edu/kermit/ckermit70.html#x1.22.5
- 378. http://www.columbia.edu/kermit/ckb2.htm
- 379. http://www.columbia.edu/kermit/ckermit70.html#x1.22.5
- 380. http://www.columbia.edu/kermit/ckermit70.html#x7.12
- 381. http://www.columbia.edu/kermit/ckermit70.html#x2.1.16
- 382. http://www.columbia.edu/kermit/ckermit70.html#x2.7
- 383. http://www.columbia.edu/kermit/ckermit70.html#x2.3.5
- 384. http://www.columbia.edu/kermit/ckermit70.html#x7.5
- 385. http://www.telefonica.es/cambiodenumeracion/
- 386. http://www.columbia.edu/kermit/ckermit70.html#x7.5
- 387. http://www.columbia.edu/kermit/ckb2.htm
- 388. http://www.columbia.edu/kermit/ckermit70.html#x2.2.2
- 389. http://www.columbia.edu/kermit/ckermit70.html#x2.1.11
- 390. http://www.columbia.edu/kermit/ckermit70.html#x2.1.13
- 391. http://www.columbia.edu/kermit/ckermit70.html#x2.1.12
- 392. http://www.columbia.edu/kermit/ckb2.htm
- 393. http://www.columbia.edu/kermit/ckermit70.html#x2.1.1
- 394. http://www.columbia.edu/kermit/ckb2.htm
- 395. http://www.columbia.edu/kermit/ckb2.htm
- 396. http://www.columbia.edu/kermit/ckermit70.html#x2.1.7
- 397. http://www.columbia.edu/kermit/ckermit70.html#x2.1.6
- 398. http://www.columbia.edu/kermit/ckb2.htm
- 399. ftp://kermit.columbia.edu/kermit/f/telnet.txt
- 400. http://www.columbia.edu/kermit/telnet.htm
- 401. ftp://kermit.columbia.edu/kermit/f/telnet.txt
- 402. http://www.columbia.edu/kermit/telnet.htm
- 403. ftp://ftp.isi.edu/in-notes/rfc1572.txt
- 404. ftp://ftp.isi.edu/in-notes/rfc779.txt
- 405. http://www.columbia.edu/kermit/ckb2.htm
- 406. http://www.columbia.edu/kermit/ckermit70.html#x2.10
- 407. http://www.columbia.edu/kermit/ckermit70.html#x2.8
- 408. http://www.columbia.edu/kermit/ckermit70.html#x1.5
- 409. http://www.columbia.edu/kermit/ckermit70.html#x4.20
- 410. http://www.psy.uq.oz.au/~ftp/Crypto/
- 411. http://www.columbia.edu/kermit/security.htm
- 412. http://srp.stanford.edu/srp/
- 413. http://www.columbia.edu/kermit/ckermit70.html#x2.7.1,
- 414. ftp://kermit.columbia.edu/kermit/f/ckccfg.txt
- 415. http://www.columbia.edu/kermit/security.htm
- 416. http://www.columbia.edu/kermit/ckb2.htm
- 417. http://www.columbia.edu/kermit/ckermit70.html#x2.7
- 418. http://www.columbia.edu/kermit/ckermit70.html#x2.0
- 419. ftp://kermit.columbia.edu/kermit/f/ckuins.txt
- 420. ftp://kermit.columbia.edu/kermit/f/ckubwr.txt
- 421. ftp://kermit.columbia.edu/kermit/f/ckuins.txt
- 422. http://www.columbia.edu/kermit/iksd.html#x4.2
- 423. http://www.columbia.edu/kermit/iksd.html
- 424. http://www.columbia.edu/kermit/ckermit70.html#x4.2.8.1
- 425. ftp://ftp.isi.edu/in-notes/rfc1945.txt
- 426. http://www.columbia.edu/kermit/ckermit70.html#x1.5
- 427. http://www.columbia.edu/kermit/ckermit70.html#x3.2
- 428. http://www.columbia.edu/kermit/ckermit70.html#x3.2
- 429. http://www.columbia.edu/kermit/ckb2.htm
- 430. http://www.columbia.edu/kermit/ckb2.htm
- 431. http://www.columbia.edu/kermit/ckermit70.html#x5.4
- 432. ftp://kermit.columbia.edu/kermit/f/ckubwr.txt
- 433. http://www.columbia.edu/kermit/ckermit70.html#x4.10
- 434. http://www.columbia.edu/kermit/ckermit70.html#x4.7.1
- 435. http://www.columbia.edu/kermit/ckermit70.html#x4.7.3
- 436. http://www.columbia.edu/kermit/ckermit70.html#x4.3
- 437. http://www.columbia.edu/kermit/ckermit70.html#x4.10
- 438. http://www.columbia.edu/kermit/ckermit70.html#x4.11
- 439. http://www.columbia.edu/kermit/ckermit70.html#x4.15
- 440. http://www.columbia.edu/kermit/ckermit70.html#x4.2.4
- 441. http://www.columbia.edu/kermit/ckermit70.html#x4.7
- 442. http://www.columbia.edu/kermit/ckermit70.html#x4.2.3
- 443. http://www.columbia.edu/kermit/ckermit70.html#x4.2.1.3
- 444. http://www.columbia.edu/kermit/ckb2.htm
- 445. http://www.columbia.edu/kermit/ckermit70.html#x4.2.2
- 446. http://www.columbia.edu/kermit/ckermit70.html#x1.5
- 447. http://www.columbia.edu/kermit/ckermit70.html#x4.2.8.2
- 448. http://www.columbia.edu/kermit/ckermit70.html#x4.3
- 449. http://www.columbia.edu/kermit/ckermit70.html#x4.10
- 450. http://www.columbia.edu/kermit/ckermit70.html#x4.11
- 451. http://www.columbia.edu/kermit/ckermit70.html#x4.15
- 452. http://www.telstra.com.au/docs/PGP/
- 453. http://www.telstra.com.au/docs/PGP/pgpdoc2/pgpdoc2_17.html
- 454. http://www.columbia.edu/kermit/security.htm
- 455. http://www.columbia.edu/kermit/ckermit70.html#x2.7
- 456. http://www.columbia.edu/kermit/ckb2.htm
- 457. http://www.columbia.edu/kermit/ckermit70.html#x2.14
- 458. http://www.columbia.edu/kermit/ckermit70.html#x1.23
- 459. http://www.columbia.edu/kermit/ckermit70.html#x4.7
- 460. http://www.columbia.edu/kermit/ckb2.htm
- 461. http://www.columbia.edu/kermit/ckb2.htm
- 462. http://www.columbia.edu/kermit/ckermit70.html#x4.9
- 463. http://www.columbia.edu/kermit/ckb2.htm
- 464. http://www.columbia.edu/kermit/ckermit70.html#x1.5.4
- 465. http://www.columbia.edu/kermit/ckermit70.html#x4.3
- 466. http://www.columbia.edu/kermit/ckermit70.html#x1.5.5
- 467. http://www.columbia.edu/kermit/ckermit70.html#x7.5
- 468. http://www.columbia.edu/kermit/ckermit70.html#x4.9
- 469. http://www.columbia.edu/kermit/ckermit70.html#x1.5.4
- 470. http://www.columbia.edu/kermit/ckermit70.html#x4.9
- 471. http://www.columbia.edu/kermit/ckermit70.html#x1.5.4
- 472. http://www.columbia.edu/kermit/ckermit70.html#x1.5.5
- 473. http://www.columbia.edu/kermit/ckb2.htm
- 474. http://www.columbia.edu/kermit/ckb2.htm
- 475. http://www.columbia.edu/kermit/ckermit70.html#x1.5
- 476. http://www.columbia.edu/kermit/ckermit70.html#x1.6
- 477. http://www.columbia.edu/kermit/ckermit70.html#x7.10
- 478. http://www.columbia.edu/kermit/ckermit70.html#x7.10.11
- 479. http://www.columbia.edu/kermit/ckermit70.html#x1.6
- 480. http://www.columbia.edu/kermit/ckermit70.html#x4.2.2
- 481. http://www.columbia.edu/kermit/ckermit70.html#x4.11
- 482. http://www.columbia.edu/kermit/ckermit70.html#x1.5.4
- 483. http://www.columbia.edu/kermit/ckermit70.html#x4.9.1
- 484. http://www.columbia.edu/kermit/ckermit70.html#x4.0.6
- 485. http://www.columbia.edu/kermit/ckermit70.html#x4.2
- 486. http://www.columbia.edu/kermit/ckermit70.html#x4.1
- 487. http://www.columbia.edu/kermit/ckermit70.html#x4.7.1
- 488. http://www.columbia.edu/kermit/ckb2.htm
- 489. http://www.columbia.edu/kermit/ckermit70.html#x1.5
- 490. http://www.columbia.edu/kermit/ckermit70.html#x4.2.2
- 491. http://www.columbia.edu/kermit/ckermit70.html#x4.7.1
- 492. http://www.columbia.edu/kermit/ckermit70.html#x4.2
- 493. http://www.columbia.edu/kermit/ckermit70.html#x4.10
- 494. http://www.columbia.edu/kermit/ckermit70.html#x4.2.2
- 495. http://www.columbia.edu/kermit/ckermit70.html#x4.7.1
- 496. http://www.columbia.edu/kermit/ckermit70.html#x4.2
- 497. http://www.columbia.edu/kermit/ckermit70.html#x4.10
- 498. http://www.columbia.edu/kermit/ckermit70.html#x1.11.5
- 499. http://www.columbia.edu/kermit/ckermit70.html#x4.0.6
- 500. http://www.columbia.edu/kermit/ckermit70.html#x4.11
- 501. http://www.columbia.edu/kermit/ckermit70.html#x4.9.1
- 502. http://www.columbia.edu/kermit/ckermit70.html#x4.11.3
- 503. http://www.columbia.edu/kermit/ckermit70.html#x4.9
- 504. http://www.columbia.edu/kermit/ckermit70.html#x4.9
- 505. http://www.columbia.edu/kermit/ckermit70.html#x4.5.1
- 506. http://www.columbia.edu/kermit/ckermit70.html#x7.10
- 507. http://www.columbia.edu/kermit/ckermit70.html#x7.10.5
- 508. http://www.columbia.edu/kermit/ckermit70.html#x7.10.3
- 509. http://www.columbia.edu/kermit/ckermit70.html#x7.10.5
- 510. http://www.columbia.edu/kermit/ckb2.htm
- 511. http://www.columbia.edu/kermit/ckermit70.html#x4.3
- 512. http://www.columbia.edu/kermit/ckermit70.html#x4.10
- 513. http://www.columbia.edu/kermit/ckermit70.html#x4.3
- 514. http://www.columbia.edu/kermit/ckermit70.html#x4.10
- 515. http://www.columbia.edu/kermit/ckermit70.html#x4.15
- 516. http://www.columbia.edu/kermit/ckermit70.html#x4.18
- 517. http://www.columbia.edu/kermit/ckermit70.html#x4.20
- 518. http://www.columbia.edu/kermit/ckermit70.html#x4.20
- 519. http://www.columbia.edu/kermit/ckermit70.html#x4.20
- 520. http://www.columbia.edu/kermit/ckermit70.html#x4.19
- 521. http://www.columbia.edu/kermit/ckermit70.html#x4.16
- 522. http://www.columbia.edu/kermit/ckermit70.html#x4.19
- 523. http://www.columbia.edu/kermit/ckermit70.html#x4.20.2.3
- 524. http://www.columbia.edu/kermit/ckermit70.html#x1.5
- 525. http://www.columbia.edu/kermit/ckermit70.html#x6.6.5.4
- 526. http://www.columbia.edu/kermit/ckermit70.html#x4.22.2
- 527. http://www.columbia.edu/kermit/ckermit70.html#x4.22.3
- 528. http://www.columbia.edu/kermit/ckb2.htm
- 529. http://www.columbia.edu/kermit/ckb2.htm
- 530. http://www.columbia.edu/kermit/ckermit70.html#x9.3
- 531. http://www.columbia.edu/kermit/ckermit70.html#x5.2.1
- 532. http://www.columbia.edu/kermit/ckermit70.html#x4.5.1
- 533. http://www.columbia.edu/kermit/ckermit70.html#x4.5.2
- 534. http://www.columbia.edu/kermit/ckermit70.html#x6.6
- 535. http://www.columbia.edu/kermit/ckermit70.html#xiii
- 536. http://www.columbia.edu/kermit/ckermit70.html#xiii
- 537. ftp://ftp.isi.edu/in-notes/rfc1489.txt
- 538. ftp://ftp.isi.edu/in-notes/rfc2319.txt
- 539. http://www.unicode.org/
- 540. http://www.columbia.edu/kermit/ckermit70.html#x6.6.2
- 541. http://www.columbia.edu/kermit/ckermit70.html#x6.6.5.1
- 542. ftp://ftp.isi.edu/in-notes/rfc2640.txt
- 543. http://www.columbia.edu/kermit/ckermit70.html#x6.6.2
- 544. http://www.columbia.edu/kermit/ckermit70.html#x6.0
- 545. http://www.columbia.edu/kermit/ckermit70.html#x6.5
- 546. http://www.columbia.edu/kermit/ckermit70.html#x6.4
- 547. http://www.columbia.edu/kermit/ckb2.htm
- 548. http://www.columbia.edu/kermit/ckermit70.html#x4.21
- 549. http://www.columbia.edu/kermit/ckermit70.html#x6.5
- 550. http://www.columbia.edu/kermit/ckermit70.html#x2.8
- 551. http://www.columbia.edu/kermit/ckermit70.html#x7.7
- 552. http://www.columbia.edu/kermit/ckermit70.html#x7.2
- 553. http://www.columbia.edu/kermit/ckermit70.html#x1.19
- 554. http://www.columbia.edu/kermit/ckermit70.html#x4.9
- 555. http://www.columbia.edu/kermit/ckermit70.html#x4.1
- 556. http://www.columbia.edu/kermit/ckermit70.html#x4.2
- 557. http://www.columbia.edu/kermit/ckermit70.html#x4.1
- 558. http://www.columbia.edu/kermit/ckermit70.html#x4.2
- 559. http://www.columbia.edu/kermit/ckermit70.html#x2.1.11
- 560. http://www.columbia.edu/kermit/ckermit70.html#x2.10
- 561. http://www.columbia.edu/kermit/ckermit70.html#ferrstring
- 562. http://www.columbia.edu/kermit/ckermit70.html#x4.2.5
- 563. http://www.columbia.edu/kermit/ckermit70.html#x2.1.10
- 564. http://www.columbia.edu/kermit/ckermit70.html#x9.1
- 565. http://www.columbia.edu/kermit/ckermit70.html#x7.23
- 566. http://www.columbia.edu/kermit/ckermit70.html#x7.23
- 567. http://www.columbia.edu/kermit/ckermit70.html#x1.22
- 568. http://www.columbia.edu/kermit/ckermit70.html#x1.6
- 569. http://www.columbia.edu/kermit/ckermit70.html#x7.23
- 570. http://www.columbia.edu/kermit/ckermit70.html#x7.24
- 571. http://www.columbia.edu/kermit/ckermit70.html#x7.24
- 572. http://www.columbia.edu/kermit/ckermit70.html#x4.2.3
- 573. http://www.columbia.edu/kermit/ckermit70.html#x7.12
- 574. http://www.columbia.edu/kermit/ckermit70.html#x7.9
- 575. http://www.columbia.edu/kermit/ckb2.htm
- 576. http://www.columbia.edu/kermit/ckermit70.html#x4.11.3
- 577. http://www.columbia.edu/kermit/ckermit70.html#x4.11.3
- 578. http://www.columbia.edu/kermit/ckermit70.html#x7.5
- 579. http://www.columbia.edu/kermit/ckermit70.html#x7.10.7
- 580. http://www.columbia.edu/kermit/ckermit70.html#x7.10.7
- 581. http://www.columbia.edu/kermit/ckermit70.html#x4.2.8.4
- 582. http://www.columbia.edu/kermit/ckermit70.html#x4.2.5
- 583. http://www.columbia.edu/kermit/ckermit70.html#x7.8
- 584. http://www.columbia.edu/kermit/ckermit70.html#x4.9.1
- 585. http://www.columbia.edu/kermit/ckb2.htm
- 586. http://www.columbia.edu/kermit/ckermit70.html#x7.19
- 587. http://www.columbia.edu/kermit/ckermit70.html#x7.16
- 588. http://www.columbia.edu/kermit/ckermit70.html#x7.9.1
- 589. http://www.columbia.edu/kermit/ckermit70.html#x7.5
- 590. http://www.columbia.edu/kermit/ckermit70.html#x7.3
- 591. http://www.columbia.edu/kermit/ckermit70.html#x4.11.3
- 592. http://www.columbia.edu/kermit/ckermit70.html#x4.5.1
- 593. http://www.columbia.edu/kermit/ckermit70.html#x7.10
- 594. http://www.columbia.edu/kermit/ckermit70.html#x7.10.10
- 595. http://www.columbia.edu/kermit/ckermit70.html#x1.5
- 596. http://www.columbia.edu/kermit/ckermit70.html#x7.23
- 597. http://www.columbia.edu/kermit/ckermit70.html#x7.10.7
- 598. http://www.columbia.edu/kermit/ckermit70.html#x7.10.7
- 599. http://www.columbia.edu/kermit/ckermit70.html#x4.11.3
- 600. http://www.columbia.edu/kermit/ckermit70.html#x7.10.11
- 601. http://www.columbia.edu/kermit/ckermit70.html#x4.9
- 602. http://www.columbia.edu/kermit/ckermit70.html#x7.10.3
- 603. http://www.columbia.edu/kermit/ckermit70.html#x7.3
- 604. http://www.columbia.edu/kermit/ckermit70.html#x7.9.2
- 605. http://www.columbia.edu/kermit/ckb2.htm
- 606. http://www.columbia.edu/kermit/ckermit70.html#x4.17.2
- 607. http://www.columbia.edu/kermit/ckermit70.html#x1.22
- 608. http://www.columbia.edu/kermit/ckermit70.html#x4.7.1
- 609. http://www.columbia.edu/kermit/ckermit70.html#x1.22
- 610. http://www.columbia.edu/kermit/ckermit70.html#x4.3
- 611. http://www.columbia.edu/kermit/ckermit70.html#x4.9
- 612. http://www.columbia.edu/kermit/ckermit70.html#x1.22
- 613. http://www.columbia.edu/kermit/ckermit70.html#x1.6
- 614. http://www.columbia.edu/kermit/ckermit70.html#x7.5
- 615. http://www.columbia.edu/kermit/ckermit70.html#x7.5
- 616. http://www.columbia.edu/kermit/ckermit70.html#x7.19
- 617. http://www.columbia.edu/kermit/ckermit70.html#x4.9.1
- 618. http://www.columbia.edu/kermit/ckermit70.html#x9.3
- 619. http://www.columbia.edu/kermit/ckermit70.html#x7.5
- 620. http://www.columbia.edu/kermit/ckb2.htm
- 621. http://www.columbia.edu/kermit/ckermit70.html#x7.4
- 622. http://www.columbia.edu/kermit/ckermit70.html#x7.20.2
- 623. http://www.columbia.edu/kermit/ckermit70.html#x7.10.5
- 624. http://www.columbia.edu/kermit/ckermit70.html#x7.10.9
- 625. http://www.columbia.edu/kermit/ckermit70.html#x1.10
- 626. http://www.columbia.edu/kermit/ckermit70.html#x1.5
- 627. http://www.columbia.edu/kermit/ckermit70.html#x4.7.1
- 628. http://www.columbia.edu/kermit/iksd.html
- 629. http://www.columbia.edu/kermit/ckermit70.html#x7.19
- 630. http://www.columbia.edu/kermit/ckermit70.html#x4.10
- 631. http://www.columbia.edu/kermit/ckermit70.html#x4.11
- 632. http://www.columbia.edu/kermit/ckermit70.html#x4.3
- 633. http://www.columbia.edu/kermit/gkermit.html
- 634. http://www.columbia.edu/kermit/ckermit70.html#x4.20
- 635. http://www.columbia.edu/kermit/gkermit.html
- 636. http://www.columbia.edu/kermit/ckb2.htm
- 637. http://www.columbia.edu/kermit/ckermit70.html#x7.3
- 638. mailto:kermit@columbia.edu
- 639. http://www.columbia.edu/kermit/ckermit70.html#top
- 640. http://www.columbia.edu/kermit/ckermit.html
- 641. http://www.columbia.edu/kermit/index.html
diff --git a/ckermit80.txt b/ckermit80.txt
deleted file mode 100644 (file)
index 493338a..0000000
+++ /dev/null
@@ -1,10349 +0,0 @@
-
-                           C-Kermit 8.0 Update Notes
-
-   [ [1]Contents ] [ [2]C-Kermit ] [ [3]Kermit Home ]
-
-              Second Supplement to Using C-Kermit, Second Edition
-
-For C-Kermit 8.0
-
-   As of C-Kermit version: 8.0.211
-   Date of C-Kermit release: 10 April 2003
-   This file last updated: Sat Apr 10 16:36:11 2004
-
-     * IF YOU ARE READING A PLAIN-TEXT version of this document, note
-       that it is a plain-text dump of a Web page. You can visit the
-       original (and possibly more up-to-date) Web page here:
-  [4]http://www.columbia.edu/kermit/ckermit80.html
-     * If you are reading the HTML version of this file with a GUI Web
-       browser, the features added since C-Kermit 8.0.201 are shown in
-       red if your browser and monitor permit. Features that were new to
-       versions 8.0.200 and 201 are in black.
-
-Authors: Frank da Cruz and Christine M. Gianone
-Address: The Kermit Project
-         Columbia University
-         612 West 115th Street
-         New York NY 10025-7799
-         USA
-Fax:     +1 (212) 662-6442
-E-Mail:  [5]kermit-support@columbia.edu
-Web:     [6]http://www.columbia.edu/kermit/
-Or:      [7]http://www.kermit-project.org/
-Or:      [8]http://www.columbia.nyc.ny.us/kermit/
-     _________________________________________________________________
-
-  NOTICES
-
-   This document:
-          Copyright Â© 1997, 2002, Frank da Cruz and Christine M. Gianone.
-          All rights reserved.
-
-   Kermit 95:
-          Copyright Â© 1995, 2002, Trustees of Columbia University in the
-          City of New York. All rights reserved.
-
-   C-Kermit:
-          Copyright Â© 1985, 2002,
-          Trustees of Columbia University in the City of New York. All
-          rights reserved. See the C-Kermit [9]COPYING.TXT file or the
-          copyright text in the [10]ckcmai.c module for disclaimer and
-          permissions.
-
-   When Kerberos(TM) and/or SRP(TM) (Secure Remote Password) and/or
-          SSL/TLS protocol are included:
-          Portions Copyright Â© 1990, Massachusetts Institute of
-          Technology.
-          Portions Copyright Â© 1991, 1993 Regents of the University of
-          California.
-          Portions Copyright Â© 1991, 1992, 1993, 1994, 1995 by AT&T.
-          Portions Copyright Â© 1997, Stanford University.
-          Portions Copyright Â© 1995-1997, Eric Young
-          <eay@cryptosoft.com>.
-
-   For the full text of the third-party copyright notices, see
-   [11]Appendix V.
-     _________________________________________________________________
-
-  WHAT IS IN THIS FILE
-
-   This file lists changes made to C-Kermit since version 7.0 was
-   released in January 2000. Use this file as a supplement to:
-
-     * The second edition of [12]Using C-Kermit; and:
-     * The [13]C-Kermit 7.0 Update Notes. Also available in plain-text
-       form as [14]ckermit70.txt.
-
-   until the third edition of Using C-Kermit is published. We apologize
-   for the scattered documentation and will consolidate it when we are
-   able.
-     _________________________________________________________________
-
-   ADDITIONAL FILES Several other files accompany this new Kermit
-   release:
-
-   [15]ckututor.html
-          C-Kermit Tutorial (for Unix). Also distributed in Nroff form as
-          [16]ckuker.nr, the Unix C-Kermit manual page.
-
-   [17]security.htm
-          Discussion of Kermit's new authentication and encryption
-          features, updated for C-Kermit 8.0.
-
-   [18]telnet.htm
-          Detailed documentation of Kermit's Telnet client, updated for
-          C-Kermit 8.0.
-
-   [19]ftpscripts.html
-          Tutorial: Writing FTP automation scripts
-
-   [20]ckcbwr.html
-          Platform-independent C-Kermit hints and tips. Also distributed
-          in plain text form as [21]ckcbwr.txt
-
-   [22]ckubwr.html
-          Unix-specific C-Kermit hints and tips. Also distributed in
-          plain text form as [23]ckubwr.txt.
-
-   [24]ckvbwr.html
-          VMS-specific C-Kermit hints and tips. Also distributed in plain
-          text form as [25]ckvbwr.txt.
-
-   [26]ckuins.html
-          Unix C-Kermit installation instructions. Also distributed in
-          plain text form as [27]ckuins.txt.
-
-   [28]ckvins.html
-          VMS C-Kermit installation instructions. Also distributed in
-          plain text form as [29]ckvins.txt.
-
-   [30]ckccfg.html
-          Compile-time configuration options. Also distributed in plain
-          text form as [31]ckccfg.txt.
-
-   [32]ckcplm.html
-          C-Kermit Program Logic Manual. Also distributed in plain text
-          form as [33]ckcplm.txt.
-
-   [34]iksd.html
-          Internet Kermit Service Aministrators Guide for Unix.
-
-   [35]skermit.html
-          C-Kermit as an SSH Subsystem (SFTP server replacement).
-
-   [ [36]Top ] [ [37]C-Kermit ] [ [38]Kermit Home ]
-  __________________________________________________________________________
-
-CONTENTS
-
-     [39]0. WHAT'S NEW
-     [40]1. FIXES SINCE VERSION 7.0.196
-     [41]2. SSH AND HTTP 
-         [42]2.1. SSH Connections
-         [43]2.2. HTTP Connections
-            [44]2.2.1. HTTP Command Switches
-            [45]2.2.2. HTTP Action Commands
-            [46]2.2.3. HTTP Headers
-            [47]2.2.4. Secure HTTP Connections
-            [48]2.2.5. HTTP Variables
-            [49]2.2.6. The HTTP Command-Line Personality
-     [50]3. THE BUILT-IN FTP CLIENT
-         [51]3.1. Making and Managing FTP Connections
-            [52]3.1.1. Kermit Command-Line Options for FTP
-            [53]3.1.2. The FTP Command-Line Personality
-            [54]3.1.3. The FTP URL Interpreter
-            [55]3.1.4. Interactive FTP Session Establishment
-         [56]3.2. Making Secure FTP Connections
-         [57]3.3. Setting FTP Preferences
-         [58]3.4. Managing Directories and Files
-         [59]3.5. Uploading Files With FTP
-            [60]3.5.1. FTP PUT Switches
-            [61]3.5.2. Update Mode
-            [62]3.5.3. Recovery
-         [63]3.6. Downloading Files With FTP
-            [64]3.6.1. FTP GET Switches
-            [65]3.6.2. Filename Collisions
-            [66]3.6.3. Recovery
-         [67]3.7. Translating Character Sets
-            [68]3.7.1. Character Sets and Uploading
-            [69]3.7.2. Character Sets and Downloading
-         [70]3.8. FTP Command Shortcuts
-         [71]3.9. Dual Sessions
-         [72]3.10. Automating FTP Sessions
-            [73]3.10.1. FTP-Specific Variables and Functions
-            [74]3.10.2. Examples
-            [75]3.10.3. Automating Secure FTP Connections
-         [76]3.11. Advanced FTP Protocol Features  [77]4. FILE SCANNING
-    [78]5. FILE AND DIRECTORY NAMES CONTAINING SPACES
-    [79]6. OTHER COMMAND PARSING IMPROVEMENTS
-         [80]6.1. Grouping Macro Arguments
-         [81]6.2. Directory and File Name Completion
-         [82]6.3. Passing Arguments to Command Files
-         [83]6.4. More-Prompting
-         [84]6.5. Commas in Macro Definitions
-         [85]6.6. Arrow Keys
-    [86]7. NEW COMMANDS AND SWITCHES
-    [87]8. SCRIPTING IMPROVEMENTS
-         [88]8.1. Performance and Debugging
-         [89]8.2. Using Macros as Numeric Variables
-         [90]8.3. New IF Conditions
-         [91]8.4. The ON_UNKNOWN_COMMAND and ON_CD Macros
-         [92]8.5. The SHOW MACRO Command
-         [93]8.6. Arrays
-         [94]8.7. New or Improved Built-in Variables and Functions
-         [95]8.8. The RETURN and END Commands
-         [96]8.9. UNDEFINing Groups of Variables
-         [97]8.10. The INPUT and MINPUT Commands
-         [98]8.11. Learned Scripts
-         [99]8.12. Pattern Matching
-         [100]8.13. Dates and Times
-         [101]8.14. Trapping Keyboard Interruption
-    [102]9. S-EXPRESSIONS
-         [103]9.1. What is an S-Expression?
-         [104]9.2. Integer and Floating-Point-Arithmetic
-         [105]9.3. How to Use S-Expressions
-         [106]9.4. Summary of Built-in Constants and Operators
-         [107]9.5. Variables
-         [108]9.6. Assignments and Scope
-         [109]9.7. Conditional Expressions
-         [110]9.8. Extensibility
-         [111]9.9. Examples
-         [112]9.10. Differences from Algebraic Notation
-         [113]9.11.Differences from Lisp
-    [114]10. FILE TRANSFER
-    [115]11. MODEMS AND DIALING
-    [116]12. TERMINAL CONNECTION
-    [117]13. CHARACTER SETS
-    [118]14. DIALOUT FROM TELNET TERMINAL SERVERS
-    [119]15. COPING WITH BROKEN KERMIT PARTNERS
-    [120]16. NEW COMMAND-LINE OPTIONS
-    [121]17. LOGS
-
-   [ [122]Top ] [ [123]C-Kermit ] [ [124]Kermit Home ]
-  __________________________________________________________________________
-
-0. WHAT'S NEW
-
-   The Initialization and Customization Files
-          C-Kermit 8.0 now supports specification of the initialization
-          file name (path) in an environment variable, CKERMIT_INI. It
-          also relies far less than before on the initialization for
-          functioning. See [125]Section 5 of the Unix C-Kermit
-          [126]installation instructions for details. As of version
-          8.0.201, C-Kermit also executes your customization file (if you
-          have one) even if the initialization file was not found.
-          Previously, the customization file was executed by a TAKE
-          command in the initialization file (and it still is, if an
-          initialization is found).
-
-   Incompatible Changes
-          As always, we do our best to avoid changes that break existing
-          scripts. However, C-Kermit 8.0 does include a rather pervasive
-          syntax change that might alter the behavior of scripts that
-          depend on the previous behavior. As described in [127]Section
-          5, C-Kermit now accepts doublequotes in most contexts where you
-          previously had to use braces to group multiple words into a
-          single field, or to force inclusion of leading or trailing
-          blanks. Most noticeably, in C-Kermit 7.0 and earlier:
-
-  echo {this is a string}
-
-          would print:
-
-  this is a string
-
-          whereas:
-
-  echo "this is a string"
-
-          printed:
-
-  "this is a string"
-
-          In C-Kermit 8.0, both print:
-
-  this is a string
-
-          To force the doublequotes to be treated as part of the string,
-          use either of the following forms:
-
-  echo {"this is a string"}
-  echo ""this is a string""
-
-          Similarly, to force braces to be treated as part of the string:
-
-  echo "{this is a string}"
-  echo {{this is a string}}
-
-          Other incompatibilities:
-
-         1. Using the SET HOST command to make HTTP connections is no
-            longer supported. Instead, use the new HTTP OPEN command,
-            described in [128]Section 2.2.
-
-   C-Kermit 7.1 Alpha.01 (8 December 2000)
-
-     Its major new features are those listed in the [129]Table of
-          Contents: the FTP client, file scanning, command parsing and
-          scripting improvements, S-Expressions, and support for the
-          Telnet Com Port Option, plus wider availability of the
-          Kerberos, SSL/TLS, and SRP security options for secure Internet
-          connections.
-
-   C-Kermit 7.1.199 Alpha.02 (4 January 2001)
-
-          + C-Kermit now accepts [130]FTP, TELNET, and IKSD URLs as its
-            first command-line argument.
-          + Character-set translation added to the FTP client for
-            [131]filenames. 
-          + Optional [132]setting of date of incoming files by FTP [M]GET
-            from the server date.
-          + [133]FTP CHECK filename added to let FTP client check the
-            existence of a file on the server.
-          + [134]FTP GET /NAMELIST:filename added to get list of server
-            filenames into a local file.
-          + [135]FTP [M]PUT /SERVER-RENAME:template added to make server
-            rename a file as indicated by the template after it has
-            arrived completely.
-          + FTP [M]GET /SERVER-RENAME:template added to make server
-            rename a file as indicated by the template after it has been
-            sent completely.
-          + FTP [136]VDIRECTORY added for getting verbose directory
-            listings from TOPS-20.
-          + [137]FTP TYPE TENEX added for transferring 8-bit binary files
-            with PDP-10s.
-          + Added [138]automatic text/binary mode switching for FTP
-            [M]GET, based on filename patterns (e.g. *.zip, *.gz, *.exe
-            are binary; *.txt, *.c are text).
-          + [139]SET SEND I-PACKETS OFF added for coping with Kermit
-            servers that do not support I packets.
-          + A new option was added to [140]\fword() and \fsplit() for
-            parsing comma-separated lists that might contain empty
-            elements.
-          + Bug fixes including:
-               o {} or "" could not be used as expected to represent the
-                 empty string.
-               o ,- on a line by itself in a macro definition caused
-                 subsequent statements to be skipped.
-               o FTP [M]GET didn't work right if path segments were
-                 included in the filespec.
-               o FTP MGET, if interrupted, did not clear its file list.
-               o Various problems with FTP PUT /AS-NAME that nobody
-                 noticed.
-               o Some FTP messages and displays interfered with each
-                 other.
-               o Parsing of YESTERDAY, TODAY, and TOMORROW in date-time
-                 fields was broken.
-               o Automatic old-to-new dialing directory format conversion
-                 was broken on VMS.
-               o Various source-code portability problems fixed.
-          + Improvement of various HELP and SHOW messages.
-
-   C-Kermit 7.1.199 Alpha.04 (1 April 2001)
-
-          + Big changes:
-               o Changed default modem type from NONE to GENERIC.
-               o Generic dialing now sends no init string at all.
-               o Changed default terminal bytesize from 7 to 8.
-          + New features:
-               o SET SESSION-LOG TIMESTAMPED-TEXT for timestamped session
-                 log.
-          + New modem types:
-               o Conexant modem family
-               o Lucent VENUS chipset
-               o PCTel V.90 chipset
-               o Zoom V.90
-               o Zoom V.92
-          + FTP client:
-               o FTP OPEN /PASSIVE and /ACTIVE switches added.
-               o Now works with servers that that don't include path in
-                 NLST response.
-               o Fixed SEND /RECURSIVE not to follow symlinks (UNIX).
-               o SET FTP VERBOSE-MODE default is now OFF instead of ON.
-          + Kermit protocol:
-               o Fixed what I hope is the last "Receive window full"
-                 error.
-               o SET PREFIXING or SET CONTROL PREFIX now automatically
-                 sets CLEARCHANNEL OFF.
-               o Fixed incorrect report of number of files transferred at
-                 end of transfer.
-               o Fixed SEND /RECURSIVE not to follow symlinks (UNIX).
-          + UNIX:
-               o HTTP and shadow passwords enabled for SCO 5.0.6.
-               o Even with SET FILENAMES CONVERTED, spaces were still
-                 accepted in incoming filenames; now they are converted
-                 to underscores.
-               o Added support for compile-time mktemp()/mkstemp()
-                 selection.
-          + VMS:
-               o Session-log format for scripted sessions fixed.
-          + Scripting:
-               o Fixed \frdir() not to follow symlinks (UNIX).
-               o Fixed \fday() not to dump core for dates prior to 17 Mar
-                 1858.
-          + General:
-               o "Closing blah..." message upon exit could not be
-                 surpressed.
-               o Added /PAGE and /NOPAGE to DELETE switches.
-               o Added GO response for DELETE /ASK (delete all the rest
-                 without asking).
-               o Added GO response to "more?" prompt (for multi-page
-                 screen output).
-               o Updated HELP texts.
-
-   C-Kermit 7.1.199 Beta.01 (10 May 2001)
-
-          + FTP client verbosity adjustments.
-          + Bug with generic modem dialing pausing several secs fixed.
-          + SET HOST /USER:, SET LOGIN USERID, etc, fixed when given no
-            user ID.
-          + A couple \v(dm_blah) dial modifier variables added.
-          + "--version" command-line switch added.
-          + Fixed NetBSD serial-port DTR handling.
-          + Lots of syntax cleanups for Flexelint and gcc -Wall.
-          + Fixed modem-type aliases to not take precedence over real
-            names.
-          + Fixed funny treatment of doublequotes by ECHO command.
-          + Enabled SET SESSION-LOG for VMS and other non-UNIX platorms.
-          + Fixed changing direction in command history buffer.
-          + Fixed handling of IKSD URLs.
-          + Made sure DELETE prints a message if it got any errors.
-
-   C-Kermit 8.0.200 Beta.02 (28 June 2001)
-
-          + Major version number increased from 7 to 8.
-          + [141]SSH command.
-          + More-consistent Kermit protocol defaults.
-          + CONNECT idle timeout and action selection.
-          + CONNECT status variable.
-          + A way to allocate more space for filename lists.
-          + Pseudoterminal handler fixed for late-model Linuxes.
-          + Command-line option -dd for timestamped debug log.
-          + Download directory now works for external protocols too.
-          + GREP /COUNT:variable.
-          + SET ATTRIBUTE RECORD-FORMAT { OFF, ON }.
-          + Bug fixes.
-
-   C-Kermit 8.0.200 Beta.03 (9 Sep 2001)
-
-          + [142]HTTP 1.1 connections and scripting
-          + [143]ON_CTRLC macro for trapping Ctrl-C in scripts
-          + [144]Date-time parsing improvements, timezones, comparison,
-            arithmetic
-          + [145]Pattern-matching improvements
-          + FTP improvements
-          + SET EXIT HANGUP { ON, OFF }
-          + SET FILE EOF { CTRL-Z, LENGTH }
-          + ASK[Q] /TIMEOUT
-          + Bug fixes
-          + New platforms
-
-   C-Kermit 8.0.200 Beta.04 (16 Nov 2001)
-
-          + [146]New Unix man page
-          + [147]New Unix installation instructions
-          + SET TELOPT policies are now enforced on non-Telnet ports if
-            the server begins Telnet negotiations.
-          + SET TERMINAL IDLE-ACTION { TELNET-NOP, TELNET-AYT }.
-          + UUCP lockfile creation race condition fixed.
-          + Dialout, modem signals, hangup, hardware flow control, etc,
-            tested extensively on many platforms, numerous problems
-            fixed.
-          + Improved hints when dialing fails.
-          + SET STOP-BITS 2 can now be given without SET FLOW HARDWARE.
-          + Major improvements in RFC 2217 Telnet Com-Port Control.
-          + Improved ability to REDIAL a modem server port.
-          + kermit -h now shows the command name in the usage usage
-            string.
-          + kermit -h now shows ALL command-line options.
-          + kermit -s blah, where blah is a symlink, now works.
-          + --noperms command-line option = SET ATTRIBUTE PERMISSIONS
-            OFF.
-          + HTTP and HTTPS URLs now supported on the command line.
-          + An http command-line personality is now available.
-          + Initialization file streamlined to load faster, anachronisms
-            removed.
-          + Updated NEWS, INTRO, HELP text, SHOW commands. In particular,
-            see SHOW COMM, HELP SET LINE, HELP WAIT.
-          + Date/time arithmetic routines converted from floating-point
-            to integer arithmetic (internally) for greater accuracy and
-            portability.
-          + Quoted strings containing commas no longer break macro
-            execution.
-          + Dynamic Kermit file-transfer timeouts are now much more
-            aggressive.
-          + New "hot keys" to turn debug.log on/off during file transfer.
-          + Improved hints when file transfer fails.
-          + FTP CD orientation messages are now printed.
-          + -R now accepted on the FTP command line to request Recursion.
-          + -m allows Active or Passive mode to be chosen on the FTP
-            command line.
-          + -dd on the FTP command line creates a timestamped debug.log.
-          + FTP command-line security options filled in.
-          + Improved automatic text/binary mode switching for MGET.
-          + Removed spurious error messages that sometimes occur during
-            MGET.
-          + DIRECTORY, GREP, TYPE, HEAD, and TAIL now have a /OUTPUT:file
-            option.
-          + TYPE /NUMBER adds line numbers.
-          + CAT = TYPE /NOPAGE; MORE = TYPE /PAGE.
-          + GETOK ?-help fixed.
-          + \v(timestamp) (= "\v(ndate) \v(time)")
-          + \v(hour) (hour of the day, 0-23)
-          + \funix2dospath() converts a UNIX path (/) to a DOS one (\).
-          + \fdos2unixpath() converts a DOS (Windows, OS/2) path to a
-            UNIX one.
-          + \fkeywordval() parses name=value pair, allows macro keyword
-            parameters.
-          + We now make every attempt to not write passwords to the
-            debug.log.
-          + New Certficate Authority certificates file, includes the
-            Kermit Project at Columbia University so you can access our
-            IKSD securely.
-          + Secure targets improved and better documented in Unix
-            makefile.
-          + All Linux (libc and glibc) builds consolidated under "make
-            linux".
-          + HP-UX makefile targets now have consistent names.
-          + New aix50 and aix51 targets added.
-
-   C-Kermit 8.0.200 Final (12 Dec 2001)
-
-          + Remote/local-mode confusion on some platforms introduced in
-            Beta.04, fixed.
-          + Many of the makefile targets adjusted, new ones added.
-          + New "make install" target should please most people.
-          + New command: SHOW IKSD.
-          + FTP over TLS.
-          + Last-minute touchups to text messages, HELP text, etc.
-          + Enable modem-signal reading for SCO OSR5 and Unixware 7.
-          + Special superfast TRANSMIT /BINARY /NOECHO /NOWAIT mode
-            added.
-          + Fixed PBX dialing in unmarked-area-code case.
-          + Improved SHOW COMMUNICATIONS tells lockfile directory,
-            typical dialout device name.
-          + Some FTP OPEN command parsing problems fixed.
-          + Some errors in date arithmetic fixed.
-          + New command: SET TERMINAL AUTODOWNLOAD { ..., ERROR { STOP,
-            CONTINUE } }
-          + New command: HELP FIREWALL.
-          + SET MODEM HANGUP-METHOD DTR added as synomym for RS232-SIGNAL
-          + Support for secure URL protocols added: telnets:, ftps:,
-            https:.
-
-   C-Kermit 8.0.201 (8 Feb 2002)
-
-          + Installability as an [148]SSH v2 Subsystem.
-          + [149]SET LOCUS command.
-          + [150]L-versions of CD, DIR, DELETE, MKDIR, etc, to force
-            local execution.
-          + [151]USER and ACCOUNT added as synonyms for FTP USER and FTP
-            ACCOUNT.
-          + [152]SHOW VARIABLES now accepts a list of variables.
-          + Rudimentary support for [153]Caller ID when receiving phone
-            calls.
-          + Up/Down [154]Arrow-key navigation of command history buffer.
-          + [155]Automatic execution of customization file if init file
-            is missing.
-
-   C-Kermit 8.0.206 Beta.01 (11 Oct 2002)
-
-        New commands:
-
-               o ORIENTATION lists location-related variables and their
-                 values.
-               o KCD changes to special directories by their symbolic
-                 names ("kcd ?" for a list).
-               o SET CD HOME path to specify home directory for CD and
-                 KCD commands.
-               o CONTINUE given at top level is equivalent to END --
-                 handy when PROMPT'ed out of a script, to continue the
-                 script.
-
-        New switches or operands for existing commands:
-
-               o GETOK /TIMEOUT
-               o ASK, ASKQ, GETOK /QUIET (suppresses error message on
-                 timeout)
-               o COPY /APPEND now allows concatenating multiple source
-                 files into one dest file.
-               o SET TCP { HTTP-PROXY, SOCKS-SERVER } /USER, /PASSWORD.
-               o DIRECTORY command now accepts multiple filespecs, e.g.
-                 "dir a b c".
-
-        SET QUIET ON now also applies to:
-
-               o SET HOST connection progress messages.
-               o "Press the X or E key to cancel" file-transfer message.
-               o REMOTE CD response.
-               o REMOTE LOGIN response.
-
-        Improvements and new features:
-
-               o Numerous FTP client fixes and new features, listed
-                 below.
-               o C-Kermit, when in remote mode at the end of a file
-                 transfer, now prints a one-line "where" message. Control
-                 with SET TRANSFER REPORT.
-               o Unix makefile "install" target now creates an UNINSTALL
-                 script.
-               o Improved operation and performance on RFC 2217 Telnet
-                 connections.
-               o Improved CONNECT (interactive terminal connection)
-                 performance.
-               o HELP text updated for many commands.
-
-        New or fixed makefile targets:
-
-               o Solaris 9 (several variations)
-               o Concurrent PowerMAX
-               o Mac OS X 10.2
-               o FreeBSD 1.0
-               o FreeBSD 4.6, 5.0
-               o AIX 5.2, 5.3
-
-        Bugs fixed (general):
-
-               o Failure to run in VMS Batch fixed.
-               o LDIRECTORY fixed to run Kermit's built-in DIRECTORY
-                 command rather than an external one.
-               o Fixed Solaris and other SVORPOSIX builds to find out
-                 their full hostnames rather than just the "uname -n"
-                 name.
-               o Fixed some problems matching strings that start with
-                 ".".
-               o Fixed some problems matching pattern that contain
-                 {a,b,c} lists.
-               o Fixed erroneous reporting of text-mode reception as
-                 binary when sender did not report the file size
-                 (cosmetic only).
-               o Many problems with SWITCH statements fixed.
-               o Fixed SET OPTIONS DIRECTORY /DOTFILES to work for server
-                 too.
-               o Fixed DELETE to print an error message if the file was
-                 not found.
-               o Fixed SET CONTROL UNPREFIX ALL and SET PREFIXING NONE to
-                 do the same thing.
-               o Fixed bugs executing macros from within the ON_EXIT
-                 macro.
-               o \fday() and \fnday() fixed for dates prior to 17 Nov
-                 1858.
-               o Serial speed-changing bug in Linux fixed.
-               o "Unbalanced braces" script parsing errors when using
-                 \{number} fixed.
-               o "if defined \v(name)" fixed to behave as described in
-                 the book.
-               o Fixed Problems caused by LOCAL variables whose names are
-                 left substrings of macro names.
-               o The INPUT command was fixed to honor the PARITY setting.
-               o Fixed bug with COPY to existing file that is longer than
-                 source file.
-               o REINPUT command failed to strip braces/quotes around its
-                 target string.
-               o Network directory lookups didn't work for SSH
-                 connections.
-               o REMOTE SET { FILE, TRANSFER } CHARACTER-SET fixed.
-               o Closed some holes whereby an incompletely received file
-                 was not deleted when SET FILE INCOMPLETE is DISCARD,
-                 e.g. when the Kermit is hung up upon.
-               o SET XFER CHARACTER-SET TRANSPARENT fixed to do the same
-                 as SET XFER TRANSLATION OFF.
-               o SET HOST PTY (e.g. SSH) connection fixed to pass along
-                 window-size changes.
-               o C-Kermit search path for TAKE files was accidentally
-                 disabled.
-
-        FTP client bugs fixed:
-
-               o Character set translation was broken on little-endian
-                 (e.g. PC) architectures.
-               o FTP PUT /SERVER-RENAME:, /RENAME-TO:, /MOVE-TO: switches
-                 were sticky.
-               o Make SET TRANSFER MODE MANUAL apply to FTP.
-               o Make SET FILE INCOMPLETE { KEEP, DISCARD } apply to FTP.
-               o FTP MGET /UPDATE handled equal times incorrectly.
-               o FTP MGET /RECOVER fixed to ignore file dates, use only
-                 size.
-               o FTP MGET /RECOVER sometimes downloaded files it didn't
-                 need to.
-               o FTP downloads with TRANSFER DISPLAY BRIEF could give
-                 misleading error messages.
-               o FTP MGET temp file not deleted if FTP DEBUG set to OFF
-                 after it was ON.
-               o LOCUS not switched back when FTP connection is lost.
-               o Set incoming file date even if it was not completely
-                 received.
-               o FTP MGET sent SIZE and MDTM commands even when it didn't
-                 have to.
-               o FTP MGET sent SIZE and MDTM commands even when it knew
-                 they wouldn't work.
-               o FTP MGET failed if no files were selected for download.
-               o FTP MGET a* b* c* would fail to get any c*'s if no b*'s
-                 existed.
-               o Big problems canceling MGET with Ctrl-C.
-               o Some extraneous LOCUS dialogs squelched.
-               o Some inconsistencies in SET FTP FILENAMES AUTO fixed.
-               o Fixed file-descriptor pileup after multiple MGETs when
-                 using mkstemp().
-               o Fixed "mget foo", where foo is a directory name.
-
-        FTP improvements:
-
-               o New [156]FTP protocol features added (FEAT, MLSD).
-               o FTP MGET /RECURSIVE now works as expected if server
-                 supports MLSD.
-               o FTP MGET /DATES-DIFFER to download if local and remote
-                 file dates differ.
-               o FTP DATES default changed to ON.
-               o FTP MPUT, MGET /EXCEPT now allows up to 64 patterns (up
-                 from 8).
-               o Top-level SITE and PASSIVE commands added for
-                 convenience.
-               o MGET /COLLISION:APPEND /AS-NAME:newfile *.* puts all
-                 remote files into one local file.
-               o SET FTP SERVER-TIME-OFFSET for when server has wrong
-                 timezone set.
-               o Allow for alternative server interpretations of [M]MPUT
-                 /UNIQUE.
-               o SET FTP ANONOMOUS-PASSWORD lets you specify the default
-                 anonymous password.
-               o Allow "GET /RECURSIVE path/file" to force local
-                 subdirectory creation.
-               o SET FTP DISPLAY is like SET TRANSFER DISPLAY but applies
-                 only to FTP.
-               o FTP { ENABLE, DISABLE } new-protocol-feature-name.
-               o FTP MGET /NODOTFILES.
-               o Debug log now records FTP commands and responses in
-                 grep-able format.
-
-   [ [157]Top ] [ [158]Contents ] [ [159]C-Kermit ] [ [160]Kermit Home ]
-  __________________________________________________________________________
-
-1. FIXES SINCE VERSION 7.0.196 First, the changes from 7.0.196 to 7.0.197...
-Source and makefile tweaks to get successful builds on platforms that were not
-available in time for the 7.0 release:
-
-     * 4.2BSD
-     * 4.3BSD
-     * AIX 4.3
-     * AT&T 3B2 and 3B20
-     * BeOS 4.5
-     * CLIX
-     * Interactive UNIX System V/386 R3.2 V4.1.1
-     * OS-9/68000
-     * OSF/1 1.3.
-     * PS/2 AIX 1.2.1
-     * SCO OSR5.0.x
-     * SCO Xenix 2.3.4
-     * SINIX 5.41/Intel
-     * Stratus FTX
-     * Stratus VOS
-     * SunOS 4.1 with X.25
-     * Ultrix 4.2
-     * Unixware 2.0
-
-   There were no functional changes from 196 to 197.
-
-   Fixes applied after C-Kermit 7.0.197 was released:
-
-   Source code: Big flexelint and "gcc -Wall" audit and cleanup.
-
-   Configuration:
-     * Solaris RTS/CTS (hardware flow control) didn't work.
-     * BSDI RTS/CTS worked only in one direction.
-     * FreeBSD 4.0 with ncurses 5.0 broke interactive command parsing.
-     * QNX-32 build lacked -DBIGBUFOK so couldn't execute big macros.
-
-   Connections:
-     * SET HOST /PTY didn't work on some platforms.
-     * Broken SET HOST /USER:xxx /PASSWORD:yyy /ACCOUNT:zzz switches
-       fixed.
-     * Transparent printing was broken in Unix.
-     * ANSWER 0 (wait forever) didn't work.
-     * Some problems in Multitech modem command strings.
-     * Spurious "?Sorry, can't condition console terminal" errors.
-     * Disabling modem command strings by setting them to nothing broke
-       dialing.
-     * SET DIAL TIMEOUT value was usually ignored.
-     * SET DIAL METHOD PULSE didn't work.
-     * Certain modem commands, if changed, not refreshed if modem type
-       changed.
-     * SET SESSION-LOG command was missing from VMS.
-     * VMS session log format fixed for scripts.
-     * HANGUP by dropping DTR didn't work in NetBSD.
-     * SET FLOW /AUTO versus SET FLOW confusion fixed.
-     * Spurious secondary Solaris lockfile removed.
-     * SCO OSR5 DTR On/Off hangup.
-     * UUCP lockfile race condition.
-
-   Commands and scripts:
-     * Missing CAUTIOUS and FAST commands restored.
-     * Broken PTY command in late-model Linuxes fixed (API changed).
-     * Fixed off-by-one error in command recall when switching direction.
-     * Fixed recall of commands that contain '?'.
-     * COPY /SWAP-BYTES didn't work on some architectures.
-     * Various combinations of COPY switches didn't work.
-     * Various problems with COPY or RENAME with a directory name as
-       target.
-     * SHIFT didn't decrement \v(argc) if used within IF, ELSE, or SWITCH
-       block.
-     * SHIFT didn't affect the \%* variable.
-     * Divide by zero improperly handled in some \function()s.
-     * Problems with RETURN from right-recursive functions.
-     * FSEEK /LINE \%c LAST didn't work if already at end.
-     * Some buffer vulnerabilities and potential memory leaks were
-       discovered and fixed.
-     * \frdirectory() fixed not to follow symbolic links.
-     * SET EXIT WARNING OFF fixed to work when EXIT given in a script.
-     * Missing DELETE and MKDIR error message fixed.
-     * \fday() core dump for ancient dates fixed.
-
-   File transfer:
-     * SEND /COMMAND was broken.
-     * CRECEIVE was broken (but RECEIVE /COMMAND was OK).
-     * Quoting wildcard chars in filenames didn't work.
-     * Problems canceling streaming file transfers with X or Z.
-     * Problems shifting between streaming and windowing file transfer.
-     * Non-FULL file-transfer displays erroneously said STREAMING when
-       not.
-     * An active SEND-LIST prevented GET from working.
-     * SET SERVER GET-PATH interpretation of relative names like "." was
-       wrong.
-     * The MAIL command was broken.
-     * "kermit -s *" might have skipped some files.
-     * Transaction log entries were not made for external protocol
-       transfers.
-     * File count report fixed to show number of files actually
-       transferred.
-     * Fixed filename conversion to convert spaces to underscores.
-     * Made SET PREFIXING / SET CONTROL PREFIX also adjust CLEARCHANNEL.
-     * More "Receive window full" errors fixed.
-     * Broken terminal buffering after curses display in Solaris fixed.
-     * SET FILE INCOMPLETE DISCARD did not work in all cases.
-     * Packet log changed to reformat the start-of-packet character
-       printably.
-     * Dynamic timeouts could grow ridiculously large.
-
-   Character sets:
-     * Hebrew-7 translations missed the letter Tav.
-     * C1 area of CP1252 was ignored.
-     * SET TRANSFER CHARACTER-SET TRANSPARENT could give garbage
-       translations.
-     * TRANSLATE might not work on Little Endian architectures.
-     * Insufficient range checking in certain TRANSLATE operations.
-
-   The following bugs in C-Kermit 8.0.200 were fixed in 8.0.201:
-
-     * An obscure path through the code could cause the Unix version of
-       C-Kermit to dump core during its startup sequence. This happened
-       to only one person, but now it's fixed.
-     * When C-Kermit 8.0 is in Kermit server mode and the client says
-       "get blah", where blah (on the server) is a symlink rather than a
-       real file, the server unreasonably refused to send the linked-to
-       file.
-     * When C-Kermit is an FTP client and says "get foo/bar" (i.e. a
-       filename that includes one or more path segments), it failed to
-       accept the incoming file (this happened only with GET, not MGET).
-     * Array references should be case insensitive but only lowercase
-       array letters were accepted.
-     * SHOW VARIABLES dumped core on \v(sexpression) and \v(svalue).
-     * Spurious refusals of remote directory listings if the remote
-       server's date was set in the past.
-     * In AIX, and maybe elsewhere too, Kermit's COPY command always
-       failed with "Source and destination are the same file" when the
-       destination file didn't exist.
-     * The VMS version of C-Kermit did not work in Batch or when SPAWN'd.
-       To compound the problem, it also pretty much ignored the -B and -z
-       command-line options, whose purpose is to work around such
-       problems.
-     * C-Kermit 8.0 could not be built on IRIX 5.x.
-     * The C-Kermit 8.0 build for QNX6 said it was an "(unknown
-       version)".
-
-   Other fixes are listed in the [161]previous section.
-
-   [ [162]Top ] [ [163]Contents ] [ [164]C-Kermit ] [ [165]Kermit Home ]
-  __________________________________________________________________________
-
-2. SSH AND HTTP
-
-  2.1. SSH Connections
-
-     This section does not apply to [166]Kermit 95 2.0, which has its
-     own built-in SSH client, which is documented [167]SEPARATELY. 
-
-   On most UNIX platforms, C-Kermit can make SSH (Secure SHell)
-   connection by running the external SSH command or program through its
-   pseudoterminal interface. The command is:
-
-   SSH text
-          Tells Kermit to start the external SSH client, passing the
-          given text to it on the command line. Normally the text is just
-          the hostname, but it can be anything else that is acceptable to
-          the ssh client. If the command succeeds, the connection is made
-          and Kermit automatically enters CONNECT (terminal) mode. You
-          can use the SSH command to make a connection to any host that
-          has an SSH server.
-
-   Kermit's SSH command gives you all the features of Kermit on an SSH
-   connection: command language, file transfer, character-set
-   translation, scripting, and all the rest. By default, C-Kermit invokes
-   SSH with "-e none", which disables the ssh escape character and makes
-   the connection transparent for purposes of file transfer. You can,
-   however, change the SSH invocation to whatever else you might need (an
-   explicit path, additional command-line arguments, etc) with:
-
-   SET SSH COMMAND text
-          Specifies the system command that Kermit's SSH command should
-          use to invoke the external SSH client. Use this command to
-          supply a specific path or alternative name, or to include
-          different or more command-line options.
-
-   In most cases, these connections work quite well. They can be scripted
-   like any other connection, and file transfer goes as fast as, or
-   faster than, on a regular Telnet connection. In some cases, however,
-   the underlying pseudoterminal driver is a limiting factor, resulting
-   in slow or failed file transfers. Sometimes you can work around such
-   problems by reducing the Kermit packet length. Note that Kermit does
-   not consider SSH connections to be reliable, so it does not offer to
-   use streaming in Kermit protocol transfers (but you can force it with
-   SET RELIABLE or SET STREAMING if you wish).
-
-   The SSH command is like the TELNET command: it enters CONNECT mode
-   automatically when the connection is made. Therefore, to script an SSH
-   connection, use:
-
-  set host /pty ssh -e none [ other-options ] host
-  if fail ...
-
-   to make the connection.
-
-   Here's a sequence that can be used to make a connection to a given
-   host using Telnet if the host accepts it, otherwise SSH:
-
-  if not defined \%1 exit 1 Usage: \%0 host
-  set quiet on
-  set host \%1 23 /telnet
-  if fail {
-      set host /pty ssh -l \m(user) -e none \%1
-      if fail exit 1 \%1: Telnet and SSH both fail
-      echo SSH connection to \%1 successful
-  } else {
-      echo Telnet connection to \%1 successful
-  }
-
-   In SSH v2, it is possible to make an SSH connection direct to a Kermit
-   server system if the host administrator has configured the SSH server
-   to allow this; [168]CLICK HERE for details.
-
-   Since Kermit uses external ssh client software, and since there are
-   different ssh clients (and different releases of each one), the exact
-   command to be used to make an SSH/Kermit connection can vary. Here is
-   the command for the OpenSSH 3.0.2p1 client:
-
-set host /pipe ssh -e none [ -l username ] -T -s hostname kermit
-
-   Example:
-
-set host /pipe ssh -e none -l olga -T -s hq.xyzcorp.com kermit
-
-   The SSH client might or might not prompt you for a password or other
-   information before it makes the connection; this depends on your SSH
-   configuration (your public and private keys, your authorized hosts
-   file, etc). Here's a brief synopsis of the OpenSSH client command
-   syntax ("man ssh" for details):
-
-   -e none
-          This tells the SSH client to use no escape character. Since we
-          will be transferring files across the connection, we don't want
-          the connection to suddenly block because some character in the
-          data.
-
-   -l username
-          This is the username on the remote host. You can omit the -l
-          option and its argument if your local and remote usernames are
-          the same. If they are different, you must supply the remote
-          username.
-
-   -T
-          This tells the SSH client to tell the SSH server not to
-          allocate a pseudoterminal. We are not making a terminal
-          connection, we don't need a terminal, and in fact if a terminal
-          were allocated on the remote end, the connection would not
-          work.
-
-   -s ... kermit
-          This tells the SSH client to tell the SSH server to start the
-          specified subsystem ("kermit") once the connection is made. The
-          subsystem name comes after the hostname.
-
-   hostname
-          The IP host name or address of the desired host.
-
-   You might want to include other or additional ssh command-line
-   options; "man ssh" explains what they are. Here are some examples for
-   the OpenSSH 3.0.2p1 client:
-
-   -oClearAllForwardings yes
-   -oForwardAgent no
-   -oForwardX11 no
-   -oFallbackToRsh no
-          These ensure that a secure connection is used and that the
-          connection used for file transfer is not also used for
-          forwarding other things that might be specified in the
-          ssh_config file.
-
-   -oProtocol 2
-          (i.e. SSH v2) Ensures that the negotiated protocol supports
-          subsystems.
-
-   Once you have an SSH connection to a Kermit server, it's just like any
-   other connection to a Kermit server (and very similar to a connection
-   to an FTP server). You give the client file transfer and management
-   commands for the server, and the server executes them. Of course you
-   can also give the client any other commands you wish.
-
-   [ [169]SSH Kermit Server Subsystem ] [ [170]Kermit 95 Built-in SSH
-   Client ]
-     _________________________________________________________________
-
-  2.2. HTTP Connections
-
-   Hypertext Transfer Protocol, or HTTP, is the application protocol of
-   the World Wide Web (WWW), used between Web browsers (clients) and Web
-   servers. It allows a client to get files from websites, upload files
-   to websites, delete files from websites, get information about website
-   directories and files, and interact with server-side CGI scripts.
-   C-Kermit includes an HTTP client capable of both clear-text and secure
-   HTTP connections, that can do all these tasks and can be automated
-   through the Kermit scripting language.
-
-   Although C-Kermit 7.0 could make HTTP connections to Web servers, it
-   could do so only when no other connection was open, and the procedure
-   was somewhat awkward. C-Kermit 8.0 improves matters by:
-
-     * Allowing an HTTP connection to be open at the same time as a
-       regular SET LINE or SET HOST connection, and also at the same time
-       as an FTP connection ([171]Section 3);
-     * Upgrading the HTTP protocol level from 1.0 to 1.1, thus allowing
-       for persistent connections, in which a series of commands can be
-       sent on the same connection, rather than only one as in HTTP 1.0
-       (and C-Kermit 7.0);
-     * Providing for "one-shot" URL-driven HTTP operations such as GET or
-       PUT.
-     * Providing a distinct HTTP command-line personality.
-
-   Persistent HTTP connections are managed with the following commands:
-
-   HTTP [ switches ] OPEN [ security-options ] host-or-url [ port ] 
-          Opens a persistent connection to the specified host (IP host
-          name or address) on the specified port. If any switches
-          (options, listed in the next section) are included, their
-          values are saved and used for all subsequent HTTP action
-          commands on the same connection. If no port is specified, HTTP
-          (80) is used. A Uniform Resource Locator (URL, [172]RFC 1738)
-          can be given instead of a hostname (or address) and port (but
-          the URL can not include a directory/file path). The security
-          options are explained [173]below. The HTTP OPEN command
-          replaces the C-Kermit 7.0 SET HOST hostname HTTP command, which
-          no longer works with HTTP GET and related commands.
-
-   HTTP CLOSE
-          Closes any open HTTP connection and clears any saved switch
-          values.
-
-   A URL starts with a protocol name, which must be http or https in this
-   case; optionally includes a username and password; and must contain a
-   host name or address:
-
-  protocol://[user[.password]]@host[:port][URI]
-
-   HTTP is Hypertext Transfer Protocol. HTTPS is the secure (SSL/TLS)
-   version of HTTP. The TCP service port is derived from the protocol
-   prefix (so normally the ":port" field is omitted). Thus the URL
-   protocol name specifies a default TCP service port and the URL user
-   and password fields can take the place of the /USER and /PASSWORD
-   switches ([174]Section 2.2.1). The optional URI is a "compact string
-   of characters for identifying an abstract or physical resource"
-   ([175]RFC 2396), such as a file. It must begin with a slash (/); if
-   the URI is omitted, "/" is supplied. Examples:
-
-   http open http://www.columbia.edu/
-          Equivalent to http open www.columbia.edu or http open
-          www.columbia.edu http.
-
-   http open https://olga.secret@www1.xyzcorp.com/
-          Equivalent to http /user:olga /pass:secret open
-          www1.xyzcorp.com https.
-
-   Persistence is accomplished unilaterally by C-Kermit 8.0. An HTTP 1.0
-   server closes the connection after each action. Although HTTP 1.1
-   allows multiple actions on the same connection, an HTTP 1.1 server
-   tends to close the connection if it is idle for more than a few
-   seconds, to defend itself against denial-of-service attacks. But when
-   you use Kermit's HTTP OPEN command to create a connection, Kermit
-   reopens it automatically (if necessary) for each HTTP action until you
-   close it with HTTP CLOSE, regardless of the server's HTTP protocol
-   version, or how many times it closes the connection.
-
-   Firewalls can be negotiated through proxies with the following
-   commands:
-
-   SET TCP HTTP-PROXY [ host[:port] ]
-          If a host (by hostname or IP address) is specified, Kermit uses
-          it as a proxy server when attempting outgoing TCP connections
-          -- not only HTTP connections, but all TCP/IP connections,
-          Telnet and FTP included. This allows Kermit to adapt to the
-          HTTP firewall penetration method (as opposed to other methods
-          such as SOCKS4). If no hostname or ip-address is specified, any
-          previously specified Proxy server is removed. If no port number
-          is specified, the "http" service is used. This command must be
-          given before the HTTP OPEN command if a proxy is to be used or
-          canceled.
-
-   HTTP [ switches ] CONNECT host[:port]
-          Instructs the HTTP server to act as a proxy, establishing a
-          connection to the specified host (IP hostname or address) on
-          the given port (80 = HTTP by default) and to redirect all data
-          transmitted between Kermit and itself to the given host for the
-          life of the connection. This command is to be used only for
-          debugging HTTP proxy connections. If a proxy connection is
-          required, instruct Kermit to use the proxy with the SET TCP
-          HTTP-PROXY command.
-
-    2.2.1. HTTP Command Switches
-
-   HTTP switches, like all other switches, are optional. When HTTP
-   switches are included with the HTTP OPEN command, they apply
-   automatically to this and all subsequent HTTP actions (GET, PUT, ...)
-   on the same connection until an HTTP CLOSE command is given. So if you
-   include switches (or the equivalent URL fields, such as user and
-   password) in the HTTP OPEN command, you can omit them from subsequent
-   commands on the same connection. If the connection has closed since
-   your last command, it is automatically reopened with the same options.
-
-   If you include switches with an HTTP action command (such as GET or
-   PUT), they apply only to that command.
-
-   /USER:name
-          To be used in case a page requires a username for access. The
-          username is sent with page requests. If it is given with the
-          OPEN command it is saved until needed. If a username is
-          included in a URL, it overrides the username given in the
-          switch. CAUTION: Username and password (and all other
-          information, including credit card numbers and other material
-          that you might prefer to protect from public view) are sent
-          across the network in clear text on regular HTTP connections,
-          but authentication is performed securely on HTTPS connections.
-
-   /PASSWORD:text
-          To be used in case a web page requires a password for access.
-          The password is sent with page requests. If it is given with
-          the OPEN command it is saved until needed. If a password is
-          given in a URL, it overrides the one given here. CAUTION: (same
-          as for /USER:).
-
-   /AGENT:user-agent
-          Identifies the client to the server. Overrides the default
-          agent string, which is "C-Kermit" (for C-Kermit) or "Kermit-95"
-          (for Kermit 95).
-
-   /ARRAY:array-designator
-          Tells Kermit to store the response headers in the given array,
-          one line per element. The array need not be declared in
-          advance. Example: /array:&a.
-
-   /TOSCREEN
-          Tells Kermit to display any response text on the screen. It
-          applies independently of the output file specification; thus it
-          is possible to have the server response go to the screen, a
-          file, both, or neither.
-
-   /HEADER:header-item(s)
-          Used for specifying any optional headers to be sent with HTTP
-          requests.
-
-  /HEADER:tag:value
-
-          To send more than one header, use braces for grouping:
-
-  /HEADER:{{tag:value}{tag:value}...}
-
-          For a list of valid tags and value formats see [176]RFC 2616,
-          "Hypertext Transfer Protocol -- HTTP/1.1". A maximum of eight
-          headers may be specified.
-
-    2.2.2. HTTP Action Commands
-
-   HTTP actions can occur within a persistent connection, or they can be
-   self-contained ("connectionless"). A persistent HTTP connection begins
-   with an HTTP OPEN command, followed by zero or more HTTP action
-   commands, and is terminated with an HTTP CLOSE command:
-
-  http open www.columbia.edu
-  if failure stop 1 HTTP OPEN failed: \v(http_message)
-  http get kermit/index.html
-  if failure stop 1 HTTP GET failed: \v(http_message)
-  (more actions possible here...)
-  http close
-
-   A self-contained HTTP action occurs when a URL is given instead of a
-   remote file name to an HTTP action command. In this case, Kermit makes
-   the HTTP connection, takes the action, and then closes the connection.
-   If an HTTP connection was already open, it is closed silently and
-   automatically.
-
-  http get http://www.columbia.edu/kermit/index.html
-
-   Kermit's HTTP action commands are as follows. Switches may be included
-   with any of these to override switch (or default) values given in the
-   HTTP OPEN command.
-
-   HTTP [ switches ] GET remote-filename [ local-filename ]
-          Retrieves the named file from the server specified in the most
-          recent HTTP OPEN command for which a corresponding HTTP CLOSE
-          command has not been given. The filename may not include
-          wildcards (HTTP protocol does not support them). If no HTTP
-          OPEN command is in effect, this form of the HTTP GET command
-          fails. The default local filename is the same as the remote
-          name, but with any pathname stripped. For example, the command
-          http get kermit/index.html stores the file in the current local
-          directory as index.html. If the /HEADERS: switch is included,
-          information about the file is also stored in the specified
-          array (explained in [177]Section 2.2.3). All files are
-          transferred in binary mode. HTTP does not provide for
-          record-format or character-set conversion.
-
-   HTTP [ switches ] GET url [ local-filename ]
-          When HTTP GET is given a URL rather than a filename, Kermit
-          opens a connection to the designated server (closing any
-          previously open HTTP connection), gets the file, and then
-          closes the connection. If the URL does not include a filename,
-          index.html is supplied. This is the self-contained one-step
-          "connectionless" method for getting a file from a Web server.
-          The data is not interpreted; HTTP GET is like "lynx -source"
-          rather than "lynx -dump".
-
-   In the remaining HTTP action commands, the distinction between a
-   remote filename and a URL are the same as in the HTTP GET command.
-
-   HTTP [ switches ] HEAD remote-filename-or-url [ local-filename ]
-          Like GET except without actually getting the file; instead it
-          retrieves only the headers. If the /ARRAY: or /TOSCREEN switch
-          is included, there is no default local output filename but you
-          can still specify one. If neither of these switches is
-          included, the default local filename is the same as the remote
-          filename, but with any path stripped and with ".head" appended.
-          The HEAD command can be used in a script with the /ARRAY:
-          switch to retrieve information about the requested resource to
-          determine whether the resource should actually be retrieved
-          with a subsequent GET request.
-
-   HTTP [ switches ] INDEX remote-directory-or-url [ local-filename ]
-          Asks the server to send a listing of the files in the given
-          server directory. This command is not supported by most Web
-          servers. Even when it is supported, there is no standard format
-          for the listing.
-
-   HTTP [ switches ] POST [ /MIME-TYPE:type ] source-file
-          remote-path-or-url [ result-file ]
-          Sends data to a process running on the remote host; the result
-          is usually an HTML file but could be anything. The data to be
-          posted must be read from a local file (the source-file). If a
-          result file is specified, Kermit stores the server's response
-          in it.
-
-   HTTP [ switches ] PUT [ MIME-TYPE:type ] local-file [
-          remote-file-or-url [ result-file ] ]
-          Uploads a local file to the server. Only the name of a single
-          file can be given; wildcards (and group transfers) are not
-          supported by HTTP protocol. If no remote filename is given, the
-          file is sent with the same name as the local file, but with any
-          pathname stripped.
-
-   HTTP [ switches ] DELETE remote-file-or-url [ local-result-file ]
-          Asks the server to delete the specified single file. If a
-          result file is specified, it will contain any response data
-          returned by the server.
-
-   Note the limitations of HTTP protocol compared to (say) FTP or Kermit.
-   There is no command for changing directories, no standard way to get
-   file or directory lists, no way to transfer file groups by using
-   wildcard notation, etc, and therefore no good way to (say) fetch all
-   pages, descend through subdirectories, perform automatic updates, etc.
-   There is no assurrance a connection will stay open and, as noted,
-   there is no provision for data conversion between unlike platforms.
-   The data's MIME headers can be used for postprocessing.
-
-    2.2.3. HTTP Headers
-
-   Each HTTP request and response contains a set of name/value pairs
-   called headers. HTTP headers are specified in [178]RFC 2616. For
-   example, an HTTP GET request for /index.html on www.columbia.edu
-   contains the following headers:
-
-  GET /index.html HTTP/1.1
-  Host: www.columbia.edu:80
-  User-agent: C-Kermit 8.0
-  Authorization: Basic base64-encoded-username-password
-
-   These might be followed by any others specified with a /HEADERS:
-   switch:
-
-  Accept: image/gif, image/x-xbitmap, image/jpeg, *.*
-  Accept-Encoding: gzip
-  Accept-Language: en
-  Accept-Charset: iso-8859-1,utf-8
-  Cookie: cookie-data
-
-   The server sends back a short report about the file prior to sending
-   the file contents. Example:
-
-  HTTP/1.1 200 OK
-  Date: Fri, 24 Aug 2001 21:09:39 GMT
-  Server: Apache/1.3.4 (Unix)
-  Last-Modified: Mon, 06 Aug 2001 21:16:13 GMT
-  ETag: "1fa137-10d7-3b6f091d"
-  Accept-Ranges: bytes
-  Content-Length: 4311
-  Content-Type: text/html
-
-   If you want to have this information available to a Kermit script you
-   can use the /ARRAY switch to have Kermit put it in array, one line per
-   array element. Example:
-
-  set exit warning off
-  http open www.columbia.edu
-  if fail exit 1 Can't reach server
-  http /array:&a get /index.html
-  if fail exit 1 Can't get file
-  echo Header lines: \fdim(&a)
-  for \%i 1 \fdim(&a) 1 {
-      echo \%i. \&a[\%i]
-  }
-
-   Note that the "Date:" item is the current date and time; the
-   "Last-Modifed:" item is the file's modification date and time. An
-   example showing how to use this information is presented in
-   [179]Section 8.13.7.
-
-    2.2.4. Secure HTTP Connections
-
-   SSL/TLS (Secure Sockets Layer / Transport Layer Security) is the
-   protocol used to secure HTTP, SMTP, and other Internet applications.
-   See the [180]C-Kermit Reference Section 5.4 for an introduction to
-   SSL/TLS. To make a secure HTTP connection, you need:
-
-    1. A secure client (a version of C-Kermit or Kermit 95 with SSL/TLS
-       security built in). Type "check ssl" at the Kermit prompt to make
-       sure you have it.
-    2. A secure server to connect to.
-    3. The CA Root Certificate used to authenticate the server to the
-       client. (see [181]Section 15 of the security reference for an
-       introduction to certificates).
-
-   And you must make a connection to the secure HTTP port: service name
-   HTTPS, port number 443 (as opposed to service HTTP, port 80). You can
-   also make secure connections to other ports by including the /TLS or
-   /SSL switch with the HTTP OPEN command, if the host supports SSL/TLS
-   on the given port:
-
-   The quality of the SSL/TLS connection depends on the cipher suite.
-   There are several possibilities:
-
-   Anonymous cipher suite:
-          If an anonymous cipher suite is negotiated, the connection is
-          encrypted but there is no authentication. This connection is
-          subject to a Man-In-The-Middle (MITM) attack.
-
-   X.509 certificate on the server:
-          When you connect to certain secure servers, an X.509
-          certificate is returned. This certificate is issued to a
-          special hostname, something like www1.xyzcorp.com or
-          wwws.xyzcorp.com (rather than the normal www.xyzcorp.com). It
-          is signed by the host's Certificate Authority (CA). If the host
-          certificate is configured on the client, it can be used to
-          verify the certificate received from the server. If the
-          certificate it verified as authentic, a check is made to ensure
-          it has not expired and it was issued to the host you were
-          attempting to connect to. If you had asked to connect to (say)
-          www.xyzcorp.com but were given a certificate for
-          www1.xyzcorp.com, you would be prompted for permission to
-          continue.
-
-          If the verification succeeded, the connection would be
-          encrypted with one-way (server-to-client) authentication. This
-          connection is not subject to a MITM attack.
-
-          If a username and password are transmitted over this
-          connection, they are not subject to interception. However, the
-          standard risks associated with passing the password to the host
-          for verification apply; for example, if the host has been
-          compromised, the password will be compromised.
-
-   X.509 client certificate:
-          If a connection has been established with an X.509 server
-          certificate, the server can ask the client to send a
-          certificate of its own. This certificate must be verified
-          against a CA Root certificate. The certificate itself (or
-          subject info from the certificate) is used to determine the
-          authorization for the client, and if successful, the username
-          and password need not be sent to the server.
-
-   Kerberos 5:
-          Instead of using X.509 certifcates, Kerberos 5 can be used to
-          perform the authentication and key exchange. In this situation,
-          there is mutual authentication between the client and server.
-          The Kerberos 5 principal is used by the server to look up the
-          appropriate authorization data. There is no need to send
-          username and password.
-
-   An HTTP connection is made with the HTTP OPEN command:
-
-   HTTP [ switches ] OPEN [ { /SSL, /TLS } ] host [ port ] 
-          If /SSL or /TLS switches are included (these are synonyms), or
-          if the service is HTTPS or the port is 443, a secure connection
-          is attempted using the current authentication settings; see
-          HELP SET AUTHENTICATION for details ([182]Section 6.2 of the
-          security reference). If the no /SSL or /TLS switch is included
-          but the port is 443 or the service is HTTPS, a secure
-          connection is attempted. If an /SSL or /TLS switch is included
-          but a port is not specified, an SSL/TLS connection is attempted
-          on the default port (80).
-
-   Certificates are covered in the separate [183]Kermit Security
-   Reference for C-Kermit 8.0. You should let Kermit know to verify
-   certificates with the SET AUTHENTICATION TLS command. For example:
-
-   SET AUTHENTICATION TLS CRL-DIR directory
-          Specifies a directory that contains certificate revocation
-          files where each file is named by the hash of the certificate
-          that has been revoked.
-
-   SET AUTHENTICATION TLS CRL-FILE filename
-          Specifies a file that contains a list of certificate
-          revocations.
-
-   SET AUTHENTICATION TLS VERIFY-DIR directory
-          Specifies a directory that contains root CA certificate files
-          used to verify the certificate chains presented by the peer.
-          Each file is named by a hash of the certificate.
-
-   SET AUTHENTICATION TLS VERIFY-FILE filename
-          Specifies a file that contains root CA certificates to be used
-          for verifying certificate chains.
-
-   SET AUTHENTICATION TLS VERIFY OFF
-          Tells Kermit not to require a certificate and accept any
-          certificate that is presented regardless of whether it is
-          valid.
-
-   There are many other options; see the security document for details.
-
-   Now suppose you need need to fetch the file denoted by the following
-   URL:
-
-  https://myuserid:mypassword@wwws.xyzcorp.com/clients/info/secret.html
-
-   Once you have set up the handling of certificates as desired, you can
-   use the following Kermit commands:
-
-  http /user:myuserid /password:mypassword open www1.xyzcorp.com https
-  if success {
-      http get /clients/info/secret.html
-      http close
-  }
-
-   As another example, let's say that you have a web form you need to
-   populate with three fields: red,white and blue.
-
-  <FORM ACTION="http://www.xyzcorp.com/cgi-bin/form.cgi" METHOD="POST">
-  <INPUT NAME="Red">
-  <INPUT NAME="White">
-  <INPUT NAME="Blue">
-  </FORM>
-
-   You can handle this with the HTTP POST command. The data to be posted
-   is stored in the local file data.txt.
-
-  Red=seven stripes&White=six stripes&Blue=fifty stars
-
-   and the response from the server will be stored into response.txt.
-
-  http open www.xyzcorp.com http
-  if success {
-    http /array:c post data.txt /cgi-bin/form.cgi response.txt
-    http close
-  }
-
-   In this scenario, the Common Gateway Interface (CGI) sends a response
-   whether it succeeds or fails in a script-dependent manner. The script
-   can either report success and enclose the response data; or it might
-   send a 302 Found error which indicates that the "Location:" header
-   should be used to determine the URL at which the data can be found.
-
-    2.2.5. HTTP Variables
-
-   \v(http_code)
-          The HTTP protocol code number of the most recent server reply,
-          e.g. 404 for "not found".
-
-   \v(http_connected)
-          1 when an HTTP connection is open, 0 when there is no HTTP
-          connection.
-
-   \v(http_host)
-          If an HTTP connection is open, the hostname:port, e.g.
-          www.columbia.edu:80; otherwise, empty.
-
-   \v(http_message)
-          Server error message, if any, from most recent HTTP command.
-
-   \v(http_security)
-          A list of the security parameters and values for the current
-          connection, if any. Empty if the connection is not to a secure
-          server, or there is no connection.
-
-   To display all the HTTP variables at once, type SHOW VAR HTTP:
-
-  C-Kermit> http open www.columbia.edu
-  C-Kermit> http get lkjlkjlkjlkj 
-  C-Kermit> sho var http
-   \v(http_code) = 404
-   \v(http_connected) = 1
-   \v(http_host) = www.columbia.edu:80
-   \v(http_message) = Not Found
-   \v(http_security) = NULL
-  C-Kermit>
-
-    2.2.6. The HTTP Command-Line Personality
-
-   If you invoke C-Kermit with the name "http" or "https", you can use a
-   special set of HTTP-specific command-line options. You can do this by
-   creating a symbolic linke "http" or "https" to the C-Kermit 8.0
-   executable, or by having a separate copy of it called "http" or
-   "https". Here's the usage message ("http -h"):
-
-  Usage: ./http host [ options... ]
-   -h             This message.
-   -d             Debug to debug.log.
-   -S             Stay (issue command prompt when done).
-   -Y             Do not execute Kermit initialization file.
-   -q             Quiet (suppress most messages).
-   -u name        Username.
-   -P password    Password.
-   -g pathname    Get remote pathname.
-   -p pathname    Put remote pathname.
-   -H pathname    Head remote pathname.
-   -l pathname    Local path for -g, -p, and -H.
-   -z opt[=value] Security options...
-      cert=file   Client certificate file
-      certsok     Accept all certificates
-      key=file    Client private key file
-      secure      Use SSL
-      verify=n    0 = none, 1 = peer , 2 = certificate required
-
-   The "host" argument is the name of a Web host, e.g. www.columbia.edu.
-   The action options are -p, -g, and -H. If you give an action option,
-   Kermit does the action and then exits. If you give a host without an
-   action option, Kermit makes an HTTP connection to the host and then
-   gives you the C-Kermit prompt. Here's a simple example that fetches a
-   publicly readable Web page:
-
-  http www.columbia.edu -g kermit/index.html
-
-   If you need to access a website for which a username and password are
-   required, you can supply them on the command line with -u and -P. If
-   you include a username but omit the password, Kermit prompts you for
-   it:
-
-  http www.columbia.edu -u olga -p kermit/index.html -l index.html
-  Password:
-
-   Note that when PUT'ing files to websites, you have to supply both the
-   -p (remote pathname) and -l (local path) options.
-
-   If your version of Kermit is built with SSL/TLS security, you can also
-   use the -z option to make secure HTTP (https) connections.
-
-   Finally, as noted in [184]Section 16, you can also give a URL instead
-   of a host name and options.
-
-   [ [185]Top ] [ [186]Contents ] [ [187]C-Kermit Home ] [ [188]Kermit
-   Home ]
-  __________________________________________________________________________
-
-3. THE BUILT-IN FTP CLIENT
-
-     3.1.  [189]Making and Managing FTP Connections
-     3.2.  [190]Making Secure FTP Connections
-     3.3.  [191]Setting FTP Preferences
-     3.4.  [192]Managing Directories and Files
-     3.5.  [193]Uploading Files With FTP
-     3.6.  [194]Downloading Files With FTP
-     3.7.  [195]Translating Character Sets
-     3.8.  [196]FTP Command Shortcuts
-     3.9.  [197]Dual Sessions
-     3.10. [198]Automating FTP Sessions
-     3.11. [199]Advanced FTP Protocol Features
-
-   Earlier versions of C-Kermit and K95 included an FTP command, but it
-   simply invoked an external FTP client. Now, by popular demand, Kermit
-   includes its own built-in FTP client that offers the following
-   advantages over traditional FTP clients (and its previous interface to
-   them):
-
-     * Any of Kermit's built-in [200]security methods can be used to
-       establish and conduct secure FTP sessions with [201]FTP servers
-       that support these methods. (Security modules can be subject to
-       export restrictions.)
-     * Kermit's FTP client uses "passive mode" by default to avoid
-       blockage by firewalls and network address translators. Of course
-       active mode can be chosen too when needed.
-     * [202]Character sets can be translated as part of the transfer
-       process even when the FTP server does not support character-set
-       translation, including to/from the new Internet standard
-       international character set, [203]Unicode UTF-8. This includes
-       both the file's name and (for text files only) its contents.
-     * All of C-Kermit's [204]file-selection mechanisms are available:
-       size, date, name patterns and lists, exception lists, etc.
-     * [205]Atomic file movement capabilities are provided (delete, move,
-       or rename files automatically after successful transfer).
-     * The correct file type, "ascii" (i.e. text) or binary, is chosen
-       automatically for each file (explained in [206]Section 4), and any
-       mixture of text and binary files can be sent in a single
-       operation, even across platforms.
-     * Update mode ("don't bother transferring files that didn't change
-       since last time") and recovery (resumption of an interrupted
-       transfer from the point of failure) are available in both
-       directions.
-     * When uploading files from UNIX to UNIX, the file's permissions can
-       be preserved if desired.
-     * Recursive directory-tree PUTs are supported between any two
-       platforms that have tree-structured file systems. Recursive GETs
-       are supported between like platforms if the server cooperates and
-       between like or unlike platforms if the server supports MLSD
-       ([207]Section 3.11).
-     * When receiving files, all of Kermit's file collision actions are
-       available: backup, update, refuse, rename, etc.
-     * Multi-file transfers can be interrupted on a per-file basis,
-       automatically skipping to the next file.
-     * FTP sessions are [208]fully scriptable.
-     * An entire FTP session (connect, login, CD, upload or download,
-       logout) can be specified on the command line without using a
-       script.
-     * All of Kermit's logging options and formats are available to keep
-       an accurate and complete record of each connection and file
-       transfer, and to aid in troubleshooting.
-     * All of Kermit's file-transfer display options are available
-       (fullscreen, brief, CRT, serial, none).
-
-   And best of all:
-     * Kermit doesn't give you those annoying per-file prompts every time
-       you start a multi-file transfer without remembering to give a
-       "prompt" command first :-).
-
-   [ [209]Top ] [ [210]FTP Top ] [ [211]FTP Client Overview ] [ [212]FTP
-   Script Tutorial ] [ [213]C-Kermit Home ] [ [214]Kermit Home ]
-     _________________________________________________________________
-
-  3.1. Making and Managing FTP Connections
-
-   Each copy of Kermit can have one FTP connection open at a time. FTP
-   connections are independent of regular terminal connections; a
-   terminal connection (serial or network via SET LINE, DIAL, SET HOST,
-   TELNET, etc) may be, but need not be, open at the same time as an FTP
-   connection, and terminal connections can also be closed, and new
-   connections opened, without interfering with the FTP connection (and
-   vice versa). Thus, for example, Kermit can have an FTP connection and
-   a TELNET connection open to the same host simultaneously, using the
-   TELNET connection (e.g.) to send mail or take other desired actions as
-   various FTP actions complete. Of course, each copy of Kermit can do
-   only one thing at a time, so it can't (for example) transfer a file
-   with FTP and another file with Kermit protocol simultaneously.
-
-   A Kermit FTP session can be established by [215]command-line options,
-   by [216]URL, or by [217]interactive commands.
-
-    3.1.1. Kermit Command-Line Options for FTP
-
-   The new command-line option '-9' (sorry, we're out of letters) can be
-   used when starting C-Kermit, telling it to make an FTP connection:
-
-  kermit -9 hostname
-
-   or if a non-default FTP port is needed:
-
-  kermit -9 hostname:port
-
-   You can also specify the username on the command line with the -M ("My
-   User ID") option that was already there for other connection types:
-
-  kermit -9 hostname -M olga
-
-   If you specify the username on the command line, Kermit uses it when
-   making the connection and does not prompt you for it (but it does
-   prompt you for the password if one is required).
-
-   Once the connection is made, you get the regular Kermit prompt, and
-   can give interactive commands such as the ones described below. When
-   you give a BYE command, Kermit closes the session and exits, just as a
-   regular FTP client would do. If you don't want Kermit to exit when you
-   give a BYE command, include the -S ("Stay") option on the command
-   line.
-
-   Other Kermit command-line options that are not specific to non-FTP
-   connections should affect the FTP session in the expected ways; for
-   example, -i and -T force binary and text mode transfers, respectively.
-
-   File transfers can not be initiated on the "kermit -9" command line;
-   for that you need to use Kermit's FTP personality (next section) or
-   you can use URLs ([218]Section 3.1.3).
-     _________________________________________________________________
-
-    3.1.2. The FTP Command-Line Personality
-
-   If you want to replace your regular FTP client with C-Kermit, you can
-   make a link called "ftp" to the C-Kermit binary (or you can store a
-   copy of the C-Kermit binary under the name "ftp"). When C-Kermit is
-   invoked with a program name of "ftp" (or "FTP", case doesn't matter),
-   it assumes the command-line personality of the regular FTP client:
-
-  ftp [ options ] hostname [ port ]
-
-   In this case the options are like those of a regular FTP client:
-
-  -d  Debug: enables debug messages and creates a debug.log file.
-  -n  No autologin: Kermit should not send your user ID automatically.
-  -t  Packet trace: accepted but is treated the same as -d.
-  -v  Verbose: accepted but ignored (operation is verbose by default).
-  -i  Not interactive: accepted but ignored.
-
-   and the hostname can also be a URL (explained in [219]Section 3.1.3).
-   To specify a non-default TCP port for the FTP server, include the port
-   number or name after the hostname.
-
-   There are also some bonus options that allow you to execute an entire
-   FTP session from the shell command line, as long as you don't include
-   the -n option. These are not available with regular FTP clients, and
-   at least one of these options (-g) conflicts with UNIX ftp (where -g
-   means "no globbing", which does not apply to Kermit), and some of them
-   (like the options above) also conflict with regular Kermit
-   command-line options:
-
-  -m mode      = "passive" (default) or "active"
-  -Y            Don't execute the Kermit initialization file [1]
-  -q            Quiet, suppresses all but error messages [1]
-  -S            Stay, don't exit automatically [1]
-  -A            Autologin anonymously [2]
-  -u name       Username for autologin [2] (synonym: -M [1])
-  -P password   Password for autologin (see cautions below) [2]
-  -D directory  cd after autologin [2]
-  -b            Binary mode [2]
-  -a            Text ("ascii") mode [2] (synonym: -T [1])
-  -R            Recursive (works with -p) [4]
-  -p files      Files to put (upload) after autologin [2] (synonym: -s [1])
-  -g files      Files to get (download) after autologin [3]
-
-   [1] Same as Kermit, not available in regular FTP clients.
-   [2] Conflicts with Kermit, not available in regular FTP clients.
-   [3] Same as Kermit, conflicts with regular FTP clients.
-   [4] Conflicts with Kermit, available in some FTP clients.
-
-   Fancier options such as restart, character-set translation, filename
-   collision selection, automatic move/rename/delete, etc, are not
-   available from the command line; for these you can use the commands
-   described in the following sections. The -R option might also work
-   with -g (GET) but that depends on the server.
-
-   The following security options are also available, explained in
-   [220]Section 3.2:
-
-  -k realm      Kerberos 4 realm [4]
-  -f            Kerberos 5 credentials forwarding [4]
-  -x            autoencryption mode [4]
-  -c cipher     SRP cipher type [4]
-  -H hash       SRP encryption hash [4]
-  -z option     Security options [4]
-
-   If you include -A or specify a name of "anonymous" or "ftp", you are
-   logged in anonymously and, in the absence of -P, Kermit automatically
-   supplies a password of "user@host", where "user" is your local user
-   ID, and "host" is the hostname of the computer where Kermit is
-   running. If you do not include -p or -g, Kermit enters command mode so
-   you can type commands or execute them from a script.
-
-   If you include -p or -g, Kermit attempts to transfer the specified
-   files and then exits automatically at the end of the transfer unless
-   you also included -S (Stay). It uses the "brief" file transfer display
-   (one line per file) unless you include the -q option to suppress it.
-
-   When uploading files with -p, Kermit switches automatically between
-   text and binary mode for each file.
-
-   When downloading, you can either specify a particular mode (text or
-   binary) to be used for all the files, or you can let Kermit select the
-   type for each file automatically, based on its name (see [221]Sections
-   3.5 and [222]3.6 for greater detail). In UNIX be sure to quote any
-   wildcard characters to prevent the shell from expanding them, as shown
-   in the examples just below. Filename collisions are handled according
-   Kermit's FILE COLLISION setting (if specified in your Kermit
-   customization file; otherwise the default, which is BACKUP).
-
-   It should go without saying that the -P option should be used with
-   caution. In addition to the well-known risks of transmitting plaintext
-   passwords over the Internet, in this case the password also echos to
-   the screen if you type it, and can be seen in ps and w listings that
-   show the user's currently active command and command-line arguments.
-   Thus command-line FTP sessions are most appropriate for secure or
-   anonymous connections (those that do not require passwords).
-
-   Here's an example in which you download the latest C-Kermit "tarball"
-   from the Columbia University FTP archive:
-
-  ftp -A kermit.columbia.edu -bg kermit/archives/ckermit.tar.gz
-
-   This assumes that "ftp" is a symbolic link to C-Kermit. It logs you in
-   anonymously and gets the ckermit.tar.gz file in binary mode from the
-   kermit/archives directory.
-
-   Here's a slightly more ambitious example that illustrates CD'ing to
-   the desired server directory to get a group of files in text mode (in
-   this case the C-Kermit source files):
-
-  ftp -A kermit.columbia.edu -D kermit/f -ag "ck[cuw]*.[cwh]" makefile
-
-   In this case we CD to the kermit/f directory so we don't have to
-   include it in each file specification, and we quote the ck[cuw]*.[cwh]
-   specification so the shell doesn't expand it, since we have to pass it
-   as-is to the server. Note also that the quotes don't go around the
-   entire file list; only around each file specification that needs to be
-   quoted.
-
-   Here's one more example, that uploads a debug log file in binary mode
-   to the Kermit incoming directory (as we might ask you to do when
-   following up on a problem report):
-
-  ftp -A kermit.columbia.edu -D kermit/incoming -bp debug.log
-
-   In this case the -D option is required to tell the server where to put
-   the incoming file.
-
-   Unless the -Y option is included, your Kermit initialization file
-   (.mykermrc in UNIX, K95.INI in Windows) is executed before the command
-   line options, so you can set any FTP-related preferences there, as
-   described in the subsequent sections.
-     _________________________________________________________________
-
-    3.1.3. The FTP URL Interpreter
-
-   If Kermit is invoked with either its regular personality (as "kermit")
-          or its FTP personality (as "ftp"), you can also give a URL
-          (Universal Resource Locator) instead of a hostname and options,
-          with or without a username and password:
-          ftp ftp://user:password@host/path
-          ftp ftp://user@host/path
-          ftp ftp://@host/path   (or ftp://:@host/path)
-          ftp ftp://host/path
-          kermit ftp://host/path
-
-   If the FTP personality is used, the service must be "ftp". In all
-   cases, a hostname or address must be included. If a user is included
-   but no password, you are prompted for the password. If a path
-   (filename) is included:
-     * If "@" is included without a user, Kermit prompts for the username
-       and password.
-     * If no user and no "@" are included, "anonymous" is used.
-     * GET is assumed.
-
-   If no path (and no action options) are included, an interactive FTP
-          session is started, as in this example:
-          ftp ftp://kermit.columbia.edu
-
-   If a path is included, but a username is not included, "anonymous" is
-   used and an appropriate user@host password is supplied automatically.
-   If authentication is successful, Kermit attempts to GET the file
-   indicated by the path or, if the path is the name of a directory, it
-   asks the server for a directory listing. In both cases, Kermit
-   disconnects from the server and exits after the operation is complete
-   (unless you have included the -S option on the command line).
-
-   Here's an example that gets a listing of the Kermit directory at the
-          Kermit ftp site:
-          ftp ftp://kermit.columbia.edu/kermit/
-
-   This example gets the top-level READ.ME file from the same directory:
-          ftp ftp://kermit.columbia.edu/kermit/READ.ME
-
-   Here's the same example, but requesting a text-mode transfer:
-          ftp -T ftp://kermit.columbia.edu/kermit/READ.ME
-          This illustrates that you can mix command-line options and URLs
-          if you desire.
-
-   Here's an example that logs in as a (fictitious) real user to get a
-          file:
-          ftp ftp://olga@ftp.xyzcorp.com/resume.txt
-          The password is not included, so Kermit prompts for it.
-
-   This scheme allows Kermit to be used as the FTP helper of other
-   applications, such as Web browsers, with all its advantages over other
-   FTP clients (especially the ones that are built in to most Web
-   browsers), e.g. that it can be given wildcards, and it can pick text
-   and binary mode automatically for each file.
-
-   HINT: suppose somebody sends you an FTP URL in email, or you see it in
-   some text. If your terminal screen supports copy/paste, copy the url,
-   and then at the shell prompt type "kermit", a space, and then paste
-   the URL, e.g.:
-
-  $ kermit ftp://alpha.greenie.net/pub/mgetty/source/1.1/mgetty1.1.27-O
-
-   "$ is the shell prompt; the part you type is underlined, the rest is
-   pasted in. Kermit does the rest.
-     _________________________________________________________________
-
-    3.1.4. Interactive FTP Session Establishment
-
-   As you read this and the following sections, bear in mind that any
-   command that can be given at the prompt can also be used in a script
-   program. Kermit's script programming language is the same as its
-   interactive command language. [223]CLICK HERE if you would like to
-   learn a bit more about script writing.
-
-   An FTP session is established with the FTP OPEN command:
-
-   FTP [ OPEN ] [ { /SSL, /TLS } ] hostname [ switches ] [ port ]
-          Opens an FTP connection to the given host on the given port
-          and, if FTP AUTOLOGIN is ON, also logs you in to the server,
-          prompting for username and password if necessary. If no port is
-          specified, the regular FTP protocol port (21) is used. The OPEN
-          keyword is optional (unless the hostname conflicts with one of
-          the FTP command keywords, which you can list by typing "ftp
-          ?").
-
-   The hostname can be an IP host name, numeric IP address, or if you
-   have a network directory active (SET NETWORK DIRECTORY; see Chapter 6
-   of [224]Using C-Kermit), an entry name in the directory. In the latter
-   case, if the given hostname matches exactly one entry, the associated
-   name or address is used; if it matches more than one, Kermit cycles
-   through them until one is found that can be opened; if it matches
-   none, then the hostname is used as-is. If a directory is active but
-   you want to bypass directory lookup, include an "=" sign at the
-   beginning of the hostname, and/or use a numeric IP address.
-
-   When an FTP connection is opened, the default file-transfer mode is
-   set to binary if the client and server platforms are alike (e.g. both
-   of them are some kind of UNIX), and to text ("ascii") if they are not
-   alike. This has no particular effect for uploading since Kermit
-   automatically switches between text and binary mode for each file, but
-   might be important for downloading. The connection is also set to
-   Stream mode and File structure. Record- or page-oriented file
-   transfers are not supported by C-Kermit's FTP client.
-
-   The optional FTP OPEN switches are:
-
-   /ANONYMOUS
-          Logs you in anonymously, automatically supplying username
-          "anonymous" and user@host as the password, based on your local
-          user and host names.
-
-   /NOLOGIN
-
-          Overrides SET FTP AUTOLOGIN ON for this connection only.
-
-   /USER:name
-          Uses the given username to log you in, thus avoiding the Name:
-          prompt.
-          Overrides SET FTP AUTOLOGIN OFF for this connection only.
-
-   /PASSWORD:text
-          Uses the given text as your password, thus avoiding the
-          Password: prompt. This switch is not recommended for use in
-          script files, which would be a security risk.
-
-   /ACCOUNT:text
-          Uses the given text as your account (or secondary password,
-          depending on the requirements of the server; most servers do
-          not require or accept an account name). If an account is not
-          supplied, you are not prompted for one.
-
-   /PASSIVE
-          Opens the connection in passive mode. Passive mode is the
-          default in Kermit's FTP client, unlike in most others, since it
-          works better through firewalls. The /PASSIVE and /ACTIVE
-          switches apply only to the connection that is being opened, and
-          do not affect the global FTP PASSIVE-MODE setting.
-
-   /ACTIVE
-          Opens the connection in active mode. Use this switch if the
-          server does not support passive mode, or use the command SET
-          FTP PASSIVE-MODE OFF.
-
-   /NOINIT
-          Added in C-Kermit 8.0.201.   Tells C-Kermit not to send REST,
-          STRU, FEAT, and MODE commands to the server when the connection
-          is opened, since these have been reported to cause confusion in
-          certain servers.
-
-   When a username or password is missing, a prompt is issued at the
-   controlling terminal and you must type the response; the response can
-   not be scripted. Use the switches to avoid prompts, or one of the
-   secure authentication methods described in the next section, or see
-   [225]SET FTP AUTOLOGIN and the [226]FTP USER and similar commands
-   described later in this section.
-
-   Examples:
-
-  ftp open kermit.columbia.edu /anonymous  ; Open and log in anonymously
-  ftp kermit.columbia.edu /anonymous       ; The OPEN keyword can be omitted
-  ftp xyzcorp.com                          ; Open and maybe prompt for username
-  ftp xyzcorp.com /user:olga               ; Open and log in as olga
-  ftp testing.abccorp.com 449              ; Specify a special TCP port number
-  ftp testing.abccorp.com /user:olaf /password:secret 449
-
-   The FTP OPEN command succeeds if a connection was opened to the server
-   (even if the given username and password were not valid) and fails
-   otherwise (see [227]Section 3.8 for details).
-
-   When your FTP session is complete, you can terminate it as follows:
-
-   FTP BYE
-          Closes the FTP connection if one was open. The FTP prefix can
-          be omitted if no other connection is open at the same time (see
-          [228]Section 3.8 for details). If a connection log is active,
-          an FTP record is written to it. If Kermit was started with the
-          -9 command-line option or with its FTP command-line
-          personality, and the -S (Stay) option was not given, AND there
-          is no other active connection, the FTP BYE command also exits,
-          just as it does on a regular FTP client. Synonyms: FTP CLOSE,
-          FTP QUIT (but if the FTP prefix is omitted from QUIT, this
-          becomes the regular Kermit QUIT command, which is equivalent to
-          EXIT; i.e. it closes the connection and exits from Kermit).
-
-   The following commands can be used to achieve greater control over the
-   connection and login process:
-
-   SET FTP ANONYMOUS-PASSWORD text
-          Allows you to choose the password text to be sent automatically
-          by Kermit when you open an FTP connection with the /ANONYMOUS
-          switch.
-
-   SET FTP AUTOLOGIN { ON, OFF }
-          If you give this command prior to opening an FTP connection, it
-          controls whether Kermit tries to log you in automatically as
-          part of the connection process. Normally ON, which means the
-          username and password are sent automatically (and prompted for
-          if they are not yet known). When OFF, FTP OPEN connects to the
-          server without logging in. OFF is equivalent to the -n
-          command-line option when using Kermit's FTP command-line
-          personality.
-
-   FTP USER name [ password [ account ] ]
-          Used to log in to an FTP server to which a connection has been
-          made without autologin, or when autologin failed. If the
-          password is furnished on the command line, it is used;
-          otherwise you are prompted for a password. An account may also
-          be furnished if required by the server; it is not required by
-          Kermit and is not prompted for if omitted. Synonyms: USER, FTP
-          LOGIN.
-
-   FTP ACCOUNT text
-          Sends an account name to a server that supports accounts. If
-          the server does not support accounts, an error response occurs.
-          If the server does support accounts, the account is accepted if
-          it is valid and rejected if it is not. The account might be
-          used for charging purposes or it might be a secondary password,
-          or it might be used for any other purpose, such as an access
-          password for a particular disk. Servers that support accounts
-          might or might not allow or require the account to be sent
-          prior to login; usually it is sent after login, if at all.
-          Synonym: ACCOUNT.
-
-   Example:
-
-set ftp autologin off                  ; One thing at a time please
-ftp xyzcorp.com                        ; Try to make the connection
-if fail exit 1 FTP connection failed   ; Check that it was made
-ftp user olga secret                   ; Now log in to the server
-if fail exit 1 FTP login failed        ; Check that it worked
-ftp account 103896854                  ; Login OK - send account
-if fail echo WARNING - FTP ACCT failed ; Warn if problem
-...                                    ; (have session here)
-bye                                    ; Log out and disconnect
-
-   The following commands are used to control or get information about
-   the FTP connection. Any particular FTP server does not necessarily
-   support all of them.
-
-   FTP RESET
-          Terminates a user session but leaves the connection open,
-          allowing a new login via FTP USER.
-
-   FTP IDLE [ number ]
-          Most FTP servers automatically log you out and and disconnect
-          your session if there has been no activity for a certain amount
-          of time. Use this command to ask the server to set its idle
-          limit to the given number of seconds. Omit the number to ask
-          the server to inform you of its current idle limit.
-
-   FTP STATUS [ filename ]
-          Asks the FTP server to send information about the current
-          session. The result is a free-format report that might include
-          server identification, username and login time, FTP protocol
-          settings, and file-transfer statistics. If a filename is given,
-          the server is supposed to send detailed information about the
-          file.
-
-   FTP SYSTEM
-          Asks the FTP server to identify its operating system (Listed in
-          Internet Assigned Numbers, Operating System Names). Examples:
-          UNIX, VMS, VM/CMS, WINDOWS-NT. Unfortunately many variations
-          are allowed (e.g. LINUX-2.0, LINUX-2.2, FREEBSD, ULTRIX, etc,
-          instead of UNIX; WINDOWS-NT-3, WINDOWS-NT-3.5, WINDOWS-NT-3.51,
-          WINDOWS-NT-4, etc). The report might also include other
-          information like "Type L8", "Type I", or "Type A", indicating
-          the file-transfer mode.
-
-   FTP HELP [ keyword [ keyword [ ... ] ]
-          Asks the server to list the commands it supports. The response
-          is usually cryptic, listing FTP command mnemonics, not the
-          commands used by the client (since the server has no way of
-          knowing anything about the client's user interface). For
-          example, the PUT command is STOR in FTP protocol. If a keyword
-          is given, which should be an FTP protocol command,
-          slightly-more- detailed help is given about the corresponding
-          command (if the FTP server supports this feature). Examples:
-          "ftp help", "ftp help stor".
-
-   FTP SITE text
-          (Advanced) Sends an FTP SITE (site-specific) command. Usually
-          this means that the FTP server is asked to run an external
-          command with the given arguments. You might be able to find out
-          what SITE commands are available by sending "ftp help site" to
-          the server, but in general the availability of and response to
-          SITE commands is (not surprisingly) site specific.
-
-   FTP QUOTE text
-          (Advanced) Sends an FTP command in FTP protocol format. Use
-          this command to send commands to the server that the FTP client
-          might not know about.
-
-   SHOW FTP
-          Lists client (Kermit) FTP settings and information. Also SHOW
-          CONNECTION, SHOW COMMUNICATIONS.
-
-   HELP FTP [ keyword ]
-          Asks Kermit to list and describe its built-in FTP commands.
-
-   HELP SET FTP [ keyword ]
-          Asks Kermit to list and describe its built-in SET FTP commands.
-
-   [ [229]Top ] [ [230]FTP Top ] [ [231]C-Kermit Home ] [ [232]Kermit
-   Home ]
-     _________________________________________________________________
-
-  3.2. Making Secure FTP Connections
-
-   Also see: [233]Accessing IBM Information Exchange with Kermit.
-
-   In the previous section, you can see several examples of traditional
-   insecure authentication: username and password sent across the network
-   in clear text. Of course this is bad practice on at least two counts:
-   (1) storing passwords in files (such as script files) gives access to
-   the target systems to anybody who can obtain read access to your
-   scripts; and (2) sending this information over the network leaves it
-   open to interception by network sniffers or compromised hosts.
-
-   Because of the increasing need for security on the Internet, FTP
-   servers are beginning to appear that offer secure forms of
-   authentication, in which no information is sent over the network that
-   would allow anyone who intercepts it to usurp your identity and gain
-   your access rights.
-
-   Kermit provides an equivalent form of FTP security for each type of
-   IETF standard security implemented in Telnet. These include
-   GSSAPI-KERBEROS5, KERBEROS4, Secure Remote Password (SRP), and
-   Transport Layer Security (SSL and TLS). It does not presently include
-   SSL tunneling nor any form of SSH v1 or v2. When Kermit is built with
-   the necessary libraries, secure FTP connections are attempted by
-   default, in which all connections are authenticated and the command
-   and data channels are private.
-
-   The use of authentication and encryption for FTP connections can be
-   adjusted with the commands listed below, which are available only if
-   your version of Kermit was built with the corresponding security
-   options and libraries:
-
-   SET FTP AUTHTYPE { AUTOMATIC, GSSAPI-KRB5, KERBEROS4, SRP, SSL, TLS }
-          Specifies an ordered list of authentication methods to be
-          attempted when AUTOAUTHENTICATION is ON. The default list is:
-          GSSAPI-KRB5, SRP, KERBEROS_V4, TLS, SSL. If none of the
-          selected methods are supported by the server, an insecure login
-          is used as a fallback. Note, by the way, that SSL or TLS can be
-          used to secure an anonymous connection.
-
-   SET FTP AUTOAUTHENTICATION { ON, OFF }
-          Tells whether authentication should be negotiated by the FTP
-          OPEN command. Default is ON. Use SET FTP AUTOAUTHENTICATION OFF
-          to force a clear-text, unencrypted connection to FTP servers
-          (such as the one at the Kermit FTP site) that normally would
-          try to negotiate secure authentication and encryption.
-
-   SET FTP AUTOENCRYPTION { ON, OFF }
-          Tells whether encryption (privacy) should be negotiated by the
-          FTP OPEN command, which can happen only if secure
-          authentication is also negotiated. Default is ON.
-
-   SET FTP AUTOLOGIN { ON, OFF }
-          Tells Kermit whether to try logging in automatically when you
-          make an FTP connection, as opposed to letting you do it "by
-          hand" with the FTP USER command.
-
-   SET FTP COMMAND-PROTECTION-LEVEL { CLEAR, CONFIDENTIAL, PRIVATE, SAFE
-          }
-          Determines the level of protection applied to the command
-          channel:
-
-  CLEAR         Data is sent in plaintext and not protected against tampering.
-  CONFIDENTIAL  Data is encrypted but not protected against tampering.
-  PRIVATE       Data is encrypted and is protected against tampering.
-  SAFE          Data is sent in plaintext but protected against tampering.
-
-          The default is PRIVATE.
-
-   SET FTP CREDENTIAL-FORWARDING { ON, OFF }
-          Tells whether end-user credentials are to be forwarded to the
-          server if supported by the authentication method (GSSAPI-KRB5
-          only). This is often required to allow access to distributed
-          file systems (e.g. AFS.)
-
-   SET FTP DATA-PROTECTION-LEVEL { CLEAR, CONFIDENTIAL, PRIVATE, SAFE }
-          Tells what level of protection is applied to subsequent data
-          channels. The meanings of the protection-level keywords are the
-          same as for SET FTP COMMAND-PROTECTION-LEVEL. The default is
-          PRIVATE.
-
-   SET FTP SRP CIPHER name
-          Specifies the cipher to be used for encryption when SRP
-          authentication is in use. The list of possible choices is
-          computed based on the capabilities of the local SRP library and
-          includes NONE plus zero or more of the following:
-
-  BLOWFISH_ECB        CAST5_ECB          DES_ECB          DES3_ECB
-  BLOWFISH_CBC        CAST5_CBC          DES_CBC          DES3_CBC
-  BLOWFISH_CFB64      CAST5_CFB64        DES_CFB64        DES3_CFB64
-  BLOWFISH_OFB64      CAST5_OFB64        DES_OFB64        DES3_OFB64
-
-          The default is DES3_ECB.
-
-   SET FTP SRP HASH name
-          Specifies the hash to be used for data protection when SRP
-          authentication is in use. The choices are MD5 and SHA. The
-          default is SHA.
-
-   Command-line options:
-
-   -k name
-          Specifies the realm to be used with Kerberos 4 authentication
-          (= SET AUTH K4 REALM name).
-
-   -f
-          Enables forwarding of Kerberos 5 credentials to the host when
-          using GSSAPI authentication (= SET AUTH K5 FORWARDABLE ON).
-
-   -x
-          Enables autoencryption (= SET FTP AUTOENCRYPTION ON).
-
-   -c cipher
-          Specifies the kind of cipher to be used for encryption with SRP
-          authentication. Equivalent to SET FTP SRP CIPHER, with the same
-          choices. If this option is not given, CAST5_CBC is used.
-
-   -H hash
-          Specifies the hash to be used for encryption with SRP
-          authentication. Equivalent to SET FTP SRP HASH, with the same
-          choices. If this option is not given, SHA is used.
-
-   -z debug
-          Turns on SSL/TLS debugging.
-
-   -z secure
-          Requires secure connection.
-
-   -z certsok
-          Says to accept all certificates without checking validity.
-
-   -z verify=n
-          Sets certificate verification mode to the given number, n:
-            0 = no verification
-            1 = verify certificate if presented
-            2 = require verification of certificate
-
-   -z cert=filename
-          Specifies a file containing a client certificate to be
-          presented to the FTP server.
-
-   -z key=filename
-          Specifies a file containing a private key matching the client
-          certificate.
-
-   -z !krb4
-          (nokrb4) Disables the use of Kerberos 4.
-
-   -z !gss
-   -z nogss
-          Disables the use of GSSAPI - Kerberos 5.
-
-   -z !srp
-   -z nosrp
-          Disables use of SRP.
-
-   -z !ssl
-   -z nossl
-          Disables the use of SSL.
-
-   -z !tls
-   -z notls
-          Disables the use of TLS.
-
-   Caution: If your FTP connection is secured via AUTH TLS, it is not
-   possible to interrupt a file transfer. This is a limitation of all
-   known FTP servers that support AUTH TLS.
-
-   Note that when using certain security methods, such as SSL or TLS, you
-   may be prompted to confirm or verify certain actions or conditions,
-   for example, whether to accept self-signed certificates. This can
-   interfere with unattended operation of scripts; see [234]Section 3.10.
-
-   [ [235]Top ] [ [236]FTP Top ] [ [237]C-Kermit Home ] [ [238]Kermit
-   Home ]
-     _________________________________________________________________
-
-   3.3. Setting FTP Preferences FTP preferences can be set globally and
-   persistently with the commands in the following sections; many of
-   these can also be overridden on a per-command basis with switches that
-   have the same name.
-
-    3.3.1. Logs, Messages, and Other Feedback
-
-   You can control the amount of feedback received from your FTP session
-   with the commands in this section. First, you can create a log of your
-   FTP transfers with the following commands:
-
-   SET TRANSACTION-LOG { VERBOSE, FTP, BRIEF }
-          Selects the log format. VERBOSE is the default, and is
-          described in [239]the manual. FTP chooses a WU-FTPD format, the
-          same as is used by the popular FTP server. BRIEF creates
-          per-file records in comma-separated-list format. For greater
-          detail, see [240]Section 4.17 of the [241]C-Kermit 7.0 Update
-          Notes.
-
-   LOG TRANSACTIONS filename
-          Records FTP (or Kermit, or any other protocol) uploads and
-          downloads in the given file using the format selected by the
-          most recent SET TRANSACTION-LOG command, if any, or else the
-          default format.
-
-   FTP screen messages and displays are controlled by the following
-   commands:
-
-   SET TRANSFER DISPLAY { FULLSCREEN, CRT, SERIAL, BRIEF, NONE, OFF }
-          FTP transfers use Kermit's normal file-transfer display styles.
-          Use this command to choose the desired format; the default on
-          most platforms is FULLSCREEN. The display is automatically
-          disabled if Kermit is running in the background or in batch.
-          BRIEF is always used for command-line initiated transfers
-          (unless suppressed by -q). While a file-transfer is in
-          progress, you can interrupt it in the normal Kermit way by
-          typing one of the following keys or key combinations:
-            X - Cancel current file but go on to the next one (if any).
-            Z - Cancel the entire transfer.   Ctrl-L or Ctrl-W - Refresh
-          the file-transfer display (if any).
-
-   SET FTP DISPLAY { FULLSCREEN, CRT, SERIAL, BRIEF, NONE, OFF }
-          Like SET TRANSFER DISPLAY, but applies only to FTP connections,
-          and does not affect Kermit- or other protocol file transfers.
-
-   SET QUIET { ON, OFF }
-          This command applies to Kermit in general, not just FTP. OFF by
-          default; when ON, it surpresses most messages from most
-          commands as well as the file-transfer display.
-
-   SET FTP PROGRESS-MESSAGES { ON, OFF }
-          Tells whether Kermit should print locally-generated feedback
-          messages for each non-file-transfer command. ON by default.
-
-   SET FTP VERBOSE-MODE { ON, OFF }
-          Tells whether to display all responses from the FTP server. OFF
-          by default. This shows all responses to all commands, except
-          when the file-transfer display is active, and unless you have
-          SET QUIET ON. When OFF, responses are shown only for commands
-          such as FTP PWD whose purpose is to display a response.
-
-   SET FTP DEBUG { ON, OFF }
-          Tells whether local client debugging information should be
-          displayed. OFF by default. When ON, the commands that are sent
-          to the server are shown, as well as its responses (even if
-          VERBOSE-MODE is OFF), plus additional informational messages
-          are printed regarding the progress of secure operations. Also,
-          the temporary file created by the [242]MGET command is not
-          deleted so you can see what's in it.
-
-   Set all of these to OFF when silent running is desired.
-
-    3.3.2. Operational Preferences
-
-   FTP DISABLE new-protocol-feature-name
-   FTP ENABLE new-protocol-feature-name
-          Explained in [243]Section 3.11.
-
-   SET FTP AUTOLOGIN { ON, OFF }
-          If you give this command prior to opening an FTP connection, it
-          controls whether Kermit tries to log you in automatically as
-          part of the connection process. Normally ON, which means the
-          username and password are sent automatically (and prompted for
-          if they are not yet known). When OFF, FTP OPEN connects to the
-          server without logging in. OFF is equivalent to the -n
-          command-line option when using Kermit's FTP command-line
-          personality. See [244]Section 3.1.4 for usage.
-
-   SET FTP PASSIVE-MODE { ON, OFF }
-          ON by default, to avoid random TCP port assignment for data
-          connections, which can prevent FTP protocol from working
-          through firewalls and network address translators (for more on
-          these topics, see the [245]Kermit security reference. Set to
-          OFF in case the FTP server does not support passive mode, or in
-          case the client has problems with it (it has been observed, for
-          example, that when using passive mode, the SCO XENIX 2.3.4
-          TCP/IP stack hangs in the connect() call forever). Synonyms:
-          PASSIVE [ ON ], PASSIVE OFF, PASV [ ON ], PASV OFF.
-
-   SET FTP SEND-PORT-COMMANDS { ON, OFF }
-          This command determines whether the FTP client sends a new PORT
-          command to the server when accepting incoming data connections
-          (as when not using passive mode.) When PASSIVE-MODE is OFF and
-          SET SEND-PORT is OFF, the port that was originally specified is
-          reused. This is the default behavior for normal FTP clients but
-          it is not compatible with many firewalls.
-
-   SET FTP CHARACTER-SET-TRANSLATION { ON, OFF }
-          Whether to translate character sets when transferring files
-          with FTP (explained in [246]Section 3.7). OFF by default.
-
-   SET FTP SERVER-CHARACTER-SET name
-          Tells Kermit the character set used by the FTP server, UTF-8 by
-          default ([247]Section 3.7).
-
-   SET FTP SERVER-TIME-OFFSET delta-time
-          Tells Kermit to apply the given [248]delta time to file
-          timestamps provided by the server for its files; for use when
-          (for example) the server does not have its timezone set
-          correctly.
-
-   SET FTP ERROR-ACTION { PROCEED, QUIT }
-          When transferring a group of files with FTP, and an error
-          occurs with one of the files, Kermit normally goes on the next
-          file. Use SET FTP ERROR-ACTION to QUIT to make Kermit stop the
-          transfer immediately and fail if an error occurs with any
-          single file in the group. Example: you have given Kermit a list
-          of files to send, and one of the files can not be found, or
-          read permission is denied. Note that cancelling a file by
-          typing 'X' during transfer is not considered an error (if you
-          want to cancel the entire transfer, type 'Z' or Ctrl-C).
-
-   SET FTP PERMISSIONS { AUTO, ON, OFF }
-          When uploading files with PUT or MPUT, this tells whether
-          Kermit should send each file's permissions. The default is OFF,
-          which means not to send permissions, in which case the uploaded
-          file's permissions are set by the FTP server according to its
-          own criteria. ON means to send them, AUTO means to send them
-          only if the client (Kermit) and server are on like platforms
-          (e.g. both UNIX). This command has no effect when downloading,
-          since the FTP protocol does not include a way for the server to
-          inform the client of a file's permissions. Also see [249]FTP
-          PUT /PERMISSIONS. Note that setting permissions after uploading
-          is likely to work (correctly or at all) only when the client
-          and server platforms are alike (e.g. both of them are some form
-          of UNIX). Also note that Windows files don't have permissions.
-          Also see [250]FTP CHMOD.
-
-   SET FTP DATES { ON, OFF }
-          When downloading files with GET or MGET, this tells whether
-          Kermit should try to set the received file's date from the
-          server's date. FTP DATES is ON by default. Note, however, that
-          FTP protocol does not allow date preservation when uploading.
-          So at best, SET FTP DATES ON can work only when downloading,
-          and then only when the server agrees to furnish file dates.
-
-   SET FTP FILENAMES { AUTO, CONVERTED, LITERAL }
-          When uploading (sending) files, this tells whether to convert
-          outbound filenames to "common form". This means allowing only
-          one period in a name, uppercasing any lowercase letters,
-          replacing spaces by underscores, etc. AUTOMATIC is the default,
-          meaning LITERAL when client and server are the same type of
-          system (e.g. UNIX) and CONVERTED otherwise. Special case: if
-          the setting is AUTOMATIC and the client is not UNIX and the
-          server identifies itself as UNIX, Kermit uses a less-strict
-          form of conversion, in which lowercase letters are not
-          uppercased and the filename can contain any number of periods,
-          but spaces are still converted to underscore. When receiving,
-          conversion generally means to change all-uppercase names to
-          lowercase and spaces to underscore.
-
-   SET FTP UNIQUE-SERVER-NAMES { ON, OFF }
-          Applies only to uploads. Tells the server to create new, unique
-          names for incoming files that have the same names as existing
-          files. OFF by default, in which case the server overwrites
-          existing files with new files of the same name. When ON, the
-          server uses its own built-in method for creating new names for
-          incoming files; for example, appending a period (.) and a
-          number to the name. CAUTION: Use this option only if you do not
-          need to refer to the file after it is uploaded, since FTP
-          protocol provides no mechanism for the client to find out what
-          name was assigned by the server.
-
-   SET FTP COLLISION { ... }
-          When downloading, what to do if an incoming file has the same
-          name as an existing file. Options are the same as for SET FILE
-          COLLISION. If this command is not given, Kermit's regular FILE
-          COLLISION setting is used. If this command is given, it
-          overrides the FILE COLLISION setting for FTP transfers only.
-          See [251]Section 3.6.2 for details.
-
-   SET FTP TYPE { TEXT, BINARY, TENEX }
-          Changes the default transfer mode. When sending (uploading)
-          files, this command has no effect unless you disable automatic
-          text/binary mode switching ([252]Section 4) with SET FILE SCAN
-          OFF or SET TRANSFER MODE MANUAL. When receiving (downloading)
-          files, this command establishes the transfer mode to be used
-          when a filename does not match any of Kermit's text or binary
-          filename patterns, unless you use SET FTP
-          GET-FILETYPE-SWITCHING or SET TRANSFER MODE MANUAL to disable
-          automatic switching, in which case, this command establishes
-          the transfer mode for all downloaded files. In all cases,
-          however, the FTP TYPE can be overridden in any GET or PUT
-          command by including a /TEXT (/ASCII), /BINARY, or /TENEX
-          switch. The FTP TYPE is independent of the Kermit FILE TYPE
-          setting. TENEX is used for sending 8-bit binary files to 36-bit
-          platforms such as TOPS-10, TOPS-20, and TENEX, and getting them
-          back again. Synonym: ASCII = TEXT. Note: there is also an FTP
-          TYPE command, which does what SET FTP TYPE does but also sends
-          a TYPE command to the server immediately if the given type is
-          different from the current one.
-
-   If you want want specific FTP preference settings to be in effect for
-   all your Kermit FTP sessions, put the desired SET FTP commands in your
-   Kermit customization file (~/.mykermrc in UNIX, K95CUSTOM.INI in
-   Windows).
-
-   [ [253]Top ] [ [254]FTP Top ] [ [255]C-Kermit Home ] [ [256]Kermit
-   Home ]
-     _________________________________________________________________
-
-  3.4. Managing Directories and Files
-
-   In Kermit, commands for directory and file management can refer to:
-
-     * The local computer
-     * A remote computer when you have a connection to a Kermit server or
-       IKSD.
-     * A remote computer when you have a connection to an FTP server.
-
-   (There can also be an HTTP connection, but the commands in this
-   section don't apply to HTTP connections.)
-
-   Thus in general, each such command comes in three forms:
-
-    1. With no prefix in C-Kermit 8.0.200, it refers to the local
-       computer (CD, DIR, etc). In C-Kermit 8.0.201 and later, however,
-       the "locus" switches to automatically to the remote FTP server
-       when you make an FTP connection (see the SET LOCUS description
-       [257]Section 7); thus C-Kermit 8.0.201 acts almost exactly like a
-       regular FTP client when it has an FTP connection, yet still acts
-       like itself on other kinds of connections.
-    2. With the REMOTE prefix, it is for a Kermit server (REMOTE CD,
-       REMOTE DIR).
-    3. With the FTP prefix, it's for an FTP server (FTP CD, FTP DIR).
-    4. Also see [258]Section 3.8, which explains "R-commands" and
-       "L-commands".
-
-   Kermit's FTP file and directory management commands are as follows.
-   When an R-command is included in the Synonyms list, be sure to read
-   [259]Section 3.8 about rules for use of R-commands.
-
-   FTP CD [ directory ]
-          Tells the FTP server to change its default (working) directory
-          to the one given, which usually must be expressed in the syntax
-          of the server platform (UNIX, VMS, etc). If the directory is
-          not specified, the result depends on the FTP server -- it might
-          complain that the command is illegal, or it might change to
-          your original login directory. Synonyms: FTP CWD (Change
-          Wording Directory); RCD.
-
-   FTP CDUP
-          Tells the FTP server to change its default (working) directory
-          to the parent directory of its current one (equivalent to
-          "cd .." in UNIX, or "cd [-]" in VMS). Synonyms: RCDUP, FTP UP.
-
-   FTP PWD
-          Asks the FTP server to report ("print") its current working
-          directory. Synonym: RPWD.
-
-   FTP MKDIR directory
-          Asks the FTP server to create the directory whose name is
-          given. In general, the name must be in the syntax of the
-          server's file system, and it must be either absolute (a full
-          pathname) or relative to the server's current (working)
-          directory. This command fails if the directory can't be created
-          for any reason, including that it exists already. Synonym:
-          RMKDIR.
-
-   FTP RMDIR directory
-          Asks the FTP server to remove the directory whose name is
-          given. The rules are the same as for MKDIR, plus in most cases,
-          the server will not remove any directory unless it is empty.
-          Synonym: RRMDIR.
-
-   FTP DIRECTORY [ filespec ] [ redirectors ]
-          Tells the FTP server to send a directory listing of the
-          specified files. If no filespec is given, the server lists all
-          files in its current working directory. The results are in
-          whatever format the server chooses to send them. You can use
-          UNIX-like redirectors to send the listing to a file or a
-          pipeline, exactly as with the regular Kermit client/server
-          REMOTE DIRECTORY command ([260]Using C-Kermit, Chapter 11).
-          Synonym: RDIRECTORY. Examples:
-
-    ftp dir                           ; Show listing of all files on screen
-    ftp dir *.txt                     ; List *.txt files on screen
-    ftp dir *.txt > somefile          ; Put listing in somefile
-    ftp dir *.txt >> somefile         ; Append listing to somefile
-    ftp dir *.txt | sort > somefile   ; Put sorted listing in somefile
-    ftp dir | more                    ; Runs list through "more"
-    ftp dir | sort | more             ; Runs list through "sort" and "more"
-
-   FTP VDIRECTORY [ filespec ] [ redirectors ]
-          "Verbose" directory. This is an alternative FTP DIRECTORY
-          command primarily for use with DECSYSTEM-20 (TOPS-20) FTP
-          servers, which send only filenames when given a DIRECTORY
-          command; the VDIRECTORY command makes them also send file
-          sizes, dates, and attributes.
-
-   FTP CHECK filespec
-          Asks the FTP server whether the given file exists or, if the
-          filespec contains wildcards, if any files match, and this
-          command succeeds or fails accordingly.
-
-   FTP MODTIME filename
-          Asks the FTP server, via the not-yet-standard FTP MDTM command,
-          to send the modification date and time of the given file. The
-          response should be a numeric string in the format:
-          yyyymmddhhmmssxxxxx... where yyyy is the year, mm is the month,
-          dd is the day, hh is the hour (0-23), mm is the minute, ss is
-          the second, and xxx... is the optional fraction of the second
-          (0 or more digits). The date and time is expressed in UTC (GMT,
-          Zulu, Zero-Meridian). The result is available programmatically
-          in the [261]\v(ftp_message) variable, and is understandable by
-          Kermit's date-time switches and functions. For example, suppose
-          we want to upload all local files that are newer than a
-          particular file on the server:
-
-  C-Kermit> ftp modtime signpost
-  C-Kermit> echo \v(ftp_message)
-  20010807113542.014
-  C-Kermit> ftp mput /after:\v(ftp_message)GMT *
-
-          Note that we must append "GMT" to the date-time string to let
-          the /AFTER switch know the time is GMT rather than local.
-
-   FTP SIZE filename
-          Asks the FTP server to send the size (in bytes) of the given
-          file. The result might vary depending on whether the current
-          FTP TYPE is binary or text ("ascii"). For a reliable byte
-          count, do FTP TYPE BINARY first. The result is available
-          programmatically in the [262]\v(ftp_message) variable.
-
-   FTP CHMOD permissions filename
-          Tells the FTP server to set the permissions (protection) of the
-          given file to the ones given. The permissions and filename must
-          be given in whatever syntax is required by the server. Example
-          (for a UNIX-based FTP server):
-
-  ftp chmod 664 oofa.txt
-
-          Not all servers support this command. For non-UNIX-based
-          servers, you might need to use FTP QUOTE or FTP SITE and the
-          appropriate platform-specific FTP server command.
-
-   FTP UMASK [ number ]
-          This command is probably specific to UNIX-based servers; it
-          sets the UNIX "umask", which is the default permissions mask
-          for new (in this case, incoming) files. Crudely put, the UNIX
-          umask is an octal representation of a binary number in in which
-          a 1 bit stands for a permission bit that must be 0, and a 0 bit
-          stands for a permission bit that can be 0 or 1 depending on
-          other factors, such as the permissions of the parent directory.
-          Example: "umask 007" requires that new files are created
-          without read/write/execute world permission. If the number is
-          not specified, the server's current umask is reported.
-
-   FTP RENAME filename newname
-          Asks the FTP server to rename the file whose name is "filename"
-          to "newname". Works only for one file; can not be used with
-          wildcards. The server's interpretation of "newname" can vary
-          (in some cases it must be a filename, in others perhaps it can
-          also be a directory name, in which case if the filename denote
-          a regular file, the file might be moved to the given
-          directory). Some servers might allow files to be renamed
-          ("moved") between physical disks or partitions, others might
-          not. Synonym: RRENAME.
-
-   FTP DELETE [ switches ] filespec [ filespec [ ... ] ]
-          Tells the FTP server to delete the file or files listed. Each
-          file specification may, but need not, contain wildcard
-          characters to match multiple files. File specifications and
-          wildcard syntax must be those of the server. Any file
-          specifications that contain spaces must be enclosed in braces
-          or doublequotes. FTP DELETE switches are:
-
- /ERROR-ACTION:  /FILENAMES:     /NOBACKUPFILES  /QUIET
- /EXCEPT:        /LARGER-THAN:   /NODOTFILES     /NOPAGE
- /PAGE           /RECURSIVE      /SMALLER-THAN:
-
-          When used with FTP DELETE, the /RECURSIVE switch deletes files
-          but not directories, and furthermore depends on the server
-          providing recursive file lists, which is not the normal
-          behavior. For further details, see the decriptions of these
-          switches in [263]Section 3.6. Synonyms: FTP MDELETE (Kermit
-          makes no distinction between DELETE and MDELETE); RDELETE.
-
-   FTP TYPE { TEXT, BINARY, TENEX }
-          Tells the FTP server to change its file-transfer type to the
-          one given, immediately. See [264]SET FTP TYPE for details.
-
-   [ [265]Top ] [ [266]FTP Top ] [ [267]C-Kermit Home ] [ [268]Kermit
-   Home ]
-     _________________________________________________________________
-
-  3.5. Uploading Files With FTP
-
-   Uploading means sending files from the client (Kermit) to the FTP
-   server. The basic command for uploading files with FTP is PUT:
-
-   FTP PUT [ switches ] [ filespec [ as-name ] ]
-          Uploads (sends) the file or files that match the file
-          specification, which may include wildcards, to the server. If
-          no filespec is given, the names of files to send are taken from
-          the /LISTFILE: file, if any, otherwise from the SEND-LIST, if
-          any. Unless you go out of your way to prevent it, Kermit
-          determines the transfer mode (text or binary) for each file
-          automatically, and switches automatically on a per-file basis.
-          If an as-name is given, the file is sent under that name
-          instead of its own (if an as-name is given with a wildcard
-          filespec, the result is a bit more complicated, and is
-          explained later in this section).
-
-   Unlike normal FTP clients, Kermit does not prompt you by default (or
-   at all) for each file; it just sends them, just as it does with Kermit
-   protocol. The filespec can be a literal filename or a Kermit pattern,
-   described in:
-
-  [269]http://www.columbia.edu/kermit/ckermit70.html#x4.9
-
-   Kermit patterns are equivalent to C-Shell patterns and provide a fair
-   amount of flexibility in selecting which files to send, which is
-   augmented by the file-selection switches presented in [270]Section
-   3.5.1.
-
-   FTP MPUT [ switches ] filespec [ filespec [ ... ] ]
-          FTP MPUT is just like FTP PUT except it allows you to give more
-          than one file specification, and it does not allow an as-name
-          in the file list. However, as-names can be given to either PUT
-          or MPUT with the /AS-NAME: switch.
-
-   If a PUT or MPUT command results in one file being uploaded, it
-   succeeds if the file is uploaded completely and fails otherwise. If
-   more than one file is selected for upload, success or failure depends
-   on the [271]FTP ERROR-ACTION setting; if it is PROCEED (the default
-   setting), then the [M]PUT command succeeds if at least one of the
-   files was completely uploaded, and fails otherwise, If FTP
-   ERROR-ACTION is QUIT, the [M]PUT command succeeds if all selected
-   files were uploaded successfully, and fails if any file failed.
-
-   FTP uploads may be interrupted just like Kermit uploads. While the
-   transfer is in progress, type:
-
-  X to interrupt the current file and go on to the next file.
-  Z to cancel the current file and all remaining files.
-  ^C (Control-C): Like Z, but might act more quickly.
-
-   MPUT may be used as in regular FTP clients, but it is not required to
-   send multiple files; in Kermit it is required only if you want to give
-   multiple file specifications. Examples:
-
-  ftp put oofa.txt               ; Send a single file oofa.txt
-  ftp put oofa.txt budget.txt    ; Send single file oofa.txt as budget.txt
-  ftp put *.txt                  ; Send all *.txt files
-  ftp mput *.txt                 ; Send all *.txt files (same as "put *.txt")
-  ftp mput *.txt foo.bar         ; Send all *.txt files plus foo.bar
-
-   The distinction between PUT and MPUT is important only when more than
-   one filespec is given, just like the distinction between Kermit SEND
-   and MSEND:
-
-  ftp put oofa.txt budget.txt    ; Send oofa.txt AS budget.txt
-  ftp mput oofa.txt budget.txt   ; Send oofa.txt AND budget.txt
-
-   If the source file specification includes any path segments, for
-   example:
-
-  put /tmp/oofa.txt
-  put subdir/another/andanother/oofa.txt
-
-   the path portion is stripped from the filename that is sent to the
-   server. However, if an as-name contains a path, it is retained.
-   Examples:
-
-  ftp put /usr/doc/oofa.txt      ; Send as "oofa.txt".
-  ftp put oofa.txt /tmp/oofa.txt ; Send as "/tmp/oofa.txt"
-
-   The latter example sends the file oofa.txt from your current local
-   directory to the server's /tmp directory. This works only if the
-   server uses the same directory notation that you used in the as-name
-   AND the given directory already exists on the server AND if you have
-   write access to it.
-
-   Use caution when uploading from a case-sensitive file system, such as
-   UNIX, to a file system that is not case sensitive, such as Windows or
-   VMS. If you have two files in UNIX, AA and aa and upload both of them,
-   the second one will overwrite the first. The only way around this
-   provided by FTP protocol is its "unique server names" feature (SET FTP
-   UNIQUE-SERVER-NAMES or the /UNIQUE switch described below).
-     _________________________________________________________________
-
-    3.5.1. FTP PUT Switches
-
-   FTP PUT and MPUT are similar in format and behavior to the regular
-   Kermit SEND and MSEND commands, and they allow most of the same
-   optional switches:
-
-C-Kermit>ftp put ? Filename, or switch, one of the following:
- /after:                 /larger-than:           /rename-to:
- /array:                 /listfile:              /server-character-set:
- /as-name:               /local-character-set:   /server-rename-to:
- /before:                /move-to:               /simulate
- /binary                 /nobackupfiles          /smaller-than:
- /command                /nodotfiles             /tenex
- /delete                 /nofollowlinks          /text
- /dotfiles               /not-after:             /transparent
- /error-action:          /not-before:            /type:
- /except:                /permissions:           /update
- /filenames:             /quiet                  /unique-server-names
- /filter:                /recover
- /followlinks            /recursive
-
-   Since most of these switches are common to Kermit's SEND and MSEND
-   commands, they described only briefly here. For greater detail see:
-
-     [272]http://www.columbia.edu/kermit/ckermit70.html#x1.5 (explanation
-   of switches)
-     [273]http://www.columbia.edu/kermit/ckermit70.html#x4.7
-   (file-transfer switches)
-
-   First the file-selection switches:
-
-   /AFTER:date-time
-   /BEFORE:date-time
-   /NOT-AFTER:date-time
-   /NOT-BEFORE:date-time
-          Only send those files modified on or after or before the given
-          date and time. These switches can be combined to select files
-          modified between two date/times. Various date-time formats are
-          accepted; if the date-time contains spaces, it must be enclosed
-          in braces or doublequotes. See
-          [274]http://www.columbia.edu/kermit/ckermit70.html#x1.6 and
-          [275]Section 8.13 of this document for details about date-time
-          formats. Examples:
-
-  ftp put /after:{1 jan 2000 0:00:00} *
-  ftp put /after:-5days *
-
-   /LARGER-THAN:number
-   /SMALLER-THAN:number
-          Only send files larger (smaller) than the given number of bytes
-          (octets). These switches can be combined to select files in a
-          certain size range.
-
-   /TYPE:{TEXT,BINARY}
-          Only send files that are the given type, which is determined
-          for each file just before sending it by file scanning. BINARY
-          includes TENEX; if you have included a /TENEX switch, or
-          previously given a [SET] FTP TYPE TENEX command, binary files
-          are sent in TENEX, rather than BINARY mode.
-
-   /[NO]DOTFILES
-          [Don't] include files whose names begin with dot (.). By
-          default, such files are not included unless your filespec
-          explicitly mentions them.
-
-   /NOBACKUPFILES
-          Don't include files whose names end with .~nnn~, where nnn is a
-          number, e.g. oofa.txt.~27~. These are backup files created by
-          Kermit, EMACS, and other applications. By default, backup files
-          are included.
-
-   /NOFOLLOWLINKS
-          (UNIX only) Skip over symbolic links rather than following them
-          (default). This applies to wildcard and/or recursive [M]PUTs;
-          if a single filename is given, and it happens to be a symbolic
-          link, the file it points to is sent.
-
-   /FOLLOWLINKS
-          (UNIX only) Always follow (resolve) symbolic links, even in
-          wildcard or recursive [M]PUTs. Use with caution. Watch out for
-          circular links, endless loops, etc.
-
-   /EXCEPT:pattern
-          Exception list -- don't send files whose names match the given
-          pattern. See [276]Section 1.5.4 of the [277]C-Kermit 7.0 Update
-          Notes for details. If you want to exclude a directory from a
-          recursive [M]PUT, use /EXCEPT:{dirname/*}.
-
-   /RECURSIVE
-          Sends the desired files from the current (or given) directory,
-          plus all directories beneath it, including empty directories,
-          replicating the directory structure on the server. No special
-          capabilities are required in the server, but of course your
-          login ID on the server must have the appropriate access and
-          permission to create directories. Recursive PUTs work not only
-          between like platforms (e.g. UNIX to UNIX) but also between
-          unlike ones (e.g. UNIX to VMS or Windows), in which case
-          text-file format differences are handled by Kermit's automatic
-          text/binary mode switching ([278]Section 4) and character-set
-          translation ([279]Section 3.7). Synonym: /SUBDIRECTORIES.
-
-   /UPDATE
-          Send only files that have changed since last time ([280]Section
-          3.5.2).
-
-   /ARRAY:arrayname
-          The "file" to be sent is an array, or a segment of one, rather
-          than a real file. In this case the other selection switches
-          don't apply. The array contents are sent in text mode, and each
-          array element is treated as a line. Example:
-
-  ftp put /as-name:array.txt /array:&a
-
-          (or, to send a segment of the array, /array:&a[100:199]). If
-          you don't include an /AS-NAME, a name of "_array_x_" is used
-          (where x is the array letter). If you include this switch, most
-          other switches are meaningless and ignored.
-
-   /COMMAND
-          The "file" to be sent is the standard output of a command,
-          rather than a real file. It is sent in text or binary mode
-          according to the prevailing FTP TYPE, which can be overridden
-          with a /TEXT or /BINARY switch. Example: Example:
-
-  ftp put /command /as-name:{userlist} {finger | sort -r}
-
-   /LISTFILE:filename
-          Tells Kermit to obtain the list of files to be sent from the
-          file whose name is given. This file must contain one file
-          specification (which may be wild) per line. If the list
-          includes files from different directories, such as a recursive
-          listing of a directory tree, the paths are recreated on the
-          server (if possible) if you include the /RECURSIVE switch;
-          otherwise all the files are sent to the current directory on
-          the server.
-
-   Now the other switches:
-
-   /AS-NAME:text
-          If a single file is being sent, send it with the given text as
-          its name. If multiple files are being sent, the text must be a
-          template that includes variables such as \v(filename),
-          \v(filenumber), \v(ntime), to allow dynamic creation of each
-          name. The same applies to the as-name field of the FTP PUT
-          command. If this switch is not included (and an as-name is not
-          included as the second filename to PUT), each file is sent with
-          its own name.
-
-   /BINARY
-   /TEXT
-   /TENEX
-          Forces this upload to take place in the given mode, regardless
-          of the current FTP TYPE setting, and without automatic
-          text/binary switching. /ASCII is a synonym for /TEXT.
-
-   /FILTER:command
-          Specifies that the file(s) is/are to be passed through the
-          given command or pipeline on their way to the server. Example:
-
-  ftp put /binary /filter:{gzip -c \v(filename)} /as-name:\v(filename).gz *
-
-   /TRANSPARENT
-   /LOCAL-CHARACTER-SET:name
-   /SERVER-CHARACTER-SET:name
-          Character-set translation for text files, explained in
-          [281]Section 3.7.
-
-   /ERROR-ACTION:{PROCEED,QUIT}
-          Overrides the prevailing [282]FTP ERROR-ACTION for the duration
-          of this PUT or MPUT command only.
-
-   /RECOVER
-          Resume an interrupted transfer where from the point of
-          interruption (explained in [283]Section 3.5.2). Synonym:
-          /RESTART.
-
-   /DELETE
-          Tells Kermit to delete each source file immediately after, and
-          only if, it has been uploaded completely and successfully.
-          This, in effect, moves the file from the client to the server.
-
-   /MOVE-TO:directory
-          Tells Kermit to move each source file to the named local
-          directory after, and only if, it has been uploaded completely
-          and successfully.
-
-   /RENAME-TO:template
-          Tells Kermit to rename each (local) source file according to
-          the given template after, and only if, it has been uploaded
-          completely and successfully. The template works as in /AS-NAME.
-
-   /SERVER-RENAME-TO:template
-          Tells Kermit to ask the server to rename each file according to
-          the given template as soon as, and only if, it has been
-          received completely and successfully. The template works as in
-          /AS-NAME. Requires write and rename access on the server, so
-          doesn't usually work with (e.g.) anonymous uploads to public
-          incoming areas where the permissions don't allow renaming.
-          Examples:
-
-        ftp mput /server-rename:\v(filename).ok *
-                Appends ".ok" to each filename on the server when it's
-                finished uploading.
-
-        ftp mput /as-name:\v(filename).tmp /server-rename:\v(filename) *
-                This is the reverse of the previous example; it uses a
-                temporary name while uploading is in progress and reverts
-                the file to its real name when uploading is complete.
-
-        ftp mput /as-name:\v(filename)
-                /server-rename:../final/\v(filename) *
-                Moves the file from the working directory to a final
-                directory when the upload is complete, but in this case
-                you have to know the pathname syntax of the server. If
-                the rename fails, the [M]PUT command fails according to
-                the [284]FTP ERROR-ACTION selection.
-
-   /FILENAMES:{AUTOMATIC,CONVERTED,LITERAL}
-          Overrides the [285]FTP FILENAMES setting for this upload only.
-
-   /PERMISSIONS:{ON,OFF}
-          Overrides the [286]FTP PERMISSIONS setting for this upload
-          only.
-
-   /UNIQUE
-          Tells Kermit to tell the server to give [287]unique names to
-          incoming files that would otherwise overwrite existing files
-          that have the same name. This switch conflicts with /UPDATE,
-          /RECOVER, /PERMISSIONS, and /SERVER-RENAME since the client has
-          no way of knowing the name assigned by the server.
-
-   /QUIET
-          Don't display file-transfer progress or statistics.
-
-   /SIMULATE
-          Shows which files would be sent without actually sending them.
-          Useful (for example) with /UPDATE (next section). The results
-          are shown in the file-transfer display (if it is not disabled)
-          and in the transaction log (if one is active). Hint: use SET
-          TRANSFER DISPLAY BRIEF.
-     _________________________________________________________________
-
-    3.5.2. Update Mode
-
-   When you include the /UPDATE switch, this means to skip sending any
-   file that already exists on the server if the local file's
-   modification date/time is not later than that of the corresponding
-   file on the server. Here is a typical application for update mode:
-   Suppose that on Computer A, you maintain a large set of files (say, a
-   collection of Web pages and graphics images, or the source files for a
-   software application), and you need to keep a parallel copy on another
-   Computer, B. Of course you could upload the entire collection every
-   day:
-
-  cd source-directory
-  ftp computerb.xyzcorp.com
-  ( authentication details... )
-  ftp cd target-directory
-  ftp put [ switches ] *
-
-   But if the total size is large or the network slow, this would be
-   unnecessarily time-consuming. Worse, if other users or sites had to
-   update whenever new files appeared in B's directory, this would cause
-   them unnecessary work. By including the /UPDATE switch:
-
-  ftp put /update [ other-switches ] *
-
-   only those files that changed since last time are uploaded. Here's how
-   it works. For each local file that is selected for uploading:
-
-     * The remote filename is determined in the normal way, according to
-       the [288]FTP FILENAMES setting, /FILENAMES switch, or the as-name,
-       if any.
-     * Kermit sends an MDTM (modification time) command for the
-       corresponding remote filename to the server.
-     * If the server does not understand the MDTM command, the file is
-       sent.
-     * If the server can't find a file with the given name, the file is
-       sent.
-     * If the local file's modification time is later than that of the
-       remote file, the file is sent.
-     * Otherwise -- the remote file exists but its modification time is
-       equal to or earlier than that of the local file -- the file is
-       skipped.
-
-   All time comparisons take place in Coordinated Universal Time
-   (UTC)([289]1), also known as GMT or Zulu time: Timezone 0; standard
-   time, without daylight savings.
-
-     WARNING: Some FTP servers, such as Novell NWFTPD.NLM, ignore or
-     misimplement the FTP specification and send local time rather than
-     UTC.
-
-   Update mode is useful only when always used in the same direction.
-   When you upload (PUT) a file with FTP, the destination file receives
-   the current timestamp on the server's computer, not the original
-   file's timestamp ([290]2). If you try to FTP PUT /UPDATE the same file
-   again, it will be skipped (as expected) since the remote copy is
-   newer. However, if you try to FTP GET /UPDATE the same file
-   ([291]Section 3.6), it will be transferred for the same reason.
-
-   To check the availability of PUT /UPDATE on a particular connection,
-   issue an FTP MODTIME command for a file that is known to exist on the
-   server. If it succeeds, PUT /UPDATE should work and in that case, you
-   can run a procedure like the one above every day: the first time, it
-   sends all the files; after that, it sends only the ones that changed.
-   If a transaction log is active, a notation is included for any files
-   that are skipped.
-
-   Notes:
-    1. Why is Coordinated Universal Time abbreviated UTC? From the
-       [292]National Institute of Standards and Technology FAQ: "In 1970
-       the Coordinated Universal Time system was devised by an
-       international advisory group of technical experts within the
-       International Telecommunication Union (ITU). The ITU felt it was
-       best to designate a single abbreviation for use in all languages
-       in order to minimize confusion. Since unanimous agreement could
-       not be achieved on using either the English word order, CUT, or
-       the French word order, TUC, the acronym UTC was chosen as a
-       compromise."
-    2. The Kermit FTP client is unusual in that, when downloading only,
-       it can set the received file's date from the file's date on the
-       server, but this should not affect the update feature. When
-       uploading to an FTP server, however, there is no mechanism for the
-       client to set the date of the uploaded file on the server.
-     _________________________________________________________________
-
-    3.5.3 Recovery
-
-   Suppose that while you are uploading a large file over a slow
-   connection, the connection is lost before the entire file is
-   transferred. With most FTP clients, you would have to start over, thus
-   resending the portion of the file that was sent already, and that is
-   already on the server. But Kermit's /RECOVER switch (Synonym:
-   /RESTART) lets you continue an interrupted transfer from the point of
-   failure, thus transferring only the part that wasn't sent already. The
-   prerequisites for recovery are:
-
-     * The transfer must be in BINARY mode, or else the client and server
-       must reside on like systems (e.g. both on some form of UNIX).
-     * The FTP server must support the SIZE command.
-
-   Here's how it works. When you include the /RECOVER switch:
-
-     * Kermit checks for conflicting switches, such as /UPDATE and
-       /UNIQUE; if /RECOVER is given with these switches an error occurs.
-       If /RECOVER is given in other circumstances where it could serve
-       no useful purpose (e.g. with arrays, pipes, or filters), it is
-       ignored.
-
-   If the switch is accepted, then for each selected file:
-
-     * If it is not binary (determined by scanning) and the client and
-       server are not on like platforms, recovery is canceled (the entire
-       file is sent). Otherwise:
-     * A SIZE command is sent for the file (using its remote name). If
-       the reply indicates the file was not found, or the SIZE command
-       was not understood, or any other kind of error, recovery is
-       canceled. Otherwise:
-     * A MDTM (modification time) command is sent for the file. If a
-       valid reply is received, and the modification time of the local
-       file is later than that of the remote file, recovery is canceled.
-       Otherwise:
-     * If the sizes of the two files are identical, the file is not sent.
-       Otherwise:
-     * Kermit seeks to the recovery spot in the local file, tells the
-       server to APPEND the data which is about to arrive to the remote
-       file, and then sends the data starting at the recovery point.
-
-   To safeguard file integrity, recovery is not attempted unless all the
-   preconditions are met. For the widest possible usefulness, APPEND is
-   used rather than RESTART. For stream transfers (the only kind that
-   Kermit supports) the results are the same.
-
-   By design, the /RECOVER switch can be included with any FTP PUT or
-   MPUT command, even if it specifies a group of files. This allows you
-   to resume an interrupted batch transfer from where it left off. The
-   files that were already completely sent are skipped, the file that was
-   interrupted is recovered, and the remaining files are uploaded.
-
-   By the way, it doesn't matter how the original partial file was
-   uploaded -- FTP, Kermit, Zmodem, etc: as long as the preconditions are
-   met, it can be recovered with FTP PUT /RECOVER, or for that matter
-   also using Kermit protocol and SEND /RECOVER.
-
-   A word of caution, however, when the original upload was in text mode
-   with character-set translation ([293]Section 3.7):
-
-     * If the original upload involved a translation from one single-byte
-       character set to another (e.g. Code Page 850 to Latin-1), recovery
-       is safe if you specify the same translations for the recovery. If
-       you don't, the resulting file will contain a mixture of character
-       sets.
-     * If the original upload involved a translation that changed the
-       size of the file (e.g. from an alphabetic Code Page or Latin
-       Alphabet to Unicode, or vice versa), recovery is NOT safe, even if
-       you specify the same translations.
-
-   Kermit has no way of knowing anything about the previous upload. As a
-   safeguard, an error occurs if you include /RECOVER and also specify a
-   character-set of UCS2 or UTF8, since recovery can't possibly work in
-   that situation. Otherwise, it's up to you to avoid unsafe recovery
-   operations.
-
-   [ [294]Top ] [ [295]FTP Top ] [ [296]C-Kermit Home ] [ [297]Kermit
-   Home ]
-     _________________________________________________________________
-
-  3.6. Downloading Files With FTP
-
-   Although uploading files with Kermit's FTP client is just as easy and
-   flexible as sending files with Kermit protocol, the same is not always
-   true for downloading because FTP servers lack some of the capabilities
-   of a Kermit server:
-
-     * If you want to get more than one file, you have to use MGET, not
-       GET, since the underlying FTP protocol is different in the two
-       cases. Kermit can't "autodetect" which one you mean, as it can
-       with PUT and MPUT, since it can't be expected to know the wildcard
-       syntax of the remote platform and/or FTP server (the same is true
-       for all other FTP clients). To complicate matters, FTP protocol
-       now includes two underlying mechanisms (NLST and MLSD) for
-       accomplishing MGET operations and, as explained in [298]Section
-       3.11, the two behave differently.
-     * Automatic text-binary mode switching is not done by the server. It
-       can be done by the client (Kermit), but in this case it is not
-       based on a file scan (since there is no way for Kermit prescan a
-       server file), but rather on the filename, using C-Kermit 7.0
-       [299]filename patterns.
-     * Some options that are available with FTP PUT can not be used with
-       FTP [M]GET or don't work the same way:
-         /PERMISSIONS (FTP protocol has no mechanism for this).
-         /[NOT-]BEFORE, /[NOT-]AFTER (because of the timezone problem).
-         /RECOVER works only in binary mode.   /RECURSIVE has limited
-       utility.
-
-   The commands for downloading are:
-
-   SET FILE DOWNLOAD-DIRECTORY [ directory ]
-          As with Kermit transfers, this command, if given, tells
-          C-Kermit where to store incoming files in the absence of a
-          specific as-name. If not given, incoming files are stored as
-          indicated by the as-name, if any, otherwise in the current
-          directory, just as with Kermit transfers. The more verbose
-          transfer display formats give the full pathname of each
-          received file, and, in case you have trouble finding a
-          downloaded file afterwards, its full path is also listed in the
-          transaction log (if you kept one), and you can also ask Kermit
-          where it went with the [300]WHERE command.
-
-   SET FTP GET-FILETYPE-SWITCHING { ON, OFF }
-          ON by default, causing Kermit to switch automatically into text
-          or binary mode for each file based on whether its name matches
-          a text pattern or binary pattern. Set this OFF, or use a /TEXT,
-          /BINARY, or /TENEX switch to defeat this feature. Use SHOW
-          PATTERNS to see the current pattern list.
-
-   [ FTP ] GET [ switches ] filename [ as-name ]
-          Asks the server to send the given file, and if it comes, stores
-          it locally under the given as-name, if any, otherwise under its
-          original name (modified according to the selected filename
-          conversion option), in your download directory, if you have
-          specified one, otherwise in the directory indicated in the
-          as-name, if any, otherwise in your current directory. If you
-          accidentally use a wildcard in the filename ("get *.txt") the
-          server will reply with a message like "File not found" (unless
-          there is a file whose name actually is "*.txt"). If FTP
-          GET-FILETYPE-SWITCHING is ON, and in the absence of any GET
-          switches to override it, the file is transferred in binary mode
-          if it matches any of Kermit's binary name patterns, and in text
-          mode if it matches any of Kermit's text name patterns, and in
-          the prevailing FTP TYPE if it matches none of these patterns.
-
-   [ FTP ] MGET [ switches ] filespec [ filespec [ filespec [ ... ] ] ]
-          Like GET, but for multiple files. One or more file
-          specifications can be given, and any or all (or none) of them
-          can contain wildcards or can be directory names. The file list
-          may not include an as-name, but you can still give one with the
-          /AS-NAME: switch.
-
-   In both the FTP GET and MGET commands, any filenames that contain
-   spaces must be enclosed in braces or doublequotes (see [301]Section 5
-   for details).
-
-   FTP downloads may be interrupted just like Kermit transfers. While the
-   transfer is in progress, type:
-
-     * X to interrupt the current file and go on to the next file.
-     * Z (or Control-C) to cancel the current file and all remaining
-       files.
-
-   Before proceeding, a brief word about temporary files. In FTP
-   protocol, the MGET command works by requesting a file list from the
-   server, and then (internally) issuing a GET command (FTP RETR protocol
-   directive) for each file. The file list returned by the server can be
-   any size at all, so in case it is huge, we don't store it in memory;
-   instead we put it in a temporary file. For troubleshooting purposes,
-   you should be aware of two points:
-
-    1. The location of the temporary file is chosen according the TMP or
-       TEMP environment variables. If neither of these variables is
-       defined, you might need to define it. In case there is not enough
-       space on the indicated disk or partition for the server's file
-       list, you might need to either clean up the temporary area, or
-       redefine the environment variable to indicate a different area
-       that has sufficient space.
-    2. If you want to look at the list yourself, use SET FTP DEBUG ON.
-       This tells Kermit to (a) give you the full pathname of the
-       temporary file at the end of each MGET command, and (b) not to
-       delete it, as it normally does.
-     _________________________________________________________________
-
-    3.6.1. FTP GET Switches
-
-   The following switches are available with FTP GET and MGET:
-
-   /TEXT
-          Specifies a text-mode transfer. Overrides the global FTP TYPE
-          setting and filename pattern-matching for the duration of the
-          current command only, All files are downloaded in text mode.
-          Synonym: /ASCII.
-
-   /BINARY
-          Specifies a binary-mode transfer. Overrides the global FTP TYPE
-          setting and filename pattern-matching for the duration of the
-          current command only. All files are downloaded in binary mode.
-
-   /TENEX
-          Like /BINARY but specifies a special binary transfer mode to be
-          used when getting 8-bit binary files from a 36-bit platform
-          such as TOPS-10, TOPS-20, or TENEX. All files are downloaded in
-          the special binary mode.
-
-   /RECOVER
-          This instructs Kermit to try to recover an incomplete download
-          from the point of failure. Works only in binary mode, and only
-          if the server supports the (not-yet-standard) FTP "REST"
-          directive. See [302]Section 3.6.3 for details. Synonym:
-          /RESTART.
-
-   /FILENAMES:{CONVERTED,LITERAL}
-          Overrides the [303]FTP FILENAMES (filename conversion) setting
-          for this download only, forcing incoming filenames to be either
-          converted or taken literally.
-
-   /AS-NAME:text
-          For GET, this is equivalent to giving an as-name after the
-          filename. For MGET, this is the only way to specify alternative
-          names for the incoming files. With MGET, the /AS-NAME text
-          should (must) contain a Kermit variable, usually \v(filename)
-          or \v(filenumber). Example:
-
-  mget /text /as-name:\v(filename).new *.c
-
-          This gets all ".c" files and stores them with "
-
-          .new" appended to their names. See the [304]C-Kermit 7.0 Update
-          Notes for details.
-
-   /COMMAND
-          This specifies that the incoming file is to be written to the
-          standard input of a command, rather than to a file. The command
-          name is the as-name from the GET command or the /AS-NAME
-          argument. If you need to refer to the incoming file's name in
-          the command, use \v(filename). See the description of the
-          regular Kermit [305]GET /COMMAND command for details and
-          examples.
-
-   /QUIET
-          Transfers the files quietly; don't put up a file-transfer
-          display.
-
-   /ERROR-ACTION:{QUIT,PROCEED}
-          This switch affects only MGET. If an error occurs with a
-          particular file, this tells whether to go on to the next file
-          (PROCEED) or to stop right away and fail (QUIT). The default is
-          PROCEED.
-
-   The file selection switches are:
-
-   /EXCEPT:{pattern} or /EXCEPT:{{pattern}{pattern}{...}}
-          Exception list for MGET; skip downloading any file whose name
-          matches any of the given patterns (when using the second
-          format, up to 64 patterns may be specified). [306]CLICK HERE
-          for syntax details.
-
-   /SMALLER-THAN:number
-          Download only files whose size is smaller than the given number
-          of bytes (octets). Requires that the FTP server support the
-          SIZE or MLSD directive.
-
-   /LARGER-THAN:number
-          Download only files whose size is greater than the given number
-          of bytes. Requires that the FTP server support the SIZE or MLSD
-          directive.
-
-   /NOBACKUPFILES
-          During MGET, don't download any files whose names end with
-          backup suffixes (.~n~ where n is a number).
-
-   /NODOTFILES
-          During MGET, don't download any files whose names begin with
-          period (.). Equivalent to /EXCEPT:{.*}.
-
-   /LISTFILE:local-filename
-          The given file contains a list of files to GET, one per line.
-          Filenames in the listfile can contain wildcard characters in
-          the syntax of the server. There is no limit on the number of
-          lines in the listfile.
-
-   /NAMELIST:local-filename
-          If this switch is given, then instead of actually retrieving
-          the selected files, the GET command retrieves a list of the
-          names of the files that would be retrieved, and places it in
-          the specifed file. The resulting file is an ordinary text file,
-          with one filename per line, suitable for reading by a person,
-          or processing by a computer program, including Kermit itself
-          (FOPEN / FREAD / FWRITE / FCLOSE), and as /FILELIST: file. If
-          the filename is omitted or given as "-" (dash, hyphen), the
-          list goes to the screen. NOTE: if you want a copy of the
-          complete list sent by the server, use SET FTP DEBUG ON, perform
-          an MGET, and the temporary file containing the list will be
-          kept rather than deleted (and Kermit tells you its name).
-
-   /UPDATE, /COLLISION:keyword
-          Explained in [307]Section 3.6.2.
-
-   /RECURSIVE
-          This means to try to download an entire directory tree, rather
-          than just files from a particular directory. In fact, FTP
-          protocol does not provide a method to request a recursive
-          download (unless the server supports MLSD; see [308]Section
-          3.11), so this works only if the FTP server does it anyway,
-          without being asked, as some do. In this case, Kermit detects
-          that names in the returned file list contain directory
-          separators, and therefore attempts to create the needed
-          directories as the files arrive. But this can work only if the
-          server is on the same kind of platform as the client, so the
-          pathname syntax can be recognized, and also because the server
-          does not switch between text and binary mode, which would be
-          vital for cross-platform transfers. Use with caution. Synonym:
-          /SUBDIRECTORIES.
-
-          Even when the server does not provide recursive file lists,
-          [M]GET /RECURSIVE forces Kermit to replicate any directory
-          structure implied or expressed by the server's file list. For
-          example:
-
-  get somepath/somefile
-
-          Gets the file named somefile from the server's somepath
-          directory and puts it Kermit's current (or download) directory,
-          whereas:
-
-  get /recursive somepath/somefile
-
-          creates the path locally and then puts the file in it.
-          Similarly for MGET:
-
-  mget */data/*
-
-          downloads all the files in all the data subdirectories of all
-          the subdirectories of the server's current directory and stores
-          them locally in Kermit's current (or download) directory,
-          whereas:
-
-  mget /recursive */data/*
-
-          re-creates the server's directory structure locally.
-
-   The FTP protocol does not include explicit mechanisms for recursion,
-   so Kermit builds upon what is available. Although an Internet draft
-   describes a mechanism ("MLSD") that would allow protocol-driven
-   recursion, similar to Kermit's File Attribute packets (circa 1984), it
-   has not yet attained RFC or standard status, and servers are not yet
-   widely available that offer this feature. In the meantime, the
-   effectiveness of MGET /RECURSIVE depends on the FTP server
-   implementation. If the server returns a recursive list in response to
-   the standard NLST command (whose behavior is ill-defined), Kermit's
-   FTP MGET /RECURSIVE command uses it to re-create the remote directory
-   tree locally. If the server supports MLSD, C-Kermit 8.0.206 and Kermit
-   95 2.1 and later are able to sense it automatically and use it, as
-   described below in [309]Section 3.11.
-
-   The /BEFORE:, /AFTER:, /NOT-BEFORE:, and /NOT-AFTER: switches are not
-   available for downloading because of the confusion with timezones.
-   Would the given times be in the local timezone, the server's timezone,
-   or GMT? The FTP server's directory listings show its own local times
-   but since we don't know what timezone the server is in, there's no way
-   to reconcile our local times with the server's. Similarly,
-   /PERMISSIONS can't be preserved in downloads because FTP protocol
-   provides no means of querying the server for a file's permission.
-
-   Source-file disposition switches:
-
-   /DELETE
-          Each file that is downloaded successfully is to be deleted from
-          the server. Requires the appropriate file access rights on the
-          server.
-
-   /SERVER-RENAME-TO:template
-          Asks the server to rename each (remote) source file immediately
-          after, and only if, it is sent correctly. See [310]PUT
-          /SERVER-RENAME-TO: for details.
-
-   Destination-file disposition switches:
-
-   /TO-SCREEN
-          Displays the incoming file on the screen rather than storing it
-          on disk. If this switch is given, the /RENAME-TO and /MOVE-TO
-          switches are ignored, the file-transfer display is suppressed,
-          and the given file(s) is/are shown on the screen. Can be used
-          with /FILTER, e.g.
-
-  get /text /to-screen /filter:more oofa.txt
-
-          In fact, you should always use /TO-SCREEN with /FILTER or
-          /COMMAND when the command would result in displaying the
-          incoming file on the screen; otherwise C-Kermit would have no
-          way of knowing to suppress its file transfer display (since it
-          can't be expected to know what the command or filter does).
-
-   /RENAME-TO:template
-          Each file that is downloaded is to be renamed as indicated if
-          and only if it was received completely and without error. The
-          template can be literal text or can contain variables that are
-          evaluated for each file. For MGET, the text must contain
-          variables; for GET it can be a literal string. The \v(filename)
-          variable contains the name of the current file, so:
-
-  ftp mget /rename-to:\v(filename).ok *
-
-          causes each file that is successfully downloaded to have ".ok"
-          appended to its name. For details see [311]Section 4.1 of the
-          [312]C-Kermit 7.0 Update Notes.
-
-   /MOVE-TO:text
-          Just like /RENAME-TO:, except the text denotes the name of a
-          directory to which successfully downloaded files are to be
-          moved. If the directory does not exist, it is created.
-
-   The file transfer display does not show the /MOVE-TO or /RENAME-TO
-   value, since the incoming file has not yet been moved or renamed.
-     _________________________________________________________________
-
-    3.6.2. Filename Collisions
-
-   What should happen if an incoming file has the same name as an
-   existing file in the same directory? By default, Kermit's FILE
-   COLLISION setting applies: BACKUP, RENAME, UPDATE, DISCARD, etc, as
-   described in [313]Using C-Kermit. Kermit's default FILE COLLISION
-   setting is BACKUP (rename the existing file and store the incoming
-   file under its own name) and therefore this is also the default FTP
-   collision action.
-
-   The name under which an incoming file is to be stored is determined as
-   follows:
-
-     * If an as-name was given, the as-name is used. Otherwise:
-     * If the client and server platforms are alike or [314]FTP FILENAMES
-       is set to LITERAL (or the /FILENAMES:LITERAL switch was given for
-       this download), the incoming filename is used literally.
-       Otherwise:
-     * The incoming filename is converted to a form that is friendly to
-       the local platform. For UNIX, for example, incoming filenames that
-       are all uppercase (as they might be from, say, VMS or an IBM
-       mainframe) are converted to lowercase.
-
-   If the resulting name coincides with the name of a local file that
-   already exists, we have a filename collision. Collisions are handled
-   according to the currently selected collision action:
-
-   SET FTP COLLISION { BACKUP, RENAME, UPDATE, DISCARD, APPEND, OVERWRITE
-          }
-          This establishes a filename collision for FTP, separate from
-          the Kermit one. The initial FTP collision setting is inherited
-          from Kermit's FILE COLLISION setting when the first FTP command
-          is given, but subsequent changes to Kermit's FILE COLLISION
-          setting do not affect the FTP COLLISION setting. SHOW FTP tells
-          the current FTP COLLISION setting.
-
-   FTP GET /COLLISION:{BACKUP,RENAME,UPDATE,DISCARD,APPEND,OVERWRITE}
-          Overrides the current FTP COLLISION action for this download
-          only.
-
-   FTP GET /UPDATE
-          This is equivalent to GET /COLLISION:UPDATE, and is included
-          for symmetry with PUT /UPDATE
-
-   FTP GET /UPDATE and /COLLISION:UPDATE mean to download only those
-   files whose modification dates on the server are later than those on
-   the client. Date-time comparisons are done in Coordinated Universal
-   Time (UTC, GMT, ZULU). The command:
-
-     FTP MGET /COLLISION:APPEND /AS-NAME:newfilename *.*
-
-   Downloads all matching remote files into a single local file (in
-   whatever order the server sends them).
-     _________________________________________________________________
-
-    3.6.3. Recovery
-
-   Recovery is available for downloads too, but there are some
-   differences from the uploading case described in [315]Section 3.5.3:
-
-     * The transfer must be in BINARY mode. It can not be in text mode,
-       even if the FTP server is on the same kind of platform as Kermit,
-       and even if there is no character-set translation. The original
-       download must also have been in binary mode.
-     * The FTP server must support the REST ("restart") directive.
-       Unfortunately, this is not a standard command; at this writing, it
-       is described only in an Internet Draft, not an RFC or Internet
-       Standard, but nevertheless it is found in several popular FTP
-       servers, such as [316]ProFTPD.
-
-   Here's how download recovery works:
-
-     * Kermit checks for conflicting switches, such as /UPDATE, /COMMAND,
-       or /FILTER. If /RECOVER is given with these switches an error
-       occurs.
-     * The prevailing transfer mode (SET FTP TYPE) must be BINARY. If it
-       is not, the /BINARY switch must have been included with the FTP
-       [M]GET command.
-
-   If the /RECOVER switch is accepted, then for each selected file:
-
-     * A SIZE command is sent for the file (using its remote name). If
-       the reply indicates the file was not found, or the SIZE command
-       was not understood, or any other kind of error, recovery is
-       canceled (i.e. the entire file is downloaded).
-     * If the sizes of the two files are identical, the file is not sent.
-       Otherwise:
-     * Kermit sends the REST directive to the server, indicating the size
-       of the local file. If the server responds affirmatively, Kermit
-       opens the local file in append mode and appends the incoming data
-       to it. Otherwise, recovery is canceled and the entire file is
-       downloaded.
-
-   The /RECOVER switch can be included with any FTP GET or MGET command,
-   even if it specifies a group of files. This lets you resume an
-   interrupted batch transfer from where it left off. The files that were
-   already completely sent are skipped, the file that was interrupted is
-   recovered, and the remaining files are uploaded. BUT... unlike with
-   uploading, where this can be done with any mixture of text and binary
-   files, when downloading, it can only be done if all the files are
-   binary.
-
-   It doesn't matter how the original partial file was downloaded -- FTP,
-   Kermit, HTTP, Zmodem, etc: as long as the preconditions are met, it
-   can be recovered with FTP [M]GET /RECOVER, or for that matter also
-   with GET /RECOVER (using Kermit protocol).
-
-   [ [317]Top ] [ [318]FTP Top ] [ [319]C-Kermit Home ] [ [320]Kermit
-   Home ]
-     _________________________________________________________________
-
-  3.7. Translating Character Sets
-
-   A possibly unique feature of Kermit's FTP client is its ability to
-   convert character sets when transferring files in text mode,
-   independent of the capabilites of the FTP server, as well as to
-   translate the character sets of filenames regardless of transfer mode.
-   For compatibility with existing FTP clients, and because there is a
-   certain performance penalty, Kermit won't do this unless you ask for
-   it. If you enable this feature, you need to inform Kermit of the
-   character set (to be) used on the server and in some cases (explained
-   below) also the local file character set. This discussion assumes you
-   know a bit about character sets (as you must if you have to use them);
-   see Chapter 16 of [321]Using C-Kermit for a detailed treatment. The
-   Kermit commands for FTP character-set conversion are:
-
-   SET FTP CHARACTER-SET-TRANSLATION { ON, OFF }
-          Whether to translate character sets when transferring text
-          files with FTP. OFF by default. Set this to ON to enable
-          character-set translation for subsequent FTP uploads and
-          downloads.
-
-   SET FTP SERVER-CHARACTER-SET [322]name
-          Text character set (to be) used by the server. Most FTP servers
-          are ignorant of character sets, so all translations are done
-          unilaterally by Kermit's FTP client. This means that when
-          downloading files, you must know in advance the character-set
-          used in the files you are downloading (and in their names).
-          When uploading, you must specify the character-set to which
-          local filenames and text-file contents are to be translated for
-          transmission to the server. If you SET FTP
-          CHARACTER-SET-TRANSLATION ON but do not specify an FTP
-          SERVER-CHARACTER-SET, [323]UTF8 is used, since this is the new
-          Internet standard international character set; it is upwards
-          compatible with ASCII and it encompasses most written languages
-          and therefore does not favor any particular group of people, as
-          any other default would do. If you SET FTP SERVER-CHARACTER-SET
-          to something (anything) when FTP CHARACTER-SET TRANSLATION is
-          OFF, this also sets the latter ON.
-
-   SET FILE CHARACTER-SET [324]name
-          This is the regular Kermit (non-FTP-specific) command for
-          identifying the character set (to be) used in local text files
-          and filenames.
-
-   TO REITERATE: If you SET FTP CHARACTER-SET TRANSLATION ON but do not
-   specify an FTP SERVER-CHARACTER-SET, outbound text files are converted
-   to UTF-8 and inbound text files are assumed to be UTF-8. If this is
-   not appropriate, be sure to also specify the desired FTP
-   SERVER-CHARACTER-SET.
-
-   You can use "special" (non-ASCII) characters in filenames in all the
-   client / server file management commands (FTP MKDIR, RMDIR, DIRECTORY,
-   VDIRECTORY, DELETE, etc), and also in file-transfer commands. When
-   giving commands such as FTP DIR (RDIR) and FTP PWD (RPWD), the reply
-   is translated too, so you can read it. In this example, the client and
-   server use entirely different codes to represent the special
-   characters of German:
-
-  C-Kermit> ftp xyzcorp.de /anonymous
-  C-Kermit> set ftp server-character-set latin1
-  C-Kermit> set file character-set german
-  C-Kermit> rcd Städte
-  C-Kermit> rpwd
-  "/pub/ftp/Städte is current directory"
-  C-Kermit> rdir
-  -rw-rw----  1 olaf     54018 Jan  6 17:58 Adenbüttel.txt
-  -rw-rw----  1 ursula     373 Jan  5 15:19 Aßlar.txt
-  -rw-rw----  1 gisbert    482 Jan  5 15:20 Blowatz.txt
-  -rw-rw----  1 gudrun     124 Jan  5 15:19 Böblingen.txt
-  -rw-rw----  1 olga     14348 Jan  7 14:23 Köln.txt
-
-   When the client and server file systems use different character sets,
-   you should take care to use only those characters that the two sets
-   share in common when creating filenames or text-file contents. For
-   example, PC code pages contain a lot line- and box-drawing characters,
-   and sometimes "smart quotes", etc, that are not found in ISO standard
-   8-bit character sets. You should be especially careful to avoid using
-   such characters in filenames.
-
-   [ [325]C-Kermit Character Sets ]
-     _________________________________________________________________
-
-    3.7.1. Character Sets and Uploading
-
-   Kermit's PUT and MPUT commands include full file-scanning
-   capabilities, as described in [326]Section 4. Thus if FTP
-   CHARACTER-SET-TRANSLATION is ON and your character-set associations
-   are set up appropriately, Kermit automatically switches on a per-file
-   basis between text and binary mode, and for each text file between
-   your chosen 7-bit text character set (e.g. ASCII or ISO 646 German),
-   8-bit text (e.g. Latin-1 or Japanese EUC), UCS-2, and UTF-8, and
-   converts each of these automatically to the server character-set, and
-   furthermore automatically differentiates between the Little and Big
-   Endian forms of UCS-2, always sending in Big Endian form.
-
-     WARNING: It is not advisable to use UCS-2 (or any Unicode
-     transformation other than UTF-8) "on the wire", i.e. as a server
-     character set. Most FTP servers are not able to cope with it, since
-     it contains lots of 0 (NUL) characters. If you do use it, Kermit
-     does not translate filenames to or from UCS-2, for reasons well
-     known to C programmers (for example, UNIX APIs assume filename
-     strings are NUL-terminated). [327]UTF-8 is the preferred (and
-     standard) Unicode format for the Internet.
-
-   FTP character-set translations differ from the regular Kermit ones by
-   not restricting translations to a file-character-set /
-   transfer-character-set pair. You can have Kermit's FTP client
-   translate between any pair of character sets it knows about. You can
-   see the list of supported character sets by typing either of the
-   following:
-
-  set ftp server-character-set ?
-  set file character-set ?
-
-   A typical list looks like this ([328]CLICK HERE for an explanation of
-   the names):
-
-  C-Kermit>set file char ? One of the following:
-   ascii            cp869-greek       hebrew-7         mazovia-pc
-   british          cyrillic-iso      hebrew-iso       next-multinational
-   bulgaria-pc      danish            hp-roman8        norwegian
-   canadian-french  dec-kanji         hungarian        portuguese
-   cp1250           dec-multinational iso2022jp-kanji  shift-jis-kanji
-   cp1251-cyrillic  dg-international  italian          short-koi
-   cp1252           dutch             jis7-kanji       spanish
-   cp437            elot927-greek     koi8             swedish
-   cp850            elot928-greek     koi8r            swiss
-   cp852            euc-jp            koi8u            ucs2
-   cp855-cyrillic   finnish           latin1-iso       utf8
-   cp858            french            latin2-iso
-   cp862-hebrew     german            latin9-iso
-   cp866-cyrillic   greek-iso         macintosh-latin
-  C-Kermit>
-
-   Thus you can translate not only between private sets (like PC code
-   pages) and standard ones (like Latin-1) as in Kermit protocol, but
-   also between any given pair of private sets (e.g. CP852 and Mazovia).
-   All conversions go through Unicode as the intermediate character set,
-   resulting in a minimum of character loss, since Unicode is a superset
-   of all other character sets known to Kermit.
-
-   In addition to the SET commands listed above, the FTP PUT and MPUT
-   commands include switches that apply only to the current command:
-
-   /LOCAL-CHARACTER-SET:name
-   /SERVER-CHARACTER-SET:name
-          Use these switches to force a particular translation. These
-          switches override the global FTP CHARACTER-SET-TRANSLATION and
-          SERVER-CHARACTER-SET settings and also character-set
-          differentiation by file scanning for the duration of the PUT or
-          MPUT command. The file scan is still performed, however, to
-          determine whether the file is text or binary; thus these
-          switches do not affect binary files unless you also include the
-          /TEXT switch to force all files to be treated as text.
-
-   In other words, if you include one or both of these switches with a
-   PUT or MPUT command, they are used. Similarly, the /TRANSPARENT switch
-   disables character-set translation for the PUT or MPUT command despite
-   the prevailing FTP CHARACTER-SET-TRANSLATION and SERVER-CHARACTER-SET
-   settings.
-
-   When uploading, the FILE CHARACTER-SET setting is ignored unless you
-   have forced Kermit not to [329]scan local files by including a /TEXT
-   or /BINARY switch with your [M]PUT command, or by disabling automatic
-   text/binary switching in some other way.
-
-   Examples:
-
-    1. Suppose you have a CP852 (East European) text file that you want
-       to upload and store in ISO Latin Alphabet 2 encoding:
-  ftp put /local-char:cp852 /server-char:latin2 magyar.txt
-    2. Suppose you always want your text files converted to Latin-2 when
-       uploading with FTP. Then put:
-  set ftp server-character-set latin2
-       in your Kermit customization file, and then you can omit the
-       /SERVER-CHARACTER-SET: switch from your FTP PUT commands:
-  ftp put /local-char:cp852 magyar.txt
-    3. Now suppose that all the text files on your PC are written in
-       Hungarian, but they have a variety of encodings, and you don't
-       want to have to include the /LOCAL-CHARACTER-SET: switch on every
-       FTP PUT command, or (more to the point) you want to be able to
-       send a mixture of these files all at once. Put these commands in
-       your Kermit customization file:
-  set ftp server-character-set latin2            ; ISO 8859-2
-  set file default 7-bit-character-set hungarian ; ISO 646 Hungarian
-  set file default 8-bit-character-set cp852     ; PC East European Code Page
-       and now PUT and MPUT will automatically detect and switch among
-       ISO 646 Hungarian, Code Page 852, UTF-8, and UCS-2 encodings,
-       translating each one to Latin-2 for uploading:
-  ftp put *.txt
-
-   And since binary files are also detected automatically, the latter can
-   be simplified to:
-
-  ftp put *
-
-   even when "*" matches a diverse collection of binary and text files,
-   because translations are skipped automatically for binary files.
-     _________________________________________________________________
-
-    3.7.2. Character Sets and Downloading
-
-   The commands and switches are the same as for uploading, but automatic
-   character-set switching works differently, since Kermit can't scan the
-   server files in advance. Instead, the transfer mode (text or binary)
-   is based on the filenames; each name is compared with Kermit's list of
-   text name patterns and binary name patterns. If the name matches a
-   binary pattern (for example, if the filename is oofa.tar.gz and one of
-   the filename patterns is "*.gz"), the file is downloaded in binary
-   mode; otherwise if it matches a text pattern (e.g. oofa.txt matches
-   "*.txt"), it is transferred in text ("ascii") mode. Otherwise, it is
-   transferred in the prevailing FTP TYPE.
-
-   In C-Kermit 8.0, the pattern lists used with FTP GET are not the same
-   lists used with Kermit transfers, and can not be viewed with SHOW
-   PATTERNS, nor adjusted with ADD and REMOVE TEXT-PATTERNS and
-   BINARY-PATTERNS, or SET FILE TEXT-PATTERNS and BINARY-PATTERNS.
-   Configuration of the FTP patterns list will be added in a future
-   release.
-
-   Examples:
-
-   get /server-char:latin1 /local-char:cp850 Grüße.txt
-          In this command, the filename contains special characters,
-          which you enter using whatever character set your local
-          computer uses, in this case PC Code Page 850 (cp850). The
-          command tells Kermit (in case it didn't know already from its
-          FILE CHARACTER-SET setting) that the local character set is
-          cp850 and the server's character-set is ISO 8859-1 Latin
-          Alphabet 1 (latin1). Kermit translates the filename from cp850
-          to latin1 and sends the latin1 name to the server. Since it's a
-          text file (matches "*.txt"), its contents are translated to
-          cp850 on arrival, and it is saved with a cp850 name.
-
-   mget /text /server:latin1 /local:utf8 *.txt
-          This command:
-
-          + Tells C-Kermit that the server's files are encoded in ISO
-            8859-1 Latin Alphabet 1.
-          + Tells C-Kermit to translate the incoming files into Unicode
-            UTF-8 for storage.
-          + Asks the server to send all ".txt" files in text mode.
-
-   mget /server:latin1 /local:utf8 *
-          Tells Kermit to get all files from the server's directory,
-          switching between text and binary mode based on the filename.
-          The names of all the files are translated (to UTF-8 in this
-          case), but contents are translated (also to UTF-8) only for
-          text files.
-
-   Note that any pair of 8-bit character sets is likely to have some
-   incompatibilities. Any characters in the source file that do not have
-   equivalents in the destination file's character set are converted to
-   question marks. This applies to both filenames and to text file
-   contents.
-
-   Also note that the server's ability to accept special characters in
-   filenames depends on the particular server. For example:
-
-  get Grüße.txt
-
-   works with WU-FTPD, but:
-
-  mget Grüß*.txt
-
-   does not.
-     _________________________________________________________________
-
-    3.7.3. RFC2640
-
-   [330]RFC2640, July 1999, specifies a method by which the FTP client
-   and server can negotiate the use of UTF8. However, RFC2640-capable
-   servers are rare to nonexistent at this writing, and in any case you
-   don't need them to be able to transfer text in UTF8. C-Kermit lets you
-   upload and download text files in any character set it knows about,
-   converting to or from any other character set it knows about, without
-   the knowledge, permission, or cooperation of the server, and
-   regardless of its capabilities.
-
-   [ [331]Top ] [ [332]FTP Top ] [ [333]C-Kermit Home ] [ [334]Kermit
-   Home ]
-     _________________________________________________________________
-
-  3.8. FTP Command Shortcuts
-
-   C-Kermit's FTP client coexists with other C-Kermit functions by
-   requiring the "ftp" prefix for each FTP-related command: FTP OPEN, FTP
-   GET, FTP BYE, and so on. For interactive use, however, this can be
-   rather awkward and sometimes surprising, for example when a GET
-   command starts a Kermit GET rather than an FTP GET. In fact, many
-   Kermit commands might just as easily apply to an FTP connection: GET,
-   PUT (SEND), BYE, and CLOSE. The following command lets you choose how
-   these commands are interpreted:
-
-   SET GET-PUT-REMOTE { AUTO, KERMIT, FTP }
-          Controls the orientation of GET, PUT, REMOTE and other
-          file-transfer and client/server commands that might apply to
-          either Kermit or FTP. The default setting is AUTO, meaning that
-          these commands apply to FTP if an FTP connection is open, and
-          to Kermit otherwise. KERMIT means they always apply to Kermit,
-          FTP means they always apply to FTP.
-
-   Here is a complete list of affected commands:
-
- Kermit Command               FTP Equivalent
-  (none)                       FTP [ OPEN ]
-  LOGIN                        FTP USER
-  LOGOUT                       FTP RESET
-  BYE                          FTP BYE
-  FINISH                       FTP BYE
-  CLOSE                        FTP BYE
-  HANGUP                       FTP BYE
-  BINARY                       FTP TYPE BINARY
-  TEXT (or ASCII)              FTP TYPE ASCII
-  SEND (or PUT)                FTP PUT
-  MSEND (or MPUT)              FTP MPUT
-  RESEND                       FTP PUT /RECOVER
-  CSEND                        FTP PUT /COMMAND
-  GET                          FTP GET
-  MGET                         FTP MGET
-  REGET                        FTP GET /RECOVER
-  REMOTE HELP      (RHELP)     FTP HELP
-  REMOTE CD        (RCD)       FTP CD (CWD)
-  REMOTE PWD       (RPWD)      FTP PWD
-  REMOTE DIRECTORY (RDIR)      FTP DIRECTORY
-  REMOTE DELETE    (RDEL)      FTP DELETE
-  REMOTE MKDIR     (RMKDIR)    FTP MKDIR
-  REMOTE RMDIR     (RRMDIR)    FTP RMDIR
-  REMOTE RENAME    (RRENAME)   FTP RENAME
-  REMOTE TYPE      (RTYPE)     FTP TYPE
-  REMOTE EXIT      (REXIT)     FTP BYE
-
-   The commands in the right-hand column always access FTP. The commands
-   in the left column can access either Kermit protocol or FTP:
-
-     * When GET-PUT-REMOTE is set to KERMIT, or to AUTO when there is no
-       FTP connection, the commands in the left-hand column access Kermit
-       protocol, and those right-hand column are required for FTP.
-     * When GET-PUT-REMOTE is set to FTP, or to AUTO when there is an
-       active FTP connection, the commands in the left-hand column access
-       the FTP connection and can not be used to access Kermit protocol.
-       In this case, if you want to be able to use both Kermit protocol
-       and the FTP connection, you must SET GET-PUT-REMOTE KERMIT, and
-       then use the FTP commands in the right-hand column to access the
-       FTP connection.
-
-   Note that file-management commands such as DIRECTORY, DELETE, CD, PWD,
-   MKDIR, RMDIR, HELP, RENAME, COPY, TYPE, and so on, always apply
-   locally, no matter what kind of connection you have. This is the
-   opposite of most FTP clients, where these commands are intended for
-   the server, and require an "L" prefix for local execution (e.g. "dir"
-   gets a directory listing from the server, "ldir" gets a local
-   directory listing). To illustrate with the CD command and a typical
-   UNIX FTP client:
-
- Client   Server      Change Local Directory     Change Remote Directory
-  FTP      FTP         lcd                        cd (cwd)
-  Kermit   Kermit      cd                         rcd, remote cd
-  Kermit   FTP         cd                         ftp cd, rcd, remote cd
-
-   Also note that not all REMOTE commands are useful with FTP, since FTP
-   servers do not offer the corresponding functions. These include:
-
-     * REMOTE ASSIGN  - FTP servers don't have variables
-     * REMOTE COPY    - FTP servers don't copy files
-     * REMOTE HOST    - FTP servers don't execute host (shell) commands
-     * REMOTE KERMIT  - FTP servers don't execute Kermit commands
-     * REMOTE PRINT   - FTP servers don't print files
-     * REMOTE QUERY   - FTP servers don't have variables
-     * REMOTE SET     - FTP servers don't have Kermit settings
-     * REMOTE WHO     - FTP servers don't send user lists
-
-   Finally note that command shortcuts do not apply to the HELP command.
-   For help about an FTP command, use (for example) "help ftp delete",
-   not "help delete" or "help rdelete".
-
-   [ [335]Top ] [ [336]FTP Top ] [ [337]C-Kermit Home ] [ [338]Kermit
-   Home ]
-     _________________________________________________________________
-
-  3.9. Dual Sessions
-
-   You can have an FTP session open at the same time as a regular Kermit
-   SET LINE or SET HOST (terminal) session. In this case, the default SET
-   GET-PUT-REMOTE AUTO setting should ensure that all "two-faced"
-   commands like GET, PUT, REMOTE, HANGUP, BYE, etc, apply to the Kermit
-   session, and all commands for the FTP session must include the FTP
-   prefix. To be absolutely certain, you can use SET GET-PUT-REMOTE
-   KERMIT.
-
-  ftp foo.bar.baz.com
-  if fail ...
-  (log in)
-  set host foo.bar.baz.com
-  if fail ...
-  (log in)
-
-   Now you have both an FTP and Telnet connection to the same host (of
-   course they could also be to different hosts, and you could also have
-   a direct or dialed serial connection instead of a Telnet connection).
-   Now assuming you have a Kermit server on the far end of the Kermit
-   connection:
-
-  rcd incoming      ; Changes Kermit server's directory (= REMOTE CD)
-  ftp cd incoming   ; Changes FTP server's directory
-  put oofa.txt      ; Sends a file on the Kermit connection
-  ftp put oofa.txt  ; Sends a file on the FTP connection
-  bye               ; Shuts down the Kermit connection
-  ftp bye           ; Shuts down the FTP connection
-
-   Note that PUT and SEND are synonyms for both FTP and Kermit
-   connections.
-
-   You can also establish dual sessions on the Kermit command line:
-
-  kermit -j host1 -9 host2
-
-   This makes a Telnet connection to host1 and an FTP connection to
-   host2.
-
-   [ [339]Top ] [ [340]FTP Top ] [ [341]C-Kermit Home ] [ [342]Kermit
-   Home ]
-     _________________________________________________________________
-
-  3.10. Automating FTP Sessions
-
-   Most of Kermit's scripting features can be used to make and control
-   FTP sessions: FOR and WHILE loops, IF-ELSE and SWITCH constructions,
-   variables, arrays, built-in functions, and all the rest. You can't use
-   INPUT, MINPUT, OUTPUT, CLEAR, or SCRIPT on an FTP session, but these
-   are not needed since the FTP protocol is well defined.
-
-   [343]CLICK HERE for an FTP scripting tutorial.
-
-    3.10.1. FTP-Specific Variables and Functions
-
-   The following variable tells whether an FTP connection is open:
-
-   \v(ftp_connected)
-          1 if there is an active FTP connection, 0 if there isn't.
-
-   The FTP OPEN command sets:
-
-   \v(ftp_host)
-          The host to which the most recent FTP connection was made.
-
-   \v(ftp_security)
-          The security method negotiated for the current FTP session. The
-          value is "NULL" when no security is used. See [344]3.2. Making
-          Secure FTP Connections.
-
-   \v(ftp_server)
-          The OS type (UNIX, VMS, etc) of the FTP server host.
-
-   The FTP USER command (or FTP OPEN /USER:, or FTP with automatic login)
-   sets:
-
-   \v(ftp_loggedin)
-          1 if you are logged in to an FTP server, 0 if you are not.
-
-   The current COMMAND-PROTECTION-LEVEL and DATA-PROTECTION-LEVEL values
-   are reflected in:
-
-   \v(ftp_cpl)
-   \v(ftp_dpl)
-          The values are "clear", "confidential", "safe" or "private".
-          See [345]3.2. Making Secure FTP Connections.
-
-   The FTP GET-PUT-REMOTE setting is reflected in:
-
-   \v(ftp_getputremote)
-          The values are "auto", "ftp", or "kermit".
-
-   Every FTP command sets the \v(success) variable, as well as the
-   following two FTP-specific variables:
-
-   \v(ftp_code)
-          The standardized numeric FTP protocol code from the server's
-          response to the last client command, a 3-digit decimal number
-          defined in [346]RFC959. Briefly:
-
-          1xx = Positive Preliminary Reply
-          2xx = Positive Completion Reply
-          3xx = Positive Intermediate Reply
-          4xx = Transient Negative Completion Reply
-          5xx = Permanent Negative Completion Reply
-
-   \v(ftp_message)
-          The text message, if any, from the server's response to the
-          last client command. If the most recent response had multiple
-          lines, this variable has only the final line. These messages
-          are not standardized and vary in format and content from server
-          to server. Synonym: \v(ftp_msg).
-
-   FTP file transfers set the regular Kermit transfer status variables:
-
-  \v(cps)         Characters per second of most recent transfer.
-  \v(filespec)    File specification used in most recent transfer.
-  \v(fsize)       Size of file most recently transferred.
-  \v(tfsize)      Total size of file group most recently transferred.
-  \v(xferstatus)  Status of most recent transfer (0 = success, 1 = failure).
-  \v(tftime)      Elapsed time of most recent transfer, in seconds.
-
-   During an FTP transfer, the per-file variables are:
-
-  \v(filename)    Name of current file.
-  \v(filenumber)  Ordinal file number in group (1, 2, 3, ...)
-     _________________________________________________________________
-
-    3.10.2. Examples
-
-   Let's begin with a simple example showing how to log in, send some
-   files, and log out:
-
-  define error if fail { ftp bye, stop 1 Error: \%1 }
-  set transact brief
-  log t
-  ftp ftp.xyzcorp.com /anonymous
-  if fail stop 1 Connection failed
-  if not \v(ftp_loggedin) stop 1 Login failed
-  ftp cd incoming
-  error {ftp cd}
-  cd upload
-  error {local cd}
-  ftp put /delete *
-  error {put}
-  ftp bye
-
-   First we define an error handling macro to be used after the
-   connection is made. Then we set up a brief-format transaction log to
-   keep a record of our file transfers. Then we make a connection to the
-   host and log in anonymously. The "if fail" command checks whether the
-   connection was made. The "if not" command checks whether login was
-   successful. Obviously the script should not continue unless both tests
-   succeed.
-
-   Next we change to the server's 'incoming' directory and to our own
-   'upload' directory, and send all the files that are in it (they can be
-   any mixture of text and binary files), deleting each source file
-   automatically after it is successfully uploaded. Each of these
-   operations is checked with the ERROR macro, which prevents the script
-   from continuing past a failure.
-
-   Finally we close the FTP session with the "bye" command.
-
-   Just like any other Kermit script, this one can be used in many ways:
-
-     * It can be stored in a file, and Kermit can be told to TAKE the
-       file.
-     * In UNIX, it can be a "[347]kerbang" script and therefore run
-       directly from the shell prompt or as a cron job.
-
-   We could have used command shortcuts like "rcd", "put", and "bye", but
-   since they can be ambiguous under certain circumstances, it is better
-   to avoid them in scripts; they are intended mainly for convenience
-   during interactive use. However, if you wish to use the shortcuts in a
-   script, you can do it this way (error handling omitted for brevity):
-
-  local \%t                       ; Declare a local temporary veriable
-  assign \%t \v(ftp_getputremote) ; Save current FTP GET-PUT-REMOTE setting
-  set ftp get-put-remote ftp      ; Choose FTP orientation
-  ftp xyzcorp.com /anonymous      ; Open an FTP connection
-  get oofa.txt                    ; GET a file
-  put foo.bar                     ; PUT a file
-  rdel yesterday.log              ; Delete a file on the server
-  bye                             ; Log out and disconnect from server.
-  set ftp get-put-remote \%t      ; Restore previous GET-PUT-REMOTE setting
-
-   Of course, FTP scripts can also be written as macros. This lets you
-   pass parameters such as hostnames, usernames, and filenames to them:
-
-  define doftpget {
-      if < \v(argc) 4 end 1 Usage: \%0 host user remotefile [ localfile ]
-      ftp \%1 /user:\%2
-      if fail end 1 FTP OPEN \%1 failed
-      if not \v(ftp_loggedin) end 1 FTP LOGIN failed
-      ftp get {\%3} {\%4}
-      if fail end 1 FTP GET \%3 failed
-      ftp bye
-  }
-
-   Add this definition to your Kermit customization file, and it will
-   always be available when you start Kermit. This macro lets you
-   download a file with FTP by giving a single command, e.g.:
-
-  doftpget xyzcorp.com anonymous oofa.txt
-     _________________________________________________________________
-
-    3.10.3. Automating Secure FTP Sessions
-
-   Often when making secure connections, you are prompted interactively
-   for certain information or permission to proceed. These prompts can
-   stop an automated procedure. To avoid them, you must give the
-   appropriate commands to disable them, and/or supply the prompted-for
-   information beforehand. Here are a few hints:
-
-     * Make sure that SET TAKE ERROR and SET MACRO ERROR are both OFF.
-       This is the default, but in case you have set either one of these
-       ON in your script or initialization file, this makes the script
-       halt on any kind of error. Normally you would want to check each
-       operation for success or failure and take appropriate action.
-     * On SSL and TLS connections, you may be asked whether it is OK to
-       proceed with a connection to server that presents a self-signed
-       certificate. You can use the SET AUTHENTICATION SSL (or TLS)
-       VERIFY or SET AUTH SSL (or TLS) CERTS-OK commands to avoid this
-       prompt by not requesting a certificate from the peer.
-     * (More to be added...)
-
-   [ [348]Top ] [ [349]FTP Top ] [ [350]FTP Script Tutorial ] [
-   [351]C-Kermit Home ] [ [352]Kermit Home ]
-     _________________________________________________________________
-
-  3.11. Advanced FTP Protocol Features
-
-   The remainder of the FTP documention (through the end of Section 3) is
-   new to C-Kermit 8.0.206, but we leave it in black to prevent
-   headaches. Except for titles.
-     * [353]TERMINOLOGY
-     * [354]FEATURE NEGOTIATION
-     * [355]USING MGET: NLST VERSUS MLSD
-     * [356]EXAMPLES
-     * [357]REFERENCES
-
-   The new releases of [358]C-Kermit (8.0.206) and [359]Kermit 95 (2.1)
-   support new FTP protocol features from RFC 2389 as well as most of
-   what's in the Elz and Hethmon Extensions to FTP Internet Draft (see
-   [360]References). Some of these features, such as SIZE (request a
-   file's size), MDTM (request file's modification time), and REST
-   (restart interrupted transfer) have been widely implemented in FTP
-   clients and servers for years (as well as in the initial release of
-   the Kermit FTP clients). Others such as FEAT and MLSD are rarely seen
-   and are new to the upcoming Kermit releases. TVFS (Trivial Virtual
-   File Store) is supported implicitly, and the UTF-8 character-set is
-   already fully supported at the protocol and data-interchange level.
-
-   For Kermit users, the main benefit of the new FTP protocol extensions
-   is the ability to do recursive downloads. But the extensions also
-   introduce complications and tradeoffs that you should be aware of. Of
-   course Kermit tries to "do the right thing" automatically in every
-   case for backwards compatibility. But (as noted later) some cases are
-   inherently ambiguous and/or can result in nasty surprises, and for
-   those situations new commands and switches are available to give you
-   precise control over Kermit's behavior, in case the defaults don't
-   produce the desired results.
-     _________________________________________________________________
-
-   3.11.1. Terminology Command-line FTP clients such as Kermit (as well
-   as the traditional FTP programs found on Unix, VMS, ..., even Windows)
-   have commands like PUT, MPUT, GET, MGET, and BYE, which they convert
-   into zero or more FTP protocol commands, such as NLST, RETR, QUIT. For
-   clarity, we'll use "command" to refer to commands given by the user to
-   the FTP client, and "directive" for FTP protocol commands sent by the
-   FTP client to the FTP server.
-     _________________________________________________________________
-
-   3.11.2. Feature Negotiation New FTP protocol features are negotiated
-   by the client sending a FEAT directive and the server responding with
-   a list of (new) features it supports, or else with an error indication
-   if it does not support the FEAT directive at all, in which case the
-   client has to guess which new features it supports (Kermit guesses
-   that it supports SIZE and MDTM but not MLST). Note that the MLST
-   feature includes MLSD, which is not listed separately as a feature.
-
-   Guessing is nice when it works, but sometimes it doesn't, and some FTP
-   servers become confused when you send them a directive they don't
-   understand, or they do something you didn't want, sometimes to the
-   point of closing the connection. For this reason, Kermit lets you
-   override default or negotiated features with the following new
-   commands:
-
-   FTP { ENABLE, DISABLE } FEAT
-          Enables or disables the automatic sending of a FEAT directive
-          upon connection to an FTP server. Note that
-          FTP [ OPEN ] /NOINIT   also inhibits sending the FEAT directive
-          (and several others) for the connection being OPEN'd, but
-          without necessarily disabling FEAT for subsequent connections
-          in the same Kermit instance. FEAT is ENABLED by default, in
-          which case many FTP servers are likely to reply:
-
-500 'FEAT': command not understood
-
-          which is normally harmless (but you never know). (In C-Kermit
-          8.0.208, this error message is suppressed unless you SET FTP
-          DEBUG ON.)
-
-   FTP ENABLE { MDTM, MLST, SIZE }
-          Enables the given directive for implicit use by the FTP GET and
-          MGET commands in case it has been disabled or erroneously
-          omitted by the server in its FEAT response. Note: MLSD can be
-          used in the FTP ENABLE and DISABLE commands as a synonym for
-          MLST. YOU MUST GIVE THIS COMMAND AFTER MAKING THE FTP
-          CONNECTION.
-
-   FTP DISABLE { MDTM, MLST, SIZE }
-          Disables implicit use of the given directive by GET or MGET in
-          case it causes problems; for example, because it makes
-          multifile downloads take too long or the server announces it
-          erroneously or misimplements it. Use DISABLE FEAT before making
-          a connection to prevent Kermit from sending the FEAT directive
-          as part of its initial sequence. Note that disabling FEAT,
-          SIZE, or MDTM does not prevent you from executing explicit FTP
-          FEATURES, FTP SIZE, or FTP MODTIME commands. Also note that
-          disabling SIZE prevents PUT /RESTART (recovery of interrupted
-          uploads) from working. YOU MUST GIVE THIS COMMAND AFTER MAKING
-          THE FTP CONNECTION.
-
-   To enable or disable more than one feature, use multiple FTP ENABLE or
-   FTP DISABLE commands. The SHOW FTP command shows which features are
-   currently enabled and disabled.
-
-   FTP FEATURES
-          This command sends a FEAT directive to the server. In case you
-          have been disabling and enabling different features, this
-          resynchronizes Kermit's feature list with the server's. If the
-          server does not support the FEAT directive, Kermit's feature
-          list is not changed.
-
-   FTP OPTIONS directive
-          Informational only: the server tells what options, if any, it
-          supports for the given directive, e.g. MLST. Fails if the
-          server does not support the OPTS directive or if the directive
-          for which options are requested is not valid. The directive is
-          case-insensitive.
-
-   FTP SIZE filename
-          Sends a SIZE directive to the server for the given file. The
-          filename must not contain wildcards. The server responds with
-          an error if the file can't be found, is not accessible, or the
-          SIZE directive is not supported, otherwise with the length of
-          the file in bytes, which Kermit displays and also makes
-          available to you in its \v(ftp_message) variable. If the
-          directive is successful, Kermit (re-)enables it for internal
-          use by the GET and MGET directives on this connection.
-
-   FTP MODTIME filename
-          Works just like the SIZE directive except it sends an MDTM
-          directive. Upon success, the server sends modification
-          date-time string, which Kermit interprets for you and also
-          makes available in its \v(ftp_message) variable.
-
-   Whenever a SIZE or MDTM directive is sent implicitly and rejected by
-   the server because it is unknown, Kermit automatically disables it.
-     _________________________________________________________________
-
-   3.11.3. Using MGET: NLST versus MLSD When you give an MGET command to
-   an FTP client, it sends a request to the FTP server for a list of
-   files, and then upon successful receipt of the list, goes through it
-   and issues a RETR (retrieve) directive for each file on the list (or
-   possibly only for selected files).
-
-   With the new FTP protocol extensions, now there are two ways to get
-   the list of files: the NLST directive, which has been part of FTP
-   protocol since the beginning, and the new MLSD directive, which is new
-   and not yet widely implemented. When NLST is used and you give a
-   command like "mget *.txt", the FTP client sends:
-
-NLST *.txt
-
-   and the server sends back a list of the files whose names match, e.g.
-
-foo.txt
-bar.txt
-baz.txt
-
-   Then when downloading each file, the client sends SIZE (if it wants
-   have a percent-done display) and MDTM (if it wants to set the
-   downloaded file's timestamp to match that of the original), as well as
-   RETR (to retrieve the file).
-
-   But when MLSD is used, the client is not supposed to send the filename
-   or wildcard to the server; instead it sends an MLSD directive with no
-   argument (or the name of a directory), and the server sends back a
-   list of all the files in the current or given directory; then the
-   client goes through the list and checks each file to see if it matches
-   the given pattern, the rationale being that the user knows only the
-   local conventions for wildcards and not necessarily the server's
-   conventions. So with NLST the server interprets wildcards; with MLSD
-   the client does.
-
-     The interpretation of NLST wildcards by the server is not
-     necessarily required or even envisioned by the FTP protocol
-     definition (RFC 959), but in practice most clients and servers work
-     this way. 
-
-   The principal advantage of MLSD is that instead of sending back a
-   simple list of filenames, it sends back a kind of database in which
-   each entry contains a filename together with information about the
-   file: type, size, timestamp, and so on; for example:
-
-size=0;type=dir;perm=el;modify=20020409191530; bin
-size=3919312;type=file;perm=r;modify=20000310140400; bar.txt
-size=6686176;type=file;perm=r;modify=20001215181000; baz.txt
-size=3820092;type=file;perm=r;modify=20000310140300; foo.txt
-size=27439;type=file;perm=r;modify=20020923151312; foo.zip
-(etc etc...)
-
-   (If the format of the file list were the only difference between NLST
-   and MLSD, the discussion would be finished: it would always be better
-   to use MLSD when available, and the MGET user interface would need no
-   changes. But there's a lot more to MLSD than the file-list format;
-   read on...)
-
-   The client learns whether the server supports MLSD in FEAT exchange.
-   But the fact that the server supports MLSD doesn't mean the client
-   should always use it. It is better to use MLSD:
-
-     * On connections where the server imposes a time penalty for every
-       command, e.g. the Red Hat Rawhide server. With MLSD, the client
-       needs to send only one command (RETR) per file, whereas NLST
-       requires three (SIZE, RETR, and MDTM). Suppose there is a
-       30-second delay for each command and 1000 files are to be fetched;
-       in that case, MLSD saves 60,000 seconds = 1000 minutes = 16 hours
-       and 40 minutes.
-     * For recursive downloads since there is no dependable way to
-       download directory trees with NLST.
-
-   But it is better to use NLST:
-
-     * If you want only a couple short files out of a large directory. In
-       this case, NLST is the better choice since the server sends a list
-       of only the files you want, not a list of (say) a million files,
-       which can make a big difference on slow connections. For example,
-       suppose your wildcard matches three files of 1K each, but the
-       million-file listing is 80MB long, and your connection is through
-       a modem. The overhead of using MLSD is practically infinite.
-     * If the server supports wildcarding features not known to the
-       client, but that can be used to achieve desirable effects
-       otherwise unobtainable, such as "[dir...]*.txt" in VMS or AOS/VS
-       "except" clauses.
-     * If you have been given a wildcard string by an FTP site
-       administrator for fetching a specific group of files out of a
-       larger directory, e.g. "mget ck[cuw]*.[cwh] makefile", that is
-       expected to work with any client (an FTP site administrator can't
-       be expected to know the wildcard syntax of every FTP client).
-
-   But when using MLSD there are complications:
-
-     * MLSD wants either a blank argument (meaning the current directory)
-       or else the name of a specific directory. The client must not send
-       it a wildcard or a filename.
-     * But if the user's command is "mget xxx", how does the client know
-       whether to send "xxx" in the MLSD directive? It might be the name
-       of a directory on on the server, in which case it should be sent,
-       or it might be the name of a file on the server (or a wildcard),
-       in which case it must not be sent. Since the client knows its own
-       wildcard syntax, then in most cases it would be right to send
-       "MLSD" with no argument if xxx is wild, and to send "MLSD xxx" if
-       it is not.
-     * But suppose the server's file system allows filename characters
-       that correspond with the client's wildcard syntax? For example:
-       "[abc]" could be either a valid VMS directory name or a wildcard
-       pattern used by the FTP client. What should the client do with
-       "mget [abc]"? In this case there must be a way for the user to
-       force sending the MGET argument as the MLSD argument.
-     * If "xxx" is a regular file in the server's current directory,
-       "mget xxx" works with NLST but not with MLSD.
-
-   To further complicate matters, NLST can (in theory) work just like
-   MLSD: if sent with a blank argument or a directory name, it is
-   supposed to return a complete list of files in the current or given
-   directory, which the client can match locally against some pattern. It
-   is not known if any FTP server or client does this but nevertheless,
-   it should be possible since this behavior can be inferred from RFC
-   959.
-
-   In view of these considerations, and given the need to preserve the
-   traditional FTP client command structure and behavior so the software
-   will be usable by most people:
-
-    1. The MGET command should produce the expected result in the common
-       cases, regardless of whether NLST or MLSD is used underneath.
-    2. For anomalous cases, the user needs a way to control whether the
-       MGET argument is sent to the server or kept for local use.
-    3. At the same time, the user might need a way to send a directory
-       name to the server, independent of any wildcard pattern.
-    4. The user needs a way to force NLST or MLSD for a given MGET
-       command.
-
-   By default, Kermit's MGET command uses MLSD if MLST is reported by the
-   server in its FEAT list. When MLSD is used, the filespec is sent to
-   the server if it is not wild (according to Kermit's own definition of
-   "wild" since it can't possibly know the server's definition). If the
-   filespec is wild it is held for local use to select files from the
-   list returned by the server. If MLST is not reported by the server or
-   is disabled, Kermit sends the MGET filespec with the NLST directive.
-
-   The default behavior can be overridden globally with FTP DISABLE MLST,
-   which forces Kermit to use NLST to get file lists. And then for
-   situations in which MLSD is enabled, the following MGET switches can
-   be used to override the defaults for a specific MGET operation:
-
-   /NLST
-          Forces the client to send NLST. Example:
-
-mget /nlst foo.*
-
-   /MLSD
-          Forces the client to send MLSD (even if MLST is disabled).
-          Example:
-
-mget /mlsd foo.*
-
-   /MATCH:pattern
-          When this switch is given, it forces the client to hold the
-          pattern for local use against the returned file list. If a
-          remote filespec is also given (e.g. the "blah" in "mget
-          /match:*.txt blah"), then it is sent as the NLST or MLSD
-          argument, presumably to specify the directory whose files are
-          to be listed. When the /MATCH switch is not given, the MGET
-          filespec is sent to the server if the directive is NLST or if
-          the filespec is not wild. Examples:
-
-  Command:                   With NLST:     With MLSD:
-    mget                      NLST           MLSD
-    mget *.txt                NLST *.txt     MLSD
-    mget foo                  NLST foo       MLSD foo
-    mget /match:*.txt         NLST           MLSD
-    mget /match:*.txt foo     NLST foo       MLSD foo
-
-   In other words, the pattern is always intepreted locally unless MGET
-   uses NLST and no /MATCH switch was given.
-     _________________________________________________________________
-
-   3.11.4. Examples
-
-  3.11.4.1. Downloading a Single File
-
-   There are no choices here, just use the FTP GET command. Kermit always
-   sends the RETR directive, and possibly SIZE and/or MDTM. The small
-   advantage of using MLST in this case is outweighed by the risk and
-   effort of coding a special case.
-
-  3.11.4.2. Downloading a Group of Files from a Single Directory
-
-   This case presents tradeoffs, especially on slow connections:
-
-     * For downloading all or most of the files in a directory, MLSD is
-       better because it eliminates the need to send SIZE and MDTM for
-       each file. No special actions are required in this case; Kermit
-       uses MLSD automatically if the server supports it (unless you have
-       disabled it).
-     * For a small number of files from a large directory, NLST is better
-       because it bypasses downloading of a potentially huge file list
-       prior to the files themselves. If you have a connection to a
-       server that supports MLSD, use the /NLST switch to force NLST:
-
-mget /nlst t[1234].h
-
-     * If the server supports MLSD but does not support separate SIZE or
-       MDTM directives, and you need the size and/or timestamp
-       information, MLSD is better; no special actions required.
-     * If the server supports MLSD but does not support the "size" and
-       "modify" facts, but it does support the SIZE or MDTM directives,
-       and you need the size and/or timestamp information, NLST is
-       better.
-
-  3.11.4.3. Downloading a Directory Tree
-
-   MLSD is the only choice for recursive downloads; they rarely, if ever,
-   work with NLST (the few cases where they do work rely on
-   extra-protocol "secret" notations for the NLST argument). No special
-   actions are required to force MLSD when the server supports it, unless
-   you have disabled it. Examples:
-
-   MGET /RECURSIVE
-          This tells the server to send all files and directories in the
-          tree rooted at its current directory.
-
-   MGET /RECURSIVE *.txt
-          This tells the server to send all *.txt files in the tree
-          rooted at its current directory.
-
-   MGET /MLSD /RECURSIVE *.txt
-          Same as the previous example but forces Kermit to send MLSD in
-          case it was disabled, or in case the server is known to support
-          it even though it did not announce it in its FEAT listing.
-
-   MGET /RECURSIVE /MATCH:*.zip archives
-          Tells the server to send all ZIP files in the tree rooted at
-          its "archives" directory.
-
-   MGET /RECURSIVE /MATCH:* [abc]
-          The server is running on VMS and you want it to send all the
-          files in the directory tree rooted at [ABC]. But since "[abc]"
-          looks just like a wildcard, you have to include a /MATCH:
-          switch to force Kermit to send "[abc]" as the MLSD argument.
-
-   In all cases in which the /RECURSIVE switch is included, the server's
-   tree is duplicated locally.
-
-     Although MLSD allows recursion and NLST does not, the MLSD
-     specification places a heavy burden on the client; the obvious,
-     straightforward, and elegant implementation (depth-first, the one
-     that Kermit currently uses) requires as many open temporary files
-     as the server's directory tree is deep, and therefore client
-     resource exhaustion -- e.g. exceeding the maximum number of open
-     files -- is a danger. Unfortunately MLSD was not designed with
-     recursion in mind. (Breadth-first traversal could be problematic
-     due to lack of sufficient navigation information.) 
-
-   Of course all of Kermit's other MGET switches can be used too, e.g.
-   for finer-grained file selection (by date, size, etc), for moving or
-   renaming files as they arrive, to override Kermit's automatic per-file
-   text/binary mode switching, to pass the incoming files through a
-   filter, to convert text-file character sets, and so on.
-
-  3.11.4.4. NLST/MLSD Summary Table
-
-   Here's a table summarizing MGET behavior when the server supports both
-   NLST and MLSD. /NLST and /MLSD switches are included for clarity to
-   indicate which protocol is being used, and the expected effects. In
-   practice you can omit the /NLST and /MLSD switches and the Kermit
-   client chooses the appropriate or desired protocol as described above.
-   Sample commands presume a Unix file system on the server, but of
-   course the server can have any file system or syntax at all.
-
-   User's Command FTP Sends Remarks
-   mget /nlst NLST Gets a list of all the files in the server's current
-   and downloads each file. The list includes names only, so Kermit also
-   must send SIZE and MDTM directives if size and timestamp information
-   is required (this is always true of NLST). Sending NLST without an
-   argument is allowed by the RFC959 NLST definition and by the Kermit
-   FTP client, but might not work with other clients, and also might not
-   work with every server.
-   mget /nlst foo NLST foo If "foo" is a directory, this gets a list of
-   all the files from the server's "foo" directory and downloads each
-   file; otherwise this downloads the file named "foo" (if any) from the
-   server's current directory.
-   mget /nlst *.txt NLST *.txt Gets a list of the files in the server's
-   current directory whose names match the pattern *.txt, and then
-   downloads each file from the list. Because we are using NLST, we send
-   the filespec (*.txt) to the server and the server interprets any
-   wildcards.
-   mget /nlst foo/*.txt NLST foo/*.txt  Gets a list of the files in the
-   server's "foo" directory whose names match the pattern *.txt, and then
-   downloads each file from the list (server interprets wildcards).
-   mget /nlst /match:*.txt NLST Gets a list of all the files in the
-   server's current directory and then downloads each one whose name
-   matches the pattern *.txt (client interprets wildcards).
-   mget /nlst /match:*.txt foo  NLST foo Gets a list of all the files in
-   the server's "foo" directory and then downloads each one whose name
-   matches the pattern *.txt (client interprets wildcards).
-   mget /mlsd MLSD Gets a list of all the files from the server's current
-   directory and then downloads each one. The list might include size and
-   timestamp information, in which case Kermit does not need to send SIZE
-   and MDTM directives for each file (this is always true of MLSD).
-   mget /mlsd foo MLSD foo Gets a list of all the files from the server's
-   "foo" directory (where the string "foo" does not contain wildcards)
-   and then downloads each one. If "foo" is a regular file and not a
-   directory, this command is supposed to fail, but some servers have
-   been observed that send the file.
-   mget /mlsd *.txt MLSD Gets a list of all the files from the server's
-   current directory and then downloads only the ones whose names match
-   the pattern "*.txt". Because we are using MLSD and the MGET filespec
-   is wild, we do not send the filespec to the server, but treat it as
-   though it had been given in a /MATCH: switch and use it locally to
-   match the names in the list.
-   mget /mlsd foo/*.txt MLSD This one won't work because MLSD requires
-   that the notions of server directory and filename-matching pattern be
-   separated. However, the client, which can't be expected to know the
-   server's file-system syntax, winds up sending a request that the
-   server will (or should) reject.
-   mget /mlsd /match:*.txt MLSD Gets a list of all the files from the
-   server's current directory and then downloads only the ones whose
-   names match the pattern "*.txt" (client interprets wildcards).
-   mget /mlsd /match:*.txt foo MLSD foo If "foo" is a directory on the
-   server, this gets a list of all the files from the server's "foo"
-   directory and then downloads only the ones whose names match the
-   pattern "*.txt" (client interprets wildcards). This leaves the server
-   CD'd to the "foo" directory; there's no way the client can restore the
-   server's original directory because MLSD doesn't give that
-   information, and since the client can not be expected to know the
-   server's file-system syntax, it would not be safe to guess. If "foo"
-   is a regular file, MLSD fails.
-   mget /mlsd foo bar MLSD This one is problematic. You're supposed to be
-   able to give MGET a list a filespecs; in this case we name two
-   directories. The client must change the server's directory to "foo" to
-   get the list of files, and then the files themselves. But then it has
-   no way to return to the server's previous directory in order to do the
-   same for "bar", as explained in the previous example.
-   mget /mlsd /match:* [abc] MLSD [abc] Including a /MATCH: switch forces
-   [abc] to be sent to the server even though the client would normally
-   think it was a wildcard and hold it for local interpretation. In this
-   example, [abc] might be a VMS directory name.
-   mget /mlsd /match:* t*.h MLSD t*.h Contrary to the MLSD specification,
-   some MLSD-capable FTP servers do interpret wildcards. This form of the
-   MGET command can be used to force a wildcard to be sent to the server
-   for interpretation.
-
-   When MLSD is used implicitly (that is, without an /MLSD switch given
-   to force the use of MLSD) and an MGET command such as "mget foo/*.txt"
-   fails, Kermit automatically falls back to NLST and tries again.
-     _________________________________________________________________
-
-   3.11.5. References
-
-    1. Postel, J., and J. Reynolds, File Transfer Protocol (FTP), RFC
-       959, October 1985: [361]ftp://ftp.isi.edu/in-notes/rfc959.txt.
-    2. Hethmon, P, and R. Elz, Feature negotiation mechanism for the File
-       Transfer Protocol, RFC 2389, August 1998:
-       [362]ftp://ftp.isi.edu/in-notes/rfc2389.txt.
-    3. Elz, R, and P. Hethmon, Extensions to FTP, Internet Draft
-       draft-ietf-ftpext-mlst-16.txt, September 2002:
-       [363]http://www.ietf.org/internet-drafts/draft-ietf-ftpext-mlst-16
-       .txt.
-    4. [364]The Kermit FTP Client (overview).
-
-   [ [365]Top ] [ [366]FTP Top ] [ [367]C-Kermit Home ] [ [368]Kermit
-   Home ]
-  __________________________________________________________________________
-
-4. FILE SCANNING
-
-   A new feature called file scanning is used in various contexts to
-   determine if a file is text or binary, and if it is text, what kind of
-   text. The overhead of file scanning is surprisingly tolerable, usually
-   about a quarter second per file. File scanning is now used instead of
-   filename patterns unless you SET FILE SCAN OFF, which restores the
-   previous behavior.
-
-   The primary benefit of file scanning is in file transfer. For all
-   practical purposes, now you can stop worrying about whether a file
-   should be sent in binary or text mode, or about sending mixtures of
-   text and binary files in a single operation, or configuring and
-   fine-tuning your lists of binary-file and text-file name patterns: now
-   it all just works.
-
-   File scanning is done by the file sender, which determines the type of
-   each file before it sends it and informs the receiver (Kermit or FTP
-   server) of the type. File scanning is NOT done by the receiver,
-   because it is the sender's responsibility to determine each file's
-   type, send the file in the right mode, and inform the receiver of the
-   mode. If both transfer partners are capable of this (or any other)
-   form of automatic text/binary mode switching, then files can be sent
-   in both directions with no worries about corruption due to
-   inappropriate transfer mode. (As noted in [369]Section 3, FTP servers
-   don't do this, so this discussion does not apply when using Kermit to
-   download from an FTP server.)
-
-   The rest of this section is mainly for the curious. If you don't read
-   it and simply accept all defaults, every file you send should go in
-   the appropriate mode automatically. As always, however, for
-   character-set translation to work for 7- and 8-bit character-set
-   files, the appropriate SET FILE CHARACTER-SET command(s) must have
-   been executed to identify their encoding (Kermit's default file
-   character-set is neutral ASCII except on platforms like HP-UX or
-   DG/UX, where the default file character-set is known). And of course,
-   receiving is another matter -- obviously the other Kermit must also
-   send each file in the appropriate mode.
-
-   Scanning is more reliable than filename patterns simply because
-   filenames are not reliable indicators of the file's contents. Classic
-   examples include ".doc" files, which are binary if Microsoft Word
-   documents but text on most other platforms, and ".com" files, which
-   are binary on DOS and Windows but text on VMS. Anyway, nobody knows
-   the naming conventions (if any) of all the applications (and persons!)
-   on your computer. Scanning, on the other hand, determines each file's
-   type by inspecting its contents rather than just looking at its name.
-
-   Also, file patterns -- even when they work as intended -- categorize
-   each file only as text or binary, whereas file scanning can make finer
-   distinctions:
-
-   BINARY
-          Binary data, not to be converted in any way. Examples include
-          binary machine code (executable programs), graphics images
-          (GIF, JPG, etc), compressed files (Z, GZ, etc), archives and
-          packages (ZIP, TAR, RPM, etc), object files and libraries (OBJ,
-          DLL, etc).
-
-   7-BIT TEXT
-          Text encoded in a 7-bit character set such as ASCII or one of
-          the ISO 646 national versions. Kermit has no way to tell which
-          character is used, only that it's 7-bit text. Typical examples
-          include program source code, README files, Perl or Kermit
-          scripts, plain-text email, HTML, TeX, and various textual
-          encodings of binary files: Hex, Base64, etc. When sending such
-          files, the FILE DEFAULT 7BIT-CHARACTER-SET is used as the file
-          character-set, and then the appropriate transfer character set
-          is chosen from the associations list (ASSOCIATE, SHOW
-          ASSOCIATIONS).
-
-   8-BIT TEXT
-          Text encoded in an 8-bit character set such as Latin-1,
-          Latin-2, Latin/Hebrew, Latin/Cyrillic, KOI8, HP-Roman8, JIS X
-          0208, Code Page 437, or Code Page 1252. Again, Kermit has no
-          way of knowing which particular set is in use, only that it's
-          8-bit text. When sending such files, the FILE DEFAULT
-          8BIT-CHARACTER-SET is used as the file character-set, and then
-          the appropriate transfer character set is chosen from the
-          associations list.
-
-   UCS2 TEXT
-          Unicode in its basic form, 16 bits (2 octets) per character.
-          When sending such files, UCS2 is the file character-set and the
-          byte order is identified automatically; the appropriate
-          transfer character set is chosen from the associations list.
-          Normally this would be UTF8. UTF-16 is not supported yet;
-          Kermit's Unicode translations are restricted to Plane 0, the
-          Base Multilingual Plane (BMP).
-
-   UTF8 TEXT
-          Unicode in its 8-bit transformation format. When sending such
-          files, UTF8 is the file character-set; the appropriate transfer
-          character set is chosen from the associations list, normally
-          UCS2 or UTF8.
-
-   File scanning is available in UNIX C-Kermit, in K-95, and to a limited
-   extent, in VMS C-Kermit (full scanning is problematic in VMS because
-   even plain-text files might contain binary record-format information).
-   The relevant commands are:
-
-   SET TRANSFER MODE { AUTOMATIC, MANUAL }
-          Tells whether the file-transfer mode (text or binary) should be
-          set by automatic or "manual" means. AUTOMATIC is the default,
-          which allows any of the automatic methods that are enabled to
-          do their jobs: FILE SCAN, FILE PATTERNS, peer recognition, etc.
-          MANUAL lets you control the transfer mode with the SET FILE
-          TYPE commands. As always, /TEXT and /BINARY switches on your
-          file-transfer commands override all other methods; if you give
-          one of these switches, scanning is not done. SHOW TRANSFER
-          displays the current TRANSFER MODE setting.
-
-   SET FILE SCAN { ON [ number ], OFF }
-          Turns this feature on and off. It's ON by default. When OFF,
-          the previous rules apply (SET FILE PATTERNS, etc). When ON is
-          given, you can also specify a number of bytes to be scanned.
-          The default is 49152 (= 48K). If a negative number is given,
-          the entire file is scanned, no matter how big, for maximum
-          certainty (for example, a PostScript file that appears to be
-          plain text might include an embedded graphic past the normal
-          scanning limit). SHOW FILE displays the current FILE SCAN
-          setting.
-
-   SET FILE DEFAULT 7BIT-CHARACTER-SET name
-          Tells the 7-bit character-set to use if scanning identifies a
-          7-bit text file, e.g. GERMAN. SHOW FILE displays the current
-          SET FILE DEFAULT settings. So does SHOW CHARACTER-SETS.
-
-   SET FILE DEFAULT 8BIT-CHARACTER-SET name
-          Tells the 8-bit character-set to use if scanning identifies an
-          8-bit text file, e.g. LATIN1. SHOW FILE and SHOW CHARACTER-SET
-          display this.
-
-   ASSOCIATE FILE-CHARACTER-SET fcs tcs
-          When sending files and a file character-set (fcs) is identified
-          by scanning, this tells C-Kermit which transfer character-set
-          (tcs) to translate it to. It also allows C-Kermit to set the
-          appropriate transfer character-set automatically whenever you
-          give a SET FILE CHARACTER-SET command.
-
-   ASSOCIATE TRANSFER-CHARACTER-SET tcs fcs
-          When receivinging files and a file arrives whose transfer
-          character-set (tcs) is announced by the sender, this command
-          tells C-Kermit which file character-set (fcs) to translate it
-          to. It also allows C-Kermit to set the appropriate file
-          character-set whenever you give a SET TRANSFER CHARACTER-SET
-          command.
-
-   SET FILE CHARACTER-SET name
-          When given for a 7-bit set, also sets FILE DEFAULT
-          7BIT-CHARACTER-SET to the same set. When given for an 8-bit
-          set, also sets FILE DEFAULT 8BIT-CHARACTER-SET to the same set.
-          If an ASSOCIATE FILE-CHARACTER-SET command has been given for
-          this set, also sets the corresponding transfer character-set.
-
-   DIRECTORY /XFERMODE [ filespec ]
-          Performs a file scan of the given files, listing the result for
-          each file. If FILE SCAN is OFF but PATTERNS are ON, the result
-          shown according to the current FILE TEXT-PATTERNS and
-          BINARY-PATTERNS, and are restricted to (B) and (T). When FILE
-          SCAN is ON, the results are:
-
-  (B)          Binary
-  (T)(7BIT)    Text: 7-bit
-  (T)(8BIT)    Text: 8-bit
-  (T)(UTF8)    Text: Unicode UTF8
-  (T)(UCS2BE)  Text: Unicode UCS2 Big Endian
-  (T)(UCS2LE)  Text: Unicode UCS2 Little Endian
-
-          So you can use DIR /XFER to get a preview of how each file in a
-          selected group will be transferred. Everything to the right of
-          the (B) or (T) is new. If FILE SCAN is OFF, you only get the
-          (B) or (T) as before.
-
-          Note: Big and Little Endian refer to the ordering of bytes
-          within a computer word. Big Endian architecture is standard and
-          is used on most non-PC computers. Little Endian architecture is
-          used on PCs.
-
-   To illustrate file-transfer with scanning, suppose you have a
-   directory containing a mixture of text and binary files, and each text
-   file can be 7-bit German ISO 646, 8-bit Latin-1, or Unicode in any of
-   the following forms: UCS2 Little Endian, UCS2 Big Endian, or UTF8
-   ([370]UTF-16 is not supported yet). Assuming all the built-in defaults
-   are in effect, the following three commands do the job:
-
-  set file char german   ; This sets the default for 7-bit text files
-  set file char latin1   ; This sets the default for 8-bit text files
-  send *
-
-   Each file is sent in the appropriate mode (text or binary), with text
-   files converted to the appropriate transfer character-set and labeled
-   so the receiver can convert them according to its own local
-   conventions.
-
-   By the way, what if you want to inhibit character-set translation but
-   still allow automatic text/binary mode switching? Previously, you
-   could simply SET TRANSFER CHARACTER-SET TRANSPARENT. But now with file
-   scanning, the file and transfer character-sets are set automatically
-   per file. A new command was added for this purpose:
-
-   SET TRANSFER TRANSLATION { ON, OFF }
-          Enables and disables file-transfer character-set translation.
-          It is enabled by default.
-
-   When TRANSFER TRANSLATION is OFF but FILE SCAN is ON, files are still
-   scanned to see if they are text or binary, but no character-set
-   translation is done when they text: only the normal record-format
-   conversion.
-
-   Like all SET commands, SET TRANSFER TRANSLATION is global and
-   persistent. You can also force a particular file-transfer command
-   (SEND, MSEND, GET, RECEIVE, TRANSMIT, etc) to not translate without
-   affecting the global translation settings by including the new
-   /TRANSPARENT switch, e.g.
-
-  send /transparent oofa.txt
-
-   As of C-Kermit 8.0.206, SET TRANSFER CHARACTER-SET TRANSPARENT implies
-   SET TRANSFER TRANSLATION OFF.
-
-   File scanning is also used in the TYPE command. The source file type
-   and character set are determined as above, and then the file is
-   automatically converted to your display character-set, line by line.
-   In Kermit 95, the display character-set is Unicode, perhaps converted
-   to your current console code page; in other versions of C-Kermit, it
-   is your current file character-set. Thus if you have the following set
-   appriately:
-
-  SET FILE CHARACTER-SET (necessary in Unix but not K95)
-  SET FILE DEFAULT 7BIT CHARACTER-SET
-  SET FILE DEFAULT 8BIT CHARACTER-SET
-
-   then you should be able to TYPE any text file and see something
-   reasonable. For example, in Unix, if your DEFAULT 7BIT-CHARACTER-SET
-   is ITALIAN and your DEFAULT 8BIT-CHARACTER-SET is LATIN1, and your
-   FILE CHARACTER-SET is LATIN1, you can TYPE an Italian ISO 646 file, a
-   Latin-1 file, or any kind of Unicode file, and have it translated
-   automatically to Latin-1 for your display.
-
-   In the GUI version of Kermit 95, you can see mixtures of many
-   different scripts if the file is UTF8 or UCS2: Roman, Cyrillic,
-   Hebrew, Greek, Armenian, Georgian, etc, all on the same screen at
-   once.
-
-   File scanning also adds a new criterion for file selection, i.e. to
-   select only text (or binary) files. Several commands now include a new
-   switch, /TYPE:{BINARY,TEXT,ALL}. BINARY means select only binary
-   regular files (not directories). TEXT means select only text files.
-   ALL means don't scan; select all files. Examples:
-
-   SEND /TYPE:BINARY *.*
-          Sends only binary files, skipping over text files.
-
-   NOTE: File scanning is NOT done when using external protocols (because
-   the external protocol programs, such as sz, are processing each file,
-   not Kermit).
-
-   DIRECTORY /TYPE:TEXT
-          Lists only text files but not binary files.
-
-   DELETE /TYPE:BINARY foo.*
-          Deletes all foo.* files that are regular binary files but does
-          not delete any text files.
-
-   CHMOD /TYPE:BINARY 775 *
-          (UNIX) Changes the permissions of all binary files to 775.
-
-   When FILE SCAN is OFF and FILE PATTERNS are ON, behavior is as before
-   with PATTERNS ON, but with some improvements:
-
-     * Pathnames are now stripped prior to pattern matching.
-     * Backup suffixes (like .~3~) are stripped prior to pattern
-       matching.
-
-   [ [371]Top ] [ [372]Contents ] [ [373]C-Kermit Home ] [ [374]Kermit
-   Home ]
-  __________________________________________________________________________
-
-5. FILE AND DIRECTORY NAMES CONTAINING SPACES
-
-   Prior to the introduction of the graphical user interface (GUI), it
-   was inconceivable that file or directory names could contain spaces,
-   because space is a field delimiter in all command languages. GUIs,
-   however, use dialog boxes for filenames, so there is never any
-   question of distinguishing a filename from adjacent fields -- because
-   there are no adjacent fields -- and therefore it has become quite
-   common on computers that have GUIs to have file and directory names
-   composed of multiple words. Of course this poses problems for command
-   shells and other text-oriented programs.
-
-   Most command shells address these problems by allowing such names to
-   be enclosed in doublequotes, e.g.:
-
-  cd "c:\Program Files"
-
-   C-Kermit previously used braces for this:
-
-  cd {c:\Program Files}
-
-   which was not what most people expected. And even when braces were
-   used, Kermit had difficulties with completion, file menus, and so
-   forth, within braced fields.
-
-   C-Kermit 8.0 allows either doublequotes or braces to be used for
-   grouping:
-
-  send "this file"
-  send {this file}
-  rename "this file" "that file"
-  rename {this file} "that file"
-  rename "this file" {that file}
-  cd {Program Files}
-  cd "Program Files"
-
-   Note that the doublequotes or brackets must enclose the whole file or
-   directory specification:
-
-  "c:\My Directory"
-
-   not:
-
-  c:\"My Directory"
-
-   In C-Kermit 8.0, you can also use completion on these filenames, in
-   which case Kermit supplies the quotes (or braces) automatically.
-   Example (in which the current directory contains only one file whose
-   name starts with "th" and its full name is "this file" (without the
-   quotes, but with the space)):
-
-  cat th<Tab>
-
-   Kermit repaints the filename field like this:
-
-  cat "this file"
-
-   That is, it backspaces over the original "th" and then writes the
-   filename in doublequotes.
-
-   If completion is only partial, Kermit still supplies the quotes, but
-   in this case also beeps. To continue the filename, you must first
-   backspace over the closing quote. The closing quote is supplied in
-   this case to make sure that you can see the spaces, especially if they
-   are trailing. For example, if the current directory contains two files
-   whose names start with "th", and their fill names are "this file" and
-   "this other file":
-
-  cat th<Tab>
-
-   Kermit prints:
-
-  cat "this "<Beep>
-
-   If it didn't print the closing quote, you would probably wonder why it
-   was beeping.
-
-   Also, if you begin a filename field with a doublequote or opening
-   brace, now you can use completion or get ?-help; this was never
-   possible before.
-
- C-Kermit>type "thi? Input file specification, one of the following:
-   this file        this other file
- C-Kermit>type "thi_
-
-   [ [375]Top ] [ [376]Contents ] [ [377]C-Kermit Home ] [ [378]Kermit
-   Home ]
-  __________________________________________________________________________
-
-6. OTHER COMMAND PARSING IMPROVEMENTS
-
-  6.1. Grouping Macro Arguments
-
-   Doublequotes now can be used in macro invocations to group arguments
-   containing spaces, where previously only braces could be used:
-
-  define xx show args
-  xx one "this is two" three
-
-   Result:
-
-  Macro arguments at level 0 (\v(argc) = 4):
-   \%0 = xx
-   \%1 = one
-   \%2 = this is two
-   \%3 = three
-
-   Also, you can now quote braces and quotes in macro args (this didn't
-   work before). Examples:
-
-  xx "{"  ; The argument is a single left brace
-  xx {"}  ; The argument is a doublequote character
-
-   In case this new behavior interferes with your scripts, you can
-   restore the previous behavior with:
-
-  SET COMMAND DOUBLEQUOTING OFF
-
-  6.2. Directory and File Name Completion
-
-   C-Kermit 8.0 also includes better completion for directory names, e.g.
-   in the CD command. If the name typed so far uniquely matches a
-   directory name, it is completed (as before), but now if the directory
-   contains any subdirectories, completion is partial (allowing you to
-   supply additional path segments without backspacing); otherwise it is
-   complete.
-
-   Completion has also been improved for file and directory names that
-   contain not only spaces (as described above) but also "metacharacters"
-   such as asterisk (*) and tilde (~): now the field is repainted if
-   necessary. For example, if the current directory contains only one
-   file whose name contains "blah", then in:
-
-  type *blah<Tab>
-
-   "*blah" is replaced by the filename. In earlier releases, the part
-   typed so far was left on the command line (and in the history buffer),
-   so even when the original command worked, the recalled version would
-   not. Similarly for ~ (the nearly-universal Unix notation for
-   username):
-
-  type ~olga/x<Tab>
-
-   is repainted as (e.g.):
-
-  type /users/home/olga/x(Beep)
-
-   Speaking of command history, the new SHOW HISTORY command shows your
-   command history and recall buffer. SAVE COMMAND HISTORY saves it into
-   a file of your choice.
-
-  6.3. Passing Arguments to Command Files
-
-   The method for passing arguments to command files has been improved.
-   Prior to C-Kermit 7.0 there was no provision for doing this. In
-   C-Kermit 7.0, the TAKE command was changed to allow arguments to be
-   given after the filename:
-
-  take commandfile arg1 arg2 ...
-
-   This was accomplished by replacing the current \%1, \%2, etc, with the
-   given arguments, since a new set of macro argument variables is
-   created only when a macro is executed, not a command file. It is much
-   more intuitive, however, if arguments to command files worked like
-   those to macros: the command file sees the arguments as its own \%1,
-   \%2, etc, but the caller's variables are not disturbed. C-Kermit 8.0
-   accomplishes this by automatically creating an intermediate temporary
-   macro to start the command file (if any arguments were given), thus
-   creating a new level of arguments as expected.
-
-  6.4. More-Prompting
-
-   The familiar --more?-- prompt that appears at the end of each
-   screenful of command-response output now accepts a new answer: G (Go)
-   meaning "show all the rest without pausing and asking me any more
-   questions". P (Proceed) is a synonym for G.
-
-  6.5. Commas in Macro Definitions
-
-   As noted in the [379]C-Kermit manual, comma is used to separate
-   commands in a macro definition. Even when the macro is defined on
-   multiple lines using curly-brace block-structure notation without
-   commas, the definition is still stored internally as a comma-separated
-   list of commands. Therefore special tricks are needed to include a
-   comma in a command. The classic example is:
-
-  define foo {
-      (some command)
-      if fail echo Sorry, blah failed...
-  }
-
-   This would result in Kermit trying to execute a "blah" command. This
-   could always be handled by enclosing the text in braces:
-
-  define foo {
-      (some command)
-      if fail echo {Sorry, blah failed...}
-  }
-
-   but doublequotes (more intuitive) should have worked too. Now they do:
-
-  define foo {
-      (some command)
-      if fail echo "Sorry, blah failed..."
-  }
-
-  6.6. Arrow Keys
-
-   As of version 8.0.201, C-Kermit on most platforms lets you access the
-   command history buffer with arrow keys, just as you always could with
-   control characters. The restrictions are:
-
-    1. Only Up and Down arrow keys are accepted.
-    2. Only 7-bit ANSI arrow-key sequences are understood (ESC followed
-       by [ or uppercase letter O, followed by uppercase letter A or (up)
-       B (down).
-
-   This change was made to facilitate command recall in Linux-based PDAs
-   that don't have a Control key, or at least not one that's easily (or
-   always) accessible, such as the Sharp Zaurus SL5500.
-
-   [ [380]Top ] [ [381]Contents ] [ [382]C-Kermit Home ] [ [383]Kermit
-   Home ]
-  __________________________________________________________________________
-
-7. NEW COMMANDS AND SWITCHES
-
-   See [384]Section 4 for more about file scanning and the /TYPE: switch.
-
-   ASK[Q] [ /TIMEOUT:number /QUIET /DEFAULT:text ] variable [ prompt ]
-          The new optional /TIMEOUT: switch for ASK and ASKQ causes the
-          command to time out and and fail if no response is given within
-          the specified number of seconds, 1 or greater (0 or less means
-          no timeout, wait forever). This works just like SET ASK-TIMER,
-          except its effect is local to the ASK command with which it is
-          given and it does not disturb the global ask timer setting. The
-          new /QUIET switch tells Kermit not to print an error message if
-          the ASK or ASKQ command times out waiting for a response.
-
-          Version 8.0.211 adds the /DEFAULT:text switch for ASK-Class
-          commands (ASK, ASKQ, and GETOK). This lets you supply a default
-          answer in case the user supplies an empty answer or the
-          /TIMEOUT: switch was included and the time limit expired
-          without an answer. In both these cases, the command succeeds.
-
-   CAT filename
-          Equivalent to TYPE /NOPAGE.
-
-   CDUP
-          Changes Kermit's local working directory to the parent of the
-          current one. Equivalent to "cd .." in UNIX or Windows, "cd [-]"
-          in VMS, "cd ^" in AOS/VS, etc; in other words, it's a
-          platform-independent way of moving one level up in a directory
-          tree.
-
-   CHMOD [ switches ] permission files
-          UNIX only. Sets file permissions for one or more files or
-          directories. The permission must be given as an octal number,
-          e.g. 664, 755. Switches: /DIRECTORIES, /FILES, /NOLIST, /PAGE,
-          /DOTFILES, /LIST, /NOPAGE, /RECURSIVE, /TYPE:{TEXT,BINARY,ALL},
-          /SIMULATE. The /TYPE: switch allows selection of only text or
-          binary files. For example, if you have a mixture of source
-          files and executables, you can use "chmod /files /type:text
-          664" to give owner/group read/write and world read permission
-          to the text files, and "chmod /files /type:binary 775" to give
-          the same plus execute permission to the executables. Use
-          /SIMULATE to see which files would be affected, without
-          actually changing their permissions.
-
-   CLEAR KEYBOARD-BUFFER
-          Flushes any as-yet unread characters from the keyboard input
-          buffer. Useful for flushing typeahead in scripts.
-
-   CONTINUE
-          When given at an interactive command prompt that was reached by
-          issuing a PROMPT command (described in this section) from a
-          script, this command returns to the script, continuing its
-          execution at the command after the PROMPT command. In this
-          context, CONTINUE is simply a more-intuitive synonym for END.
-
-   COPY, RENAME, and TRANSLATE
-          These commands now work on file groups if the target filename
-          is a directory, e.g. "copy oofa.* ..", "rename * ~olga/tmp/"
-
-   COPY /APPEND source destination
-          The source file specification can now include wildcards, in
-          which case all of the source files that match will go into the
-          destination file in alphabetical order by name.
-
-   DELETE /ASK
-          Asks permission to delete each file before deleting it. In
-          C-Kermit 7.0, the answers were "yes" (or "ok") and "no".
-          C-Kermit 8.0 adds "go" (meaning, delete all the rest without
-          asking) and "quit" (cancel the DELETE command and return to the
-          prompt).
-
-   DELETE /DIRECTORIES
-          Deletes not only files but also directories.
-
-   DELETE /RECURSIVE
-          Deletes all files that match the given file specification in
-          the current (or given) directory and all directories beneath
-          it.
-
-   DELETE /SUMMARY
-          Prints only the number of files deleted and total size freed,
-          without listing each file.
-
-   DELETE /TREE
-          Shorthand for DELETE /RECURSIVE /DIRECTORIES /DOTFILES/.
-          Equivalent to Windows DELTREE or Unix "rm -Rf". If no file
-          specification is given, the contents of the current directory,
-          plus all of its subdirectories and their contents, are deleted.
-
-   DELETE /TYPE:BINARY
-          Delete only regular binary files (requires FILE SCAN ON).
-
-   DELETE /TYPE:TEXT
-          Delete only regular text files (requires FILE SCAN ON).
-
-   DIRECTORY [ switches ] [ filespec [ filespec [ filespec ... ] ] ]
-          The DIRECTORY command now accepts more than one file
-          specification; e.g. "directory moon.txt sun.doc stars.*".
-
-   DIRECTORY /NORECURSIVE xxx
-          If xxx is a directory name, forces listing of the directory
-          itself rather than its contents.
-
-   DIRECTORY /FOLLOWLINKS xxx
-          (UNIX only) Tells the DIRECTORY command to follow symbolic
-          links. This not the default because it can cause endless loops.
-
-   DIRECTORY /NOFOLLOWLINKS xxx
-          (UNIX only) Tells the DIRECTORY command not to follow symbolic
-          links, but rather, merely to list them. This is the default.
-
-   DIRECTORY /OUTPUT:filename
-          Sends the results of the DIRECTORY command to the given file.
-
-   DIRECTORY /SUMMARY
-          Prints only the number of directories and files and the total
-          size, without listing each file.
-
-   DIRECTORY /TYPE:{TEXT,BINARY}
-          Shows only files of the selected type, based on file scan.
-
-   DIRECTORY /XFERMODE
-          Now shows results of file scan (see [385]Section 4).
-
-   FOPEN [ switches ] channel filename
-
-          As of version 8.0.211, FOPEN allows /dev/tty as a filename in
-          Unix-based operating systems.
-
-   FREAD /TRIM
-          (8.0.211) Trims any trailing blanks or tabs from the item (such
-          as a line of text) that it has read.
-
-   FREAD /UNTABIFY
-          (8.0.211) Converts Horizontal Tab characters to the appropriate
-          number of spaces, based on VT100-like tab stops
-          (1,9,17,25,...).
-
-   GREP [ switches ] pattern files
-          Similar to Unix grep command: displays file lines that match
-          the given [386]pattern. Switches:
-
-        /COUNT[:variable]
-                Don't show the matching lines, just tell how many lines
-                match. If a variable name is specified, the count is
-                stored in the given variable.
-
-        /DOTFILES
-                Include files whose names begin with dot.
-
-        /LINENUMBERS
-                Show line numbers of matching lines.
-
-        /NAMEONLY
-                only list the names of files that contain matching lines,
-                but not the lines themselves.
-
-        /NOBACKUP
-                Skip backup files.
-
-        /NOCASE
-                Ignore alphabetic case while pattern matching.
-
-        /NODOTFILES
-                skip files whose names start with dot (period).
-
-        /NOLIST
-                Suppress output but set SUCCESS or FAILURE according to
-                search result.
-
-        /NOMATCH
-                Look for lines that do not match the pattern.
-
-        /NOPAGE
-                Don't pause between screens of output.
-
-        /OUTPUT:filename
-                Write results into the given file.
-
-        /PAGE
-                Pause between screens of output.
-
-        /RECURSIVE
-                Search files in subdirectories too.
-
-        /TYPE:{TEXT,BINARY}
-                Search only files of the specified type.
-
-          Synonyms: FIND, SEARCH.
-
-   GETOK /TIMEOUT:n /QUIET /DEFAULT:text
-          The new /QUIET switch instructs GETOK, when given a timeout,
-          not to print an error message if it times out. As of 8.0.211, a
-          default answer can be supplied (see ASK).
-
-   HEAD [ switches ] filename
-          Equivalent to TYPE /HEAD [ other-switches ] filename.
-
-   HELP DATE
-          Explains date-time formats, including timezone notation and
-          delta times.
-
-   HELP FIREWALLS
-          Explains the firewall negotiation capabilities of your version
-          of Kermit.
-
-   KCD [ symbolic-directory-name ]
-          Changes Kermit's working directory to the named symbolic
-          directory, such as such as exedir, inidir, startup, download,
-          or and home. Type "kcd ?" for a list of symbolic directory
-          names known to your copy of Kermit, or give the new ORIENTATION
-          command for a more detailed explanation. If you give a KCD
-          command without a directory name, Kermit returns to its "home"
-          directory, which is determined in some way that depends on the
-          underlying operating system, but which you can redefine with
-          the (new) SET CD HOME command. Your home directory is shown by
-          SHOW CD and it's also the value of the \v(home) variable.
-
-   LICENSE
-          Displays the C-Kermit license.
-
-   L-commands
-          When Kermit has a connection to a Kermit or FTP server, file
-          managment commands such as CD, DIRECTORY, and DELETE might be
-          intended for the local computer or the remote server. C-Kermit
-          8.0.200 and earlier always executes these commands on the local
-          computer. If you want them executed by the remote server, you
-          have to prefix them with REMOTE (e.g. REMOTE CD) or use special
-          R-command aliases (e.g. RCD = REMOTE CD, RDIR = REMOTE DIR,
-          etc). But this feels unnatural to FTP users, who expect
-          unprefixed file management commands to be executed by the
-          remote server, rather than locally. C-Kermit 8.0.201 adds
-          automatic locus switching to present an FTP-like interface for
-          FTP connections and the normal Kermit interface for Kermit
-          connections, and a SET LOCUS command (described below) to
-          control whether or how this is done. For when LOCUS is REMOTE,
-          a new set of commands was added for local management: LCD
-          (Local CD), LDIR (Local DIR), etc. These are described below
-          under SET LOCUS.
-
-   MORE filename
-          Equivalent to TYPE /PAGE.
-
-   ORIENTATION
-          Displays symbolic directory names and the corresponding
-          variable names and values. The symbolic names, such as exedir,
-          inidir, startup, download, and home, can be used as arguments
-          to the new KCD command.
-
-   PROMPT [ text ]
-          For use in a macro or command file: enters interactive command
-          mode within the current context ([387]Section 8.1). If the
-          optional text is included, the prompt is set to it. The text
-          can include variables, functions, etc, as in the SET PROMPT
-          command. They are evaluated each time the prompt is printed.
-          Unlike the SET PROMPT command, the text argument applies only
-          to the current command level. Thus you can have different
-          prompts at different levels.
-
-   REMOTE SET MATCH { DOTIFILE, FIFO } { ON, OFF }
-          Allows the client to tell the server whether wildcards sent to
-          the server should match dot files (files whose names begin with
-          period) or FIFOs (named pipes). See SET MATCH.
-
-   SET ATTRIBUTE RECORD-FORMAT { ON, OFF }
-          Allows control of the Kermit's Record-Format attribute. Set
-          this to OFF in case incoming file are refused due to unknown or
-          invalid record formats if you want to accept the file anyway
-          (and, perhaps, postprocess it to fix its record format).
-
-   SET CD HOME [ directory ]
-          Specifies the target directory for the CD and KCD commands,
-          when they are given without an argument, and also sets the
-          value of the \v(home) variable.
-
-   SET EXIT HANGUP { OFF, ON }
-          Normally ON, meaning that when Kermit exits, it also explicitly
-          hangs up the current SET LINE / SET PORT serial port according
-          to the current SET MODEM TYPE and SET MODEM HANGUP METHOD, and
-          closes the port device if it was opened by Kermit in the first
-          place (as opposed to inherited). SET EXIT HANGUP OFF tells
-          Kermit not to do this. This can't prevent the operating system
-          from closing the device when Kermit exits (and it's a "last
-          close") but if the port or modem have been conditioned to
-          somehow ignore the close and keep the connection open, at least
-          Kermit itself won't do anything explicit to hang it up or close
-          it.
-
-   SET FILE EOF { CTRL-Z, LENGTH }
-          Specifies the end-of-file detection method to be used by
-          C-Kermit when sending and receiving text files, and in the TYPE
-          and similar text-file oriented commands. The normal and default
-          method is LENGTH. You can specify CTRL-Z when handling CP/M or
-          MS-DOS format text files, in which a Ctrl-Z (ASCII 26)
-          character within the file marks the end of the file.
-
-   SET FILE LISTSIZE number
-          Allocates space for the given number of filenames to be filled
-          in by the wildcard expander. The current number is shown by
-          SHOW FILE. If you give a command that includes a filename
-          containing a wildcard (such as "*") that matches more files
-          that Kermit's list has room for, you can adjust the list size
-          with this command.
-
-   SET FILE STRINGSPACE number
-          Allocates space for the given amount of filename strings for
-          use by the wildcard expander. The current number is shown by
-          SHOW FILE. The number is the total number of bytes of all the
-          file specifications that match the given wildcard.
-
-     If you need to process a bigger list of files than your computer
-     has memory for, you might be able use an external file list. The
-     Kermit SEND and the FTP PUT and GET commands accept a /LISTFILE:
-     switch, which gives the name of a file that contains the list of
-     files to be transferred. Example for UNIX:
-
-  !find . -print | grep / > /tmp/names
-  ftp put /update /recursive /listfile:/tmp/names
-
-   SET LOCUS { AUTO, LOCAL, REMOTE }
-          Added in C-Kermit 8.0.201.   Sets the locus for unprefixed file
-          management commands such as CD, DIRECTORY, MKDIR, etc. When
-          LOCUS is LOCAL these commands act locally and a REMOTE (or R)
-          prefix (e.g. REMOTE CD, RCD, RDIR) is required to send file
-          management commands to a remote server. When LOCUS is REMOTE,
-          an L prefix is required to issue local file management commands
-          (e.g. LCD, LDIR). The word LOCAL can't be used as a prefix
-          since it is already used for declaring local variables. LOCUS
-          applies to all types of connections, and thus is orthogonal to
-          SET GET-PUT-REMOTE, which selects between Kermit and FTP for
-          remote file-transfer and management commands. The default LOCUS
-          is AUTO, which means we switch to REMOTE whenever an FTP
-          connection is made, and to LOCAL whenever a non-FTP connection
-          is made, and switch back accordingly whenever a connnection is
-          closed. So by default, Kermit behaves in its traditional manner
-          unless you make an FTP connection, in which case it acts like a
-          regular FTP client (but better :-)   LOCUS applies to the
-          following commands:
-
-  Unprefixed    Remote       Local        Description        
-   CD (CWD)      RCD          LCD          Change (Working) Directory
-   CDUP          RCDUP        LCDUP        CD Up
-   PWD           RPWD         LPWD         Print Working Directory
-   DIRECTORY     RDIR         LDIR         Request a directory listinga
-   DELETE        RDEL         LDEL         Delete (a) file(s)
-   RENEME        RREN         LREN         Rename a file
-   MKDIR         RMKDIR       LMKDIR       Create a directory
-   RMDIR         RRMDIR       LRMDIR       Remove a directory
-
-   SET MATCH { DOTIFILE, FIFO } { ON, OFF }
-          Whether C-Kermit filename patterns (wildcards) should match
-          filenames that start with dot (period), or (Unix only) FIFOs
-          (named pipes). The defaults are to skip dotfiles in Unix but
-          match them elsewhere, and to skip FIFOs. Applies to both
-          interactive use and to server mode, when the server receives
-          wildcards, e.g. in a GET command. Also see REMOTE SET MATCH.
-
-   SET OPTIONS DIRECTORY /DOTFILES
-          Now works for server listings too (UNIX only). Give this
-          command prior to having Kermit enter server mode, and then it
-          will show files whose names begin with dot (period) when sent a
-          REMOTE DIRECTORY command.
-
-   SET QUIET ON
-          (as well as the -q command-line option) Now applies also to:
-
-          + SET HOST connection progress messages.
-          + "Press the X or E key to cancel" file-transfer message.
-          + REMOTE CD response.
-          + REMOTE LOGIN response.
-
-   SET RECEIVE PERMISSIONS { ON, OFF }
-          Tells C-Kermit whether to set the permissions of incoming files
-          (received with Kermit protocol) from the permissions supplied
-          in the file's Attribute packet (if any). Normally ON. Also see
-          SET SEND PERMISSIONS.
-
-   SET ROOT directory
-          Like UNIX chroot, without requiring privilege. Sets the root
-          for file access, does not allow reference to or creation of
-          files outside the root, and can't be undone.
-
-   SET SEND PERMISSIONS { ON, OFF }
-          Tells C-Kermit whether to include file permissions in the
-          attributes it includes with each file when sending with Kermit
-          protocol. Also see SET RECEIVE PERMISSIONS.
-
-   SET TCP { HTTP-PROXY, SOCKS-SERVER } /USER:name /PASSWORD:text
-          These commands now allow specification of username and
-          password.
-
-   SET TERMINAL . . .
-          (See [388]Section 12.)
-
-   SET TRANSFER MESSAGE [ text ]
-          Sets an initial text message to be displayed in the
-          file-transfer display. The transfer message is automatically
-          deleted once used, so must be set each time a message a
-          desired. Any variables in the message are evaluated at the time
-          the SET command is given. If the optional text is omitted, any
-          transfer message that is currently set is removed. Synonym: SET
-          XFER MSG. SHOW TRANSFER displays it if it has been set but not
-          yet used.
-
-   SHOW COMMUNICATIONS
-          In C-Kermit 8.0, SHOW COMMUNICATIONS, when given in remote mode
-          (i.e. before any connection has been established), tells the
-          typical dialout device name for the particular platform on
-          which it's running (e.g. TXA0: for VMS, or /dev/cua0p0 for
-          HP-UX). On Unix platforms, it also tells the name of the
-          lockfile directory. This way, you have an idea of what the SET
-          LINE device name should look like, and if the SET LINE command
-          fails, you know the name of the directory or device that is
-          protected against you.
-
-   SHOW VARIABLES [ name [ name [ ... ] ] ]
-          In C-Kermit 8.0.201 you can request values of a list of
-          built-in (\v(xxx)) variables. Each name is a pattern, as
-          before, but now it a free pattern rather than an anchored one
-          (explained in [389]Section 8.12) so now "show var date time"
-          shows the values of all variables whose names include the
-          strings "date" or "time".
-
-   TAIL [ switches ] filename
-          Equivalent to TYPE /TAIL [ other-switches ] filename.
-
-   TRANSMIT /NOECHO [ other switches ] filename
-          The /NOECHO switch is equivalent to giving the command SET
-          TRANSMIT ECHO OFF prior to the TRANSMIT command, except the
-          switch affects only the command with which it was given and
-          does not affect the prevailing global setting.
-
-   TRANSMIT /NOWAIT [ other switches ] filename
-          The /NOWAIT switch is equivalent to giving the command SET
-          TRANSMIT PROMPT 0 prior to the TRANSMIT command, except the
-          switch affects only the command with which it was given and
-          does not affect the prevailing global setting.
-
-   TRANSMIT /NOWAIT /NOECHO /BINARY [ other switches ] filename
-          When the TRANSMIT command is given with the /NOWAIT, /NOECHO,
-          and /BINARY switches, this activates a special "blast the whole
-          file out the communications connection all at once" mode that
-          Kermit didn't have prior to version 8.0. There has been
-          increasing demand for this type of transmission with the advent
-          of devices that expect image (e.g. .JPG) or sound (e.g. .MP3)
-          files as raw input. The obvious question is: how does the
-          receiving device know when it has the whole file? This depends
-          on the device, of course; usually after a certain amount of
-          time elapses with nothing arriving, or else when Kermit hangs
-          up or closes the connection.
-
-   TYPE /CHARACTER-SET:name
-          Allows you to specify the character set in which the file to be
-          typed is encoded.
-
-   TYPE /NUMBER
-          Adds line numbers.
-
-   TYPE /OUTPUT:filename
-          Sends the results of the TYPE command to the given file.
-
-   TYPE /TRANSLATE-TO:name
-          Used in conjunction with TYPE /CHARACTER-SET:xxx; allows you to
-          specify the character set in which the file is to be displayed.
-
-   TYPE /TRANSPARENT
-          Used to disable character-set translation in the TYPE command,
-          which otherwise can take place automatically based on file
-          scanning, even when /CHARACTER-SET and /TRANSLATE-TO switches
-          are not given.
-
-   VOID text
-          Parses the text, evaluating any backslash items in it (such as
-          function calls) but doesn't do anything further, except
-          possibly printing error messages. Useful for invoking functions
-          that have side effects without using or printing their direct
-          results, e.g. "void \fsplit(\%a,&a)".
-
-  Symbolic Links in UNIX
-
-   The UNIX versions of C-Kermit have had /FOLLOWLINKS and /NOFOLLOWLINKS
-   switches added to several commands to control the treatment of
-   symbolic links. Different commands deal differently with symbolic
-   links:
-
-   Kermit SEND, FTP MPUT
-          /NOFOLLOWLINKS is the default, which means symbolic links are
-          skipped entirely. The alternative, /FOLLOWLINKS, should be used
-          with caution, since an innocent link might point to a whole
-          file system, or it might cause a loop. There is no way in
-          Kermit or FTP protocol to send the link itself. We either skip
-          them or follow them; we can't duplicate them.
-
-   DIRECTORY
-          /NOFOLLOWLINKS is the default, which means the DIRECTORY
-          command lists symbolic links in a way that shows they are
-          links, but it does not follow them. The alternative,
-          /FOLLOWLINKS, follows links and gives information about the
-          linked-to directories and files.
-
-   DELETE, RMDIR
-          The DELETE command does not have link-specific switches. DELETE
-          never follows links. If you tell Kermit to delete a symbolic
-          link, it deletes the link itself, not the linked-to file. Ditto
-          for RMDIR.
-
-   COPY
-          The COPY command behaves just like the UNIX cp command; it
-          always follows links.
-
-   RENAME
-          The RENAME command behaves just like the UNIX mv command; it
-          operates on links directly rather than following.
-
-   [ [390]Top ] [ [391]Contents ] [ [392]C-Kermit Home ] [ [393]Kermit
-   Home ]
-  __________________________________________________________________________
-
-8. OTHER SCRIPTING IMPROVEMENTS
-
-  8.1. Performance and Debugging
-
-   A command cache for frequently used commands plus some related
-   optimizations increases the speed of compute-bound scripts by anywhere
-   from 50% to 1000%.
-
-   The new PROMPT command can be used to set breakpoints for debugging
-   scripts. If executed in a command file or macro, it gives you an
-   interactive command prompt in the current context of the script, with
-   all its variables, arguments, command stack, etc, available for
-   examination or change, and the ability to resume the script at any
-   point (END resumes it, Ctrl-C or STOP cancels it and returns to top
-   level).
-
-   The new Ctrl-C trapping feature ([394]Section 8.14) lets you intercept
-   interruption of scripts. This can be used in combination with the
-   PROMPT command to debug scripts. Example:
-
-define ON_CTRLC {
-    echo INTERRUPTED BY CTRL-C...
-    echo The command stack has not yet been rolled back:
-    show stack
-    echo Type Ctrl-C again or use the END command to return to top level.
-    prompt Debug>
-}
-
-   Adding this ON_CTRL definition to your script lets you interrupt it at
-   any point and get prompt that is issued at the current command level,
-   so you can query local variables, etc.
-
-   [ [395]Top ] [ [396]Contents ] [ [397]C-Kermit Home ] [ [398]Kermit
-   Home ]
-     _________________________________________________________________
-
-  8.2. Using Macros as Numeric Variables
-
-   A macro is a way to assign a value to a name, and then use the name to
-   refer to the value. Macros are used in two ways in Kermit: as
-   "subroutines" or functions composed of Kermit commands, which are
-   executed, or as variables to hold arbitrary values -- text, numbers,
-   filenames, etc.
-
-   When a macro is to be executed, its name is given as if it were a
-   C-Kermit command, optionally preceded by the word "do". When a macro
-   is used as a variable, it must be "escaped" with \m(xxx) (or
-   equivalent function, e.g. \s(xxx), \:(xxx), \fdefinition(xxx)), where
-   xxx is the macro name, for example:
-
-  define filename /usr/olga/oofa.txt
-  send \m(filename)
-
-   Of course variables can also hold numbers:
-
-  define size 17
-  declare \&a[\m(size)]
-  ...
-  define index 3
-  if ( == \m(index) 3 ) echo The third value is: \&a[\m(index)]
-  evaluate index (\m(index) * 4)
-  if ( > \m(index) \m(size) ) echo Out of range!
-
-   But these are contexts in which only numbers are valid. C-Kermit 8.0
-   has been changed to treat non-escaped non-numeric items in strictly
-   numeric contexts as macro names. So it is now possible (but not
-   required) to omit the \m(...) notation and just use the macro name in
-   these contexts:
-
-  define size 17
-  declare \&a[size]
-  ...
-  define index 3
-  if ( == index 3 ) echo The third value is: \&a[index]
-  evaluate index (index * 4)
-  if ( > index size ) echo Out of range!
-
-   This is especially nice for loops that deal with arrays. Here, for
-   example, is a loop that reverses the order of the elements in an
-   array. Whereas formerly it was necessary to write:
-
-  .\%n ::= \fdim(&a)
-  for \%i 1 \%n/2 1 {
-      .tmp := \&a[\%n-\%i+1]
-      .\&a[\%n-\%i+1] := \&a[\%i]
-      .\&a[\%i] := \m(tmp)
-  }
-
-   Recoding this to use macro names "i" and "n" instead of the backslash
-   variables \%i and \%n, we have:
-
-  .n ::= \fdim(&a)
-  for i 1 n/2 1 {
-      .tmp := \&a[n-i+1]
-      .\&a[n-i+1] := \&a[i]
-      .\&a[i] := \m(tmp)
-  }
-
-   which reduces the backslash count to less than half. The final
-   statement in the loop could be written ".\&a[i] ::= tmp" if the array
-   contained only numbers (since ::= indicates arithmetic expression
-   evaluation).
-
-   Also, now you can use floating-point numbers in integer contexts (such
-   as array subscripts), in which case they are truncated to an integer
-   value (i.e. the fractional part is discarded).
-
-   Examples of numeric contexts include:
-
-     * Array subscripts.
-     * Any numeric function argument.
-     * Right-hand side of ::= assignments.
-     * EVALUATE command or \fevaluate() function expression.
-     * The INCREMENT or DECREMENT by-value.
-     * IF =, >, <, !=, >=, and <= comparands.
-     * The IF number construct.
-     * FOR-loop variables.
-     * STOP, END, and EXIT status codes.
-     * The INPUT timeout value.
-     * PAUSE, WAIT, SLEEP, MSLEEP intervals.
-     * The SHIFT argument.
-     * Numeric switch arguments, e.g. TYPE /WIDTH:number, SEND
-       /LARGER:number.
-     * SCREEN MOVE-TO row and column number.
-     * Various SET DIAL parameters (timeout, retry limit, etc).
-     * Various SET SEND or RECEIVE parameters (packet length, window
-       size, etc).
-     * Various other SET parameters.
-
-   and:
-
-     * S-Expressions (explained in [399]Section 9).
-
-   Macro names used in numeric contexts must not include mathematical
-   operators. Although it is legal to create a macro called "foo+bar", in
-   a numeric context this would be taken as the sum of the values of
-   "foo" and "bar". Any such conflict can be avoided, of course, by
-   enclosing the macro name in \m(...).
-
-   [ [400]Top ] [ [401]Contents ] [ [402]C-Kermit Home ] [ [403]Kermit
-   Home ]
-     _________________________________________________________________
-
-  8.3. New IF Conditions
-
-   Several new IF conditions are available:
-
-   IF DECLARED arrayname
-          Explained in [404]Section 8.6.
-
-   IF KBHIT
-          Allows a script to test whether a key was pressed without
-          actually trying to read it.
-
-   IF KERBANG (Unix only)
-          True if Kermit was started from a Kerbang script. This is
-          useful for knowing how to interpret the \&@[] and \&_[]
-          argument vector arrays, and under what conditions to exit.
-
-   IF INTEGER n
-          This is just a synonym for IF NUMERIC, which is true if n
-          contains only digits (or, if n is a variable, its value
-          contains only digits).
-
-   By contrast, IF FLOAT n succeeds if n is a floating-point number OR an
-   integer (or a variable with floating-point or integer value).
-   Therefore, IF FLOAT should be used whenever any kind of number is
-   acceptable, whereas IF INTEGER (or IF NUMERIC) when only an integer
-   can be used.
-
-   [ [405]Top ] [ [406]Contents ] [ [407]C-Kermit Home ] [ [408]Kermit
-   Home ]
-     _________________________________________________________________
-
-  8.4. The ON_UNKNOWN_COMMAND Macro
-
-   The new ON_UNKNOWN_COMMAND macro, if defined, is executed whenever you
-   give a command that is not known to C-Kermit; any operands are passed
-   as arguments. Here are some sample definitions:
-
-  DEF ON_UNKNOWN_COMMAND telnet \%1 ; Treat unknown commands as hostnames
-  DEF ON_UNKNOWN_COMMAND dial \%1   ; Treat unknown commands phone numbers
-  DEF ON_UNKNOWN_COMMAND take \%1   ; Treat unknown commands as filenames
-  DEF ON_UNKNOWN_COMMAND !\%*       ; Treat unknown commands as shell commands
-
-   The ON_CD macro, if defined, is executed whenever Kermit is given a CD
-   (change directory) command (8.0.211). Upon entry to this macro, the
-   directory has already changed and the new directory string is
-   available in the \v(directory) variable, and also as the first
-   argument (\%1).
-
-   [ [409]Top ] [ [410]Contents ] [ [411]C-Kermit Home ] [ [412]Kermit
-   Home ]
-     _________________________________________________________________
-
-  8.5. The SHOW MACRO Command
-
-   The SHOW MACRO command has been changed to accept more than one macro
-   name:
-
-  (setq a 1 b 2 c 3)
-  show mac a b c
-  a = 1
-  b = 2
-  c = 3
-
-   An exact match is required for each name (except that case doesn't
-   matter). If you include wildcard characters, however, a pattern match
-   is performed:
-
-  show mac [a-c]*x
-
-   shows all macros whose names start with a, b, or c, and end with x.
-
-   [ [413]Top ] [ [414]Contents ] [ [415]C-Kermit Home ] [ [416]Kermit
-   Home ]
-     _________________________________________________________________
-
-  8.6. Arrays
-
-   A clarification regarding references to array names (as opposed to
-   array elements): You can use array-name "abbreviations" like &a only
-   in contexts that expect array names, like ARRAY commands or array-name
-   function arguments such as the second argument of \fsplit(). In a
-   LOCAL statement, however, you have to write \&a[], since "local &a"
-   might refer to a macro named "&a".
-
-   In function arguments, however, you MUST use the abbreviated form:
-   \fsplit(\%a,&a) or \fsplit(\%a,&a[]). If you include the backslash (as
-   in "\fsplit(\%a,\&a[])") a parse error occurs.
-
-   Here are the new array-related commands:
-
-   IF DECLARED arrayname
-          Allows a script to test whether an array has been declared. The
-          arrayname can be a non-array backslash variable such as \%1 or
-          \m(name), in which case it is evaluated first, and the result
-          is treated as the array name. Otherwise, arrayname is treated
-          as in the ARRAY commands: it can be a, &a, &a[], \&a, \&a[],
-          \&a[3], \&a[3:9], etc, with the appropriate results in each
-          case. Synonym: IF DCL.
-
-   UNDECLARE arrayname
-          UNDECLARE is a new top-level command to undeclare an array.
-          Previously this could only be done with "declare \&a[0]" (i.e.
-          re-declare the array with a dimension of 0).
-
-   ARRAY LINK linkname arrayname
-          Creates a symbolic link from the array named by linkname (which
-          must be the name of an array that is not yet declared in the
-          current context) to the array named by arrayname (which must
-          the name of a currently declared array that is not itself a
-          link, or a variable containing the name of such an array). The
-          two names indicate the same array: if you change an array
-          element, the change is reflected in the link too, and vice
-          versa. If you undeclare the link, the real array is unaffected.
-          If you undeclare the real array, all links to it disappear. If
-          you resize an array (directly or through a link), all links to
-          it are updated automatically.
-
-   Array links let you pass array names as arguments to macros. For
-   example, suppose you had a program that needed to uppercase all the
-   elements of different arrays at different times. You could write a
-   macro to do this, with the array name as an argument. But without
-   array links, there would be no way to refer to the argument array
-   within the macro. Array links make it easy:
-
-  define arrayupper {
-      local \&e[] \%i
-      array link \&e[] \%1
-      for i 1 \fdim(&e) 1 { .\&e[i] := \fupper(\&e[i]) }
-  }
-  declare \&a[] = these are some words
-  arrayupper &a
-  show array &a
-
-   The macro declares the array link LOCAL, which means it doesn't
-   conflict with any array of the same name that might exist outside the
-   macro, and that the link is destroyed automatically when the macro
-   exits. This works, by the way, even if the link name and the macro
-   argument name are the same, as long as the link is declared LOCAL.
-
-   As noted, you can't make a link to a nonexistent array. So when
-   writing a macro whose job is to create an array whose name is passed
-   as an argument, you must declare the array first (the size doesn't
-   matter as long as it's greater than 0). Example:
-
-  define tryme {                ; Demonstration macro
-      local \&e[]               ; We only need this inside the macro
-      array link \&e[] \%1      ; Make local link
-      shift                     ; Shift argument list
-      void \fsplit(\%*,&e)      ; Split remainder of arg list into array
-  }
-  declare \&a[1]                ; Declare target array in advance
-  tryme &a here are some words  ; Invoke the macro with array name and words
-  show array a                  ; See the results
-
-   One final improvement allows the macro itself to declare the array
-   (this was not possible in earlier Kermit releases): if the array name
-   in the DECLARE command is a variable (and not an array name), or
-   includes variables, the resulting value is used as the array name. So:
-
-  define tryme {                ; Demonstration macro
-      declare \%1[1]            ; Preliminary declaration for target array
-      local \&e[]               ; We only need this inside the macro
-      array link \&e[] \%1      ; Make local link
-      shift                     ; Shift argument list
-      void \fsplit(\%*,&e)      ; Split remainder of arg list into array
-  }
-  tryme &a here are some words  ; Invoke the macro with array name and words
-  show array a                  ; See the results
-
-   The SHOW ARRAY command now indicates whether an array name is a link.
-
-   Also see the descriptions of [417]\fjoin() and [418]\fsplit(), plus
-   [419]Section 8.10 on the MINPUT command, which shows how an entire
-   array (or segment of it) can be used as the MINPUT target list.
-
-   [ [420]Top ] [ [421]Contents ] [ [422]C-Kermit Home ] [ [423]Kermit
-   Home ]
-     _________________________________________________________________
-
-  8.7. New or Improved Built-in Variables and Functions
-
-   The following new built-in variables are available:
-
-  \v(buildid)       A date string like "20000808" indicating when C-Kermit was
-built.
-  \v(ftime)         Current time, secs since midnight, including fraction of se
-cond.
-  \v(iprompt)       The current SET PROMPT value
-  \v(sexp)          The most recent S-Expression (see [424]Section 9)
-  \v(sdepth)        The current S-Expression invocation depth ([425]Section 9)
-  \v(svalue)        The value of the most recent S-Expression ([426]Section 9)
-
-  \v(ftp_code)      Most recent FTP response code ([427]Section 3)
-  \v(ftp_connected) FTP connection status ([428]Section 3)
-  \v(ftp_cpl)       FTP Command Protection Level ([429]Section 3.2)
-  \v(ftp_dpl)       FTP Data Protection Level ([430]Section 3.2)
-  \v(ftp_getputremote) The current SET GET-PUT-REMOTE setting ([431]Section 3.8
-)
-  \v(ftp_host)      Name or IP address of FTP server ([432]Section 3)
-  \v(ftp_loggedin)  FTP login status ([433]Section 3)
-  \v(ftp_message)   Most recent FTP response message ([434]Section 3)
-  \v(ftp_security)  FTP Security method ([435]Section 3.2)
-  \v(ftp_server)    OS type of FTP server ([436]Section 3)
-
-  \v(http_code)       Most recent HTTP response code
-  \v(http_connected)  HTTP connection status
-  \v(http_host)       Name or IP address of HTTP server
-  \v(http_message)    Most recent HTTP response message
-  \v(http_security)   TLS cipher used to secure the HTTP session
-
-  \v(hour)            Hour of the day, 0 to 23.
-  \v(timestamp)       Equivalent to "\v(ndate) \v(time)".
-
-  \v(log_debug)       Current debug log file, if any.
-  \v(log_packet)      Current packet log file, if any.
-  \v(log_session)     Current session log file, if any.
-  \v(log_transaction) Current transaction log file, if any.
-  \v(log_connection)  Current connection log file, if any.
-
-   The following new or improved built-in functions are available:
-
-  \fcmdstack()            Allows programmatic access to the command stack.
-  \fcvtdate()             [437]Section 8.13, format options added
-  \fdelta2secs()          [438]Section 8.13
-  \fdostounixpath(s1)     Converts a DOS filename to Unix format.
-  \fsplit()               Now allows grouping/nesting in source string.
-  \fword()                Allows the same grouping and nesting.
-  \fjoin(&a,s1,n1,n2)     Copies an array into a single string.
-  \fsubstitute(s1,s2,s3)  Substitutes characters within a string.
-  \freplace()             Has new 4th "occurrence" argument.
-  \fsexpression()         Evaluates an S-Expression (explained in [439]Section
-9).
-  \ftrim(), \fltrim()     Now trim CR and LF by default, as well as SP and Tab.
-  \funixtodospath(s1)     Converts a Unix filename to DOS format.
-  \fkeywordval(s1,c1)     Assigns values to keywords (macros) (explained below)
-.
-
-   Most functions that have "2" in their names to stand for the word "to"
-   can now also be written with "to", e.g. "\fdelta2secs(),"
-   \fdeltatosecs()."
-
-   \funtabify(string)
-          (New to 8.0.211) Replaces Horizontal Tab characters in the
-          given string with spaces based on VT100-like tab stops.
-
-   \fverify(s1,s2,n)
-          As of version 8.0.211, returns -1 if s2 is an empty string.
-          Previously it returned 0, making \fverify(abc,\%a) look as if
-          \%a was a string combosed of a's, b's, and/or c's when in fact
-          it contained nothing.
-
-   \fcode(string)
-          As of version 8.0.211, returns 0 if string is empty or missing.
-          Previously it returned the empty string, which made it unsafe
-          to use in arithmetic or boolean expressions.
-
-   \v(inscale)
-          New to version 8.0.211, its value is the INPUT SCALE-FACTOR
-          ([440]Section 8.10), default 1.0.
-
-  8.7.1. The \fkeywordval() Function
-
-   \fkeywordval(s1,c1) is new to C-Kermit 8.0. Given a string s1 of the
-   form "name=value", it creates a macro with the given name and assigns
-   it the given value. If no value appears after the equal sign, any
-   existing macro of the given name is undefined. Blanks are
-   automatically trimmed from around the name and value. The optional c1
-   parameter is the assignment operator character, equal sign (=) by
-   default. This function is handy for processing keyword parameters or
-   any other form of parameter-value pair. Suppose, for example, you want
-   to write a macro that accepts keyword parameters rather than
-   positional ones:
-
-  define MYDIAL {
-      local \%i modem hangup method device speed number
-      def number 5551234          ; Assign default parameter values
-      def speed 57600
-      def modem usrobotics
-      def hangup rs232
-      def method tone
-      def country 1
-      for \%i 1 \v(argc)-1 1 {    ; Parse any keyword parameters...
-          if not \fkeywordval(\&_[\%i]) end 1 Bad parameter: "\&_[\%i]"
-      }
-      set dial country \m(country)
-      set modem type \m(modem)
-      set modem hang \m(hangup)
-      set dial method \m(tone)
-      set line \m(device)
-      if fail stop 1
-      set speed \m(speed)
-      if fail stop 1
-      show comm
-      set dial display on
-      dial \m(number)
-      if success connect
-  }
-
-   In this example, all the defaults are set up inside the macro, and
-   therefore it can be invoked with no parameters at all. But if you want
-   to have the macro dial a different number, you can supply it as
-   follows:
-
-  mydial number=7654321
-
-   You can supply any number of keyword parameters, and you can give them
-   in any order:
-
-  mydial number=7654321 hangup=modem speed=115200
-
-  8.7.2. The \fsplit(), \fjoin(), and \fword() Functions
-
-   \fjoin(&a,s1,n1,n2) is also new; it creates a string from an array (or
-   a piece of one). &a is the name of the array (a range specifier can be
-   included); s1 is a character or string to separate each element in the
-   result string (can be omitted, in which case the elements are not
-   separated at all), and n1 is a grouping mask, explained below. If s1
-   is empty or not specified, the array elements are separated with
-   spaces. If you want the elements concatenated with no separator,
-   include a nonzero n2 argument. Given the array:
-
-  declare \&a[] = 0 1 2 3 4 5 6 7 8 9
-
-   you can get effects like this:
-
-  \fjoin(&a)      0 1 2 3 4 5 6 7 8 9
-  \fjoin(&a,:)    0:1:2:3:4:5:6:7:8:9
-  \fjoin(&a,{,})  0,1,2,3,4,5,6,7,8,9
-  \fjoin(&a,...)  0...1...2...3...4...5...6...7...8...9
-  \fjoin(&a,,,1)  0123456789
-
-   \fsplit(), \fword(), \fstripb(), and \fjoin() accept a "grouping mask"
-   argument, n1, which is a number from 0 to 63, in which:
-
-   1 = "" doublequotes
-   2 = {} braces
-   4 = '' singlequotes
-   8 = () parentheses
-  16 = [] square brackets
-  32 = <> angle brackets
-
-   These can be OR'd (added) together to make any number 0-63 (-1 is
-   treated the same as 63, 0 means no grouping). If a bit is on, the
-   corresponding kind of grouping is selected. (If more than 1 bit is set
-   for \fjoin(), only the lowest-order one is used.)
-
-   If you include the same character in the grouping mask and the include
-   list, the grouping mask takes precedence. Example:
-
-  def \%a  a "b c d" e
-  \fsplit(\%a,&a[],,,-1)  = 3  <-- doublequote used for grouping
-  \fsplit(\%a,&a[],,",-1) = 3  <-- doublequote still used for grouping
-
-   Nesting of matched left and right grouping characters (parentheses,
-   braces, and brackets, but not quotes) is recognized. Example:
-
-  def \%a a (b c <d e [f g {h i} j k] l m> n o) p
-  \fsplit(\%a,&a,,,0)  = 16 (no grouping)
-  \fsplit(\%a,&a,,,2)  = 15 (braces only)
-  \fsplit(\%a,&a,,,16) = 11 (square brackets only)
-  \fsplit(\%a,&a,,,32) =  7 (angle brackets only)
-  \fsplit(\%a,&a,,,63) =  3 (all)
-  \fsplit(\%a,&a,,,-1) =  3 (all)
-
-   \fsplit() and \fjoin() are "reciprocal" functions. You can split a
-   string up into an array and join it back into a new string that is
-   equivalent, as long as \fsplit() and \fjoin() are given equivalent
-   grouping masks, except that the type of braces might change. Example:
-
-  def \%a a {b c [d e] f g} "h i" j <k l> m
-  echo STRING=[\%a]
-  echo WORDS=\fsplit(\%a,&a,,,-1)
-  show array a
-  asg \%b \fjoin(&a,{ },2)
-  echo JOIN  =[\%b]
-  echo WORDS=\fsplit(\%b,&b,,,-1)
-  show array b
-
-   The arrays a and b are identical. The strings a and b are as follows:
-
-  \%a: a {b c [d e] f g} "h i" j <k l> m
-  \%b: a {b c [d e] f g} {h i} j {k l} m
-
-   It is possible to quote separator grouping characters with backslash
-   to override their grouping function. And of course to include
-   backslash itself in the string, it must be quoted too. Furthermore,
-   each backslash must be doubled, so the command parser will still pass
-   one backslash to \fsplit() for each two that it sees. Here are some
-   examples using \fsplit() with a grouping mask of 8 (treat parentheses
-   as grouping characters).
-
-  String                  Result
-    a b c d e f             6
-    a b\\ c d e f           5
-    a b (c d e) f           4
-    a b \\(c d e\\) f       6
-    a b \\\\(c d e\\\\) f   7
-
-   \fsplit() has also been changed to create its array (if one is given)
-   each time it is called, so now it can be conveniently called in a loop
-   without having to redeclare the array each time.
-
-   Incidentally... Sometimes you might want to invoke \fsplit() in a
-   situation where you don't care about its return value, e.g. when you
-   just want to fill the array. Now you can "call" \fsplit() or any other
-   function with the new [441]VOID command:
-
-  void \fsplit(\%a,&a)
-
-   \fsplit() and \fjoin() also accept a new, optional 6th argument, an
-   options flag, a number that can specify a number of options. So far
-   there is just one option, whose value is 1:
-
-   separator-flag
-          Normally separators are collapsed. So, for example,
-
-  \fword(Three        little          words,2)
-
-          returns "little" (the second word). Space is a separator, but
-          there are multiple spaces between each word. If the value 1 is
-          included in the option flag, however, each separator counts. If
-          two separators are adjacent, an empty word is produced between
-          them. This is useful for parsing (e.g.) comma-separated lists
-          exported from databases or spreadsheets.
-
-  8.7.3. The \fcmdstack() Function
-
-   The new \fcmdstack() function gives access to the command stack:
-
-   \fcmdstack(n1,n2)
-          Arguments: n1 is the command stack level. If omitted, the
-          current level, \v(cmdlevel), is used. n2 is a function code
-          specifying the desired type of information:
-
-  0 (default) = name of object at level n1.
-  1 (nonzero) = object type (0 = prompt; 1 = command file; 2 = macro).
-
-          The default for n2 is 0.
-
-   The name associated with prompt is "(prompt)". Here's a loop that can
-   be included in a macro or command file to show the stack (similar to
-   what the SHOW STACK command does):
-
-  for \%i \v(cmdlevel) 0 -1 {
-      echo \%i. [\fcmdstack(\%i,1)] \fcmdstack(\%i,0)
-  }
-
-   In this connection, note that \v(cmdfile) always indicates the most
-   recently invoked active command file (if any), even if that file is
-   executing a macro. Similarly, \v(macro) indicates the most recently
-   invoked macro (if any), even if the current command source is not a
-   macro. The name of the "caller" of the currently executing object
-   (command file or macro) is:
-
-  \fcmdstack(\v(cmdlevel)-1)
-
-   and its type is:
-
-  \fcmdstack(\v(cmdlevel)-1,1)
-
-   To find the name of the macro that invoked the currently executing
-   object, even if one or more intermediate command files (or prompting
-   levels) are involved, use a loop like this:
-
-  for \%i \v(cmdlevel)-1 0 -1 {
-      if = \fcmdstack(\%i,1) 2 echo CALLER = \fcmdstack(\%i,0)
-  }
-
-   Of course if you make a macro to do this, the macro must account for
-   its own additional level:
-
-  define CALLER {
-      for \%i \v(cmdlevel)-2 0 -1 {
-          if = \fcmdstack(\%i,1) 2 return \fcmdstack(\%i,0)
-      }
-      return "(none)"
-  }
-
-   The built-in variable \v(cmdsource) gives the current command source
-   as a word ("prompt", "file", or "macro").
-
-  8.7.4. The VOID Command
-
-   VOID is like ECHO in that all functions and variables in its argument
-   text are evaluated. but it doesn't print anything (except possibly an
-   error message if a function was invocation contained or resulted in
-   any errors). VOID sets FAILURE if it encounters any errors, SUCCESS
-   otherwise.
-
-   [ [442]Top ] [ [443]Contents ] [ [444]C-Kermit Home ] [ [445]Kermit
-   Home ]
-     _________________________________________________________________
-
-  8.8. The RETURN and END Commands
-
-   The execution of a macro is terminated in any of the following ways:
-
-     * With an END [ number [ message ] ] command. If a number is given,
-       the macro succeeds if the number is 0, and fails if it is not
-       zero; if a number is not given, the macro succeeds.
-     * With a STOP command, which works just like END except it peels
-       back the command stack all the way to top level.
-     * With a RETURN [ text ] command, in which case the macro always
-       succeeds.
-     * By running out of commands to execute, in which case the macro
-       succeeds or fails according the most recently executed command
-       that sets success or failure.
-
-   The same considerations apply to command files invoked by the TAKE
-   command.
-
-   If a macro does not execute any commands that set success or failure,
-   then invoking the macro does not change the current SUCCESS/FAILURE
-   status. It follows, then, that the mere invocation of a macro does not
-   change the SUCCESS/FAILURE status either. This makes it possible to
-   write macros to react to the status of other commands (or macros), for
-   example:
-
-  define CHKLINE {
-      if success end 0
-      stop 1 SET LINE failed - please try another device.
-  }
-  set modem type usrobotics
-  set line /dev/cua0
-  chkline
-  set speed 57600
-  dial 7654321
-
-   By the way, none of this is news. But it was not explicitly documented
-   before, and C-Kermit 7.0 and earlier did not always handle the RETURN
-   statement as it should have.
-
-   [ [446]Top ] [ [447]Contents ] [ [448]C-Kermit Home ] [ [449]Kermit
-   Home ]
-     _________________________________________________________________
-
-  8.9. UNDEFINing Groups of Variables
-
-   The UNDEFINE command, which previously accepted one variable name, now
-   accepts a list of them, and also accepts wildcard notation to allow
-   deletion of variables that match a given pattern.
-
-   UNDEFINE [ switches ] name [ name [ name [ ... ] ] ]
-          Undefines the variables whose names are given. Up to 64 names
-          may be given in one UNDEFINE command.
-
-   If you omit the switches and include only one name, the UNDEFINE
-   command works as before.
-
-   Switches include:
-
-   /MATCHING
-          Specifies that the names given are to treated as patterns
-          rather than literal variable names. Note: pattern matching
-          can't be used with array references; use the ARRAY command to
-          manipulate arrays and subarrays.
-
-   /LIST
-          List the name of each variable to be undefined, and whether it
-          was undefined successfully ("ok" or "error"), plus a summary
-          count at the end.
-
-   /SIMULATE
-          List the names of the variables that would be deleted without
-          actually deleting them. Implies /LIST.
-
-   The UNDEFINE command fails if there were any errors and succeeds
-   otherwise.
-
-   The new _UNDEFINE command is like UNDEFINE, except the names are
-   assumed to be variable names themselves, which contain the names (or
-   parts of them) of the variables to be undefined. For example, if you
-   have the following definitions:
-
-  define \%a foo
-  define foo This is some text
-
-   then:
-
-  undef \%a
-
-   undefines the variable \%a, but:
-
-  _undef \%a
-
-   undefines the macro foo.
-
-   Normal Kermit patterns are used for matching; metacharacters include
-   asterisk, question mark, braces, and square brackets. Thus, when using
-   the /MATCHING switch, if the names of the macros you want to undefine
-   contain any of these characters, you must quote them with backslash to
-   force them to be taken literally. Also note that \%* is not the name
-   of a variable; it is a special notation used within a macro for "all
-   my arguments". The command "undef /match \%*" deletes all \%x
-   variables, where x is 0..9 and a..z. Use "undef /match \%[0-9]" to
-   delete macro argument variables or "undef /match \%[i-n]" to delete a
-   range of \%x variables.
-
-   [ [450]Top ] [ [451]Contents ] [ [452]C-Kermit Home ] [ [453]Kermit
-   Home ]
-     _________________________________________________________________
-
-  8.10. The INPUT and MINPUT Commands
-
-   As of C-Kermit 8.0.211, the INPUT and MINPUT commands accept a switch:
-
-   [M]INPUT /NOMATCH timeout
-          The /NOMATCH switch allows INPUT or MINPUT to read incoming
-          material for the specified amount of time, without attempting
-          to match it with any text or patterns. When this switch is
-          included, the [M]INPUT command succeeds when the timeout
-          interval expires, with \v(instatus) set to 1, meaning "timed
-          out", or fails upon interruption or i/o error.
-
-   Also in version 8.0.211, there is a new way to apply a scale factor to
-   [M]INPUT timeouts:
-
-   SET INPUT SCALE-FACTOR floating-point-number
-          This scales all [M]INPUT timeouts by the given factor, allowing
-          time-sensitive scripts to be adjusted to changing conditions
-          such as congested networks or different-speed modems without
-          having to change each INPUT-class command. This affects only
-          those timeouts that are given in seconds, not as wall-clock
-          times. Although the scale factor can have a fractional part,
-          the INPUT timeout is still an integer. The new built-in
-          variable \v(inscale) tells the current INPUT SCALE-FACTOR.
-
-   The MINPUT command can be used to search the incoming data stream for
-   several targets simultaneously. For example:
-
-  MINPUT 8 one two three
-
-   waits up to 8 seconds for one of the words "one", "two", or "three" to
-   arrive. Words can be grouped to indicate targets that contain spaces:
-
-  MINPUT 8 nineteeen twenty "twenty one"
-
-   And of course you can also use variables in place of (or as part of)
-   the target names:
-
-  MINPUT 8 \%a \&x[3] \m(foo)
-
-   Until now you had to know the number of targets in advance when
-   writing the MINPUT statement. Each of the examples above has exactly
-   three targets.
-
-   But suppose your script needs to look for a variable number of
-   targets. For this you can use arrays and \fjoin(), described in
-   [454]Section 8.7. Any number of \fjoin() invocations can be included
-   in the MINPUT target list, and each one is expanded into the
-   appropriate number of separate targets each time the MINPUT command is
-   executed. Example:
-
-  declare \&a[10] = one two three
-  minput 10 foo \fjoin(&a) bar
-
-   This declares an array of ten elements, and assigns values to the
-   first three of them. The MINPUT command looks for these three (as well
-   as the words "foo" and "bar"). Later, if you assign additional
-   elements to the array, the same MINPUT command also looks for the new
-   elements.
-
-   If an array element contains spaces, each word becomes a separate
-   target. To create one target per array element, use \fjoin()'s
-   grouping feature:
-
-  dcl \&a[] = {aaa bbb} {ccc ddd} {xxx yyy zzz}
-
-  minput 10 \fjoin(&a)     <-- 7 targets
-  minput 10 \fjoin(&a,,2)  <-- 3 targets
-
-   [ [455]Top ] [ [456]Contents ] [ [457]C-Kermit Home ] [ [458]Kermit
-   Home ]
-     _________________________________________________________________
-
-  8.11. Learned Scripts
-
-   C-Kermit now includes a simple script recorder that monitors your
-   commands, plus your actions during CONNECT mode, and automatically
-   generates a script program that mimics what it observed. You should
-   think of this feature as a script-writing ASSISTANT since, as you will
-   see [459]later in this section, the result generally needs some
-   editing to make it both secure and flexible. The script recorder is
-   controlled by the new LEARN command:
-
-   LEARN [ /ON /OFF /CLOSE ] [ filename ]
-          If you give a filename, the file is opened for subsequent
-          recording. The /ON switch enables recording to the current file
-          (if any); /OFF disables recording. /CLOSE closes the current
-          script recording file (if any). If you give a filename without
-          any switches, /ON is assumed.
-
-   The /OFF and /ON switches let you turn recording off and on during a
-   session without closing the file.
-
-   When recording:
-
-     * All commands that you type (or recall) at the prompt are recorded
-       in the file except:
-          + LEARN commands are not recorded.
-          + The CONNECT command is not recorded.
-          + The TELNET command is converted to SET HOST /NETWORK:TCP.
-     * Commands obtained from macros or command files are not recorded.
-     * During CONNECT:
-          + Every line you type is converted to an OUTPUT command.
-          + The last prompt before any line you type becomes an INPUT
-            command.
-          + Timeouts are calculated automatically for each INPUT command.
-          + A PAUSE command is inserted before each OUTPUT command just
-            to be safe.
-
-   Thus the script recorder is inherently line-oriented. It can't be used
-   to script character-oriented interactions like typing Space to a
-   "More?" prompt or editing a text file with VI or EMACS.
-
-   But it has advantages too; for example it takes control characters
-   into account that might not be visible to you otherwise, and it
-   automatically converts control characters in both the input and output
-   streams to the appropriate notation. It can tell, for example that the
-   "$ " prompt on the left margin in UNIX is really {\{13}\{10}$ },
-   whereas in VMS it might be {\{13}\{10}\{13}$ }. These sequences are
-   detected and recorded automatically.
-
-   A learned script should execute correctly when you give a TAKE command
-   for it. However, it is usually appropriate to edit the script a bit.
-   The most important change would be to remove any passwords from it.
-   For example, if the script contains:
-
-  INPUT 9 {\{13}\{10}Password: }
-  IF FAIL STOP 1 INPUT timeout
-  PAUSE 1
-  OUTPUT bigsecret\{13}
-
-   you should replace this by something like:
-
-  INPUT 9 {\{13}\{10}Password: }
-  IF FAIL STOP 1 INPUT timeout
-  ASKQ pswd Please type your password:
-  PAUSE 1
-  OUTPUT \m(pswd)\{13}
-
-   The LEARN command can't do this for you since it knows nothing about
-   "content"; it only knows about lines and can't be expected to parse or
-   understand them -- after all, the Password prompt might be in some
-   other language. So remember: if you use the LEARN command to record a
-   login script, be sure edit the resulting file to remove any passwords.
-   Also be sure to delete any backup copies your editor or OS might have
-   made of the file.
-
-   Other manual adjustments might also be appropriate:
-
-     * If the target of an INPUT command can vary, you can replace the
-       INPUT command with MINPUT and the appropriate target list, and/or
-       the target with a \fpattern(). For example, suppose you are
-       dialing a number that can be answered by any one of 100 terminal
-       servers, whose prompts are ts-00>, ts-01>, ts-02>, ... ts-99>. The
-       script records a particular one of these, but you want it to work
-       for all of them, so change (e.g.):
-  INPUT 10 ts-23>  ; or whatever
-       to:
-  INPUT 10 \fpattern(ts-[0-9][0-9]>)
-     * The INPUT timeout values are conservative, but they are based only
-       on a single observation; you might need to tune them.
-     * The PAUSE commands might not be necessary, or the PAUSE interval
-       might need adjustment.
-     * In case you made typographical errors during recording, they are
-       incorporated in your script; you can edit them out if you want to.
-
-   Here is a sample script generated by Kermit ("learn vms.ksc") in which
-   a Telnet connection is made to a VMS computer, the user logs in,
-   starts Kermit on VMS, sends it a file, and then logs out:
-
-  ; Scriptfile: vms.ksc
-  ; Directory:  /usr/olga
-  ; Recorded:   20001124 15:21:23
-
-  SET HOST /NETWORK:TCP vms.xyzcorp.com
-  IF FAIL STOP 1 Connection failed
-
-  INPUT 7 {\{13}\{10}\{13}Username: }
-  IF FAIL STOP 1 INPUT timeout
-  PAUSE 1
-  OUTPUT olga\{13}
-  INPUT 3 {\{13}\{10}\{13}Password: }
-  IF FAIL STOP 1 INPUT timeout
-  PAUSE 1
-  OUTPUT secret\{13}
-  INPUT 18 {\{13}\{10}\{13}$ }
-  IF FAIL STOP 1 INPUT timeout
-  PAUSE 1
-  OUTPUT set default [.incoming]\{13}
-  INPUT 12 {\{13}\{10}\{13}$ }
-  IF FAIL STOP 1 INPUT timeout
-  PAUSE 1
-  OUTPUT kermit\{13}
-  INPUT 15 {\{13}\{10}\{13}ALTO:[OLGA.INCOMING] C-Kermit>}
-  IF FAIL STOP 1 INPUT timeout
-  PAUSE 1
-  OUTPUT receive\{13}
-  send myfile.txt
-
-  INPUT 18 {\{13}\{10}\{13}ALTO:[OLGA.INCOMING] C-Kermit>}
-  IF FAIL STOP 1 INPUT timeout
-  PAUSE 1
-  OUTPUT exit\{13}
-  INPUT 6 {\{13}\{10}\{13}$ }
-  IF FAIL STOP 1 INPUT timeout
-  PAUSE 1
-  OUTPUT logout\{13}
-  close
-  exit
-
-   The commands generated by Kermit during CONNECT (INPUT, IF FAIL,
-   PAUSE, and OUTPUT) have uppercase keywords; the commands typed by the
-   user are in whatever form the user typed them (in this case,
-   lowercase).
-
-   [ [460]Top ] [ [461]Contents ] [ [462]C-Kermit Home ] [ [463]Kermit
-   Home ]
-     _________________________________________________________________
-
-  8.12. Pattern Matching
-
-   A pattern is a character string that is used to match other strings.
-   Patterns can contain metacharacters that represent special actions
-   like "match any single character", "match zero or more characters",
-   "match any single character from a list", and so on. The best known
-   application of patterns is in file specifications that contain
-   wildcards, as in "send *.txt", meaning "send all files whose names end
-   with .txt".
-
-   Patterns are also used in increasingly many other ways, to the extent
-   it is useful to point out certain important distinctions in the ways
-   in which they are used:
-
-   Anchored Patterns
-          If an anchored pattern does not begin with "*", it must match
-          the beginning of the string, and if it does not end with "*",
-          it must match the end of the string. For example, the anchored
-          pattern "abc" matches only the string "abc", not "abcde" or
-          "xyzabc" or "abcabc". The anchored pattern "abc*" matches any
-          string that starts with "abc"; the anchored pattern "*abc"
-          matches any string that ends with "abc"; the anchored pattern
-          "*abc*" matches any string that contains "abc" (including any
-          that start and/or end with it).
-
-   Floating Patterns
-          A floating pattern matches any string that contains a substring
-          that matches the pattern. In other words, a floating pattern
-          has an implied "*" at the beginning and end. You can anchor a
-          floating pattern to the beginning by starting it with "^", and
-          you can anchor it to the end by ending it with "$" (see
-          examples below).
-
-   Wildcards
-          A wildcard is an anchored pattern that has the additional
-          property that "*" does not match directory separators.
-
-   This terminology lets us describe Kermit's commands with a bit more
-   precision. When a pattern is used for matching filenames, it is a
-   wildcard, except in the TEXT-PATTERNS and BINARY-PATTERNS lists and
-   /EXCEPT: clauses, in which case directory separators are not
-   significant (for example, a BINARY-PATTERN of "*.exe" matches any file
-   whose name ends in .exe, no matter how deeply it might be buried in
-   subdirectories). When Kermit parses a file specification directly,
-   however, it uses the strict wildcard definition. For example, "send
-   a*b" sends all files whose names start with "a" and end with "b" in
-   the current directory, and not any files whose names end with "b" that
-   happen to be in subdirectories whose names start with "a". And as
-   noted, wildcards are anchored, so "delete foo" deletes the file named
-   "foo", and not all files whose names happen to contain "foo".
-
-   Most other patterns are anchored. For example:
-
-  if match abc bc ...
-
-   does not succeed (and you would be surprised if it did!). In fact, the
-   only floating patterns are the ones used by commands or functions that
-   search for patterns in files, arrays, or strings. These include:
-
-     * The GREP and TYPE /MATCH commands.
-     * The \fsearch(), \frsearch(), and \farraylook() functions.
-
-   Thus these are the only contexts in which explicit anchors ("^" and
-   "$") may be used:
-
-   grep abc *.txt
-          Prints all lines containing "abc" in all files whose names end
-          with ".txt".
-
-   grep ^abc *.txt
-          Prints all lines that start with "abc" in all ".txt" files.
-
-   grep abc$ *.txt
-          Prints all lines that end with "abc" in all ".txt" files.
-
-   grep ^a*z$ *.txt
-          Prints all lines that start with "a" and end with "z" in all
-          ".txt" files.
-
-   Similarly for TYPE /PAGE, /fsearch(), /frsearch(), and \farraylook().
-
-   Here is a brief summary of anchored and floating pattern equivalences:
-
-  Anchored   Floating
-    abc       ^abc$
-    *abc      abc$
-    abc*      ^abc
-    *abc*     abc
-
-   [ [464]Top ] [ [465]Contents ] [ [466]C-Kermit Home ] [ [467]Kermit
-   Home ]
-     _________________________________________________________________
-
-  8.13. Dates and Times
-
-   C-Kermit's comprehension of date-time formats is considerably expanded
-   in version 8.0. Any command that reads dates, including the DATE
-   command itself, or any switch, such as the /BEFORE: and /AFTER:
-   switches, or any function such as \fcvtdate(), now can understand
-   dates and times expressed in any ISO 8601 format, in Unix "asctime"
-   format, in FTP MDTM format, and in practically any format used in RFC
-   822 or RFC 2822 electronic mail, with or without timezones, and in a
-   great many other formats as well. HELP DATE briefly summarizes the
-   acceptable date-time formats.
-
-   Furthermore, C-Kermit 8.0 includes a new and easy-to-use form of
-   date-time arithmetic, in which any date or time can be combined with a
-   "delta time", to add or subtract the desired time interval (years,
-   months, weeks, days, hours, minutes, seconds) to/from the given date.
-   And new functions are available to compare dates and to compute their
-   differences.
-
-   As you can imagine, all this requires quite a bit of "syntax". The
-   basic format is:
-
-  [ date ] [ time ] [ delta ]
-
-   Each field is optional, but in most cases (depending on the context)
-   there must be at least one field. If a date is given, it must come
-   first. If no date is given, the current date is assumed. If no time is
-   given, an appropriate time is supplied depending on whether a date was
-   supplied. If no delta is given, no arithmetic is done. If a delta is
-   given without a date or time, the current date and time are used as
-   the base.
-
-   Date-time-delta fields are likely to contain spaces (although they
-   need not; space-free forms are always available). Therefore, in most
-   contexts -- and notably as switch arguments -- date-time information
-   must be enclosed in braces or doublequotes, for example:
-
-  send /after:"8-Aug-2001 12:00 UTC" *.txt
-
-   Kermit's standard internal format for dates and times is:
-
-  yyyymmdd hh:mm:ss
-
-   for example:
-
-  20010208 10:28:01
-
-   Date-times can always be given in this format. yyyy is the 4-digit
-   year, mm is the two-digit month (1-12; supply leading zero for
-   Jan-Sep), dd is the 2-digit day (leading zero for 1-9), hh is the hour
-   (0-23), mm the minute (0-59), ss the second (0-59), each with leading
-   zero if less than the field width. The date and time can be separated
-   by a space, an underscore, a colon, or the letter T. The time is in
-   24-hour format. Thus the various quantites are at the following fixed
-   positions:
-
-Position  Contents                    
-   1-4    Year   (4 digits, 0000-9999)
-   5-6    Month  (2 digits, 1-12)
-   7-8    Day    (2 digits, 1-31)
-   9      Date-Time Separator (space, :, _, or the letter T)
-  10-11   Hour   (2 digits, 0-23)
-  12      Hour-Minute Separator (colon)
-  13-14   Minute (2 digits, 0-59)
-  15      Minute-Second Separator (colon)
-  16-17   Second (2 digits, 0-59)
-
-   Example:
-
-  19800526 13:07:12  26 May 1980, 13:07:12 (1:07:12PM)
-
-   This is the format produced by the DATE command and by any function
-   that returns a date-time. It is suitable for lexical comparison and
-   sorting, and for use as a date-time in any Kermit command. When this
-   format is given as input to a command or function, various date-time
-   separators (as noted) are accepted:
-
-  19800526 13:07:12  26 May 1980, 13:07:12 (1:07:12PM)
-  20010208_10:28:35  2 February 2001, 10:28:35 AM
-  18580101:12:00:00  1 January 1858, noon
-  20110208T00:00:00  2 February 2011, midnight
-
-   Certain other special date-time formats that are encountered on
-   computer networks are recognized:
-
-   Asctime Format
-          This is a fixed format used by Unix, named after Unix's
-          asctime() ("ASCII time") function. It is always exactly 24
-          characters long. Example: Fri Aug 10 16:38:01 2001
-
-   Asctime with Timezone
-          This is like Asctime format, but includes a 3-character
-          timezone between the time and year. It is exactly 28 characters
-          long. Example: Fri Aug 10 16:38:01 GMT 2001
-
-   E-Mail Format
-          E-mail date-time formats are defined in [468]RFC 2822 with a
-          fair amount of flexibility and options. The following examples
-          are typical of e-mails and HTTP (web-page) headers:
-
-  Sat, 14 Jul 2001 11:49:29                (No timezone)
-  Fri, 24 Mar 2000 14:19:59 EST            (Symbolic timezone)
-  Tue, 26 Jun 2001 10:19:45 -0400 (EDT)    (GMT Offset + comment)
-
-   FTP MDTM Format
-          This is the date-time format supplied by FTP servers that
-          support the (not yet standard but widely used nevertheless)
-          MDTM command, by which the FTP client asks for a file's
-          modification time:
-
-  yyyymmddhhmmss[.ffff]
-
-          where yyyy is the 4-digit year, mm is the 2-digit month, and so
-          on, exactly 14 digits long. An optional fractional part
-          (fraction of second) may also be included, separated by a
-          decimal point (period). Kermit rounds to the nearest second.
-          Example:
-
-  20020208102835.515                       (8 February 2002 10:28:36 AM)
-
-    8.13.1. The Date
-
-   The date, if given, must precede the time and/or delta, and can be in
-   many, many formats. For starters, you can use several symbolic date
-   names in place of actual dates:
-
-   NOW
-          This is replaced by the current date and time. The time can not
-          be overriden (if you want to supply a specific time, use TODAY
-          rather than NOW).
-
-   TODAY
-          This is replaced by the current date and a default time of
-          00:00:00 is supplied, but can be overridden by a specific time;
-          for example, if today is 8 February 2002, then "TODAY" is
-          "20020802 00:00:00" but "TODAY 10:28" is "20020802 10:28:00".
-
-   TOMORROW
-          Like TODAY, but one day later (if today is 8 February 2002,
-          then "TOMORROW" is "20020803 00:00:00" but "TOMORROW 16:30" is
-          "20020803 16:30:00").
-
-   YESTERDAY
-          Like TODAY, but one day earlier.
-
-   MONDAY, TUESDAY, WEDNESDAY, ..., SUNDAY
-          The date on the given day of the week, today or later. A
-          default time of 00:00:00 is supplied but can be overridden.
-          Example: "SATURDAY 12:00" means next Saturday (or today, if
-          today is Saturday) at noon.
-
-   You can give an explicit date in almost any conceivable format, but
-   there are some rules:
-
-     * If a date is given, it must have three fields: day, month, and
-       year; the order can vary (except that the month can not be last).
-     * If names are used for days, months, etc, they must be English.
-     * The year must lie between 0000 and 9999, inclusive.
-     * All calendar calculations use Gregorian dating, so calculated
-       dates for years prior to 1582 (or later, depending on the country)
-       will not agree with historical dates. Other forms of dating (e.g.
-       Hebrew, Chinese) are not supported.
-
-   Various date-field separators are accepted: hyphen, slash, space,
-   underscore, period. The same field separator (if any) must be used in
-   both places; for example 18-Sep-2001 but not 18-Sep/2001. Months can
-   be numeric (1-12) or English names or abbreviations. Month name
-   abbreviations are normally three letters, e.g. Apr, May, Jun, Jul.
-   Capitalization doesn't matter.
-
-   Here are a few examples:
-
-  18 Sep 2001                              (English month, abbreviated)
-  18 September 2001                        (English month, spelled out)
-  2001 Sept 18                             (Year, month, day)
-  18-Sep-2001                              (With hyphens)
-  18/09/2001                               (All numeric with slashes)
-  18.09.2001                               (Ditto, with periods)
-  18_09_2001                               (Ditto, with underscores)
-  09/18/2001                               (See below)
-  2001/09/18                               (See below)
-  September 18, 2001                       (Correspondence style)
-  Sep-18-2001                              (Month-day-year)
-  20010918                                 (Numeric, no separators)
-
-   You can also include the day of the week with a specific date, in
-   which case it is accepted (if it is a valid day name), but not
-   verified to agree with the given date:
-
-  Tue, 18 Sep 2001                         (Abbreviated, with comma)
-  Tue,18 Sep 2001                          (Comma but no space)
-  Tue 18 Sep 2001                          (Abbreviated, no comma)
-  Tuesday 18 Sep 2001                      (Spelled out)
-  Tuesday, 18 Sep 2001                     (etc)
-  Friday, 18 Sep 2001                      (Accepted even if not Friday)
-
-   In all-numeric dates with the year last, such as 18/09/2001, Kermit
-   identifies the year because it's 4 digits, then decides which of the
-   other two numbers is the month or day based on its value. If both are
-   12 or less and are unequal, the date is ambiguous and is rejected. In
-   all-numeric dates with the year first, the second field is always the
-   month and the third is the day. The month never comes last. A date
-   with no separators is accepted only if it is all numeric and has
-   exactly eight digits, and is assumed to be in yyyymmdd format.
-
-  20010918                                 (18-Sep-2001 00:00:00)
-
-   or 14 digits (as in FTP MDTM format):
-
-  20010918123456                           (18-Sep-2001 12:34:56)
-
-   You can always avoid ambiguity by putting the year first, or by using
-   an English, rather than numeric, month. A date such as 09/08/2001
-   would be ambiguous but 2001/09/08 is not, nor is 09-Aug-2001.
-
-   Until the late 1990s, it was common to encounter 2-digit years, and
-   these are found to this day in old e-mails and other documents. Kermit
-   accepts these dates if they have English months, and interprets them
-   according to the windowing rules of [469]RFC 2822: "If a two digit
-   year is encountered whose value is between 00 and 49, the year is
-   interpreted by adding 2000, ending up with a value between 2000 and
-   2049. If a two digit year is encountered with a value between 50 and
-   99, or any three digit year is encountered, the year is interpreted by
-   adding 1900."
-
-   If you need to specify a year prior to 1000, use leading zeros to
-   ensure it is not misinterpreted as a "non-Y2K-compliant" modern year:
-
-  7-Oct-77                                 (19771007 00:00:00)
-  7-Oct-0077                               (00771007 00:00:00)
-
-    8.13.2. The Time
-
-   The basic time format is hh:mm:dd; that is hours, minutes, seconds,
-   separated by colons, perhaps with an optional fractional second
-   separated by a decimal point (period). The hours are in 24-hour
-   format; 12 is noon, 13 is 1pm, and so on. Fields omitted from the
-   right default to zero. Fields can be omitted from the left or middle
-   by including the field's terminating colon. Examples:
-
-  11:59:59                                 (11:59:59 AM)
-  11:59                                    (11:59:00 AM)
-  11                                       (11:00:00 AM)
-  11:59:59.33                              (11:59:59 AM)
-  11:59:59.66                              (Noon)
-  03:21:00                                 (3:21:00 AM)
-  3:21:00                                  (3:21:00 AM)
-  15:21:00                                 (3:21:00 PM)
-  :21:00                                   (00:21:00 AM)
-  ::01                                     (00:00:01 AM)
-  11::59                                   (11:00:59 AM)
-
-   Leading zeros can be omitted, but it is customary and more readable to
-   keep them in the minute and second fields:
-
-  03:02:01                                 (03:02:01 AM)
-  3:02:01                                  (03:02:01 AM)
-  3:2:1                                    (03:02:01 AM)
-
-   AM/PM notation is accepted if you wish to use it:
-
-  11:59:59                                 (11:59:59 AM)
-  11:59:59AM                               (11:59:59 AM)
-  11:59:59A.M.                             (11:59:59 AM)
-  11:59:59am                               (11:59:59 AM)
-  11:59:59a.m.                             (11:59:59 AM)
-  11:59:59PM                               (11:59:59 PM = 23:59:59)
-  11:59:59P.M.                             (11:59:59 PM = 23:59:59)
-  11:59:59pm                               (11:59:59 PM = 23:59:59)
-  11:59:59p.m.                             (11:59:59 PM = 23:59:59)
-
-   You can omit the colons if you wish, in which case Kermit uses the
-   following rules to interpret the time:
-
-    1. 6 digits is hh:mm:ss, e.g. 123456 is 12:34:56.
-    2. 5 digits is h:mm:ss, e.g. 12345 is 1:23:45.
-    3. 4 digits is hh:mm, e.g. 1234 is 12:34.
-    4. 3 digits is h:mm, e.g. 123 is 1:23.
-    5. 2 digits is hh, e.g. 12 is 12:00.
-    6. 1 digit is h (the hour), e.g. 1 is 1:00.
-
-   Examples:
-
-  1                                        (01:00:00 AM)
-  10                                       (10:00:00 AM)
-  230                                      (02:30:00 AM)
-  230pm                                    (02:30:00 PM = 14:30:00)
-  1115                                     (11:15:00 AM)
-  2315                                     (11:15:00 PM = 23:15:00 PM)
-  23150                                    (02:31:50 AM)
-  231500                                   (23:15:00 PM)
-
-    8.13.3. Time Zones
-
-   If a time is given, it can (but need not) be followed by a time zone
-   designator. If no time zone is included, the time is treated as local
-   time and no timezone conversions are performed.
-
-   The preferred time zone designator is the UTC Offset, as specified in
-   [470]RFC 2822: a plus sign or minus sign immediately followed by
-   exactly four decimal digits, signifying the difference in hh (hours)
-   and mm (minutes) from Universal Coordinated Time (UTC, also known as
-   Greenwich Mean Time, or GMT), with negative numbers to the West and
-   positive numbers to the East. For example:
-
-  Fri, 13 Jul 2001 12:54:29 -0700
-
-   indicates a local time of 12:54:29 that is 07 hours and 00 minutes
-   behind (less than, East of) Universal Time. The space is optional, so
-   the example could also be written as:
-
-  Fri, 13 Jul 2001 12:54:29-0700
-
-   The following symbolic time zones are also accepted, as specified by
-   [471]RFC 2822 and/or in ISO 8601:
-
-  GMT  =  +0000       Greenwich Mean Time
-  Z    =  +0000       Zulu (Zero Meridian) Time
-  UTC  =  +0000       Universal Coordinated Time
-  UT   =  +0000       Universal Time
-  EDT  =  -0400       Eastern (USA) Daylight Time
-  EST  =  -0500       Eastern (USA) Standard Time
-  CDT  =  -0500       Central (USA) Daylight Time
-  CST  =  -0600       Central (USA) Standard Time
-  MDT  =  -0600       Mountain (USA) Daylight Time
-  MST  =  -0700       Mountain (USA) Standard Time
-  PDT  =  -0700       Pacific (USA) Daylight Time
-  PST  =  -0800       Pacific (USA) Standard Time
-
-   Note that GMT, Z, UTC, and UT all express the same concept: standard
-   (not daylight) time at the Zero Meridian. UTC, by the way, is an
-   international standard symbol and does not correspond to the order of
-   the English words, Universal Coordinated Time, but it happens to have
-   the same initial letters as these words. Of course hundreds of other
-   symbolic timezones and variations exist, but they are not
-   standardized, and are therefore not supported by Kermit.
-
-   When a time zone is included with a time, the time is converted to
-   local time. In case the conversion crosses a midnight boundary, the
-   date is adjusted accordingly. Examples converting to EST (Eastern USA
-   Standard Time = -0500):
-
- 11:30:00      =  11:30:00
- 11:30:00 EST  =  11:30:00
- 11:30:00 GMT  =  06:30:00
- 11:30:00 PST  =  14:30:00
- 11:30:00Z     =  06:30:00
- 11:30PM GMT   =  18:30:00
- 11:30 -0500   =  11:30:00
- 11:30 -0800   =  08:30:00
- 11:30 +0200   =  04:30:00
-
-   Unlike most of Kermit's other date-time conversions, timezone
-   knowledge (specifically, the offset of local time from UTC) is
-   embodied in the underlying operating system, not in Kermit itself, and
-   any conversion errors in this department are the fault of the OS. For
-   example, most UNIX platforms do not perform conversions for years
-   prior to 1970.
-
-    8.13.4. Delta Time
-
-   Date/time expressions can be composed of a date and/or time and a
-   delta time, or a delta time by itself. When a delta time is given by
-   itself, it is relative to the current local date and time. Delta times
-   have the following general format:
-
-  {+,-}[number units][hh[:mm[:ss]]]
-
-   In other words, a delta time always starts with a plus or minus sign,
-   which is followed by a "part1", a "part2", or both. The "part1", if
-   given, specifies a number of days, weeks, months, or years; "part2"
-   specifies a time in hh:mm:ss notation. In arithmetic terms, these
-   represents some number of days or other big time units, and then a
-   fraction of a day expressed as hours, minutes, and seconds; these are
-   to be added to or subtracted from the given (or implied) date and
-   time. The syntax is somewhat flexible, as shown by the following
-   examples:
-
-  +1 day                (Plus one day)
-  +1day                 (Ditto)
-  +1d                   (Ditto)
-  + 1 day               (Ditto)
-  + 1 day 3:00          (Plus one day and 3 hours)
-  +1d3:00               (Ditto)
-  +1d3                  (Ditto)
-  +3:00:00              (Plus 3 hours)
-  +3:00                 (Ditto)
-  +3                    (Ditto)
-  +2 days               (Plus 2 days)
-  -12 days 7:14:22      (Minus 12 days, 7 hours, 14 minutes, and 22 seconds)
-
-   The words "week", "month", and "year" can be used like "day" in the
-   examples above. A week is exactly equivalent to 7 days. When months
-   are specified, the numeric month number of the date is incremented or
-   decremented by the given number, and the year and day adjusted
-   accordingly if necessary (for example, 31-Jan-2001 +1month =
-   03-Mar-2001 because February does not have 31 days). When years are
-   specified, they are added or subtracted to the base year. Examples
-   (assuming the current date is 10-Aug-2001 and the current time is
-   19:21:11):
-
-  18-Sep-2001 +1day              (20010918 00:00:00)
-  today +1day                    (20010811 00:00:00)
-  now+1d                         (20010811 19:21:11)
-  + 1 day                        (20010811 19:21:11)
-  + 1 day 3:14:42                (20010811 22:35:54)
-  + 7 weeks                      (20010928 19:21:11)
-  +1d3:14:42                     (20010811 22:35:54)
-  +1w3:14:42                     (20010817 22:35:54)
-  +1m3:14:42                     (20010910 22:35:54)
-  +1y3:14:42                     (20020810 22:35:54)
-  2 feb 2001 + 10 years          (20110208 00:00:00)
-  2001-02-08 +10y12              (20110208 12:00:00)
-  31-dec-1999 23:59:59+00:00:01  (20000101 00:00:00)
-  28-feb-1996 +1day              (19960229 00:00:00) (leap year)
-  28-feb-1997 +1day              (19970301 00:00:00) (nonleap year)
-  28-feb-1997 +1month            (19970328 00:00:00)
-  28-feb-1997 +1month 11:59:59   (19970328 11:59:59)
-  28-feb-1997 +20years           (20170228 00:00:00)
-  28-feb-1997 +8000years         (99970228 00:00:00)
-
-   For compatibility with VMS, the following special delta-time format is
-   also accepted:
-
-  +number-hh:mm:ss
-  -number-hh:mm:ss
-
-   (no spaces). The hyphen after the number indicates days. It
-   corresponds exactly to the Kermit notation:
-
-  +numberdhh:mm:ss
-  -numberdhh:mm:ss
-
-   The following forms all indicate exactly the same date and time:
-
-  18-Sep-2001 12:34:56 +1-3:23:01
-  18-Sep-2001 12:34:56 +1d3:23:01
-  18-Sep-2001 12:34:56 +1 day 3:23:01
-
-   and mean "add a day plus 3 hours, 23 minutes, and 1 second" to the
-   given date.
-
-   Note that delta times are not at all the same as UTC offsets; the
-   former specifies an adjustment to the given date/time and the latter
-   specifies that the local time is a particular distance from Universal
-   Time, for example:
-
-  11-Aug-2001 12:34:56 -0800          (20010811 16:34:56 -- UTC Offset)
-  11-Aug-2001 12:34:56 -08:00         (20010811 04:34:56 -- Delta time)
-
-   If you give a time followed by a modifer that starts with a + or -
-   sign, how does Kermit know whether it's a UTC offset or a delta time?
-   It is treated as a UTC offset if the sign is followed by exactly four
-   decimal digits; otherwise it is a delta time. Examples (for USA
-   Eastern Daylight Time):
-
-  11-Aug-2001 12:34:56 -0800          (20010811 16:34:56 -- UTC Offset)
-  11-Aug-2001 12:34:56 -08:00         (20010811 04:34:56 -- Delta time)
-  11-Aug-2001 12:34:56 -800           (20010811 04:34:56 -- Delta time)
-  11-Aug-2001 12:34:56 -8             (20010811 04:34:56 -- Delta time)
-
-   The first example says that at some unknown place which is 8 hours
-   ahead of Universal Time, the time is 12:34:56, and this corresponds to
-   16:34:56 in Eastern Daylight time. The second example says to subtract
-   8 hours from the local time. The third and fourth are delta times
-   because, even though a colon is not included, the time does not
-   consist of exactly 4 digits.
-
-   When a delta time is written after a timezone, however, there is no
-   ambiguity and no syntax distinction is required:
-
-  11-Aug-2001 12:34:56 -0800 -0800    (20010811 08:34:56)
-  11-Aug-2001 12:34:56 -0800 -08:00   (Ditto)
-  11-Aug-2001 12:34:56 -08:00 -08:00  (Illegal)
-
-    8.13.5. The DATE Command
-
-   Obviously a great many combinations of date, time, time zone, and
-   delta time are possible, as well as many formatting options. The
-   purpose of all this flexibility is to comply with as many standards as
-   possible -- Internet RFCs, ISO standards, and proven corporate
-   standards -- as well as with notations commonly used by real people,
-   in order that dates and times from the widest variety of sources can
-   be assigned to a variable and used in any date-time field in any
-   Kermit command.
-
-   You can test any date-and/or-time format with the DATE command, which
-   converts it to standard yyyymmdd hh:mm:ss format if it is understood,
-   or else gives an explicit error message (rather than just "BAD DATE"
-   as in previous C-Kermit releases) to indicate what is wrong with it.
-   Examples (on Tuesday, 31 July 2001 in New York City, Eastern Daylight
-   Time, UTC -0400):
-
-  DATE command argument                   Result           
-  12:30                                   20010731 12:30:00
-  12:30:01                                20010731 12:30:01
-  12:30:01.5                              20010731 12:30:02
-  1230                                    20010731 12:30:00
-  230                                     20010731 02:30:00
-  230+1d                                  20010801 02:30:00
-  230+1d3:00                              20010801 05:30:00
-  20010718 19:21:15                       20010718 19:21:15
-  20010718_192115                         20010718 19:21:15
-  20010718T192115                         20010718 19:21:15
-  18 Jul 2001 +0400                       20010717 23:59:59
-  18 Jul 2001 192115                      20010718 19:21:15
-  18 Jul 2001 192115.8                    20010718 19:21:16
-  18-Jul-2001T1921                        20010718 19:21:00
-  18-Jul-2001 1921Z                       20010718 15:21:00
-  18-Jul-2001 1921 GMT                    20010718 15:21:00
-  18-Jul-2001 1921 UTC                    20010718 15:21:00
-  18-Jul-2001 1921 Z                      20010718 15:21:00
-  18-Jul-2001 1921Z                       20010718 15:21:00
-  18-Jul-2001 1921 -04:00:00              20010718 19:21:00
-  21-Jul-2001_08:20:00am                  20010721 08:20:00
-  21-Jul-2001_8:20:00P.M.                 20010721 20:20:00
-  Fri Jul 20 11:26:25 2001                20010720 11:26:25
-  Fri Jul 20 11:26:25 GMT 2001            20010720 07:26:25
-  Sun, 9 Apr 2000 06:46:46 +0100          20000409 01:46:46
-  Sunday, 9 Apr 2000 06:46:46 +0100       20000409 01:46:46
-  now                                     20010731 19:41:12
-  today                                   20010731 00:00:00
-  today 09:00                             20010731 09:00:00
-  tomorrow                                20010801 00:00:00
-  tomorrow 09:00                          20010801 09:00:00
-  tomorrow 09:00 GMT                      20010801 05:00:00
-  yesterday                               20010730 00:00:00
-  yesterday 09:00                         20010730 09:00:00
-  + 3 days                                20010803 00:00:00
-  +3 days                                 20010803 00:00:00
-  +3days                                  20010803 00:00:00
-  + 3days                                 20010803 00:00:00
-  + 3 days 09:00                          20010803 09:00:00
-  + 2 weeks                               20010814 00:00:00
-  + 1 month                               20010831 00:00:00
-  - 7 months                              20001231 00:00:00
-  + 10 years                              20110731 00:00:00
-  friday                                  20010803 00:00:00
-  saturday                                20010804 00:00:00
-  sunday                                  20010805 00:00:00
-  monday                                  20010806 00:00:00
-  tuesday                                 20010731 00:00:00
-  wednesday                               20010801 00:00:00
-  thursday                                20010802 00:00:00
-  friday 07:00                            20010803 07:00:00
-  thursday 1:00pm                         20010802 13:00:00
-  thursday 1:00pm GMT                     20010802 09:00:00
-  Thu, 10 Nov 94 10:50:47 EST             19941110 10:50:47
-  Fri, 20 Oct 1995 18:35:15 -0400 (EDT)   19951020 18:35:15
-  31/12/2001                              20011231 00:00:00
-  12/31/2001                              20011231 00:00:00
-  2001-July-20                            20010720 00:00:00
-  2001-September-30                       20010930 00:00:00
-  30-September-2001                       20010930 00:00:00
-  Sep 30, 2001 12:34:56                   20010930 12:34:56
-  September 30, 2001                      20010930 00:00:00
-  September 30, 2001 630                  20010930 06:30:00
-  September 30 2001 630                   20010930 06:30:00
-  Sep-30-2001 12:34:59                    20010930 12:34:59
-  20010807113542.014                      20010807 11:35.42
-  20010807113542.014Z                     20010807 07:35:42
-
-    8.13.6. New Date-Time Functions
-
-   In the following descriptions, date-time function arguments are the
-   same free-format date-time strings discussed above, with the same
-   defaults for missing fields. They are automatically converted to
-   standard format internally prior to processing.
-
-   \fcvtdate(d1)
-          Converts the date-time d1 to standard format and local time.
-          This function is not new, but now it accepts a wider range of
-          argument formats that can include timezones and/or delta times.
-          If the first argument is omitted, the current date and time are
-          assumed. The optional second argument is a format code for the
-          result:
-
-     n1 = 1: yyyy-mmm-dd hh:mm:ss (mmm = English 3-letter month
-     abbreviation)
-     n1 = 2: dd-mmm-yyyy hh:mm:ss (ditto)
-     n1 = 3: yyyymmddhhmmss (all numeric)
-
-   \futcdate(d1)
-          Converts the date-time d1 to Universal Coordinated Time (UTC),
-          also known as GMT or Zulu or Zero-Meridian time. The default d1
-          is NOW. If d1 is a valid date-time, the UTC result is returned
-          in standard format, yyyymmdd hh:ss:mm.
-
-   \fcmpdates(d1,d2)
-          Compares two free-format date-times, d1 and d2, and, if both
-          arguments are valid, returns a number: -1 if d1 is earlier than
-          (before) d2; 0 if d1 is the same as d2; 1 if d1 is later than
-          (after) d2.
-
-   \fdiffdates(d1,d2)
-          Computes the difference between two free-format date-times, d1
-          and d2. If both arguments are valid, returns a delta time which
-          is negative if d1 is earlier than (before) d2 and positive
-          otherwise. If d1 and d2 are equal, the result is "+0:00".
-          Otherwise, the result consists of the number of days, hours,
-          minutes, and seconds that separate the two date-times. If the
-          number of days is zero, it is omitted. If the number of days is
-          nonzero but the hours, minutes, and seconds are all zero, the
-          time is omitted. if the seconds are zero, they are omitted.
-
-   \fdelta2secs(dt)
-          Converts a delta time to seconds. For example, "+1d00:00:01" to
-          86401. Valid delta times must start with a + or - sign. Days
-          are accepted as time units, but not years, months, or weeks. If
-          the result would overflow a computer long word (as would happen
-          with 32-bit long words when the number of days is greater than
-          24854), the function fails.
-
-   HINT: Although Kermit has a number of built-in date and time
-   variables, it doesn't have a single one suitable for writing a
-   timestamp. For this you would normally use something like "\v(ndate)
-   \v(time)". But \fcvtdate() (with no arguments) is equivalent: it
-   returns the current date and time in yyyymmdd hh:mm:ss format,
-   suitable for time stamping.
-
-    8.13.7. Date-Time Programming Examples
-
-   Here's a macro that converts any date-time to UTC, which you might use
-   if C-Kermit didn't already have a \futcdate() function:
-
-  define utcdate {
-      .local := \fcvtdate(\%*)                 ; 1.
-      .tmp := \fcvtdate(\m(local)UTC)          ; 2.
-      .offset := \fdiffdate(\m(local),\m(tmp)) ; 3.
-      .utc := \fcvtdate(\m(local)\m(offset))   ; 4.
-      sho mac utc                              ; 5.
-  }
-
-   Brief explanation: Line 1 converts the macro argument, a free-format
-   date-time, to standard-format local time. Line 2 appends the "UTC"
-   timezone to the local time and converts the result to local time. In
-   other words, we take the same time as the local time, but pretend it's
-   UTC time, and convert it to local time. For example, if New York time
-   is 4 hours ahead of UTC, then 6:00pm New York time is 2:00pm UTC. Line
-   3 gets the difference of the two results (e.g. "+04:00"). Line 4
-   appends the difference (delta time) to the local time, and converts it
-   again, which adds (or subtracts) the UTC offset to the given time.
-   Line 5 displays the result.
-
-   Here's a script that opens a web page, gets its headers into an array,
-   scans the array for the "Last-Modified:" header, and inteprets it:
-  http open www.columbia.edu
-  if fail stop 1 HTTP OPEN failed
-  http /array:a head index.html /dev/null
-  if fail stop 1 HTTP GET failed
-  show array a
-  for \%i 1 \fdim(&a) 1 {
-      .\%x := \findex(:,\&a[\%i])
-      if not \%x continue
-      .tag := \fleft(\&a[\%i],\%x-1)
-      .val := \fltrim(\fsubstr(\&a[\%i],\%x+1))
-      if ( eq "\m(tag)" "Last-Modified" ) {
-          echo HTTP Date: \m(val)
-          .rdate := \fcvtdate(\m(val))
-          echo {Standard Date (local): \m(rdate)}
-          echo {Standard Date (UTC):   \futcdate(\m(rdate))}
-          break
-      }
-  }
-  http close
-
-   The result:
-
-  HTTP Date: Mon, 13 Aug 2001 20:05:42 GMT
-  Standard Date (local): 20010813 16:05:42
-  Standard Date (UTC):   20010813 20:05:42
-
-   As you can see, Kermit had no trouble decoding the date-time-string
-   from the website, converting to local time, and converting back to UTC
-   with no conflicts or loss of information. If it had been in any other
-   known format, the result would have been the same.
-
-   Now suppose we want to download the web page only if it is newer than
-   our local copy. The \fdate(filename) function (which returns the
-   modification date-time of the given file) and the new \fcmpdates()
-   function make it easy. Insert the following just before the BREAK
-   statement:
-
-  if ( < 0 \fcmpdates(\m(rdate),\fdate(index.html)) ) {
-     echo GETTING index.html...
-     http get index.html index.html
-     if success echo HTTP GET OK
-  } else {
-     echo index.html: no update needed
-  }
-  http close
-  exit
-
-   This says, "if 0 is less than the comparison of the remote file date
-   and the local file date, get the remote file, otherwise skip it." And
-   it automatically reconciles the time-zone difference (if any).
-
-   It would be nice to be able to extend this script into a
-   general-purpose website updater, but unfortunately HTTP protocol
-   doesn't provide any mechanism for the client to ask the server for a
-   list of files, recursive or otherwise.
-
-   [ [472]Top ] [ [473]Contents ] [ [474]C-Kermit Home ] [ [475]Kermit
-   Home ]
-     _________________________________________________________________
-
-  8.14. Trapping Keyboard Interruption
-
-   Normally when you type Ctrl-C and Kermit is in command mode (as
-   opposed to CONNECT mode) with COMMAND INTERRUPTION ON (as it is unless
-   you have set it OFF), Kermit interrupts any command that is currently
-   in progress, and if a command file or macro is executing, rolls the
-   command stack back to top level, closing all open command files,
-   deactivating all macros, deallocating all local variables and arrays,
-   and leaving you at the command prompt.
-
-   Suppose, however, you want certain actions to occur when a script is
-   interrupted; for example, closing open files, writing log entries, or
-   displaying summary results. You can do this by defining a macro named
-   ON_CTRLC. When Ctrl-C is detected, and a macro with this name is
-   defined, Kermit executes it from the current command level, thus
-   giving it full access to the environment in which the interruption
-   occurred, including local variables and open files. Only when the
-   ON_CTRLC macro completes execution is the command stack rolled back to
-   top level.
-
-   Once the ON_CTRLC macro is defined, it can be executed only once. This
-   is to prevent recursion if the user types Ctrl-C while the ON_CTRLC
-   macro is executing. If you type Ctrl-C while the Ctrl-C macro is
-   active, this does not start a new copy of ON_CTRLC; rather, it returns
-   to the top-level command prompt. After the ON_CTRLC macro returns, it
-   has been removed from the macro table so if you want to use it again
-   or install a different Ctrl-C trap, you must execute a new DEFINE
-   ON_CTRLC command. In any case, as always when you interrupt a script
-   with Ctrl-C, its completion status is FAILURE.
-
-   Normally the ON_CTRLC macro would be defined in the command file or
-   macro to which it applies, and should be declared LOCAL. This way, if
-   the command file or macro completes successfully without being
-   interrupted, the ON_CTRLC definition disappears automatically.
-   Otherwise the definition would still be valid and the macro would be
-   executed, probably out of context, the next time you typed Ctrl-C.
-
-   Here's a simple example of a command file that sets a Ctrl-C trap for
-   itself:
-
-  local on_ctrlc              ; Make Ctrl-C trap local to this command file.
-  define on_ctrlc {           ; Define the ON_CTRLC macro.
-      echo Interrupted at \v(time).
-      echo Iterations: \%n
-  }
-  xecho Type Ctrl-C to quit
-  for \%n 1 999 1 {           ; Prints a dot every second until interrupted.
-      sleep 1
-      xecho .
-  }
-  echo Finished normally at \v(time) ; Get here only if not interrupted.
-  decrement \%n
-  echo Iterations: \%n
-
-   This prints a summary no matter whether it completes normally or is
-   interrupted from the keyboard. In both cases the trap is automatically
-   removed afterwards.
-
-   For an example of how to use ON_CTRLC to debug scripts, see
-   [476]Section 8.1.
-
-   [ [477]Top ] [ [478]Contents ] [ [479]C-Kermit Home ] [ [480]Kermit
-   Home ]
-  __________________________________________________________________________
-
-9. S-EXPRESSIONS
-
-   This section is primarily for those who want to write
-   calculation-intensive scripts, especially if they require
-   floating-point arithmetic, and/or for those who are familiar with the
-   LISP programming language.
-
-   Ever since C-Kermit version 5 was released in 1988, scripting has been
-   one of its major attractions, and arithmetic is a key part of it.
-   Versions 5 and 6 included integer arithmetic only, using traditional
-   algebraic notation, e.g.:
-
-  echo \fevaluate(3*(2+7)/2)
-  13
-
-   C-Kermit 7.0 added support for floating-point arithmetic, but only
-   through function calls:
-
-  echo \ffpdivide(\ffpmultiply(3.0,\ffpadd(2.0,7.0)),2.0)
-  13.5
-
-   C-Kermit 8.0 introduces a third form of arithmetic that treats
-   integers and floating-point numbers uniformly, is easier to read and
-   write, and executes very quickly:
-
-  (/ (* 3 (+ 2 7)) 2)
-  13.5
-
-   But first some background.
-
-   The Kermit command and scripting language differs from true
-   programming languages (such as C or Fortran) in many ways; one of the
-   most prominent differences is the way in which variables are
-   distinguished from constants. In a command language, words are taken
-   literally; for example, the Unix shell:
-
-  cat foo.bar
-
-   displays the file named foo.bar. Whereas in a programming language
-   like C, words are assumed to be variables:
-
-  s = foo.bar;    /* Assigns the value of foo.bar to the variable s */
-
-   To make a programming language take words literally, you have to quote
-   or "escape" them:
-
-  s = "foo.bar";  /* Assigns a pointer to the string "foo.bar" to the variable
-s */
-
-   The opposite holds for command languages: to get them to treat a word
-   as a variable rather than a constant, you have to escape them. For
-   example, in the Unix shell:
-
-  foo=123         ; Assign value 123 to variable foo.
-  echo foo        ; Prints "foo"
-  echo $foo       ; Prints "123"
-
-   And in Kermit:
-
-  define foo 123  ; Assign value 123 to variable foo.
-  echo 123        ; This prints "123".
-  echo foo        ; This prints "foo".
-  echo \m(foo)    ; This prints "123".
-
-   In other words, character strings (such as "foo" above) are
-   interpreted as literal strings, rather than variable names, except in
-   special commands like DEFINE that deal specifically with variable
-   names (or in numeric contexts as explained in [481]Section 8.2). The
-   special "escape" character (dollar sign ($) for the shell, backslash
-   (\) for Kermit) indicates that a variable is to be replaced by its
-   value.
-
-   The requirement to escape variable names in command languages normally
-   does not impose any special hardship, but can add a considerable
-   notational burden to arithmetic expressions, which are typically full
-   of variables. Especially in Kermit when floating point numbers are
-   involved, where you must use special \ffpxxx() functions, e.g.
-   "\ffpadd(\m(a),\m(b))" rather than the simple "+" operator to add two
-   floating-point numbers together, because the original arithmetic
-   handler doesn't support floating point (this might change in the
-   future). To illustrate, the general formula for the area of a triangle
-   is:
-
-  sqrt(s * (s - a) * (s - b) * (s - c))
-
-   where a, b, and c are the lengths of the triangle's three sides and:
-
-  s = (a + b + c) / 2
-
-   Except in special cases (e.g. a = 3, b = 4, c = 5), the result has a
-   fractional part so the computation must be done using floating-point
-   arithmetic. We can create a Kermit 7.0 function for this as follows:
-
-  def area {
-      local s t1 t2 t3
-      assign s \ffpdiv(\ffpadd(\ffpadd(\%1,\%2),\%3),2.0)
-      assign t1 \ffpsub(\m(s),\%1)
-      assign t2 \ffpsub(\m(s),\%2)
-      assign t3 \ffpsub(\m(s),\%3)
-      return \ffpsqrt(\ffpmul(\m(s),\ffpmul(\m(t1),\ffpmul(\m(t2),\m(t3)))))
-  }
-
-   But as you can see, this is rather cumbersome. Note, in particular,
-   that arithmetic functions like \ffpadd(), \ffpmul(), etc, take exactly
-   two operands (like their symbolic counterparts + and *), so obtaining
-   the product of three or more numbers (as we do in this case) is
-   awkward.
-
-   Using the alternative S-Expression notation, we can reduce this to a
-   form that is both easier to read and executes faster (the details are
-   explained later):
-
-  def newarea {
-      (let s (/ (+ \%1 \%2 \%3) 2.0))
-      (sqrt (* s (- s \%1) (- s \%2) (- s \%3)))
-  }
-
-   In both examples, the \%1..3 variables are the normal Kermit macro
-   arguments, referenced by the normal escaping mechanism. For increased
-   readability, we can also assign the macro arguments \%1, \%2, and \%3
-   to the letters a, b, and c corresponding to our formula:
-
-def newarea {
-    (let a \%1 b \%2 c \%3)
-    (let s (/ (+ a b c) 2.0))
-    (sqrt (* s (- s a) (- s b) (- s c)))
-}
-
-   And now the Kermit function reads almost like the original formula.
-   Here Kermit behaves more like a regular programming language. In an
-   S-Expression, macro names need not be escaped when they are used as
-   the names of numeric variables.
-
-   [ [482]Top ] [ [483]Contents ] [ [484]C-Kermit Home ] [ [485]Kermit
-   Home ]
-     _________________________________________________________________
-
-  9.1. What is an S-Expression?
-
-   The S-Expression concept is borrowed from the Lisp programming
-   language. "S-Expression" is short for Symbolic Expression (itself
-   sometimes shortened to SEXP). S-Expressions provide a kind of
-   Alternative Mini-Universe within the Kermit command language when the
-   regular rules don't apply, a universe enclosed in parentheses.
-
-   C-Kermit does not pretend to be a full Lisp interpreter; only the
-   arithmetic parts of Lisp have been incorporated: S-Expressions that
-   operate on numbers and return numeric values (plus extensibility
-   features described in [486]Section 9.8, which allow some degree of
-   string processing).
-
-   An S-Expression is a list of zero or more items, separated by spaces,
-   within parentheses. Examples:
-
-  ()
-  (1)
-  (a)
-  (+ a 1)
-  (* 2 a b)
-
-   If the S-Expression is empty, it has the NIL (empty) value. If it is
-   not empty and the first item is an operator (such as + or *), there
-   can be zero or more subsequent items, called the operands:
-
-  (+ 1 2)
-
-   Here the operator is "+" and the operands are "1" and "2", and the
-   value of the S-Expression is the value of the operation (in this case
-   3). The operator always comes first, which is different from the
-   familiar algebraic notation; this because S-Expression operators can
-   have different numbers of operands:
-
-  (+ 1)
-  (+ 1 2)
-  (+ 1 2 3 4 5 6 7 8 9)
-
-   If the first item in the S-Expression is not an operator, then it must
-   be a variable or a number (or a macro; see [487]Section 9.8), and the
-   S-Expression can only contain one item; in this case, the
-   S-Expression's value is the value of the variable or number:
-
-  (a)
-  (3)
-
-   Operands can be numbers, variables that have numeric values, functions
-   that return numbers, or other S-Expressions. To illustrate an
-   S-Expression within an S-Expression, observe that:
-
-  (+ 1 2)
-
-   is equivalent to any of the following (plus an infinite number of
-   others):
-
-  (+ 1 (+ 1 1))
-  (+ (- 3 2) (/ 14 (+ 3 4)))
-
-   S-Expressions can be nested to any reasonable level; for example, the
-   value of the following S-Expression is 64:
-
-  (- (* (+ 2 (* 3 4)) (- 9 (* 2 2))) 6)
-
-   Operators have no precedence, implied or otherwise, since they can't
-   be mixed. The only exceptions are unary + and -, which simply indicate
-   the sign of a number:
-
-  (* 3 -1)
-
-   Order of evaluation is specified entirely by parentheses, which are
-   required around each operator and its operands: (+ a (* b c)) instead
-   of (a + b * c).
-
-   S-Expressions provide a simple and isolated environment in which
-   Kermit's macro names can be used without the \m(...) escaping that is
-   normally required. Given:
-
-  define a 1
-  define b 2
-  define c 3
-
-   Then:
-
-  (+ \m(a) \m(b) \m(c))
-
-   is equivalent to:
-
-  (+ a b c)
-
-   Within an S-Expression, as in other strictly numeric contexts
-   ([488]Section 8.2), any operand that starts with a letter is treated
-   as a Kermit macro name. In this context, abbreviations are not
-   accepted; variable names must be spelled out in full. Alphabetic case
-   is not significant; "a" and "A" are the same variable, but both are
-   different from "area".
-
-   Of course, regular Kermit variables and functions can be used in
-   S-Expressions in the normal ways:
-
-  (* \v(math_pi) (^ \%r 2))             ; Area of a circle with radius \%r
-  (+ \fjoin(&a))                        ; Sum of all elements of array \&a[]
-
-   [ [489]Top ] [ [490]Contents ] [ [491]C-Kermit Home ] [ [492]Kermit
-   Home ]
-     _________________________________________________________________
-
-  9.2. Integer and Floating-Point-Arithmetic
-
-   Normally, if all numbers in an S-Expression are integers, the result
-   is an integer:
-
-  (+ 1 1)                               ; Result is 2
-  (/ 9 3)                               ; Result is 3
-
-   If any of the operands is floating point, however, the result is also
-   floating point:
-
-  (+ 1 1.0)                             ; Result is 2.0
-  (/ 9.0 3)                             ; Result is 3.0
-
-   If all the operands are integers but the result has a fractional part,
-   the result is floating point:
-
-  (/ 10 3)                              ; Result is 3.333333333333333
-
-   To force an integer result in such cases, use the TRUNCATE operator:
-
-  (truncate (/ 10 3))                   ; Result is 3
-
-   Similarly, to force a computation to occur in floating point, you can
-   coerce one of its operands to FLOAT:
-
-  (+ 1 (float 1))                       ; Result is 2.0
-
-   The result is also floating point if the magnitude of any integer
-   operand, intermediate result, or the result itself, is larger than the
-   maximum for the underlying machine architecture:
-
-  (^ 100 100)
-
-   If the result is too large even for floating-point representation,
-   "Infinity" is printed; if it is too small to be distinguished from 0,
-   0.0 is returned.
-
-   Large numbers can be used and large results generated, but they are
-   accurate only to the precision of the underlying machine. For example,
-   the result of:
-
- (+ 111111111111111111111 222222222222222222222)
-
-   should be 333333333333333333333, but 333333333333333300000.0 is
-   produced instead if the machine is accurate to only about 16 decimal
-   digits, even with coercion to floating-point. The order of magnitude
-   is correct but the least significant digits are wrong. The imprecise
-   nature of the result is indicated by the ".0" at the end. Contrast
-   with:
-
- (+ 111111111 222222222)
-
-   which produces an exact integer result.
-
-   [ [493]Top ] [ [494]Contents ] [ [495]C-Kermit Home ] [ [496]Kermit
-   Home ]
-     _________________________________________________________________
-
-  9.3. How to Use S-Expressions
-
-   S-Expressions may be given as commands to C-Kermit. Any command whose
-   first character is "(" (left parenthesis) is interpreted as an
-   S-Expression.
-
-   If you enter an S-Expression at the C-Kermit> prompt, its result is
-   printed:
-
-  C-Kermit>(/ 10.0 3)
-   3.333333333333333
-  C-Kermit>
-
-   If an S-Expression is executed within a macro or command file, its
-   value is not printed. However, you can control the printing action
-   with:
-
-   SET SEXPRESSION ECHO { AUTO, ON, OFF }
-          AUTO is the default, meaning print the value at top level only;
-          ON means always print the value; OFF means never print it.
-
-   In any case, the value of the most recent S-Expression (and the
-   S-Expression itself) may be accessed programmatically through the
-   following variables:
-
-   \v(sexpression)
-          The S-Expression most recently executed.
-
-   \v(svalue)
-          The value of the S-Expression most recently executed.
-
-   Besides issuing S-Expressions as commands in themselves, you can also
-   execute them anywhere within a Kermit command, but in this case they
-   must be enclosed in a function call (otherwise they are taken
-   literally):
-
-   \fsexpression(s)
-          The argument "s" is an S-Expression; the outer parentheses may
-          be omitted. The value of the S-Expression is returned. Note
-          that since S-Expressions usually contain spaces, some form of
-          grouping or quoting might be needed in some contexts:
-
-  echo \fsexpression((+ 1 1))            ; Outer parentheses may be included
-  echo \fsexpr(+ 1 1)                    ; Outer parentheses may be omitted
-  echo Value = "\fsexp(+ 1 a)"           ; Can be embedded in strings
-  echo Value = \&a[\fsexp(/ b 2)]        ; Can be used in array subscripts
-  if = {\fsexp(+ 1 1)} 2 {               ; Braces needed here for grouping
-      echo One plus one still equals two
-  }
-
-   The IF statement illustrates how to use S-Expressions as (or in) IF or
-   WHILE conditions:
-
-     * Although S-Expressions and IF conditions are similar in
-       appearance, they are not interchangeable. Therefore you must use
-       \fsexpr() to let Kermit know it's an S-Expression rather than a
-       regular IF condition, or a boolean or algebraic expression within
-       an IF condition.
-     * In contexts where a single "word" is expected, you must enclose
-       the \fsexp() invocation in braces if the S-Expression contains
-       spaces (and most of them do).
-
-   If an S-Expression is the last command executed in a macro, its value
-   becomes the return value of the macro; no RETURN command is needed.
-   Example:
-
-  def newarea {
-      (let s (/ (+ \%1 \%2 \%3) 2.0))
-      (sqrt (* s (- s \%1) (- s \%2) (- s \%3)))
-  }
-
-   This is equivalent to (but more efficient than):
-
-  def newarea {
-      (let s (/ (+ \%1 \%2 \%3) 2.0))
-      return \fsexp(sqrt (* s (- s \%1) (- s \%2) (- s \%3)))
-  }
-
-   When an S-Expression is entered as a command -- that is, the first
-   nonblank character of the command is a left parenthesis -- then it is
-   allowed to span multiple lines, as many as you like, until the first
-   left parenthesis is matched:
-
-  (let s (/
-          (+
-           \%1
-           \%2
-           \%3
-           )
-          2.0
-          )
-       )
-  (sqrt (*
-         s
-         (- s \%1)
-         (- s \%2)
-         (- s \%3)
-         )
-        )
-
-   The S-Expression concept lends itself easily to embedding and
-   recursion, but the depth to which recursion can occur is limited by
-   the resources of the computer (memory size, address space, swap space
-   on disk) and other factors. There is no way that C-Kermit can know
-   what this limit is, since it varies not only from computer to
-   computer, but also from moment to moment. If resources are exhausted
-   by recursion, C-Kermit simply crashes; there's no way to trap this
-   error. However, you can set a depth limit on S-Expressions:
-
-   SET SEXPRESSION DEPTH-LIMIT number
-          Limits the number of times the S-Expression reader can invoke
-          itself without returning to the given number. The default limit
-          is 1000. This limit applies to S-Expressions embedded within
-          other S-Expressions as well as to S-Expressions that invoke
-          recursive macros. If the limit is exceeded, Kermit prints
-          "?S-Expression depth limit exceeded" and returns to its prompt.
-          More about recursion in [497]Section 9.8.
-
-   You can also test the depth programmatically:
-
-   \v(sdepth)
-          The current S-Expression invocation depth. The depth includes
-          both nesting level and recursion. For example, in:
-          (foo (foo (foo (foo (foo))))), the innermost (foo) is at depth
-          5.
-
-   Help, completion, and syntax checking are not available within an
-   S-Expression. If you type ? within an S-Expression, it says:
-
-  C-Kermit>(? S-Expression ("help sexp" for details)
-
-   As it says, typing "help sexp" will display a brief help text.
-
-   The SHOW SEXPRESSION command displays current SET SEXPRESSION settings
-   and related information.
-
-   [ [498]Top ] [ [499]Contents ] [ [500]C-Kermit Home ] [ [501]Kermit
-   Home ]
-     _________________________________________________________________
-
-  9.4. Summary of Built-in Constants and Operators
-
-   Three constants are built in:
-
-     * PI, whose value is the value of pi (the quotient of circumference
-       of any circle and its diameter, 3.141592653...) to the underlying
-       machine's precision;
-     * T, which always has the value 1, which signifies truth in Kermit
-       logical expressions or S-Expressions;
-     * NIL, which always has the empty value, and can serve as a False
-       truth value.
-
-   These constants are specific to S-Expressions and are not visible
-   outside them. They may not be used as the target of an assignment. So,
-   for example:
-
-  (setq t 0)   Fails
-  assign t 0   Succeeds but this is not the same T!
-
-   E (the base of natural logarithms, 2.7182818184...) is not built in
-   since it is not intrinsic in most Lisp dialects. If you want E to be
-   the base of natural logarithms you can:
-
-  (setq e (exp 1))
-
-   Operators are either symbols (such as "+") or words. Words must be
-   spelled out in full, not abbreviated. Differences of alphabetic case
-   are ignored.
-
-   The most basic operation in S-Expressions is evaluation:
-
-   EVAL [ s-expression or variable or number [ another [ another ... ] ]
-          ]
-          Evaluates its operands and returns the value of the last one
-          evaluated. Examples:
-
-  (eval)                                0
-  (eval 1)                              1
-  (eval a)                              value of a
-  (eval (+ 1 a))                        value of a+1
-  (eval (setq a 1) (setq b (+ a 0.5)))  value of b (= a+0.5)
-
-          You can use "." as a shorthand for EVAL:
-
-  (.)
-  (. 1)
-  (. a)
-  (. (+ 1 a))
-  (. (setq a 1) (setq b (+ a 0.5)))
-
-   Opposite of EVAL is the operator that suppresses evaluation of its
-   operand:
-
-   QUOTE item
-          The value (quote item) is "item". If the item is itself an
-          S-Expression, the result is the S-Expression with the outer
-          parentheses stripped. Examples:
-
-  (quote)                               (illegal)
-  (quote a)                             a
-  (quote hello)                         hello
-  (quote (this is a string))            this is a string
-  (quote this is a string)              (illegal)
-
-          A shorthand notation is also accepted for quoting:
-          'a is equivalent to (quote a). And therefore:
-          '(a b c) is equivalent to (quote (a b c)).
-          More about quoting in [502]Section 9.8.
-
-   STRING item
-          Is a combination of EVAL and QUOTE. It evaluates the item as an
-          S-Expression, and then puts quotes around the result (more
-          about this in [503]Section 9.8).
-
-   The following operators assign values to variables:
-
-   SETQ [ variable [ value [ variable [ value [ ... ] ] ] ] ]
-          Applies to global variables. For each variable given: if a
-          value is not given, the variable is undefined. If a value is
-          given, assigns the value to the variable. The value may be a
-          number, a variable, or anything that resolves to a number
-          including an S-Expression. Returns the value of the last
-          assignment. Examples:
-
-  (setq)             Does nothing, returns NIL.
-  (setq a)           Undefines a, returns NIL.
-  (setq a 1)         Assigns 1 to a, returns 1.
-  (setq a 1 b 2)     Assigns 1 to a, 2 to b, returns 2.
-  (setq a 1 b 2 c)   Assigns 1 to a, 2 to b, undefines c, returns NIL.
-
-   To undefine a variable that is not the final one in the list, give it
-   a value of "()" or NIL:
-
-  (setq a () b 2)    Undefines a, assigns 2 to b, returns 2.
-  (setq a nil b 2)   Ditto.
-
-   Note that a variable can be used right away once it has a value:
-
-  (setq a 1 b a)     Assigns 1 to a, the value of a (1) to b, returns 1.
-
-   The results of SETQ (when used with macro names) can be checked
-   conveniently with SHOW MACRO, e.g:
-
-  show mac a b c
-
-   LET [ variable [ value [ variable [ value [ ... ] ] ] ] ]
-          Like SETQ, but applies to local variables. Note that "local" is
-          used in the Kermit sense, not the Lisp sense; it applies to the
-          current Kermit command level, not to the current S-Expression.
-
-   If you want to use SETQ or LET to assign a value to a backslash
-   variable such as \%a or \&a[2], you must double the backslash:
-
-  (setq \\%a 3)
-  (setq \\%b (+ \%a 1))
-  (setq \\&a[2] (setq (\\%c (+ \%a \%b))))
-
-   In other words:
-
-     * Double the backslash when you want to indicate the variable's
-       NAME;
-     * Don't double the backslash when you want its VALUE.
-
-   See [504]Section 9.6 for a fuller explanation of variable syntax and
-   scope.
-
-   Here's a summary table of arithmetic operators; in the examples, a is
-   2 and b is -1.3:
-
-  Operator  Description                            Example           Result
-  +         Adds all operands (0 or more)          (+ a b)           0.7
-  -         Subtracts all operands (0 or more)     (- 9 5 2 1)       1
-  *         Multiplies all operands (0 or more)    (* a (+ b 1) 3)  -1.80
-  /         Divides all operands (2 or more)       (/ b a 2)        -0.325
-  ^         Raise given number to given power      (^ 3 2)           9
-  ++        Increments variables                   (++ a 1.2)        3.2
-  --        Decrements variables                   (-- a)            1
-  ABS       Absolute value of 1 operand            (abs (* a b 3))   7.8
-  MAX       Maximum of all operands (1 or more)    (max 1 2 3 4)     4
-  MIN       Minimum of all operands (1 or more)    (min 1 2 3 4)     1
-  MOD (%)   Modulus of all operands (1 or more)    (mod 7 4 2)       1
-  FLOAT     Convert an integer to floating-point   (float 1)         1.0
-  TRUNCATE  Integer part of floating-point operand (truncate 3.333)  3
-  CEILING   Ceiling of floating-point operand      (ceiling 1.25)    2
-  FLOOR     Floor of floating-point operand        (floor 1.25)      1
-  ROUND     Operand rounded to nearest integer     (round 1.75)      2
-  SQRT      Square root of 1 operand               (sqrt 2)          1.414..
-  EXP       e (2.71828..) to the given power       (exp -1)          0.367..
-  SIN       Sine of angle-in-radians               (sin (/ pi 2))    1.0
-  COS       Cosine of angle-in-radians             (cos pi)         -1.0
-  TAN       Tangent of angle-in-radians            (tan pi)          0.0
-  LOG       Natural log (base e) of given number   (log 2.7183)      1.000..
-  LOG10     Log base 10 of given number            (log10 1000)      3.0
-
-   The ++ and -- operators are also assignment operators and work just
-   like SETQ and LET in their interpretations of operators and operands,
-   but:
-
-     * Each target variable must already be defined and have a numeric
-       value;
-     * The assignment value is the amount by which to increment or
-       decrement the variable.
-     * If an assignment value is not given, 1 is used.
-
-   If you include more than one variable-value pair in a ++ or --
-   expression, every variable (except, optionally, the last) must be
-   followed by a value. Examples:
-
-  (++ a)                Equivalent to (setq a (+ a 1)) and to (++ a 1)
-  (++ a 2)              Equivalent to (setq a (+ a 2))
-  (-- a (* 2 pi))       Equivalent to (setq a (- a (* 2 pi)))
-  (++ a 1 b 1 c 1 d)    Equivalent to four SETQs incrementing a,b,c,d by 1.
-
-   Another group of operators forms the predicates. These return a "truth
-   value", in which 0 (or NIL) is false, and 1 or any other nonzero
-   number is true.
-
-  Operator  Description                            Example           Result
-  = (or ==) Operands are equal                     (= 1 1.0)         1
-  !=        Operands are not equal                 (!= 1 1.0)        0
-  <         Operands in strictly ascending order   (< 1 2 3)         1
-  <=        Operands in ascending order            (<= 1 1 2 3)      1
-  >         Operands in strictly descending order  (> 3 2 1)         1
-  >=        Operands in descending order           (<= 3 3 2 1)      1
-  AND (&&)  Operands are all true                  (and 1 1 1 1 0)   0
-  OR  (||)  At least one operand is true           (or 1 1 1 1 0)    1
-  XOR       Logical Exclusive OR                   (xor 3 1)         0
-  NOT (!)   Reverses truth value of operand        (not 3)           0
-
-   The Exclusive OR of two values is true if one value is true and the
-   other value is false.
-
-   And another group operates on bits within an integer word:
-
-  Operator  Description                            Example           Result
-  &         Bitwise AND                            (& 7 2)           2
-  |         Bitwise OR                             (| 1 2 3 4)       7
-  #         Bitwise Exclusive OR                   (# 3 1)           2
-  ~         Reverses all bits                      (~ 3)            -4
-
-   These operators coerce their operands to integer by truncation if
-   necessary. The result of bit reversal is hardware dependent.
-
-   The final category of operator works on truth values:
-
-  Operator  Description                            Example           Result
-  IF        Conditional evaluation                 (if (1) 2 3)      2
-
-   IF (predicate) (s1) [ (s2) ]
-          The IF operator is similar to Kermit's IF command. If the
-          predicate is true (i.e. evaluates to a nonzero number), the
-          first S-Expression (s1) is evaluated and its value is returned.
-          Otherwise, if (s2) is given, it is evaluated and its value
-          returned; if (s2) is not given, nothing happens and the NIL
-          (empty) value is returned.
-
-   You can group multiple expressions in the s1 and s2 expressions using
-   EVAL (or "."):
-
-  (if (< a 0) (eval (setq x 0) (setq y 0)) (eval (setq x a) (setq y b)))
-
-   or equivalently:
-
-  (if (< a 0) (. (setq x 0) (setq y 0)) (. (setq x a) (setq y b)))
-
-   Each operator has its own requirement as to number and type of
-   operands. In the following table, "number" means any kind of number --
-   integer or floating-point -- or a variable, function, macro, or
-   S-Expression that returns a number; "vname" means variable name,
-   "fpnumber" means a floating-point number (or anything that resolves to
-   one), and "integer" means integer (or anything that resolves to one).
-   "truthvalue" means anything that resolves to a value of zero or an
-   empty value (which indicates false) or a nonzero value (which
-   indicates true). "any" means any kind of value, including none at all.
-
-  Operator  Number of operands   Type of operands    Returns
-  EVAL  (.) 0 or more            S-Expression        Last value (default NIL)
-  STRING    1                    S-Expression        string
-  QUOTE (') 1                    word                string
-  SETQ      0 or more            vname value pairs   Last value (default NIL)
-  LET       0 or more            vname value pairs   Last value (default NIL)
-  +         0 or more            number              number     (default 0)
-  -         0 or more            number              number     (default 0)
-  *         0 or more            number              number     (see note (1))
-  /         2 or more            number              number
-  ^         2 or more            number              number
-  ++        1 or more            vname value pairs   Result of last increment
-  --        1 or more            vname value pairs   Result of last decrement
-  ABS       1                    number              number
-  MAX       1 or more            number              number
-  MIN       1 or more            number              number
-  MOD (%)   2                    number              number
-  FLOAT     1                    number              fpnumber
-  TRUNCATE  1                    number              integer
-  CEILING   1                    number              integer
-  FLOOR     1                    number              integer
-  ROUND     1                    number              integer
-  SQRT      1                    number              fpnumber
-  EXP       1                    number              fpnumber
-  SIN       1                    number              fpnumber
-  COS       1                    number              fpnumber
-  TAN       1                    number              fpnumber
-  LOG       1                    number              fpnumber
-  LOG10     1                    number              fpnumber
-  = (==)    1 or more            number              truthvalue
-  !=        1 or more            number              truthvalue
-  <         1 or more            number              truthvalue
-  <=        1 or more            number              truthvalue
-  >         1 or more            number              truthvalue
-  >=        1 or more            number              truthvalue
-  AND (&&)  1 or more            truthvalue          truthvalue
-  OR  (||)  1 or more            truthvalue          truthvalue
-  XOR       2                    truthvalue          truthvalue
-  NOT (!)   1                    truthvalue          truthvalue
-  &         1 or more            number (see note 2) integer
-  |         1 or more            number (see note 2) integer
-  #         2                    number (see note 2) integer
-  ~         1                    number (see note 2) integer
-  IF        2 or 3               truthvalue,any,any  any
-
-   Operators that don't require any arguments return the default values
-   shown.
-
-    1. The value of "*", when used as an operator, is initially "1" and
-       the value of the most recent S-Expression thereafter, as in Franz
-       Lisp. This is handy when doing a series of calculations by hand:
-  C-Kermit>(* 13272.42 0.40)
-   5308.968
-  C-Kermit>(/ * 2)
-   2654.4840
-  C-Kermit>
-    2. The bitwise operators coerce their operands to integer by
-       truncation.
-
-   [ [505]Top ] [ [506]Contents ] [ [507]C-Kermit Home ] [ [508]Kermit
-   Home ]
-     _________________________________________________________________
-
-  9.5. Variables
-
-   As noted elsewhere in this discussion, all backslash items (variables
-   such as \%a, macro parameters such as \%1, array elements such as
-   \&a[\%i], built-in variables such as \v(ndate), built-in functions
-   such as \fjoin(), macro names enclosed in \m(), \s(), or \:(), etc)
-   are evaluated at "top level" before the S-Expression is sent to the
-   S-Expression reader. To use a backslash variable as the target of an
-   assignment (e.g. by SETQ, LET, ++, or --), you must double the
-   backslash, e.g. (setq \\%r 1234). This is discussed at greater length
-   in the next section.
-
-   Thus S-Expression reader generally deals only with macro names (not
-   backslash items) as variables. It is important to understand how the
-   reader handles macro names. There are fundamentally two kinds of
-   S-Expressions: those that contain a single element, such as:
-
-  (foo)
-
-   and those that contain more than one element:
-
-  (foo a b c)
-
-   If an S-Expression contains only one element, and it is the name of a
-   macro, the macro's definition is examined. If the definition is a
-   number (integer or floating-point, positive or negative), then this
-   becomes the value of the expression. If the definition starts with '
-   (apostrophe), then the quoted word or string is the value of the
-   expression (explained in [509]Section 9.8). Otherwise, the macro is
-   assumed to be composed of Kermit commands (possibly including
-   S-Expressions), which are executed. If the macro has a RETURN value,
-   or it executes an S-Expression as its last command, the result becomes
-   the value of the S-Expression; otherwise the result is empty.
-
-   For S-Expressions that contain more than one element, and the first
-   element is the name of a macro, then this macro is executed with the
-   arguments that are given, after the arguments are evaluated by the
-   S-Expression reader. Likewise, If the first element is a built-in
-   operator, then it is applied to the operands after they are evaluated.
-   In both cases, each operand is fed to the S-Expression reader
-   recursively for evaluation. If an operand is a number or a quoted
-   string, it is used as-is. But if it's a macro name, this degenerates
-   into the first case, and the previous paragraph applies.
-
-   Examples:
-
-  define foo 123
-  (foo)                                Result: 123
-  define foo 'abc
-  (foo)                                Result: abc
-  define foo '(one two three)
-  (foo)                                Result: one two three
-  define foo return \frandom(1000)
-  (foo)                                Result: 713 (or other number)
-  define foo (+ a b)
-  (foo)                                Result: The sum of a and b
-
-   A more difficult example:
-
-  define foo abc
-  (foo)                                Result: ???
-
-   The result in the last example depends on the definition of abc:
-
-     * If it has no definition, an error occurs; otherwise:
-     * If the definition is an S-Expression, the result is the
-       S-Expression's value; otherwise:
-     * If the definition consists of Kermit commands, they are executed.
-       But in this case "(foo)" produces the empty result, because it
-       doesn't RETURN anything.
-
-   The use of macros as S-Expression operators is described in
-   [510]Section 9.8.
-
-   [ [511]Top ] [ [512]Contents ] [ [513]C-Kermit Home ] [ [514]Kermit
-   Home ]
-     _________________________________________________________________
-
-  9.6. Assignments and Scope
-
-   The assignment operators SETQ and LET apply to global and local
-   variables, respectively. SETQ and LET are standard Lisp operators
-   adapted to Kermit scoping rules. When the operands are numeric or
-   arithmetic, SETQ is equivalent to Kermit's EVALUATE command:
-
-  (setq a (+ 1 2))
-  evaluate a 1 + 2
-
-   When the operand is a string, SETQ is equivalent to DEFINE:
-
-  (setq a '(this is a string))
-  define a this is a string
-
-   In the first case, both statements create a macro named "a" with a
-   value of 3. But in neither case is the macro "a" necessarily global.
-   If either of these commands executes in an environment (i.e. macro
-   invocation level) where a "local a" command has been given, the "a"
-   macro is global to that environment, but is not visible outside it.
-
-   LET is equivalent to the Kermit LOCAL command, followed by the
-   corresponding EVALUATE:
-
-  (let a (+ 1 2))
-
-   is equivalent to:
-
-  local a
-  evaluate a 1 + 2
-
-   Again, "local" in this context applies to the Kermit macro invocation
-   stack, not to the S-Expression nesting level. To illustrate, recall
-   our "newarea" macro:
-
-def newarea {
-    (let a \%1 b \%2 c \%3)
-    (let s (/ (+ a b c) 2.0))
-    (sqrt (* s (- s a) (- s b) (- s c)))
-}
-
-   Because SETQ and LET expressions return a value, they can be placed
-   within a larger S-Expression. In this case we can replace the first
-   reference to the "s" variable by its defining expression:
-
-def newarea {
-    (let a \%1 b \%2 c \%3)
-    (sqrt (* (let s (/ (+ a b c) 2.0)) (- s a) (- s b) (- s c)))
-}
-
-   This would not work if LET were local to the S-Expression, but it
-   works nicely in the context of Kermit macros. The previous definition
-   is equivalent to:
-
-def newarea {
-    local a b c s
-    (setq a \%1 b \%2 c \%3)
-    (sqrt (* (setq s (/ (+ a b c) 2.0)) (- s a) (- s b) (- s c)))
-}
-
-   In both cases, the variables a, b, c, and s are local to the "newarea"
-   macro, and global within it.
-
-   Multiple assignments can be handled in several ways. Here is the
-   obvious way to initialize a series of variables to the same value:
-
-  (setq a 0)
-  (setq b 0)
-  (setq c 0)
-  (setq s 0)
-
-   Here is a more compact and efficient way of doing the same thing:
-
-  (setq a 0 b 0 c 0 s 0)
-
-   However, in case the value was more complex, it's better to put only
-   one copy of it in the S-Expression; in this case we rely on the fact
-   that SETQ returns the value of its last assignment:
-
-  (setq a (setq b (setq c (setq s (* x (^ y 2))))))
-
-   Similarly, to set a series of variables to x, x+1, x+2, ...
-
-  (setq c (+ (setq b (+ (setq a (+ (setq s x) 1)) 1)) 1))
-
-   In the last example, you can see why "last" does not always correspond
-   to "rightmost" (the leftmost variable "c" is assigned last).
-
-   If you are working with backslash variables like \%a or array elements
-   like \&a[1], remember two rules:
-    1. Don't put spaces inside array brackets.
-    2. You must double the backslash when using SETQ, LET, ++, or -- to
-       assign a value to a backslash variable.
-
-   Examples of assigning to a backslash variable:
-
-  (setq x 1)
-  (setq \\%a 0)
-  (setq \\&a[x+1] 1)
-  (++ \\%x)
-  (-- \\&a[x+2])
-
-   Examples of referring to a backslash variable's value:
-
-  (setq a (+ \%a 1))
-  (setq b (+ \%a \&a[1]))
-  (++ a \%x)
-  (-- b \&a[1])
-
-   The special notation is required because all backslashed items (\%x
-   variables, array elements, built-in \v(xxx) variables, and \fxxx()
-   function invocations) are evaluated in a single pass BEFORE the
-   S-Expression is executed; any other approach would result in
-   unacceptable performance. So, for example, in:
-
-  declare \&a[] = 1 2 3
-  define \%x 4
-  define \%y 0
-  (setq \\%y (+ \%x \&a[1]))
-
-   the S-Expression becomes:
-
-  (setq \%y (+ 4 1))
-
-   before it is sent to the S-Expression evaluator. If the backslash had
-   not been doubled on the assignment target, the result would have been:
-
-  (setq 0 (+ 4 1))
-
-   which is illegal because you can't assign a value to a number.
-   Conversely, if backslashes were doubled on right-hand-side values:
-
-  (setq \\%y (+ \\%x \\&a[1])
-
-   this too, would give an error (not numeric - "\%x").
-
-   If you omit the double backslash in the assignment target, the result
-   depends on whether the variable already has a value:
-
-  (setq \%a (* 3 3))
-
-   If \%a has a non-numeric single-word value, then this becomes the name
-   of the variable that is assigned by SETQ. To illustrate:
-
-  define \%a foo
-  echo \%a
-  foo
-  (setq \%a (* 3 3))
-  echo \%a
-  foo
-  show macro foo
-  foo = 9
-
-   If \%a has no value, a numeric value, or a multiword value, an
-   "invalid assignment" error occurs.
-
-   [ [515]Top ] [ [516]Contents ] [ [517]C-Kermit Home ] [ [518]Kermit
-   Home ]
-     _________________________________________________________________
-
-  9.7. Conditional Expressions
-
-   The IF operator provides a compact form of decision-making within
-   S-Expressions. An IF expression can stand wherever a number might
-   stand, as long is it returns a number. Here's a quick way to obtain
-   the average value of all the elements in an array that contains only
-   numbers:
-
-  (/ (+ \fjoin(&a)) (float \fdim(&a)))
-
-   This results in a "Divide by zero" error if the array is empty. If you
-   want to define the average value of an empty array to be 0 instead of
-   getting an error, you can use IF to check the array size:
-
-  (if \fdim(&a) (/ (+ \fjoin(&a)) (float \fdim(&a))) 0)
-
-   or equivalently:
-
-  (if (not \fdim(&a)) 0 (/ (+ \fjoin(&a)) (float \fdim(&a))))
-
-   Of course, IF can fit anywhere else into an S-Expression:
-
-  (setq a (+ b (if (< c 0) 0 c)))
-
-   and the IF expression can be as complex as you like:
-
-  (setq a (+ b (if (and (or (> x 0) (> y 0)) (< c 0) (> d 1) (!= e 0)) 1 0)))
-
-   and the "then" and "else" parts can contain multiple S-Expressions
-   enclosed within (EVAL ...):
-
-  (if x (eval (...) (...) (...)) (eval (...) (...) (...)))
-
-   AND and OR operators are guaranteed to "short circuit". If any operand
-   of AND is false, none of the subsequent operands is evaluated;
-   likewise, if an OR operand is true, no further operands are evaluated.
-
-   Bear in mind that the S-Expression IF is not the same as Kermit IF;
-   the condition is only allowed to be an S-Expression or a variable or
-   number, not the whole list of possibilities you see when you type "if
-   ?" at the C-Kermit> prompt. But keep reading...
-
-   [ [519]Top ] [ [520]Contents ] [ [521]C-Kermit Home ] [ [522]Kermit
-   Home ]
-     _________________________________________________________________
-
-  9.8. Extensibility
-
-   To extend the capabilities of S-Expressions, you can use Kermit macro
-   names as operators, with the following limitations:
-
-     * The macro must not have the same name as a built-in operator.
-     * You must use the full macro name, not an abbreviation.
-
-   And with the following enhancement:
-
-     * If the last statement executed by the macro is an S-Expression,
-       its value is returned automatically. In other words:
-
-  define bump (++ \%1)
-
-   is equivalent to:
-
-  define bump return \fsexpression(++ \%1)
-
-   Here's an example in which we define a FIBONACCI operator that returns
-   the nth element, n >= 0, of the Fibonacci series, 0 1 1 2 3 5 8 13 21
-   34 55, . . ., in which the first element is 0, the second is 1, and
-   each subsequent element is the sum of the two before it. This series
-   was devised by Leonardo Pisano, Filius Bonacci (Fibonacci for short)
-   in 1202 to describe how fast rabbits can breed, and also forms the
-   basis for the Golden Mean, the branching behavior of plants, the
-   spiral of a nautilus shell, etc. (Thanks to [523]Dat Thuc Nguyen for
-   December 2003 corrections to this section!)
-
-   We can write a FIBONACCI function as a macro easily with
-   S-Expressions:
-
-  define FIBONACCI {
-    (if (== \%1 0) 0
-        (if (== \%1 1) 1 (+ (fibonacci (- \%1 2)) (fibonacci (- \%1 1)))))
-  }
-
-   You can read this as:
-
-     If the argument (\%1) is 0, return a result of 0; if it is 1,
-     return 1; otherwise:
-     return the sum of fibonacci(argument - 2) and fibonacci(argument -
-     1)
-
-   Note that a RETURN statement is not needed, since S-Expressions
-   automatically set the return value of their containing macros.
-
-   For comparison, here's how it would be coded without S-Expressions:
-
-  define FIBONACCI {
-      if == \%1 0 {
-          return 0
-      } else if == \%1 1 {
-          return 1
-      } else {
-          return \feval(\fexec(fibonacci \feval(\%1-2)) -
-               + \fexec(fibonacci \feval(\%1-1)))
-      }
-  }
-
-   Now we can use the FIBONACCI function (whichever way you write it)
-   just as if it were a built-in operator:
-
-  (fibonacci 6)
-
-   Or:
-
-  (setq a 10)
-  (fibonacci a)
-
-   Within S-Expressions only (not outside them), S-Expressions themselves
-   can be used as macro arguments:
-
-  (setq a 2 b 4)
-  (setq x (fibonacci (* a b )))
-
-   The value of the S-Expression (in this case "8"), and not the
-   S-Expression itself, is sent to the macro.
-
-   Your macro is responsible for argument validation and error handling.
-   A robust Fibonacci macro would be more like this:
-
-  define FIBONACCI {
-      if < \v(argc) 2 end 1 ?\%0: Missing argument
-      if > \v(argc) 2 end 1 ?\%0: Too many arguments
-      if not integer \%1 end 1 ?\%0: Integers only
-      if < \%1 1 end 1 ?\%0: Argument out of range
-      (if (== \%1 0) 0
-         (if (== \%1 1) 1 (+ (fibonacci (- \%1 2)) (fibonacci (- \%1 1)))))
-  }
-
-   Recall that "END nonzero-number [ message ]" causes a macro invocation
-   to fail. When the macro is the operator in an S-Expression, this makes
-   the S-Expression fail too. Also note that our Fibonacci macro is just
-   an illustration, not a practical example. Since it is recursive (calls
-   itself), it won't work for large arguments because the call stack can
-   exceed available memory. See [524]Section 9.9.2 for a practical
-   alternative.
-
-   Kermit macros, when used as S-Expression operators, can do anything at
-   all except initiate file transfers: they can print messages on the
-   screen, read and write files, interact with the user, and so on. For
-   example, here's a macro ASKME that asks you to enter a number, makes
-   sure that you did, and then returns its value for use in the
-   S-Expression:
-
-  define ASKME {
-      local \%n
-      while true {
-          ask \%n { Number: }
-          if not def \%n continue
-          if not numeric \%n {
-              echo Not numeric - "\%n"
-              continue
-          }
-          break
-      }
-      return \%n
-  }
-  (setq a (* 2 (askme))) ; Get number from user, double it, assign result to a.
-
-   Here's a macro you can use to validate that a number is in a given
-   range:
-
-  define inrange {
-      if != \v(argc) 4 end 1 ?\%0: Wrong number of arguments
-      if ( < \%1 \%2 || > \%1 \%3 ) return 0
-      return 1
-  }
-
-   The first argument is the number to be checked, the second is the
-   minimum acceptable value, the third is the maximum. You can use this
-   (for example) in IF conditions:
-
-  define yes echo \%1 IS OK
-  define no echo \%1 IS NOT OK
-
-  (setq a -1 b 999)
-  (if (inrange a 0 100) (yes a) (no a))
-  (if (inrange b -1000 +1000) (yes b) (no b))
-
-   This is just an illustration, of course; there's already a built-in
-   operator to let you do range checking without help from macros:
-
-  (if (<= 0 a 100) (yes a) (no a))
-  (if (<= -1000 b +1000) (yes b) (no b))
-
-   To send string parameters to a macro, some kind of quoting is required
-   to tell the S-Expression parser to take a given "word" literally
-   rather than replacing it by its value. For this we use the Lisp QUOTE
-   operator:
-
-  define length return \flength(\%1)
-  (length (quote abcdefghijklmnopqrstuvwxyz))
-  26
-
-   This causes the string "abcdefghijklmnopqrstuvwxyz" to be sent
-   literally to the LENGTH macro. Kermit, like Lisp, also offers a
-   shortcut for QUOTE, that lets us quote a word by prefixing it with a
-   single quote (') character, also called apostophe (ASCII 39):
-
-  (length 'abcdefghijklmnopqrstuvwxyz)
-  26
-
-   The two forms are equivalent.
-
-   How the macro treats its arguments is up to the macro. In the example
-   above, the argument is treated as a literal string. However, it can
-   also be treated as a variable name:
-
-  define string This is a string
-  define length return \flength(\m(\%1))
-  (length 'string)
-  16
-
-   Note the construct \m(\%1). This means "the value of the macro whose
-   name is the value of
-   \%1". The value of \%1 in this case is the word "string", and the
-   value of the macro whose name is "string" is "This is a string".
-
-   What if the macro takes multiple arguments, or a variable number of
-   them? Here's a simple macro that prints a phrase that includes its
-   arguments:
-
-  define complain echo It's too \%*!
-
-   (Recall that \%* means "all arguments".)
-
-   It can be called in the traditional way:
-
-  complain hot                       Result: "It's too hot!"
-  complain cold and wet              Result: "It's too cold and wet!"
-
-   Or from an S-Expression if you quote the arguments:
-
-  (complain 'hot)                    Result: "It's too hot!"
-  (complain 'cold 'and 'wet)         Result: "It's too cold and wet!"
-
-   To group multiple words into a single argument, use parentheses:
-
-  (complain (quote (cold and wet)))  Result: "It's too cold and wet!"
-  (complain '(cold and wet))         Result: "It's too cold and wet!"
-
-   Note the difference:
-
-  (complain 'cold 'and 'wet)         Three arguments
-  (complain '(cold and wet))         One argument
-
-   Since the COMPLAIN macro uses \%* to refer to all its arguments, no
-   matter how many, it doesn't care which form you use. But it makes a
-   difference in cases where the macro refers to its arguments
-   individually.
-
-   To illustrate, let's consider a macro that receives the name of a
-   macro and its argument list and executes it with its arguments,
-   without knowing how many arguments there are. The following LOOP macro
-   is used to execute the given macro with the given argument list the
-   requested number of times:
-
-  def loop { local i, for i 1 \%1 1 do \%2 \%3 }
-
-   Within the LOOP macro, the first argument (\%1) is the loop count, \%2
-   is the macro name, and \%3 is the argument list. When the LOOP macro
-   is invoked traditionally like this:
-
-  loop 3 complain hot
-
-   it prints "It's too hot!" three times. To invoke it from an
-   S-Expression, you must quote both the macro name as well as the
-   argument, since in this case the macro name itself is an argument:
-
-  (loop 3 'complain 'hot)
-
-   Now what if you need to send different or variable numbers of
-   arguments to the LOOP macro? The LOOP macro can handle it already,
-   provided you group the arguments into LOOP's third argument (\%3). In
-   Kermit syntax, without grouping:
-
-  loop 3 complain cold and wet
-
-   prints "It's too cold!" three times ("and wet" is lost); but with
-   grouping (either of the following two forms):
-
-  loop 3 complain {cold and wet}
-  loop 3 complain "cold and wet"
-
-   the LOOP macro prints "It's too cold and wet!" three times as desired.
-
-   To do the same thing in an S-Expression, just use the Lisp forms of
-   quoting instead of the Kermit forms; the following two are equivalent:
-
-  (loop 3 'complain (quote (cold and wet)))
-  (loop 3 'complain '(cold and wet))
-
-   Here's a similar example in which we write a macro that shows both the
-   name and the value of one or more other macros, whose names are given
-   as arguments (similar to "show macro"):
-
-  define display {
-      local \%i
-      for \%i 1 \v(argc)-1 1 {
-          echo \&_[\%i] = \m(\&_[\%i])
-      }
-  }
-
-   (Recall that \&_[] is the macro's argument vector array, equivalent to
-   \%1, \%2, ...) The DISPLAY macro can be used in S-Expressions like
-   this:
-
-  (setq a 1 b 2 c 3)
-  (display 'a 'b 'c 'd)
-
-   which prints:
-
-  a = 1
-  b = 2
-  c = 3
-  d =
-
-   The names must be quoted to prevent their evaluation before they are
-   sent to the macro. This ability to pass variables "by name" to macros,
-   rather than by value, lets you write macros that change the values of
-   argument variables. For example, here's a macro that doubles the value
-   of its argument variable:
-
-  define double (++ \%1 \%1)
-
-   which you can call like this:
-
-  (setq a 12)
-  (double 'a)
-
-   In the macro, \%1 is replace by the variable name "a"; "(++ a a)" adds
-   "a" to itself, and sets the value of "a" to the result.
-
-   There are no built-in operators other than QUOTE, ', and STRING for
-   handling strings in S-Expressions, but using just these, plus macros
-   that use Kermit's regular string-handling features, you can easily
-   extend S-Expressions to do string manipulation:
-
-  define len return \flen(\%1)               Returns length of argument string
-  define cap return \fupper(\%1)             Uppercase argument string
-  define rev return \freverse(\%1)           Reverses argument string
-  define sub return \fsubstr(\%1,\%2,\%3)    Returns substring of arg string
-
-  (len '(this is a string))                  Result: 16
-  (rev '(this is a string))                  Result: gnirts a si siht
-  (rev (cap '(this is a string)))            Result: GNIRTS A SI SIHT
-  (sub (rev (cap '(this is a string))) 5 9)  Result: TS A SI S
-
-   You can assign a string to a macro name as follows:
-
-  (setq foo '(this is a string))
-  (setq foo (quote (this is a string)))
-
-   The two are exactly equivalent. In both cases, the macro "foo" has the
-   value:
-
-  '(this is a string)
-
-   so when it is retrieved it can be identified as a string rather than a
-   number or commands to be executed. Thus:
-
-  (setq foo (quote (this is a string)))
-  show macro foo
-  foo = '(this is a string)
-  (foo)
-  this is a string
-
-   Note the different results for "show macro foo" and "(foo)". The
-   former shows the internal definition; the latter evaluates the
-   variable, which removes the quoting. And perhaps more important, note
-   that if the apostrophe and surrounding parentheses were not stored as
-   part of the definition, (foo) would try to execute "this is a string"
-   as a command.
-
-   Given the assignment above, the following work as expected:
-
-  (len foo)                                  Result: 16
-  (rev foo)                                  Result: gnirts a si siht
-  (rev (cap foo))                            Result: GNIRTS A SI SIHT
-  (sub (rev (cap foo)) 5 8)                  Result: TS A SI S
-
-   Note that, unlike built-in S-Expression operators that return numbers
-   or truth values, these operators return strings. If you want to assign
-   their return values to other variables, you can do so:
-
-  (setq bar (rev (cap foo)))                 Result: GNIRTS A SI SIHT
-
-   But now the S-Expression processor doesn't know the value of "bar" is
-   supposed to be a string, rather than a macro to execute. For this you
-   need one final special operator, STRING. The STRING operator takes an
-   S-Expression as an operand, evaluates it, and then returns its value
-   enclosed in '(), so you can use the value as a string is subsequent
-   S-Expressions. Use STRING for referencing macros that return strings:
-
-  (setq bar (string (rev (cap foo))))        Result: '(GNIRTS A SI SIHT)
-
-   STRING is like QUOTE, except that it evaluates its operand before
-   applying the quoting, rather than taking the operand literally.
-
-   To reference backslash variables or functions that return string
-   values, you must use the regular quoting mechanisms:
-
-  (setq time '(\v(time)))
-  (setq date '(\v(date)))
-  assign \%r this is a string
-  (setq s1 '(\%r))
-
-   That's because backslash items are evaluated BEFORE the S-Expression
-   parser ever sees them, and the values of \v(time) and so on are not
-   valid S-Expressions, so STRING won't like them.
-
-   Finally a brief word on the touchy topic of quoting. Suppose you want
-   to include (say) literal parentheses in a string that will later be
-   processed by the S-Expression reader (or \fsplit() or \fword()).
-   Normally, you can't do this because parentheses are meaningful in
-   these contexts. To defeat the normal parsing rules, you can quote the
-   parentheses with backslash. However, due to the many levels of string
-   processing involved, a surprisingly large amount of backslashes might
-   be required, for example:
-
-  (setq s '(a b (c d) \\\\\\\\\\\\\\\\(e f (g h) x\\\\\\\\\\\\\\\\) j k))
-
-   This is nearly impossible to explain(*). Instead, just remember two
-   points:
-
-     * In situations like this, it's better to use DEFINE to create the
-       string, rather than SETQ. The example above requires only double
-       backslashes when DEFINE is used:
-  define s '(a b (c d) \\(e f (g h) x\\) j k)
-     * The level of quoting depends on how many levels of evaluation the
-       string must pass through, which is not always obvious. However,
-       the number of backslashes required in any given situation is
-       always a power of 2. So if 1 doesn't work, try 2; if 2 doesn't
-       work, try 4; if 4 doesn't work, try 8, 16, 32, and so on.
-
-   Considerations like this apply in any scripting language (shell, Tcl,
-   Perl, Python, etc). The situation is known as "Quoting Hell".
-
-   (*) If you really want an explanation, here it is:
-
-     * Every SEXP has its backslash items evaluated in a single pass at
-       top level before being passed to the SEXP reader, so \%1,
-       \v(ftime), etc, can be evaluated up front, freeing the SEXP reader
-       of having to know about such things, which in turn makes it much
-       more efficient. Therefore one level of quoting is lost right away,
-       and therefore you must double each backslash that is to be used as
-       a quote.
-     * When the SEXP reader sees '\', it treats it as a quote; discards
-       it and keeps the next character. Thus '\\' becomes '\'. This would
-       be the end of it, except that:
-     * The SEXP reader must call itself recursively on its operands, so
-       we must double any quotes in the operands: 2^2 = 4.
-     * If the result is to be passed as an argument to a macro, the
-       backslashes must again be doubled, because the macro processor
-       evaluates the arguments before sending them to the macro: 2^3 = 8.
-     * If the macro itself is to see the quotes, rather than just the
-       result of the quoting, the quotes must be doubled again: 2^4 = 16.
-
-   Moral: To create string constants in which grouping characters must be
-   quoted, use DEFINE rather than SETQ.
-
-   [ [525]Top ] [ [526]Contents ] [ [527]C-Kermit Home ] [ [528]Kermit
-   Home ]
-     _________________________________________________________________
-
-  9.9. Examples
-
-    9.9.1. Statistics
-
-   The following program computes statistics -- means, maxima, mimima,
-   variance, standard deviation, and correlation -- from data stored in
-   parallel arrays, \&x[] and \&y[], which can contain any mixture of
-   integer and floating-point numbers: positive, negative, or zero. Array
-   setup and validation are not shown. Except for the traditional FOR
-   loop and printing the results at the end, the entire computation is
-   done with S-Expressions:
-
-; Initialize sums, maxima, minima, and number of elements
-
-  (setq xsum 0 ysum 0 xsum2 0 ysum2 0 xysum 0)
-  (setq xmin (setq xmax \&x[1]) ymin (setq ymax \&y[1]))
-  (setq n \fdim(&x))
-
-; Loop through elements and accumulate sums, maxima, and minima
-
-  for i 1 n 1 {
-      (setq x \&x[i] y \&y[i])                    ; Notational convenience
-      (setq xmax (max xmax x) ymax (max ymax y))  ; X and Y maxima
-      (setq xmin (min xmin x) ymin (min ymin y))  ; X and Y minima
-      (++ xsum x ysum y)                          ; X and Y sums
-      (++ xsum2 (^ x 2) ysum2 (^ y 2))            ; Sum of X and Y squares
-      (++ xysum (* x y))                          ; Sum of XY products
-  }
-
-; Calculate results
-
-  (setq xmean (/ xsum n) ymean (/ ysum n))        ; Mean X and Y
-  (setq xss (- xsum2 (/ (^ xsum 2) n)))           ; Intermediate values
-  (setq yss (- ysum2 (/ (^ ysum 2) n)))
-  (setq xyss (- xysum (/ (* xsum ysum) n)))
-  (setq xvar (/ xss n) yvar (/ yss n))            ; X and Y variance
-  (setq sdx (sqrt xvar) sdy (sqrt yvar))          ; Std deviation in X and Y
-  (setq tmp (* xss yss))
-  (setq cc (if tmp (/ xyss (sqrt tmp)) 1.0))      ; Correlation coefficient
-  show macro xmean ymean xvar yvar sdx sdy cc     ; Print the results
-
-   The final "if tmp" check accounts for the possibility that both arrays
-   contain all 0's. Results can also be printed with "echo CC = \m(cc)",
-   or any other desired way. Interestingly, if we had not needed the sum
-   of the squares and products, we could have obtained the sums, maxima,
-   and minima of the X's and Y's without a loop like this:
-
-  (setq xsum (+ \fjoin(&x)) ysum (+ \fjoin(&y)))
-  (setq xmax (max \fjoin(&x)) ymax (max \fjoin(&y)))
-  (setq xmin (min \fjoin(&x)) ymin (min \fjoin(&y)))
-
-   Any Kermit function that returns numbers or lists of numbers can be
-   included in an S-Expression as an operand.
-     _________________________________________________________________
-
-    9.9.2. Practical Fibonacci Series
-
-   The recursive Fibonacci example given previously is simple and
-   elegant, but not very useful since it causes memory occupation to grow
-   each time it calls itself, until eventually both physical memory and
-   disk swap space are filled and the program crashes. Even for small
-   arguments, like 17, execution time can be prohibitive:
-
-  (setq t1 \v(ftime))
-  (setq result (fibonacci 17))
-  (setq t2 (- \v(ftime) t1))
-  echo FIBONACCI(17) = \m(result): TIME = \ffpround(t2,3)
-
-   prints (on a certain rather slow computer):
-
-  FIBONACCI(17) = 1597: TIME = 5.861
-
-   Any recursive function can be recoded iteratively. The result is not
-   as pretty, but execution is far less expensive:
-
-    define FIBITER {
-        (if (== \%3 0) (\%2) (fibiter (+ \%1 \%2) \%1 (- \%3 1)))
-    }
-    define FIBONACCI {
-        (fibiter 1 0 \%1)
-    }
-
-   Here's the result on the same computer for the same argument of 17:
-
-  FIBONACCI(17) = 1597: TIME = 0.015
-
-   (47 times faster.) Execution time increases proportionally to the size
-   of the argument in the iterative case, whereas in the recursive case
-   it goes up geometrically, quickly reaching infinity.
-
-   [ [529]Top ] [ [530]Contents ] [ [531]C-Kermit Home ] [ [532]Kermit
-   Home ]
-     _________________________________________________________________
-
-  9.10. Differences from Algebraic Notation
-
-   In C-Kermit:
-
-     * Algebraic notation uses infix operators and normal rules of
-       operator precedence, with parentheses used to force exceptions to
-       the rules; many operations can be included in an expression.
-       S-Expressions use prefix operators with no intrinsic precedence;
-       each operation is enclosed in parentheses, and the arrangement of
-       parentheses determines precedence.
-     * Algebraic infix operators require two operands; S-Expression
-       prefix operators can accept a variable number of operands.
-     * You can use algebraic notation anywhere that C-Kermit accepts a
-       number, e.g. "echo \&a[((1+1)*2-1]", but you can use S-Expressions
-       only as top-level commands. You can, however, use either algebraic
-       or S-Expressions anywhere at all by enclosing them in \fevaluate()
-       or \fsexpression(), respectively.
-     * You can use any mixture of integer and floating-point numbers in
-       S-Expressions, but only integers are permitted in algebraic
-       expressions. Outside of S-Expressions, floating point arithmetic
-       is supported only by \ffp...() function calls.
-     * Operators and operands in S-Expressions must be separated by
-       spaces, e.g. "(+ a b)". Spaces are not required in algebraic
-       expressions: "((a+b)*c)".
-     * When assigning values to backslash variables (such as \%x or
-       \&a[2]) using SETQ or LET, you must double the backslash.
-
-   [ [533]Top ] [ [534]Contents ] [ [535]C-Kermit Home ] [ [536]Kermit
-   Home ]
-     _________________________________________________________________
-
-  9.11. Differences from Lisp
-
-     * Kermit has a lot of built-in operators not found in Lisp: ++, ^,
-       etc.
-     * Most dialects of real Lisp do not allow S-Expressions that don't
-       start with an operator, for example:
-  (a)
-       This expression can cause an error in Lisp (even if "a" has a
-       value), but is acceptable in Kermit, where it returns the value of
-       the variable "a". Similarly, (1) returns the value "1".
-     * In real Lisp, EVAL requires exactly one operand. In Kermit, it can
-       have 0, 1, 2, or more operands. It returns the value of the last
-       operand evaluated.
-     * Real Lisp SETQ and LET usually require an even number of operands.
-       Kermit allows an odd number, in which case the last (or only)
-       variable is undefined (i.e. deleted, destroyed).
-     * Kermit does not support ratios such as "7/8". Some Lisp dialects
-       accept ratios as numbers, and generate ratios when told to divide
-       two integers whose quotient is not a whole number; e.g. in Common
-       Lisp:
-  [13] USER(37): (/ (+ 1 2 3 4) 3)
-  10/3
-  [13] USER(38):
-     * The result of (/ 10 3) is 3.333.... Some Lisp dialects truncate
-       the result to 3 since both operands are integers, some don't; some
-       give the result as a ratio. C-Kermit always gives a floating point
-       result when there is a fractional part. If you want an integer
-       result, you can use TRUNCATE, FLOOR, or CEILING, e.g. (truncate (/
-       10 3)).
-     * There is currently no "bignum" support. Large numbers can be used
-       and large results generated, but (as noted in [537]Section 9.2)
-       they are accurate only to the precision of the underlying machine.
-       \v(math_precision) gives the machine precision as a number of
-       decimal digits, e.g. 16.
-     * Scientific notation for floating-point numbers is not supported.
-       If the magnitude of a number is greater than the precision of the
-       underlying hardware, the less-significant digits are shown but
-       their values are meaningless. If it the number is too small to be
-       represented internally, it is shown as "0.0".
-     * Many Lisp features are omitted: List processing (CAR, CDR, etc),
-       DEFUN, Lisp-specific control structures, and so on.
-
-   [ [538]Top ] [ [539]Contents ] [ [540]C-Kermit Home ] [ [541]Kermit
-   Home ]
-  __________________________________________________________________________
-
-10. FILE TRANSFER
-
-   New commands and switches:
-
-   SET TRANSFER REPORT { OFF, ON }
-          Enables or disables the (new) one-line message printed by
-          Kermit after a remote-mode file transfer to indicate the source
-          and destination file, complete with path, to let you know where
-          the file went.
-
-   SEND /TYPE:{TEXT,BINARY}
-          Sends only files of the given type (see [542]Section 4).
-
-   SEND /NOFOLLOWLINKS:
-          (UNIX only) Skip over symbolic links rather than following them
-          (default). This applies to wildcard and/or recursive SENDs; if
-          a single filename is given, and it happens to be a symbolic
-          link, the file it points to is sent.
-
-   SEND /FOLLOWLINKS:
-          (UNIX only) Follow (resolve) symbolic links. Watch out for
-          circular links, endless loops, etc.
-
-   SET SEND I-PACKETS { OFF, ON }
-          When sending commands to a Kermit server, this tells whether
-          command packets should be preceded by an I (information)
-          packet, which is used to synchronize parameters prior to
-          executing the command. Normally ON. The only reason to set this
-          OFF is for communicating with buggy Kermit servers that
-          misbehave when an I packet is sent to them. There is also a SET
-          RECEIVE I-PACKETS command, but presently it has no effect.
-
-   SET TRANSFER MESSAGE [ text ]
-          Sets an initial message to be shown in the Last Message field
-          of the fullscreen file-transfer display.
-
-   SET TRANSFER TRANSLATION { ON, OFF }
-          Inhibits or re-enables text-file transfer character-set
-          translation globally.
-
-   { SEND, MSEND, GET, RECEIVE } /TRANSPARENT
-          Inhibits character-set translation for this transfer only.
-
-   { GET, RECEIVE } /PIPES:{ON,OFF}
-          Overrides global TRANSFER PIPES setting for this transfer only;
-          ON allows incoming files with names like "!tar xf -" to be
-          opened as pipelines rather than regular files.
-
-   The following new "hot keys" are available when Kermit's file-transfer
-   display is visible:
-
-     D: Turn on debugging, open "debug.log" if not already open.
-     d: Turn off debugging but leave log open (if it was open).
-     T: Turn on debug-log timestamps.
-     t: Turn off debug-log timestamps.
-
-   Other improvements:
-     * SET FILE DOWNLOAD-DIRECTORY now works for external protocols (e.g.
-       sz/rz) too.
-     * Improved automatic per-file text/binary switching, described in
-       [543]Section 4.
-     * When sending a file group (e.g. "send *.*"), failure to open a
-       file is no longer fatal; now C-Kermit simply goes ahead to the
-       next file.
-     * Transaction log entries are now made for external protocols too.
-
-   [ [544]Top ] [ [545]Contents ] [ [546]C-Kermit Home ] [ [547]Kermit
-   Home ]
-  __________________________________________________________________________
-
-11. MODEMS AND DIALING
-
-   In C-Kermit 8.0, the default modem type for dialing has changed from
-   NONE (= DIRECT, meaning no modem) to GENERIC. This change should have
-   no impact on direct connections. For dialing, it means that, unless
-   you SET MODEM TYPE to a specific type, such as USROBOTICS or CONEXANT,
-   Kermit assumes:
-
-    1. The modem uses the Hayes AT command set.
-    2. The modem supports error correction, data compression, and
-       hardware flow control and is already configured to use them.
-
-   In fact, Kermit assumes the modem is completely configured, and
-   therefore does not send it an initialization string or any
-   configuration commands. Instead, it sends only the simplest and most
-   portable commands:
-
-     ATQ0V1          Give dial result codes.
-     ATDTnumber      Dial the number.
-
-   (or ATD or ATDP, as appropriate).
-
-   The new defaults work for direct connections and for most modern
-   modems on most platforms, and they work much faster than
-   "full-treatment" dialing. If the new defaults don't work for you, or
-   if you need to perform explicit modem configuations or interactions,
-   then set a specific modem type and use the SET MODEM and SET DIAL
-   commands as documented in Using C-Kermit.
-
-     WARNING: Don't use the generic modem on hosts that do not support
-     RTS/CTS flow control. If Xon/Xoff is in use on the serial port,
-     you'll need to select a particular modem type so Kermit knows what
-     command to give it to enable Xon/Xoff flow control between itself
-     and your serial port.
-
-   The following new modem types were added in C-Kermit 8.0:
-
-     lucent:          Lucent Venus chipset
-     pctel:           PCTel V.90 chipset
-     conexant:        Conexant (ex-Rockwell) modem family
-     zoom-v32bis:     New name for "Zoom"
-     zoom-v34         Zoom V.34
-     zoom-v90         Zoom V.90 56K
-     zoom-v92:        Zoom V.92 with V.44 data compression
-     zoltrix-v34:     New name for "zoltrix"
-     zoltrix-hsp-v90: Synonym for PCTel
-     zoltrix-hcf-v90: Synonym for ITU-T-V250
-     smartlink-v90:   Synonym for usrobotics (same chipset)
-     acer-v90:        Synonym for Rockwell-v90
-
-   New DIAL-related variables:
-
-     \v(dm_hf):  Dial modifier: Wait for Hook-Flash.
-     \v(dm_wb):  Dial modifier: Wait for Bong.
-
-   Finally, if dialing fails, Kermit now prints a context-sensitive hint
-   suggesting possible reasons and remedies.
-
-   Added in C-Kermit 8.0.201:   Rudimentary support for Caller ID, for
-   use with the ANSWER command. If the modem reports Caller ID
-   information, Kermit stores it in variables that you can access after
-   the call is answered:
-
-  \v(callid_date)   The date of the call
-  \v(callid_time)   The time of the call
-  \v(callid_name)   The name of the caller
-  \v(callid_nmbr)   The telephone number of the caller
-  \v(callid_mesg)   A message
-
-   The format of these items depends on the originating and answering
-   phone companies and the modems and their configuration.
-
-   Not very many modems support Caller ID, and those that do (a) tend to
-   have it disabled by default, and (b) use different commands to enable
-   it. A quick survey shows of some current models shows:
-
-   - USR V.90:      No
-   - ITU-T V.250:   No
-   - Lucent Venus:  No
-   - Diamond Supra: #CID=1
-   - Rockwell 56K:  #CID=1
-   - PCTEL:         #CID=1
-   - Zoltrix:       +VCID=1
-   - Conexant:      +VCID=1
-
-   To use Kermit's Caller ID feature, you have to set the modem to wait
-   for at least two rings before answering, and you have to give the
-   command to enable Caller ID; for example (after choosing a modem with
-   SET MODEM TYPE):
-
-  set modem command autoanswer on ATS0=2#CID=1\{13}
-  set modem command autoanswer on ATS0=2+VCID=1\{13}
-
-   These commands can be undone with:
-
-  set modem command autoanswer on ATS0=1#CID=0\{13}
-  set modem command autoanswer on ATS0=1+VCID=0\{13}
-
-   Kermit presently has no built-in knowledge of the Caller ID
-   capabilities or commands of the modems in its database.
-
-   Since the variables can be accessed only after the call is answered,
-   the only way to refuse a call is to answer it, inspect the variables,
-   and then hang it up if desired.
-
-   [ [548]Top ] [ [549]Contents ] [ [550]C-Kermit Home ] [ [551]Kermit
-   Home ]
-  __________________________________________________________________________
-
-12. TERMINAL CONNECTION
-
-   Now that 7-bit connections are no longer the norm, the default
-   terminal bytesize (also called "data size" or "word size") in C-Kermit
-   8.0 is 8 bits, rather than 7 bits as it was in C-Kermit 7.0 and
-   earlier:
-
-   SET ESCAPE character
-          This command, which specifies your CONNECT-mode escape
-          character, allows you to specify any ASCII control character in
-          a variety of formats. C-Kermit 8.0.201 now also lets you
-          specify any 8-bit value, 128-255, as the escape character. In
-          the SET ESCAPE command, you can type the 8-bit character
-          literally or you can enter its numeric code. Here are examples
-          that you can enter from a terminal or console that uses the ISO
-          Latin-1 character set:
-
-  C-Kermit> set escape Ãƒ
-  C-Kermit> set escape 195
-  C-Kermit> show escape
-   Escape character: Code 195 (Ã): enabled
-  C-Kermit>
-
-          Both of these commands set the escape character value to 195
-          (decimal), which happens to be uppercase letter A with Tilde in
-          Latin-1. SHOW ESCAPE and SHOW TERMINAL show the value, as does
-          the CONNECT message.
-
-   SET TERMINAL AUTODOWNLOAD ERROR { STOP, CONTINUE }
-          When Kermit has a terminal connection to another computer, and
-          a file transfer is initiated automatically because a Kermit
-          packet was received in CONNECT mode (i.e. in the terminal
-          screen), this command tells what Kermit should do if the
-          transfer fails. The default is to STOP, which leaves Kermit in
-          command mode with its file-transfer display showing, so you can
-          see that the transfer failed and why. If you SET TERMINAL
-          AUTODOWNLOAD ERROR CONTINUE, this causes Kermit to return
-          automatically to its terminal screen (i.e. resume its CONNECT
-          session) as if the transfer had succeeded; this can be
-          desirable if the entire session is under control of a
-          host-based script.
-
-   SET TERMINAL BYTESIZE { 7, 8 }
-          The byte size to use during CONNECT and INPUT command
-          execution, which can be more restrictive than the bytesize
-          implied by the current PARITY setting, but not less
-          restrictive. In C-Kermit 7.0 and earlier, the terminal bytesize
-          was 7 by default to protect against the likelihood that parity
-          was in use on the connection without the user's knowledge. When
-          the terminal bytesize is 8 (as it is in C-Kermit 8.0 and
-          later), the user will see garbage in this (increasingly
-          unlikely) situation. Note that 8 data bits are required for
-          most character sets other than ASCII: Latin-1, UTF-8, and so
-          on.
-
-   A new command has been added to produce timestamped session logs:
-
-   SET TERMINAL SESSION-LOG TIMESTAMPED-TEXT
-          Records the terminal session in text mode (like SET TERMINAL
-          SESSION-LOG TEXT) but adds a timestamp at the beginning of each
-          line. The timestamp format is hh:mm:ss.nnn, and indicates the
-          time at which the first character of the line appeared.
-
-   In most UNIX versions (those built with the select()-capable CONNECT
-   module -- pretty much all the ones that have or could have TELNET
-   included), an idle timeout feature has been added:
-
-   SET TERMINAL IDLE-TIMEOUT number
-          If the number is not 0, then Kermit is to take an action when
-          the given amount of time passes with no activity during CONNECT
-          mode. If the number is positive it is the maximum number of
-          idle seconds; if number is negative it represents milliseconds
-          (thousandths of seconds). If 0 is given as the number, there
-          are no idle timeouts. Synonym: SET TERMINAL IDLE-LIMIT.
-
-   SET TERMINAL IDLE-ACTION { RETURN, HANGUP, EXIT, OUTPUT [ string ] }
-          The action to be taken upon an idle timeout in CONNECT mode.
-          RETURN to the prompt, HANGUP the connection, EXIT from Kermit,
-          or OUTPUT the given string (if no string is given, a NUL (ASCII
-          0) character is sent).
-
-   SET TERMINAL IDLE-ACTION { TELNET-NOP, TELNET-AYT }
-          Actions that can be selected on Telnet connections only, that
-          might be useful if idle limits are enforced by the Telnet
-          server or in the TCP/IP protocol: TELNET-NOP sends a "NO
-          Operation" (do-nothing) command, which causes no response from
-          the server; TELNET-AYT sends an "Are You There" message to the
-          server, which should make the server send back a message.
-          Neither of these actions interferes with your remote session.
-
-   SET TERMINAL IDLE-ACTION is useful for connections to hosts or
-   services that automatically log you out after a certain amount of idle
-   time, e.g.:
-
-  set term idle-timeout 300
-  set term idle-action output \32
-
-   sends a space (as if you had pressed the space bar) every 300 seconds
-   (five minutes) while there is no activity (32 is the ASCII code for
-   space).
-
-   When C-Kermit returns from CONNECT to command mode, the reason for the
-   transition is given in a new variable, \v(cx_status):
-
-      0  No CONNECT command given yet.
-      1  User escaped back manually.
-      2  A trigger string was encountered.
-      3  IKSD entered server mode.
-      4  Application Program Command received from host.
-      5  Idle timeout.
-      6  Telnet protocol error.
-      7  Keystroke macro.
-      8  Time limit exceeded.
-    100  Internal error.
-    101  Carrier required by not detected.
-    102  I/O error on connection.
-    103  Disconnected by host.
-    104  Disconnected by user.
-    105  Session limit exceeded.
-    106  Rejected due to Telnet policy.
-    107  Received kill signal.
-
-   Values 100 and above indicate there is no connection.
-
-   [ [552]Top ] [ [553]Contents ] [ [554]C-Kermit Home ] [ [555]Kermit
-   Home ]
-  __________________________________________________________________________
-
-13. CHARACTER SETS
-
-   See the section on [556]file scanning above, and the section on
-   character-set conversion in [557]FTP. Also:
-
-     * True support for CP1252 (rather than treating it as Latin-1).
-     * Proper handling of C1 values when converting ISO 8-bit text to
-       UTF-8.
-     * TYPE /CHARACTER-SET: /TRANSLATE-TO: allows specific translations.
-     * The TRANSLATE command now works on multiple files.
-     * K_CHARSET environment variable to set the file character-set.
-     * SET TRANSFER TRANSLATION OFF.
-     * FTP client character-set translation ([558]Section 3.7).
-
-   [ [559]Top ] [ [560]Contents ] [ [561]C-Kermit Home ] [ [562]Kermit
-   Home ]
-  __________________________________________________________________________
-
-14. DIALOUT FROM TELNET TERMINAL SERVERS
-
-   For years, C-Kermit has supported dialing out from Telnet modem
-   servers (also called reverse terminal servers or access servers), but
-   until now there was no way for Kermit to control the communication
-   parameters (speed, parity, etc) on the serial port of the terminal
-   server; it had to use whatever was there.
-
-   But now, if you make a connection to a server that supports the Telnet
-   Com Port Control Option, [563]RFC 2217, you have the same degree of
-   control as you would have over a serial port on the computer where
-   Kermit is running: SET SPEED, SET FLOW, SET PARITY, SET STOP-BITS,
-   SHOW COMM, WAIT, SET CARRIER-WATCH, the modem-signal variables,
-   sending Break, and so on, apply to the connection between the terminal
-   server and the modem.
-
-   For example, using a Cisco Access Server 2509, where specifying a TCP
-   port in the 6000's selects a serial port that can be used for dialing
-   out:
-
-  set host xxx 6001      ; xxx is the IP hostname or address of the server
-  (log in if necessary)  ; With a script or by hand
-  set modem type usr     ; Tell Kermit what kind of modem it has
-  set speed 57600        ; This affects the server's port
-  set flow rts/cts       ; Ditto
-  dial 7654321
-
-   The modem server might or might not require a login sequence. It might
-   also allow for automatic authentication, e.g. via Kerberos tickets.
-   NOTE: If the modem server requires a login sequence, then REDIAL might
-   not work as expected.
-
-   When you have a Telnet Com Port connection, your SET SPEED and SET
-   FLOW options change automatically to reflect the capabilities of the
-   server, rather than those of your local computer.
-
-   See the configuration manual for your server for additional
-   information. For example, how to set up the server to drop the Telnet
-   connection automatically when the telephone call is hung up (e.g.
-   "autohangup" on Cisco models).
-
-   For a Linux-based Telnet Com-Port server, click the Srdird link:
-
-   [ [564]Top ] [ [565]Contents ] [ [566]Sredird ] [ [567]C-Kermit Home ]
-   [ [568]Kermit Home ]
-  __________________________________________________________________________
-
-15. COPING WITH BROKEN KERMIT PARTNERS
-
-   There are lots of faulty Kermit protocol implementations out there,
-   found mainly in 3rd-party products ranging from communications
-   software packages to file-transfer functions imbedded within devices.
-   This topic is covered [569]HERE for C-Kermit 7.0, but C-Kermit 8.0
-   adds some additional tricks.
-
-   SET ATTRIBUTE RECORD-FORMAT { ON, OFF }
-          Allows control of the Kermit's Record-Format attribute. Set
-          this to OFF in case incoming file are refused due to unknown or
-          invalid record formats if you want to accept the file anyway.
-
-   SET SEND I-PACKETS { ON, OFF }
-          A Kermit server is supposed to accept I-packets; this is how
-          the client lets the server know its capabilities and
-          preferences before sending a command. Apparently there is at
-          least one Kermit server implementation that does not accept
-          I-packets, and does not properly respond with an Error packet
-          if it gets one. To get around such situations in C-Kermit 8.0,
-          you can use SET SEND I-PACKETS OFF to inhibit the sending of I
-          packets. In this case, the client must be able to adjust to the
-          server's configuration, rather than the other way around as we
-          are used to.
-
-   SET PROTOCOL KERMIT {} {} {}
-          C-Kermit 6.0 and later automatically send "autoupload" and
-          "autodownload" commands when in local mode and you give a file
-          transfer command. For example, if you tell kermit to "send
-          oofa.txt", Kermit sends "kermit -r" and a carriage return, in
-          case you had forgotten to start Kermit on the far end and told
-          it to receive a file. If a Kermit program had already been
-          started on the far end, it should harmlessly absorb this
-          string. However, some Kermit programs violate the Kermit
-          protocol definition and treat such strings as Kermit packets
-          even though they are not. In such cases, give this command to
-          set the Kermit protocol autoupload and download strings to
-          nothing, which tells Kermit not to send them. (This is not a
-          new feature, but it was not previously included in the "Coping"
-          section of the documentation.)
-
-   [ [570]Top ] [ [571]Contents ] [ [572]C-Kermit Home ] [ [573]Kermit
-   Home ]
-  __________________________________________________________________________
-
-16. NEW COMMAND-LINE OPTIONS
-
-   kermit -h Now prints a complete listing of its command-line options,
-   rather than an abbreviated list squeezed into a 24x80 space.
-
-   -dd              Debug, like -d but adds timestamps
-   --version  Shows C-Kermit version number.
-   --noperms  Equivalent to SET ATTRIBUTE PROTECTION OFF.
-
-   Kermit now accepts a selection of URLs (Universal Resource Locators)
-   as its first command-line argument. These are:
-
-   telnet:hostname
-          Makes a Telnet connection to the given host (IP hostname or
-          address).
-
-   ftp://[user[:password]@]hostname[/path...]
-          Makes an FTP connection to the given host (IP hostname or
-          address). If a username is given, Kermit tries to log you in;
-          if a password is given, it is used; if not, you are prompted
-          for one. If no username is given, an anonymous login is
-          performed. If a pathname is included, Kermit tries to GET the
-          given file. See [574]Section 3.1.3 for details.
-
-   ftps://[user[:password]@]hostname[/path...]
-          Makes a secure FTP connection over SSL.
-
-   telnets://[user[:password]@]hostname
-          Makes a secure Telnet connection over SSL.
-
-   kermit://[user[:password]@]hostname[/path...]
-          Makes a connection to an [575]Internet Kermit Server.
-
-   http://[user[:password]@]hostname[/path...]
-          Makes a connection to Web server.
-
-   https://[user[:password]@]hostname[/path...]
-          Makes a connection to secure Web server.
-
-   [ [576]Top ] [ [577]Contents ] [ [578]C-Kermit Home ] [ [579]Kermit
-   Home ]
-  __________________________________________________________________________
-
-17. LOGS
-
-   In C-Kermit 8.0, we make an effort to keep passwords out of the debug
-   log. This can never be 100% effective, but it's better than before,
-   when there were no precautions at all. Whenever Kermit knows it's
-   prompting for, parsing, or transmitting a password, it temporarily
-   turns off logging and then turns it back on afterwards. This keeps the
-   debug log password-free in most common cases, but there can be no
-   guarantees.
-
-   As noted elsewhere, the new "-dd" command-line option selects a
-   timestamped debug log (equivalent to "set debug timestamps on", "log
-   debug debug.log").
-
-   C-Kermit 8.0 also supports a new timestamped session log via "set
-   session-log timestamped-text", "log session".
-
-   There have been requests for other kinds of logs, for example a
-   command log. These might be added at some point. One person wanted to
-   be able to log commands with timestamps, but only commands issued at
-   the prompt, not commands from files or macros, and also wanted a
-   header line at the beginning showing the date, user, and host. This
-   can be done as follows:
-
-  .filename := \v(home)commands.log  ; (for example)
-  fopen /write \%c \m(filename)
-  if success {
-      fwrite /line \%c \v(date): User=\v(user) Host=\v(host)
-      fclose \%c
-      set debug timestamps on
-      log debug {| grep "CMD(P)" >> \m(filename)} append
-  }
-
-   [ [580]Top ] [ [581]Contents ] [ [582]C-Kermit Home ] [ [583]Kermit
-   Home ]
-     _________________________________________________________________
-
-   C-Kermit 8.0 Update Notes / [584]The Kermit Project / Columbia
-   University / 15 Dec 2003
-
-References
-
-   1. http://www.columbia.edu/kermit/ckermit80.html#contents
-   2. http://www.columbia.edu/kermit/ckermit.html
-   3. http://www.columbia.edu/kermit/index.html
-   4. http://www.columbia.edu/kermit/ckermit80.html
-   5. mailto:kermit-support@columbia.edu
-   6. http://www.columbia.edu/kermit/
-   7. http://www.kermit-project.org/
-   8. http://www.columbia.nyc.ny.us/kermit/
-   9. ftp://kermit.columbia.edu/kermit/f/COPYING.TXT
-  10. ftp://kermit.columbia.edu/kermit/f/ckcmai.c
-  11. http://www.columbia.edu/kermit/ckermit80.html#xv
-  12. http://www.columbia.edu/kermit/ck60manual.html
-  13. http://www.columbia.edu/kermit/ckermi70.html
-  14. ftp://kermit.columbia.edu/kermit/f/ckermit70.txt
-  15. http://www.columbia.edu/kermit/ckututor.html
-  16. ftp://kermit.columbia.edu/kermit/f/ckuker.nr
-  17. http://www.columbia.edu/kermit/security.htm
-  18. http://www.columbia.edu/kermit/telnet.htm
-  19. http://www.columbia.edu/kermit/ftpscripts.html
-  20. http://www.columbia.edu/kermit/ckcbwr.html
-  21. ftp://kermit.columbia.edu/kermit/f/ckcbwr.txt
-  22. http://www.columbia.edu/kermit/ckubwr.html
-  23. ftp://kermit.columbia.edu/kermit/f/ckubwr.txt
-  24. http://www.columbia.edu/kermit/ckvbwr.html
-  25. ftp://kermit.columbia.edu/kermit/f/ckvbwr.txt
-  26. http://www.columbia.edu/kermit/ckuins.html
-  27. ftp://kermit.columbia.edu/kermit/f/ckuins.txt
-  28. http://www.columbia.edu/kermit/ckvins.html
-  29. ftp://kermit.columbia.edu/kermit/f/ckvins.txt
-  30. http://www.columbia.edu/kermit/ckccfg.html
-  31. ftp://kermit.columbia.edu/kermit/f/ckccfg.txt
-  32. http://www.columbia.edu/kermit/ckcplm.html
-  33. ftp://kermit.columbia.edu/kermit/f/ckcplm.txt
-  34. http://www.columbia.edu/kermit/iksd.html
-  35. http://www.columbia.edu/kermit/skermit.html
-  36. http://www.columbia.edu/kermit/ckermit80.html#top
-  37. http://www.columbia.edu/kermit/ckermit.html
-  38. http://www.columbia.edu/kermit/index.html
-  39. http://www.columbia.edu/kermit/ckermit80.html#x0
-  40. http://www.columbia.edu/kermit/ckermit80.html#x1
-  41. http://www.columbia.edu/kermit/ckermit80.html#x2
-  42. http://www.columbia.edu/kermit/ckermit80.html#x2.1
-  43. http://www.columbia.edu/kermit/ckermit80.html#x2.2
-  44. http://www.columbia.edu/kermit/ckermit80.html#x2.2.1
-  45. http://www.columbia.edu/kermit/ckermit80.html#x2.2.2
-  46. http://www.columbia.edu/kermit/ckermit80.html#x2.2.3
-  47. http://www.columbia.edu/kermit/ckermit80.html#x2.2.4
-  48. http://www.columbia.edu/kermit/ckermit80.html#x2.2.5
-  49. http://www.columbia.edu/kermit/ckermit80.html#x2.2.6
-  50. http://www.columbia.edu/kermit/ckermit80.html#x3
-  51. http://www.columbia.edu/kermit/ckermit80.html#x3.1
-  52. http://www.columbia.edu/kermit/ckermit80.html#x3.1.1
-  53. http://www.columbia.edu/kermit/ckermit80.html#x3.1.2
-  54. http://www.columbia.edu/kermit/ckermit80.html#x3.1.3
-  55. http://www.columbia.edu/kermit/ckermit80.html#x3.1.4
-  56. http://www.columbia.edu/kermit/ckermit80.html#x3.2
-  57. http://www.columbia.edu/kermit/ckermit80.html#x3.3
-  58. http://www.columbia.edu/kermit/ckermit80.html#x3.4
-  59. http://www.columbia.edu/kermit/ckermit80.html#x3.5
-  60. http://www.columbia.edu/kermit/ckermit80.html#x3.5.1
-  61. http://www.columbia.edu/kermit/ckermit80.html#x3.5.2
-  62. http://www.columbia.edu/kermit/ckermit80.html#x3.5.3
-  63. http://www.columbia.edu/kermit/ckermit80.html#x3.6
-  64. http://www.columbia.edu/kermit/ckermit80.html#x3.6.1
-  65. http://www.columbia.edu/kermit/ckermit80.html#x3.6.2
-  66. http://www.columbia.edu/kermit/ckermit80.html#x3.6.3
-  67. http://www.columbia.edu/kermit/ckermit80.html#x3.7
-  68. http://www.columbia.edu/kermit/ckermit80.html#x3.7.1
-  69. http://www.columbia.edu/kermit/ckermit80.html#x3.7.2
-  70. http://www.columbia.edu/kermit/ckermit80.html#x3.8
-  71. http://www.columbia.edu/kermit/ckermit80.html#x3.9
-  72. http://www.columbia.edu/kermit/ckermit80.html#x3.10
-  73. http://www.columbia.edu/kermit/ckermit80.html#x3.10.1
-  74. http://www.columbia.edu/kermit/ckermit80.html#x3.10.2
-  75. http://www.columbia.edu/kermit/ckermit80.html#x3.10.3
-  76. http://www.columbia.edu/kermit/ckermit80.html#x3.11
-  77. http://www.columbia.edu/kermit/ckermit80.html#x4
-  78. http://www.columbia.edu/kermit/ckermit80.html#x5
-  79. http://www.columbia.edu/kermit/ckermit80.html#x6
-  80. http://www.columbia.edu/kermit/ckermit80.html#x6.1
-  81. http://www.columbia.edu/kermit/ckermit80.html#x6.2
-  82. http://www.columbia.edu/kermit/ckermit80.html#x6.3
-  83. http://www.columbia.edu/kermit/ckermit80.html#x6.4
-  84. http://www.columbia.edu/kermit/ckermit80.html#x6.5
-  85. http://www.columbia.edu/kermit/ckermit80.html#x6.6
-  86. http://www.columbia.edu/kermit/ckermit80.html#x7
-  87. http://www.columbia.edu/kermit/ckermit80.html#x8
-  88. http://www.columbia.edu/kermit/ckermit80.html#x8.1
-  89. http://www.columbia.edu/kermit/ckermit80.html#x8.2
-  90. http://www.columbia.edu/kermit/ckermit80.html#x8.3
-  91. http://www.columbia.edu/kermit/ckermit80.html#x8.4
-  92. http://www.columbia.edu/kermit/ckermit80.html#x8.5
-  93. http://www.columbia.edu/kermit/ckermit80.html#x8.6
-  94. http://www.columbia.edu/kermit/ckermit80.html#x8.7
-  95. http://www.columbia.edu/kermit/ckermit80.html#x8.8
-  96. http://www.columbia.edu/kermit/ckermit80.html#x8.9
-  97. http://www.columbia.edu/kermit/ckermit80.html#x8.10
-  98. http://www.columbia.edu/kermit/ckermit80.html#x8.11
-  99. http://www.columbia.edu/kermit/ckermit80.html#x8.12
- 100. http://www.columbia.edu/kermit/ckermit80.html#x8.13
- 101. http://www.columbia.edu/kermit/ckermit80.html#x8.14
- 102. http://www.columbia.edu/kermit/ckermit80.html#x9
- 103. http://www.columbia.edu/kermit/ckermit80.html#x9.1
- 104. http://www.columbia.edu/kermit/ckermit80.html#x9.2
- 105. http://www.columbia.edu/kermit/ckermit80.html#x9.3
- 106. http://www.columbia.edu/kermit/ckermit80.html#x9.4
- 107. http://www.columbia.edu/kermit/ckermit80.html#x9.5
- 108. http://www.columbia.edu/kermit/ckermit80.html#x9.6
- 109. http://www.columbia.edu/kermit/ckermit80.html#x9.7
- 110. http://www.columbia.edu/kermit/ckermit80.html#x9.8
- 111. http://www.columbia.edu/kermit/ckermit80.html#x9.9
- 112. http://www.columbia.edu/kermit/ckermit80.html#x9.10
- 113. http://www.columbia.edu/kermit/ckermit80.html#x9.11
- 114. http://www.columbia.edu/kermit/ckermit80.html#x10
- 115. http://www.columbia.edu/kermit/ckermit80.html#x11
- 116. http://www.columbia.edu/kermit/ckermit80.html#x12
- 117. http://www.columbia.edu/kermit/ckermit80.html#x13
- 118. http://www.columbia.edu/kermit/ckermit80.html#x14
- 119. http://www.columbia.edu/kermit/ckermit80.html#x15
- 120. http://www.columbia.edu/kermit/ckermit80.html#x16
- 121. http://www.columbia.edu/kermit/ckermit80.html#x17
- 122. http://www.columbia.edu/kermit/ckermit80.html#top
- 123. http://www.columbia.edu/kermit/ckermit.html
- 124. http://www.columbia.edu/kermit/index.html
- 125. http://www.columbia.edu/kermit/ckuins.html#x5
- 126. http://www.columbia.edu/kermit/ckuins.html
- 127. http://www.columbia.edu/kermit/ckermit80.html#x5
- 128. http://www.columbia.edu/kermit/ckermit80.html#x2.2
- 129. http://www.columbia.edu/kermit/ckermit80.html#contents
- 130. http://www.columbia.edu/kermit/ckermit80.html#x15
- 131. http://www.columbia.edu/kermit/ckermit80.html#x3.7
- 132. http://www.columbia.edu/kermit/ckermit80.html#ftpdates
- 133. http://www.columbia.edu/kermit/ckermit80.html#ftpcheck
- 134. http://www.columbia.edu/kermit/ckermit80.html#ftpnamelist
- 135. http://www.columbia.edu/kermit/ckermit80.html#srvrename
- 136. http://www.columbia.edu/kermit/ckermit80.html#ftpvdir
- 137. http://www.columbia.edu/kermit/ckermit80.html#setftptype
- 138. http://www.columbia.edu/kermit/ckermit80.html#x3.6
- 139. http://www.columbia.edu/kermit/ckermit80.html#x15
- 140. http://www.columbia.edu/kermit/ckermit80.html#x8.7
- 141. http://www.columbia.edu/kermit/ckermit80.html#x2.1
- 142. http://www.columbia.edu/kermit/ckermit80.html#x2.2
- 143. http://www.columbia.edu/kermit/ckermit80.html#x8.14
- 144. http://www.columbia.edu/kermit/ckermit80.html#x8.13
- 145. http://www.columbia.edu/kermit/ckermit80.html#x8.13
- 146. http://www.columbia.edu/kermit/ckututor.html
- 147. http://www.columbia.edu/kermit/ckuins.html
- 148. http://www.columbia.edu/kermit/skermit.html
- 149. http://www.columbia.edu/kermit/ckermit80.html#setlocus
- 150. http://www.columbia.edu/kermit/ckermit80.html#lcommands
- 151. http://www.columbia.edu/kermit/ckermit80.html#ftpuser
- 152. http://www.columbia.edu/kermit/ckermit80.html#showvar
- 153. http://www.columbia.edu/kermit/ckermit80.html#callerid
- 154. http://www.columbia.edu/kermit/ckermit80.html#x6.6
- 155. http://www.columbia.edu/kermit/ckermit80.html#x0
- 156. http://www.columbia.edu/kermit/ckermit80.html#x3.11
- 157. http://www.columbia.edu/kermit/ckermit80.html#top
- 158. http://www.columbia.edu/kermit/ckermit80.html#contents
- 159. http://www.columbia.edu/kermit/ckermit.html
- 160. http://www.columbia.edu/kermit/index.html
- 161. http://www.columbia.edu/kermit/ckermit80.html#x0
- 162. http://www.columbia.edu/kermit/ckermit80.html#top
- 163. http://www.columbia.edu/kermit/ckermit80.html#contents
- 164. http://www.columbia.edu/kermit/ckermit.html
- 165. http://www.columbia.edu/kermit/index.html
- 166. http://www.columbia.edu/kermit/k95.html
- 167. http://www.columbia.edu/kermit/sshclient.html
- 168. http://www.columbia.edu/kermit/skermit.html
- 169. http://www.columbia.edu/kermit/skermit.html
- 170. http://www.columbia.edu/kermit/sshclien.htm
- 171. http://www.columbia.edu/kermit/ckermit80.html#x3
- 172. ftp://ftp.isi.edu/in-notes/rfc1738.txt
- 173. http://www.columbia.edu/kermit/ckermit80.html#x2.2.2
- 174. http://www.columbia.edu/kermit/ckermit80.html#x2.2.1
- 175. ftp://ftp.isi.edu/in-notes/rfc2396.txt
- 176. ftp://ftp.isi.edu/in-notes/rfc2616.txt
- 177. http://www.columbia.edu/kermit/ckermit80.html#x2.2.3
- 178. ftp://ftp.isi.edu/in-notes/rfc2616.txt
- 179. http://www.columbia.edu/kermit/ckermit80.html#x8.13.7
- 180. http://www.columbia.edu/kermit/security.htm#x5.4
- 181. http://www.columbia.edu/kermit/security.htm#x15
- 182. http://www.columbia.edu/kermit/security.htm#x6.2
- 183. http://www.columbia.edu/kermit/security.html
- 184. http://www.columbia.edu/kermit/ckermit80.html#x16
- 185. http://www.columbia.edu/kermit/ckermit80.html#top
- 186. http://www.columbia.edu/kermit/ckermit80.html#contents
- 187. http://www.columbia.edu/kermit/ckermit.html
- 188. http://www.columbia.edu/kermit/index.html
- 189. http://www.columbia.edu/kermit/ckermit80.html#x3.1
- 190. http://www.columbia.edu/kermit/ckermit80.html#x3.2
- 191. http://www.columbia.edu/kermit/ckermit80.html#x3.3
- 192. http://www.columbia.edu/kermit/ckermit80.html#x3.4
- 193. http://www.columbia.edu/kermit/ckermit80.html#x3.5
- 194. http://www.columbia.edu/kermit/ckermit80.html#x3.6
- 195. http://www.columbia.edu/kermit/ckermit80.html#x3.7
- 196. http://www.columbia.edu/kermit/ckermit80.html#x3.8
- 197. http://www.columbia.edu/kermit/ckermit80.html#x3.9
- 198. http://www.columbia.edu/kermit/ckermit80.html#x3.10
- 199. http://www.columbia.edu/kermit/ckermit80.html#x3.11
- 200. http://www.columbia.edu/kermit/security.htm
- 201. http://www.columbia.edu/kermit/security.htm#servers
- 202. http://www.columbia.edu/kermit/ckcsets.html
- 203. http://www.columbia.edu/kermit/unicode.html
- 204. http://www.columbia.edu/kermit/ckermi70.htm#x1.5.4
- 205. http://www.columbia.edu/kermit/case10.html
- 206. http://www.columbia.edu/kermit/ckermit80.html#x4
- 207. http://www.columbia.edu/kermit/ckermit80.html#x3.11
- 208. http://www.columbia.edu/kermit/ftpscripts.html
- 209. http://www.columbia.edu/kermit/ckermit80.html#top
- 210. http://www.columbia.edu/kermit/ckermit80.html#ftp
- 211. http://www.columbia.edu/kermit/ftpclient.html
- 212. http://www.columbia.edu/kermit/ftpscripts.html
- 213. http://www.columbia.edu/kermit/ckermit.html
- 214. http://www.columbia.edu/kermit/index.html
- 215. http://www.columbia.edu/kermit/ckermit80.html#x3.1.1
- 216. http://www.columbia.edu/kermit/ckermit80.html#x3.1.3
- 217. http://www.columbia.edu/kermit/ckermit80.html#x3.1.4
- 218. http://www.columbia.edu/kermit/ckermit80.html#x3.1.3
- 219. http://www.columbia.edu/kermit/ckermit80.html#x3.1.3
- 220. http://www.columbia.edu/kermit/ckermit80.html#x3.2
- 221. http://www.columbia.edu/kermit/ckermit80.html#x3.5
- 222. http://www.columbia.edu/kermit/ckermit80.html#x3.6
- 223. http://www.columbia.edu/kermit/ftpscripts.html
- 224. http://www.columbia.edu/kermit/ckb2.htm
- 225. http://www.columbia.edu/kermit/ckermit80.html#ftpautolog
- 226. http://www.columbia.edu/kermit/ckermit80.html#ftpuser
- 227. http://www.columbia.edu/kermit/ckermit80.html#x3.8
- 228. http://www.columbia.edu/kermit/ckermit80.html#x3.8
- 229. http://www.columbia.edu/kermit/ckermit80.html#top
- 230. http://www.columbia.edu/kermit/ckermit80.html#ftp
- 231. http://www.columbia.edu/kermit/ckermit.html
- 232. http://www.columbia.edu/kermit/index.html
- 233. http://www.columbia.edu/kermit/ibm_ie.html
- 234. http://www.columbia.edu/kermit/ckermit80.html#x3.10
- 235. http://www.columbia.edu/kermit/ckermit80.html#top
- 236. http://www.columbia.edu/kermit/ckermit80.html#ftp
- 237. http://www.columbia.edu/kermit/ckermit.html
- 238. http://www.columbia.edu/kermit/index.html
- 239. http://www.columbia.edu/kermit/ck60manual.html
- 240. http://www.columbia.edu/kermit/ckermit70.html#x4.17
- 241. http://www.columbia.edu/kermit/ckermit70.html
- 242. http://www.columbia.edu/kermit/ckermit80.html#x3.6
- 243. http://www.columbia.edu/kermit/ckermit80.html#x3.11
- 244. http://www.columbia.edu/kermit/ckermit80.html#x3.1.4
- 245. http://www.columbia.edu/kermit/security.html
- 246. http://www.columbia.edu/kermit/ckermit80.html#x3.7
- 247. http://www.columbia.edu/kermit/ckermit80.html#x3.7
- 248. http://www.columbia.edu/kermit/ckermit80.html#x8.13.4
- 249. http://www.columbia.edu/kermit/ckermit80.html#permswitch
- 250. http://www.columbia.edu/kermit/ckermit80.html#ftpchmod
- 251. http://www.columbia.edu/kermit/ckermit80.html#x3.6.2
- 252. http://www.columbia.edu/kermit/ckermit80.html#x4
- 253. http://www.columbia.edu/kermit/ckermit80.html#top
- 254. http://www.columbia.edu/kermit/ckermit80.html#ftp
- 255. http://www.columbia.edu/kermit/ckermit.html
- 256. http://www.columbia.edu/kermit/index.html
- 257. http://www.columbia.edu/kermit/ckermit80.html#x7
- 258. http://www.columbia.edu/kermit/ckermit80.html#x3.8
- 259. http://www.columbia.edu/kermit/ckermit80.html#x3.8
- 260. http://www.columbia.edu/kermit/ckb2.htm
- 261. http://www.columbia.edu/kermit/ckermit80.html#x3.10
- 262. http://www.columbia.edu/kermit/ckermit80.html#x3.10
- 263. http://www.columbia.edu/kermit/ckermit80.html#x3.6
- 264. http://www.columbia.edu/kermit/ckermit80.html#setftptype
- 265. http://www.columbia.edu/kermit/ckermit80.html#top
- 266. http://www.columbia.edu/kermit/ckermit80.html#ftp
- 267. http://www.columbia.edu/kermit/ckermit.html
- 268. http://www.columbia.edu/kermit/index.html
- 269. http://www.columbia.edu/kermit/ckermit70.html#x4.9
- 270. http://www.columbia.edu/kermit/ckermit80.html#x3.5.1
- 271. http://www.columbia.edu/kermit/ckermit80.html#erroraction
- 272. http://www.columbia.edu/kermit/ckermit70.html#x1.5
- 273. http://www.columbia.edu/kermit/ckermit70.html#x4.7
- 274. http://www.columbia.edu/kermit/ckermit70.html#x1.6
- 275. http://www.columbia.edu/kermit/ckermit80.html#x8.13
- 276. http://www.columbia.edu/kermit/ckermi70.htm#x1.5.4
- 277. http://www.columbia.edu/kermit/ckermi70.htm
- 278. http://www.columbia.edu/kermit/ckermit80.html#x4
- 279. http://www.columbia.edu/kermit/ckermit80.html#x3.7
- 280. http://www.columbia.edu/kermit/ckermit80.html#x3.5.2
- 281. http://www.columbia.edu/kermit/ckermit80.html#x3.7
- 282. http://www.columbia.edu/kermit/ckermit80.html#erroraction
- 283. http://www.columbia.edu/kermit/ckermit80.html#x3.5.2
- 284. http://www.columbia.edu/kermit/ckermit80.html#erroraction
- 285. http://www.columbia.edu/kermit/ckermit80.html#ftpfilenames
- 286. http://www.columbia.edu/kermit/ckermit80.html#ftpperms
- 287. http://www.columbia.edu/kermit/ckermit80.html#ftpunique
- 288. http://www.columbia.edu/kermit/ckermit80.html#ftpfilenames
- 289. http://www.columbia.edu/kermit/ckermit80.html#note_utc
- 290. http://www.columbia.edu/kermit/ckermit80.html#note_date
- 291. http://www.columbia.edu/kermit/ckermit80.html#x3.6
- 292. http://www.boulder.nist.gov/timefreq/faq/faq.htm#10:
- 293. http://www.columbia.edu/kermit/ckermit80.html#x3.7
- 294. http://www.columbia.edu/kermit/ckermit80.html#top
- 295. http://www.columbia.edu/kermit/ckermit80.html#ftp
- 296. http://www.columbia.edu/kermit/ckermit.html
- 297. http://www.columbia.edu/kermit/index.html
- 298. http://www.columbia.edu/kermit/ckermit80.html#x3.11
- 299. http://www.columbia.edu/kermit/ckermi70.htm#x4.3
- 300. http://www.columbia.edu/kermit/ckermit70.html
- 301. http://www.columbia.edu/kermit/ckermit80.html#x5
- 302. http://www.columbia.edu/kermit/ckermit80.html#x3.6.3
- 303. http://www.columbia.edu/kermit/ckermit80.html#ftpfilenames
- 304. http://www.columbia.edu/kermit/ckermi70.htm#x4.1
- 305. http://www.columbia.edu/kermit/ckermi70.htm#x4.2.2
- 306. http://www.columbia.edu/kermit/ckermi70.htm#x1.5.4
- 307. http://www.columbia.edu/kermit/ckermit80.html#x3.6.2
- 308. http://www.columbia.edu/kermit/ckermit80.html#x3.11
- 309. http://www.columbia.edu/kermit/ckermit80.html#x3.11
- 310. http://www.columbia.edu/kermit/ckermit80.html#srvrename
- 311. http://www.columbia.edu/kermit/ckermi70.htm#x4.1
- 312. http://www.columbia.edu/kermit/ckermi70.htm
- 313. http://www.columbia.edu/kermit/ckb2.htm
- 314. http://www.columbia.edu/kermit/ckermit80.html#ftpfilenames
- 315. http://www.columbia.edu/kermit/ckermit80.html#x3.5.3
- 316. http://www.proftpd.net/
- 317. http://www.columbia.edu/kermit/ckermit80.html#top
- 318. http://www.columbia.edu/kermit/ckermit80.html#ftp
- 319. http://www.columbia.edu/kermit/ckermit.html
- 320. http://www.columbia.edu/kermit/index.html
- 321. http://www.columbia.edu/kermit/ckb2.htm
- 322. http://www.columbia.edu/kermit/ckcsets.html
- 323. http://www.columbia.edu/kermit/unicode.html
- 324. http://www.columbia.edu/kermit/ckcsets.html
- 325. http://www.columbia.edu/kermit/ckcsets.html
- 326. http://www.columbia.edu/kermit/ckermit80.html#x4
- 327. http://www.columbia.edu/kermit/utf8.html
- 328. http://www.columbia.edu/kermit/ckcsets.html
- 329. http://www.columbia.edu/kermit/ckermit80.html#x4
- 330. ftp://ftp.isi.edu/in-notes/rfc2640.txt
- 331. http://www.columbia.edu/kermit/ckermit80.html#top
- 332. http://www.columbia.edu/kermit/ckermit80.html#ftp
- 333. http://www.columbia.edu/kermit/ckermit.html
- 334. http://www.columbia.edu/kermit/index.html
- 335. http://www.columbia.edu/kermit/ckermit80.html#top
- 336. http://www.columbia.edu/kermit/ckermit80.html#ftp
- 337. http://www.columbia.edu/kermit/ckermit.html
- 338. http://www.columbia.edu/kermit/index.html
- 339. http://www.columbia.edu/kermit/ckermit80.html#top
- 340. http://www.columbia.edu/kermit/ckermit80.html#ftp
- 341. http://www.columbia.edu/kermit/ckermit.html
- 342. http://www.columbia.edu/kermit/index.html
- 343. http://www.columbia.edu/kermit/ftpscripts.html
- 344. http://www.columbia.edu/kermit/ckermit80.html#x3.2
- 345. http://www.columbia.edu/kermit/ckermit80.html#x3.2
- 346. ftp://ftp.isi.edu/in-notes/rfc959.txt
- 347. http://www.columbia.edu/kermit/ckscripts.html
- 348. http://www.columbia.edu/kermit/ckermit80.html#top
- 349. http://www.columbia.edu/kermit/ckermit80.html#ftp
- 350. http://www.columbia.edu/kermit/ftpscript.html
- 351. http://www.columbia.edu/kermit/ckermit.html
- 352. http://www.columbia.edu/kermit/index.html
- 353. http://www.columbia.edu/kermit/ckermit80.html#x3.11.1
- 354. http://www.columbia.edu/kermit/ckermit80.html#x3.11.2
- 355. http://www.columbia.edu/kermit/ckermit80.html#x3.11.3
- 356. http://www.columbia.edu/kermit/ckermit80.html#x3.11.4
- 357. http://www.columbia.edu/kermit/ckermit80.html#x3.11.5
- 358. http://www.columbia.edu/kermit/ckermit.html
- 359. http://www.columbia.edu/kermit/k95.html
- 360. http://www.columbia.edu/kermit/ckermit80.html#x3.11.5
- 361. ftp://ftp.isi.edu/in-notes/rfc959.txt
- 362. ftp://ftp.isi.edu/in-notes/rfc2389.txt
- 363. http://www.ietf.org/internet-drafts/draft-ietf-ftpext-mlst-16.txt
- 364. http://www.columbia.edu/kermit/ftpclient.html
- 365. http://www.columbia.edu/kermit/ckermit80.html#top
- 366. http://www.columbia.edu/kermit/ckermit80.html#ftp
- 367. http://www.columbia.edu/kermit/ckermit.html
- 368. http://www.columbia.edu/kermit/index.html
- 369. http://www.columbia.edu/kermit/ckermit80.html#x3
- 370. http://www.columbia.edu/kermit/ckermit80.html#ucs2
- 371. http://www.columbia.edu/kermit/ckermit80.html#top
- 372. http://www.columbia.edu/kermit/ckermit80.html#contents
- 373. http://www.columbia.edu/kermit/ckermit.html
- 374. http://www.columbia.edu/kermit/index.html
- 375. http://www.columbia.edu/kermit/ckermit80.html#top
- 376. http://www.columbia.edu/kermit/ckermit80.html#contents
- 377. http://www.columbia.edu/kermit/ckermit.html
- 378. http://www.columbia.edu/kermit/index.html
- 379. http://www.columbia.edu/kermit/ckb2.htm
- 380. http://www.columbia.edu/kermit/ckermit80.html#top
- 381. http://www.columbia.edu/kermit/ckermit80.html#contents
- 382. http://www.columbia.edu/kermit/ckermit.html
- 383. http://www.columbia.edu/kermit/index.html
- 384. http://www.columbia.edu/kermit/ckermit80.html#x4
- 385. http://www.columbia.edu/kermit/ckermit80.html#x4
- 386. http://www.columbia.edu/kermit/ckermit80.html#x8.12
- 387. http://www.columbia.edu/kermit/ckermit80.html#x8.1
- 388. http://www.columbia.edu/kermit/ckermit80.html#x12
- 389. http://www.columbia.edu/kermit/ckermit80.html#x8.12
- 390. http://www.columbia.edu/kermit/ckermit80.html#top
- 391. http://www.columbia.edu/kermit/ckermit80.html#contents
- 392. http://www.columbia.edu/kermit/ckermit.html
- 393. http://www.columbia.edu/kermit/index.html
- 394. http://www.columbia.edu/kermit/ckermit80.html#x8.14
- 395. http://www.columbia.edu/kermit/ckermit80.html#top
- 396. http://www.columbia.edu/kermit/ckermit80.html#contents
- 397. http://www.columbia.edu/kermit/ckermit.html
- 398. http://www.columbia.edu/kermit/index.html
- 399. http://www.columbia.edu/kermit/ckermit80.html#x9
- 400. http://www.columbia.edu/kermit/ckermit80.html#top
- 401. http://www.columbia.edu/kermit/ckermit80.html#contents
- 402. http://www.columbia.edu/kermit/ckermit.html
- 403. http://www.columbia.edu/kermit/index.html
- 404. http://www.columbia.edu/kermit/ckermit80.html#x8.6
- 405. http://www.columbia.edu/kermit/ckermit80.html#top
- 406. http://www.columbia.edu/kermit/ckermit80.html#contents
- 407. http://www.columbia.edu/kermit/ckermit.html
- 408. http://www.columbia.edu/kermit/index.html
- 409. http://www.columbia.edu/kermit/ckermit80.html#top
- 410. http://www.columbia.edu/kermit/ckermit80.html#contents
- 411. http://www.columbia.edu/kermit/ckermit.html
- 412. http://www.columbia.edu/kermit/index.html
- 413. http://www.columbia.edu/kermit/ckermit80.html#top
- 414. http://www.columbia.edu/kermit/ckermit80.html#contents
- 415. http://www.columbia.edu/kermit/ckermit.html
- 416. http://www.columbia.edu/kermit/index.html
- 417. http://www.columbia.edu/kermit/ckermit80.html#fjoin
- 418. http://www.columbia.edu/kermit/ckermit80.html#fsplit
- 419. http://www.columbia.edu/kermit/ckermit80.html#x8.10
- 420. http://www.columbia.edu/kermit/ckermit80.html#top
- 421. http://www.columbia.edu/kermit/ckermit80.html#contents
- 422. http://www.columbia.edu/kermit/ckermit.html
- 423. http://www.columbia.edu/kermit/index.html
- 424. http://www.columbia.edu/kermit/ckermit80.html#x9
- 425. http://www.columbia.edu/kermit/ckermit80.html#x9
- 426. http://www.columbia.edu/kermit/ckermit80.html#x9
- 427. http://www.columbia.edu/kermit/ckermit80.html#x3
- 428. http://www.columbia.edu/kermit/ckermit80.html#x3
- 429. http://www.columbia.edu/kermit/ckermit80.html#x3.2
- 430. http://www.columbia.edu/kermit/ckermit80.html#x3.2
- 431. http://www.columbia.edu/kermit/ckermit80.html#x3.8
- 432. http://www.columbia.edu/kermit/ckermit80.html#x3
- 433. http://www.columbia.edu/kermit/ckermit80.html#x3
- 434. http://www.columbia.edu/kermit/ckermit80.html#x3
- 435. http://www.columbia.edu/kermit/ckermit80.html#x3.2
- 436. http://www.columbia.edu/kermit/ckermit80.html#x3
- 437. http://www.columbia.edu/kermit/ckermit80.html#x8.13
- 438. http://www.columbia.edu/kermit/ckermit80.html#x8.13
- 439. http://www.columbia.edu/kermit/ckermit80.html#x9
- 440. http://www.columbia.edu/kermit/ckermit80.html#x8.10
- 441. http://www.columbia.edu/kermit/ckermit80.html#x8.7.4
- 442. http://www.columbia.edu/kermit/ckermit80.html#top
- 443. http://www.columbia.edu/kermit/ckermit80.html#contents
- 444. http://www.columbia.edu/kermit/ckermit.html
- 445. http://www.columbia.edu/kermit/index.html
- 446. http://www.columbia.edu/kermit/ckermit80.html#top
- 447. http://www.columbia.edu/kermit/ckermit80.html#contents
- 448. http://www.columbia.edu/kermit/ckermit.html
- 449. http://www.columbia.edu/kermit/index.html
- 450. http://www.columbia.edu/kermit/ckermit80.html#top
- 451. http://www.columbia.edu/kermit/ckermit80.html#contents
- 452. http://www.columbia.edu/kermit/ckermit.html
- 453. http://www.columbia.edu/kermit/index.html
- 454. http://www.columbia.edu/kermit/ckermit80.html#x8.7
- 455. http://www.columbia.edu/kermit/ckermit80.html#top
- 456. http://www.columbia.edu/kermit/ckermit80.html#contents
- 457. http://www.columbia.edu/kermit/ckermit.html
- 458. http://www.columbia.edu/kermit/index.html
- 459. http://www.columbia.edu/kermit/ckermit80.html#scriptedit
- 460. http://www.columbia.edu/kermit/ckermit80.html#top
- 461. http://www.columbia.edu/kermit/ckermit80.html#contents
- 462. http://www.columbia.edu/kermit/ckermit.html
- 463. http://www.columbia.edu/kermit/index.html
- 464. http://www.columbia.edu/kermit/ckermit80.html#top
- 465. http://www.columbia.edu/kermit/ckermit80.html#contents
- 466. http://www.columbia.edu/kermit/ckermit.html
- 467. http://www.columbia.edu/kermit/index.html
- 468. ftp://ftp.isi.edu/in-notes/rfc2822.txt
- 469. ftp://ftp.isi.edu/in-notes/rfc2822.txt
- 470. ftp://ftp.isi.edu/in-notes/rfc2822.txt
- 471. ftp://ftp.isi.edu/in-notes/rfc2822.txt
- 472. http://www.columbia.edu/kermit/ckermit80.html#top
- 473. http://www.columbia.edu/kermit/ckermit80.html#contents
- 474. http://www.columbia.edu/kermit/ckermit.html
- 475. http://www.columbia.edu/kermit/index.html
- 476. http://www.columbia.edu/kermit/ckermit80.html#x8.1
- 477. http://www.columbia.edu/kermit/ckermit80.html#top
- 478. http://www.columbia.edu/kermit/ckermit80.html#contents
- 479. http://www.columbia.edu/kermit/ckermit.html
- 480. http://www.columbia.edu/kermit/index.html
- 481. http://www.columbia.edu/kermit/ckermit80.html#x8.2
- 482. http://www.columbia.edu/kermit/ckermit80.html#top
- 483. http://www.columbia.edu/kermit/ckermit80.html#contents
- 484. http://www.columbia.edu/kermit/ckermit.html
- 485. http://www.columbia.edu/kermit/index.html
- 486. http://www.columbia.edu/kermit/ckermit80.html#x9.8
- 487. http://www.columbia.edu/kermit/ckermit80.html#x9.8
- 488. http://www.columbia.edu/kermit/ckermit80.html#x8.2
- 489. http://www.columbia.edu/kermit/ckermit80.html#top
- 490. http://www.columbia.edu/kermit/ckermit80.html#contents
- 491. http://www.columbia.edu/kermit/ckermit.html
- 492. http://www.columbia.edu/kermit/index.html
- 493. http://www.columbia.edu/kermit/ckermit80.html#top
- 494. http://www.columbia.edu/kermit/ckermit80.html#contents
- 495. http://www.columbia.edu/kermit/ckermit.html
- 496. http://www.columbia.edu/kermit/index.html
- 497. http://www.columbia.edu/kermit/ckermit80.html#x9.8
- 498. http://www.columbia.edu/kermit/ckermit80.html#top
- 499. http://www.columbia.edu/kermit/ckermit80.html#contents
- 500. http://www.columbia.edu/kermit/ckermit.html
- 501. http://www.columbia.edu/kermit/index.html
- 502. http://www.columbia.edu/kermit/ckermit80.html#x9.8
- 503. http://www.columbia.edu/kermit/ckermit80.html#x9.8
- 504. http://www.columbia.edu/kermit/ckermit80.html#x9.6
- 505. http://www.columbia.edu/kermit/ckermit80.html#top
- 506. http://www.columbia.edu/kermit/ckermit80.html#contents
- 507. http://www.columbia.edu/kermit/ckermit.html
- 508. http://www.columbia.edu/kermit/index.html
- 509. http://www.columbia.edu/kermit/ckermit80.html#x9.8
- 510. http://www.columbia.edu/kermit/ckermit80.html#x9.8
- 511. http://www.columbia.edu/kermit/ckermit80.html#top
- 512. http://www.columbia.edu/kermit/ckermit80.html#contents
- 513. http://www.columbia.edu/kermit/ckermit.html
- 514. http://www.columbia.edu/kermit/index.html
- 515. http://www.columbia.edu/kermit/ckermit80.html#top
- 516. http://www.columbia.edu/kermit/ckermit80.html#contents
- 517. http://www.columbia.edu/kermit/ckermit.html
- 518. http://www.columbia.edu/kermit/index.html
- 519. http://www.columbia.edu/kermit/ckermit80.html#top
- 520. http://www.columbia.edu/kermit/ckermit80.html#contents
- 521. http://www.columbia.edu/kermit/ckermit.html
- 522. http://www.columbia.edu/kermit/index.html
- 523. mailto:thucdat@hotmail.com
- 524. http://www.columbia.edu/kermit/ckermit80.html#x9.9.2
- 525. http://www.columbia.edu/kermit/ckermit80.html#top
- 526. http://www.columbia.edu/kermit/ckermit80.html#contents
- 527. http://www.columbia.edu/kermit/ckermit.html
- 528. http://www.columbia.edu/kermit/index.html
- 529. http://www.columbia.edu/kermit/ckermit80.html#top
- 530. http://www.columbia.edu/kermit/ckermit80.html#contents
- 531. http://www.columbia.edu/kermit/ckermit.html
- 532. http://www.columbia.edu/kermit/index.html
- 533. http://www.columbia.edu/kermit/ckermit80.html#top
- 534. http://www.columbia.edu/kermit/ckermit80.html#contents
- 535. http://www.columbia.edu/kermit/ckermit.html
- 536. http://www.columbia.edu/kermit/index.html
- 537. http://www.columbia.edu/kermit/ckermit80.html#x9.2
- 538. http://www.columbia.edu/kermit/ckermit80.html#top
- 539. http://www.columbia.edu/kermit/ckermit80.html#contents
- 540. http://www.columbia.edu/kermit/ckermit.html
- 541. http://www.columbia.edu/kermit/index.html
- 542. http://www.columbia.edu/kermit/ckermit80.html#x4
- 543. http://www.columbia.edu/kermit/ckermit80.html#x4
- 544. http://www.columbia.edu/kermit/ckermit80.html#top
- 545. http://www.columbia.edu/kermit/ckermit80.html#contents
- 546. http://www.columbia.edu/kermit/ckermit.html
- 547. http://www.columbia.edu/kermit/index.html
- 548. http://www.columbia.edu/kermit/ckermit80.html#top
- 549. http://www.columbia.edu/kermit/ckermit80.html#contents
- 550. http://www.columbia.edu/kermit/ckermit.html
- 551. http://www.columbia.edu/kermit/index.html
- 552. http://www.columbia.edu/kermit/ckermit80.html#top
- 553. http://www.columbia.edu/kermit/ckermit80.html#contents
- 554. http://www.columbia.edu/kermit/ckermit.html
- 555. http://www.columbia.edu/kermit/index.html
- 556. http://www.columbia.edu/kermit/ckermit80.html#x4
- 557. http://www.columbia.edu/kermit/ckermit80.html#x3.7
- 558. http://www.columbia.edu/kermit/ckermit80.html#x3.7
- 559. http://www.columbia.edu/kermit/ckermit80.html#top
- 560. http://www.columbia.edu/kermit/ckermit80.html#contents
- 561. http://www.columbia.edu/kermit/ckermit.html
- 562. http://www.columbia.edu/kermit/index.html
- 563. ftp://ftp.isi.edu/in-notes/rfc2217.txt
- 564. http://www.columbia.edu/kermit/ckermit80.html#top
- 565. http://www.columbia.edu/kermit/ckermit80.html#contents
- 566. ftp://kermit.columbia.edu/kermit/sredird/
- 567. http://www.columbia.edu/kermit/ckermit.html
- 568. http://www.columbia.edu/kermit/index.html
- 569. http://www.columbia.edu/kermit/ckermi70.htm#x4.22
- 570. http://www.columbia.edu/kermit/ckermit80.html#top
- 571. http://www.columbia.edu/kermit/ckermit80.html#contents
- 572. http://www.columbia.edu/kermit/ckermit.html
- 573. http://www.columbia.edu/kermit/index.html
- 574. http://www.columbia.edu/kermit/ckermit80.html#x3.1.3
- 575. http://www.columbia.edu/kermit/cuiksd.html
- 576. http://www.columbia.edu/kermit/ckermit80.html#top
- 577. http://www.columbia.edu/kermit/ckermit80.html#contents
- 578. http://www.columbia.edu/kermit/ckermit.html
- 579. http://www.columbia.edu/kermit/index.html
- 580. http://www.columbia.edu/kermit/ckermit80.html#top
- 581. http://www.columbia.edu/kermit/ckermit80.html#contents
- 582. http://www.columbia.edu/kermit/ckermit.html
- 583. http://www.columbia.edu/kermit/index.html
- 584. http://www.columbia.edu/kermit/index.html
diff --git a/ckermod.ini b/ckermod.ini
deleted file mode 100644 (file)
index 5848c3f..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-; File CKERMOD.INI, Sample C-Kermit 7.0 customization file.
-;
-; This file, which is ONLY A SAMPLE, should be called:
-;
-;   .mykermrc   (UNIX, OS-9, Aegis, BeBox, Plan 9)
-;   CKERMOD.INI (VMS, OpenVMS, AOS/VS, OS/2, Amiga, Atari ST)
-;   ckermod.ini (Stratus VOS)
-;
-; This file is executed automatically by the standard C-Kermit initialization
-; file, CKERMIT.INI (or .kermrc).  This file is not executed by C-Kermit itself
-; unless the initialization file is not found.
-;
-; MODify this file to suit your needs and preferences, and install it in your
-; home directory.  Or replace it entirely with a new file.
-;
-; The design of this sample customization file lets you fill in a section for
-; each different operating system where you run C-Kermit.
-;
-; In UNIX, if you give this file execute permission and make sure the top
-; line indicates the full path of the C-Kermit 7.0-or-later executable, you
-; can execute this file directly, as if it was a shell script, except it is
-; interpreted by Kermit rather than the shell.  This lets you have as many
-; different startup files as you like, each suited to a particular purpose.
-;
-; Authors:  Christine Gianone, Frank da Cruz, Jeffrey Altman,
-;           The Kermit Project, Columbia University.
-; Creation: 23 November 1992 for C-Kermit 5A(188).
-; Modified: 30 June 1993 for edit 189.
-;           04 October 1994 for edit 190.
-;           17 April 1995 for edit 191.
-;            6 September 1996 for version 6.0, edit 192.
-;            1 January 2000 for version 7.0, edit 196.
-;           14 October 2001 for version 8.0, edit 200.
-
-ECHO
-ECHO Executing SAMPLE C-Kermit customization file \v(cmdfile) for \v(system)...
-ECHO { Please edit this file to reflect your needs and preferences.}
-ECHO
-;
-; ... and then remove the ECHO commands above.
-
-COMMENT - Settings that apply to all the systems I use:
-;
-set delay 1                  ; I escape back quickly
-set dial display on          ; I like to watch C-Kermit dial
-
-; Dialing locale and method
-;
-; SET DIAL COUNTRY-CODE 1    ; Uncomment and replace with yours
-; SET DIAL AREA-CODE 000     ; Uncomment and replace with yours
-; SET DIAL LD-PREFIX 1       ; Uncomment and replace with yours
-; SET DIAL INTL-PREFIX 011   ; Uncomment and replace with yours
-; SET DIAL METHOD TONE       ; Uncomment and replace with PULSE if necessary
-; SET DIAL DIRECTORY ... ... ; List dialing directory files here
-
-if < \v(version) 600192 -
-  stop 1 \v(cmdfile): C-Kermit 6.0.192 or later required.
-
-set take error on            ; Make errors fatal temporarily
-check if                     ; Do we have an IF command?
-set take error off           ; Yes we do, back to normal
-
-; The ON_EXIT macro is executed automatically when C-Kermit exits.
-; Define as desired.
-;
-define ON_EXIT echo Returning you to \v(system) now.
-
-; System-independent quick dialing macro.  Depends on having the
-; macros MYMODEM, MYPORT, and (optionally) MYSPEED defined in the
-; system-dependent sections below.
-;
-define MYDIAL {
-    if not defined MYMODEM end 1 {\%0: Modem type not defined.}
-    set modem type \m(MYMODEM)
-    if fail end 1 {\%0: \m(MYMODEM): Unsupported modem type.}
-    if not defined MYPORT end 1 {\%0: Communication port not defined.}
-    set port \m(MYPORT)
-    if fail end 1 {\%0: SET PORT \m(MYPORT) failed.}
-    if defined MYFLOW set flow \m(MYFLOW)
-    if fail end 1 {\%0: SET FLOW \m(MYFLOW) failed.}
-    if defined MYSPEED set speed \m(MYSPEED)
-    if fail end 1 {\%0: SET SPEED \m(MYSPEED) failed.}
-    dial \%1\%2\%3\%4\%5\%6\%7\%8\%9
-    end \v(status)
-}
-
-forward \v(system)              ; Go execute system-dependent commands
-
-:UNIX                           ; UNIX, all versions...
-define MYPORT /dev/cua          ; My dialing environment
-define MYMODEM usr              ; Replace these by what you actually have
-define MYSPEED 57600
-;
-; If you want all your downloads to go to the same directory, no matter
-; what your current directory is, uncomment and edit the following command:
-;
-;   set file download-directory ~/download ; Download directory for UNIX
-
-; Put other UNIX-specific commands here...
-end                             ; End of UNIX section
-
-:VMS                            ; VMS and OpenVMS
-define MYPORT TXA0:             ; My dialing environment
-define MYMODEM usr              ; Replace these by what you actually have
-define MYSPEED 57600
-; set file download-directory [\$(USER).DOWNLOAD] ; Download directory for VMS
-; Put other VMS-specific commands here...
-end                             ; End of VMS section
-
-:WIN32                          ; Windows and OS/2 customizations...
-:OS/2
-define MYPORT COM1              ; My dialing environment
-define MYMODEM usr              ; Replace these by what you actually have
-define MYSPEED 57600
-set command byte 8              ; Use 8 bits between Kermit and console
-set xfer char latin1            ; Use Latin-1 for text file transfer
-set term char latin1            ; And use Latin-1 during CONNECT mode
-; set file download-directory C:\DOWNLOADS
-end
-
-:OS9/68K                        ; OS-9/68000
-define MYPORT /t3               ; My dialing environment
-define MYMODEM usr              ; Replace these by what you actually have
-define MYSPEED 9600
-; set file download-directory ~/downloads
-end                             ; End of OS-9 section
-
-:AOS/VS                         ; Data General AOS/VS
-define MYPORT @con3             ; My dialing environment
-define MYMODEM usr              ; Replace these by what you actually have
-define MYSPEED 9600
-; set file download-directory \v(home)DOWNLOADS
-end
-
-; And so on, you get the idea...
-; Fill in the sections that apply to you.
-
-:Stratus_VOS                   ; Stratus VOS
-:Amiga                          ; Commodore Amiga
-:Atari_ST                       ; Atari ST
-:Macintosh                      ; Apple Macintosh
-:unknown                        ; Others
-
-; (End of CKERMOD.INI)
index 5ee8e10..8679a99 100644 (file)
--- a/ckuat2.h
+++ b/ckuat2.h
@@ -1,7 +1,7 @@
 /*
   C K U A T 2 . H  --  Kerberos headers for C-Kermit
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2009,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -275,11 +275,6 @@ void castexp_ofb64_printsub P((unsigned char *, int, unsigned char *, int));
 extern int encrypt_debug_mode;
 #endif
 
-#ifndef CRYPT_DLL
-extern int (*decrypt_input) P((int));
-extern void (*encrypt_output) P((unsigned char *, int));
-#endif /* CRYPT_DLL */
-
 int decrypt_ks_hack(unsigned char *, int);
 
 #endif /* __ENCRYPTION__ */
@@ -291,7 +286,7 @@ struct _crypt_dll_init {
 
     /* Version 1 variables */
     int (*p_ttol)(char *,int);
-    int (*p_dodebug)(int,char *,char *,long);
+    int (*p_dodebug)(int,char *,char *,CK_OFF_T);
     int (*p_dohexdump)(char *,char *,int);
     void (*p_tn_debug)(char *);
     int (*p_vscrnprintf)(char *, ...);
index 0ba4360..ea9bc7d 100644 (file)
--- a/ckuath.c
+++ b/ckuath.c
@@ -1,8 +1,8 @@
-char *ckathv = "Authentication, 8.0.232, 7 Feb 2004";
+char *ckathv = "Authentication, 9.0.235, 16 Mar 2010";
 /*
   C K U A T H . C  --  Authentication for C-Kermit
 
-  Copyright (C) 1999, 2004,
+  Copyright (C) 1999, 2010,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -121,7 +121,11 @@ int accept_complete = 0;
 #ifndef VMS
 #ifndef FREEBSD4
 #ifndef OpenBSD
+#ifdef MACOSX
+#include <sys/malloc.h>
+#else /* MACOSX */
 #include <malloc.h>
+#endif /* MACOSX */
 #endif /* OpenBSD */
 #endif /* FREEBSD4 */
 #endif /* VMS */
@@ -137,7 +141,9 @@ int accept_complete = 0;
 #undef printf
 #endif /* printf */
 #include "krb5.h"
+
 #include "com_err.h"
+
 #ifdef saveprintf
 #define printf saveprintf
 #endif /* saveprintf */
@@ -209,8 +215,10 @@ _PROTOTYP(const char * krb_get_err_text_entry, (int));
 #ifdef CK_SSL
 #ifdef LIBDES
 #ifdef OPENSSL_097
+#ifdef CK_DES
 #define OPENSSL_ENABLE_OLD_DES_SUPPORT
 #include <openssl/des.h>
+#endif /* CK_DES */
 #endif /* OPENSSL_097 */
 #ifndef HEADER_DES_H
 #define HEADER_DES_H
@@ -294,6 +302,12 @@ static krb5_keyblock     *k5_session_key = NULL;
 static krb5_ticket       *k5_ticket = NULL;
 #ifndef KRB5_SERVICE_NAME
 #define KRB5_SERVICE_NAME    "host"
+#ifdef MACOSX
+#define MIT_CURRENT 1
+#define decode_krb5_ticket  krb5_decode_ticket
+#define krb5_read_message   ck_krb5_read_message
+#define krb5_write_message  ck_krb5_write_message
+#endif /* MACOSX */
 #endif
 
 _PROTOTYP(static int k5_auth_send,(int,int,int));
@@ -1464,7 +1478,7 @@ ck_tn_sb_encrypt(sb,len) char * sb; int len;
 
     buf[0] = SB;
     memcpy( &buf[1], sb, len-2 );
-    rc = encrypt_parse(buf,len-1);
+    rc = encrypt_parse((CHAR *)buf,len-1);
 
     if (rc < 0) {
         free(buf);
@@ -1568,13 +1582,13 @@ ck_tn_encrypt( s,n ) char * s; int n;
 
     if (g_kstream->encrypt && encrypt_is_encrypting()) {
 #ifdef DEBUG
-      hexdump("from plaintext", s, n);
+      ckhexdump("from plaintext", s, n);
 #endif
         i.ptr = s;
         i.length = n;
         g_kstream->encrypt(&i, NULL);
 #ifdef DEBUG
-        hexdump("to cyphertext", s, n);
+        ckhexdump("to cyphertext", s, n);
 #endif
     }
     else debug(F101,"ck_tn_encrypt not encrypting","",n);
@@ -1598,14 +1612,14 @@ ck_tn_decrypt( s,n ) char * s; int n;
     if (g_kstream->decrypt && encrypt_is_decrypting()) {
 
 #ifdef DEBUG
-        hexdump("from cyphertext", s, n);
+        ckhexdump("from cyphertext", s, n);
 #endif
 
         i.ptr = s;
         i.length = n;
         g_kstream->decrypt(&i, NULL);
 #ifdef DEBUG
-        hexdump("to plaintext", s, n);
+        ckhexdump("to plaintext", s, n);
 #endif
     }
     else debug(F101,"ck_tn_decrypt not decrypting","",n);
@@ -3152,7 +3166,7 @@ auth_send(parsedat,end_sub) unsigned char *parsedat; int end_sub;
                                    &encdata, &data);
 #else /* MIT_CURRENT */
             memset(k4_sched,0,sizeof(Schedule));
-            hexdump("auth_send",cred.session,8);
+            ckhexdump("auth_send",cred.session,8);
             rc = des_key_sched(cred.session, k4_sched);
             if ( rc == -1 ) {
                 printf("?Invalid DES key specified in credentials\r\n");
@@ -3167,7 +3181,7 @@ auth_send(parsedat,end_sub) unsigned char *parsedat; int end_sub;
                 debug(F110,"auth_send",
                       "DES Key Schedule not set by credentials",0);
             }
-            hexdump("auth_send schedule",k4_sched,8*16);
+            ckhexdump("auth_send schedule",k4_sched,8*16);
 
             des_set_random_generator_seed(cred.session);
 
@@ -3176,7 +3190,7 @@ auth_send(parsedat,end_sub) unsigned char *parsedat; int end_sub;
                 des_fixup_key_parity(k4_session_key);
             } while ( ck_des_is_weak_key(k4_session_key) );
 
-            hexdump("auth_send des_new_random_key(k4_session_key)",
+            ckhexdump("auth_send des_new_random_key(k4_session_key)",
                      k4_session_key,8);
 
             /* Decrypt the session key so that we can send it to the */
@@ -3186,7 +3200,7 @@ auth_send(parsedat,end_sub) unsigned char *parsedat; int end_sub;
 #else /* NT */
             des_ecb_encrypt(&k4_session_key, &k4_session_key, k4_sched, 0);
 #endif /* NT */
-            hexdump(
+            ckhexdump(
                 "auth_send des_ecb_encrypt(k4_session_key,k4_session_key,0)",
                 k4_session_key,8
                     );
@@ -3200,7 +3214,7 @@ auth_send(parsedat,end_sub) unsigned char *parsedat; int end_sub;
             des_ecb_encrypt(&k4_session_key, &k4_challenge, k4_sched, 0);
 #endif /* NT */
 
-            hexdump("auth_send des_ecb_encrypt(k4_session_key,k4_challenge,0)",
+            ckhexdump("auth_send des_ecb_encrypt(k4_session_key,k4_challenge,0)",
                      k4_challenge,8);
 #endif /* MIT_CURRENT */
             /*
@@ -3214,7 +3228,7 @@ auth_send(parsedat,end_sub) unsigned char *parsedat; int end_sub;
                 if (x < 256)            /* if no overflow, all done */
                     break;
             }
-            hexdump("auth_send k4_challenge+1",k4_challenge,8);
+            ckhexdump("auth_send k4_challenge+1",k4_challenge,8);
 #ifdef MIT_CURRENT
             data.data = k4_challenge;
             data.length = 8;
@@ -3234,7 +3248,7 @@ auth_send(parsedat,end_sub) unsigned char *parsedat; int end_sub;
 #else /* NT */
             des_ecb_encrypt(&k4_challenge, &k4_challenge, k4_sched, 1);
 #endif /* NT */
-            hexdump("auth_send des_ecb_encrypt(k4_session_key,k4_challenge,1)",
+            ckhexdump("auth_send des_ecb_encrypt(k4_session_key,k4_challenge,1)",
                      k4_challenge,8);
 #endif /* MIT_CURRENT */
         }
@@ -3281,18 +3295,19 @@ auth_send(parsedat,end_sub) unsigned char *parsedat; int end_sub;
     case AUTHTYPE_KERBEROS_V5:
         debug(F111,"auth_send KRB5","k5_auth.length",k5_auth.length);
         for ( i=0 ; i<k5_auth.length ; i++ ) {
-            if ( ((char *)k5_auth.data)[i] == IAC )
+            if ( (char *)k5_auth.data[i] == IAC )
                 iaccnt++;
         }
-
-        if ( k5_auth.length + iaccnt + 10 < sizeof(buf) )
-          k5_auth.length = copy_for_net(&buf[7], k5_auth.data, k5_auth.length);
-        else {
+        if ( k5_auth.length + iaccnt + 10 < sizeof(buf) ) {
+           k5_auth.length = copy_for_net(&buf[7],
+                                         (CHAR *)k5_auth.data,
+                                         k5_auth.length);
+       } else {
           debug(F100,"auth_send() KRB5 auth data too large for buffer","",0);
           k5_auth.length = 0;
         }
 
-        sprintf(&buf[k5_auth.length+7], "%c%c", IAC, SE);       /* safe */
+        sprintf((char *)&buf[k5_auth.length+7], "%c%c", IAC, SE); /* safe */
         if (deblog || tn_deb || debses) {
             int i;
             ckmakxmsg(tn_msg,TN_MSG_LEN,
@@ -3301,7 +3316,7 @@ auth_send(parsedat,end_sub) unsigned char *parsedat; int end_sub;
                       AUTHMODE_NAME(mode)," AUTH ",
                       NULL,NULL,NULL,NULL,NULL
                      );
-            tn_hex((char *)tn_msg,TN_MSG_LEN,&buf[7],k5_auth.length);
+            tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&buf[7],k5_auth.length);
             ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
             debug(F100,tn_msg,"",0);
             if (tn_deb || debses) tn_debug(tn_msg);
@@ -3966,7 +3981,7 @@ k4_auth_reply(parsedat,end_sub) unsigned char *parsedat; int end_sub;
 #else /* NT */
         des_ecb_encrypt(&k4_session_key, &k4_session_key, k4_sched, 1);
 #endif /* NT */
-        hexdump(
+        ckhexdump(
             "k4_auth_reply des_ecb_encrypt(k4_session_key,k4_session_key,1)",
              k4_session_key,
              8
@@ -4001,9 +4016,9 @@ k4_auth_reply(parsedat,end_sub) unsigned char *parsedat; int end_sub;
             return AUTH_FAILURE;
         }
 
-        hexdump("KRB4_RESPONSE &parsedat[5]",&parsedat[5],8);
+        ckhexdump("KRB4_RESPONSE &parsedat[5]",&parsedat[5],8);
 #ifdef CK_ENCRYPTION
-        hexdump("KRB4_RESPONSE k4_challenge",k4_challenge,8);
+        ckhexdump("KRB4_RESPONSE k4_challenge",k4_challenge,8);
 
         /* The datablock returned from the host should match the value */
         /* we stored in k4_challenge.                                  */
@@ -4097,7 +4112,7 @@ k4_auth_is(parsedat,end_sub) unsigned char *parsedat; int end_sub;
             memcpy((void *)k4_auth.dat, (void *)data, k4_auth.length);
         } else
             k4_auth.length = 0;
-        hexdump("k4_auth.dat",k4_auth.dat, k4_auth.length);
+        ckhexdump("k4_auth.dat",k4_auth.dat, k4_auth.length);
 
         /* Get Instance */
         inaddr.s_addr = inet_addr(myipaddr);
@@ -4122,7 +4137,7 @@ k4_auth_is(parsedat,end_sub) unsigned char *parsedat; int end_sub;
                             krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
                             instance, 0, &k4_adat, k4_keytab)) {
 
-            hexdump("k4_adat", &k4_adat, sizeof(AUTH_DAT));
+            ckhexdump("k4_adat", &k4_adat, sizeof(AUTH_DAT));
             krb_kntoln(&k4_adat, k4_name);
             ckmakmsg(strTmp,sizeof(strTmp),
                      "Kerberos failed him as ", k4_name,NULL,NULL);
@@ -4137,7 +4152,7 @@ k4_auth_is(parsedat,end_sub) unsigned char *parsedat; int end_sub;
 #ifdef CK_ENCRYPTION
         memcpy((void *)k4_session_key, (void *)k4_adat.session,
                 sizeof(Block));                 /* safe */
-        hexdump("k4_auth_is k4_session_key",k4_session_key,sizeof(Block));
+        ckhexdump("k4_auth_is k4_session_key",k4_session_key,sizeof(Block));
 #endif /* ENCRYPTION */
         krb_kntoln(&k4_adat, k4_name);
 
@@ -4257,10 +4272,10 @@ k4_auth_is(parsedat,end_sub) unsigned char *parsedat; int end_sub;
             debug(F110,"auth_is CHALLENGE",
                    "DES Key Schedule not set by credentials",0);
         }
-        hexdump("auth_is schedule",k4_sched,8*16);
+        ckhexdump("auth_is schedule",k4_sched,8*16);
 
         memcpy((void *)datablock, (void *)data, sizeof(Block)); /* safe */
-        hexdump("auth_is challege",datablock,sizeof(Block));
+        ckhexdump("auth_is challege",datablock,sizeof(Block));
 
         /*
         * Take the received encrypted challenge, and encrypt
@@ -4272,7 +4287,7 @@ k4_auth_is(parsedat,end_sub) unsigned char *parsedat; int end_sub;
 #else /* NT */
         des_ecb_encrypt(&datablock, &k4_session_key, k4_sched, 1);
 #endif /* NT */
-        hexdump("auth_is des_ecb_encrypt(datablock,k4_session_key,1)",
+        ckhexdump("auth_is des_ecb_encrypt(datablock,k4_session_key,1)",
                  k4_session_key,8);
 
 #ifdef CK_SSL
@@ -4293,7 +4308,7 @@ k4_auth_is(parsedat,end_sub) unsigned char *parsedat; int end_sub;
 #else /* NT */
         des_ecb_encrypt(&datablock, &k4_challenge, k4_sched, 0);
 #endif /* NT */
-        hexdump("auth_is des_ecb_encrypt(datablock,k4_challenge,0)",
+        ckhexdump("auth_is des_ecb_encrypt(datablock,k4_challenge,0)",
                  k4_session_key,8);
 #endif /* MIT_CURRENT */
         for (r = 7; r >= 0; r--) {
@@ -4303,7 +4318,7 @@ k4_auth_is(parsedat,end_sub) unsigned char *parsedat; int end_sub;
             if (t < 256)                /* if no overflow, all done */
                 break;
         }
-        hexdump("auth_is k4_challenge+1",k4_challenge,8);
+        ckhexdump("auth_is k4_challenge+1",k4_challenge,8);
 
 #ifdef MIT_CURRENT
         kdata.data = k4_challenge;
@@ -4325,7 +4340,7 @@ k4_auth_is(parsedat,end_sub) unsigned char *parsedat; int end_sub;
 #else /* NT */
         des_ecb_encrypt(&k4_challenge, &k4_challenge, k4_sched, 1);
 #endif /* NT */
-        hexdump("auth_is des_ecb_encrypt(k4_challenge_key,k4_challenge,1)",
+        ckhexdump("auth_is des_ecb_encrypt(k4_challenge_key,k4_challenge,1)",
                  k4_challenge,8);
 
 #endif /* MIT_CURRENT */
@@ -4397,7 +4412,7 @@ ck_krb5_autoget_TGT(char * realm)
         if ( !ok )
             passwd[0] = '\0';
     } else {
-        ckstrncpy(passwd,pwbuf,sizeof(passwd));
+        ckstrncpy(passwd,(char *)pwbuf,sizeof(passwd));
 #ifdef OS2
         if ( pwcrypt )
             ck_encrypt((char *)passwd);
@@ -5107,7 +5122,7 @@ k5_auth_reply(how,data,cnt) int how; unsigned char *data; int cnt;
             ssl_get_server_finished(&tls_verify[0],12);
             ssl_get_client_finished(&tls_verify[12],12);
 
-            reply.data = data;
+            reply.data = (char *)data;
             reply.length = cnt;
 
                        krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
@@ -5237,7 +5252,7 @@ k5_auth_is(how,data,cnt) int how; unsigned char *data; int cnt;
     data += 4;                                  /* Point to status byte */
     cnt -= 4;
 
-    hexdump("k5_auth_is data",data,cnt);
+    ckhexdump("k5_auth_is data",data,cnt);
     debug(F111,"k5_auth_is","how",how);
 
     if (cnt-- < 1) {
@@ -5259,12 +5274,15 @@ k5_auth_is(how,data,cnt) int how; unsigned char *data; int cnt;
 
 #ifdef HEIMDAL
         if (!r)
-            r = krb5_auth_con_setaddrs_from_fd(k5_context,auth_context,&ttyfd);
-
+            r = krb5_auth_con_setaddrs_from_fd(k5_context,
+                                              auth_context,
+                                              &ttyfd);
         if (!r)
-            r = krb5_sock_to_principal(k5_context,0,"host",
-                                       KRB5_NT_SRV_HST,&server);
-
+            r = krb5_sock_to_principal(k5_context,
+                                      0,
+                                      "host",
+                                       KRB5_NT_SRV_HST,
+                                      &server);
         if (!r)
 #else /* HEIMDAL */
         if (!r) {
@@ -5331,7 +5349,7 @@ k5_auth_is(how,data,cnt) int how; unsigned char *data; int cnt;
             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
                 ssl_get_client_finished(&type_check[2],12);
                 ssl_get_server_finished(&type_check[14],12);
-                hexdump("k5_auth_is type_check",type_check,26);
+                ckhexdump("k5_auth_is type_check",type_check,26);
             }
 #endif /* CK_SSL */
 
@@ -5390,7 +5408,7 @@ k5_auth_is(how,data,cnt) int how; unsigned char *data; int cnt;
             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
                 ssl_get_client_finished(&type_check[2],12);
                 ssl_get_server_finished(&type_check[14],12);
-                hexdump("k5_auth_is type_check",type_check,26);
+                ckhexdump("k5_auth_is type_check",type_check,26);
             }
 #endif /* CK_SSL */
 
@@ -6041,7 +6059,7 @@ k5_auth_is(how,data,cnt) int how; unsigned char *data; int cnt;
     data += 4;                                  /* Point to status byte */
     cnt -= 4;
 
-    hexdump("gssk5_auth_is data",data,cnt);
+    ckhexdump("gssk5_auth_is data",data,cnt);
     debug(F111,"gssk5_auth_is","how",how);
 
     if (cnt-- < 1) {
@@ -6773,8 +6791,8 @@ srp_is(how,data,cnt) int how; unsigned char *data; int cnt;
             if (!(ssl_active_flag || tls_active_flag))
 #endif /* CK_SSL */
             {
-                hexdump("SRP_RESPONSE ts",ts,sizeof(ts));
-                hexdump("SRP_RESPONSE session_key",
+                ckhexdump("SRP_RESPONSE ts",ts,sizeof(ts));
+                ckhexdump("SRP_RESPONSE session_key",
                          ts->session_key,
                          SESSION_KEY_LEN
                          );
@@ -11299,10 +11317,10 @@ ck_krb_rlogin(hostname, port,
 
         debug(F100,"ck_krb_rlogin version 5","",0);
 
-        realm = ck_krb5_realmofhost(hostname);
+        realm = ck_krb5_realmofhost((char *)hostname);
         if (!realm) {
             ckstrncpy(strTmp, "Can't find realm for host \"",AUTHTMPBL);
-            ckstrncat(strTmp, hostname,AUTHTMPBL);
+            ckstrncat(strTmp, (char *)hostname,AUTHTMPBL);
             ckstrncat(strTmp, "\"",AUTHTMPBL);
             printf("?Kerberos 5 error: %s\r\n",strTmp);
             krb5_errno = KRB5_ERR_HOST_REALM_UNKNOWN;
@@ -11317,15 +11335,13 @@ ck_krb_rlogin(hostname, port,
                 (ck_krb5_is_tgt_valid() > 0)) )
             ck_krb5_autoget_TGT(realm);
 
-        buflen = strlen(term_speed)+strlen(remoteuser)+64;
-        if ((cksumbuf = malloc(buflen)) == 0)
-        {
+        buflen = strlen((char *)term_speed) + strlen((char *)remoteuser) + 64;
+        if ((cksumbuf = malloc(buflen)) == 0) {
             printf("Unable to allocate memory for checksum buffer.\r\n");
             return(-1);
         }
-
         ckmakmsg(cksumbuf,buflen,ckuitoa((unsigned short) ntohs(port)),":",
-                  term_speed,remoteuser);
+                (char *)term_speed,(char *)remoteuser);
         cksumdat.data = cksumbuf;
         cksumdat.length = strlen(cksumbuf);
 
@@ -11351,8 +11367,9 @@ ck_krb_rlogin(hostname, port,
             return(-1);
         }
         memset(get_cred,0,sizeof(krb5_creds));
-        status = krb5_sname_to_principal(k5_context, hostname, service,
-                                          KRB5_NT_SRV_HST, &get_cred->server);
+        status = krb5_sname_to_principal(k5_context, (char *) hostname,
+                                        service, KRB5_NT_SRV_HST,
+                                        &get_cred->server);
         if (status) {
             printf("ck_krb_rlogin: krb5_sname_to_principal failed: %s\r\n",
                      error_message(status));
@@ -11492,14 +11509,14 @@ ck_krb_rlogin(hostname, port,
             krb5_free_ap_rep_enc_part(k5_context, rep_ret);
         }
 
-        (void) ttol(remoteuser, strlen(remoteuser)+1);
-        (void) ttol(term_speed, strlen(term_speed)+1);
-        (void) ttol(localuser, strlen(localuser)+1);
+        (void) ttol(remoteuser, strlen((char *)remoteuser)+1);
+        (void) ttol(term_speed, strlen((char *)term_speed)+1);
+        (void) ttol(localuser, strlen((char *)localuser)+1);
 
         if (forward_flag) {   /* Forward credentials (global) */
             if (status = krb5_fwd_tgt_creds( k5_context,
                                              auth_context,
-                                             hostname,
+                                             (char *)hostname,
                                              ret_cred->client,
                                              ret_cred->server,
                                              0,
@@ -11531,7 +11548,7 @@ ck_krb_rlogin(hostname, port,
 
         if ((c = ttinc(0)) < 0) {
             if (c==-1) {
-                perror(hostname);
+                perror((char *)hostname);
             } else {
                 printf("ck_krb_rlogin: bad connection with remote host\r\n");
             }
@@ -11819,7 +11836,7 @@ krb5_des_read(fd, buf, len, secondary)
     if (status = krb5_c_encrypt_length(k5_context, 
                                     k5_session_key->enctype,
                                     use_ivecs ? rd_len + 4 : rd_len,
-                                    &net_len)) {
+                                   (size_t *)&net_len)) {
         errno = status;
         return(-1);
     }
@@ -12120,7 +12137,7 @@ int len;
     } else if ( cc != rd_len )
         return(0);
 
-    hexdump("krb4_des_read des_inbuf",des_inbuf,8);
+    ckhexdump("krb4_des_read des_inbuf",des_inbuf,8);
 #ifdef CK_ENCRYPTION
 #ifdef KRB524
     (void) des_pcbc_encrypt(des_inbuf,
@@ -12138,7 +12155,7 @@ int len;
                              DECRYPT);
 #endif /* KRB524 */
 #endif /* ENCRYPTION */
-    hexdump("krb4_des_read storage",storage,8);
+    ckhexdump("krb4_des_read storage",storage,8);
 
     /*
     * when the cleartext block is < 8 bytes, it is "right-justified"
@@ -12200,9 +12217,9 @@ int len;
         random_confounder(8 - len, garbage_buf);
         /* this "right-justifies" the data in the buffer */
         (void) memcpy(garbage_buf + 8 - len, buf, len); /* safe */
-        hexdump("krb4_des_write garbage_buf",garbage_buf,8);
+        ckhexdump("krb4_des_write garbage_buf",garbage_buf,8);
     } else
-        hexdump("krb4_des_write buf",buf,8);
+        ckhexdump("krb4_des_write buf",buf,8);
 #ifdef CK_ENCRYPTION
 #ifdef KRB524
     (void) des_pcbc_encrypt((len < 8) ? garbage_buf : buf,
@@ -12221,10 +12238,10 @@ int len;
 #endif /* KRB524 */
 #endif /* ENCRYPTION */
     if ( len < 8 )
-        hexdump("krb4_des_write (post pcbc) garbage_buf",garbage_buf,8);
+        ckhexdump("krb4_des_write (post pcbc) garbage_buf",garbage_buf,8);
     else
-        hexdump("krb4_des_write (post pcbc) buf",buf,8);
-    hexdump("krb4_des_write (des_outpkt+4)",(des_outpkt+4),8);
+        ckhexdump("krb4_des_write (post pcbc) buf",buf,8);
+    ckhexdump("krb4_des_write (des_outpkt+4)",(des_outpkt+4),8);
 
     /* tell the other end the real amount, but send an 8-byte padded
     packet */
@@ -12232,7 +12249,7 @@ int len;
     len_buf[1] = (len & 0xff0000) >> 16;
     len_buf[2] = (len & 0xff00) >> 8;
     len_buf[3] = (len & 0xff);
-    hexdump("krb4_des_write des_outpkt len",des_outpkt,12);
+    ckhexdump("krb4_des_write des_outpkt len",des_outpkt,12);
     cc = net_write(fd, des_outpkt, roundup(len,8)+4);
     debug(F111,"net_write","chars written",cc);
     return(len);
@@ -13211,8 +13228,13 @@ ck_auth_init( hostname, ipaddr, username, socket )
     /* create k5_context */
     krb5_init_context(&k5_context);
 #ifndef MIT_CURRENT
+#ifndef NO_KRB5_INIT_ETS
+/* This routine is a no-op in Kerberos 1.4.x and later */
+/* and in some installations it can't be found in which case */
+/* define NO_KRB5_INIT_ETS */
     if (k5_context)
         krb5_init_ets(k5_context);
+#endif /* NO_KRB5_INIT_ETS */
 #endif /* MIT_CURRENT */
 #ifdef KRB524_CONV
     krb524_init_ets(k5_context);
@@ -13284,4 +13306,57 @@ auth_finished(result) int result; {
         break;
     }
 }
+
+#ifdef MACOSX
+#ifdef KRB5
+
+krb5_error_code
+ck_krb5_write_message(krb5_context con, krb5_pointer ptr, krb5_data *data)
+{
+    int fd = *((int *)ptr);
+    long msglen;
+
+    msglen = htonl(data->length);
+    if (net_write(fd,(CHAR *)&msglen,4) != 4) {
+        return(-1);
+    }
+    if ( data->length ) {
+        if (net_write(fd,data->data,data->length) != data->length) {
+            return(-1);
+        }
+    }
+    return(0);
+}
+
+krb5_error_code
+ck_krb5_read_message( krb5_context context,
+                      krb5_pointer ptr,
+                      krb5_data * data)
+{
+    extern int ttyfd;
+    int fd = *((int *)ptr);
+    long msglen;
+    char *p;
+    int i, rc;
+
+    if (net_read(fd,&msglen,4) < 0)
+        return(-1);
+
+    data->length = ntohl(msglen);
+    if ( data->length ) {
+        data->data = malloc(data->length);
+
+        i = 0;
+        while ( i < data->length ) {
+            if ((rc = net_read(fd,&data->data[i],(data->length - i))) < 0)
+                return(-1);
+            i += rc;
+        }
+    }
+    return(0);
+}
+#endif /* KRB5 */
+#endif /* MACOSX */
 #endif /* CK_SECURITY */
+
+
index 0dbe8dc..914a06f 100644 (file)
--- a/ckuath.h
+++ b/ckuath.h
@@ -4,7 +4,7 @@
   Author: Jeffrey E Altman <jaltman@secure-endpoints.com>,
             Secure Endpoints Inc., New York City.
 
-  Copyright (C) 1999, 2004,
+  Copyright (C) 1999, 2009,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -116,6 +116,13 @@ _PROTOTYP(int SendSSLAuthSB, (int, void *, int));
     /* successfully in Kermit 95 due to the segmentation of crypto     */
     /* into a separate DLL.                                            */
 
+#ifndef KRB5_INIT_ETS
+/* krb5_init_ets() is a no-op in Kerberos 1.4.x and later */
+/* and in some installations it can't be found so now by default */
+/* we don't use it. */
+#define NO_KRB5_INIT_ETS
+#endif /* KRB5_INIT_ETS */
+
 #define KRB_DEFTIM 600                  /* Default lifetime (minutes) */
 
 /* Kerberos structure definitions */
diff --git a/ckubwr.txt b/ckubwr.txt
deleted file mode 100644 (file)
index 4b0d387..0000000
+++ /dev/null
@@ -1,5330 +0,0 @@
-
-                       C-Kermit 8.0 Unix Hints and Tips
-
-     Frank da Cruz
-     [1]The Kermit Project, [2]Columbia University
-
-   As of: C-Kermit 8.0.211 10 April 2004
-   This page last updated: Fri Apr 16 16:13:14 2004 (New York USA Time)
-
-     IF YOU ARE READING A PLAIN-TEXT version of this document, note it
-     is a plain-text dump of a Web page. You can visit the original (and
-     possibly more up-to-date) Web page here:
-
-  [3]http://www.columbia.edu/kermit/ckubwr.html
-
-     Since the material in this file has been accumulating since 1985,
-     some (much) of it might be dated. [4]Feedback from experts on
-     particular OS's and platforms is always welcome. 
-
-   [ [5]C-Kermit ] [ [6]Installation Instructions ] [ [7]TUTORIAL ]
-    ________________________________________________________________________
-
-  CONTENTS
-
-    1. [8]INTRODUCTION
-    2. [9]PREBUILT C-KERMIT BINARIES
-    3. [10]PLATFORM-SPECIFIC NOTES
-    4. [11]GENERAL UNIX-SPECIFIC LIMITATIONS AND BUGS
-    5. [12]INITIALIZATION AND COMMAND FILES
-    6. [13]COMMUNICATION SPEED SELECTION
-    7. [14]COMMUNICATIONS AND DIALING
-    8. [15]HARDWARE FLOW CONTROL
-    9. [16]TERMINAL CONNECTION AND KEY MAPPING
-   10. [17]FILE TRANSFER
-   11. [18]EXTERNAL FILE TRANSFER PROTOCOLS
-   12. [19]SECURITY
-   13. [20]MISCELLANEOUS USER REPORTS
-   14. [21]THIRD-PARTY DRIVERS
-
-   Quick Links:   [ [22]Linux ] [ [23]*BSD ] [[24]Mac OS X] [ [25]AIX ] [
-   [26]HP-UX ] [ [27]Solaris ] [ [28]SCO ] [ [29]DEC/Compaq ]
-    ________________________________________________________________________
-
-  1. INTRODUCTION
-
-   [ [30]Top ] [ [31]Contents ] [ [32]Next ]
-
-   SECTION CONTENTS
-
-  1.1. [33]Documentation
-  1.2. [34]Technical Support
-  1.3. [35]The Year 2000
-  1.4. [36]The Euro
-
-   THIS IS WHAT USED TO BE CALLED the "beware file" for the Unix version
-   of C-Kermit, previously distributed as ckubwr.txt and, before that, as
-   ckuker.bwr, after the fashion of old Digital Equipment Corporation
-   (DEC) software releases that came with release notes (describing what
-   had changed) and a "beware file" listing known bugs, limitations,
-   "non-goals", and things to watch out for. The C-Kermit beware file has
-   been accumulating since 1985, and it applies to many different
-   hardware platforms and operating systems, and many versions of them,
-   so it is quite large. Prior to C-Kermit 8.0, it was distributed only
-   in plain-text format. Now it is available as a Web document with
-   links, internal cross references, and so on, to make it easier to use.
-
-   This document applies to Unix C-Kermit in general, as well as to
-   specific Unix variations like [37]Linux, [38]AIX, [39]HP-UX,
-   [40]Solaris, and so on, and should be read in conjunction with the
-   [41]platform-independent C-Kermit beware file, which contains similar
-   information, but applying to all versions of C-Kermit (VMS, Windows,
-   OS/2, AOS/VS, VOS, etc, as well as to Unix).
-
-   There is much in this document that is (only) of historical interest.
-   The navigation links should help you skip directly to the sections
-   that are relevant to you. Numerous offsite Web links are supposed to
-   lead to further information but, as you know, Web links go stale
-   frequently and without warning. If you can supply additional,
-   corrected, updated, or better Web links, please feel free to [42]let
-   us know.
-
-  1.1. Documentation
-
-   [ [43]Top ] [ [44]Contents ] [ [45]Next ]
-
-   C-Kermit 6.0 is documented in the book [46]Using C-Kermit, Second
-   Edition, by Frank da Cruz and Christine M. Gianone, Digital Press,
-   Burlington, MA, USA, ISBN 1-55558-164-1 (1997), 622 pages. This
-   remains the definitive C-Kermit documentation. Until the third edition
-   is published (sorry, there is no firm timeframe for this), please also
-   refer to:
-
-   [47]Supplement to Using C-Kermit, Second Edition, For C-Kermit 7.0
-          Thorough documentation of features new to version 7.0.
-
-   [48]Supplement to Using C-Kermit, Second Edition, For C-Kermit 8.0
-          Thorough documentation of features new to version 8.0.
-
-  1.2. Technical Support
-
-   [ [49]Top ] [ [50]Contents ] [ [51]Section Contents ] [ [52]Next ] [
-   [53]Previous ]
-
-   For information on how to get technical support, please visit:
-
-    [54]http://www.columbia.edu/kermit/support.html
-
-  1.3. The Year 2000
-
-   [ [55]Top ] [ [56]Contents ] [ [57]Section Contents ] [ [58]Next ] [
-   [59]Previous ]
-
-   The Unix version of C-Kermit, release 6.0 and later, is "Year 2000
-   compliant", but only if the underlying operating system is too.
-   Contact your Unix operating system vendor to find out which operating
-   system versions, patches, hardware, and/or updates are required.
-   (Quite a few old Unixes are still in operation in the new millenium,
-   but with their date set 28 years in the past so at least the non-year
-   parts of the calendar are correct.)
-
-   As of C-Kermit 6.0 (6 September 1996), post-millenium file dates are
-   recognized, transmitted, received, and reproduced correctly during the
-   file transfer process in C-Kermit's File Attribute packets. If
-   post-millenium dates are not processed correctly on the other end,
-   file transfer still takes place, but the modification or creation date
-   of the received file might be incorrect. The only exception would be
-   if the "file collision update" feature is being used to prevent
-   unnecessary transfer of files that have not changed since the last
-   time a transfer took place; in this case, a file might be transferred
-   unnecessarily, or it might not be transferred when it should have
-   been. Correct operation of the update feature depends on both Kermit
-   programs having the correct date and time.
-
-   Of secondary importance are the time stamps in the transaction and/or
-   debug logs, and the date-related script programming constructs, such
-   as \v(date), \v(ndate), \v(day), \v(nday), and perhaps also the
-   time-related ones, \v(time) and \v(ntime), insofar as they might be
-   affected by the date. The \v(ndate) is a numeric-format date of the
-   form yyyymmdd, suitable for both lexical and numeric comparison and
-   sorting: e.g. 19970208 or 20011231. If the underlying operating system
-   returns the correct date information, these variables will have the
-   proper values. If not, then scripts that make decisions based on these
-   variables might not operate correctly.
-
-   Most date-related code is based upon the C Library asctime() string,
-   which always has a four-digit year. In Unix, the one bit of code in
-   C-Kermit that is an exception to this rule is several calls to
-   localtime(), which returns a pointer to a tm struct, in which the year
-   is presumed to be expressed as "years since 1900". The code depends on
-   this assumption. Any platforms that violate it will need special
-   coding. As of this writing, no such platforms are known.
-
-   Command and script programming functions that deal with dates use
-   C-Kermit specific code that always uses full years.
-
-  1.4. The Euro
-
-   [ [60]Top ] [ [61]Contents ] [ [62]Section Contents ] [ [63]Previous ]
-
-   C-Kermit 7.0 and later support Unicode (ISO 10646), ISO 8859-15 Latin
-   Alphabet 9, PC Code Page 858, Windows Code Pages 1250 and 1251, and
-   perhaps other character sets, that encode the Euro symbol, and can
-   translate among them as long as no intermediate character-set is
-   involved that does not include the Euro.
-    ________________________________________________________________________
-
-  2. PREBUILT C-KERMIT BINARIES
-
-   [ [64]Top ] [ [65]Contents ] [ [66]Next ] [ [67]Previous ]
-
-   It is often dangerous to run a binary C-Kermit (or any other) program
-   built on a different computer. Particularly if that computer had a
-   different C compiler, libraries, operating system version, processor
-   features, etc, and especially if the program was built with shared
-   libraries, because as soon as you update the libraries on your system,
-   they no longer match the ones referenced in the binary, and the binary
-   might refuse to load when you run it, in which case you'll see error
-   messages similar to:
-
-  Could not load program kermit
-  Member shr4.o not found or file not an archive
-  Could not load library libcurses.a[shr4.o]
-  Error was: No such file or directory
-
-   (These samples are from AIX.) To avoid this problem, we try to build
-   C-Kermit with statically linked libraries whenever we can, but this is
-   increasingly impossible as shared libraries become the norm.
-
-   It is often OK to run a binary built on an earlier OS version, but it
-   is rarely possible (or safe) to run a binary built on a later one, for
-   example to run a binary built under Solaris 8 on Solaris 2.6.
-   Sometimes even the OS-or-library patch/ECO level makes a difference.
-
-   A particularly insidious problem occurs when a binary was built on a
-   version of the OS that has patches from the vendor (e.g. to
-   libraries); in many cases you won't be able to run such a binary on an
-   unpatched version of the same platform.
-
-   When in doubt, build C-Kermit from the source code on the computer
-   where it is to be run (if possible!). If not, ask us for a binary
-   specific to your configuration. We might have one, and if we don't, we
-   might be able to find somebody who will build one for you.
-    ________________________________________________________________________
-
-  3. NOTES ON SPECIFIC UNIX VERSIONS
-
-   [ [68]Top ] [ [69]Contents ] [ [70]Next ] [ [71]Previous ]
-
-   SECTION CONTENTS
-
-  3.0.  [72]C-KERMIT ON PC-BASED UNIXES
-  3.1.  [73]C-KERMIT AND AIX
-  3.2.  [74]C-KERMIT AND HP-UX
-  3.3.  [75]C-KERMIT AND LINUX
-  3.4.  [76]C-KERMIT AND NEXTSTEP
-  3.5.  [77]C-KERMIT AND QNX
-  3.6.  [78]C-KERMIT AND SCO
-  3.7.  [79]C-KERMIT AND SOLARIS
-  3.8.  [80]C-KERMIT AND SUNOS
-  3.9.  [81]C-KERMIT AND ULTRIX
-  3.10. [82]C-KERMIT AND UNIXWARE
-  3.11. [83]C-KERMIT AND APOLLO SR10
-  3.12. [84]C-KERMIT AND TANDY XENIX 3.0
-  3.13. [85]C-KERMIT AND OSF/1 (DIGITAL UNIX) (TRU64 UNIX)
-  3.14. [86]C-KERMIT AND SGI IRIX
-  3.15. [87]C-KERMIT AND THE BEBOX
-  3.16. [88]C-KERMIT AND DG/UX
-  3.17. [89]C-KERMIT AND SEQUENT DYNIX
-  3.18. [90]C-KERMIT AND {FREE,OPEN,NET}BSD
-  3.19. [91]C-KERMIT AND MAC OS X
-  3.20. [92]C-KERMIT AND COHERENT
-
-   The following sections apply to specific Unix versions. Most of them
-   contain references to FAQs (Frequently Asked Questions), but these
-   tend to be ephemeral. For possibly more current information see:
-
-  [93]http://www.faqs.org
-  [94]http://aplawrence.com/Unixart/newtounix.html
-
-   One thread that runs through many of them, and implicitly perhaps
-   through all, concerns the problems that occur when trying to dial out
-   on a serial device that is (also) enabled for dialing in. The
-   "solutions" to this problem are many, varied, diverse, and usually
-   gross, involving configuring the device for bidirectional use. This is
-   done in a highly OS-dependent and often obscure manner, and the
-   effects (good or evil) are also highly dependent on the particular OS
-   (and getty variety, etc). Many examples are given in the
-   [95]OS-specific sections below.
-
-   An important point to keep in mind is that C-Kermit is a
-   cross-platform, portable software program. It was not designed
-   specifically and only for your particular Unix version, or for that
-   matter, for Unix in particular at all. It also runs on VMS, AOS/VS,
-   VOS, and other non-Unix platforms. All the Unix versions of C-Kermit
-   share common i/o modules, with compile-time #ifdef constructions used
-   to account for the differences among the many Unix products and
-   releases. If you think that C-Kermit is behaving badly or missing
-   something on your particular Unix version, you might be right -- we
-   can't claim to be expert in hundreds of different OS / version /
-   hardware / library combinations. If you're a programmer, take a look
-   at the source code and [96]send us your suggested fixes or changes. Or
-   else just [97]send us a report about what seems to be wrong and we'll
-   see what we can do.
-    ________________________________________________________________________
-
-  3.0. C-KERMIT ON PC-BASED UNIXES
-
-   [ [98]Top ] [ [99]Contents ] [ [100]Section Contents ] [ [101]Next ]
-
-   Also see: [102]http://www.pcunix.com/.
-
-   SECTION CONTENTS
-
-  3.0.1. [103]Interrupt Conflicts
-  3.0.2. [104]Windows-Specific Hardware
-  3.0.3. [105]Modems
-  3.0.4. [106]Character Sets
-  3.0.5. [107]Keyboard, Screen, and Mouse Access
-  3.0.6. [108]Laptops
-
-  3.0.1. Interrupt Conflicts
-
-   [ [109]Top ] [ [110]Contents ] [ [111]Section Contents ] [ [112]Next ]
-
-   PCs are not the best platform for real operating systems like Unix.
-   The architecture suffers from numerous deficiencies, not the least of
-   which is the stiflingly small number of hardware interrupts (either 7
-   or 15, many of which are preallocated). Thus adding devices, using
-   multiple serial ports, etc, is always a challenge and often a
-   nightmare. The free-for-all nature of the PC market and the lack of
-   standards combined with the diversity of Unix OS versions make it
-   difficult to find drivers for any particular device on any particular
-   version of Unix.
-
-   Of special interest to Kermit users is the fact that there is no
-   standard provision in the PC architecture for more than 2
-   communication (serial) ports. COM3 and COM4 (or higher) will not work
-   unless you (a) find out the hardware address and interrupt for each,
-   (b) find out how to provide your Unix version with this information,
-   and (c) actually set up the configuration in the Unix startup files
-   (or whatever other method is used). Watch out for interrupt conflicts,
-   especially when using a serial mouse, and don't expect to be able to
-   use more than two serial ports.
-
-   The techniques for resolving interrupt conflicts are different for
-   each operating system (Linux, NetBSD, etc). In general, there is a
-   configuration file somewhere that lists COM ports, something like
-   this:
-
-  com0    at isa? port 0x3f8 irq 4      # DOS COM1
-  com1    at isa? port 0x2f8 irq 3      # DOS COM2
-
-   The address and IRQ values in this file must agree with the values in
-   the PC BIOS and with the ports themselves, and there must not be more
-   than one device with the same interrupt. Unfortunately, due to the
-   small number of available interrupts, installing new devices on a PC
-   almost always creates a conflict. Here is a typical tale from a Linux
-   user (Fred Smith) about installing a third serial port:
-
-     ...problems can come from a number of causes. The one I fought with
-     for some time, and finally conquered, was that my modem is on an
-     add-in serial port, cua3/IRQ5. By default IRQ5 has a very low
-     priority, and does not get enough service in times when the system
-     is busy to prevent losing data. This in turn causes many resends.
-     There are two 'fixes' that I know of, one is to relax hard disk
-     interrupt hogging by using the correct parameter to hdparm, but I
-     don't like that one because the hdparm man page indicates it is
-     risky to use. The other one, the one I used, was to get 'irqtune'
-     and use it to give IRQ5 the highest priority instead of nearly the
-     lowest. Completely cured the problem.
-
-   Here's another one from a newsgroup posting:
-
-     After much hair pulling, I've discovered why my serial port won't
-     work. Apparently my [PC] has three serial devices (two comm ports
-     and an IR port), of which only two at a time can be active. I
-     looked in the BIOS setup and noticed that the IR port was
-     activated, but didn't realize at the time that this meant that COM2
-     was thereby de-activated. I turned off the IR port and now the
-     serial port works as advertised.
-    ________________________________________________________________________
-
-  3.0.2. Windows-Specific Hardware
-
-   [ [113]Top ] [ [114]Contents ] [ [115]Section Contents ] [ [116]Next ]
-   [ [117]Previous ]
-
-   To complicate matters, the PC platform is becoming increasingly and
-   inexorably Windows-oriented. More and more add-on devices are "Windows
-   only" -- meaning they are incomplete and rely on proprietary
-   Windows-based software drivers to do the jobs that you would expect
-   the device itself to do. PCMCIA, PCI, or "Plug-n-Play" devices are
-   rarely supported on PC-based Unix versions such as SCO; Winmodems,
-   Winprinters, and the like are not supported on any Unix variety (with
-   [118]a few exceptions). The self-proclaimed Microsoft PC 97 (or later)
-   standard only makes matters worse since its only purpose to ensure
-   that PCs are "optimized to run Windows 95 and Windows NT 4.0 and
-   future versions of these operating systems".
-
-   With the exception noted (the Lucent modem, perhaps a handful of
-   others by the time you read this), drivers for "Win" devices are
-   available only for Windows, since the Windows market dwarfs that of
-   any particular Unix brand, and for that matter all Unixes (or for that
-   matter, all non-Windows operating systems) combined. If your version
-   of Unix (SCO, Linux, BSDI, FreeBSD, etc) does not support a particular
-   device, then C-Kermit can't use it either. C-Kermit, like any Unix
-   application, must access all devices through drivers and not directly
-   because Unix is a real operating system.
-
-   Don't waste time thinking that you, or anybody else, could write a
-   Linux (or other Unix) driver for a Winmodem or other "Win" device.
-   First of all, these devices generally require realtime control, but
-   since Unix is a true multitasking operating system, realtime device
-   control is not possible outside the kernel. Second, the specifications
-   for these devices are secret and proprietary, and each one (and each
-   version of each one) is potentially different. Third, a Winmodem
-   driver would be enormously complex; it would take years to write and
-   debug, by which time it would be obsolete.
-
-   A more recent generation of PCs (circa 1999-2000) is marketed as
-   "Legacy Free". One can only speculate what that could mean. Most
-   likely it means it will ONLY run the very latest versions of Windows,
-   and is made exclusively of Winmodems, Winprinters, Winmemory, and
-   Win-CPU-fans (Legacy Free is a concept [119]pioneered by Microsoft).
-
-   Before you buy a new PC or add-on equipment, especially serial ports,
-   internal modems, or printers, make sure they are compatible with your
-   version of Unix. This is becoming an ever-greater challenge; only a
-   huge company like Microsoft can afford to be constantly cranking out
-   and/or verifying drivers for the thousands of video boards, sound
-   cards, network adapters, SCSI adapters, buses, etc, that spew forth in
-   an uncontrolled manner from all corners of the world on a daily basis.
-   With very few exceptions, makers of PCs assemble the various
-   components and then verify them only with Windows, which they must do
-   since they are, no doubt, preloading the PC with Windows. To find a
-   modern PC that is capable of running a variety of non-Windows
-   operating systems (e.g. Linux, SCO OpenServer, Unixware, and Solaris)
-   is a formidable challenge requiring careful study of each vendor's
-   "compatibility lists" and precise attention to exact component model
-   numbers and revision levels.
-    ________________________________________________________________________
-
-  3.0.3. Modems
-
-   [ [120]Top ] [ [121]Contents ] [ [122]Section Contents ] [ [123]Next ]
-   [ [124]Previous ]
-
-   External modems are recommended:
-
-     * They don't need any special drivers.
-     * You can use the lights and speaker to troubleshoot dialing.
-     * You can share them among all types of computers.
-     * You can easily turn them off and on when power-cycling seems
-       warranted.
-     * They are more likely to have manuals.
-
-   Internal PC modems (even when they are not Winmodems, which is
-   increasingly unlikely in new PCs) are always trouble, especially in
-   Unix. Even when they work for dialing out, they might not work for
-   dialing in, etc. Problems that occur when using an internal modem can
-   almost always be eliminated by switching to an external one. Even when
-   an internal modem is not a Winmodem or Plug-n-Play, it is often a
-   no-name model of unknown quality -- not the sort of thing you want
-   sitting directly on your computer's bus. (Even if it does not cause
-   hardware problems, it probably came without a command list, so no Unix
-   software will know how to control it.) For more about Unix compatible
-   modems, see:
-
-  [125]http://www.idir.net/~gromitkc/winmodem.html
-
-   Remember that PCs, even now -- more than two decades after they were
-   first introduced -- are not (in general) capable of supporting more
-   than 2 serial devices. Here's a short success story from a recent
-   newsgroup posting: "I have a Diamond SupraSonic II dual modem in my
-   machine. What I had to end up doing is buying a PS/2 mouse and port
-   and install it. Had to get rid of my serial mouse. I also had to
-   disable PnP in my computer bios. I was having IRQ conflicts between my
-   serial mouse and 'com 3'. Both modems work fine for me. My first modem
-   is ttyS0 and my second is ttyS1." Special third-party multiport boards
-   such as [126]DigiBoard are available for certain Unix platforms
-   (typically SCO, maybe Linux) that come with special platform-specific
-   drivers.
-    ________________________________________________________________________
-
-  3.0.4. Character Sets
-
-   [ [127]Top ] [ [128]Contents ] [ [129]Section Contents ] [ [130]Next ]
-   [ [131]Previous ]
-
-   PCs generally have PC code pages such as CP437 or CP850, and these are
-   often used by PC-based Unix operating systems, particularly on the
-   console. These are supported directly by C-Kermit's SET FILE
-   CHARACTER-SET and SET TERMINAL CHARACTER-SET commands. Some PC-based
-   Unix versions, such as recent Red Hat Linux releases, might also
-   support Microsoft Windows code pages such as CP1252, or even Latin
-   Alphabet 1 itself (perhaps displayed with CP437 glyphs). (And work is
-   in progress to support Unicode UTF8 in Linux.)
-
-   Certain Windows code pages are not supported directly by C-Kermit, but
-   since they are ISO Latin Alphabets with nonstandard "extensions" in
-   the C1 control range, you can substitute the corresponding Latin
-   alphabet (or other character set) in any C-Kermit character-set
-   related commands:
-
-  Windows Code Page    Substitution
-   CP 1004              Latin-1
-   CP 1051              HP Roman-8
-
-   Other Windows code pages are mostly (or totally) incompatible with
-   their Latin Alphabet counterparts (e.g. CP1250 and Latin-2), and
-   several of these are already supported by C-Kermit 7.0 and later
-   (1250, 1251, and 1252).
-    ________________________________________________________________________
-
-  3.0.5. Keyboard, Screen, and Mouse Access
-
-   [ [132]Top ] [ [133]Contents ] [ [134]Section Contents ] [ [135]Next ]
-   [ [136]Previous ]
-
-   Finally, note that as a real operating system, Unix (unlike Windows)
-   does not provide the intimate connection to the PC keyboard, screen,
-   and mouse that you might expect. Unix applications can not "see" the
-   keyboard, and therefore can not be programmed to understand F-keys,
-   Editing keys, Arrow keys, Alt-key combinations, and the like. This is
-   because:
-
-    a. Unix is a portable operating system, not only for PCs;
-    b. Unix sessions can come from anywhere, not just the PC's own
-       keyboard and screen; and:
-    c. even though it might be possible for an application that actually
-       is running on the PC's keyboard and screen to access these devices
-       directly, there are no APIs (outside of X) for this.
-    ________________________________________________________________________
-
-  3.0.6. Laptops
-
-   [ [137]Top ] [ [138]Contents ] [ [139]Section Contents ] [
-   [140]Previous ]
-
-   (To be filled in . . .)
-    ________________________________________________________________________
-
-  3.1. C-KERMIT AND AIX
-
-   [ [141]Top ] [ [142]Contents ] [ [143]Section Contents ] [ [144]Next ]
-   [ [145]Previous ]
-
-   SECTION CONTENTS
-
-  3.1.1. [146]AIX: General
-  3.1.2. [147]AIX: Network Connections
-  3.1.3. [148]AIX: Serial Connections
-  3.1.4. [149]AIX: File Transfer
-  3.1.5. [150]AIX: Xterm Key Map
-
-   For additional information see:
-     * [151]http://www.emerson.emory.edu/services/aix-faq/
-     * [152]http://www.faqs.org/faqs/by-newsgroup/comp/comp.unix.aix.html
-     * [153]http://www.cis.ohio-state.edu/hypertext/faq/usenet/aix-faq/to
-       p.html
-     * [154]http://aixpdslib.seas.ucla.edu/
-     * [155]http://www.rootvg.net (AIX history)
-     * [156]ftp://rtfm.mit.edu/pub/usenet/news.answers/aix-faq/part1
-     * [157]ftp://mirrors.aol.com/pub/rtfm/usenet-by-hierarchy/comp/unix/
-       aix
-
-   and/or read the [158]comp.unix.aix newsgroup.
-      ______________________________________________________________________
-
-    3.1.1. AIX: General
-
-   [ [159]Top ] [ [160]Contents ] [ [161]Section Contents ] [ [162]Next ]
-
-   About AIX version numbers: "uname -a" tells the two-digit version
-   number, such as 3.2 or 4.1. The three-digit form can be seen with the
-   "oslevel" command (this information is unavailable at the API level
-   and is reportedly obtained by scanning the installed patch list).
-   Supposedly all three-digit versions within the same two-digit version
-   (e.g. 4.3.1, 4.3.2) are binary compatible; i.e. a binary built on any
-   one of them should run on all others, but who knows. Most AIX
-   advocates tell you that any AIX binary will run on any AIX version
-   greater than or equal to the one under which it was built, but
-   experience with C-Kermit suggests otherwise. It is always best to run
-   a binary built under your exact same AIX version, down to the third
-   decimal place, if possible. Ideally, build it from source code
-   yourself. Yes, this advice would be easier to follow if AIX came with
-   a C compiler.
-      ______________________________________________________________________
-
-    3.1.2. AIX: Network Connections
-
-   [ [163]Top ] [ [164]Contents ] [ [165]Section Contents ] [ [166]Next ]
-   [ [167]Previous ]
-
-   File transfers into AIX 4.2 or 4.3 through the AIX Telnet or Rlogin
-   server have been observed to fail (or accumulate huge numbers of
-   correctable errors, or even disconnect the session), when exactly the
-   same kind of transfers into AIX 4.1 work without incident, as do such
-   transfers into all non-AIX platforms on the same kind of connections
-   (with a few exceptions noted elsewhere in this document). AIX 4.3.3
-   seems to be particularly fragile in this regard; the weakness seems to
-   be in its pseudoterminal (pty) driver. High-speed streaming transfers
-   work perfectly, however, if the AIX Telnet server and pty driver are
-   removed from the picture; e.g, by using "set host * 3000" on AIX.
-
-   The problem can be completely cured by replacing the IBM Telnet server
-   with [168]MIT's Kerberos Telnet server -- even if you don't actually
-   use the Kerberos part. Diagnosis: AIX pseudoterminals (which are
-   controlled by the Telnet server to give you a login terminal for your
-   session) have quirks that not even IBM knows about. The situation with
-   AIX 5.x is not known, but if it has the same problem, the same cure is
-   available.
-
-   Meanwhile, the only remedy when going through the IBM Telnet server is
-   to cut back on Kermit's performance settings until you find a
-   combination that works:
-
-     * SET STREAMING OFF
-     * SET WINDOW-SIZE small-number
-     * SET { SEND, RECEIVE } PACKET-LENGTH small-number
-     * SET PREFIXING { CAUTIOUS, ALL }
-
-   In some cases, severe cutbacks are required, e.g. those implied by the
-   ROBUST command. Also be sure that the AIX C-Kermit on the remote end
-   has "set flow none" (which is the default). NOTE: Maybe this one can
-   also be addressed by starting AIX telnetd with the "-a" option. The
-   situation with SSH connections is not known, but almost certainly the
-   same.
-
-   When these problems occur, the system error log contains:
-
-  LABEL:          TTY_TTYHOG
-  IDENTIFIER:     0873CF9F
-  Type:           TEMP
-  Resource Name:  pts/1
-
-  Description
-  TTYHOG OVER-RUN
-
-  Failure Causes
-  EXCESSIVE LOAD ON PROCESSOR
-
-  Recommended Actions
-  REDUCE SYSTEM LOAD.
-  REDUCE SERIAL PORT BAUD RATE
-
-   Before leaving the topic of AIX pseudoterminals, it is very likely
-   that Kermit's PTY and SSH commands do not work well either, for the
-   same reason that Telnet connections into AIX don't work well. A brief
-   test with "pty rlogin somehost" got a perfectly usable terminal
-   (CONNECT) session, but file-transfer problems like those just
-   described.
-
-   Reportedly, telnet from AIX 4.1-point-something to non-Telnet ports
-   does not work unless the port number is in the /etc/services file;
-   it's not clear from the report whether this is a problem with AIX
-   Telnet (in which case it would not affect Kermit), or with the sockets
-   library (in which case it would). The purported fix is IBM APAR
-   IX61523.
-
-   C-Kermit SET HOST or TELNET from one AIX 3.1 (or earlier) system to
-   another won't work right unless you set your local terminal type to
-   something other than AIXTERM. When your terminal type is AIXTERM, AIX
-   TELNET sends two escapes whenever you type one, and the AIX telnet
-   server swallows one of them. This has something to do with the "hft"
-   device. This behavior seems to be removed in AIX 3.2 and later.
-      ______________________________________________________________________
-
-    3.1.3. AIX: Serial Connections
-
-   [ [169]Top ] [ [170]Contents ] [ [171]Section Contents ] [ [172]Next ]
-   [ [173]Previous ]
-
-   In AIX 3, 4, or 5, C-Kermit won't be able to "set line /dev/tty0" (or
-   any other dialout device) if you haven't installed "cu" or "uucp" on
-   your system, because installing these is what creates the UUCP
-   lockfile directory. If SET LINE commands always result in "Sorry,
-   access to lock denied", even when C-Kermit has been given the same
-   owner, group, and permissions as cu:
-
-  -r-sr-xr-x   1 uucp     uucp       67216 Jul 27 1999  cu
-
-   and even when you run it as root, then you must go back and install
-   "cu" from your AIX installation media.
-
-   According to IBM's "From Strength to Strength" document (21 April
-   1998), in AIX 4.2 and later "Async supports speeds on native serial
-   ports up to 115.2kbps". However, no API is documented to achieve
-   serial speeds higher than 38400 bps. Apparently the way to do this --
-   which might or might not work only on the IBM 128-port multiplexer --
-   is:
-
-  cxma-stty fastbaud /dev/tty0
-
-   which, according to "man cxma-stty":
-
-     fastbaud Alters the baud rate table, so 50 baud becomes 57600 baud.
-     -fastbaud Restores the baud rate table, so 57600 baud becomes 50
-     baud.
-
-   Presumably (but not certainly) this extrapolates to 110 "baud" becomes
-   76800 bps, and 150 becomes 115200 bps. So to use high serial speeds in
-   AIX 4.2 or 4.3, the trick would be to give the "cxma-stty fastbaud"
-   command for the desired tty device before starting Kermit, and then
-   use "set speed 50", "set speed 110", or "set speed 150" to select
-   56700, 76800, or 115200 bps. It is not known whether cxma-stty
-   requires privilege.
-
-   According to one report, "Further investigation with IBM seems to
-   indicate that the only hardware capable of doing this is the 128-port
-   multiplexor with one (or more) of the 16 port breakout cables
-   (Enhanced Remote Async Node 16-Port EIA-232). We are looking at about
-   CDN$4,000 in hardware just to hang a 56kb modem on there. Of course,
-   we can then hang 15 more, if we want. This hardware combo is described
-   to be good to 230.4kbps."
-
-   Another report says (quote from AIX newsgroup, March 1999):
-
-     The machine type and the adapter determine the speed that one can
-     actually run at. The older microchannel machines have much slower
-     crystal frequencies and may not go beyond 76,800. A feature put
-     into AIX 421 allows one to key in non-POSIX baud rates and if the
-     uart can support that speed, it will get set. this applies also to
-     43p's and beyond. 115200 is the max for the 43P's native serial
-     port. As crytal frequencies continue to increase, the built-in
-     serial ports speeds will improve. To use 'uucp' or 'ate' at the
-     higher baud rates, configure the port for the desired speed, but
-     set the speed of uucp or ate to 50. Any non-POSIX speeds set in the
-     ttys configuration will the be used. In the case of the 128-port
-     adapters or the ISA 8-port or PCI 8-port adapter, there are only a
-     few higher baud rates.
-
-    a. Change the port to enable high baud rates:
-          + B50 for 57600
-          + B75 for 76800
-          + B110 for 115200
-          + B200 for 230000
-    b. chdev -l ttyX -a fastbaud=enable
-          + For the 128 ports original style rans, only 57600 bps is
-            supported.
-          + For the new enhanced RANs, up to 230Kbps is supported.
-
-   In AIX 2.2.1 on the RT PC with the 8-port multiplexer, SET SPEED 38400
-   gives 9600 bps, but SET SPEED 19200 gives 19200 (on the built-in S1
-   port).
-
-   Note that some RS/6000s (e.g. the IBM PowerServer 320) have
-   nonstandard rectangular 10-pin serial ports; the DB-25 connector is
-   NOT a serial port; it is a parallel printer port. IBM cables are
-   required for the serial ports, (The IBM RT PC also had rectangular
-   serial ports -- perhaps the same as these, perhaps different.)
-
-   If you dial in to AIX through a modem that is connected directly to an
-   AIX port (e.g. on the 128-port multiplexer) and find that data is
-   lost, especially when uploading files to the AIX system (and system
-   error logs report buffer overruns on the port):
-
-    1. Make sure the port and modem are BOTH configured for hardware
-       (RTS/CTS) flow control. The port is configured somewhere in the
-       system configuration, outside of Kermit.
-    2. Tell C-Kermit to "set flow keep"; experimentation shows that SET
-       FLOW RTS/CTS has no effect when used in remote mode (i.e. on
-       /dev/tty, as opposed to a specify port device).
-    3. Fixes for bugs in the original AIX 4.2 tty (serial i/o) support
-       and other AIX bugs are available from IBM at:
-  [174]http://service.software.ibm.com/rs6000/
-       Downloads -> Software Fixes -> Download FixDist gets an
-       application for looking up known problems.
-
-   Many problems reported with bidirectional terminal lines on AIX 3.2.x
-   on the RS/6000. Workaround: don't use bidirectional terminal lines, or
-   write a shell-script wrapper for Kermit that turns getty off on the
-   line before starting Kermit, or before Kermit attempts to do the SET
-   LINE. (But note: These problems MIGHT be fixed in C-Kermit 6.0 and
-   later.) The commands for turning getty off and on (respectively) are
-   /usr/sbin/pdisable and /usr/sbin/penable.
-      ______________________________________________________________________
-
-    3.1.4. AIX: File Transfer
-
-   [ [175]Top ] [ [176]Contents ] [ [177]Section Contents ] [ [178]Next ]
-   [ [179]Previous ]
-
-   Evidently AIX 4.3 (I don't know about earlier versions) does not allow
-   open files to be overwritten. This can cause Kermit transfers to fail
-   when FILE COLLISION is OVERWRITE, where they might work on other Unix
-   varieties or earlier AIX versions.
-
-   Transfer of binary -- and maybe even text -- files can fail in AIX if
-   the AIX terminal has particular port can have character-set
-   translation done for it by the tty driver. The following advice from a
-   knowledgeable AIX user:
-
-     [This feature] has to be checked (and set/cleared) with a separate
-     command, unfortunately stty doesn't handle this. To check:
-
-  $ setmaps
-  input map: none installed
-  output map: none installed
-
-     If it says anything other than "none installed" for either one, it
-     is likely to cause a problem with kermit. To get rid of installed
-     maps:
-
-  $ setmaps -t NOMAP
-
-     However, I seem to recall that with some versions of AIX before
-     3.2.5, only root could change the setting. I'm not sure what
-     versions - it might have only been under AIX 3.1 that this was
-     true. At least with AIX 3.2.5 an ordinary user can set or clear the
-     maps.
-
-   On the same problem, another knowledgeable AIX user says:
-
-     The way to get information on the NLS mapping under AIX (3.2.5
-     anyway) is as follows. From the command line type:
-
-  lsattr -l tty# -a imap -a omap -E -H
-
-     Replace the tty number for the number sign above. This will give a
-     human readable output of the settings that looks like this;
-
-  # lsattr -l tty2 -a imap -a omap -E -H
-  attribute value description     user_settable
-
-  imap      none  INPUT map file  True
-  omap      none  OUTPUT map file True
-
-     If you change the -H to a -O, you get output that can easily be
-     processed by another program or a shell script, for example:
-
-  # lsattr -l tty2 -a imap -a omap -E -O
-  #imap:omap
-  none:none
-
-     To change the settings from the command line, the chdev command is
-     used with the following syntax.
-
-  chdev -l tty# -a imap='none' -a omap='none'
-
-     Again substituting the appropriate tty port number for the number
-     sign, "none" being the value we want for C-Kermit. Of course, the
-     above can also be changed by using the SMIT utility and selecting
-     devices - tty. (...end quote)
-      ______________________________________________________________________
-
-    3.1.5. AIX: Xterm Key Map
-
-   [ [180]Top ] [ [181]Contents ] [ [182]Section Contents ] [
-   [183]Previous ]
-
-   Here is a sample configuration for setting up an xterm keyboard for
-   VT220 or higher terminal emulation on AIX, courtesy of Bruce Momjian,
-   Drexel Hill, PA. Xterm can be started like this:
-
-  xterm $XTERMFLAGS +rw +sb +ls $@ -tm 'erase ^? intr ^c' -name vt220 \
-          -title vt220 -tn xterm-220 "$@" &
-
----------------------------------------------------------------------------
-  XTerm*VT100.Translations: #override \n\
-          <Key>Home: string(0x1b) string("[3~") \n \
-          <Key>End: string(0x1b) string("[4~") \n
-  vt220*VT100.Translations: #override \n\
-  Shift   <Key>F1: string("[23~") \n \
-  Shift   <Key>F2: string("[24~") \n \
-  Shift   <Key>F3: string("[25~") \n \
-  Shift   <Key>F4: string("[26~") \n \
-  Shift   <Key>F5: string("[K~") \n \
-  Shift   <Key>F6: string("[31~") \n \
-  Shift   <Key>F7: string("[31~") \n \
-  Shift   <Key>F8: string("[32~") \n \
-  Shift   <Key>F9: string("[33~") \n \
-  Shift   <Key>F10: string("[34~") \n \
-  Shift   <Key>F11: string("[28~") \n \
-  Shift   <Key>F12: string("[29~") \n \
-          <Key>Print: string(0x1b) string("[32~") \n\
-          <Key>Cancel: string(0x1b) string("[33~") \n\
-          <Key>Pause: string(0x1b) string("[34~") \n\
-          <Key>Insert: string(0x1b) string("[2~") \n\
-          <Key>Delete: string(0x1b) string("[3~") \n\
-          <Key>Home: string(0x1b) string("[1~") \n\
-          <Key>End: string(0x1b) string("[4~") \n\
-          <Key>Prior: string(0x1b) string("[5~") \n\
-          <Key>Next: string(0x1b) string("[6~") \n\
-          <Key>BackSpace: string(0x7f) \n\
-          <Key>Num_Lock: string(0x1b) string("OP") \n\
-          <Key>KP_Divide: string(0x1b) string("Ol") \n\
-          <Key>KP_Multiply: string(0x1b) string("Om") \n\
-          <Key>KP_Subtract: string(0x1b) string("OS") \n\
-          <Key>KP_Add: string(0x1b) string("OM") \n\
-          <Key>KP_Enter: string(0x1b) string("OM") \n\
-          <Key>KP_Decimal: string(0x1b) string("On") \n\
-          <Key>KP_0: string(0x1b) string("Op") \n\
-          <Key>KP_1: string(0x1b) string("Oq") \n\
-          <Key>KP_2: string(0x1b) string("Or") \n\
-          <Key>KP_3: string(0x1b) string("Os") \n\
-          <Key>KP_4: string(0x1b) string("Ot") \n\
-          <Key>KP_5: string(0x1b) string("Ou") \n\
-          <Key>KP_6: string(0x1b) string("Ov") \n\
-          <Key>KP_7: string(0x1b) string("Ow") \n\
-          <Key>KP_8: string(0x1b) string("Ox") \n\
-          <Key>KP_9: string(0x1b) string("Oy") \n
-
-  !       <Key>Up: string(0x1b) string("[A") \n\
-  !       <Key>Down: string(0x1b) string("[B") \n\
-  !       <Key>Right: string(0x1b) string("[C") \n\
-  !       <Key>Left: string(0x1b) string("[D") \n\
-
-  *visualBell:    true
-  *saveLines:     1000
-  *cursesemul:    true
-  *scrollKey:     true
-  *scrollBar:     true
-    ________________________________________________________________________
-
-  3.2. C-KERMIT AND HP-UX
-
-   [ [184]Top ] [ [185]Contents ] [ [186]Section Contents ] [ [187]Next ]
-   [ [188]Previous ]
-
-   SECTION CONTENTS
-
-  3.2.0. [189]Common Problems
-  3.2.1. [190]Building C-Kermit on HP-UX
-  3.2.2. [191]File Transfer
-  3.2.3. [192]Dialing Out and UUCP Lockfiles in HP-UX
-  3.2.4. [193]Notes on Specific HP-UX Releases
-  3.2.5. [194]HP-UX and X.25
-
-   REFERENCES
-
-   For further information, read the [195]comp.sys.hp.hpux newsgroup.
-
-   C-Kermit is included as part of the HP-UX operating system by contract
-   between Hewlett Packard and Columbia University for HP-UX 10.00 and
-   later. Each level of HP-UX includes a freshly built C-Kermit binary in
-   /bin/kermit, which should work correctly. Binaries built for regular
-   HP-UX may be used on Trusted HP-UX and vice-versa, except for use as
-   IKSD because of the different authentication methods.
-
-   Note that HP does not update C-Kermit versions for any but its most
-   current HP-UX release. So, for example, HP-UX 10.20 has C-Kermit 6.0;
-   11.00 has C-Kermit 7.0, and 11.22 has 8.0. Of course, as with all
-   software, older Kermit versions have bugs (such as buffer overflow
-   vulnerabilities) that are fixed in later versions. From time to time,
-   HP discovers one of these (long-ago fixed) bugs and issues a security
-   alert for the older OS's, recommending some draconian measure to avoid
-   the problem. The true fix in each situation is to install the current
-   release of C-Kermit.
-
-  3.2.0. Common Problems
-
-   [ [196]Top ] [ [197]Contents ] [ [198]Section Contents ] [ [199]Next ]
-
-   Some HP workstations have a BREAK/RESET key. If you hit this key while
-   C-Kermit is running, it might kill or suspend the C-Kermit process.
-   C-Kermit arms itself against these signals, but evidently the
-   BREAK/RESET key is -- at least in some circumstances, on certain HP-UX
-   versions -- too powerful to be caught. (Some report that the first
-   BREAK/RESET shows up as SIGINT and is caught by C-Kermit's former
-   SIGINT handler even when SIGINT is currently set to SIG_IGN; the
-   second kills Kermit; other reports suggest the first BREAK/RESET sends
-   a SIGTSTP (suspend signal) to Kermit, which it catches and suspends
-   itself. You can tell C-Kermit to ignore suspend signals with SET
-   SUSPEND OFF. You can tell C-Kermit to ignore SIGINT with SET COMMAND
-   INTERRUPTION OFF. It is not known whether these commands also grant
-   immunity to the BREAK/RESET key (one report states that with SET
-   SUSPEND OFF, the BREAK/RESET key is ignored the first four times, but
-   kills Kermit the 5th time). In any case:
-
-    1. If this key is mapped to SIGINT or SIGTSTP, C-Kermit catches or
-       ignores it, depending on which mode (CONNECT, command, etc) Kermit
-       is in.
-    2. If it causes HP-UX to kill C-Kermit, there is nothing C-Kermit can
-       do to prevent it.
-
-   When HP-UX is on the remote end of the connection, it is essential
-   that HP-UX C-Kermit be configured for Xon/Xoff flow control (this is
-   the default, but in case you change it and then experience
-   file-transfer failures, this is a likely reason).
-    ________________________________________________________________________
-
-  3.2.1. Building C-Kermit on HP-UX
-
-   [ [200]Top ] [ [201]Contents ] [ [202]Section Contents ] [ [203]Next ]
-   [ [204]Previous ]
-
-     This section applies mainly to old (pre-10.20) HP-UX version on
-     old, slow, and/or memory-constrained hardware.
-
-   During the C-Kermit 6.0 Beta cycle, something happened to ckcpro.w
-   (or, more precisely, the ckcpro.c file that is generated from it)
-   which causes HP optimizing compilers under HP-UX versions 7.0 and 8.0
-   (apparently on all platforms) as well as under HP-UX 9.0 on Motorola
-   platforms only, to blow up. In versions 7.0 and 8.0 the problem has
-   spread to other modules.
-
-   The symptoms vary from the system grinding to a halt, to the compiler
-   crashing, to the compilation of the ckcpro.c module taking very long
-   periods of time, like 9 hours. This problem is handled by compiling
-   the modules that tickle it without optimization; the new C-Kermit
-   makefile takes care of this, and shows how to do it in case the same
-   thing begins happening with other modules.
-
-   On HP-UX 9.0, a kernel parameter, maxdsiz (maximum process data
-   segment size), seems to be important. On Motorola systems, it is 16MB
-   by default, whereas on RISC systems the default is much bigger.
-   Increasing maxdsiz to about 80MB seems to make the problem go away,
-   but only if the system also has a lot of physical memory -- otherwise
-   it swaps itself to death.
-
-   The optimizing compiler might complain about "some optimizations
-   skipped" on certain modules, due to lack of space available to the
-   optimizer. You can increase the space (the incantation depends on the
-   particular compiler version -- see the [205]makefile), but doing so
-   tends to make the compilations take a much longer time. For example,
-   the "hpux0100o+" makefile target adds the "+Onolimit" compiler flag,
-   and about an hour to the compile time on an HP-9000/730. But it *does*
-   produce an executable that is about 10K smaller :-)
-
-   In the makefile, all HP-UX entries automatically skip optimization of
-   problematic modules.
-    ________________________________________________________________________
-
-  3.2.2. File Transfer
-
-   [ [206]Top ] [ [207]Contents ] [ [208]Section Contents ] [ [209]Next ]
-   [ [210]Previous ]
-
-   Telnet connections into HP-UX versions up to and including 11.11 (and
-   possibly 11.20) tend not to lend themselves to file transfer due to
-   limitations, restrictions, and/or bugs in the HP-UX Telnet server
-   and/or pseudoterminal (pty) driver.
-
-   In C-Kermit 6.0 (1996) an unexpected slowness was noted when
-   transferring files over local Ethernet connections when an HP-UX
-   system (9.05 or 10.00) was on the remote end. The following experiment
-   was conducted to determine the cause. C-Kermit 6.0 was used; the
-   situation is slightly better using C-Kermit 7.0's streaming feature
-   and HP-UX 10.20 on the far end.
-
-   The systems were HP-UX 10.00 (on 715/33) and SunOS 4.1.3 (on
-   Sparc-20), both on the same local 10Mbps Ethernet, packet length 4096,
-   parity none, control prefixing "cautious", using only local disks on
-   each machine -- no NFS. In the C-Kermit 6.0 (ACK/NAK) case, the window
-   size was 20; in the streaming case there is no window size (i.e. it is
-   infinite). The test file was C-Kermit executable, transferred in
-   binary mode. Conditions were relatively poor: the Sun and the local
-   net heavily loaded; the HP system is old, slow, and
-   memory-constrained.
-
-                   C-Kermit 6.0...    C-Kermit 7.0...
- Local    Remote   ACK/NAK........    Streaming......
- Client   Server   Send    Receive    Send    Receive
-  Sun      HP       36       18        64       18
-  HP       HP       25       15        37       16
-  HP       Sun      77       83       118       92
-  Sun      Sun      60       60       153      158
-
-   So whenever HP is the remote we have poor performance. Why?
-
-     * Changing file display to CRT has no effect (so it's not the curses
-       library on the client side).
-     * Changing TCP RECV-BUFFER or SEND-BUFFER has little effect.
-     * Telling the client to make a binary-mode connection (SET TELNET
-       BINARY REQUESTED, which successfully negotiates a binary
-       connection) has no effect on throughput.
-
-   BUT... If I start HP-UX C-Kermit as a TCP service:
-
-  set host * 3000
-  server
-
-   and then from the client "set host xxx 3000", I get:
-
-                   C-Kermit 6.0...    C-Kermit 7.0...
- Local    Remote   ACK/NAK........    Streaming......
- Client   Server   Send    Receive    Send    Receive
-  Sun      HP       77       67       106      139
-  HP       HP       50       50        64       62
-  HP       Sun      57       85       155      105
-  Sun      Sun      57       50       321      314
-
-   Therefore the HP-UX telnet server or pty driver seems to be adding
-   more overhead than the SunOS one, and most others. When going through
-   this type of connection (a remote telnet server) there is little
-   Kermit can do improve matters, since the telnet server and pty driver
-   are between the two Kermits, and neither Kermit program can have any
-   influence over them (except putting the Telnet connection in binary
-   mode, but that doesn't help).
-
-   (The numbers for the HP-HP transfers are lower than the others since
-   both Kermit processes are running on the same slow 33MHz CPU.)
-
-   Matters seem to have deteriorated in HP-UX 11. Now file transfers over
-   Telnet connections fail completely, rather than just being slow. In
-   the following trial, a Telnet connection was made from Kermit 95 to
-   HP-UX 11.11 on an HP-9000/785/B2000 over local 10Mbps Ethernet running
-   C-Kermit 8.00 in server mode (under the HP-UX Telnet server):
-
-                   Text........    Binary......
-  Stream  Pktlen   GET     SEND    GET     SEND
-    On     4000    Fail    Fail    Fail    Fail
-    Off    4000    Fail    Fail    Fail    Fail
-    Off    2000    OK      Fail    OK      Fail
-    On     2000    OK      Fail    OK      Fail
-    On     3000    Fail    Fail    Fail    Fail
-    On     2500    Fail    Fail    Fail    Fail
-    On     2047    OK      Fail    OK      Fail
-    On     2045    OK      Fail    OK      Fail
-    Off     500    OK      OK      OK      OK
-    On      500    OK      Fail    OK      Fail
-    On      240    OK      Fail    OK      Fail
-
-   As you can see, downloads are problematic unless the receiver's Kermit
-   packet length is 2045 or less, but uploads work only with streaming
-   disabled and the packet length restricted to 500. To force file
-   transfers to work on this connection, the desktop Kermit must be told
-   to:
-
-  set streaming off
-  set receive packet-length 2000
-  set send packet-length 500
-
-   However, if a connection is made between the same two programs on the
-   same two computers over the same network, but this time a direct
-   socket-to-socket connection bypassing the HP-UX Telnet server and pty
-   driver (tell HP-UX C-Kermit to "set host /server * 3000 /raw"; tell
-   desktop client program to "set host blah 3000 /raw"), everything works
-   perfectly with the default Kermit settings (streaming, 4K packets,
-   liberal control-character unprefixing, 8-bit transparency, etc):
-
-                   Text........    Binary......
-  Stream  Pktlen   GET     SEND    GET     SEND
-    On     4000    OK      OK      OK      OK
-
-   And in this case, transfer rates were approximately 900,000 cps. To
-   verify that the behavior reported here is not caused by the new Kermit
-   release, the same experiment was performed on a Telnet connection from
-   the same PC over the same network to the old 715/33 running HP-UX
-   10.20 and C-Kermit 8.00. Text and binary uploads and downloads worked
-   perfectly (albeit slowly) with all the default settings -- streaming,
-   4K packets, etc.
-    ________________________________________________________________________
-
-  3.2.3. Dialing Out and UUCP Lockfiles in HP-UX
-
-   [ [211]Top ] [ [212]Contents ] [ [213]Section Contents ] [ [214]Next ]
-   [ [215]Previous ]
-
-   HP workstations do not come with dialout devices configured; you have
-   to do it yourself (as root). First look in /dev to see what's there;
-   for example in HP-UX 10.00 or later:
-
-  ls -l /dev/cua*
-  ls -l /dev/tty*
-
-   If you find a tty0p0 device but no cua0p0, you'll need to creat one if
-   you want to dial out; the tty0p0 does not work for dialing out. It's
-   easy: start SAM; in the main Sam window, double-click on Peripheral
-   Device, then in the Peripheral Devices window, double-click on
-   Terminals and Modems. In the Terminals and Modems dialog, click on
-   Actions, then choose "Add modem" and fill in the blanks. For example:
-   Port number 0, speed 57600 (higher speeds tend not to work reliably),
-   "Use device for calling out", do NOT "Receive incoming calls" (unless
-   you know what you are doing), leave "CCITT modem" unchecked unless you
-   really have one, and do select "Use hardware flow control (RTS/CTS)".
-   Then click OK. This creates cua0p0 as well as cul0p0 and ttyd0p0
-
-   If the following sequence:
-
-  set line /dev/cua0p0 ; or other device
-  set speed 115200     ; or other normal speed
-
-   produces the message "?Unsupported line speed". This means either that
-   the port is not configured for dialout (go into SAM as described above
-   and make sure "Use device for calling out" is selected), or else that
-   speed you have given (such as 460800) is supported by the operating
-   system but not by the physical device (in which case, use a lower
-   speed like 57600).
-
-   In HP-UX 9.0, serial device names began to change. The older names
-   looked like "/dev/cua00", "/dev/tty01", etc (sometimes with only one
-   digit). The newer names have two digits with the letter "p" in
-   between. HP-UX 8.xx and earlier have the older form, HP-UX 10.00 and
-   later have the newer form. HP-UX 9.xx has the newer form on Series 800
-   machines, and the older form on other hardware models. The situation
-   is summarized in the following table (the Convio 10.0 column applies
-   to HP-UX 10 and 11).
-
-  Converged HP-UX Serial I/O Filenames : TTY Mux Naming
-  ---------------------------------------------------------------------
-  General meaning      Old Form     S800 9.0           Convio 10.0
-  ---------------------------------------------------------------------
-  tty* hardwired ports  tty<YY>     tty<X>p<Y>         tty<D>p<p>
-                                    diag:mux<X>        diag:mux<D>
-  ---------------------------------------------------------------------
-  ttyd* dial-in modems  ttyd<YY>    ttyd<X>p<Y>        ttyd<D>p<p>
-                                    diag:ttyd<X>p<Y>   diag:ttyd<D>p<p>
-  ---------------------------------------------------------------------
-  cua* auto-dial out    cua<YY>     cua<X>p<Y>         cua<D>p<p>
-                                    diag:cua<X>p<Y>
-  ---------------------------------------------------------------------
-  cul* dial-out         cul<YY>     cul<X>p<Y>         cul<D>p<p>
-                                    diag:cul<X>p<Y>
-  ---------------------------------------------------------------------
-   <X>= LU (Logical Unit)  <D>= Devspec (decimal card instance)
-   <Y> or <YY> = Port      <p>= Port
-
-   For dialing out, you should use the cua or cul devices. When
-   C-Kermit's CARRIER setting is AUTO or ON, C-Kermit should pop back to
-   its prompt automatically if the carrier signal drops, e.g. when you
-   log out from the remote computer or service. If you use the tty<D>p<d>
-   (e.g. tty0p0) device, the carrier signal should be ignored. The
-   tty<D>p<d> device should be used for direct connections where the
-   carrier signal does not follow RS-232 conventions (use the cul device
-   for hardwired connections through a true null modem). Do not use the
-   ttyd<D>p<d> device for dialing out.
-
-   Kermit's access to serial devices is controlled by "UUCP lockfiles",
-   which are intended to prevent different users using different software
-   programs (Kermit, cu, etc, and UUCP itself) from accessing the same
-   serial device at the same time. When a device is in use by a
-   particular user, a file with a special name is created in:
-
-  /var/spool/locks  (HP-UX 10.00 and later)
-  /usr/spool/uucp   (HP-UX 9.xx and earlier)
-
-   The file's name indicates the device that is in use, and its contents
-   indicates the process ID (pid) of the process that is using the
-   device. Since serial devices and the locks directory are not both
-   publicly readable and writable, Kermit and other communication
-   software must be installed setuid to the owner (bin) of the serial
-   device and setgid to the group (daemon) of the /var/spool/locks
-   directory. Kermit's setuid and setgid privileges are enabled only when
-   opening the device and accessing the lockfiles.
-
-   Let's say "unit" means a string of decimal digits (the interface
-   instance number) followed (in HP-UX 10.00 and later) by the letter "p"
-   (lowercase), followed by another string of decimal digits (the port
-   number on the interface), e.g.:
-
-  "0p0", "0p1", "1p0", etc       (HP-UX 10.00 and later)
-  "0p0", "0p1", "1p0", etc       (HP-UX 9.xx on Series 800)
-  "00",  "01",  "10",  "0", etc  (HP-UX 9.xx not on Series 800)
-  "00",  "01",  "10",  "0", etc  (HP-UX 8.xx and earlier)
-
-   Then a normal serial device (driver) name consists of a prefix ("tty",
-   "ttyd", "cua", "cul", or possibly "cuad" or "culd") followed by a
-   unit, e.g. "cua0p0". Kermit's treatment of UUCP lockfiles is as close
-   as possible to that of the HP-UX "cu" program. Here is a table of the
-   lockfiles that Kermit creates for unit 0p0:
-
-  Selection      Lockfile 1     Lockfile 2  
-  /dev/tty0p0    LCK..tty0p0    (none)
-* /dev/ttyd0p0   LCK..ttyd0p0   (none)
-  /dev/cua0p0    LCK..cua0p0    LCK..ttyd0p0
-  /dev/cul0p0    LCK..cul0p0    LCK..ttyd0p0
-  /dev/cuad0p0   LCK..cuad0p0   LCK..ttyd0p0
-  /dev/culd0p0   LCK..culd0p0   LCK..ttyd0p0
-  <other>        LCK..<other>   (none)
-
-   (* = Dialin device, should not be used.)
-
-   In other words, if the device name begins with "cu", a second lockfile
-   for the "ttyd" device, same unit, is created, which should prevent
-   dialin access on that device.
-
-   The <other> case allows for symbolic links, etc, but of course it is
-   not foolproof since we have no way of telling which device is really
-   being used.
-
-   When C-Kermit tries to open a dialout device whose name ends with a
-   "unit", it searches the lockfile directory for all possible names for
-   the same unit. For example, if user selects /dev/cul2p3, Kermit looks
-   for lockfiles named:
-
-  LCK..tty2p3
-  LCK..ttyd2p3
-  LCK..cua2p3
-  LCK..cul2p3
-  LCK..cuad2p3
-  LCK..culd2p3
-
-   If any of these files are found, Kermit opens them to find out the ID
-   (pid) of the process that created them; if the pid is still valid, the
-   process is still active, and so the SET LINE command fails and the
-   user is informed of the pid so s/he can use "ps" to find out who is
-   using the device.
-
-   If the pid is not valid, the file is deleted. If all such files (i.e.
-   with same "unit" designation) are successfully removed, then the SET
-   LINE command succeeds; up to six messages are printed telling the user
-   which "stale lockfiles" are being removed.
-
-   When the "set line" command succeeds in HP-UX 10.00 and later,
-   C-Kermit also creates a Unix System V R4 "advisory lock" as a further
-   precaution (but not guarantee) against any other process obtaining
-   access to the device while you are using it.
-
-   If the selected device was in use by "cu", Kermit can't open it,
-   because "cu" has changed its ownership, so we never get as far as
-   looking at the lockfiles. In the normal case, we can't even look at
-   the device to see who the owner is because it is visible only to its
-   (present) owner. In this case, Kermit says (for example):
-
-  /dev/cua0p0: Permission denied
-
-   When Kermit releases a device it has successfully opened, it removes
-   all the lockfiles that it created. This also happens whenever Kermit
-   exits "under its own power".
-
-   If Kermit is killed with a device open, the lockfile(s) are left
-   behind. The next Kermit program that tries to assign the device, under
-   any of its various names, will automatically clean up the stale
-   lockfiles because the pids they contain are invalid. The behavior of
-   cu and other communication programs under these conditions should be
-   the same.
-
-   Here, by the way, is a summary of the differences between the HP-UX
-   port driver types from John Pezzano of HP:
-
-     There are three types of device files for each port.
-
-     The ttydXXX device file is designed to work as follows:
-
-    1. The process that opens it does NOT get control of the port until
-       CD is asserted. This was intentional (over 15 years ago) to allow
-       getty to open the port but not control it until someone called in.
-       If a process wants to use the direct or callout device files
-       (ttyXXX and culXXX respectively), they will then get control and
-       getty would be blocked. This eliminated the need to use uugetty
-       (and its inherent problems with lock files) for modems. You can
-       see this demonstrated by the fact that "ps -ef" shows a ? in the
-       tty column for the getty process as getty does not have the port
-       yet.
-    2. Once CD is asserted, the port is controlled by getty (or the
-       process handling an incoming call) if there was no process using
-       the port. The ? in the "ps" command now shows the port. At this
-       point, the port accepts data.
-
-     Therefore you should use either the callout culXXX device file
-     (immediate control but no data until CD is asserted) or the direct
-     device file ttyXXX which gives immediate control and immediate data
-     and which ignores by default modem control signals.
-
-     The ttydXXX device should be used only for callin and my
-     recommendation is to use it only for getty and uugetty.
-    ________________________________________________________________________
-
-  3.2.4 Notes on Specific HP-UX Releases
-
-   SECTION CONTENTS
-
-  3.2.4.1. [216]HP-UX 11
-  3.2.4.2. [217]HP-UX 10
-  3.2.4.3. [218]HP-UX 9
-  3.2.4.4. [219]HP-UX 8
-  3.2.4.5. [220]HP-UX 7 and Earlier
-
-  3.2.4.1. HP-UX 11
-
-   [ [221]Top ] [ [222]Contents ] [ [223]Section Contents ] [ [224]Next ]
-
-   As noted in [225]Section 3.2.2, the HP-UX 11 Telnet server and/or
-   pseudoterminal driver are a serious impediment to file transfer over
-   Telnet connections into HP-UX. If you have a Telnet connection into
-   HP-UX 11, tell your desktop Kermit program to:
-
-  set streaming off
-  set receive packet-length 2000
-  set send packet-length 500
-
-   File transfer speeds over connections from HP-UX 11 (dialed or Telnet)
-   are not impeded whatsoever, and can go at whatever speed is allowed by
-   the connection and the Kermit partner on the far end.
-
-   PA-RISC binaries for HP-UX 10.20 or later should run on any PA-RISC
-   system, S700 or S800, as long as the binary was not built under a
-   later HP-UX version than the host operating system. HP-UX 11.00 and
-   11.11 are only for PA-RISC systems. HP-UX 11.20 is only for IA64
-   (subsequent HP-UX releases will be for both PA-RISC and IA64). To
-   check binary compatibility, the following C-Kermit 8.0 binaries were
-   run successfully on an HP-9000/785 with HP-UX 11.11:
-
-     * Model 7xx HP-UX 10.20
-     * Model 8xx HP-UX 10.20
-     * Model 7xx HP-UX 11.00
-     * Model 8xx HP-UX 11.00
-     * Model 7xx HP-UX 11.11
-     * Model 8xx HP-UX 11.11
-
-   Binaries built under some of the earlier HP-UX releases, such as 9.05,
-   might also work, but only if built for the same hardware family (e.g.
-   s700).
-    ________________________________________________________________________
-
-  3.2.4.2. HP-UX 10
-
-   [ [226]Top ] [ [227]Contents ] [ [228]Section Contents ] [ [229]Next ]
-   [ [230]Previous ]
-
-   Beginning in HP-UX 10.10, libcurses is linked to libxcurses, the new
-   UNIX95 (X/Open) version of curses, which has some serious bugs; some
-   routines, when called, would hang and never return, some would dump
-   core. Evidently libxcurses contains a select() routine, and whenever
-   C-Kermit calls what it thinks is the regular (sockets) select(), it
-   gets the curses one, causing a segmentation fault. There is a patch
-   for this from HP, PHCO_8086, "s700_800 10.10 libcurses patch", "shared
-   lib curses program hangs on 10.10", "10.10 enhanced X/Open curses core
-   dumps due to using wrong select call", 96/08/02 (you can tell if the
-   patch is installed with "what /usr/lib/libxcurses.1"; the unpatched
-   version is 76.20, the patched one is 76.20.1.2). It has been verified
-   that C-Kermit works OK with the patched library, but results are not
-   definite for HP-UX 10.20 or higher.
-
-   To ensure that C-Kermit works even on non-patched HP-UX 10.10 systems,
-   separate makefile entries are provided for HP-UX 10.00/10.01, 10.10,
-   10.20, etc, in which the entries for 10.10 and above link with
-   libHcurses, which is "HP curses", the one that was used in
-   10.00/10.01. HP-UX 11.20 and later, however, link with libcurses, as
-   libHcurses disappeared in 11.20.
-    ________________________________________________________________________
-
-  3.2.4.3. HP-UX 9
-
-   [ [231]Top ] [ [232]Contents ] [ [233]Section Contents ] [ [234]Next ]
-   [ [235]Previous ]
-
-   HP-UX 9.00 and 9.01 need patch PHNE_10572 (note: this replaces
-   PHNE_3641) for hptt0.o, asio0.o, and ttycomn.o in libhp-ux.a. Contact
-   Hewlett Packard if you need this patch. Without it, the dialout device
-   (tty) will be hung after first use; subsequent attempts to use will
-   return an error like "device busy". (There are also equivalent patches
-   for s700 9.03 9.05 9.07 (PHNE_10573) and s800 9.00 9.04 (PHNE_10416).
-
-   When C-Kermit is in server mode, it might have trouble executing
-   REMOTE HOST commands. This problem happens under HP-UX 9.00 (Motorola)
-   and HP-UX 9.01 (RISC) IF the C-Shell is the login shell AND with the
-   C-Shell Revision 70.15. Best thing is to install HP's Patch PHCO_4919
-   for Series 300/400 and PHCO_5015 for the Series 700/800. PHCO_5015 is
-   called "s700_800 9.X cumulative csh(1) patch with memory leak fix"
-   which works for HP-UX 9.00, 9.01, 9.03, 9.04, 9.05 and 9.07. At least
-   you need C-Shell Revision 72.12!
-
-   C-Kermit works fine -- including its curses-based file-transfer
-   display -- on the console terminal, in a remote session (e.g. when
-   logged in to the HP 9000 on a terminal port or when telnetted or
-   rlogin'd), and in an HP-VUE hpterm window or an xterm window.
-    ________________________________________________________________________
-
-  3.2.4.4. HP-UX 8
-
-   [ [236]Top ] [ [237]Contents ] [ [238]Section Contents ] [ [239]Next ]
-   [ [240]Previous ]
-
-   To make C-Kermit work on HP-UX 8.05 on a model 720, obtain and install
-   HP-UX patch PHNE_0899. This patch deals with a lot of driver issues,
-   particularly related to communication at higher speeds.
-
-   One user reports:
-
-     On HP-UX 8 DON'T install 'tty patch' PHKL_4656, install PHKL_3047
-     instead! Yesterday I tried this latest tty patch PHKL_4656 and had
-     terrible problems. This patch should fix RTS/CTS problems. With
-     text transver all looks nice. But when I switched over to binary
-     files the serial interface returned only rubish to C-Kermit. All
-     sorts of protocol, CRC and packed errors I had. After several tests
-     and after uninstalling that patch, all transvers worked fine. MB's
-     of data without any errors. So keep your fingers away from that
-     patch. If anybody needs the PHKL_3047 patch I have it here. It is
-     no longer availabel from HP's patch base.
-    ________________________________________________________________________
-
-  3.2.4.5. HP-UX 7 and Earlier
-
-   [ [241]Top ] [ [242]Contents ] [ [243]Section Contents ] [
-   [244]Previous ]
-
-   When transferring files into HP-UX 5 or 6 over a Telnet connection,
-   you must not use streaming, and you must not use a packet length
-   greater than 512. However, you can use streaming and longer packets
-   when sending files from HP-UX on a Telnet connection. In C-Kermit 8.0,
-   the default receive packet length for HP-UX 5 and 6 was changed to 500
-   (but you can still increase it with SET RECEIVE PACKET-LENGTH if you
-   wish, e.g. for non-Telnet connections). Disable streaming with SET
-   STREAMING OFF.
-
-   The HP-UX 5.00 version of C-Kermit does not include the fullscreen
-   file-transfer because of problems with the curses library.
-
-   If HP-UX 5.21 with Wollongong TCP/IP is on the remote end of a Telnet
-   connection, streaming transfers to HP-UX invariably fail. Workaround:
-   SET STREAMING OFF. Packets longer than about 1000 should not be used.
-   Transfers from these systems, however, can use streaming and/or longer
-   packets.
-
-   Reportedly, "[there is] a bug in C-Kermit using HP-UX version 5.21 on
-   the HP-9000 series 500 computers. It only occurs when the controlling
-   terminal is using an HP-27140 six-port modem mux. The problem is not
-   present if the controlling terminal is logged into an HP-27130
-   eight-port mux. The symptom is that just after dialing successfully
-   and connecting Kermit locks up and the port is unusable until both
-   forks of Kermit and the login shell are killed." (This report predates
-   C-Kermit 6.0 and might no longer apply.)
-    ________________________________________________________________________
-
-  3.2.5. HP-UX and X.25
-
-   [ [245]Top ] [ [246]Contents ] [ [247]Section Contents ] [
-   [248]Previous ]
-
-   Although C-Kermit presently does not include built-in support for
-   HP-UX X.25 (as it does for the Sun and IBM X.25 products), it can
-   still be used to make X.25 connections as follows: start Kermit and
-   then telnet to localhost. After logging back in, start padem as you
-   would normally do to connect over X.25. Padem acts as a pipe between
-   Kermit and X.25. In C-Kermit 7.0, you might also be able to avoid the
-   "telnet localhost" step by using:
-
-  C-Kermit> pty padem address
-
-   This works if padem uses standard i/o (who knows?).
-    ________________________________________________________________________
-
-  3.3. C-KERMIT AND LINUX
-
-   [ [249]Top ] [ [250]Contents ] [ [251]Section Contents ] [ [252]Next ]
-   [ [253]Previous ]
-
-   SECTION CONTENTS
-
-  3.3.1. [254]Problems Building C-Kermit for Linux
-  3.3.2. [255]Problems with Serial Devices in Linux
-  3.3.3. [256]Terminal Emulation in Linux
-  3.3.4. [257]Dates and Times
-  3.3.5. [258]Startup Errors
-  3.3.6. [259]The Fullscreen File Transfer Display
-
-   REFERENCES
-
-   For further information, read the [260]comp.os.linux.misc,
-   [261]comp.os.linux.answers, and other Linux-oriented newsgroups, and
-   see:
-
-   The Linux Document Project (LDP)
-          [262]http://www.tldp.org/
-
-   The Linux FAQ
-          [263]http://www.tldp.org/FAQ/Linux-FAQ.html
-
-   The Linux HOWTOs (especially the Serial HOWTO)
-
-     [264]http://www.tldp.org/HOWTO/Serial-HOWTO.html
-
-     [265]http://tldp.org/HOWTO/Modem-HOWTO.html
-
-     [266]ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO
-
-     [267]ftp://tsx-11.mit.edu/pub/linux/docs/HOWTO
-
-     [268]http://www.tldp.org/HOWTO/
-
-     [269]http://www.tldp.org/hmirrors.html
-
-   Linux Vendor Tech Support Pages:
-
-     [270]http://www.redhat.com/apps/support/
-
-     [271]http://www.debian.org/support
-
-     [272]http://www.slackware.com/support/
-
-     [273]http://www.caldera.com/support/
-
-     [274]http://www.suse.com/support/
-
-     [275]http://www.mandrake.com/support/
-
-     [276]http://www.turbolinux.com/support/
-
-   Linux Winmodem Support
-          [277]http://www.linmodems.org/
-
-   Also see general comments on PC-based Unixes in [278]Section 3.0.
-
-   What Linux version is it? -- "uname -a" supplies only kernel
-   information, but these days it's the distribution that matters: Red
-   Hat 7.3, Debian 2.2, Slackware 8.0, etc. Unfortunately there's no
-   consistent way to get the distribution version. Usually it's in a
-   distribution-specific file:
-
-     Red Hat:   /etc/issue or /etc/redhat-release
-     Debian:    /etc/debian_version
-     Slackware: /etc/slackware-version (at least in later versions)
-
-   Did you know: DECnet is available for Linux? See:
-
-  [279]http://linux.dreamtime.org/decnet/
-
-   (But there is no support for it in C-Kermit -- anybody interested in
-   adding it, please [280]let us know).
-
-   Before proceeding, let's handle the some of the most frequently asked
-   question in the Linux newsgroups:
-
-    1. Neither C-Kermit nor any other Linux application can use
-       Winmodems, except in the [281]rare cases where Linux drivers have
-       been written for them. See [282]Section 3.0.2 for details.
-    2. "Why does it take such a long time to make a telnet connection to
-       (or from) my Linux PC?" (this applies to C-Kermit and to regular
-       Telnet). Most telnet servers these days perform reverse DNS
-       lookups on the client (for security and/or logging reasons). If
-       the Telnet client's address cannot be found by the server's local
-       DNS server, the DNS request goes out to the Internet at large, and
-       this can take quite some time. The solution to this problem is to
-       make sure that both client and host are registered in DNS, and
-       that the registrations are exported. C-Kermit itself performs
-       reverse DNS lookups unless you tell it not to; this is to allow
-       C-Kermit to let you know which host it is actually connected to in
-       case you have made a connection to a host pool (multihomed host).
-       You can disable C-Kermit's reverse DNS lookup with SET TCP
-       REVERSE-DNS-LOOKUP OFF.
-    3. (Any question that has the word "Telnet" in it...) The knee-jerk
-       reaction is "don't use Telnet, use SSH!" There's nothing wrong
-       with Telnet. In fact it's far superior to SSH as a protocol in
-       terms of features and extensibility, not to mention platform
-       neutrality. The issue lurking behind the knee-jerk reaction is
-       security. SSH is thought to be secure, whereas Telnet is thought
-       to be insecure. This is true for clear-text Telnet (because
-       passwords travel in the clear across the network), but apparently
-       few people realize that [283]secure Telnet clients and servers
-       have been available for years, and these are more secure than SSH
-       (for reasons explained [284]HERE.
-    4. (Any question that has the word "FTP" in it...) The knee-jerk
-       reaction being "Don't use FTP, use SCP!" (or SFTP). Same answer as
-       above, but moreso. SCP and SFTP are not only not platform neutral,
-       they're diversity-hostile. They transfer files only in binary
-       mode, which mangles text files across different platforms, to the
-       same degree the platform's text-file record format and character
-       set differ. An extreme example would be an Variable-Block format
-       EBCDIC text file on an IBM mainframe, binary transfer of which to
-       Unix would do you little good indeed. FTP was designed with
-       diversity in mind and secure versions are available.
-    ________________________________________________________________________
-
-  3.3.1. Problems Building C-Kermit for Linux
-
-   [ [285]Top ] [ [286]Contents ] [ [287]Section Contents ] [ [288]Next ]
-
-   Modern Linux distributions like Red Hat give you a choice at
-   installation whether to include "developer tools". Obviously, you
-   can't build C-Kermit or any other C program from source code if you
-   have not installed the developer tools. But to confuse matters, you
-   might also have to choose (separately) to install the "curses" or
-   "ncurses" terminal control library; thus it is possible to install the
-   C compiler and linker, but omit the (n)curses library and headers. If
-   curses is not installed, you will not be able to build a version of
-   C-Kermit that supports the fullscreen file-transfer display, in which
-   case you'll need to use the "linuxnc" makefile target (nc = No Curses)
-   or else install ncurses before building.
-
-   There are all sorts of confusing issues caused by the many and varied
-   Linux distributions. Some of the worst involve the curses library and
-   header files: where are they, what are they called, which ones are
-   they really? Other vexing questions involve libc5 vs libc6 vs glibc vs
-   glibc2 (C libraries), gcc vs egcs vs lcc (compilers), plus using or
-   avoiding features that were added in a certain version of Linux or a
-   library or a distribution, and are not available in others. As of
-   C-Kermit 8.0, these questions should be resolved by the "linux"
-   makefile target itself, which does a bit of looking around to see
-   what's what, and then sets the appropriate CFLAGS.
-    ________________________________________________________________________
-
-  3.3.2. Problems with Serial Devices in Linux
-
-   [ [289]Top ] [ [290]Contents ] [ [291]Section Contents ] [ [292]Next ]
-   [ [293]Previous ]
-
-     Also see: "man setserial", "man irqtune".
-     And: [294]Sections 3.0, [295]6, [296]7, and [297]8 of this
-     document.
-
-     NOTE: Red Hat Linux 7.2 and later include a new API that allows
-     serial-port arbitration by non-setuid/gid programs. This API has
-     not yet been added to C-Kermit. If C-Kermit is to be used for
-     dialing out on Red Hat 7.2 or later, it must still be installed as
-     described in in Sections [298]10 and [299]11 of the
-     [300]Installation Instructions. 
-
-   Don't expect it to be easy. Queries like the following are posted to
-   the Linux newsgroups almost daily:
-
-     Problem of a major kind with my Compaq Presario 1805 in the sense
-     that the pnpdump doesn't find the modem and the configuration tells
-     me that the modem is busy when I set everything by hand!
-
-     I have <some recent SuSE distribution>, kernel 2.0.35. Using the
-     Compaq tells me that the modem (which is internal) is on COM2, with
-     the usual IRQ and port numbers. Running various Windows diagnostics
-     show me AT-style commands exchanged so I have no reason to beleive
-     that it is a Winmodem. Also, the diagnostics under Win98 tell me
-     that I am talking to an NS 16550AN.
-
-   [Editor's note: This does not necessarily mean it isn't a Winmodem.]
-
-     Under Linux, no joy trying to talk to the modem on /dev/cua1
-     whether via minicom, kppp, or chat; kppp at least tells me that
-     tcgetattr() failed.
-
-     Usage of setserial:
-
-  setserial /dev/cua1 port 0x2F8 irq 3 autoconfig
-  setserial -g /dev/cua1
-
-     tells me that the uart is 'unknown'. I have tried setting the UART
-     manullay via. setserial to 16550A, 16550, and the other one (8550?)
-     (I didn't try 16540). None of these manual settings resulted in any
-     success.
-
-     A look at past articles leads me to investigate PNP issues by
-     calling pnpdump but pnpdump returns "no boards found". I have
-     looked around on my BIOS (Phoenix) and there is not much evidence
-     of it being PNP aware. However for what it calls "Serial port A",
-     it offers a choice of Auto, Disabled or Manual settings (currently
-     set to Auto), but using the BIOS interface I tried to change to
-     'manual' and saw the default settings offered to be were 0x3F8 and
-     IRQ 4 (COM1). The BIOS menus did not give me any chance to
-     configure COM2 or any "modem". I ended up not saving any BIOS
-     changes in the course of my investigations.
-
-   You can also find out a fair amount about your PC's hardware
-   configuration in the text files in /proc, e.g.:
-
-  -r--r--r--    1 root            0 Sep  4 14:00 /proc/devices
-  -r--r--r--    1 root            0 Sep  4 14:00 /proc/interrupts
-  -r--r--r--    1 root            0 Sep  4 14:00 /proc/ioports
-  -r--r--r--    1 root            0 Sep  4 14:00 /proc/pci
-
-   From the directory listing they look like empty files, but in fact
-   they are text files that you "cat":
-
-$ cat /proc/pci
-   Bus  0, device  14, function  0:
-     Serial controller: US Robotics/3Com 56K FaxModem Model 5610 (rev 1).
-       IRQ 10.
-       I/O at 0x1050 [0x1057].
-
-$ setserial -g /dev/ttyS4
-/dev/ttyS4, UART: 16550A, Port: 0x1050, IRQ: 10
-
-$ cat /proc/ioports
-1050-1057 : US Robotics/3Com 56K FaxModem Model 5610
-   1050-1057 : serial(auto)
-
-$ cat /proc/interrupts
-            CPU0
-   0:    7037515          XT-PIC  timer
-   1:          2          XT-PIC  keyboard
-   2:          0          XT-PIC  cascade
-   4:          0          XT-PIC  serial
-   8:          1          XT-PIC  rtc
-   9:     209811          XT-PIC  usb-uhci, eth0
-  14:     282015          XT-PIC  ide0
-  15:          6          XT-PIC  ide1
-
-   Watch out for PCI, PCMCIA and Plug-n-Play devices, Winmodems, and the
-   like (see cautions in [301]Section 3.0 Linux supports Plug-n-Play
-   devices to some degree via the isapnp and pnpdump programs; read the
-   man pages for them. (If you don't have them, look on your installation
-   CD for isapnptool or download it from sunsite or a sunsite mirror or
-   other politically correct location du jour).
-
-   PCI modems do not use standard COM port addresses. The I/O address and
-   IRQ are assigned by the BIOS. All you need to do to get one working,
-   find out the I/O address and interrupt number with (as root) "lspci -v
-   | more" and then give the resulting address and interrupt number to
-   setserial.
-
-   Even when you have a real serial port, always be wary of interrupt
-   conflicts and similar PC hardware configuration issues: a PC is not a
-   real computer like other Unix workstations -- it is generally pieced
-   together from whatever random components were the best bargain on the
-   commodity market the week it was built. Once it's assembled and boxed,
-   not even the manufacturer will remember what it's made of or how it
-   was put together because they've moved on to a new model. Their job is
-   to get it (barely) working with Windows; for Linux and other OS's you
-   are on your own.
-
-   "set line /dev/modem" or "set line /dev/ttyS2", etc, results in an
-   error, "/dev/modem is not a tty". Cause unknown, but obviously a
-   driver issue, not a Kermit one (Kermit uses "isatty()" to check that
-   the device is a tty, so it knows it will be able to issue all the
-   tty-related ioctl's on it, like setting the speed & flow control). Try
-   a different name (i.e. driver) for the same port, e.g. "set line
-   /dev/cua2" or whatever.
-
-   To find what serial ports were registered at the most recent system
-   boot, type (as root): "grep tty /var/log/dmesg".
-
-   "set modem type xxx" (where xxx is the name of a modem) followed by
-   "set line /dev/modem" or "set
-   line /dev/ttyS2", etc, hangs (but can be interrupted with Ctrl-C).
-   Experimentation shows that if the modem is configured to always assert
-   carrier (&C0) the same command does not hang. Again, a driver issue.
-   Use /dev/cua2 (or whatever) instead. (Or not -- hopefully none of
-   these symptoms occurs in C-Kermit 7.0 or later.)
-
-   "set line /dev/cua0" reports "Device is busy", but "set line
-   /dev/ttyS0" works OK.
-
-   In short: If the cua device doesn't work, try the corresponding ttyS
-   device. If the ttyS device doesn't work, try the corresponding cua
-   device -- but note that Linux developers do not recommend this, and
-   are phasing out the cua devices. From /usr/doc/faq/howto/Serial-HOWTO:
-
-   12.4. What's The Real Difference Between the /dev/cuaN And /dev/ttySN
-          Devices?
-          The only difference is the way that the devices are opened. The
-          dialin devices /dev/ttySN are opened in blocking mode, until CD
-          is asserted (ie someone connects). So, when someone wants to
-          use the /dev/cuaN device, there is no conflict with a program
-          watching the /dev/ttySN device (unless someone is connected of
-          course). The multiple /dev entries, allow operation of the same
-          physical device with different operating characteristics. It
-          also allows standard getty programs to coexist with any other
-          serial program, without the getty being retrofitted with
-          locking of some sort. It's especially useful since standard
-          Unix kernel file locking, and UUCP locking are both advisory
-          and not mandatory.
-
-   It was discovered during development of C-Kermit 7.0 that rebuilding
-   C-Kermit with -DNOCOTFMC (No Close/Open To Force Mode Change) made the
-   aforementioned problem with /dev/ttyS0 go away. It is not yet clear,
-   however, what its affect might be on the /dev/cua* devices. As of 19
-   March 1998, this option has been added to the CFLAGS in the makefile
-   entries for Linux ("make linux").
-
-   Note that the cua device is now "deprecated", and new editions of
-   Linux will phase (have phased) it out in favor of the ttyS device. See
-   (if it's still there):
-
-  [302]http://linuxwww.db.erau.edu/mail_archives/linux-kernel/Mar_98/1441.html
-
-   (no, of course it isn't; you'll have to use your imagination). One
-   user reported that C-Kermit 7.0, when built with egcs 1.1.2 and run on
-   Linux 2.2.6 with glibc 2.1 (hardware unknown but probably a PC) dumps
-   core when given a "set line /dev/ttyS1" command. When rebuilt with
-   gcc, it works fine.
-
-   All versions of Linux seem to have the following deficiency: When a
-   modem call is hung up and CD drops, Kermit can no longer read the
-   modem signals; SHOW COMMUNICATIONS says "Modem signals not available".
-   The TIOCMGET ioctl() returns -1 with errno 5 ("I/O Error").
-
-   The Linux version of POSIX tcsendbreak(), which is used by C-Kermit to
-   send regular (275msec) and long (1.5sec) BREAK signals, appears to
-   ignore its argument (despite its description in the man page and info
-   topic), and always sends a regular 275msec BREAK. This has been
-   observed in Linux versions ranging from Debian 2.1 to Red Hat 7.1.
-    ________________________________________________________________________
-
-  3.3.3. Terminal Emulation in Linux
-
-   [ [303]Top ] [ [304]Contents ] [ [305]Section Contents ] [ [306]Next ]
-   [ [307]Previous ]
-
-   C-Kermit is not a terminal emulator. For a brief explanation of why
-   not, see [308]Section 3.0.5. For a fuller explanation, [309]ClICK
-   HERE.
-
-   In Unix, terminal emulation is supplied by the Window in which you run
-   Kermit: the regular console screen, which provides Linux Console
-   "emulation" via the "console" termcap entry, or under X-Windows in an
-   xterm window, which gives VTxxx emulation. An xterm that includes
-   color ANSI and VT220 emulation is available with Xfree86:
-
-  [310]http://dickey.his.com/xterm/xterm.html
-
-   Before starting C-Kermit in an xterm window, you might need to tell
-   the xterm window's shell to "stty sane".
-
-   To set up your PC console keyboard to send VT220 key sequences when
-   using C-Kermit as your communications program in an X terminal window
-   (if it doesn't already), create a file somewhere (e.g. in /root/)
-   called .xmodmaprc, containing something like the following:
-
-  keycode 77  = KP_F1       ! Num Lock     => DEC Gold (PF1)
-  keycode 112 = KP_F2       ! Keypad /     => DEC PF1
-  keycode 63  = KP_F3       ! Keypad *     => DEC PF3
-  keycode 82  = KP_F4       ! Keypad -     => DEC PF4
-  keycode 111 = Help        ! Print Screen => DEC Help
-  keycode 78  = F16         ! Scroll Lock  => DEC Do
-  keycode 110 = F16         ! Pause        => DEC Do
-  keycode 106 = Find        ! Insert       => DEC Find
-  keycode 97  = Insert      ! Home         => DEC Insert
-  keycode 99  = 0x1000ff00  ! Page Up      => DEC Remove
-  keycode 107 = Select      ! Delete       => DEC Select
-  keycode 103 = Page_Up     ! End          => DEC Prev Screen
-  keycode 22  = Delete      ! Backspace sends Delete (127)
-
-   Then put "xmodmap filename" in your .xinitrc file (in your login
-   directory), e.g.
-
-  xmodmap /root/.xmodmaprc
-
-   Of course you can move things around. Use the xev program to find out
-   key codes.
-
-   Console-mode keys are mapped separately using loadkeys, and different
-   keycodes are used. Find out what they are with showkey.
-
-   For a much more complete VT220/320 key mapping for [311]Xfree86 xterm,
-   [312]CLICK HERE.
-    ________________________________________________________________________
-
-  3.3.4. Dates and Times
-
-   [ [313]Top ] [ [314]Contents ] [ [315]Section Contents ] [ [316]Next ]
-   [ [317]Previous ]
-
-   If C-Kermit's date-time (e.g. as shown by its DATE command) differs
-   from the system's date and time:
-
-    a. Make sure the libc to which Kermit is linked is set to GMT or is
-       not set to any time zone. Watch out for mixed libc5/libc6 systems;
-       each must be set indpendently.
-    b. If you have changed your TZ environment variable, make sure it is
-       exported. This is normally done in /etc/profile or /etc/TZ.
-    ________________________________________________________________________
-
-  3.3.5. Startup Errors
-
-   [ [318]Top ] [ [319]Contents ] [ [320]Section Contents ] [ [321]Next ]
-   [ [322]Previous ]
-
-   C-Kermit should work on all versions of Linux current through March
-   2003, provided it was built on the same version you have, with the
-   same libraries and header files (just get the source code and "make
-   linux"). Binaries tend not to travel well from one Linux machine to
-   another, due to their many differences. There is no guarantee that a
-   particular C-Kermit binary will not stop working at a later date,
-   since Linux tends to change out from under its applications. If that
-   happens, rebuild C-Kermit from source. If something goes wrong with
-   the build process, look on the [323]C-Kermit website for a newer
-   version. If you have the latest version, then [324]report the problem
-   to us.
-
-   Inability to transfer files in Red Hat 7.2: the typical symptom would
-   be if you start Kermit and tell it to RECEIVE, it fails right away
-   with "?/dev/tty: No such device or address" or "?Bad file descriptor".
-   One report says this is because of csh, and if you change your shell
-   to bash or other shell, it doesn't happen. Another report cite bugs in
-   Red Hat 7.2 Telnetd "very seldom (if ever) providing a controlling
-   tty, and lots of other people piled on saying they have the same
-   problem.") A third theory is that this happens only when Linux has
-   been installed without "virtual terminal support".
-
-   A search of RedHat's errata pages shows a bug advisory (RHBA-2001-153)
-   issued 13 November 2001, but updated 6 December, about this same
-   symptom (but with tcsh and login.) Seems that login was not always
-   assigning a controlling TTY for the session, which would make most use
-   of "/dev/tty" somewhat less than useful.
-
-  [325]http://www.redhat.com/support/errata/RHBA-2001-153.html
-
-   Quoting: "Due to terminal handling problems in /bin/login, tcsh would
-   not find the controlling terminal correctly, and a shell in single
-   user mode would exhibit strange terminal input characteristics. This
-   update fixes both of these problems."
-
-   Since the Red Hat 5.1 release (circa August 1998), there have been
-   numerous reports of prebuilt Linux executables, and particularly the
-   Kermit RPM for Red Hat Linux, not working; either it won't start at
-   all, or it gives error messages about "terminal type unknown" and
-   refuses to initialize its curses support. The following is from the
-   [326]Kermit newsgroup:
-
-     From: rchandra@hal9000.buf.servtech.com
-     Newsgroups: comp.protocols.kermit.misc
-     Subject: Red Hat Linux/Intel 5.1 and ncurses: suggestions
-     Date: 22 Aug 1998 15:54:46 GMT
-     Organization: Verio New York
-     Keywords: RedHat RPM 5.1
-
-     Several factors can influence whether "linux" is recognized as a
-     terminal type on many Linux systems.
-
-    1. Your program, or the libraries it linked with (if statically
-       linked), or the libraries it dynamically links with at runtime,
-       are looking for an entry in /etc/termcap that isn't there. (not
-       likely, but possible... I believe but am not certain that this is
-       a very old practice in very old [n]curses library implementations
-       to use a single file for all terminal descriptions.)
-    2. Your program, or the libraries...are looking for a terminfo file
-       that just plain isn't there. (also not so likely, since many
-       people in other recent message threads said that other programs
-       work OK).
-    3. Your program, or the libraries...are looking for a terminfo file
-       that is stored at a pathname that isn't expected by your program,
-       the libraries--and so on. I forgot if I read this in the errata
-       Web page or where exactly I discovered this (Netscape install?
-       Acrobat install?), but it may just be that one libc (let's say for
-       sake of argument, libc5, but I don't know this to be true) expects
-       your terminfo to be in /usr/share/terminfo, and the other (let's
-       say libc6/glibc) expects /usr/lib/terminfo. I remember that the
-       specific instructions in this bugfix/workaround were to do the
-       following or equivalent:
-  cd /usr/lib
-  ln -s ../share/terminfo ./terminfo
-       or:
-  ln -s /usr/share/terminfo /usr/lib/terminfo
-
-     So what this says is that the terminfo database/directory structure
-     can be accessed by either path. When something goes to reference
-     /usr/lib/terminfo, the symlink redirects it to essentially
-     /usr/share/terminfo, which is where it really resides on your
-     system. I personally prefer wherever possible to use relative
-     symlinks, because they still hold, more often than break, across
-     mount points, particularly NFS mounts, where the directory
-     structure may be different on the different systems.
-
-   Evidently the terminfo file moved between Red Hat 5.0 and 5.1, but Red
-   Hat did not include a link to let applications built prior to 5.1 find
-   it. Users reported that installing the link fixes the problem.
-    ________________________________________________________________________
-
-  3.3.6. The Fullscreen File Transfer Display
-
-   [ [327]Top ] [ [328]Contents ] [ [329]Section Contents ] [
-   [330]Previous ]
-
-   Starting with ncurses versions dated 1998-12-12 (about a year before
-   ncurses 5.0), ncurses sets the terminal for buffered i/o, but
-   unfortunately is not able to restore it upon exit from curses (via
-   endwin()). Thus after a file transfer that uses the fullscreen file
-   transfer display, the terminal no longer echos nor responds
-   immediately to Tab, ?, and other special command characters. The same
-   thing happens on other platforms that use ncurses, e.g. FreeBSD.
-   Workarounds:
-
-     * Use SET XFER DISPLAY BRIEF, CRT, SERIAL, or NONE instead of
-       FULLSCREEN; or:
-     * Rebuild with KFLAGS=-DNONOSETBUF (C-Kermit 8.0)
-
-   In Red Hat 7.1, when using C-Kermit in a Gnome terminal window, it was
-   noticed that when the fullscreen file transfer display exits (via
-   endwin()), the previous (pre-file-transfer-display) screen is
-   restored. Thus you can't look at the completed display to see what
-   happened. This is a evidently a new feature of xterm. I can only
-   speculate that initscreen() and endwin() must send some kind of
-   special escape sequences that command xterm to save and restore the
-   screen. To defeat this effect, tell Linux you have a vt100 or other
-   xterm-compatible terminal that is not actually an xterm, or else tell
-   Kermit to SET TRANSFER DISPLAY to something besides FULLSCREEN.
-    ________________________________________________________________________
-
-  3.4. C-KERMIT AND NEXTSTEP
-
-   [ [331]Top ] [ [332]Contents ] [ [333]Section Contents ] [ [334]Next ]
-   [ [335]Previous ]
-
-   Run C-Kermit in a Terminal, Stuart, or xterm window, or when logged in
-   remotely through a serial port or TELNET connection. C-Kermit does not
-   work correctly when invoked directly from the NeXTSTEP File Viewer or
-   Dock. This is because the terminal-oriented gtty, stty, & ioctl calls
-   don't work on the little window that NeXTSTEP pops up for non-NeXTSTEP
-   applications like Kermit. CBREAK and No-ECHO settings do not take
-   effect in the command parser -- commands are parsed strictly line at a
-   time. "set line /dev/cua" works. During CONNECT mode, the console
-   stays in cooked mode, so characters are not transmitted until carriage
-   return or linefeed is typed, and you can't escape back. If you want to
-   run Kermit directly from the File Viewer, then launch it from a shell
-   script that puts it in the desired kind of window, something like this
-   (for "Terminal"):
-
-  Terminal -Lines 24 -Columns 80 -WinLocX 100 -WinLocY 100 $FONT $FONTSIZE \
-  -SourceDotLogin -Shell /usr/local/bin/kermit &
-
-   C-Kermit does not work correctly on a NeXT with NeXTSTEP 3.0 to which
-   you have established an rlogin connection, due to a bug in NeXTSTEP
-   3.0, which has been reported to NeXT.
-
-   The SET CARRIER command has no effect on the NeXT -- this is a
-   limitation of the NeXTSTEP serial-port device drivers.
-
-   Hardware flow control on the NeXT is selected not by "set flow
-   rts/cts" in Kermit (since NeXTSTEP offers no API for this), but
-   rather, by using a specially-named driver for the serial device:
-   /dev/cufa instead /dev/cua; /dev/cufb instead of /dev/cub. This is
-   available only on 68040-based NeXT models (the situation for Intel
-   NeXTSTEP implementations is unknown).
-
-   NeXT-built 68030 and 68040 models have different kinds of serial
-   interfaces; the 68030 has a Macintosh-like RS-422 interface, which
-   lacks RTS and CTS signals; the 68040 has an RS-423 (RS-232 compatible)
-   interface, which supports the commonly-used modem signals. WARNING:
-   the connectors look exactly the same, but the pins are used in
-   completely DIFFERENT ways -- different cables are required for the two
-   kinds of interfaces.
-
-     IF YOU GET LOTS OF RETRANSMISSIONS during file transfer, even when
-     using a /dev/cuf* device and the modem is correctly configured for
-     RTS/CTS flow control, YOU PROBABLY HAVE THE WRONG KIND OF CABLE.
-
-   On the NeXT, Kermit reportedly (by TimeMon) causes the kernel to use a
-   lot of CPU time when using a "set line" connection. That's because
-   there is no DMA channel for the NeXT serial port, so the port must
-   interrupt the kernel for each character in or out.
-
-   One user reported trouble running C-Kermit on a NeXT from within
-   NeXT's Subprocess class under NeXTstep 3.0, and/or when rlogin'd from
-   one NeXT to another: Error opening /dev/tty:, congm: No such device or
-   address. Diagnosis: Bug in NeXTSTEP 3.0, cure unknown.
-    ________________________________________________________________________
-
-  3.5. C-KERMIT AND QNX
-
-   [ [336]Top ] [ [337]Contents ] [ [338]Section Contents ] [ [339]Next ]
-   [ [340]Previous ]
-
-   See also: The [341]comp.os.qnx newsgroup.
-
-   Support for QNX 4.x was added in C-Kermit 5A(190). This is a
-   full-function implementation, thoroughly tested on QNX 4.21 and later,
-   and verified to work in both 16-bit and 32-bit versions. The 16-bit
-   version was dropped in C-Kermit 7.0 since it can no longer be built
-   successfully (after stripping most most features, I succeeded in
-   getting it to compile and link without complaint, but the executable
-   just beeps when you run it); for 16-bit QNX 4.2x, use C-Kermit 6.0 or
-   earlier, or else [342]G-Kermit.
-
-   The 32-bit version (and the 16-bit version prior to C-Kermit 7.0)
-   supports most of C-Kermit's advanced features including TCP/IP, high
-   serial speeds, hardware flow-control, modem-signal awareness, curses
-   support, etc.
-
-   BUG: In C-Kermit 6.0 on QNX 4.22 and earlier, the fullscreen file
-   transfer display worked fine the first time, but was fractured on
-   subsequent file transfers. Cause and cure unknown. In C-Kermit 7.0 and
-   QNX 4.25, this no longer occurs. It is not known if it would occur in
-   C-Kermit 7.0 or later on earlier QNX versions.
-
-   Dialout devices are normally /dev/ser1, /dev/ser2, ..., and can be
-   opened explicitly with SET LINE. Reportedly, "/dev/ser" (no unit
-   number) opens the first available /dev/sern device.
-
-   Like all other Unix C-Kermit implementations, QNX C-Kermit does not
-   provide any kind of terminal emulation. Terminal specific functions
-   are provided by your terminal, terminal window (e.g. QNX Terminal or
-   xterm), or emulator.
-
-   QNX C-Kermit, as distributed, does not include support for UUCP
-   line-locking; the QNX makefile entries (qnx32 and qnx16) include the
-   -DNOUUCP switch. This is because QNX, as distributed, does not include
-   UUCP, and its own communications software (e.g. qterm) does not use
-   UUCP line locking. If you have a UUCP product installed on your QNX
-   system, remove the -DNOUUCP switch from the makefile entry and
-   rebuild. Then check to see that Kermit's UUCP lockfile conventions are
-   the same as those of your UUCP package; if not, read the [343]UUCP
-   lockfile section of the [344]Installation Instructions and make the
-   necessary changes to the makefile entry (e.g. add -DHDBUUCP).
-
-   QNX does, however, allow a program to get the device open count. This
-   can not be a reliable form of locking unless all applications do it,
-   so by default, Kermit uses this information only for printing a
-   warning message such as:
-
-  C-Kermit>set line /dev/ser1
-  WARNING - "/dev/ser1" looks busy...
-
-   However, if you want to use it as a lock, you can do so with:
-
-  SET QNX-PORT-LOCK { ON, OFF }
-
-   This is OFF by default; if you set in ON, C-Kermit will fail to open
-   any dialout device when its open count indicates that another process
-   has it open. SHOW COMM (in QNX only) displays the setting, and if you
-   have a port open, it also shows the open count.
-
-   As of C-Kermit 8.0, C-Kermit's "open-count" form of line locking works
-   only in QNX4, not in QNX6 (this might change in a future C-Kermit
-   release).
-    ________________________________________________________________________
-
-  3.6. C-KERMIT AND SCO
-
-   [ [345]Top ] [ [346]Contents ] [ [347]Section Contents ] [ [348]Next ]
-   [ [349]Previous ]
-
-   SECTION CONTENTS
-
-3.6.1. [350]SCO XENIX
-3.6.2. [351]SCO UNIX and OSR5
-3.6.3. [352]Unixware
-3.6.4. [353]Open UNIX 8
-
-   REFERENCES
-
-     * The comp.unix.sco.* newsgroups.
-     * [354]Section 3.10 below for Unixware.
-     * The following FAQs:
-
-        The comp.sco.misc FAQ:
-                [355]http://aplawrence.com/SCOFAQ/
-
-        Caldera (SCO) comp.unix.sco.programmer FAQ:
-                [356]http://www.zenez.com/cgi-bin/scoprogfaq/faq.pl
-
-        The UnixWare 7/OpenUNIX 8 FAQ:
-                [357]http://www.zenez.com/cgi-bin/scouw7faq/faq.pl
-                [358]http://zenez.pcunix.com/cgi-bin/scouw7faq/faq.pl
-
-        High Speed Modems for SCO Unix:
-                [359]http://pcunix.com/Unixart/modems.html
-
-        The UnixWare FAQ
-                [360]http://www.freebird.org/faq/
-
-        The UnixWare 1.x and 2.0 Programmer FAQ
-                [361]http://www.freebird.org/faq/developer.html
-
-        Caldera Support Knowledge Base
-                [362]http://support.caldera.com/caldera
-
-        [363]http://stage.caldera.com/ta/
-                Caldera (SCO) Technical Article Search Center
-
-        [364]http://aplawrence.com/newtosco.html
-                New to SCO (Tony Lawrence)
-
-   The same comments regarding terminal emulation and key mapping apply
-   to SCO operating systems as to all other Unixes. C-Kermit is not a
-   terminal emulator, and you can't use it to map F-keys, Arrow keys,
-   etc. The way to do this is with xmodmap (xterm) or loadkeys (console).
-   For a brief explanation, see [365]Section 3.0.5. For a fuller
-   explanation, [366]ClICK HERE.
-
-   Also see general comments on PC-based Unixes in [367]Section 3.0.
-
-  3.6.1. SCO XENIX
-
-   [ [368]Top ] [ [369]Contents ] [ [370]Section Contents ] [ [371]Next ]
-
-   Old Xenix versions... Did you know: Xenix 3.0 is *older* than Xenix
-   2.0?
-
-   In Xenix 2.3.4 and probably other Xenix versions, momentarily dropping
-   DTR to hang up a modem does not work. DTR goes down but does not come
-   up again. Workaround: Use SET MODEM HANGUP-METHOD MODEM-COMMAND.
-   Anybody who would like to fix this is welcome to take a look at
-   tthang() in [372]ckutio.c. Also: modem signals can not be read in
-   Xenix, and the maximum serial speed is 38400.
-
-   There is all sorts of confusion among SCO versions, particularly when
-   third- party communications boards and drivers are installed,
-   regarding lockfile naming conventions, as well as basic functionality.
-   As far as lockfiles go, all bets are off if you are using a
-   third-party multiport board. At least you have the source code.
-   Hopefully you also have a C compiler :-)
-
-   Xenix 2.3.0 and later claim to support RTSFLOW and CTSFLOW, but this
-   is not modern bidirectional hardware flow control; rather it
-   implements the original RS-232 meanings of these signals for
-   unidirectional half-duplex line access: If both RTSFLOW and CTSFLOW
-   bits are set, Xenix asserts RTS when it wants to send data and waits
-   for CTS assertion before it actually starts sending data (also,
-   reportedly, even this is broken in Xenix 2.3.0 and 2.3.1).
-    ________________________________________________________________________
-
-  3.6.2. SCO UNIX AND OSR5
-
-   [ [373]Top ] [ [374]Contents ] [ [375]Section Contents ] [ [376]Next ]
-   [ [377]Previous ]
-
-   SCO systems tend to use different names (i.e. drivers) for the same
-   device. Typically /dev/tty1a refers to a terminal device that has no
-   modem control; open, read, write, and close operations do not depend
-   on carrier. On the other hand, /dev/tty1A (same name, but with final
-   letter upper case), is the same device with modem control, in which
-   carrier is required (the SET LINE command does not complete until
-   carrier appears, read/write operations fail if there is no carrier,
-   etc).
-
-   SCO OpenServer 5.0.5 and earlier do not support the reading of modem
-   signals. Thus "show comm" does not list modem signals, and C-Kermit
-   does not automatically pop back to its prompt when the modem hangs up
-   the connection (drops CD). The ioctl() call for this is simply not
-   implmented, at least not in the standard drivers. OSR5.0.6 attempts to
-   deal with modem signals but fails; however OSR5.0.6a appears to
-   function properly.
-
-   Dialing is likely not to work well in SCO OpenServer 5.0.x because
-   many of the serial-port APIs simply do not operate when using the
-   standard drivers. For example, if DTR is dropped by the recommended
-   method (setting speed to 0 for half a seconds, then restoring the
-   speed), DTR and RTS go down but never come back up. When in doubt SET
-   MODEM HANGUP-METHOD MODEM-COMMAND or SET DIAL HANGUP OFF.
-
-   On the other hand, certain functions that might not (do not) work
-   right or at all when using SCO drivers (e.g. high serial speeds,
-   hardware flow control, and/or reading of modem signals) might work
-   right when using third-party drivers. (Example: hardware flow control
-   works, reportedly, only on uppercase device like tty1A -- not tty1a --
-   and only when CLOCAL is clear when using the SCO sio driver, but there
-   are no such restrictions in, e.g., [378]Digiboard drivers).
-
-   One user reports that he can't transfer large files with C-Kermit
-   under SCO OSR5.0.0 and 5.0.4 -- after the first 5K, everything falls
-   apart. Same thing without Kermit -- e.g. with ftp over a PPP
-   connection. Later, he said that replacing SCO's SIO driver with FAS,
-   an alternative communications driver, made the problem go away:
-
-  [379]ftp://ftp.fu-berlin.de/pub/unix/driver/fas
-
-   With regard to bidirectional serial ports on OpenServer 5.0.4, the
-   following advice appeared on an SCO-related newsgroup:
-
-     No amount of configuration information is going to help you on
-     5.0.4 unless it includes the kludge for the primary problem. With
-     almost every modem, the 5.0.4 getty will barf messages and may or
-     may not connect. There are 2 solutions and only one works on 5.0.4.
-     Get the atdialer binary from a 5.0.0 system and substitute it for
-     the native 5.0.4 atdialer. The other solution is to upgrade to
-     5.0.5. And, most of all, on any OpenServer products, do NOT run the
-     badly broken Modem Manager. Configure the modems in the time
-     honored way that dates back to Xenix.
-
-   Use SCO-provided utilities for switching the directionality of a modem
-   line, such as "enable" and "disable" commands. For example, to dial
-   out on tty1a, which is normally set up for logins:
-
-  disable tty1a
-  kermit -l /dev/tty1a
-  enable tty1a
-
-   If a tty device is listed as an ACU in /usr/lib/uucp/Devices and is
-   enabled, getty resets the ownership and permissions to uucp.uucp and
-   640 every time the device is released. If you want to use the device
-   only for dialout, and you want to specify other owners or permissions,
-   you should disable it in /usr/lib/uucp/Devices; this will prevent
-   getty from doing things to it. You should also changes the device's
-   file modes in /etc/conf/node.d/sio by changing fields 5-7 for the
-   desired device(s); this determines how the devices are set if you
-   relink the kernel.
-
-   One SCO user of C-Kermit 5A(190) reported that only one copy of Kermit
-   can run at a time when a Stallion Technologies multiport boards are
-   installed. Cause, cure, and present status unknown (see [380]Section
-   14 for more info regarding Stallion).
-
-   Prior to SCO OpenServer 5.0.4, the highest serial port speed supported
-   by SCO was 38400. However, in some SCO versions (e.g. OSR5) it is
-   possible to map rarely-used lower speeds (like 600 and 1800) to higher
-   ones like 57600 and 115200. To find out how, go to
-   [381]http://www.sco.com/ and search for "115200". In OSR5.0.4, serial
-   speeds up to 921600 are supported through the POSIX interface;
-   C-Kermit 6.1.193 or later, when built for OSR5.0.4 using /bin/cc (NOT
-   the UDK, which hides the high-speed definitions from CPP), supports
-   these speeds, but you might be able to run this binary on earlier
-   releases to get the high serial speeds, depending on various factors,
-   described by Bela Lubkin of SCO:
-
-  Serial speeds under SCO Unix / Open Desktop / OpenServer
-  ========================================================
-  Third party drivers (intelligent serial boards) may provide any speeds
-  they desire; most support up to 115.2Kbps.
-
-  SCO's "sio" driver, which is used to drive standard serial ports with
-  8250/16450/16550 and similar UARTs, was limited to 38400bps in older
-  releases.  Support for rates through 115.2Kbps was added in the
-  following releases:
-
-    SCO OpenServer Release 5.0.0 (requires supplement "rs40b")
-    SCO OpenServer Release 5.0.2 (requires supplement "rs40a" or "rs40b")
-    SCO OpenServer Release 5.0.4 or later
-    SCO Internet FastStart Release 1.0.0 or later
-
-   SCO supplements are at [382]ftp://ftp.sco.com/; the "rs40" series are
-   under directory /Supplements/internet
-
-   Kermit includes the high serial speeds in all OSR5 builds, but that
-   does not necessarily mean they work. For example, on our in-house
-   5.0.5 system, SET SPEED 57600 or higher seems to succeed (no error
-   occurs) but when we read the speed back the driver says it is 50.
-   Similarly, 76800 becomes 75, and 115200 becomes 110. Testing shows the
-   resulting speed is indeed the low one we read back, not the high one
-   we asked for. Moral: Use speeds higher than 38400 with caution on SCO
-   OSR5.
-
-   Reportedly, if you have a script that makes a TCP/IP SET HOST (e.g.
-   Telnet) connection to SCO 3.2v4.2 with TCP/IP 1.2.1, and then does the
-   following:
-
-  script $ exit
-  hangup
-
-   this causes a pseudoterminal (pty) to be consumed on the SCO system;
-   if you do it enough times, it will run out of ptys. An "exit" command
-   is being sent to the SCO shell, and a HANGUP command is executed
-   locally, so the chances are good that both sides are trying to close
-   the connection at once, perhaps inducing a race condition in which the
-   remote pty is not released. It was speculated that this would be fixed
-   by applying SLS net382e, but it did not. Meanwhile, the workaround is
-   to insert a "pause" between the SCRIPT and HANGUP commands. (The
-   situation with later SCO releases is not known.)
-
-   SCO UNIX and OpenServer allow their console and/or terminal drivers to
-   be configured to translate character sets for you. DON'T DO THIS WHEN
-   USING KERMIT! First of all, you don't need it -- Kermit itself already
-   does this for you. And second, it will (a) probably ruin the
-   formatting of your screens (depending on which emulation you are
-   using); and (b) interfere with all sorts of other things -- legibility
-   of non-ASCII text on the terminal screen, file transfer, etc. Use:
-
-  mapchan -n
-
-   to turn off this feature.
-
-   Note that there is a multitude of SCO entries in the makefile, many of
-   them exhibiting an unusually large number of compiler options. Some
-   people actually understand all of this. Reportedly, things are
-   settling down with SCO OpenServer 5.x and Unixware 7 (and Open UNIX 8
-   and who knows what the next one will be -- Linux probably) -- the SCO
-   UDK compiler is said to generate binaries that will run on either
-   platform, by default, automatically. When using gcc or egcs, on the
-   other hand, differences persist, plus issues regarding the type of
-   binary that is generated (COFF, ELF, etc), and where and how it can
-   run. All of this could stand further clarification by SCO experts.
-    ________________________________________________________________________
-
-  3.6.3. Unixware
-
-   [ [383]Top ] [ [384]Contents ] [ [385]Section Contents ] [ [386]Next ]
-   [ [387]Previous ]
-
-   Unixware changed hands several times before landing at SCO, and so has
-   its [388]own section in this document. (Briefly: AT&T UNIX Systems
-   Laboratories sold the rights to the UNIX name and to System V R4 (or
-   R5?) to Novell; later Novell spun its UNIX division off into a new
-   company called Univel, which eventually was bought by SCO, which later
-   was bought by Caldera, which later sort of semi-spun-off SCO...)
-    ________________________________________________________________________
-
-  3.6.4. Open UNIX 8
-
-   [ [389]Top ] [ [390]Contents ] [ [391]Section Contents ] [
-   [392]Previous ]
-
-   SCO was bought by Caldera in 2000 or 2001 and evolved Unixware 7.1
-   into Caldera Open UNIX 8.00. It's just like Unixware 7.1 as far as
-   Kermit is concerned (the Unixware 7.1 makefile target works for Open
-   UNIX 8.00, and in fact a Unixware 7.1 Kermit binary built on Unixware
-   7.1 runs under OU8; a separate OU8 makefile target exists simply to
-   generate an appropriate program startup herald). Open Unix is now
-   defunct; subsequent releases are called UnixWare again (e.g. UnixWare
-   7.1.3).
-    ________________________________________________________________________
-
-  3.7. C-KERMIT AND SOLARIS
-
-   [ [393]Top ] [ [394]Contents ] [ [395]Section Contents ] [ [396]Next ]
-   [ [397]Previous ]
-
-   SECTION CONTENTS
-
-3.7.1. [398]Serial Port Configuration
-3.7.2. [399]Serial Port Problems
-3.7.3. [400]SunLink X.25
-3.7.4. [401]Sun Workstation Keyboard Mapping
-3.7.5. [402]Solaris 2.4 and Earlier
-
-   REFERENCES
-
-     * The [403]comp.unix.solaris newsgroup
-     * [404]http://access1.sun.com/
-     * [405]http://docs.sun.com/
-     * [406]http://www.sunhelp.com/
-     * [407]http://www.wins.uva.nl/pub/solaris/solaris2/
-     * [408]http://www.wins.uva.nl/cgi-bin/sfaq.cgi
-     * [409]ftp://ftp.wins.uva.nl/pub/solaris
-     * [410]http://www.science.uva.nl/pub/solaris/solaris2.html
-
-   And about serial communications in particular, see "Celeste's Tutorial
-   on Solaris 2.x Modems and Terminals":
-
-  [411]http://www.stokely.com/
-
-   In particular:
-
-  [412]http://www.stokely.com/unix.sysadm.resources/faqs.sun.html
-
-   For PC-based Solaris, also see general comments on PC-based Unixes in
-   [413]Section 3.0. Don't expect Solaris or any other kind of Unix to
-   work right on a PC until you resolve all interrupt conflicts. Don't
-   expect to be able to use COM3 or COM4 (or even COM2) until you have
-   configured their addresses and interrupts.
-    ________________________________________________________________________
-
-  3.7.1. Serial Port Configuration
-
-   [ [414]Top ] [ [415]Contents ] [ [416]Section Contents ] [
-   [417]Section Contents ] [ [418]Next ]
-
-   Your serial port can't be used -- or at least won't work right --
-   until it is enabled in Solaris. For example, you get a message like
-   "SERIAL: Operation would block" when attempting to dial. This probably
-   indicates that the serial port has not been enabled for use with
-   modems. You'll need to follow the instructions in your system setup or
-   management manual, such as (e.g.) the Desktop SPARC Sun System &
-   Network Manager's Guide, which should contain a section "Setting up
-   Modem Software"; read it and follow the instructions. These might (or
-   might not) include running a program called "eeprom", editing some
-   system configuration file (such as, for example:
-
-  /platform/i86pc/kernel/drv/asy.conf
-
-   and then doing a configuration reboot, or running some other programs
-   like drvconfig and devlinks. "man eeprom" for details.
-
-   Also, on certain Sun models like IPC, the serial port hardware might
-   need to have a jumper changed to make it an RS-232 port rather than
-   RS-423.
-
-   eeprom applies only to real serial ports, not to "Spiff" devices
-   (serial port expander), in which case setup with Solaris' admintool is
-   required.
-
-   Another command you might need to use is pmadm, e.g.:
-
-  pmadm -d -p zsmon -s tty3
-  pmadm -e -p zsmon -s tty3
-
-   You can use the following command to check if a process has the device
-   open:
-
-  fuser -f /dev/term/3
-
-   In some cases, however (according to Sun support, May 2001) "It is
-   still possible that a zombie process has hold of the port EVEN IF
-   there is no lock file and the fuser command comes up empty. In that
-   case, the only way to resolve the problem is by rebooting."
-
-   If you can't establish communication through a serial port to a device
-   that is not asserting CD (Carrier Detect), try setting the environment
-   variable "ttya-ignore-cd" to "true" (replace "ttya" with the port
-   name).
-    ________________________________________________________________________
-
-  3.7.2. Serial Port Problems
-
-   [ [419]Top ] [ [420]Contents ] [ [421]Section Contents ] [ [422]Next ]
-   [ [423]Previous ]
-
-   Current advice from Sun is to always the /dev/cua/x devices for
-   dialing out, rather than the /dev/term/x. Nevertheless, if you have
-   trouble dialing out with one, try the other.
-
-   Reportedly, if you start C-Kermit and "set line" to a port that has a
-   modem connected to it that is not turned on, and then "set flow
-   rts/cts", there might be some (unspecified) difficulties closing the
-   device because the CTS signal is not coming in from the modem.
-    ________________________________________________________________________
-
-  3.7.3. SunLink X.25
-
-   [ [424]Top ] [ [425]Contents ] [ [426]Section Contents ] [ [427]Next ]
-   [ [428]Previous ]
-
-   The built-in SunLink X.25 support for Solaris 2.3/2.4./25 and SunLink
-   8.01 or 9.00 works OK provided the X.25 system has been installed and
-   initialized properly. Packet sizes might need to be reduced to 256,
-   maybe even less, depending on the configuration of the X.25
-   installation. On one connection where C-Kermit 6.0 was tested, very
-   large packets and window sizes could be used in one direction, but
-   only very small ones would work in the other.
-
-   In any case, according to Sun, C-Kermit's X.25 support is superfluous
-   with SunLink 8.x / Solaris 2.3. Quoting an anonymous Sun engineer:
-
-     ... there is now no need to include any X.25 code within kermit. As
-     of X.25 8.0.1 we support the use of kermit, uucp and similar
-     protocols over devices of type /dev/xty. This facility was there in
-     8.0, and should also work on the 8.0 release if patch 101524 is
-     applied, but I'm not 100% sure it will work in all cases, which is
-     why we only claim support from 8.0.1 onwards.
-
-     When configuring X.25, on the "Advanced Configuration->Parameters"
-     screen of the x25tool you can select a number of XTY devices. If
-     you set this to be > 1, press Apply, and reboot, you will get a
-     number of /dev/xty entries created.
-
-     Ignore /dev/xty0, it is a special case. All the others can be used
-     exactly as if they were a serial line (e.g. /dev/tty) connected to
-     a modem, except that instead of using Hayes-style commands, you use
-     PAD commands.
-
-     From kermit you can do a 'set line' command to, say, /dev/xty1,
-     then set your dialing command to be "CALL 12345678", etc. All the
-     usual PAD commands will work (SET, PAR, etc).
-
-     I know of one customer in Australia who is successfully using this,
-     with kermit scripts, to manage some X.25-connected switches. He
-     used standard kermit, compiled for Solaris 2, with X.25 8.0 xty
-     devices.
-    ________________________________________________________________________
-
-  3.7.4. Sun Workstation Keyboard Mapping
-
-   [ [429]Top ] [ [430]Contents ] [ [431]Section Contents ] [ [432]Next ]
-   [ [433]Previous ]
-
-   Hints for using a Sun workstation keyboard for VT emulation when
-   accessing VMS, from the [434]comp.os.vms newsgroup:
-
-     From: Jerry Leichter <leichter@smarts.com>
-     Newsgroups: comp.os.vms
-     Subject: Re: VT100 keyboard mapping to Sun X server
-     Date: Mon, 19 Aug 1996 12:44:21 -0400
-
-     > I am stuck right now using a Sun keyboard (type 5) on systems
-     running SunOS
-     > and Solaris. I would like to use EVE on an OpenVMS box with
-     display back to
-     > the Sun. Does anyone know of a keyboard mapping (or some other
-     procedure)
-     > which will allow the Sun keyboard to approximate a VT100/VT220?
-
-     You can't get it exactly - because the keypad has one fewer key -
-     but you can come pretty close. Here's a set of keydefs I use:
-
-  keycode 101=KP_0
-  keycode 119=KP_1
-  keycode 120=KP_2
-  keycode 121=KP_3
-  keycode 98=KP_4
-  keycode 99=KP_5
-  keycode 100=KP_6
-  keycode 75=KP_7
-  keycode 76=KP_8
-  keycode 77=KP_9
-  keycode 52=KP_F1
-  keycode 53=KP_F2
-  keycode 54=KP_F3
-  keycode 57=KP_Decimal
-  keycode 28=Left
-  keycode 29=Right
-  keycode 30=KP_Separator
-  keycode 105=KP_F4
-  keycode 78=KP_Subtract
-  keycode 8=Left
-  keycode 10=Right
-  keycode 32=Up
-  keycode 33=Down
-  keycode 97=KP_Enter
-
-     Put this in a file - I use "keydefs" in my home directory and feed
-     it into xmodmap:
-
-  xmodmap - <$HOME/keydefs
-
-     This takes care of the arrow keys and the "calculator" key cluster.
-     The "+" key will play the role of the DEC "," key. The Sun "-" key
-     will be like the DEC "-" key, though it's in a physically different
-     position - where the DEC PF4 key is. The PF4 key is ... damn, I'm
-     not sure where "key 105" is. I *think* it may be on the leftmost
-     key of the group of four just above the "calculator" key cluster.
-
-     I also execute the following (this is all in my xinitrc file):
-
-  xmodmap -e 'keysym KP_Decimal = KP_Decimal'
-  xmodmap -e 'keysym BackSpace = Delete BackSpace' \
-          -e 'keysym Delete = BackSpace Delete'
-  xmodmap -e 'keysym KP_Decimal = Delete Delete KP_Decimal'
-  xmodmap -e 'add mod1 = Meta_R'
-  xmodmap -e 'add mod1 = Meta_L'
-
-     Beware of one thing about xmodmap: Keymap changes are applied to
-     the *whole workstation*, not just to individual windows. There is,
-     in fact, no way I know of to apply them to individual windows.
-     These definitions *may* confuse some Unix programs (and/or some
-     Unix users).
-
-     If you're using Motif, you may also need to apply bindings at the
-     Motif level. If just using xmodmap doesn't work, I can try and dig
-     that stuff up for you.
-    ________________________________________________________________________
-
-  3.7.5. Solaris PPP Connections
-
-   [ [435]Top ] [ [436]Contents ] [ [437]Section Contents ] [ [438]Next ]
-   [ [439]Previous ]
-
-   The following is a report from a user of C-Kermit 8.0 on Solaris 8 and
-   9, who had complained that while Kermit file transfers worked
-   perfectly on direct (non-PPP) dialout connections, they failed
-   miserably on PPP connections. We suggested that the PPP dialer
-   probably was not setting the port and/or modem up in the same way that
-   Kermit did:
-
-     I want to get back on this and tell you what the resolution was.
-     You pointed me in the direction of flow control, which turned out
-     to be the key.
-
-     Some discussion on the comp.unix.solaris newsgroup led to some
-     comments from Greg Andrews about the need to use the uucp driver to
-     talk to the modem (/dev/cua/a). I had to remind Greg that no matter
-     what the manpages for the zs and se drivers say, the ppp that Sun
-     released with Solaris 8 7/01, and has in Solaris 9, is a setuid
-     root program, and simply trying to make a pppd call from user space
-     specifying /dev/cua/a would fail because of permissions. Greg
-     finally put the question to the ppp people, who came back with
-     information that is not laid out anywhere in the docs available for
-     Solaris users. Namely, put /dev/cua/a in one of the priviledged
-     options files in the /etc/ppp directory. That, plus resetting the
-     OBP ttya-ignore-cd flag (this is Sun hardware) to false, seems to
-     have solved the problems.
-
-     While I note that I had installed Kermit suid to uucp to use
-     /dev/cua/a on this particular box, it seems to run fine through
-     /dev/term/a. Not so with pppd.
-
-     With this change in place, I seem to be able to upload and download
-     through telnet run on Kermit with the maximum length packets. I
-     note that the window allocation display does show STREAMING, using
-     telnet. Running ssh on Kermit, I see the standard 1 of 30 windows
-     display, and note that there appears to be a buffer length limit
-     between 1000 and 2000 bytes. Run with 1000, and it's tick-tock,
-     solid as a rock. With 2000 I see timeout errors and RTS/CTS action
-     on the modem.
-
-   Kermit's packet-length and other controls let you make adjustments
-   like this to get around whatever obstacles might be thrown up -- in
-   this case (running Kermit over ssh), the underling Solaris PTY driver.
-    ________________________________________________________________________
-
-  3.7.6. Solaris 2.4 and Earlier
-
-   [ [440]Top ] [ [441]Contents ] [ [442]Section Contents ] [
-   [443]Previous ]
-
-   C-Kermit can't be compiled successfully under Solaris 2.3 using
-   SUNWspro cc 2.0.1 unless at least some of the following patches are
-   applied to cc (it is not known which one(s), if any, fix the problem):
-
-     * 100935-01 SparcCompiler C 2.0.1: bad code generated when addresses
-       of two double arguments are involved
-     * 100961-05 SPARCcompilers C 2.0.1: conditional expression with
-       function returning structure gives wrong value
-     * 100974-01 SparcWorks 2.0.1: dbx jumbo patch
-     * 101424-01 SPARCworks 2.0.1 maketool SEGV's instantly on Solaris
-       2.3
-
-   With unpatched cc 2.0.1, the symptom is that certain modules generate
-   truncated object files, resulting in many unresolved references at
-   link time.
-
-     The rest of the problems in this section have to do with
-     bidirectional terminal ports and the Solaris Port Monitor. A bug in
-     C-Kermit 5A ticked a bug in Solaris. The C-Kermit bug was fixed in
-     version 6.0, and the Solaris bug was fixed in 2.4 (I think, or
-     maybe 2.5). 
-
-   Reportedly, "C-Kermit ... causes a SPARCstation running Solaris 2.3 to
-   panic after the modem connects. I have tried compiling C-Kermit with
-   Sun's unbundled C compiler, with GCC Versions 2.4.5 and 2.5.3, with
-   make targets 'sunos51', 'sunos51tcp', 'sunos51gcc', and even 'sys5r4',
-   and each time it compiles and starts up cleanly, but without fail, as
-   soon as I dial the number and get a 'CONNECT' message from the modem,
-   I get:
-
-  BAD TRAP
-  kermit: Data fault
-  kernel read fault at addr=0x45c, pme=0x0
-  Sync Error Reg 80 <INVALID>
-  ...
-  panic: Data Fault.
-  ...
-  Rebooting...
-
-   The same modem works fine for UUCP/tip calling." Also (reportedly),
-   this only happens if the dialout port is configured as in/out via
-   admintool. If it is configured as out-only, no problem. This is the
-   same dialing code that works on hundreds of other System-V based Unix
-   OS's. Since it should be impossible for a user program to crash the
-   operating system, this problem must be chalked up to a Solaris bug.
-   Even if you SET CARRIER OFF, CONNECT, and dial manually by typing
-   ATDTnnnnnnn, the system panics as soon as the modem issues its CONNECT
-   message. (Clearly, when you are dialing manually, C-Kermit does not
-   know a thing about the CONNECT message, and so the panic is almost
-   certainly caused by the transition of the Carrier Detect (CD) line
-   from off to on.) This problem was reported by many users, all of whom
-   say that C-Kermit worked fine on Solaris 2.1 and 2.2. If the
-   speculation about CD is true, then a possible workaround might be to
-   configure the modem to leave CD on (or off) all the time. Perhaps by
-   the time you read this, a patch will have been issued for Solaris 2.3.
-
-   The following is from Karl S. Marsh, Systems & Networks Administrator,
-   AMBIX Systems Corp, Rochester, NY:
-
-     Environment: Solaris 2.3 Patch 101318-45 C-Kermit 5A(189) (and
-     presumably this applies to 188 and 190 also). eeprom setting:
-
-  ttya-rts-dtr-off=false
-  ttya-ignore-cd=false
-  ttya-mode=19200,8,n,8,-
-
-     To use C-Kermit on a bidirectional port in this environment, do not
-     use admintool to configure the port. Use admintool to delete any
-     services running on the port and then quit admintool and issue the
-     following command:
-
-  pmadm -a -p zsmon -s ttyb -i root -fu -v 1 -m "`ttyadm -b -d /dev/term/b \
-  -l conttyH -m ldterm,ttcompat -s /usr/bin/login -S n`"
-
-     [NOTE: This was copied from a blurry fax, so please check it
-     carefully] where:
-
-  -a = Add service
-  -p = pmtag (zsmon)
-  -s = service tag (ttyb)
-  -i = id to be associated with service tag (root)
-  -fu = create utmp entry
-  -v = version of ttyadm
-  -m = port monitor-specific portion of the port monitor administrative file
-       entry for the service
-  -b = set up port for bidirectional use
-  -d = full path name of device
-  -l = which ttylabel in the /etc/ttydefs file to use
-  -m = a list of pushable STREAMS modules
-  -s = pathname of service to be invoked when connection request received
-  -S = software carrier detect on or off (n = off)
-
-     "This is exactly how I was able to get Kermit to work on a
-     bi-directional port without crashing the system."
-
-   On the Solaris problem, also see SunSolve Bug ID 1150457 ("Using
-   C-Kermit, get Bad Trap on receiving prompt from remote system").
-   Another user reported "So, I have communicated with the Sun tech
-   support person that submitted this bug report [1150457]. Apparently,
-   this bug was fixed under one of the jumbo kernel patches. It would
-   seem that the fix did not live on into 101318-45, as this is EXACTLY
-   the error that I see when I attempt to use kermit on my system."
-
-   Later (Aug 94)... C-Kermit dialout successfully tested on a Sun4m with
-   a heavily patched Solaris 2.3. The patches most likely to have been
-   relevant:
-
-     * 101318-50: SunOS 5.3: Jumbo patch for kernel (includes libc,
-       lockd)
-     * 101720-01: SunOS 5.3: ttymon - prompt not always visible on a
-       modem connection
-     * 101815-01: SunOS 5.3: Data fault in put() NULL queue passed from
-       ttycommon_qfull()
-     * 101328-01: SunOS 5.3: Automation script to properly setup tty
-       ports prior to PCTS execution
-
-   Still later (Nov 94): another user (Bo Kullmar in Sweden) reports that
-   after using C-Kermit to dial out on a bidirectional port, the port
-   might not answer subsequent incoming calls, and says "the problem is
-   easy enough to fix with the Serial Port Manager; I just delete the
-   service and install it again using the graphical interface, which
-   underneath uses commands like sacadm and pmadm." Later Bo reports, "I
-   have found that if I run Kermit with the following script then it
-   works. This script is for /dev/cua/a, "-s a" is the last a in
-   /dev/cua/a:
-
-  #! /bin/sh
-  kermit
-  sleep 2
-  surun pmadm -e -p zsmon -s a
-    ________________________________________________________________________
-
-  3.8. C-KERMIT AND SUNOS
-
-   [ [444]Top ] [ [445]Contents ] [ [446]Section Contents ] [ [447]Next ]
-   [ [448]Previous ]
-
-   For additional information, see "Celeste's Tutorial on SunOS 4.1.3+
-   Modems and Terminals":
-
-  [449]http://www.stokely.com/
-
-   For FAQs, etc, from Sun, see:
-     * [450]http://access1.sun.com/
-
-   For history of Sun models and SunOS versions, see (should be all the
-   same):
-     * [451]http://www.ludd.luth.se/~bear/project/sun/sun.hardware.txt
-     * [452]ftp://ftp.netcom.com/pub/ru/rubicon/sun.hdwr.ref
-     * [453]ftp://ftp.intnet.net/pub/SUN/Sun-Hardware-Ref
-
-   Sun SPARCstation users should read the section "Setting up Modem
-   Software" in the Desktop SPARC Sun System & Network Manager's Guide.
-   If you don't set up your serial ports correctly, Kermit (and other
-   communications software) won't work right.
-
-   Also, on certain Sun models like IPC, the serial port hardware might
-   need to have a jumper changed to make it an RS-232 port rather than
-   RS-423.
-
-   Reportedly, C-Kermit does not work correctly on a Sun SPARCstation in
-   an Open Windows window with scrolling enabled. Disable scrolling, or
-   else invoke Kermit in a terminal emulation window (xterm, crttool,
-   vttool) under SunView (this might be fixed in later SunOS releases).
-
-   On the Sun with Open Windows, an additional symptom has been reported:
-   outbound SunLink X.25 connections "magically" translate CR typed at
-   the keyboard into LF before transmission to the remote host. This
-   doesn't happen under SunView.
-
-   SET CARRIER ON, when used on the SunOS 4.1 version of C-Kermit
-   (compiled in the BSD universe), causes the program to hang
-   uninterruptibly when SET LINE is issued for a device that is not
-   asserting carrier. When Kermit is built in the Sys V universe on the
-   same computer, there is no problem (it can be interrupted with
-   Ctrl-C). This is apparently a limitation of the BSD-style tty driver.
-
-   SunOS 4.1 C-Kermit has been observed to dump core when running a
-   complicated script program under cron. The dump invariably occurs in
-   ttoc(), while trying to output a character to a TCP/IP TELNET
-   connection. ttoc() contains a write() call, and when the system or the
-   network is very busy, the write() call can get stuck for long periods
-   of time. To break out of deadlocks caused by stuck write() calls,
-   there is an alarm around the write(). It is possible that the core
-   dump occurs when this alarm signal is caught. (This one has not been
-   observed recently -- possibly fixed in edit 190.)
-
-   On Sun computers with SunOS 4.0 or 4.1, SET FLOW RTS/CTS works only if
-   the carrier signal is present from the communication device at the
-   time when C-Kermit enters packet mode or CONNECT mode. If carrier is
-   not sensed (e.g. when dialing), C-Kermit does not attempt to turn on
-   RTS/CTS flow control. This is because the SunOS serial device driver
-   does not allow characters to be output if RTS/CTS is set (CRTSCTS) but
-   carrier (and DSR) are not present. Workaround (maybe): SET CARRIER OFF
-   before giving the SET LINE command, establish the connection, then SET
-   FLOW RTS/CTS
-
-   It has also been reported that RTS/CTS flow control under SunOS 4.1
-   through 4.1.3 works only on INPUT, not on output, and that there is a
-   patch from Sun to correct this problem: Patch-ID# T100513-04, 20 July
-   1993 (this patch might apply only to SunOS 4.1.3). It might also be
-   necessary to configure the eeprom parameters of the serial port; e.g.
-   do the following as root at the shell prompt:
-
-  eeprom  ttya-ignore-cd=false
-  eeprom  ttya-rts-dtr-off=true
-
-   There have been reports of file transfer failures on Sun-3 systems
-   when using long packets and/or large window sizes. One user says that
-   when this happens, the console issues many copies of this message:
-
-  chaos vmunix: zs1: ring buffer overflow
-
-   This means that SunOS is not scheduling Kermit frequently enough to
-   service interrupts from the zs serial device (Zilog 8350 SCC serial
-   communication port) before its input silo overflows. Workaround: use
-   smaller packets and/or a smaller window size, or use "nice" to
-   increase Kermit's priority. Use hardware flow control if available, or
-   remove other active processes before running Kermit.
-
-   SunLink X.25 support in C-Kermit 5A(190) was built and tested
-   successfully under SunOS 4.1.3b and SunLink X.25 7.00.
-    ________________________________________________________________________
-
-  3.9. C-KERMIT AND ULTRIX
-
-   [ [454]Top ] [ [455]Contents ] [ [456]Section Contents ] [ [457]Next ]
-   [ [458]Previous ]
-
-   See also: The [459]comp.unix.ultrix and [460]comp.sys.dec newsgroups.
-
-   There is no hardware flow control in Ultrix. That's not a Kermit
-   deficiency, but an Ultrix one.
-
-   When sending files to C-Kermit on a Telnet connection to a remote
-   Ultrix system, you must SET PREFIXING ALL (or at least prefix more
-   control characters than are selected by SET PREFIXING CAUTIOUS).
-
-   Reportedly, DEC ULTRIX 4.3 is immune to C-Kermit's disabling of
-   SIGQUIT, which is the signal that is generated when the user types
-   Ctrl-\, which kills the current process (i.e. C-Kermit) and dumps
-   core. Diagnosis and cure unknown. Workaround: before starting C-Kermit
-   -- or for that matter, when you first log in because this applies to
-   all processes, not just Kermit -- give the following Unix command:
-
-  stty quit undef
-
-   Certain operations driven by RS-232 modem signal do not work on
-   DECstations or other DEC platforms whose serial interfaces use MMP
-   connectors (DEC version of RJ45 telephone jack with offset tab). These
-   connectors convey only the DSR and DTR modem signals, but not carrier
-   (CD), RTS, CTS, or RI. Use SET CARRIER OFF to enable communication, or
-   "hotwire" DSR to CD.
-
-   The maximum serial speed on the DECstation 5000 is normally 19200, but
-   various tricks are available (outside Kermit) to enable higher rates.
-   For example, on the 5000/200, 19200 can be remapped (somehow,
-   something to do with "a bit in the SIR", whatever that is) to 38400,
-   but in software you must still refer to this speed as 19200; you can't
-   have 19200 and 38400 available at the same time.
-
-   19200, reportedly, is also the highest speed supported by Ultrix, but
-   NetBSD reportedly supports speeds up to 57600 on the DECstation,
-   although whether and how well this works is another question.
-
-   In any case, given the lack of hardware flow control in Ultrix, high
-   serial speeds are problematic at best.
-    ________________________________________________________________________
-
-  3.10. C-KERMIT AND UNIXWARE
-
-   [ [461]Top ] [ [462]Contents ] [ [463]Section Contents ] [ [464]Next ]
-   [ [465]Previous ]
-
-   See also:
-     * The Freebird Project (Unixware software repository)
-       [466]http://www.freebird.org/
-     * The UnixWare FAQ: [467]http://www.freebird.org/faq/
-     * The following newsgroups:
-          + [468]comp.unix.unixware.misc
-          + [469]comp.unix.sco.misc.
-
-   Also see general comments on PC-based Unixes in [470]Section 3.0. By
-   the way, this section is separate from the SCO (Caldera) section
-   because at the time this section was started, Unixware was owned by a
-   company called Univel. Later it was sold to Novell, and then to SCO.
-   Still later, SCO was sold to Caldera.
-
-   In Unixware 2.0 and later, the preferred serial device names (drivers)
-   are /dev/term/00 (etc), rather than /dev/tty00 (etc). Note the
-   following correspondence of device names and driver characteristics:
-
-  New name       Old name     Description              
-  /dev/term/00   /dev/tty00   ???
-  /dev/term/00h  /dev/tty00h  Modem signals and hardware flow control
-  /dev/term/00m  /dev/tty00m  Modem signals(?)
-  /dev/term/00s  /dev/tty00s  Modem signals and software flow control
-  /dev/term/00t  /dev/tty00t  ???
-
-   Lockfile names use device.major.minor numbers, e.g.:
-
-  /var/spool/locks/LK.7679.003.005
-
-   The minor number varies according to the device name suffix (none, h,
-   m, s, or t). Only the device and major number are compared, and thus
-   all of the different names for the same physical device (e.g. all of
-   those shown in the table above) interlock effectively.
-
-   Prior to UnixWare 7, serial speeds higher than 38400 are not
-   supported. In UnixWare 7, we also support 57600 and 115200, plus some
-   unexpected ones like 14400, 28800, and 76800, by virtue of a strange
-   new interface, evidently peculiar to UnixWare 7, discovered while
-   digging through the header files: tcsetspeed(). Access to this
-   interface is allowed only in POSIX builds, and thus the UnixWare 7
-   version of C-Kermit is POSIX-based, unlike C-Kermit for Unixware 1.x
-   and 2.x (since the earlier UnixWare versions did not support high
-   serial speeds, period).
-
-   HOWEVER, turning on POSIX features engages all of the "#if
-   (!_POSIX_SOURCE)" clauses in the UnixWare header files, which in turn
-   prevent us from having modem signals, access to the hardware flow
-   control APIs, select(), etc -- in short, all the other things we need
-   in communications software, especially when high speeds are used. Oh
-   the irony. And so C-Kermit must be shamelessly butchered -- as it has
-   been so many times before -- to allow us to have the needed features
-   from the POSIX and non-POSIX worlds. See the UNIXWAREPOSIX sections of
-   [471]ckutio.c.
-
-   After the butchery, we wind up with Unixware 2.x having full
-   modem-signal capability, but politically-correct Unixware 7.x lacking
-   the ability to automatically detect a broken connection when carrier
-   drops.
-
-   Meanwhile the Unixware tcsetspeed() function allows any number at all
-   (any long, 0 or positive) as an argument and succeeds if the number is
-   a legal bit rate for the serial device, and fails otherwise. There is
-   no list anywhere of legal speeds. Thus the SET SPEED keyword table
-   ("set speed ?" to see it) is hardwired based on trial and error with
-   all known serial speeds, the maximum being 115200. However, to allow
-   for the possibility that other speeds might be allowed in the future
-   (or with different port drivers), the SET SPEED command for UnixWare 7
-   only allows you to specify any number at all; a warning is printed if
-   the number is not in the list, but the number is accepted anyway; the
-   command succeeds if tcsetspeed() accepts the number, and fails
-   otherwise.
-
-   In C-Kermit 8.0 testing, it was noticed that the POSIX method for
-   hanging up the phone by dropping DTR (set speed 0, pause, restore
-   speed) did not actually drop DTR. The APIs do not return any error
-   indication, but nothing happens. I changed tthang() to skip the
-   special case I had made for Unixware and instead follow the normal
-   path: if TIOCSDTR is defined use that, otherwise blah blah... It turns
-   out TIOCSDTR *is* defined, and it works.
-
-   So in Unixware (at least in 2.1.3) we can read modem signals, hangup
-   by toggling DTR, and so on, BUT... But once the remote hangs up and
-   Carrier drops, the API for reading modem signals ceases to function;
-   although the device is still open, the TIOCMGET ioctl always raises
-   errno 6 = ENXIO, "No such device or address".
-
-   Old business:
-
-   Using C-Kermit 6.0 on the UnixWare 1.1 Application Server, one user
-   reported a system panic when the following script program is executed:
-
-  set line /dev/tty4
-  set speed 9600
-  output \13
-  connect
-
-   The panic does not happen if a PAUSE is inserted:
-
-  set line /dev/tty4
-  set speed 9600
-  pause 1
-  output \13
-  connect
-
-   This is using a Stallion EasyIO card installed as board 0 on IRQ 12 on
-   a Gateway 386 with the Stallion-supplied driver. The problem was
-   reported to Novell and Stallion and (reportedly) is now fixed.
-    ________________________________________________________________________
-
-  3.11. C-KERMIT AND APOLLO SR10
-
-   [ [472]Top ] [ [473]Contents ] [ [474]Section Contents ] [ [475]Next ]
-   [ [476]Previous ]
-
-   Reportedly, version 5A(190), when built under Apollo SR10 using "make
-   sr10-bsd", compiles, links, and executes OK, but leaves the terminal
-   unusable after it exits -- the "cs7" or "cs8" (character size)
-   parameter has become cs5. The terminal must be reset from another
-   terminal. Cause and cure unknown. Suggested workaround: Wrap Kermit in
-   a shell script something like:
-
-  kermit @*
-  stty sane
-    ________________________________________________________________________
-
-  3.12. C-KERMIT AND TANDY XENIX 3.0
-
-   [ [477]Top ] [ [478]Contents ] [ [479]Section Contents ] [ [480]Next ]
-   [ [481]Previous ]
-
-   C-Kermit 7.0 was too big to be built on Tandy Xenix, even in a minimum
-   configuration; version 6.0 is the last one that fits.
-
-   Reportedly, in C-Kermit 6.0, if you type lots of Ctrl-C's during
-   execution of the initialization file, ghost Kermit processes will be
-   created, and will compete for the keyboard. They can only be removed
-   via "kill -9" from another terminal, or by rebooting. Diagnosis --
-   something strange happening with the SIGINT handler while the process
-   is reading the directory (it seems to occur during the SET PROMPT
-   [\v(dir)] ... sequence). Cure: unknown. Workaround: don't interrupt
-   C-Kermit while it is executing its init file on the Tandy 16/6000.
-    ________________________________________________________________________
-
-  3.13. C-KERMIT AND OSF/1 (DIGITAL UNIX) (TRU64 UNIX)
-
-   [ [482]Top ] [ [483]Contents ] [ [484]Section Contents ] [ [485]Next ]
-   [ [486]Previous ]
-
-   While putting together and testing C-Kermit 8.0, it was discovered
-   that binaries built for one version of Tru64 Unix (e.g. 4.0G) might
-   exhibit very strange behavior if run on a different version of Tru64
-   Unix (e.g. 5.1A). The typical symptom was that a section of the
-   initialization file would be skipped, notably locating the dialing
-   and/or network directory as well as finding and executing the
-   customization file, ~/.mykermrc. This problem also is reported to
-   occur on Tru64 Unix 5.0 (Rev 732) even when running a C-Kermit binary
-   that was built there. However, the Tru64 5.1A binary works correctly
-   on 5.0. Go figure.
-
-   When making Telnet connections to a Digital Unix or Tru64 system, and
-   your Telnet client forwards your user name, the Telnet server
-   evidently stuffs the username into login's standard input, and you
-   see:
-
-  login: ivan
-  Password:
-
-   This is clearly going to play havoc with scripts that look for
-   "login:". Workaround (when Kermit is your Telnet client): SET LOGIN
-   USER to nothing, to prevent Kermit from sending your user ID.
-
-   Before you can use a serial port on a new Digital Unix system, you
-   must run uucpsetup to enable or configure the port. Evidently the
-   /dev/tty00 and 01 devices that appear in the configuration are not
-   usable; uucpsetup turns them into /dev/ttyd00 and 01, which are. Note
-   that uucpsetup and other uucp-family programs are quite primitive --
-   they only know about speeds up to 9600 bps and their selection of
-   modems dates from the early 1980s. None of this affects Kermit, though
-   -- with C-Kermit, you can use speeds up to 115200 bps (at least in
-   DU4.0 and later) and modern modems with hardware flow control and all
-   the rest.
-
-   Reportedly, if a modem is set for &S0 (assert DSR at all times), the
-   system resets or drops DTR every 30 seconds; reportedly DEC says to
-   set &S1.
-
-   Digital Unix 3.2 evidently wants to believe your terminal is one line
-   longer than you say it is, e.g. when a "more" or "man" command is
-   given. This is has nothing to do with C-Kermit, but tends to annoy
-   those who use Kermit or other terminal emulators to access Digital
-   Unix systems. Workaround: tell Unix to "stty rows 23" (or whatever).
-
-   Reportedly, there is some bizarre behavior when trying to use a
-   version of C-Kermit built on one Digital Unix 4.0 system on another
-   one, possibly due to differing OS or library revision levels; for
-   example, the inability to connect to certain TCP/IP hosts. Solution:
-   rebuild C-Kermit from source code on the system where you will be
-   using it.
-
-   Digital Unix tgetstr() causes a segmentation fault. C-Kermit 7.0 added
-   #ifdefs to avoid calling this routine in Digital Unix. As a result,
-   the SCREEN commands always send ANSI escape sequences -- even though
-   curses knows your actual terminal type.
-
-   Reportedy the Tru64 Unix 4.0E 1091 Telnet server does not tolerate
-   streaming transfers into itself, at least not when the sending Kermit
-   is on the same local network. Solution: tell one Kermit or the other
-   (or both) to "set streaming off". This might or might be the case with
-   earlier and/or later Tru64, Digital Unix, and OSF/1 releases.
-    ________________________________________________________________________
-
-  3.14. C-KERMIT AND SGI IRIX
-
-   [ [487]Top ] [ [488]Contents ] [ [489]Section Contents ] [ [490]Next ]
-   [ [491]Previous ]
-
-   See also:
-     * The [492]comp.sys.sgi.misc and [493]comp.sys.sgi.admin newsgroups.
-       [494]The SGI website
-     * The SGI FAQ:
-          + [495]http://www-viz.tamu.edu/~sgi-faq/
-          + [496]ftp://viz.tamu.edu/pub/sgi/faq/
-
-   About IRIX version numbers: "uname -a" tells the "two-digit" version
-   number, such as "5.3" or "6.5". The three-digit form can be seen with
-   "uname -R". (this information is unavailable at the simple API level).
-   Supposedly all three-digit versions within the same two-digit version
-   (e.g. 6.5.2, 6.5.3) are binary compatible; i.e. a binary built on any
-   one of them should run on all others. The "m" suffix denotes just
-   patches; the "f" suffix indicates that features were added.
-
-   An IRIX binary built on lower MIPS model (Instruction Set
-   Architecture, ISA) can run on higher models, but not vice versa:
-
-     MIPS1 R3000 and below
-     MIPS2 R4000
-     MIPS3 R4x00
-     MIPS4 R5000 and above
-
-   Furthermore, there are different Application Binary Inferfaces (ABIs):
-
-     COFF    32 bits, IRIX 5.3, 5.2, 5.1, 4.x and below
-     o32 ELF 32 bits, IRIX 5.3, 6.0 - 6.5
-     N32 ELF 32 bits, IRIX 6.2 - 6.5
-     N64 ELF 64 bits, IRIX 6.2 - 6.5
-
-   Thus a prebuilt IRIX binary works on a particular machine only if (a)
-   the machine's IRIX version (to one decimal place) is equal to or
-   greater than the version under which the binary was built; (b) the
-   machine's MIPS level is greater or equal to that of the binary; and
-   (c) the machine supports the ABI of the binary. If all three
-   conditions are not satisfied, of course, you can build a binary
-   yourself from source code since, unlike some other Unix vendors, SGI
-   does supply a C compiler and libraries.
-
-   SGI did not supply an API for hardware flow control prior to IRIX 5.2.
-   C-Kermit 6.1 and higher for IRIX 5.2 and higher supports hardware flow
-   control in the normal way, via "set flow rts/cts".
-
-   For hardware flow control on earlier IRIX and/or C-Kermit versions,
-   use the ttyf* (modem control AND hardware flow control) devices and
-   not the ttyd* (direct) or ttym* (modem control but no hardware flow
-   control) ones, and obtain the proper "hardware handshaking" cable from
-   SGI, which is incompatible with the ones for the Macintosh and NeXT
-   even though they look the same ("man serial" for further info) and
-   tell Kermit to "set flow keep" and "set modem flow rts/cts".
-
-   Serial speeds higher than 38400 are available in IRIX 6.2 and later,
-   on O-class machines (e.g. Origin, Octane) only, and are supported by
-   C-Kermit 7.0 and later. Commands such as "set speed 115200" may be
-   given on other models (e.g. Iris, Indy, Indigo) but will fail because
-   the OS reports an invalid speed for the device.
-
-   Experimentation with both IRIX 5.3 and 6.2 shows that when logged in
-   to IRIX via Telnet, that remote-mode C-Kermit can't send files if the
-   packet length is greater than 4096; the Telnet server evidently has
-   this restriction (or bug), since there is no problem sending long
-   packets on serial or rlogin connections. However, it can receive files
-   with no problem if the packet length is greater than 4096. As a
-   workaround, the FAST macro for IRIX includes "set send packet-length
-   4000". IRIX 6.5.1 does not have this problem, so evidently it was
-   fixed some time after IRIX 6.2. Tests show file-transfer speeds are
-   better (not worse) with 8K packets than with 4K packets from IRIX
-   6.5.1.
-
-   Reportedly some Indys have bad serial port hardware. IRIX 5.2, for
-   example, needs patch 151 to work around this; or upgrade to a later
-   release. Similarly, IRIX 5.2 has several problems with serial i/o,
-   flow control, etc. Again, patch or upgrade.
-
-   Reportedly on machines with IRIX 4.0, Kermit cannot be suspended by
-   typing the suspend ("swtch") character if it was started from csh,
-   even though other programs can be suspended this way, and even though
-   the Z and SUSPEND commands still work correctly. This is evidently
-   because IRIX's csh does not deliver the SIGTSTP signal to Kermit. The
-   reason other programs can be suspended in the same environment is
-   probably that they do not trap SIGTSTP themselves, so the shell is
-   doing the suspending rather than the application.
-
-   Also see notes about IRIX 3.x in the [497]C-Kermit for Unix
-   Installation Instructions.
-
-   If you have problems making TCP/IP connections in versions of IRIX
-   built with GCC 2.95.2, see the bugs section of:
-
-  [498]http://freeware.sgi.com/Installable/gcc-2.95.2.html.
-
-   Reportedly, if you allow gcc to compile C-Kermit on Irix you should be
-   aware that there might be problems with some of the network code. The
-   specifics are at
-   [499]http://freeware.sgi.com/Installable/gcc-2.95.2.html; scroll down
-   to the "known bugs" section at the end of the document.
-    ________________________________________________________________________
-
-  3.15. C-KERMIT AND THE BEBOX
-
-   [ [500]Top ] [ [501]Contents ] [ [502]Section Contents ] [ [503]Next ]
-   [ [504]Previous ]
-
-   See also: The [505]comp.sys.be newsgroup.
-
-   The BeBox has been discontinued and BeOS repositioned for PC
-   platforms. The POSIX parts of BeOS are not finished, nor is the
-   sockets library, therefore a fully functional version of C-Kermit is
-   not possible. In version 6.0 of C-Kermit, written for BeOS DR7, it was
-   possible to:
-
-     * set line /dev/serial2 (and probably the other serial ports)
-     * set speed 115200 (and at least some of the lower baud rates)
-     * connect
-     * set modem type hayes (and likely others, too)
-     * dial phone-number
-     * set send packet-length 2048 (other lengths for both send and
-       receive)
-     * set receive packet length 2048
-     * set file type binary (text mode works, too) (with remote kermit
-       session in server mode)
-     * put bedrop.jpg
-     * get bedrop.jpg
-     * get bedrop.jpg bedrop.jpg2
-     * finish, bye
-
-   The following do not work:
-     * kermit does not detect modem hangup
-     * !/RUN/PUSH [commandline command]
-     * Running kermit in remote mode
-     * Using other protocols (x/y/zmodem)
-     * TCP networking interface (Be's TCP/IP API has a ways to go, still)
-
-   C-Kermit does not work on BeOS DR8 because of changes in the
-   underlying APIs. Unfortunately not enough changes were made to allow
-   the regular POSIX-based C-Kermit to work either. Note: the lack of a
-   fork() service requires the select()-based CONNECT module, but there
-   is no select(). There is a select() in DR8, but it doesn't work.
-
-   C-Kermit 7.0 was built for BeOS 4.5 and works in remote mode. It does
-   not include networking support since the APIs are still not there. It
-   is not known if dialing out works, but probably not. Be experts are
-   welcome to lend a hand.
-    ________________________________________________________________________
-
-  3.16. C-KERMIT AND DG/UX
-
-   [ [506]Top ] [ [507]Contents ] [ [508]Section Contents ] [ [509]Next ]
-   [ [510]Previous ]
-
-   Somebody downloaded the C-Kermit 6.0 binary built under DG/UX 5.40 and
-   ran it under DG/UX 5.4R3.10 -- it worked OK except that file dates for
-   incoming files were all written as 1 Jan 1970. Cause and cure unknown.
-   Workaround: SET ATTRIBUTE DATE OFF. Better: Use a version of C-Kermit
-   built under and for DG/UX 5.4R3.10.
-    ________________________________________________________________________
-
-  3.17. C-KERMIT AND SEQUENT DYNIX
-
-   [ [511]Top ] [ [512]Contents ] [ [513]Section Contents ] [ [514]Next ]
-   [ [515]Previous ]
-
-   Reportedly, when coming into a Sequent Unix (DYNIX) system through an
-   X.25 connection, Kermit doesn't work right because the Sequent's
-   FIONREAD ioctl returns incorrect data. To work around, use the
-   1-character-at-a-time version of myread() in ckutio.c (i.e. undefine
-   MYREAD in ckutio.c and rebuild the program). This is unsatisfying
-   because two versions of the program would be needed -- one for use
-   over X.25, and the other for serial and TCP/IP connections.
-    ________________________________________________________________________
-
-  3.18. C-KERMIT AND {FREE,OPEN,NET}BSD
-
-   [ [516]Top ] [ [517]Contents ] [ [518]Section Contents ] [ [519]Next ]
-   [ [520]Previous ]
-
-   Some NebBSD users have reported difficulty escaping back from CONNECT
-   mode, usually when running NetBSD on non-PC hardware. Probably a
-   keyboard issue.
-
-   NetBSD users have also reported that C-Kermit doesn't pop back to the
-   prompt if the modem drops carrier. This needs to be checked out &
-   fixed if possible.
-
-   (All the above seems to work properly in C-Kermit 7.0 and later.)
-    ________________________________________________________________________
-
-  3.19. C-KERMIT AND MAC OS X (Rhapsody, Darwin, Jaguar, Panther)
-
-   [ [521]Top ] [ [522]Contents ] [ [523]Section Contents ] [ [524]Next ]
-   [ [525]Previous ]
-
-   Mac OS X is Apple's 4.4BSD Unix variety, closely related to FreeBSD,
-   but different. "uname -a" is singularly uninformative, as in Linux,
-   giving only the Darwin kernel version number. As far as I can tell,
-   there is no way to find out the Mac OS X version number, such as 10.3
-   (in Linux you can find the distribution version in a
-   distribution-dependent file). Here are some points to be aware of:
-
-     * The biggest gotcha for Kermit users is that Mac OS X does not
-       support serial ports and, as far as I can tell, doesn't support
-       its built-in modem either, for anything other than making Internet
-       connections. Macintoshes capable of running Mac OS X, such as the
-       G5, some without serial ports and without any APIs to support
-       them, and also without the UUCP family of programs (including cu),
-       nor any standard for serial-port lockfile directory.
-     * At least early versions of Mac OS X came without Curses, Termlib,
-       or Terminfo libraries. Later versions seem to have ncurses. Kermit
-       uses curses for its file-transfer display. See elsewhere about
-       curses-vs-ncurses confusion.
-     * In the HFS+ file system, filenames are case-folded. Thus
-       "makefile" and "Makefile" are the same file. The UFS file system
-       is, like normal Unix, case-sensitive.
-     * Files that are composed of a resource fork and a data fork... I
-       doubt that C-Kermit does anything useful with them. There is no
-       code in C-Kermit for traditional two-forked Macintosh files, but
-       it could be added if there is any demand.
-     * In case you want to transfer a traditional Macintosh text file (or
-       data fork of a file that is plain text), you can use these
-       C-Kermit commands:
-
-set file eol cr
-set file character-set apple-quickdraw
-send /text filename
-
-     * File or pathnames that include spaces must be enclosed in either
-       doublequotes or curly braces in C-Kermit commands.
-     * Mac OS X has its own package format for applications, called
-       "fink". Various fink packages for C-Kermit are floating around
-       that are not standard releases. For example, there's a C-Kermit
-       8.0.201 package in which C-Kermit was modifed (at least) to use a
-       UUCP lockfile directory that does not exist on vanilla Mac OS X
-       systems.
-
-    Mac OS X and Serial Ports
-
-   Apple is in the forefront of companies that believe serial ports have
-   no use in the modern world and so has simply eliminated all traces of
-   them from its machines and OS. But of course serial ports are still
-   needed to connect not only to external modems, but also to the control
-   ports of hubs, routers, terminal servers, PBXs, and similar devices,
-   not to mention barcode readers, POS systems and components, automated
-   factory-floor equipment, and scientific, medical, and lab equipment
-   (to name a few). Among workers in these areas, there is a need to add
-   serial ports back onto this platform, which is being filled by
-   third-party products such as the [526]Keyspan USB Serial Adapter. To
-   use the Keyspan device, you must install the accompanying device
-   drivers, which wind up giving you serial ports with names like
-   /dev/cu.USA19H3b1P1.1.
-
-   To configure your Mac OS X system to allow C-Kermit to use these (or
-   any other) serial devices:
-
-    1. su
-       chgrp xxxx /var/spool/lock
-       chmod g+w /var/spool/lock
-       chgrp xxxx /dev/cu.*
-       (where xxxx is the name of the group for users to whom serial-port
-       access is to be granted). Use "admin" or other existing group, or
-       create a new group if desired. NB:
-
-     In the absence of official guidance from Apple or anyone else, we
-     choose /var/spool/lock as the lockfile directory because this
-     directory (a) already exists on vanilla Mac OS X installations, and
-     (b) it is the directory used for serial-port lockfiles on many
-     other platforms. 
-    2. Put all users who need access to the serial port in the same
-       group.
-    3. Make sure the serial device files that are to be used by C-Kermit
-       have group read-write permission and (if you care) lack world
-       read-write permission, e.g.:
-       chmod g+rw,o-rw /dev/cu.*
-
-   If you do the above, then there's no need to become root to use
-   Kermit, or to make Kermit suid or sgid. Just do this:
-
-chmod 775 wermit
-mv wermit /usr/local/bin/kermit
-
-   (or whatever spot is more appropriate). For greater detail about
-   installation (man page, etc), [527]CLICK HERE.
-
-   Back when Macs had serial ports, they were not RS-232 (the standard
-   for connecting computers with nearby modems) but rather RS-422 or -423
-   (a standard for connecting serial devices over longer distances).
-   Macintosh serial ports do not support modems well because they do not
-   have enough wires (or more properly in the case RS-422/423, wire
-   pairs) to convey a useful subset of modem signals. The Keyspan USB
-   adapter gives you two Mini-Din8 RS-422 ports, that are no better (or
-   worse) for communicating with modems or serial devices than a real Mac
-   Din-8 port was. In essense, you get Data In, Data Out, and two modem
-   signals. It looks to me as if the signals chosen by Keyspan are RTS
-   and CTS. This gives you hardware flow control, but at the expense of
-   Carrier Detect. Thus to use C-Kermit with a Keyspan USB serial port,
-   you must tell C-Kermit to:
-
-set modem type none                ; (don't expect a modem)
-set carrier-watch off              ; (ignore carrier signal)
-set port /dev/cu.USA19H3b1P1.1     ; (open the port)
-set flow rts/cts                   ; (this is the default)
-set speed 57600                    ; (or whatever)
-connect                            ; (or whatever)
-
-   Use Ctrl-\C in the normal manner to escape back to the C-Kermit>
-   prompt. Kermit can't pop back to its prompt automatically when Carrier
-   drops because there is no Carrier signal.
-
-         Instructions for the built-in modem remain to be written.
-
-   Links:
-     * [528]Unix tips for Mac OS X (Jerry Stratton)
-    ________________________________________________________________________
-
-  3.20. C-KERMIT AND COHERENT
-
-   [ [529]Top ] [ [530]Contents ] [ [531]Section Contents ] [
-   [532]Previous ]
-
-   Also see:
-
-     [533]http://www.uni-giessen.de/faq/archiv/coherent-faq.general/msg00
-   000.html
-
-   Mark Williams COHERENT was perhaps the first commercial Unix-based
-   operating system for PCs, first appearing about 1983 or -84 for the
-   PC/XT (?), and popular until about 1993, when Linux took over.
-   C-Kermit, as of version 8.0, is still current for COHERENT 386 4.2
-   (i.e. only for i386 and above). Curses is included, but lots of other
-   features are omitted due to lack of the appropriate OS features, APIs,
-   libraries, hardware, or just space: e.g. TCP/IP, floating-point
-   arithmetic, learned scripts. Earlier versions of COHERENT ran on 8086
-   and 80286, but these are to small to build or run C-Kermit, but
-   G-Kermit should be OK (as might be ancient versions of C-Kermit).
-
-   You can actually build a version with floating point support -- just
-   take -DNOFLOAT out of CFLAGS and add -lm to LIBS; NOFLOAT is the
-   default because COHERENT tends to run on old PCs that don't have
-   floating-point hardware. You can also add "-f" to CFLAGS to have it
-   link in the floating-point emulation library. Also I'm not sure why
-   -DNOLEARN is included, since it depends on select(), which COHERENT
-   has.
-    ________________________________________________________________________
-
-  4. GENERAL UNIX-SPECIFIC HINTS, LIMITATIONS, AND BUGS
-
-   [ [534]Top ] [ [535]Contents ] [ [536]Next ] [ [537]Previous ]
-
-  4.1. Modem Signals
-
-   There seems to be an escalating demand for the ability to control
-   "dumb serial devices" (such as "smartcard readers", barcode readers,
-   etc) by explicitly manipulating modem signals, particularly RTS. This
-   might have been easy to do in DOS, where there is no operating system
-   standing between the application and the serial device, but it is
-   problematic in Unix, where modem signals are controlled by the serial
-   device driver. If the driver does not provide an API for doing this,
-   then the application can't do it. If it does provide an API, expect it
-   to be totally different on each Unix platform, since there is no
-   standard for this.
-
-  4.2. NFS Troubles
-
-   Beginning with C-Kermit 6.0, the default C-Kermit prompt includes your
-   current (working) directory; for example:
-
-  [/usr/olga] C-Kermit>
-
-   (In C-Kermit 7.0 the square braces were replaced by round parentheses
-   to avoid conflicts with ISO 646 national character sets.)
-
-   If that directory is on an NFS-mounted disk, and NFS stops working or
-   the disk becomes unavailable, C-Kermit will hang waiting for NFS
-   and/or the disk to come back. Whether you can interrupt C-Kermit when
-   it is hung this way depends on the specific OS. Kermit has called the
-   operating systems's getcwd() function, and is waiting for it to
-   return. Some versions of Unix (e.g. HP-UX 9.x) allow this function to
-   be interrupted with SIGINT (Ctrl-C), others (such as HP-UX 8.x) do
-   not. To avoid this effect, you can always use SET PROMPT to change
-   your prompt to something that does not involve calling getcwd(), but
-   if NFS is not responding, C-Kermit will still hang any time you give a
-   command that refers to an NFS-mounted directory. Also note that in
-   some cases, the uninterruptibility of NFS-dependent system or library
-   calls is considered a bug, and sometimes there are patches. For HP-UX,
-   for example:
-
-                                                        replaced by:
-  HP-UX 10.20     libc    PHCO_8764                     PHCO_14891/PHCO_16723
-  HP-UX 10.10     libc    PHCO_8763                     PHCO_14254/PHCO_16722
-  HP-UX 9.x       libc    PHCO_7747       S700          PHCO_13095
-  HP-UX 9.x       libc    PHCO_6779       S800          PHCO_11162
-
-  4.3. C-Kermit as Login Shell
-
-   You might have reason to make C-Kermit the login shell for a specific
-   user, by entering the pathname of Kermit (possibly with command-line
-   switches, such as -x to put it in server mode) into the shell field of
-   the /etc/passwd file. This works pretty well. In some cases, for
-   "ultimate security", you might want to use a version built with
-   -DNOPUSH (see the [538]Configurations Options document for this, but
-   even if you don't, then PUSHing or shelling out from C-Kermit just
-   brings up a new copy of C-Kermit (but warning: this does not prevent
-   the user from explicitly running a shell; e.g. "run /bin/sh"; use
-   NOPUSH to prevent this).
-
-  4.4. C-Kermit versus screen and splitvt
-
-   C-Kermit file transfers will probably not work if attemped through the
-   "splitvt" or GNU "screen" programs because the screen optimization (or
-   at least, line wrapping, control-character absorption) done by this
-   package interferes with Kermit's packets.
-
-   The same can apply to any other environment in which the user's
-   session is captured, monitored, recorded, or manipulated. Examples
-   include the 'script' program (for making a typescript of a session),
-   the Computronics PEEK package and pksh (at least versions of it prior
-   to 1.9K), and so on.
-
-   You might try the following -- what we call "doomsday Kermit" --
-   settings to push packets through even the densest and most obstructive
-   connections, such as "screen" and "splitvt" (and certain kinds of 3270
-   protocol emulators): Give these commands to BOTH Kermit programs:
-
-  SET FLOW NONE
-  SET CONTROL PREFIX ALL
-  SET RECEIVE PACKET-LENGTH 70
-  SET RECEIVE START 62
-  SET SEND START 62
-  SET SEND PAUSE 100
-  SET BLOCK B
-
-   If it works, it will be slow.
-
-  4.5. C-Kermit versus DOS Emulators
-
-   On Unix workstations equipped with DOS emulators like SoftPC, watch
-   out for what these emulators do to the serial port drivers. After
-   using a DOS emulator, particularly if you use it to run DOS
-   communications software, you might have to reconfigure the serial
-   ports for use by Unix.
-
-  4.6. C-Kermit versus Job Control
-
-   Interruption by Ctrl-Z makes Unix C-Kermit try to suspend itself with
-   kill(0,SIGTSTP), but only on platforms that support job control, as
-   determined by whether the symbol SIGTSTP is defined (or on POSIX or
-   SVR4 systems, if syconf(_SC_JOB_CONTROL) or _POSIX_JOB_CONTROL in
-   addition to SIGTSTP). However, if Kermit is running under a login
-   shell (such as the original Bourne shell) that does not support job
-   control, the user's session hangs and must be logged out from another
-   terminal, or hung up on. There is no way Kermit can defend itself
-   against this. If you use a non-job control shell on a computer that
-   supports job control, give a command like "stty susp undef" to fix it
-   so the suspend signal is not attached to any particular key, or give
-   the command SET SUSPEND OFF to C-Kermit, or build C-Kermit with
-   -DNOJC.
-
-  4.7. Dates and Times
-
-   Unix time conversion functions typically apply locale rules to return
-   local time in terms of any seasonal time zone change in effect for the
-   given date. The diffdate function assumes that the same timezone rules
-   are in effect for both dates, but a date with timezone information
-   will be converted to the local time zone in effect at the given time,
-   e.g., a GMT specification will produce either a Standard Time or
-   Daylight Savings Time, depending on which applies at the given time.
-   An example using the 2001 seasonal change from EDT (-0400) to EST
-   (-0500):
-
-  C-Kermit> DATE 20011028 05:01:02 GMT  ; EDT
-  20011028 01:01:02
-  C-Kermit> DATE 20011028 06:01:02 GMT  ; EST
-  20011028 01:01:02
-  C-Kermit>
-
-   but the implicit change in timezone offset is not recognized:
-
-  C-Kermit> echo \fdiffdate(20011028 05:01:02 GMT, 20011028 06:01:02 GMT)
-  +0:00
-  C-Kermit>
-
-   Date/time arithmetic, offsets, delta times, and timezone support are
-   new to C-Kermit 8.0, and might be expected to evolve and improve in
-   subsequent releases.
-
-   On some platforms, files downloaded with HTTP receive the current
-   timestamp, rather than the HTTP "Last Modified" time (this can be
-   fixed by including utime.h, e.g. in SunOS and Tru64...).
-
-  4.8. Pseudoterminals
-
-   The SSH and PTY commands work by assigning a pseudoterminal and
-   reading and writing from it. Performance varies according to the
-   specific platform ranging from very fast to very flow.
-
-   SSH and PTY commands can fail if (a) all pseudoterminals are in use;
-   or (b) you do not have read/write access to the pseudoterminal that
-   was assigned. An example of (b) was reported with the Zipslack
-   Slackware Linux distribution, in which the pseudoterminals were
-   created with crw-r--r-- permission, instead of crw-rw-rw-.
-
-  4.9. Miscellaneous
-
-     * Reportedly, the Unix C-Kermit server, under some conditions, on
-       certain particular systems, fails to log out its login session
-       upon receipt of a BYE command. Before relying on the BYE command
-       working, test it a few times to make sure it works on your system:
-       there might be system configuration or security mechanisms to
-       prevent an inferior process (like Kermit) from killing a superior
-       one (like the login shell).
-     * On AT&T 7300 (3B1) machines, you might have to "stty nl1" before
-       starting C-Kermit. Do this if characters are lost during
-       communications operations.
-     * Under the bash shell (versions prior to 1.07 from CWRU), "pushing"
-       to an inferior shell and then exiting back to Kermit leaves Kermit
-       in the background such that it must be explicitly fg'd. This is
-       reportedly fixed in version 1.07 of bash (and definitely in modern
-       bash versions).
-    ________________________________________________________________________
-
-  5. INITIALIZATION AND COMMAND FILES
-
-   [ [539]Top ] [ [540]Contents ] [ [541]Next ] [ [542]Previous ]
-
-   C-Kermit's initialization file for Unix is .kermrc (lowercase, starts
-   with period) in your home directory, unless Kermit was built with the
-   system-wide initialization-file option (see the [543]C-Kermit for Unix
-   Installation Instructions).
-
-   C-Kermit identifies your home directory based on the environment
-   variable, HOME. Most Unix systems set this variable automatically when
-   you log in. If C-Kermit can't find your initialization file, check
-   your HOME variable:
-
-  echo $HOME      (at the Unix prompt)
-
-   or:
-
-  echo \$(HOME)   (at the C-Kermit prompt)
-
-   If HOME is not defined, or is defined incorrectly, add the appropriate
-   definition to your Unix .profile or .login file, depending on your
-   shell:
-
-  setenv HOME full-pathname-of-your-home-directory  (C-Shell, .login file)
-
-   or:
-
-  HOME=full-pathname-of-your-home-directory         (sh, ksh, .profile file)
-  export HOME
-
-   NOTE: Various other operations depend on the correct definition of
-   HOME. These include the "tilde-expansion" feature, which allows you to
-   refer to your home directory as "~" in filenames used in C-Kermit
-   commands, e.g.:
-
-  send ~/.kermrc
-
-   as well as the \v(home) variable.
-
-   Prior to version 5A(190), C-Kermit would look for its initialization
-   file in the current directory if it was not found in the home
-   directory. This feature was removed from 5A(190) because it was a
-   security risk. Some people, however, liked this behavior and had
-   .kermrc files in all their directories that would set up things
-   appropriately for the files therein. If you want this behavior, you
-   can accomplish it in various ways, for example:
-
-     * Create a shell alias, for example:
-  alias kd="kermit -Y ./.kermrc"
-     * Create a .kermrc file in your home directory, whose contents are:
-  take ./.kermrc
-
-   Suppose you need to pass a password from the Unix command line to a
-   C-Kermit script program, in such a way that it does not show up in
-   "ps" or "w" listings. Here is a method (not guaranteed to be 100%
-   secure, but definitely more secure than the more obvious methods):
-
-  echo mypassword | kermit myscript
-
-   The "myscript" file contains all the commands that need to be executed
-   during the Kermit session, up to and including EXIT, and also includes
-   an ASK or ASKQ command to read the password from standard input, which
-   has been piped in from the Unix 'echo' command, but it must not
-   include a CONNECT command. Only "kermit myscript" shows up in the ps
-   listing.
-    ________________________________________________________________________
-
-  6. COMMUNICATION SPEED SELECTION
-
-   [ [544]Top ] [ [545]Contents ] [ [546]Next ] [ [547]Previous ]
-
-   Version-7 based Unix implementations, including 4.3 BSD and earlier
-   and Unix systems based upon BSD, use a 4-bit field to record a serial
-   device's terminal speed. This leaves room for 16 speeds, of which the
-   first 14 are normally:
-
-     0, 50, 75, 110, 134.5, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-     and 9600
-
-   The remaining two are usually called EXTA and EXTB, and are defined by
-   the particular Unix implementation. C-Kermit determines which speeds
-   are available on your system based on whether symbols for them are
-   defined in your terminal device header files. EXTA is generally
-   assumed to be 19200 and EXTB 38400, but these assumptions might be
-   wrong, or they might not apply to a particular device that does not
-   support these speeds. Presumably, if you try to set a speed that is
-   not legal on a particular device, the driver will return an error, but
-   this can not be guaranteed.
-
-   On these systems, it is usually not possible to select a speed of
-   14400 bps for use with V.32bis modems. In that case, use 19200 or
-   38400 bps, configure your modem to lock its interface speed and to use
-   RTS/CTS flow control, and tell C-Kermit to SET FLOW RTS/CTS and SET
-   DIAL SPEED-MATCHING OFF.
-
-   The situation is similar, but different, in System V. SVID Third
-   Edition lists the same speeds, 0 through 38400.
-
-   Some versions of Unix, and/or terminal device drivers that come with
-   certain third-party add-in high-speed serial communication interfaces,
-   use the low "baud rates" to stand for higher ones. For example, SET
-   SPEED 50 gets you 57600 bps; SET SPEED 75 gets you 76800; SET SPEED
-   110 gets 115200.
-
-   SCO ODT 3.0 is an example where a "baud-rate-table patch" can be
-   applied that can rotate the tty driver baud rate table such that
-   600=57600 and 1800=115k baud. Similarly for Digiboard
-   multiport/portservers, which have a "fastbaud" setting that does this.
-   Linux has a "setserial" command that can do it, etc.
-
-   More modern Unixes support POSIX-based speed setting, in which the
-   selection of speeds is not limited by a 4-bit field. C-Kermit 6.1
-   incorporates a new mechanism for finding out (at compile time) which
-   serial speeds are supported by the operating system that does not
-   involve editing of source code by hand; on systems like Solaris 5.1,
-   IRIX 6.2, and SCO OSR5.0.4, "set speed ?" will list speeds up to
-   460800 or 921600. In C-Kermit 7.0 and later:
-
-    1. If a symbol for a particular speed (say B230400 for 230400 bps)
-       appears in whatever header file defines acceptable serial speeds
-       (e.g. <termbits.h> or <sys/termios.h> or <sys/ttydev.h>, etc), the
-       corresponding speed will appear in C-Kermit's "set speed ?" list.
-    2. The fact that a given speed is listed in the header files and
-       appears in C-Kermit's list does not mean the driver will accept
-       it. For example, a computer might have some standard serial ports
-       plus some add-on ones with different drivers that accept a
-       different repertoire of speeds.
-    3. The fact that a given speed is accepted by the driver does not
-       guarantee the underlying hardware can accept it.
-
-   When Kermit is given a "set speed" command for a particular device,
-   the underlying system service is called to set the speed; its return
-   code is checked and the SET SPEED command fails if the return code
-   indicates failure. Regardless of the system service return status, the
-   device's speed is then read back and if it does not match the speed
-   that was requested, an error message is printed and the command fails.
-
-   Even when the command succeeds, this does not guarantee successful
-   operation at a particular speed, especially a high one. That depends
-   on electricity, information theory, etc. How long is the cable, what
-   is its capacitance, how well is it shielded, etc, not to mention that
-   every connection has two ends and its success depends on both of them.
-   (With the obvious caveats about internal modems, is the cable really
-   connected, interrupt conflicts, etc etc etc).
-
-   Note, in particular, that there is a certain threshold above which
-   modems can not "autobaud" -- i.e. detect the serial interface speed
-   when you type AT (or whatever else the modem's recognition sequence
-   might be). Such modems need to be engaged at a lower speed (say 2400
-   or 9600 or even 115200 -- any speed below their autobaud threshold)
-   and then must be given a modem-specific command (which can be found in
-   the modem manual) to change their interface speed to the desired
-   higher speed, and then the software must also be told to change to the
-   new, higher speed.
-
-   For additional information, read [548]Section 9.5 of the Installation
-   Instructions, plus any platform-specific notes in [549]Section 3
-   above.
-    ________________________________________________________________________
-
-  7. COMMUNICATIONS AND DIALING
-
-   [ [550]Top ] [ [551]Contents ] [ [552]Next ] [ [553]Previous ]
-
-  7.1. Serial Ports and Modems
-
-   If you SET LINE to a serial port modem-control device that has nothing
-   plugged in to it, or has a modem connected that is powered off, and
-   you have not given a prior SET MODEM TYPE or SET CARRIER-WATCH OFF
-   command, the SET LINE command is likely to hang. In most cases, you
-   can Ctrl-C out. If not, you'll have to kill C-Kermit from another
-   terminal.
-
-   Similarly, if you give a SET MODEM TYPE HAYES (or USR, or any other
-   modem type besides DIRECT, NONE, or UNKNOWN) and then SET LINE to an
-   empty port, the subsequent close (implicit or explicit) is liable to
-   hang or even crash (through no fault of Kermit's -- the hanging or
-   crashing is inside a system call such as cfsetospeed() or close()).
-
-   The SET CARRIER-WATCH command works as advertised only if the
-   underlying operating system and device drivers support this feature;
-   in particular only if a read() operation returns immediately with an
-   error code if the carrier signal goes away or, failing that, if
-   C-Kermit can obtain the modem signals from the device driver (you can
-   tell by giving a "set line" command to a serial device, and then a
-   "show communications" command -- if modem signals are not listed,
-   C-Kermit won't be able to detect carrier loss, the WAIT command will
-   not work, etc). Of course, the device itself (e.g. modem) must be
-   configured appropriately and the cables convey the carrier and other
-   needed signals, etc.
-
-   If you dial out from Unix system, but then notice a lot of weird
-   character strings being stuck into your session at random times
-   (especially if they look like +++ATQ0H0 or login banners or prompts),
-   that means that getty is also trying to control the same device.
-   You'll need to dial out on a device that is not waiting for a login,
-   or else disable getty on the device.
-
-   As of version 7.0, C-Kermit makes explicit checks for the Carrier
-   Detect signal, and so catches hung-up connections much better than 6.0
-   and earlier. However, it still can not be guaranteed to catch every
-   ever CD on-to-off transition. For example, when the HP-UX version of
-   C-Kermit is in CONNECT mode on a dialed connection and CARRIER-WATCH
-   ON or AUTO, and you turn off the modem, HP-UX is stuck in a read()
-   that never returns. (C-Kermit does not pop back to its prompt
-   automatically, but you can still escape back.)
-
-   If, on the other hand, you log out from the remote system, and it
-   hangs up, and CD drops on the local modem, C-Kermit detects this and
-   pops back to the prompt as it should. (Evidently there can be a
-   difference between CD and DSR turning off at the same time, versus CD
-   turning off while DSR stays on; experimentation with &S0/&S1/&S2 on
-   your modem might produce the desired results).
-
-   When Unix C-Kermit exits, it closes (and must close) the
-   communications device. If you were dialed out, this will most likely
-   hang up the connection. If you want to get out of Kermit and still use
-   Kermit's communication device, you have several choices:
-
-    1. Shell out from Kermit or suspend Kermit, and refer to the device
-       literally (as in "term -blah -blah < /dev/cua > /dev/cua").
-    2. Shell out from Kermit and use the device's file descriptor which
-       Kermit makes available to you in the \v(ttyfd) variable.
-    3. Use C-Kermit's REDIRECT command.
-    4. Use C-Kermit new EXEC /REDIRECT command.
-
-   If you are having trouble dialing:
-
-    1. Make sure the dialout line is configured correctly. More about
-       this below.
-    2. Make sure all necessary patches are installed for your operating
-       system.
-    3. If you can't dial on a "bidirectional" line, then configure it for
-       outbound-only (remove the getty) and try again. (The mechanisms --
-       if any -- for grabbing bidirectional lines for dialout vary wildly
-       among Unix implementations and releases, and C-Kermit -- which
-       runs on well over 300 different Unix variations -- makes no effort
-       to keep up with them; the recommended method for coping with this
-       situation is to wrap C-Kermit in a shell script that takes the
-       appropriate actions.)
-    4. Make sure C-Kermit's SET DIAL and SET MODEM parameters agree with
-       the modem you are actually using -- pay particular attention to
-       SET DIAL SPEED-MATCHING.
-    5. If MODEM HANGUP-METHOD is set to RS232-SIGNAL, change it to
-       MODEM-COMMAND. Or vice-versa.
-    6. Try SET DIAL HANGUP OFF before the DIAL command. Also, SET DIAL
-       DISPLAY ON to watch what's happening. See [554]Section 8 of the
-       [555]Installation Instructions.
-    7. Read pages 50-67 of [556]Using C-Kermit.
-    8. As a last resort, don't use the DIAL command at all; SET CARRIER
-       OFF and CONNECT to the modem and dial interactively, or write a
-       script program to dial the modem.
-
-   Make sure your dialout line is correctly configured for dialing out
-   (as opposed to login). The method for doing this is different for each
-   kind of Unix system. Consult your system documentation for configuring
-   lines for dialing out (for example, Sun SparcStation IPC users should
-   read the section "Setting up Modem Software" in the Desktop SPARC Sun
-   System & Network Manager's Guide; HP-9000 workstation users should
-   consult the manual Configuring HP-UX for Peripherals, etc).
-
-   Symptom: DIAL works, but a subsequent CONNECT command does not.
-   Diagnosis: the modem is not asserting Carrier Detect (CD) after the
-   connection is made, or the cable does not convey the CD signal. Cure:
-   Reconfigure the modem, replace the cable. Workaround: SET CARRIER OFF
-   (at least in System-V based Unix versions).
-
-   For Berkeley-Unix-based systems (4.3BSD and earlier), Kermit includes
-   code to use LPASS8 mode when parity is none, which is supposed to
-   allow 8-bit data and Xon/Xoff flow control at the same time. However,
-   as of edit 174, this code is entirely disabled because it is
-   unreliable: even though the host operating system might (or might not)
-   support LPASS8 mode correctly, the host access protocols (terminal
-   servers, telnet, rlogin, etc) generally have no way of finding out
-   about it and therefore render it ineffective, causing file transfer
-   failures. So as of edit 174, Kermit once again uses rawmode for 8-bit
-   data, and so there is no Xon/Xoff flow control during file transfer or
-   terminal emulation in the Berkeley-based versions (4.3 and earlier,
-   not 4.4).
-
-   Also on Berkeley-based systems (4.3 and earlier), there is apparently
-   no way to configure a dialout line for proper carrier handling, i.e.
-   ignore carrier during dialing, require carrier thereafter, get a fatal
-   error on any attempt to read from the device after carrier drops (this
-   is handled nicely in System V by manipulation of the CLOCAL flag). The
-   symptom is that carrier loss does not make C-Kermit pop back to the
-   prompt automatically. This is evident on the NeXT, for example, but
-   not on SunOS, which supports the CLOCAL flag. This is not a Kermit
-   problem, but a limitation of the underlying operating system. For
-   example, the cu program on the NeXT doesn't notice carrier loss
-   either, whereas cu on the Sun does.
-
-   On certain AT&T Unix systems equipped with AT&T modems, DIAL and
-   HANGUP don't work right. Workarounds: (1) SET DIAL HANGUP OFF before
-   attempting to dial; (2) If HANGUP doesn't work, SET LINE, and then SET
-   LINE <device> to totally close and reopen the device. If all else
-   fails, SET CARRIER OFF.
-
-   C-Kermit does not contain any particular support for AT&T DataKit
-   devices. You can use Kermit software to dial in to a DataKit line, but
-   C-Kermit does not contain the specialized code required to dial out
-   from a DataKit line. If the Unix system is connected to DataKit via
-   serial ports, dialout should work normally (e.g. set line /dev/ttym1,
-   set speed 19200, connect, and then see the DESTINATION: prompt, from
-   which you can connect to another computer on the DataKit network or to
-   an outgoing modem pool, etc). But if the Unix system is connected to
-   the DataKit network through the special DataKit interface board, then
-   SET LINE to a DataKit pseudodevice (such as /dev/dk031t) will not work
-   (you must use the DataKit "dk" or "dkcu" program instead). In C-Kermit
-   7.0 and later, you can make Kermit connections "though" dk or dkcu
-   using "set line /pty".
-
-   In some BSD-based Unix C-Kermit versions, SET LINE to a port that has
-   nothing plugged in to it with SET CARRIER ON will hang the program (as
-   it should), but it can't be interrupted with Ctrl-C. The interrupt
-   trap is correctly armed, but apparently the Unix open() call cannot be
-   interrupted in this case. When SET CARRIER is OFF or AUTO, the SET
-   LINE will eventually return, but then the program hangs
-   (uninterruptibly) when the EXIT or QUIT command (or, presumably,
-   another SET LINE command) is given. The latter is probably because of
-   the attempt to hang up the modem. (In edit 169, a timeout alarm was
-   placed around this operation.)
-
-   With SET DIAL HANGUP OFF in effect, the DIAL command might work only
-   once, but not again on the same device. In that case, give a CLOSE
-   command to close the device, and then another SET LINE command to
-   re-open the same device. Or rebuild your version of Kermit with the
-   -DCLSOPN compile-time switch.
-
-   The DIAL command says "To cancel: Type your interrupt character
-   (normally Ctrl-C)." This is just one example of where program messages
-   and documentation assume your interrupt character is Ctrl-C. But it
-   might be something else. In most (but not necessarily all) cases, the
-   character referred to is the one that generates the SIGINT signal. If
-   Ctrl-C doesn't act as an interrupt character for you, type the Unix
-   command "stty -a" or "stty all" or "stty everything" to see what your
-   interrupt character is. (Kermit could be made to find out what the
-   interrupt character is, but this would require a lot of
-   platform-dependent coding and #ifdefs, and a new routine and interface
-   between the platform-dependent and platform-independent parts of the
-   program.)
-
-   In general, the hangup operation on a serial communication device is
-   prone to failure. C-Kermit tries to support many, many different kinds
-   of computers, and there seems to be no portable method for hanging up
-   a modem connection (i.e. turning off the RS-232 DTR signal and then
-   turning it back on again). If HANGUP, DIAL, and/or Ctrl-\H do not work
-   for you, and you are a programmer, look at the tthang() function in
-   ckutio.c and see if you can add code to make it work correctly for
-   your system, and send the code to the address above. (NOTE: This
-   problem has been largely sidestepped as of edit 188, in which Kermit
-   first attempts to hang up the modem by "escaping back" via +++ and
-   then giving the modem's hangup command, e.g. ATH0, when DIAL
-   MODEM-HANGUP is ON, which is the default setting.)
-
-   Even when Kermit's modem-control software is configured correctly for
-   your computer, it can only work right if your modem is also configured
-   to assert the CD signal when it is connected to the remote modem and
-   to hang up the connection when your computer drops the DTR signal. So
-   before deciding Kermit doesn't work with your modem, check your modem
-   configuration AND the cable (if any) connecting your modem to the
-   computer -- it should be a straight-through modem cable conducting the
-   signals FG, SG, TD, RD, RTS, CTS, DSR, DTR, CD, and RI.
-
-   Many Unix systems keep aliases for dialout devices; for example,
-   /dev/acu might be an alias for /dev/tty00. But most of these Unix
-   systems also use UUCP lockfile conventions that do not take this
-   aliasing into account, so if one user assigns (e.g.) /dev/acu, then
-   another user can still assign the same device by referring to its
-   other name. This is not a Kermit problem -- Kermit must follow the
-   lockfile conventions used by the vendor-supplied software (cu, tip,
-   uucp).
-
-   The SET FLOW-CONTROL KEEP option should be given *before* any
-   communication (dialing, terminal emulation, file transfer,
-   INPUT/OUTPUT/TRANSMIT, etc) is attempted, if you want C-Kermit to use
-   all of the device's preexisting flow-control related settings. The
-   default flow-control setting is XON/XOFF, and it will take effect when
-   the first communication-related command is given, and a subsequent SET
-   FLOW KEEP command will not necessarily know how to restore *all* of
-   the device's original flow-control settings.
-
-  7.2. Network Connections
-
-   C-Kermit tries to use the 8th bit for data when parity is NONE, and
-   this generally works on real Unix terminal (tty) devices, but it often
-   does not work when the Unix system is accessed over a network via
-   telnet or rlogin protocols, including (in many cases) through terminal
-   servers. For example, an Encore computer with Annex terminal servers
-   only gives a 7-bit path if the rlogin protocol is selected in the
-   terminal server but it gives the full 8 bits if the proprietary RDP
-   protocol is used.
-
-   If file transfer does not work through a host to which you have
-   rlogin'd, use "rlogin -8" rather than "rlogin". If that doesn't work,
-   tell both Kermit programs to "set parity space".
-
-   The Encore TELNET server does not allow long bursts of input. When you
-   have a TELNET connection to an Encore, tell C-Kermit on the Encore to
-   SET RECEIVE PACKET-LENGTH 200 or thereabouts.
-    ________________________________________________________________________
-
-  8. HARDWARE FLOW CONTROL
-
-   [ [557]Top ] [ [558]Contents ] [ [559]Next ] [ [560]Previous ]
-
-   SET FLOW RTS/CTS is available in Unix C-Kermit only when the
-   underlying operating system provides an Application Program Interface
-   (API) for turning this feature on and off under program control, which
-   turns out to be a rather rare feature among Unix systems. To see if
-   your Unix C-Kermit version supports hardware flow control, type "set
-   flow ?" at the C-Kermit prompt, and look for "rts/cts" among the
-   options. Other common situations include:
-
-    1. The API is available, so "set flow rts/cts" appears as a valid
-       C-Kermit command, but it doesn't do anything because the device
-       driver (part of the operating system) was never coded to do
-       hardware flow control. This is common among System V R4
-       implementations (details below).
-    2. The API is not available, so "set flow rts/cts" does NOT appear as
-       a valid C-Kermit command, but you can still get RTS/CTS flow
-       control by selecting a specially named device in your SET LINE
-       command. Examples:
-          + NeXTSTEP: /dev/cufa instead of /dev/cua, /dev/cufb instead of
-            /dev/cub (68040 only; "man zs" for further info).
-          + IRIX: /dev/ttyf2 instead of /dev/ttyd2 or /dev/ttym2 ("man 7
-            serial").
-    3. The API is available, doesn't work, but a workaround as in (2) can
-       be used.
-    4. The API is available, but Kermit doesn't know about it. In these
-       cases, you can usually use an stty command to enable RTS/CTS on
-       the device, e.g. "stty crtscts" or "stty ctsflow", "stty rtsflow",
-       before starting Kermit, and then tell Kermit to SET FLOW KEEP.
-    5. No API and no special device drivers. Hardware flow control is
-       completely unavailable.
-
-   System V R4 based Unixes are supposed to supply a <termiox.h> file,
-   which gives Kermit the necessary interface to command the terminal
-   driver to enable/disable hardware flow control. Unfortunately, but
-   predictably, many implementations of SVR4 whimsically place this file
-   in /usr/include/sys rather than /usr/include (where SVID clearly
-   specifies it should be; see SVID, Third Edition, V1, termiox(BA_DEV).
-   Thus if you build C-Kermit with any of the makefile entries that
-   contain -DTERMIOX or -DSTERMIOX (the latter to select
-   <sys/termiox.h>), C-Kermit will have "set flow rts/cts" and possibly
-   other hardware flow-control related commands. BUT... That does not
-   necessarily mean that they will work. In some cases, the underlying
-   functions are simply not coded into the operating system.
-
-   WARNING: When hardware flow control is available, and you enable in
-   Kermit on a device that is not receiving the CTS signal, Kermit can
-   hang waiting for CTS to come up. This is most easily seen when the
-   local serial port has nothing plugged in to it, or is connected to an
-   external modem that is powered off.
-    ________________________________________________________________________
-
-  9. TERMINAL CONNECTION AND KEY MAPPING
-
-   [ [561]Top ] [ [562]Contents ] [ [563]Next ] [ [564]Previous ]
-
-   C-Kermit is not a terminal emulator. Refer to page 147 of [565]Using
-   C-Kermit, 2nd Edition: "Most versions of C-Kermit -- Unix, VMS,
-   AOS/VS, VOS, etc -- provide terminal connection without emulation.
-   These versions act as a 'semitransparent pipe' between the remote
-   computer and your terminal, terminal emulator, console driver, or
-   window, which in turn emulates (or is) a specific kind of terminal."
-   The environment in which you run C-Kermit is up to you.
-
-   If you are an X Windows user, you should be aware of an alternative to
-   xterm that supports VT220 emulation, from Thomas E. Dickey:
-
-  [566]http://dickey.his.com/xterm/xterm.html
-
-   Unix C-Kermit's SET KEY command currently can not be used with keys
-   that generate "wide" scan codes or multibyte sequences, such as
-   workstation function or arrow keys, because Unix C-Kermit does not
-   have direct access to the keyboard.
-
-   However, many Unix workstations and/or console drivers provide their
-   own key mapping feature. With xterm, for example, you can use
-   'xmodmap' ("man xmodmap" for details); here is an xterm mapping to map
-   the Sun keyboard to DEC VT200 values for use with VT-terminal oriented
-   applications like VMS EVE:
-
-  keycode 101=KP_0
-  keycode 119=KP_1
-  keycode 120=KP_2
-  keycode 121=KP_3
-  keycode 98=KP_4
-  keycode 99=KP_5
-  keycode 100=KP_6
-  keycode 75=KP_7
-  keycode 76=KP_8
-  keycode 77=KP_9
-  keycode 52=KP_F1
-  keycode 53=KP_F2
-  keycode 54=KP_F3
-  keycode 57=KP_Decimal
-  keycode 28=Left
-  keycode 29=Right
-  keycode 30=KP_Separator
-  keycode 105=KP_F4
-  keycode 78=KP_Subtract
-  keycode 8=Left
-  keycode 10=Right
-  keycode 32=Up
-  keycode 33=Down
-  keycode 97=KP_Enter
-
-   Users of Linux consoles can use loadkeys ("man dumpkeys loadkeys
-   keytables" for details. The format used by loadkeys is compatible with
-   that used by Xmodmap, although it is not definitely certain that the
-   keycodes are compatible for different keyboard types (e.g. Sun vs HP
-   vs PC, etc).
-    ________________________________________________________________________
-
-  10. FILE TRANSFER
-
-   [ [567]Top ] [ [568]Contents ] [ [569]Next ] [ [570]Previous ]
-
-   If uploads (or downloads) fail immediately, give the CAUTIOUS command
-   to Kermit and try again. If they still fail, then try SET PREFIXING
-   ALL. If they still fail, try SET PARITY SPACE. If they still fail, try
-   ROBUST.
-
-   If reception (particularly of large files and/or binary files) begins
-   successfully but then fail constently after a certain amount of bytes
-   have been sent, check:
-
-     * Your ulimit ("ulimit -a")
-     * The amount of available space on the target disk ("df ." or "df -k
-       .")
-     * Your personal disk quota (platform- and site-dependent)
-     * The maximum file size on the receiver's file system (e.g. 2GB in
-       old verions the Linux VFS file system, and/or in applications that
-       have not been recoded to use new "large file" APIs).
-     * If it's an NFS-mounted disk (if so, try uploading to a local disk)
-     * Is there an "idle limit" on the receiving end?
-
-   If none of these seem to explain it, then the problem is not size
-   related, but reflects some clash between the file contents and the
-   characteristics of the connection, in which case follow the
-   instructions in the first paragraph of this section.
-
-   Suppose two copies of Kermit are receiving files into the same
-   directory, and the files have the same name, e.g. "foo.bar". Whichever
-   one starts first opens an output file called "foo.bar". The second one
-   sees there is already a foo.bar file, and so renames the existing
-   foo.bar to foo.bar.~1~ (or whatever). When the first file has been
-   received completely, Kermit goes to change its modification time and
-   permissions to those given by the file sender in the Attribute packet.
-   But in Unix, the APIs for doing this take a filename, not a file
-   descriptor. Since the first Kermit's file has been renamed, and the
-   second Kermit is using the original name, the first Kermit changes the
-   modtime and permissions of the second Kermit's file, not its own.
-   Although there might be a way to work around this in the code, e.g.
-   using inode numbers to keep track of which file is which, this would
-   be tricky and most likely not very portable. It's better to set up
-   your application to prevent such things from happening, which is easy
-   enough using the script language, filename templates, etc.
-
-   Suppose you start C-Kermit with a command-line argument to send or
-   receive a file (e.g. "kermit -r") and then type Ctrl-\c immediately
-   afterwards to escape back and initiate the other end of the transfer,
-   BUT your local Kermit's escape character is not Ctrl-\. In this case,
-   the local Kermit passes the Ctrl-\ to the remote system, and if this
-   is Unix, Ctrl-\ is likely to be its SIGQUIT character, which causes
-   the current program to halt and dump core. Well, just about the first
-   thing C-Kermit does when it starts is to disable the SIGQUIT signal.
-   However, it is still possible for SIGQUIT to cause Kermit to quit and
-   dump core if it is delivered while Kermit is being loaded or started,
-   before the signal can be disabled. There's nothing Kermit itself can
-   do about this, but you can prevent it from happening by disabling
-   SIGQUIT in your Unix session. The command is usually something like:
-
-  stty quit undef
-
-   Unix C-Kermit does not reject incoming files on the basis of size.
-   There appears to be no good (reliable, portable) way to determine in
-   advance how much disk space is available, either on the device, or
-   (when quotas or other limits are involved) to the user.
-
-   Unix C-Kermit discards all carriage returns from incoming files when
-   in text mode.
-
-   If C-Kermit has problems creating files in writable directories when
-   it is installed setuid or setgid on BSD-based versions of Unix such as
-   NeXTSTEP 3.0, it probably needs to be rebuilt with the -DSW_ACC_ID
-   compilation switch.
-
-   If you SET FILE DISPLAY FULLSCREEN, and C-Kermit complains "Sorry,
-   terminal type not supported", it means that the terminal library
-   (termcap or termlib) that C-Kermit was built with does not know about
-   a terminal whose name is the current value of your TERM environment
-   variable. If this happens, but you want to have the fullscreen file
-   transfer display, EXIT from C-Kermit and set a Unix terminal type from
-   among the supported values that is also supported by your terminal
-   emulator, or else have an entry for your terminal type added to the
-   system termcap and/or terminfo database.
-
-   If you attempt to suspend C-Kermit during local-mode file transfer and
-   then continue it in the background (via bg), it will block for "tty
-   output" if you are using the FULLSCREEN file transfer display. This is
-   apparently a problem with curses. Moving a local-mode file transfer
-   back and forth between foreground and background works correctly,
-   however, with the SERIAL, CRT, BRIEF, or NONE file transfer displays.
-
-   If C-Kermit's command parser no longer echoes, or otherwise acts
-   strangely, after returning from a file transfer with the fullscreen
-   (curses) display, and the curses library for your version of Unix
-   includes the newterm() function, then try rebuilding your version of
-   C-Kermit with -DCK_NEWTERM. Similarly if it echoes doubly, which might
-   even happen during a subsequent CONNECT session. If rebuilding with
-   -DCK_NEWTERM doesn't fix it, then there is something very strange
-   about your system's curses library, and you should probably not use
-   it. Tell C-Kermit to SET FILE DISPLAY CRT, BRIEF, or anything else
-   other than FULLSCREEN, and/or rebuild without -DCK_CURSES, and without
-   linking with (termlib and) curses. Note: This problem seemed to have
-   escalated in C-Kermit 7.0, and -DCK_NEWTERM had to be added to many
-   builds that previously worked without it: Linux, AIX 4.1, DG/UX, etc.
-   In the Linux case, it is obviously because of changes in the (n)curses
-   library; the cause in the other cases is not known.
-
-   C-Kermit creates backup-file names (such as "oofa.txt.~1~") based on
-   its knowledge of the maximum filename length on the platform where it
-   is running, which is learned at compile time, based on MAXNAMLEN or
-   equivalent symbols from the system header files. But suppose C-Kermit
-   is receiving files on a Unix platform that supports long filenames,
-   but the incoming files are being stored on an NFS-mounted file system
-   that supports only short names. NFS maps the external system to the
-   local APIs, so C-Kermit has no way of knowing that long names will be
-   truncated. Or that C-Kermit is running on a version of Unix that
-   supports both long-name and short-name file systems simultaneously
-   (such as HP-UX 7.00). This can cause unexpected behavior when creating
-   backup files, or worse. For example, you are sending a group of files
-   whose names are differentiated only by characters past the point at
-   which they would be truncated, each file will overwrite the previous
-   one upon arrival.
-    ________________________________________________________________________
-
-  11. EXTERNAL FILE TRANSFER PROTOCOLS
-
-   [ [571]Top ] [ [572]Contents ] [ [573]Next ] [ [574]Previous ]
-
-   SECTION CONTENTS
-
-  11.1. [575]C-Kermit as an External Protocol
-  11.2. [576]Invoking External Protocols from C-Kermit
-
-   Unix C-Kermit can be used in conjunction with other communications
-   software in various ways. C-Kermit can be invoked from another
-   communications program as an "external protocol", and C-Kermit can
-   also invoke other communication software to perform external
-   protocols.
-
-   This sort of operation makes sense only when you are dialing out from
-   your Unix system (or making a network connection from it). If the Unix
-   system is the one you have dialed in to, you don't need any of these
-   tricks. Just run the desired software on your Unix system instead of
-   Kermit. When dialing out from a Unix system, the difficulty is getting
-   two programs to share the same communication device in spite of the
-   Unix UUCP lockfile mechanism, which would normally prevent any
-   sharing, and preventing the external protocol from closing (and
-   therefore hanging up) the device when it exits back to the program
-   that invoked it.
-
-  11.1. C-KERMIT AS AN EXTERNAL PROTOCOL
-
-   [ [577]Top ] [ [578]Contents ] [ [579]Section Contents ] [ [580]Next ]
-
-   (This section deleted; see [581]Using C-Kermit, 2nd Ed, Chapter 14.)
-
-   "pcomm" is a general-purpose terminal program that provides file
-   transfer capabilities itself (X- and YMODEM variations) and the
-   ability to call on external programs to do file transfers (ZMODEM and
-   Kermit, for example). You can tell pcomm the command to send or
-   receive a file with an external protocol:
-                        Send                            Receive  
-        ZMODEM          sz filename                     rz
-        Kermit          kermit -s filename              kermit -r
-
-   pcomm runs external programs for file transfer by making stdin and
-   stdout point to the modem port, and then exec-ing "/bin/sh -c xxx"
-   (where xxx is the appropriate command). However, C-Kermit does not
-   treat stdin and stdout as the communication device unless you instruct
-   it:
-
-
-                        Send                            Receive  
-        Kermit          kermit -l 0 -s filename         kermit -l 0 -r
-
-   The "-l 0" option means to use file descriptor 0 for the communication
-   device.
-
-   In general, any program can pass any open file descriptor to C-Kermit
-   for the communication device in the "-l" command-line option. When
-   Kermit is given a number as the argument to the "-l" option, it simply
-   uses it as a file descriptor, and it does not attempt to close it upon
-   exit.
-
-   Here's another example, for Seyon (a Linux communication program).
-   First try the technique above. If that works, fine; otherwise... If
-   Seyon does not give you a way to access and pass along the file
-   descriptor, but it starts up the Kermit program with its standard i/o
-   redirected to its (Seyon's) communications file descriptor, you can
-   also experiment with the following method, which worked here in brief
-   tests on SunOS. Instead of having Seyon use "kermit -r" or "kermit -s
-   filename" as its Kermit protocol commands, use something like this
-   (examples assume C-Kermit 6.0):
-
-   For serial connections:
-
-  kermit -YqQl 0 -r                     <-- to receive
-  kermit -YqQl 0 -s filename(s)         <-- to send one or more files
-
-   For Telnet connections:
-
-  kermit -YqQF 0 -r                     <-- to receive
-  kermit -YqQF 0 -s filename(s)         <-- to send one or more files
-
-   Command line options:
-
-  Y    - skip executing the init file
-  Q    - use fast file transfer settings (default in 8.0)
-  l 0  - transfer files using file descriptor 0 for a serial connection
-  F 0  - transfer files using file descriptor 0 for a Telnet connection
-  q    - quiet - no messages
-  r    - receive
-  s    - send
-
-  11.2. INVOKING EXTERNAL PROTOCOLS FROM C-KERMIT
-
-   [ [582]Top ] [ [583]Contents ] [ [584]Section Contents ] [
-   [585]Previous ]
-
-     (This section is obsolete, but not totally useless. See Chapter 14
-     of [586]Using C-Kermit, 2nd Edition). 
-
-   After you have opened a communication link with C-Kermit's SET LINE
-   (SET PORT) or SET HOST (TELNET) command, C-Kermit makes its file
-   descriptor available to you in the \v(ttyfd) variable so you can pass
-   it along to other programs that you RUN from C-Kermit. Here, for
-   example, C-Kermit runs itself as an external protocol:
-
-  C-Kermit>set modem type hayes
-  C-Kermit>set line /dev/acu
-  C-Kermit>set speed 2400
-  C-Kermit>dial 7654321
-   Call complete.
-  C-Kermit>echo \v(ttyfd)
-   3
-  C-Kermit>run kermit -l \v(ttyfd)
-
-   Other programs that accept open file descriptors on the command line
-   can be started in the same way.
-
-   You can also use your shell's i/o redirection facilities to assign
-   C-Kermit's open file descriptor (ttyfd) to stdin or stdout. For
-   example, old versions of the Unix ZMODEM programs, sz and rz, when
-   invoked as external protocols, expect to find the communication device
-   assigned to stdin and stdout with no option for specifying any other
-   file descriptor on the sz or rz command line. However, you can still
-   invoke sz and rz as exterior protocols from C-Kermit if your current
-   shell ($SHELL variable) is ksh (the Korn shell) or bash (the
-   Bourne-Again shell), which allows assignment of arbitrary file
-   descriptors to stdin and stdout:
-
-  C-Kermit> run rz <&\v(ttyfd) >&\v(ttyfd)
-
-   or:
-
-  C-Kermit> run sz oofa.zip <&\v(ttyfd) >&\v(ttyfd)
-
-   In version 5A(190) and later, you can use C-Kermit's REDIRECT command,
-   if it is available in your version of C-Kermit, to accomplish the same
-   thing without going through the shell:
-
-  C-Kermit> redirect rz
-
-   or:
-
-  C-Kermit> redirect sz oofa.zip
-
-   A complete set of rz,sz,rb,sb,rx,sx macros for Unix C-Kermit is
-   defined in the file ckurzsz.ini. It automatically chooses the best
-   redirection method (but is redundant since C-Kermit 6.0, which now has
-   built-in support for external protocols via its SET PROTOCOL command).
-
-   Note that external protocols can be used on C-Kermit SET LINE or SET
-   HOST connections only if they operate through standard input and
-   standard output. If they open their own connections, Kermit can't
-   redirect them over its own connection.
-    ________________________________________________________________________
-
-  12. SECURITY
-
-   [ [587]Top ] [ [588]Contents ] [ [589]Next ] [ [590]Previous ]
-
-   As of version 7.0, C-Kermit supports a wide range of security options
-   for authentication and encryption: Kerberos 4, Kerberos 5 / GSSAPI,
-   SSL/TLS, and SRP. See the separate [591]security document for details.
-    ________________________________________________________________________
-
-  13. MISCELLANEOUS USER REPORTS
-
-   [ [592]Top ] [ [593]Contents ] [ [594]Next ] [ [595]Previous ]
-
-Date: Thu, 12 Mar 92 1:59:25 MEZ
-From: Walter Mecky <walter@rent-a-guru.de>
-Subject: Help.Unix.sw
-To: svr4@pcsbst.pcs.com, source@usl.com
-
-PRODUCT:        Unix
-RELEASE:        Dell SVR4 V2.1 (is USL V3.0)
-MACHINE:        AT-386
-PATHNAME:       /usr/lib/libc.so.1
-                /usr/ccs/lib/libc.a
-ABSTRACT:       Function ttyname() does not close its file descriptor
-DESCRIPTION:
-        ttyname(3C) opens /dev but never closes it. So if it is called
-        often enough the open(2) in ttyname() fails. Because the broken
-        ttyname() is in the shared lib too all programs using it can
-        fail if they call it often enough. One important program is
-        uucico which calls ttyname for every file it transfers.
-
-   Here is a little test program if your system has the bug:
-
-#include <stdlib.h>
-#include <stdio.h>
-main() {
-    int i = 0;
-    while (ttyname(0) != NULL)
-      i++;
-    perror("ttyname");
-    printf("i=%d\n", i);
-}
-
-   If this program runs longer than some seconds you don't have the bug.
-
-   WORKAROUND: None FIX: Very easy if you have source code.
-
-   Another user reports some more explicit symptoms and recoveries:
-
-> What happens is when invoking ckermit we get one of the following
-> error messages:
->   You must set line
->   Not a tty
->   No more processes.
-> One of the following three actions clears the peoblem:
->   shutdown -y -g0 -i6
->   kill -9 the ttymon with the highest PID
->   Invoke sysadm and disable then enable the line you want to use.
-> Turning off respawn of sac -t 300 and going to getty's and uugetty's
-> does not help.
->
-> Also C-Kermit reports "?timed out closing /dev/ttyxx".
-> If this happens all is well.
-
-------------------------------
-
-   (Note: the following problem also occurs on SGI and probably many
-   other Unix systems):
-
-   From: James Spath <spath@jhunix.hcf.jhu.edu>
-   To: Info-Kermit-Request@cunixf.cc.columbia.edu
-   Date: Wed, 9 Sep 1992 20:20:28 -0400
-   Subject: C-Kermit vs uugetty (or init) on Sperry 5000
-
-   We have successfully compiled the above release on a Unisys/Sperry
-   5000/95. We used the sys5r3 option, rather than sys5r2 since we have
-   VR3 running on our system. In order to allow dialout access to
-   non-superusers, we had to do "chmod 666 /dev/tty###, where it had been
-   -rw--w--w- (owned by uucp), and to do "chmod +w /usr/spool/locks". We
-   have done text and binary file transfers through local and remote
-   connections.
-
-   The problem concerning uucp ownership and permissions is worse than I
-   thought at first. Apparently init or uugetty changes the file
-   permissions after each session. So I wrote the following C program to
-   open a set of requested tty lines. I run this for any required
-   outgoing line prior to a Kermit session.
-
-   ------ cut here -------
-/* opentty.c -- force allow read on tty lines for modem i/o */
-/* idea from: restrict.c -- System 5 Admin book Thomas/Farrow p. 605 */
-/* /jes jim spath {spath@jhunix.hcj.jhu.edu } */
-/* 08-Sep-92 NO COPYRIGHT. */
-/* this must be suid to open other tty lines */
-
-/* #define DEBUG */
-#define TTY "/dev/tty"
-#define LOK "/usr/spool/locks/LCK..tty"
-#include <stdio.h>
-
-/* allowable lines: */
-#define TOTAL_LINES 3
-static char allowable[TOTAL_LINES][4] = { "200", "201", "300" };
-static int total=TOTAL_LINES;
-int allow;
-
-/* states: */
-#define TTY_UNDEF 0
-#define TTY_LOCK  1
-#define TTY_OKAY  2
-
-main(argc, argv)
-int argc; char *argv[]; {
-    char device[512];
-    char lockdev[512];
-    int i;
-    if (argc == 1) {
-        fprintf(stderr, "usage: open 200 [...]\n");
-    }
-    while (--argc > 0 && (*++argv) != NULL ) {
-#ifdef DEBUG
-        fprintf(stderr, "TRYING: %s%s\n", TTY, *argv);
-#endif
-        sprintf(device, "%s%s", TTY, *argv);
-        sprintf(lockdev, "%s%s", LOK, *argv);
-        allow = TTY_UNDEF; i = 0;
-        while (i <= total) { /* look at all defined lines */
-#ifdef DEBUG
-            fprintf(stderr, "LOCKFILE? %s?\n", lockdev);
-#endif
-            if (access(lockdev, 00) == 0) {
-                allow=TTY_LOCK;
-                break;
-            }
-#ifdef DEBUG
-            fprintf(stderr, "DOES:%s==%s?\n", allowable[i], *argv);
-#endif
-            if (strcmp(allowable[i], *argv) == 0)
-              allow=TTY_OKAY;
-            i++;
-        }
-#ifdef DEBUG
-        fprintf(stderr, "allow=%d\n", allow);
-#endif
-        switch (allow) {
-          case TTY_UNDEF:
-            fprintf (stderr, "open: not allowed on %s\n", *argv);
-            break;
-          case TTY_LOCK:
-            fprintf (stderr, "open: device locked: %s\n", lockdev);
-            break;
-          case TTY_OKAY:
-            /* attempt to change mode on device */
-            if (chmod (device, 00666) < 0)
-              fprintf (stderr, "open: cannot chmod on %s\n", device);
-            break;
-          default:
-            fprintf (stderr, "open: FAULT\n");
-        }
-    }
-    exit (0);
-}
-    ________________________________________________________________________
-
-  14. THIRD-PARTY DRIVERS
-
-   [ [596]Top ] [ [597]Contents ] [ [598]Next ] [ [599]Previous ]
-
-   Unix versions, especially those for PCs (SCO, Unixware, etc) might be
-   augmented by third-party communication-board drivers from Digiboard,
-   Stallion, etc. These can sometimes complicate matters for Kermit
-   considerably since Kermit has no way of knowing that it is going
-   through a possibly nonstandard driver. Various examples are listed in
-   the earlier sections of this document; search for Stallion, Digiboard,
-   etc. Additionally:
-
-     * The Stallion Technologies EasyConnection serial board driver does
-       not always report the state of DSR as low. From Stallion (October
-       1997): "Unfortunately, this is a bug in our driver. We have
-       implemented all of the other TIOMC functions, eg DTR, DCD, RTS and
-       CTS, but not DSR. Our driver should report the actual state of DSR
-       on those of our cards that have a DSR signal. That the driver
-       always reports DSR as not asserted (0), is a bug in the driver.
-       The driver should be either reporting the state of DSR correctly
-       on those cards that support DSR or as always asserted (1) on those
-       cards that do not have a DSR signal. This will be fixed in a
-       future version of our drivers; at this time I cannot say when this
-       will be." And later, "As far as I can tell, we don't support the
-       termios/termiox ioctls that relate specifically to DSR and RI; all
-       the rest are supported. This will, as I mentioned earlier, be
-       fixed in the next release of our ATA software."
-       - World Wide Escalation Support, Stallion Technologies, Toowong
-       QLD, [600]support@stallion.oz.au.
-
-   Later (December 1997, from the same source):
-
-     * We have now released a new version of the ATA software, version
-       5.4.0. This version fixes the problem with the states of the DSR
-       and RI signals and how they were being reported by the driver.
-       This is the problem that you reported in October. The DSR signal
-       is reported correctly on those cards that support the DSR signal,
-       such as the early revision of the EasyIO card and the
-       EasyConnection 8D4 panel, and as always asserted on those cards
-       that do not support the DSR signal in the hardware. The new driver
-       is available from our Web site, [601]www.stallion.com, in the
-       /drivers/ata5/UnixWare directory.
-
-   [ [602]Top ] [ [603]Contents ] [ [604]C-Kermit Home ] [ [605]C-Kermit
-   8.0 Overview ] [ [606]Kermit Home ]
-     _________________________________________________________________
-
-   C-Kermit 8.0 Unix Hints and Tips / [607]The Kermit Project /
-   [608]Columbia University / [609]kermit@columbia.edu
-
-References
-
-   1. http://www.columbia.edu/kermit/
-   2. http://www.columbia.edu/
-   3. http://www.columbia.edu/kermit/ckubwr.html
-   4. mailto:kermit-support@columbia.edu
-   5. http://www.columbia.edu/kermit/ckermit.html
-   6. http://www.columbia.edu/kermit/ckuins.html
-   7. http://www.columbia.edu/kermit/ckututor.html
-   8. http://www.columbia.edu/kermit/ckubwr.html#x1
-   9. http://www.columbia.edu/kermit/ckubwr.html#x2
-  10. http://www.columbia.edu/kermit/ckubwr.html#x3
-  11. http://www.columbia.edu/kermit/ckubwr.html#x4
-  12. http://www.columbia.edu/kermit/ckubwr.html#x5
-  13. http://www.columbia.edu/kermit/ckubwr.html#x6
-  14. http://www.columbia.edu/kermit/ckubwr.html#x7
-  15. http://www.columbia.edu/kermit/ckubwr.html#x8
-  16. http://www.columbia.edu/kermit/ckubwr.html#x9
-  17. http://www.columbia.edu/kermit/ckubwr.html#x10
-  18. http://www.columbia.edu/kermit/ckubwr.html#x11
-  19. http://www.columbia.edu/kermit/ckubwr.html#x12
-  20. http://www.columbia.edu/kermit/ckubwr.html#x13
-  21. http://www.columbia.edu/kermit/ckubwr.html#x14
-  22. http://www.columbia.edu/kermit/ckubwr.html#x3.3
-  23. http://www.columbia.edu/kermit/ckubwr.html#x3.18
-  24. http://www.columbia.edu/kermit/ckubwr.html#x3.19
-  25. http://www.columbia.edu/kermit/ckubwr.html#x3.1
-  26. http://www.columbia.edu/kermit/ckubwr.html#x3.2
-  27. http://www.columbia.edu/kermit/ckubwr.html#x3.7
-  28. http://www.columbia.edu/kermit/ckubwr.html#x3.6
-  29. http://www.columbia.edu/kermit/ckubwr.html#x3.13
-  30. http://www.columbia.edu/kermit/ckubwr.html#top
-  31. http://www.columbia.edu/kermit/ckubwr.html#contents
-  32. http://www.columbia.edu/kermit/ckubwr.html#x2
-  33. http://www.columbia.edu/kermit/ckubwr.html#x1.1
-  34. http://www.columbia.edu/kermit/ckubwr.html#x1.2
-  35. http://www.columbia.edu/kermit/ckubwr.html#x1.3
-  36. http://www.columbia.edu/kermit/ckubwr.html#x1.4
-  37. http://www.columbia.edu/kermit/ckubwr.html#x3.3
-  38. http://www.columbia.edu/kermit/ckubwr.html#x3.1
-  39. http://www.columbia.edu/kermit/ckubwr.html#x3.2
-  40. http://www.columbia.edu/kermit/ckubwr.html#x3.7
-  41. http://www.columbia.edu/kermit/ckcbwr.html
-  42. mailto:kermit-support@columbia.edu
-  43. http://www.columbia.edu/kermit/ckubwr.html#top
-  44. http://www.columbia.edu/kermit/ckubwr.html#contents
-  45. http://www.columbia.edu/kermit/ckubwr.html#x1.2
-  46. http://www.columbia.edu/kermit/ck60manual.html
-  47. http://www.columbia.edu/kermit/ckermit70.html
-  48. http://www.columbia.edu/kermit/ckermit80.html
-  49. http://www.columbia.edu/kermit/ckubwr.html#top
-  50. http://www.columbia.edu/kermit/ckubwr.html#contents
-  51. http://www.columbia.edu/kermit/ckubwr.html#x1
-  52. http://www.columbia.edu/kermit/ckubwr.html#x1.3
-  53. http://www.columbia.edu/kermit/ckubwr.html#x1.1
-  54. http://www.columbia.edu/kermit/support.html
-  55. http://www.columbia.edu/kermit/ckubwr.html#top
-  56. http://www.columbia.edu/kermit/ckubwr.html#contents
-  57. http://www.columbia.edu/kermit/ckubwr.html#x1
-  58. http://www.columbia.edu/kermit/ckubwr.html#x1.4
-  59. http://www.columbia.edu/kermit/ckubwr.html#x1.2
-  60. http://www.columbia.edu/kermit/ckubwr.html#top
-  61. http://www.columbia.edu/kermit/ckubwr.html#contents
-  62. http://www.columbia.edu/kermit/ckubwr.html#x1
-  63. http://www.columbia.edu/kermit/ckubwr.html#x1.3
-  64. http://www.columbia.edu/kermit/ckubwr.html#top
-  65. http://www.columbia.edu/kermit/ckubwr.html#contents
-  66. http://www.columbia.edu/kermit/ckubwr.html#x3
-  67. http://www.columbia.edu/kermit/ckubwr.html#x1
-  68. http://www.columbia.edu/kermit/ckubwr.html#top
-  69. http://www.columbia.edu/kermit/ckubwr.html#contents
-  70. http://www.columbia.edu/kermit/ckubwr.html#x4
-  71. http://www.columbia.edu/kermit/ckubwr.html#x2
-  72. http://www.columbia.edu/kermit/ckubwr.html#x3.0
-  73. http://www.columbia.edu/kermit/ckubwr.html#x3.1
-  74. http://www.columbia.edu/kermit/ckubwr.html#x3.2
-  75. http://www.columbia.edu/kermit/ckubwr.html#x3.3
-  76. http://www.columbia.edu/kermit/ckubwr.html#x3.4
-  77. http://www.columbia.edu/kermit/ckubwr.html#x3.5
-  78. http://www.columbia.edu/kermit/ckubwr.html#x3.6
-  79. http://www.columbia.edu/kermit/ckubwr.html#x3.7
-  80. http://www.columbia.edu/kermit/ckubwr.html#x3.8
-  81. http://www.columbia.edu/kermit/ckubwr.html#x3.9
-  82. http://www.columbia.edu/kermit/ckubwr.html#x3.10
-  83. http://www.columbia.edu/kermit/ckubwr.html#x3.11
-  84. http://www.columbia.edu/kermit/ckubwr.html#x3.12
-  85. http://www.columbia.edu/kermit/ckubwr.html#x3.13
-  86. http://www.columbia.edu/kermit/ckubwr.html#x3.14
-  87. http://www.columbia.edu/kermit/ckubwr.html#x3.15
-  88. http://www.columbia.edu/kermit/ckubwr.html#x3.16
-  89. http://www.columbia.edu/kermit/ckubwr.html#x3.17
-  90. http://www.columbia.edu/kermit/ckubwr.html#x3.18
-  91. http://www.columbia.edu/kermit/ckubwr.html#x3.19
-  92. http://www.columbia.edu/kermit/ckubwr.html#x3.20
-  93. http://www.faqs.org/
-  94. http://aplawrence.com/Unixart/newtounix.html
-  95. http://www.columbia.edu/kermit/x3
-  96. mailto:kermit-support@columbia.edu
-  97. http://www.columbia.edu/kermit/support.html
-  98. http://www.columbia.edu/kermit/ckubwr.html#top
-  99. http://www.columbia.edu/kermit/ckubwr.html#contents
- 100. http://www.columbia.edu/kermit/ckubwr.html#x3
- 101. http://www.columbia.edu/kermit/ckubwr.html#x3.1
- 102. http://www.pcunix.com/
- 103. http://www.columbia.edu/kermit/ckubwr.html#x3.0.1
- 104. http://www.columbia.edu/kermit/ckubwr.html#x3.0.2
- 105. http://www.columbia.edu/kermit/ckubwr.html#x3.0.3
- 106. http://www.columbia.edu/kermit/ckubwr.html#x3.0.4
- 107. http://www.columbia.edu/kermit/ckubwr.html#x3.0.5
- 108. http://www.columbia.edu/kermit/ckubwr.html#x3.0.6
- 109. http://www.columbia.edu/kermit/ckubwr.html#top
- 110. http://www.columbia.edu/kermit/ckubwr.html#contents
- 111. http://www.columbia.edu/kermit/ckubwr.html#x3.0
- 112. http://www.columbia.edu/kermit/ckubwr.html#x3.0.2
- 113. http://www.columbia.edu/kermit/ckubwr.html#top
- 114. http://www.columbia.edu/kermit/ckubwr.html#contents
- 115. http://www.columbia.edu/kermit/ckubwr.html#x3.0
- 116. http://www.columbia.edu/kermit/ckubwr.html#x3.0.3
- 117. http://www.columbia.edu/kermit/ckubwr.html#x3.0.1
- 118. http://www.linmodems.org/
- 119. http://www.microsoft.com/hwdev/platform/PCdesign/LR/default.asp
- 120. http://www.columbia.edu/kermit/ckubwr.html#top
- 121. http://www.columbia.edu/kermit/ckubwr.html#contents
- 122. http://www.columbia.edu/kermit/ckubwr.html#x3.0
- 123. http://www.columbia.edu/kermit/ckubwr.html#x3.0.4
- 124. http://www.columbia.edu/kermit/ckubwr.html#x3.0.2
- 125. http://www.idir.net/~gromitkc/winmodem.html
- 126. http://www.digi.com/
- 127. http://www.columbia.edu/kermit/ckubwr.html#top
- 128. http://www.columbia.edu/kermit/ckubwr.html#contents
- 129. http://www.columbia.edu/kermit/ckubwr.html#x3.0
- 130. http://www.columbia.edu/kermit/ckubwr.html#x3.0.5
- 131. http://www.columbia.edu/kermit/ckubwr.html#x3.0.3
- 132. http://www.columbia.edu/kermit/ckubwr.html#top
- 133. http://www.columbia.edu/kermit/ckubwr.html#contents
- 134. http://www.columbia.edu/kermit/ckubwr.html#x3.0
- 135. http://www.columbia.edu/kermit/ckubwr.html#x3.0.6
- 136. http://www.columbia.edu/kermit/ckubwr.html#x3.0.4
- 137. http://www.columbia.edu/kermit/ckubwr.html#top
- 138. http://www.columbia.edu/kermit/ckubwr.html#contents
- 139. http://www.columbia.edu/kermit/ckubwr.html#x3.0
- 140. http://www.columbia.edu/kermit/ckubwr.html#x3.0.5
- 141. http://www.columbia.edu/kermit/ckubwr.html#top
- 142. http://www.columbia.edu/kermit/ckubwr.html#contents
- 143. http://www.columbia.edu/kermit/ckubwr.html#x3
- 144. http://www.columbia.edu/kermit/ckubwr.html#x3.2
- 145. http://www.columbia.edu/kermit/ckubwr.html#x3.0
- 146. http://www.columbia.edu/kermit/ckubwr.html#x3.1.1
- 147. http://www.columbia.edu/kermit/ckubwr.html#x3.1.2
- 148. http://www.columbia.edu/kermit/ckubwr.html#x3.1.3
- 149. http://www.columbia.edu/kermit/ckubwr.html#x3.1.4
- 150. http://www.columbia.edu/kermit/ckubwr.html#x3.1.5
- 151. http://www.emerson.emory.edu/services/aix-faq/
- 152. http://www.faqs.org/faqs/by-newsgroup/comp/comp.unix.aix.html
- 153. http://www.cis.ohio-state.edu/hypertext/faq/usenet/aix-faq/top.html
- 154. http://aixpdslib.seas.ucla.edu/
- 155. http://www.rootvg.net (AIX history)/
- 156. ftp://rtfm.mit.edu/pub/usenet/news.answers/aix-faq/part1
- 157. ftp://mirrors.aol.com/pub/rtfm/usenet-by-hierarchy/comp/unix/aix
- 158. news:comp.unix.aix
- 159. http://www.columbia.edu/kermit/ckubwr.html#top
- 160. http://www.columbia.edu/kermit/ckubwr.html#contents
- 161. http://www.columbia.edu/kermit/ckubwr.html#x3.1
- 162. http://www.columbia.edu/kermit/ckubwr.html#x3.1.2
- 163. http://www.columbia.edu/kermit/ckubwr.html#top
- 164. http://www.columbia.edu/kermit/ckubwr.html#contents
- 165. http://www.columbia.edu/kermit/ckubwr.html#x3.1
- 166. http://www.columbia.edu/kermit/ckubwr.html#x3.1.3
- 167. http://www.columbia.edu/kermit/ckubwr.html#x3.1.1
- 168. http://www.columbia.edu/kermit/security.html#servers
- 169. http://www.columbia.edu/kermit/ckubwr.html#top
- 170. http://www.columbia.edu/kermit/ckubwr.html#contents
- 171. http://www.columbia.edu/kermit/ckubwr.html#x3.1
- 172. http://www.columbia.edu/kermit/ckubwr.html#x3.1.4
- 173. http://www.columbia.edu/kermit/ckubwr.html#x3.1.2
- 174. http://service.software.ibm.com/rs6000/
- 175. http://www.columbia.edu/kermit/ckubwr.html#top
- 176. http://www.columbia.edu/kermit/ckubwr.html#contents
- 177. http://www.columbia.edu/kermit/ckubwr.html#x3.1
- 178. http://www.columbia.edu/kermit/ckubwr.html#x3.1.5
- 179. http://www.columbia.edu/kermit/ckubwr.html#x3.1.3
- 180. http://www.columbia.edu/kermit/ckubwr.html#top
- 181. http://www.columbia.edu/kermit/ckubwr.html#contents
- 182. http://www.columbia.edu/kermit/ckubwr.html#x3.1
- 183. http://www.columbia.edu/kermit/ckubwr.html#x3.1.4
- 184. http://www.columbia.edu/kermit/ckubwr.html#top
- 185. http://www.columbia.edu/kermit/ckubwr.html#contents
- 186. http://www.columbia.edu/kermit/ckubwr.html#x3
- 187. http://www.columbia.edu/kermit/ckubwr.html#x3.3
- 188. http://www.columbia.edu/kermit/ckubwr.html#x3.1
- 189. http://www.columbia.edu/kermit/ckubwr.html#x3.2.0
- 190. http://www.columbia.edu/kermit/ckubwr.html#x3.2.1
- 191. http://www.columbia.edu/kermit/ckubwr.html#x3.2.2
- 192. http://www.columbia.edu/kermit/ckubwr.html#x3.2.3
- 193. http://www.columbia.edu/kermit/ckubwr.html#x3.2.4
- 194. http://www.columbia.edu/kermit/ckubwr.html#x3.2.5
- 195. news:comp.sys.hp.hpux
- 196. http://www.columbia.edu/kermit/ckubwr.html#top
- 197. http://www.columbia.edu/kermit/ckubwr.html#contents
- 198. http://www.columbia.edu/kermit/ckubwr.html#x3.2
- 199. http://www.columbia.edu/kermit/ckubwr.html#x3.2.1
- 200. http://www.columbia.edu/kermit/ckubwr.html#top
- 201. http://www.columbia.edu/kermit/ckubwr.html#contents
- 202. http://www.columbia.edu/kermit/ckubwr.html#x3.2
- 203. http://www.columbia.edu/kermit/ckubwr.html#x3.2.2
- 204. http://www.columbia.edu/kermit/ckubwr.html#x3.2.0
- 205. ftp://kermit.columbia.edu/kermit/f/makefile
- 206. http://www.columbia.edu/kermit/ckubwr.html#top
- 207. http://www.columbia.edu/kermit/ckubwr.html#contents
- 208. http://www.columbia.edu/kermit/ckubwr.html#x3.2
- 209. http://www.columbia.edu/kermit/ckubwr.html#x3.2.3
- 210. http://www.columbia.edu/kermit/ckubwr.html#x3.2.1
- 211. http://www.columbia.edu/kermit/ckubwr.html#top
- 212. http://www.columbia.edu/kermit/ckubwr.html#contents
- 213. http://www.columbia.edu/kermit/ckubwr.html#x3.2
- 214. http://www.columbia.edu/kermit/ckubwr.html#x3.2.4
- 215. http://www.columbia.edu/kermit/ckubwr.html#x3.2.2
- 216. http://www.columbia.edu/kermit/ckubwr.html#x3.2.4.1
- 217. http://www.columbia.edu/kermit/ckubwr.html#x3.2.4.2
- 218. http://www.columbia.edu/kermit/ckubwr.html#x3.2.4.3
- 219. http://www.columbia.edu/kermit/ckubwr.html#x3.2.4.4
- 220. http://www.columbia.edu/kermit/ckubwr.html#x3.2.4.5
- 221. http://www.columbia.edu/kermit/ckubwr.html#top
- 222. http://www.columbia.edu/kermit/ckubwr.html#contents
- 223. http://www.columbia.edu/kermit/ckubwr.html#x3.2
- 224. http://www.columbia.edu/kermit/ckubwr.html#x3.2.4.2
- 225. http://www.columbia.edu/kermit/ckubwr.html#x3.2.2
- 226. http://www.columbia.edu/kermit/ckubwr.html#top
- 227. http://www.columbia.edu/kermit/ckubwr.html#contents
- 228. http://www.columbia.edu/kermit/ckubwr.html#x3.2.4
- 229. http://www.columbia.edu/kermit/ckubwr.html#x3.2.4.3
- 230. http://www.columbia.edu/kermit/ckubwr.html#x3.2.4.1
- 231. http://www.columbia.edu/kermit/ckubwr.html#top
- 232. http://www.columbia.edu/kermit/ckubwr.html#contents
- 233. http://www.columbia.edu/kermit/ckubwr.html#x3.2.4
- 234. http://www.columbia.edu/kermit/ckubwr.html#x3.2.4.4
- 235. http://www.columbia.edu/kermit/ckubwr.html#x3.2.4.2
- 236. http://www.columbia.edu/kermit/ckubwr.html#top
- 237. http://www.columbia.edu/kermit/ckubwr.html#contents
- 238. http://www.columbia.edu/kermit/ckubwr.html#x3.2.4
- 239. http://www.columbia.edu/kermit/ckubwr.html#x3.2.4.5
- 240. http://www.columbia.edu/kermit/ckubwr.html#x3.2.4.3
- 241. http://www.columbia.edu/kermit/ckubwr.html#top
- 242. http://www.columbia.edu/kermit/ckubwr.html#contents
- 243. http://www.columbia.edu/kermit/ckubwr.html#x3.2.4
- 244. http://www.columbia.edu/kermit/ckubwr.html#x3.2.4.4
- 245. http://www.columbia.edu/kermit/ckubwr.html#top
- 246. http://www.columbia.edu/kermit/ckubwr.html#contents
- 247. http://www.columbia.edu/kermit/ckubwr.html#x3.2
- 248. http://www.columbia.edu/kermit/ckubwr.html#x3.2.4
- 249. http://www.columbia.edu/kermit/ckubwr.html#top
- 250. http://www.columbia.edu/kermit/ckubwr.html#contents
- 251. http://www.columbia.edu/kermit/ckubwr.html#x3
- 252. http://www.columbia.edu/kermit/ckubwr.html#x3.4
- 253. http://www.columbia.edu/kermit/ckubwr.html#x3.2
- 254. http://www.columbia.edu/kermit/ckubwr.html#x3.3.1
- 255. http://www.columbia.edu/kermit/ckubwr.html#x3.3.2
- 256. http://www.columbia.edu/kermit/ckubwr.html#x3.3.3
- 257. http://www.columbia.edu/kermit/ckubwr.html#x3.3.4
- 258. http://www.columbia.edu/kermit/ckubwr.html#x3.3.5
- 259. http://www.columbia.edu/kermit/ckubwr.html#x3.3.6
- 260. news:comp.os.linux.misc
- 261. news:comp.os.linux.answers
- 262. http://www.tldp.org/
- 263. http://www.tldp.org/FAQ/Linux-FAQ.html
- 264. http://www.tldp.org/HOWTO/Serial-HOWTO.html
- 265. http://tldp.org/HOWTO/Modem-HOWTO.html
- 266. ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO
- 267. ftp://tsx-11.mit.edu/pub/linux/docs/HOWTO
- 268. http://www.tldp.org/HOWTO/
- 269. http://www.tldp.org/hmirrors.html
- 270. http://www.redhat.com/apps/support/
- 271. http://www.debian.org/support
- 272. http://www.slackware.com/support/
- 273. http://www.caldera.com/support/
- 274. http://www.suse.com/support/
- 275. http://www.mandrake.com/support/
- 276. http://www.turbolinux.com/support/
- 277. http://www.linmodems.org/
- 278. http://www.columbia.edu/kermit/ckubwr.html#x3.0
- 279. http://linux.dreamtime.org/decnet/
- 280. mailto:kermit-support@columbia.edu
- 281. http://www.linmodems.org/
- 282. http://www.columbia.edu/kermit/ckubwr.html#x3.0.2
- 283. http://www.columbia.edu/kermit/security.html#servers
- 284. http://www.columbia.edu/kermit/sshclient.html
- 285. http://www.columbia.edu/kermit/ckubwr.html#top
- 286. http://www.columbia.edu/kermit/ckubwr.html#contents
- 287. http://www.columbia.edu/kermit/ckubwr.html#x3
- 288. http://www.columbia.edu/kermit/ckubwr.html#x3.3.2
- 289. http://www.columbia.edu/kermit/ckubwr.html#top
- 290. http://www.columbia.edu/kermit/ckubwr.html#contents
- 291. http://www.columbia.edu/kermit/ckubwr.html#x3.3
- 292. http://www.columbia.edu/kermit/ckubwr.html#x3.3.3
- 293. http://www.columbia.edu/kermit/ckubwr.html#x3.3.1
- 294. http://www.columbia.edu/kermit/ckubwr.html#x3.0
- 295. http://www.columbia.edu/kermit/ckubwr.html#x6
- 296. http://www.columbia.edu/kermit/ckubwr.html#x7
- 297. http://www.columbia.edu/kermit/ckubwr.html#x8
- 298. http://www.columbia.edu/kermit/ckuins.html#x10
- 299. http://www.columbia.edu/kermit/ckuins.html#x11
- 300. http://www.columbia.edu/kermit/ckuins.html
- 301. http://www.columbia.edu/kermit/ckubwr.html#x3.0
- 302. http://linuxwww.db.erau.edu/mail_archives/linux-kernel/Mar_98/1441.html
- 303. http://www.columbia.edu/kermit/ckubwr.html#top
- 304. http://www.columbia.edu/kermit/ckubwr.html#contents
- 305. http://www.columbia.edu/kermit/ckubwr.html#x3.3
- 306. http://www.columbia.edu/kermit/ckubwr.html#x3.3.4
- 307. http://www.columbia.edu/kermit/ckubwr.html#x3.3.2
- 308. http://www.columbia.edu/kermit/ckubwr.html#x3.0.5
- 309. http://www.columbia.edu/kermit/ckfaq.html#term
- 310. http://dickey.his.com/xterm/xterm.html
- 311. http://dickey.his.com/xterm/xterm.html
- 312. ftp://kermit.columbia.edu/kermit/f/xmodmap.txt
- 313. http://www.columbia.edu/kermit/ckubwr.html#top
- 314. http://www.columbia.edu/kermit/ckubwr.html#contents
- 315. http://www.columbia.edu/kermit/ckubwr.html#x3.3
- 316. http://www.columbia.edu/kermit/ckubwr.html#x3.3.5
- 317. http://www.columbia.edu/kermit/ckubwr.html#x3.3.3
- 318. http://www.columbia.edu/kermit/ckubwr.html#top
- 319. http://www.columbia.edu/kermit/ckubwr.html#contents
- 320. http://www.columbia.edu/kermit/ckubwr.html#x3.3
- 321. http://www.columbia.edu/kermit/ckubwr.html#x3.3.6
- 322. http://www.columbia.edu/kermit/ckubwr.html#x3.3.4
- 323. http://www.columbia.edu/kermit/ckermit.html
- 324. mailto:kermit-support@columbia.edu
- 325. http://www.redhat.com/support/errata/RHBA-2001-153.html
- 326. news:comp.protocols.kermit.misc
- 327. http://www.columbia.edu/kermit/ckubwr.html#top
- 328. http://www.columbia.edu/kermit/ckubwr.html#contents
- 329. http://www.columbia.edu/kermit/ckubwr.html#x3.3
- 330. http://www.columbia.edu/kermit/ckubwr.html#x3.3.5
- 331. http://www.columbia.edu/kermit/ckubwr.html#top
- 332. http://www.columbia.edu/kermit/ckubwr.html#contents
- 333. http://www.columbia.edu/kermit/ckubwr.html#x3
- 334. http://www.columbia.edu/kermit/ckubwr.html#x3.5
- 335. http://www.columbia.edu/kermit/ckubwr.html#x3.3
- 336. http://www.columbia.edu/kermit/ckubwr.html#top
- 337. http://www.columbia.edu/kermit/ckubwr.html#contents
- 338. http://www.columbia.edu/kermit/ckubwr.html#x3
- 339. http://www.columbia.edu/kermit/ckubwr.html#x3.6
- 340. http://www.columbia.edu/kermit/ckubwr.html#x3.4
- 341. news:comp.os.qnx
- 342. http://www.columbia.edu/kermit/gkermit.html
- 343. http://www.columbia.edu/kermit/ckuins.html#x10
- 344. http://www.columbia.edu/kermit/ckuins.html
- 345. http://www.columbia.edu/kermit/ckubwr.html#top
- 346. http://www.columbia.edu/kermit/ckubwr.html#contents
- 347. http://www.columbia.edu/kermit/ckubwr.html#x3
- 348. http://www.columbia.edu/kermit/ckubwr.html#x3.7
- 349. http://www.columbia.edu/kermit/ckubwr.html#x3.5
- 350. http://www.columbia.edu/kermit/ckubwr.html#x3.6.1
- 351. http://www.columbia.edu/kermit/ckubwr.html#x3.6.2
- 352. http://www.columbia.edu/kermit/ckubwr.html#x3.6.3
- 353. http://www.columbia.edu/kermit/ckubwr.html#x3.6.4
- 354. http://www.columbia.edu/kermit/ckubwr.html#x3.10
- 355. http://aplawrence.com/SCOFAQ/
- 356. http://www.zenez.com/cgi-bin/scoprogfaq/faq.pl
- 357. http://www.zenez.com/cgi-bin/scouw7faq/faq.pl
- 358. http://zenez.pcunix.com/cgi-bin/scouw7faq/faq.pl
- 359. http://pcunix.com/Unixart/modems.html
- 360. http://www.freebird.org/faq/
- 361. http://www.freebird.org/faq/developer.html
- 362. http://support.caldera.com/caldera
- 363. http://stage.caldera.com/ta/
- 364. http://aplawrence.com/newtosco.html
- 365. http://www.columbia.edu/kermit/ckubwr.html#x3.0.5
- 366. http://www.columbia.edu/kermit/ckfaq.html#term
- 367. http://www.columbia.edu/kermit/ckubwr.html#x3.0
- 368. http://www.columbia.edu/kermit/ckubwr.html#top
- 369. http://www.columbia.edu/kermit/ckubwr.html#contents
- 370. http://www.columbia.edu/kermit/ckubwr.html#x3.6
- 371. http://www.columbia.edu/kermit/ckubwr.html#x3.6.1
- 372. ftp://kermit.columbia.edu/kermit/c-kermit/ckutio.c
- 373. http://www.columbia.edu/kermit/ckubwr.html#top
- 374. http://www.columbia.edu/kermit/ckubwr.html#contents
- 375. http://www.columbia.edu/kermit/ckubwr.html#x3.6
- 376. http://www.columbia.edu/kermit/ckubwr.html#x3.6.3
- 377. http://www.columbia.edu/kermit/ckubwr.html#x3.6.1
- 378. http://www.digi.com/
- 379. ftp://ftp.fu-berlin.de/pub/unix/driver/fas
- 380. http://www.columbia.edu/kermit/ckubwr.html#x14
- 381. http://www.sco.com/
- 382. ftp://ftp.sco.com/
- 383. http://www.columbia.edu/kermit/ckubwr.html#top
- 384. http://www.columbia.edu/kermit/ckubwr.html#contents
- 385. http://www.columbia.edu/kermit/ckubwr.html#x3.6
- 386. http://www.columbia.edu/kermit/ckubwr.html#x3.6.4
- 387. http://www.columbia.edu/kermit/ckubwr.html#x3.6.2
- 388. http://www.columbia.edu/kermit/ckubwr.html#x3.10
- 389. http://www.columbia.edu/kermit/ckubwr.html#top
- 390. http://www.columbia.edu/kermit/ckubwr.html#contents
- 391. http://www.columbia.edu/kermit/ckubwr.html#x3.6
- 392. http://www.columbia.edu/kermit/ckubwr.html#x3.6.3
- 393. http://www.columbia.edu/kermit/ckubwr.html#top
- 394. http://www.columbia.edu/kermit/ckubwr.html#contents
- 395. http://www.columbia.edu/kermit/ckubwr.html#x3
- 396. http://www.columbia.edu/kermit/ckubwr.html#x3.8
- 397. http://www.columbia.edu/kermit/ckubwr.html#x3.6
- 398. http://www.columbia.edu/kermit/ckubwr.html#x3.7.1
- 399. http://www.columbia.edu/kermit/ckubwr.html#x3.7.2
- 400. http://www.columbia.edu/kermit/ckubwr.html#x3.7.3
- 401. http://www.columbia.edu/kermit/ckubwr.html#x3.7.4
- 402. http://www.columbia.edu/kermit/ckubwr.html#x3.7.5
- 403. news:comp.unix.solaris
- 404. http://access1.sun.com/
- 405. http://docs.sun.com/
- 406. http://www.sunhelp.com/
- 407. http://www.wins.uva.nl/pub/solaris/solaris2/
- 408. http://www.wins.uva.nl/cgi-bin/sfaq.cgi
- 409. ftp://ftp.wins.uva.nl/pub/solaris
- 410. http://www.science.uva.nl/pub/solaris/solaris2.html
- 411. http://www.stokely.com/
- 412. http://www.stokely.com/unix.sysadm.resources/faqs.sun.html
- 413. http://www.columbia.edu/kermit/ckubwr.html#x3.0
- 414. http://www.columbia.edu/kermit/ckubwr.html#top
- 415. http://www.columbia.edu/kermit/ckubwr.html#contents
- 416. http://www.columbia.edu/kermit/ckubwr.html#x3
- 417. http://www.columbia.edu/kermit/ckubwr.html#x3.7
- 418. http://www.columbia.edu/kermit/ckubwr.html#x3.7.2
- 419. http://www.columbia.edu/kermit/ckubwr.html#top
- 420. http://www.columbia.edu/kermit/ckubwr.html#contents
- 421. http://www.columbia.edu/kermit/ckubwr.html#x3.7
- 422. http://www.columbia.edu/kermit/ckubwr.html#x3.7.3
- 423. http://www.columbia.edu/kermit/ckubwr.html#x3.7.1
- 424. http://www.columbia.edu/kermit/ckubwr.html#top
- 425. http://www.columbia.edu/kermit/ckubwr.html#contents
- 426. http://www.columbia.edu/kermit/ckubwr.html#x3.7
- 427. http://www.columbia.edu/kermit/ckubwr.html#x3.7.4
- 428. http://www.columbia.edu/kermit/ckubwr.html#x3.7.2
- 429. http://www.columbia.edu/kermit/ckubwr.html#top
- 430. http://www.columbia.edu/kermit/ckubwr.html#contents
- 431. http://www.columbia.edu/kermit/ckubwr.html#x3.7
- 432. http://www.columbia.edu/kermit/ckubwr.html#x3.7.5
- 433. http://www.columbia.edu/kermit/ckubwr.html#x3.7.3
- 434. news:comp.os.vms
- 435. http://www.columbia.edu/kermit/ckubwr.html#top
- 436. http://www.columbia.edu/kermit/ckubwr.html#contents
- 437. http://www.columbia.edu/kermit/ckubwr.html#x3.7
- 438. http://www.columbia.edu/kermit/ckubwr.html#x3.7.6
- 439. http://www.columbia.edu/kermit/ckubwr.html#x3.7.4
- 440. http://www.columbia.edu/kermit/ckubwr.html#top
- 441. http://www.columbia.edu/kermit/ckubwr.html#contents
- 442. http://www.columbia.edu/kermit/ckubwr.html#x3.7
- 443. http://www.columbia.edu/kermit/ckubwr.html#x3.7.5
- 444. http://www.columbia.edu/kermit/ckubwr.html#top
- 445. http://www.columbia.edu/kermit/ckubwr.html#contents
- 446. http://www.columbia.edu/kermit/ckubwr.html#x3
- 447. http://www.columbia.edu/kermit/ckubwr.html#x3.9
- 448. http://www.columbia.edu/kermit/ckubwr.html#x3.7
- 449. http://www.stokely.com/
- 450. http://access1.sun.com/
- 451. http://www.ludd.luth.se/~bear/project/sun/sun.hardware.txt
- 452. ftp://ftp.netcom.com/pub/ru/rubicon/sun.hdwr.ref
- 453. ftp://ftp.intnet.net/pub/SUN/Sun-Hardware-Ref
- 454. http://www.columbia.edu/kermit/ckubwr.html#top
- 455. http://www.columbia.edu/kermit/ckubwr.html#contents
- 456. http://www.columbia.edu/kermit/ckubwr.html#x3
- 457. http://www.columbia.edu/kermit/ckubwr.html#x3.10
- 458. http://www.columbia.edu/kermit/ckubwr.html#x3.8
- 459. news:comp.unix.ultrix
- 460. news:comp.sys.dec
- 461. http://www.columbia.edu/kermit/ckubwr.html#top
- 462. http://www.columbia.edu/kermit/ckubwr.html#contents
- 463. http://www.columbia.edu/kermit/ckubwr.html#x3
- 464. http://www.columbia.edu/kermit/ckubwr.html#x3.11
- 465. http://www.columbia.edu/kermit/ckubwr.html#x3.9
- 466. http://www.freebird.org/
- 467. http://www.freebird.org/faq/
- 468. news:comp.unix.unixware.misc
- 469. news:comp.unix.sco.misc
- 470. http://www.columbia.edu/kermit/ckubwr.html#x3.0
- 471. ftp://kermit.columbia.edu/kermit/f/ckutio.c
- 472. http://www.columbia.edu/kermit/ckubwr.html#top
- 473. http://www.columbia.edu/kermit/ckubwr.html#contents
- 474. http://www.columbia.edu/kermit/ckubwr.html#x3
- 475. http://www.columbia.edu/kermit/ckubwr.html#x3.12
- 476. http://www.columbia.edu/kermit/ckubwr.html#x3.10
- 477. http://www.columbia.edu/kermit/ckubwr.html#top
- 478. http://www.columbia.edu/kermit/ckubwr.html#contents
- 479. http://www.columbia.edu/kermit/ckubwr.html#x3
- 480. http://www.columbia.edu/kermit/ckubwr.html#x3.13
- 481. http://www.columbia.edu/kermit/ckubwr.html#x3.11
- 482. http://www.columbia.edu/kermit/ckubwr.html#top
- 483. http://www.columbia.edu/kermit/ckubwr.html#contents
- 484. http://www.columbia.edu/kermit/ckubwr.html#x3
- 485. http://www.columbia.edu/kermit/ckubwr.html#x3.14
- 486. http://www.columbia.edu/kermit/ckubwr.html#x3.12
- 487. http://www.columbia.edu/kermit/ckubwr.html#top
- 488. http://www.columbia.edu/kermit/ckubwr.html#contents
- 489. http://www.columbia.edu/kermit/ckubwr.html#x3
- 490. http://www.columbia.edu/kermit/ckubwr.html#x3.15
- 491. http://www.columbia.edu/kermit/ckubwr.html#x3.13
- 492. news:comp.sys.sgi.misc
- 493. news:comp.sys.sgi.admin
- 494. http://www.sgi.com/
- 495. http://www-viz.tamu.edu/~sgi-faq/
- 496. ftp://viz.tamu.edu/pub/sgi/faq/
- 497. http://www.columbia.edu/kermit/ckuins.html
- 498. http://freeware.sgi.com/Installable/gcc-2.95.2.html
- 499. http://freeware.sgi.com/Installable/gcc-2.95.2.html
- 500. http://www.columbia.edu/kermit/ckubwr.html#top
- 501. http://www.columbia.edu/kermit/ckubwr.html#contents
- 502. http://www.columbia.edu/kermit/ckubwr.html#x3
- 503. http://www.columbia.edu/kermit/ckubwr.html#x3.16
- 504. http://www.columbia.edu/kermit/ckubwr.html#x3.14
- 505. news:comp.sys.be
- 506. http://www.columbia.edu/kermit/ckubwr.html#top
- 507. http://www.columbia.edu/kermit/ckubwr.html#contents
- 508. http://www.columbia.edu/kermit/ckubwr.html#x3
- 509. http://www.columbia.edu/kermit/ckubwr.html#x3.17
- 510. http://www.columbia.edu/kermit/ckubwr.html#x3.15
- 511. http://www.columbia.edu/kermit/ckubwr.html#top
- 512. http://www.columbia.edu/kermit/ckubwr.html#contents
- 513. http://www.columbia.edu/kermit/ckubwr.html#x3
- 514. http://www.columbia.edu/kermit/ckubwr.html#x3.18
- 515. http://www.columbia.edu/kermit/ckubwr.html#x3.16
- 516. http://www.columbia.edu/kermit/ckubwr.html#top
- 517. http://www.columbia.edu/kermit/ckubwr.html#contents
- 518. http://www.columbia.edu/kermit/ckubwr.html#x3
- 519. http://www.columbia.edu/kermit/ckubwr.html#x3.19
- 520. http://www.columbia.edu/kermit/ckubwr.html#x3.17
- 521. http://www.columbia.edu/kermit/ckubwr.html#top
- 522. http://www.columbia.edu/kermit/ckubwr.html#contents
- 523. http://www.columbia.edu/kermit/ckubwr.html#x3
- 524. http://www.columbia.edu/kermit/ckubwr.html#x3.20
- 525. http://www.columbia.edu/kermit/ckubwr.html#x3.18
- 526. http://www.keyspan.com/products/usb/adapter/
- 527. http://www.columbia.edu/kermit/ckuins.html
- 528. http://cerebus.sandiego.edu/~jerry/UnixTips/
- 529. http://www.columbia.edu/kermit/ckubwr.html#top
- 530. http://www.columbia.edu/kermit/ckubwr.html#contents
- 531. http://www.columbia.edu/kermit/ckubwr.html#x3
- 532. http://www.columbia.edu/kermit/ckubwr.html#x3.19
- 533. http://www.uni-giessen.de/faq/archiv/coherent-faq.general/msg00000.html
- 534. http://www.columbia.edu/kermit/ckubwr.html#top
- 535. http://www.columbia.edu/kermit/ckubwr.html#contents
- 536. http://www.columbia.edu/kermit/ckubwr.html#x5
- 537. http://www.columbia.edu/kermit/ckubwr.html#x3
- 538. http://www.columbia.edu/kermit/ckccfg.html
- 539. http://www.columbia.edu/kermit/ckubwr.html#top
- 540. http://www.columbia.edu/kermit/ckubwr.html#contents
- 541. http://www.columbia.edu/kermit/ckubwr.html#x6
- 542. http://www.columbia.edu/kermit/ckubwr.html#x4
- 543. http://www.columbia.edu/kermit/ckuins.html
- 544. http://www.columbia.edu/kermit/ckubwr.html#top
- 545. http://www.columbia.edu/kermit/ckubwr.html#contents
- 546. http://www.columbia.edu/kermit/ckubwr.html#x7
- 547. http://www.columbia.edu/kermit/ckubwr.html#x5
- 548. http://www.columbia.edu/kermit/ckuins.html#9.5
- 549. http://www.columbia.edu/kermit/ckubwr.html#x3
- 550. http://www.columbia.edu/kermit/ckubwr.html#top
- 551. http://www.columbia.edu/kermit/ckubwr.html#contents
- 552. http://www.columbia.edu/kermit/ckubwr.html#x8
- 553. http://www.columbia.edu/kermit/ckubwr.html#x6
- 554. http://www.columbia.edu/kermit/ckuins.html#x8
- 555. http://www.columbia.edu/kermit/ckuins.html
- 556. http://www.columbia.edu/kermit/ck60manual.html
- 557. http://www.columbia.edu/kermit/ckubwr.html#top
- 558. http://www.columbia.edu/kermit/ckubwr.html#contents
- 559. http://www.columbia.edu/kermit/ckubwr.html#x9
- 560. http://www.columbia.edu/kermit/ckubwr.html#x7
- 561. http://www.columbia.edu/kermit/ckubwr.html#top
- 562. http://www.columbia.edu/kermit/ckubwr.html#contents
- 563. http://www.columbia.edu/kermit/ckubwr.html#x10
- 564. http://www.columbia.edu/kermit/ckubwr.html#x8
- 565. http://www.columbia.edu/kermit/ck60manual.html
- 566. http://dickey.his.com/xterm/xterm.html
- 567. http://www.columbia.edu/kermit/ckubwr.html#top
- 568. http://www.columbia.edu/kermit/ckubwr.html#contents
- 569. http://www.columbia.edu/kermit/ckubwr.html#x11
- 570. http://www.columbia.edu/kermit/ckubwr.html#x9
- 571. http://www.columbia.edu/kermit/ckubwr.html#top
- 572. http://www.columbia.edu/kermit/ckubwr.html#contents
- 573. http://www.columbia.edu/kermit/ckubwr.html#x12
- 574. http://www.columbia.edu/kermit/ckubwr.html#x10
- 575. http://www.columbia.edu/kermit/ckubwr.html#x11.1
- 576. http://www.columbia.edu/kermit/ckubwr.html#x11.2
- 577. http://www.columbia.edu/kermit/ckubwr.html#top
- 578. http://www.columbia.edu/kermit/ckubwr.html#contents
- 579. http://www.columbia.edu/kermit/ckubwr.html#x11
- 580. http://www.columbia.edu/kermit/ckubwr.html#x11.2
- 581. http://www.columbia.edu/kermit/ck60manual.html
- 582. http://www.columbia.edu/kermit/ckubwr.html#top
- 583. http://www.columbia.edu/kermit/ckubwr.html#contents
- 584. http://www.columbia.edu/kermit/ckubwr.html#x11
- 585. http://www.columbia.edu/kermit/ckubwr.html#x11.1
- 586. http://www.columbia.edu/kermit/ck60manual.html
- 587. http://www.columbia.edu/kermit/ckubwr.html#top
- 588. http://www.columbia.edu/kermit/ckubwr.html#contents
- 589. http://www.columbia.edu/kermit/ckubwr.html#x13
- 590. http://www.columbia.edu/kermit/ckubwr.html#x11
- 591. http://www.columbia.edu/kermit/security.html
- 592. http://www.columbia.edu/kermit/ckubwr.html#top
- 593. http://www.columbia.edu/kermit/ckubwr.html#contents
- 594. http://www.columbia.edu/kermit/ckubwr.html#x14
- 595. http://www.columbia.edu/kermit/ckubwr.html#x12
- 596. http://www.columbia.edu/kermit/ckubwr.html#top
- 597. http://www.columbia.edu/kermit/ckubwr.html#contents
- 598. http://www.columbia.edu/kermit/ckubwr.html#x15
- 599. http://www.columbia.edu/kermit/ckubwr.html#x14
- 600. mailto:support@stallion.oz.au
- 601. http://www.stallion.com/
- 602. http://www.columbia.edu/kermit/ckubwr.html#top
- 603. http://www.columbia.edu/kermit/ckubwr.html#contents
- 604. http://www.columbia.edu/kermit/ckermit.html
- 605. http://www.columbia.edu/kermit/ck80.html
- 606. http://www.columbia.edu/kermit/index.html
- 607. http://www.columbia.edu/kermit/index.html
- 608. http://www.columbia.edu/
- 609. mailto:kermit@columbia.edu
index e1bca34..3ea4807 100644 (file)
--- a/ckucmd.c
+++ b/ckucmd.c
@@ -1,14 +1,16 @@
 #include "ckcsym.h"
 
-char *cmdv = "Command package 8.0.157, 11 May 2003";
+char *cmdv = "Command package 9.0.168, 12 March 2010";
 
 /*  C K U C M D  --  Interactive command package for Unix  */
 
+/* (In reality, it's for all platforms, not just Unix) */
+
 /*
   Author: Frank da Cruz (fdc@columbia.edu),
   Columbia University Academic Information Systems, New York City.
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2010,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -83,7 +85,7 @@ struct keytab cmonths[] = {
 
 #ifndef NOSPL
 _PROTOTYP( int chkvar, (char *) );
-extern int askflag;
+extern int askflag, echostars;
 #endif /* NOSPL */
 
 #ifdef CKROOT
@@ -96,6 +98,7 @@ extern int inserver;
 
 int cmfldflgs = 0;                     /* Flags for cmfld() */
 int cmkwflgs = 0;                      /* Flags from last keyword parse */
+static int nomsg = 0;
 static int blocklvl = 0;               /* Block nesting level */
 static int linebegin = 0;              /* Flag for at start of a line */
 static int quoting = 1;                        /* Quoting is allowed */
@@ -203,10 +206,6 @@ modules would have to be changed...
 #include <io.h>
 #endif /* OS2 */
 
-#ifdef NT
-#define stricmp _stricmp
-#endif /* NT */
-
 #ifdef OSK
 #define cc ccount                      /* OS-9/68K compiler bug */
 #endif /* OSK */
@@ -249,6 +248,10 @@ int psetf = 0,                          /* Flag that prompt has been set */
     inword = 0;                                /* In the middle of getting a word */
 
 char *dfprom = "Command? ";             /* Default prompt */
+#ifndef NOLASTFILE
+char *lastfile = NULL;                 /* Last filespec */
+static char *tmplastfile = NULL;       /* Last filespec candidate */
+#endif /* NOLASTFILE */
 
 int cmflgs;                             /* Command flags */
 int cmfsav;                            /* A saved version of them */
@@ -264,6 +267,7 @@ char *cmdbuf = NULL;                        /* Command buffer */
 char *savbuf = NULL;                   /* Buffer to save copy of command */
 char *atmbuf = NULL;                   /* Atom buffer - for current field */
 char *atxbuf = NULL;                   /* For expanding the atom buffer */
+char *prevcmd = NULL;
 static char *atybuf = NULL;            /* For copying atom buffer */
 static char *filbuf = NULL;            /* File name buffer */
 static char *cmprom = NULL;            /* Program's prompt */
@@ -296,6 +300,7 @@ char cmdbuf[CMDBL+4];                   /* Command buffer */
 char savbuf[CMDBL+4];                   /* Buffer to save copy of command */
 char atmbuf[ATMBL+4];                   /* Atom buffer */
 char atxbuf[CMDBL+4];                   /* For expanding the atom buffer */
+char prevcmd[CMDBL+4];                 /* For displaying the last command */
 static char atybuf[ATMBL+4];           /* For copying atom buffer */
 static char filbuf[ATMBL+4];           /* File name buffer */
 static char cmprom[PROMPTL+1];         /* Program's prompt */
@@ -304,7 +309,7 @@ static char cmprxx[PROMPTL+1];              /* Program's prompt, unevaluated */
 
 /* Command buffer pointers */
 
-#define PPVLEN 24
+#define PPVLEN VNAML                   /* 20080305 Wolfram Sang (was 24) */
 char ppvnambuf[PPVLEN+1] = { NUL, NUL };
 
 char * cmbptr = NULL;                  /* Current position (for export) */
@@ -585,7 +590,7 @@ kwdhelp(s,n,pat,pre,post,off,xhlp)
     return;
 }
 
-/*  F I L H E L P  --  Given a file list, print names in columns.  */
+/*  F I L H E L P  --  Given a file list, print names in columns.  */
 /*
   Call with:
     n     - number of entries
@@ -593,6 +598,8 @@ kwdhelp(s,n,pat,pre,post,off,xhlp)
     post  - suffix to add to each filename
     off   - offset on first screenful, allowing room for introductory text
     cmdirflg - 1 if only directory names should be listed, 0 to list all files
+    fs    - call fileselect() to decide whether to include each file.
+    The rest of the args are the same as for fileselect().
 
   Arranges filenames in columns with width based on longest filename.
   Does "more?" prompting at end of screen.
@@ -600,7 +607,22 @@ kwdhelp(s,n,pat,pre,post,off,xhlp)
 */
 
 int
-filhelp(n,pre,post,off,cmdirflg) int n, off; char *pre, *post; int cmdirflg; {
+#ifdef CK_ANSIC
+xfilhelp(
+    int n, char *pre, char *post, int off, int cmdirflag,
+    int fs, char *sa, char *sb, char *sna, char *snb,
+    CK_OFF_T minsiz, CK_OFF_T maxsiz,
+    int nbu, int nxlist,
+    char ** xlist
+)
+#else
+xfilhelp(n,pre,post,off,cmdirflg,
+        fs,sa,sb,sna,snb,minsiz,maxsiz,nbu,nxlist,xlist)
+    int n, off; char *pre, *post; int cmdirflg;
+    int fs; char *sa,*sb,*sna,*snb; CK_OFF_T minsiz,maxsiz;
+    int nbu,nxlist; char ** xlist;
+#endif /* CK_ANSIC */
+ {
     char filbuf[CKMAXPATH + 1];                /* Temp buffer for one filename */
     int width = 0;
     int cols, height, i, j, k, lc, n2 = 0, rc = 0, itsadir = 0;
@@ -630,6 +652,11 @@ filhelp(n,pre,post,off,cmdirflg) int n, off; char *pre, *post; int cmdirflg; {
            if (cmdirflg && !itsadir)   /* No, listing directories only? */
              continue;                 /* So skip this one. */
 #endif /* COMMENT */
+           if (fs) if (fileselect(filbuf,
+                          sa,sb,sna,snb,
+                          minsiz,maxsiz,nbu,nxlist,xlist) < 1) {
+                    continue;
+           }
 #ifdef VMS
            ckstrncpy(filbuf,zrelname(filbuf,cdp),CKMAXPATH);
 #endif /* VMS */
@@ -728,6 +755,17 @@ xfilhelp:
     }
 }
 
+/*
+  Simpler front end for xfilhelp() with shorter arg list when no
+  file selection is needed.
+*/
+int
+filhelp(n,pre,post,off,cmdirflg) int n, off; char *pre, *post; int cmdirflg; {
+    return(xfilhelp(n,pre,post,off,cmdirflg,
+                   0,NULL,NULL,NULL,NULL,
+                   (CK_OFF_T)0,(CK_OFF_T)0,0,0,(char **)NULL));
+}
+
 /*  C M S E T U P  --  Set up command buffers  */
 
 #ifdef DCMDBUF
@@ -736,6 +774,8 @@ cmsetup() {
     if (!(cmdbuf = malloc(CMDBL + 4))) return(-1);
     if (!(savbuf = malloc(CMDBL + 4))) return(-1);
     savbuf[0] = '\0';
+    if (!(prevcmd = malloc(CMDBL + 4))) return(-1);
+    prevcmd[0] = '\0';
     if (!(atmbuf = malloc(ATMBL + 4))) return(-1);
     if (!(atxbuf = malloc(CMDBL + 4))) return(-1);
     if (!(atybuf = malloc(ATMBL + 4))) return(-1);
@@ -810,8 +850,10 @@ prompt(f) xx_strp f; {
     sx = cmprxx;                       /* Unevaluated copy */
     if (f) {                           /* If conversion function given */
        sy = cmprom;                    /* Evaluate it */
+#ifdef COMMENT
        debug(F101,"prompt sx","",sx);
        debug(F101,"prompt sy","",sy);
+#endif /* COMMENT */
        n = PROMPTL;
        if ((*f)(sx,&sy,&n) < 0)        /* If evaluation failed */
          sx = cmprxx;                  /* revert to unevaluated copy */
@@ -1210,8 +1252,29 @@ untab(s) char *s; {
    -1 if reparse needed,
     0 otherwise, with argument n set to the number that was parsed
 */
+/* This is the traditional cmnum() that gets an int */
 int
 cmnum(xhlp,xdef,radix,n,f) char *xhlp, *xdef; int radix, *n; xx_strp f; {
+    CK_OFF_T z = (CK_OFF_T)0, check;
+    int x;
+    x = cmnumw(xhlp,xdef,radix,&z,f);
+    *n = z;
+    check = *n;
+    if (check != z) {
+       printf("?Magnitude of result too large for integer - %s\n",ckfstoa(z));
+       return(-9);
+    }
+    return(x);
+}
+
+/*
+  This is the new cmnum() that gets a "wide" result, whatever CK_OFF_T
+  is defined to be, normally 32 or 64 bits, depending on the platform.
+  fdc, 24 Dec 2005.
+*/
+int
+cmnumw(xhlp,xdef,radix,n,f)
+    char *xhlp, *xdef; int radix; CK_OFF_T *n; xx_strp f; {
     int x; char *s, *zp, *zq;
 #ifdef COMMENT
     char lbrace, rbrace;
@@ -1260,7 +1323,7 @@ cmnum(xhlp,xdef,radix,n,f) char *xhlp, *xdef; int radix, *n; xx_strp f; {
            if (!strcmp(zp,"-1")) return(-2);
        }
        errno = 0;                      /* Got one, we're done. */
-        *n = atoi(zp);
+        *n = ckatofs(zp);
        if (errno) {
            perror(zp);
            return(-9);
@@ -1294,7 +1357,7 @@ cmnum(xhlp,xdef,radix,n,f) char *xhlp, *xdef; int radix, *n; xx_strp f; {
            if (!strcmp(zp,"-1")) return(-2);
        }
        errno = 0;
-        *n = atoi(zp);
+        *n = ckatofs(zp);
        if (errno) {
            perror(zp);
            return(-9);
@@ -1320,7 +1383,7 @@ cmnum(xhlp,xdef,radix,n,f) char *xhlp, *xdef; int radix, *n; xx_strp f; {
                if (!strcmp(zp,"-1")) return(-2);
            }
            errno = 0;
-           *n = atoi(p);
+           *n = ckatofs(p);
            if (errno) {
                perror(p);
                return(-9);
@@ -1565,6 +1628,7 @@ o_again:
         wild = 1 if name contains '*' or '?', 0 otherwise.
 */
 
+#ifdef COMMENT /* This horrible hack has been replaced - see further down */
 /*
    C M I O F I  --  Parse an input file OR the name of a nonexistent file.
 
@@ -1584,6 +1648,7 @@ cmiofi(xhlp,xdef,xp,wild,f) char *xhlp, *xdef, **xp; int *wild; xx_strp f; {
     nomsg = msgsave;
     return(x);
 }
+#endif /* COMMENT */
 
 int
 cmifi(xhlp,xdef,xp,wild,f) char *xhlp, *xdef, **xp; int *wild; xx_strp f; {
@@ -1653,6 +1718,7 @@ cmifi2(xhlp,xdef,xp,wild,d,path,f,dirflg)
     int i, x, itsadir, xc, expanded = 0, nfiles = 0, children = -1;
     int qflag = 0;
     long y;
+    CK_OFF_T filesize;
     char *sp = NULL, *zq, *np = NULL;
     char *sv = NULL, *p = NULL;
 #ifdef DTILDE
@@ -1682,6 +1748,9 @@ cmifi2(xhlp,xdef,xp,wild,d,path,f,dirflg)
     if (!xhlp) xhlp = "";
     if (!xdef) xdef = "";
 
+#ifndef NOLASTFILE
+    makestr(&tmplastfile,NULL);
+#endif /* NOLASTFILE */
     nzxopts = 0;                       /* zxpand() options */
     debug(F101,"cmifi d","",d);
     if (d & 2) {                       /* d & 2 means don't follow symlinks */
@@ -1758,6 +1827,9 @@ cmifi2(xhlp,xdef,xp,wild,d,path,f,dirflg)
          case 0:                       /* SP */
            if (xc == 0)                /* If no input... */
              *xp = xdef;               /* substitute the default */
+#ifndef NOLASTFILE
+           makestr(&tmplastfile,*xp);  /* Make a copy before bstripping */
+#endif /* #ifndef NOLASTFILE */
            *xp = brstrip(*xp);         /* Strip braces */
            if (**xp == NUL) {          /* 12 mar 2001 */
                if (np) free(np);
@@ -2052,6 +2124,9 @@ cmifi2(xhlp,xdef,xp,wild,d,path,f,dirflg)
            if (itsadir && d && !dirflg) { /* It's a directory and not wild */
                if (sv) free(sv);       /* and it's ok to parse directories */
                if (np) free(np);
+#ifndef NOLASTFILE
+               makestr(&lastfile,tmplastfile);
+#endif /* NOLASTFILE */
                return(x);
            }
            if (y == 0) {               /* File was not found */
@@ -2140,7 +2215,8 @@ cmifi2(xhlp,xdef,xp,wild,d,path,f,dirflg)
                          printf("?Off Limits: %s\n",sv);
                        else
 #endif /* CKROOT */
-                         printf("?No %s match - %s\n",
+                         if (!quiet)
+                           printf("?No %s match - %s\n",
                                 dirflg ? "directories" : "files", sv);
                    }
                    if (sv) free(sv);
@@ -2161,6 +2237,9 @@ cmifi2(xhlp,xdef,xp,wild,d,path,f,dirflg)
            } else if (*wild || y > 1) {
                if (sv) free(sv);
                if (np) free(np);
+#ifndef NOLASTFILE
+               makestr(&lastfile,tmplastfile);
+#endif /* NOLASTFILE */
                return(x);
            }
 
@@ -2171,7 +2250,7 @@ cmifi2(xhlp,xdef,xp,wild,d,path,f,dirflg)
              znext(*xp);               /* Get first (only?) matching file */
            if (dirflg)                 /* Maybe wild and expanded */
              itsadir = isdir(*xp);     /* so do this again. */
-           y = dirflg ? itsadir : zchki(*xp); /* Now check accessibility */
+           filesize = dirflg ? itsadir : zchki(*xp); /* Check accessibility */
            if (expanded) {
 #ifdef ZXREWIND
                nfiles = zxrewind();    /* Rewind so next znext() gets 1st */
@@ -2184,15 +2263,16 @@ cmifi2(xhlp,xdef,xp,wild,d,path,f,dirflg)
 #endif /* ZXREWIND */
            }
            debug(F111,"cmifi nfiles",*xp,nfiles);
+           debug(F101,"cmifi filesize","",filesize);
            free(sv);                   /* done with this */
            sv = NULL;
-           if (dirflg && y == 0) {
+           if (dirflg && !filesize) {
                printf("?Not a directory - %s\n",*xp);
 #ifdef CKCHANNELIO
                z_error = FX_ACC;
 #endif /* CKCHANNELIO */
                return(-9);
-           } else if (y == -3) {
+           } else if (filesize == (CK_OFF_T)-3) {
                if (!xcmfdb) {
                    if (diractive)
                      /* Don't show filename if we're not allowed to see it */
@@ -2205,10 +2285,15 @@ cmifi2(xhlp,xdef,xp,wild,d,path,f,dirflg)
                z_error = FX_ACC;
 #endif /* CKCHANNELIO */
                return(xcmfdb ? -6 : -9);
-           } else if (y == -2) {
+           } else if (filesize == (CK_OFF_T)-2) {
                if (!recursive) {
                    if (np) free(np);
-                   if (d) return(0);
+                   if (d) {
+#ifndef NOLASTFILE
+                       makestr(&lastfile,tmplastfile);
+#endif /* NOLASTFILE */
+                       return(0);
+                   }
                    if (!xcmfdb)
                      printf("?File not readable - %s\n",*xp);
 #ifdef CKCHANNELIO
@@ -2216,7 +2301,7 @@ cmifi2(xhlp,xdef,xp,wild,d,path,f,dirflg)
 #endif /* CKCHANNELIO */
                    return(xcmfdb ? -6 : -9);
                }
-           } else if (y < 0) {
+           } else if (filesize < (CK_OFF_T)0) {
                if (np) free(np);
                if (!nomsg && !xcmfdb)
                  printf("?File not found - %s\n",*xp);
@@ -2226,6 +2311,9 @@ cmifi2(xhlp,xdef,xp,wild,d,path,f,dirflg)
                return(xcmfdb ? -6 : -9);
            }
            if (np) free(np);
+#ifndef NOLASTFILE
+           makestr(&lastfile,tmplastfile);
+#endif /* NOLASTFILE */
            return(x);
 
 #ifndef MAC
@@ -2632,6 +2720,9 @@ cmifi2(xhlp,xdef,xp,wild,d,path,f,dirflg)
                        return(-9);
                    }
                    if (np) free(np);
+#ifndef NOLASTFILE
+                   makestr(&lastfile,tmplastfile);
+#endif /* NOLASTFILE */
                    return(0);
 #ifndef VMS
 #ifdef CK_TMPDIR
@@ -2744,7 +2835,7 @@ cmifi2(xhlp,xdef,xp,wild,d,path,f,dirflg)
            fflush(stdout);
            break;
 #endif /* MAC */
-        }
+       }
 #ifdef BS_DIRSEP
         dirnamflg = 1;
         x = gtword(0);                  /* No, get a word */
@@ -2752,7 +2843,7 @@ cmifi2(xhlp,xdef,xp,wild,d,path,f,dirflg)
 #else
         x = gtword(0);                  /* No, get a word */
 #endif /* BS_DIRSEP */
-    *xp = atmbuf;
+       *xp = atmbuf;
     }
 }
 
@@ -2822,7 +2913,7 @@ cmfld(xhlp,xdef,xp,f) char *xhlp, *xdef, **xp; xx_strp f; {
                }
            }
            *xp = atmbuf;               /* Point to what we got. */
-           debug(F111,"cmfld 2",atmbuf,(f) ? 1 : 0);
+           debug(F111,"cmfld 2",atmbuf,((f) ? 1 : 0));
            if (f) {                    /* If a conversion function is given */
                zq = atxbuf;            /* employ it now. */
                atxn = CMDBL;
@@ -2977,7 +3068,7 @@ cmtxt(xhlp,xdef,xp,f) char *xhlp; char *xdef; char **xp; xx_strp f; {
                char * sx = atxbuf;
                zq = atxbuf;            /* Point to the expansion buffer */
                atxn = CMDBL;           /* specify its length */
-               debug(F111,"cmtxt calling (*f)",*xp,atxbuf);
+               /* debug(F111,"cmtxt calling (*f)",*xp,atxbuf); */
                if ((x = (*f)(*xp,&zq,&atxn)) < 0) return(-2);
                sx = atxbuf;
 #ifndef COMMENT
@@ -3076,18 +3167,26 @@ cmtxt(xhlp,xdef,xp,f) char *xhlp; char *xdef; char **xp; xx_strp f; {
    n        --  number of entries in table;
    xhlp     --  pointer to help string;
    xdef     --  pointer to default keyword;
-   f        --  processing function (e.g. to evaluate variables)
+   f        --  string preprocessing function (e.g. to evaluate variables)
    pmsg     --  0 = don't print error messages
                 1 = print error messages
                 2 = include CM_HLP keywords even if invisible
                 3 = 1+2
                 4 = parse a switch (keyword possibly ending in : or =)
+                8 = don't strip comments (used, e.g., for "help #")
  Returns:
    -3       --  no input supplied and no default available
    -2       --  input doesn't uniquely match a keyword in the table
    -1       --  user deleted too much, command reparse required
     n >= 0  --  value associated with keyword
 */
+
+/*
+  Front ends for cmkey2(): 
+  cmkey()  - The normal keyword parser
+  cmkeyx() - Like cmkey() but suppresses error messages
+  cmswi()  - Switch parser
+*/
 int
 cmkey(table,n,xhlp,xdef,f)
 /* cmkey */  struct keytab table[]; int n; char *xhlp, *xdef; xx_strp f; {
@@ -3143,9 +3242,12 @@ cmkey2(table,n,xhlp,xdef,tok,f,pmsg)
            return(-9);
        }
         rtimer();                       /* Reset timer */
-    } else {
+    } else {                            /* Otherwise get a command word */
         rtimer();                       /* Reset timer */
-        zz = gtword((pmsg == 4) ? 1 : 0);/* Otherwise get a command word */
+       if (pmsg & 8)                    /* 8 is for parsing HELP tokens */
+         zz = gtword(4);
+       else
+         zz = gtword((pmsg == 4) ? 1 : 0);
     }
 
     debug(F101,"cmkey table length","",n);
@@ -3160,7 +3262,10 @@ cmkey2(table,n,xhlp,xdef,tok,f,pmsg)
        switch (zz) {
          case -10:                     /* Timeout */
            if (gtimer() < timelimit) {
-               zz = gtword((pmsg == 4) ? 1 : 0);
+               if (pmsg & 8)           /* 8 is for parsing HELP tokens */
+                 zz = gtword(4);
+               else
+                 zz = gtword((pmsg == 4) ? 1 : 0);
                continue;
            } else {
 #ifdef IKSD
@@ -3227,6 +3332,7 @@ cmkey2(table,n,xhlp,xdef,tok,f,pmsg)
                }
 #endif /* M_UNGW */
            }
+#ifdef COMMENT                         /* ^^^ */
            if (cmswitch && *atmbuf != '/') {
                if (pmsg & 1) {
                    bleep(BP_FAIL);
@@ -3235,6 +3341,7 @@ cmkey2(table,n,xhlp,xdef,tok,f,pmsg)
                cmflgs = -2;
                return(-6);
            }
+#endif /* COMMENT */
            if (cmswitch) {
                int i;
                for (i = 0; i < wordlen; i++) {
@@ -3556,7 +3663,7 @@ cmkey2(table,n,xhlp,xdef,tok,f,pmsg)
            printf("\n%d - Unexpected return code from gtword\n",zz);
            return(cmflgs = -2);
        }
-       zz = gtword((pmsg == 4) ? 1 : 0);
+       zz = (pmsg & 8) ? gtword(4) : gtword((pmsg == 4) ? 1 : 0);
        debug(F111,"cmkey gtword zz",atmbuf,zz);
     }
 }
@@ -3685,7 +3792,7 @@ cmdelta(yy, mo, dd, hh, mm, ss, sign, dyy, dmo, ddd, dhh, dmm, dss)
        debug(F101,"cmdelta hh","",hh);
        debug(F101,"cmdelta mm","",mm);
        debug(F101,"cmdelta ss","",ss);
-       debug(F101,"cmdelta sin","",sign);
+       debug(F101,"cmdelta sign","",sign);
        debug(F101,"cmdelta dyy","",dyy);
        debug(F101,"cmdelta dmo","",dmo);
        debug(F101,"cmdelta ddd","",ddd);
@@ -3727,11 +3834,24 @@ cmdelta(yy, mo, dd, hh, mm, ss, sign, dyy, dmo, ddd, dhh, dmm, dss)
     }
     sign = (sign < 0) ? -1 : 1;
     if (dmo != 0) {
-       mo += (sign * dmo);
-       if (mo > 12 || mo < 0) {
-           yy += mo / 12;
-           mo = mo % 12;
-       }
+        if (sign > 0) {
+            mo += (sign * dmo);
+            if (mo > 12) {
+                yy += mo / 12;
+                mo = mo % 12;
+            }
+        } else if (sign < 0) {
+            while (dmo > 12) {
+                yy--;
+                dmo -= 12;
+            }
+            if (dmo < mo) {
+                mo -= dmo;
+            } else {
+                yy--;
+                mo = 12 - (dmo - mo);
+            }
+        }
     }
     if (dyy != 0) {
        yy += (sign * dyy);
@@ -4163,6 +4283,13 @@ cmcvtdate(s,t) char * s; int t; {
        p = s;
        goto delta;
     }
+#ifdef COMMENT
+/*
+  What is the purpose of this?  It breaks parsing of email dates like
+  "Wed, 13 Feb 2002 17:43:02 -0800 (PST)".  Removing this code fixes the
+  problem and Kermit still passes the 'dates' script.
+  - fdc, Sat Nov 26 10:52:45 2005.
+*/
     if (dow > -1) {
        /* Day of week given followed by something that is not a time */
        /* or a delta so it can't be valid */
@@ -4170,6 +4297,7 @@ cmcvtdate(s,t) char * s; int t; {
        debug(F111,"cmcvtdate fail",cmdatemsg,-1);
        return(NULL);
     }
+#endif /* COMMENT */
 
     /* Handle "today", "yesterday", "tomorrow", and +/- n units */
 
@@ -4706,12 +4834,28 @@ cmcvtdate(s,t) char * s; int t; {
        isgmt++;                        /* All dates are GMT from here down */
        if (zone != 0) {                /* But not this one so make it GMT */
            hh += zone;                 /* RFC 822 timezone: EST etc */
+           debug(F101,"cmcvtdate hh + zone","",hh);
            if (hh > 23) {              /* Offset crosses date boundary */
+               int i;
                long jd;
                jd = mjd(yyyymmdd);     /* Get MJD */
                jd += hh / 24;          /* Add new day(s) */
                hh = hh % 24;           /* and convert back to yyyymmdd */
                ckstrncpy(yyyymmdd,mjd2date(jd),YYYYMMDD);
+               debug(F111,"cmcvtdate zone-adjusted date",yyyymmdd,hh);
+               for (i = 0; i < 4; i++)
+                 yearbuf[i] = yyyymmdd[i];
+               yearbuf[4] = NUL;
+               monbuf[0] = yyyymmdd[4];
+               monbuf[1] = yyyymmdd[5];
+               monbuf[2] = NUL;
+               daybuf[0] = yyyymmdd[6];
+               daybuf[1] = yyyymmdd[7];
+               daybuf[2] = NUL;
+               day = daybuf;
+               nday = atoi(daybuf);
+               month = monbuf;
+               year = yearbuf;
            }
        }
        p = p3;                         /* Put back whatever we poked above */
@@ -4768,7 +4912,7 @@ cmcvtdate(s,t) char * s; int t; {
            p++;
        }
     }
-    debug(F110,"cmcvtdate after timezone",p,0);
+    debug(F110,"cmcvtdate source string after timezone",p,0);
 
     if (*p) {                          /* Anything left? */
        p2 = p;
@@ -5250,6 +5394,7 @@ cmdiffdate(d1,d2) char * d1, * d2; {
     return((char *)result);
 }
 
+#ifndef NOSPL
 /* s h u f f l e d a t e  --  Rearrange date string */
 
 /*
@@ -5259,11 +5404,13 @@ cmdiffdate(d1,d2) char * d1, * d2; {
       1: Reformat date to yyyy-mmm-dd (mmm = English month abbreviation).
       2: Reformat date to dd-mmm-yyyy (mmm = English month abbreviation).
       3: Reformat as numeric yyyymmddhhmmss.
+      4: Reformat in asctime() format Sat Nov 26 11:10:34 2005
     Returns:
       Pointer to result if args valid, otherwise original arg pointer.
 */
 char *
 shuffledate(p,opt) char * p; int opt; {
+    extern char * wkdays[];
     int len;
     char ibuf[32];
     static char obuf[48];
@@ -5272,10 +5419,58 @@ shuffledate(p,opt) char * p; int opt; {
 
     if (!p) p = "";
     if (!*p) p = ckdate();
-    if (opt < 1 || opt > 3)
+    if (opt < 1 || opt > 4)
       return(p);
     len = strlen(p);
     if (len < 8 || len > 31) return(p);
+    if (opt == 4) {                    /* Asctime format (26 Nov 2005) */
+       char c, * s;
+       long z; int k;
+       ckstrncpy(ibuf,p,31);
+       k = len;
+       while (k >= 0 && ibuf[k] == CR || ibuf[k] == LF)
+         ibuf[k--] = NUL;
+       while (k >= 0 && ibuf[k] == SP || ibuf[k] == HT)
+         ibuf[k--] = NUL;
+       if (k < 9) ckstrncpy(&ibuf[8]," 00:00:00",9);
+       p = ibuf;
+        z = mjd(p);                     /* Convert to modified Julian date */
+        z = z % 7L;
+        if (z < 0) {
+            z = 0 - z;
+            k = 6 - ((int)z + 3) % 7;
+        } else {
+            k = ((int)z + 3) % 7;      /* Day of week */
+        }
+       s = wkdays[k];
+        obuf[0] = s[0];                        /* Day of week */
+        obuf[1] = s[1];
+        obuf[2] = s[2];
+        obuf[3] = SP;                  /* Space */
+       c = p[6];
+        p[6] = NUL;
+       mm = atoi(&ibuf[4]);            /* Month */
+       s = moname[mm-1];               /* Name of month */
+       p[6] = c;
+
+        obuf[4] = s[0];                        /* Month */
+        obuf[5] = s[1];
+        obuf[6] = s[2];
+        obuf[7] = SP;                  /* Space */
+       if (p[6] == '0')                /* Date of month */
+         obuf[8] = SP;
+       else
+         obuf[8] = p[6];
+        obuf[9] = p[7];
+       ckstrncpy(&obuf[10],&p[8],10);  /* Time */
+        obuf[19] = SP;                 /* Space */
+       obuf[20] = p[0];                /* Year */
+       obuf[21] = p[1];
+       obuf[22] = p[2];
+       obuf[23] = p[3];
+       obuf[24] = NUL;
+       return((char *)obuf);
+    }
     if (opt == 3) {
        ckstrncpy(obuf,p,48);
        /* yyyymmdd hh:mm:ss */
@@ -5325,6 +5520,7 @@ shuffledate(p,opt) char * p; int opt; {
     }
     return((char *)obuf);
 }
+#endif /* NOSPL */
 
 /*  C K C V T D A T E  --  Like cmcvtdate(), but returns string.  */
 /*  For use by date-related functions */
@@ -5662,10 +5858,11 @@ cmcfm() {
 /* See ckucmd.h for FDB and OFDB definitions. */
 
 struct OFDB cmresult = {               /* Universal cmfdb result holder */
-    NULL,
-    0,
-    NULL,
-    0
+    NULL,                              /* Address of succeeding FDB struct */
+    0,                                 /* Function code */
+    NULL,                              /* String result */
+    0,                                 /* Integer result */
+    (CK_OFF_T)0                                /* Wide result */
 };
 
 VOID
@@ -5699,6 +5896,7 @@ cmfdb(fdbin) struct FDB * fdbin; {
     struct FDB * in = fdbin;
     struct OFDB * out = &cmresult;
     int x = 0, n, r;
+    CK_OFF_T w = (CK_OFF_T)0;
     char *s, *xp, *m = NULL;
     int errbits = 0;
 
@@ -5738,6 +5936,19 @@ cmfdb(fdbin) struct FDB * fdbin; {
            debug(F101,"cmfdb cmnum","",x);
            if (x < 0) errbits |= 1;
            break;
+         case _CMNUW:                  /* Wide cmnum - 24 Dec 2005 */
+           r = in->ndata1;
+           if (r != 10 && r != 8) r = 10;
+#ifndef NOSPL
+            x_ifnum = 1;                /* Disables warning messages */
+#endif /* NOSPL */
+           x = cmnumw(in->hlpmsg,in->dflt,r,&w,in->spf);
+#ifndef NOSPL
+            x_ifnum = 0;
+#endif /* NOSPL */
+           debug(F101,"cmfdb cmnumw","",w);
+           if (x < 0) errbits |= 1;
+           break;
          case _CMOFI:
            x = cmofi(in->hlpmsg,in->dflt,&s,in->spf);
            debug(F101,"cmfdb cmofi","",x);
@@ -5795,8 +6006,10 @@ cmfdb(fdbin) struct FDB * fdbin; {
            out->fdbaddr = in;
            out->sresult = s;
            out->nresult = (in->fcode == _CMKEY) ? x : n;
+           out->wresult = w;
            out->kflags = (in->fcode == _CMKEY) ? cmkwflgs : 0;
            debug(F111,"cmfdb out->nresult",out->sresult,out->nresult);
+           debug(F111,"cmfdb out->wresult",out->sresult,out->wresult);
            nomsg = 0;
            xcmfdb = 0;
            /* debug(F111,"cmfdb cmdbuf & crflag",cmdbuf,crflag); */
@@ -5836,7 +6049,6 @@ cmfdb(fdbin) struct FDB * fdbin; {
        pp = np = bp = xp;              /* Back up pointers */
        cmflgs = -1;                    /* Force a reparse */
 
-
 #ifndef NOSPL
        if (!askflag) {                 /* If not executing ASK-class cmd... */
 #endif /* NOSPL */
@@ -5853,6 +6065,29 @@ cmfdb(fdbin) struct FDB * fdbin; {
     }
 }
 
+/*
+   C M I O F I  --  Parse an input file OR the name of a nonexistent file.
+
+   Replaces the commented-out version above.  This one actually works and
+   has the expected straightforward interface.
+*/
+int
+cmiofi(xhlp,xdef,xp,wild,f) char *xhlp, *xdef, **xp; int *wild; xx_strp f; {
+    int x;
+    struct FDB f1, f2;
+    cmfdbi(&f1,_CMIFI,xhlp,xdef,"",0,0,f,NULL,&f2);
+    cmfdbi(&f2,_CMOFI,"","","",0,0,f,NULL,NULL);
+    x = cmfdb(&f1);
+    if (x < 0) {
+       if (x == -3) {
+           x = -9;
+           printf("?Filename required\n");
+       }
+    }
+    *wild = cmresult.nresult;
+    *xp = cmresult.sresult;
+    return(x);
+}
 
 /*  G T W O R D  --  Gets a "word" from the command input stream  */
 
@@ -5862,6 +6097,7 @@ Usage: retcode = gtword(brk);
   brk = 1 to add ':' and '=' (for parsing switches).  These characters
         act as break characters only if the first character of the field
         is slash ('/'), i.e. switch introducer.
+  brk = 4 to not strip comments (used only for "help #" and "help ;").
 
 Returns:
 -10 Timelimit set and timed out
@@ -5939,7 +6175,6 @@ gtword(brk) int brk; {
     if (con_reads_mt) connoi_mt();      /* Task would interfere w/cons read */
 #endif /* datageneral */
 
-
 #ifdef COMMENT
 #ifdef DEBUG
     if (deblog) {
@@ -6062,7 +6297,11 @@ CMDIRPARSE:
 
        c = *bp;
         if (!c) {                      /* If no char waiting in reparse buf */
-           if (dpx && (!pushc
+           if ((dpx
+#ifndef NOSPL
+                || echostars
+#endif /* NOSPL */
+                ) && (!pushc
 #ifndef NOSPL
                        || askflag
 #endif /* NOSPL */
@@ -6206,9 +6445,11 @@ CMDIRPARSE:
                break;
              case ';':                 /* Trailing comment */
              case '#':
-               if (inword == 0 && quoting) { /* If not in a word */
-                   comment = 1;        /* start a comment. */
-                   cp = bp;            /* remember where it starts. */
+               if (! (brk & 4) ) {     /* If not keeping comments */
+                   if (inword == 0 && quoting) { /* If not in a word */
+                       comment = 1;    /* start a comment. */
+                       cp = bp;        /* remember where it starts. */
+                   }
                }
                break;
            }
@@ -6218,13 +6459,13 @@ CMDIRPARSE:
                /* debug(F101,"gtword echof 2","",echof); */
 #ifdef BEBOX
                 if (echof) {
-                    putchar(c);                /* echo it. */
+                   cmdecho((char) c, 0); /* Echo what was typed. */
                     fflush(stdout);
                     fflush(stderr);
                 }
 #else
-                if (echof) {           /* echo it. */
-                   putchar((CHAR)c);
+                if (echof) {
+                   cmdecho((char) c, 0); /* Echo what was typed. */
                    if (timelimit)
                      fflush(stdout);
                }
@@ -6260,19 +6501,20 @@ CMDIRPARSE:
                  blocklvl--;
             }
            if ((c == '=' || c == ':') &&
-               !kstartactive && !comment && brk && (firstnb == '/')
+               /* ^^^ */
+               !kstartactive && !comment && brk /* && (firstnb == '/') */
                ) {
                 *bp++ = (char) c;      /* Switch argument separator */
                /* debug(F111,"gtword switch argsep",cmdbuf,brk); */
 #ifdef BEBOX
                 if (echof) {
-                    putchar(c);                /* Echo it. */
+                   cmdecho((char) c, 0); /* Echo what was typed. */
                     fflush(stdout);
                     fflush(stderr);
                 }
 #else
                if (echof) {
-                   putchar((CHAR)c);
+                   cmdecho((char) c, 0); /* Echo what was typed. */
                    if (timelimit)
                      fflush(stdout);
                }
@@ -6280,7 +6522,7 @@ CMDIRPARSE:
                if ((*pp != lbrace) || (bracelvl == 0)) {
                    np = bp;
                    cmbptr = np;
-                   if (setatm(pp,0) < 0) {
+                   if (setatm(pp,2) < 0) { /* ^^^ */
                        printf("?Field too long error 1\n");
                        debug(F111,"gtword too long #1",pp,strlen(pp));
                        return(-9);
@@ -6447,7 +6689,7 @@ CMDIRPARSE:
                        && !kstartactive
                        && !comment
                        ) {
-                       putchar((CHAR)c);
+                       cmdecho((char) c, 0);
                        *bp = NUL;
                        if (setatm(pp,0) < 0) {
                            debug(F111,"gtword too long ?",pp,strlen(pp));
@@ -6546,18 +6788,32 @@ CMDIRPARSE:
                      printf("\n%s",cmprom);
                      cpx = cmdbuf;
                      while ((cx = *cpx++)) {
-#ifdef isprint
-                         putchar((CHAR) (isprint(cx) ? cx : '^'));
-#else
-                         putchar((CHAR) ((cx >= SP && cx < DEL) ? cx : '^'));
-#endif /* isprint */
+                         cmdecho(cx,0);
                      }
                      fflush(stdout);
                      continue;
                  }
+#ifndef NOLASTFILE
+                 case VT:
+                   if (lastfile) {
+                       printf("%s ",lastfile);
+#ifdef GEMDOS
+                       fflush(stdout);
+#endif /* GEMDOS */
+                       inword = cmflgs = 0;
+                       addbuf(lastfile);       /* Supply default. */
+                       if (setatm(lastfile,0) < 0) {
+                           printf("Last name too long\n");
+                           if (np) free(np);
+                           return(-9);
+                       }
+                   } else {            /* No default */
+                       bleep(BP_WARN);
+                   }
+                   return(0);
+#endif /* NOLASTFILE */
                }
 
-
 #ifdef CK_RECALL
                if (on_recall &&        /* Reading commands from keyboard? */
                    (cm_recall > 0) &&  /* Saving commands? */
@@ -6633,7 +6889,12 @@ CMDIRPARSE:
                 fflush(stderr);
             }
 #else
-            if (echof) cmdecho((char) c, 0); /* Echo what was typed. */
+#ifdef NOSPL
+            if (echof || chsrc)
+#else
+            if (echof || (echostars && chsrc))
+#endif /* NOSPL */
+             cmdecho((char) c, 0);     /* Echo what was typed. */
 #endif /* BEBOX */
         } else {                       /* This character was quoted. */
            int qf = 1;
@@ -7209,7 +7470,10 @@ cmdnewl(c) char c;
 
 static VOID
 cmdchardel() {                         /* Erase a character from the screen */
-    if (!dpx) return;
+#ifndef NOSPL
+    if (!echostars)
+#endif /* NOSPL */
+      if (!dpx) return;
 #ifdef datageneral
     /* DG '\b' is EM (^y or \031) */
     if (termtype == 1)
@@ -7234,7 +7498,15 @@ cmdecho(char c, int quote)
 cmdecho(c,quote) char c; int quote;
 #endif /* CK_ANSIC */
 { /* cmdecho */
+#ifdef NOSPL
     if (!dpx) return;
+#else
+    if (!echostars) {
+       if (!dpx) return;
+    } else {
+       c = (char)echostars;
+    }
+#endif /* NOSPL */
     /* Echo tty input character c */
     if (quote) {
        putchar(BS);
@@ -7245,7 +7517,9 @@ cmdecho(c,quote) char c; int quote;
 #else
        putchar((CHAR) ((c >= SP && c < DEL) ? c : '^'));
 #endif /* isprint */
-    } else putchar(c);
+    } else {
+       putchar(c);
+    }
 #ifdef OS2
     if (quote==1 && c==CR) putchar((CHAR) NL);
 #endif /* OS2 */
@@ -7550,7 +7824,7 @@ lookup(table,cmd,n,x) char *cmd; struct keytab table[]; int n, *x; {
 
     if (!ckstrcmp(table[n-1].kwd,cmd,cmdlen,0)) {
         if (x) *x = n-1;
-       debug(F111,"lookup",table[i].kwd,table);
+       /* debug(F111,"lookup",table[i].kwd,table); */
         return(table[n-1].kwval);
     } else return(-1);
 }
index e994843..7cd4ced 100644 (file)
--- a/ckucmd.h
+++ b/ckucmd.h
@@ -4,7 +4,7 @@
   Author: Frank da Cruz <fdc@columbia.edu>
   Columbia University Kermit Project, New York City.
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2009,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -212,8 +212,9 @@ typedef struct OFDB {
     struct FDB * fdbaddr;              /* Address of succeeding FDB struct */
     int fcode;                         /* Function code */
     char * sresult;                    /* String result */
-    int nresult;                       /* Numeric result */
+    int nresult;                       /* Integer result */
     int kflags;                                /* Keyword flags if any */
+    CK_OFF_T wresult;                  /* Long integer ("wide") result */
 } ofdb;
 
 #ifndef CKUCMD_C
@@ -230,6 +231,7 @@ extern struct OFDB cmresult;
 #define _CMKEY 5                       /* Keyword */
 #define _CMCFM 6                       /* Confirmation */
 #define _CMDAT 7                       /* Date/time */
+#define _CMNUW 8                       /* Wide version of cmnum */
 
 /* Function prototypes */
 
@@ -237,7 +239,7 @@ _PROTOTYP( int xxesc, (char **) );
 _PROTOTYP( int cmrini, (int) );
 _PROTOTYP( VOID cmsetp, (char *) );
 _PROTOTYP( VOID cmsavp, (char [], int) );
-_PROTOTYP( char * cmgetp, () );
+_PROTOTYP( char * cmgetp, (void) );
 _PROTOTYP( VOID prompt, (xx_strp) );
 _PROTOTYP( VOID pushcmd, (char *) );
 _PROTOTYP( VOID cmres, (void) );
@@ -248,6 +250,7 @@ _PROTOTYP( int cmpush, (void) );
 _PROTOTYP( int cmpop, (void) );
 _PROTOTYP( VOID untab, (char *) );
 _PROTOTYP( int cmnum, (char *, char *, int, int *, xx_strp ) );
+_PROTOTYP( int cmnumw, (char *, char *, int, CK_OFF_T *, xx_strp ) );
 _PROTOTYP( int cmofi, (char *, char *, char **, xx_strp ) );
 _PROTOTYP( int cmifi, (char *, char *, char **, int *, xx_strp ) );
 _PROTOTYP( int cmiofi, (char *, char *, char **, int *, xx_strp ) );
@@ -284,7 +287,7 @@ _PROTOTYP( int cmdconchk, (void) );
 #ifdef CK_RECALL
 _PROTOTYP( char * cmgetcmd, (char *) );
 _PROTOTYP( VOID addcmd, (char *) );
-_PROTOTYP( VOID cmaddnext, () );
+_PROTOTYP( VOID cmaddnext, (void) );
 #endif /* CK_RECALL */
 _PROTOTYP( char * cmcvtdate, (char *, int) );
 _PROTOTYP( char * cmdiffdate, (char *, char *) );
@@ -292,6 +295,13 @@ _PROTOTYP( char * cmdelta, (int,
                            int,int,int,int,int,int,int,int,int,int,int,int ));
 _PROTOTYP( char * shuffledate, (char *, int) );
 _PROTOTYP( int filhelp, (int, char *, char *, int, int) );
+_PROTOTYP( int xfilhelp, (int, char *, char *, int, int,
+                         int,
+                         char *, char *, char *, char *,
+                         CK_OFF_T, CK_OFF_T,
+                         int, int,
+                         char **) );
+_PROTOTYP( int delta2sec, (char *, long *) );
 
 #ifdef DCMDBUF
 _PROTOTYP( int cmsetup, (void) );
index 296b106..337197c 100644 (file)
--- a/ckucns.c
+++ b/ckucns.c
@@ -1,12 +1,12 @@
 #include "ckcsym.h"
-char *connv = "CONNECT Command for UNIX:select(), 8.0.135, 29 Nov 2002";
+char *connv = "CONNECT Command for UNIX:select(), 9.0.139, 1 Mar 2010";
 
 /*  C K U C N S  --  Terminal connection to remote system, for UNIX  */
 /*
   Author: Frank da Cruz <fdc@columbia.edu>,
   Columbia University Academic Information Systems, New York City.
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2010,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -135,7 +135,8 @@ extern struct ck_p ptab[];
 
 extern int local, escape, duplex, parity, flow, seslog, sessft, debses,
  mdmtyp, ttnproto, cmask, cmdmsk, network, nettype, sosi, tnlm,
- xitsta, what, ttyfd, ttpipe, quiet, backgrd, pflag, tt_crd, tn_nlm, ttfdflg,
+ xitsta, what, ttyfd, ttpipe, quiet, backgrd, pflag, tt_crd, tt_lfd,
+ tn_nlm, ttfdflg,
  tt_escape, justone, carrier, ttpty, hwparity;
 
 #ifndef NODIAL
@@ -330,20 +331,23 @@ static int printing = 0;
 #endif /* NOCSETS */
 #endif /* NOESCSEQ */
 
+/* inesc[] and oldesc[] made global 2010/03/01 for INPUT command */
+
 static int escseq = 0;                 /* 1 = Recognizer is active */
-static int inesc[2] = { 0, 0 };                /* State of sequence recognizer */
-static int oldesc[2] = { -1, -1 };     /* Previous state of recognizer */
+/* static */ int inesc[2] = { 0, 0 };  /* State of sequence recognizer */
+/* static */ int oldesc[2] = { -1, -1 }; /* Previous state of recognizer */
 
 #ifdef NOESCSEQ
+#define ES_NORMAL 0                    /* Normal, not in an escape sequence */
 #define chkaes(x,y) 0
 #else
 /*
   As of C-Kermit 5A(178), the CONNECT command skips past ANSI escape sequences
   to avoid translating the characters within them.  This allows the CONNECT
   command to work correctly with a host that uses a 7-bit ISO 646 national
-  character set, in which characters like '[' would normally be translated
-  into accented characters, ruining the terminal's interpretation (and
-  generation) of escape sequences.
+  character set, in which characters like '[' would normally be converted to
+  accented letters, ruining the terminal's interpretation (and generation)
+  of escape sequences.
 
   As of 5A(190), the CONNECT command responds to APC escape sequences
   (ESC _ text ESC \) if the user SETs TERMINAL APC ON or UNCHECKED, and the
@@ -707,6 +711,22 @@ chkaes(c,src) char c; int src;
 }
 #endif /* NOESCSEQ */
 
+VOID
+#ifdef CK_ANSIC
+LOGCHAR(char c)
+#else
+LOGCHAR(c) char c;
+#endif /* CK_ANSIC */
+/* LOGCHAR */ {                         /* Log character c to session log */
+    /* but skip over escape sequences if session log is text */
+    if (escseq) {
+       if ((sessft == XYFT_T) && (debses == 0) &&
+           (inesc[0] != ES_NORMAL || oldesc[0] != ES_NORMAL))
+         return;
+    }
+    logchar(c);
+}
+
 /*  C K C P U T C  --  C-Kermit CONNECT Put Character to Screen  */
 /*
   Output is buffered to avoid slow screen writes on fast connections.
@@ -1286,7 +1306,7 @@ conect() {
              default:
                s = "binary";
            }
-           printf("Session Log: %s, %s\r\n",sesfil,s);
+           printf("Session Log: %s, %s (%d) \r\n",sesfil,s,sessft);
        }
        if (debses) printf("Debugging Display...)\r\n");
     }
@@ -1449,7 +1469,9 @@ conect() {
 /*
   We need to activate the escape-sequence recognition feature when:
    (a) translation is elected, AND
-   (b) the local and/or remote set is a 7-bit set other than US ASCII.
+   (b) the local and/or remote set is a 7-bit set other than US ASCII;
+  Or:
+   SET SESSION-LOG is TEXT (so we can strip escape sequences out of the log);
   Or:
    SET TERMINAL APC is not OFF (handled in the next statement).
 */
@@ -1460,6 +1482,10 @@ conect() {
 #endif /* NOCSETS */
 
 #ifndef NOESCSEQ
+    if (!escseq) {                     /* 2009/10/22 */
+       if (seslog && !sessft)
+         escseq = 1;
+    }
 #ifdef CK_APC
     escseq = escseq || (apcstatus & APC_ON);
     apcactive = 0;                     /* An APC command is not active */
@@ -1468,8 +1494,9 @@ conect() {
 #ifdef XPRINT
     escseq |= tt_print;
 #endif /* XPRINT */
-    inesc[0] = ES_NORMAL;              /* Initial state of recognizer */
-    inesc[1] = ES_NORMAL;
+    /* Initial state of recognizer */
+    inesc[0] = ES_NORMAL;              /* Remote to screen */
+    inesc[1] = ES_NORMAL;              /* Keyboard to remote */
     debug(F101,"CONNECT escseq","",escseq);
 #endif /* NOESCSEQ */
 
@@ -1665,9 +1692,11 @@ conect() {
        if (deblog) {
            debug(F101,"CONNECT gotkbd","",gotkbd);
            debug(F101,"CONNECT kbc","",kbc);
+#ifdef COMMENT
 #ifndef NOSETKEY
            debug(F101,"CONNECT kmptr","",kmptr);
 #endif /* NOSETKEY */
+#endif /* COMMENT */
        }
 #endif /* DEBUG */
 
@@ -1783,7 +1812,7 @@ conect() {
            }
            if (escseq)
              apcrc = chkaes((char)c,1);
-#else
+#else  /* NOCSETS */
            outxbuf[0] = c;
            outxcount = 1;
            outxbuf[outxcount] = NUL;
@@ -1871,7 +1900,7 @@ conect() {
                            c2 = csave;
                            if (sessft == 0 && csave == '\r')
                              c2 = '\n';
-                           logchar((char)c2);
+                           LOGCHAR((char)c2);
                        }
                    }
                } else {
@@ -1889,7 +1918,6 @@ conect() {
            gotnet = 0;
            prev = c;
            c = ckcgetc(0);             /* Get next character */
-           /* debug(F101,"CONNECT c","",c); */
            if (c < 0) {                /* Failed... */
                ckcputf();              /* Flush CONNECT output buffer */
                if (msgflg) {
@@ -2054,13 +2082,17 @@ conect() {
 
            if (debses) {               /* Output character to screen */
                char *s;                /* Debugging display... */
-               s = dbchr(c);
-               while (*s)
-                 ckcputc(*s++);
+               s = dbchr(c);           /* Make char into string */
+               while (*s) {            /* Output each char from string */
+                   ckcputc(*s);
+                   if (seslog)         /* And maybe log it. */
+                     LOGCHAR((char)*s);
+                   s++;
+               }
            } else {                    /* Regular display ... */
                c &= cmask;             /* Apply Kermit-to-remote mask */
                if (seslog && sessft)   /* If binary session log */
-                 logchar((char)c);     /* log the character now. */
+                 LOGCHAR((char)c);     /* log the character now. */
 #ifndef NOXFER
 #ifdef CK_AUTODL
 /*
@@ -2222,7 +2254,7 @@ conect() {
                      continue;
                    else if (oldesc[0] == ES_GOTESC && !apcactive) {
                        ckcputc(ESC);   /* Write saved ESC */
-                       if (seslog && !sessft) logchar((char)ESC);
+                       if (seslog && !sessft) LOGCHAR((char)ESC);
                    } else if (apcrc) { /* We have an APC */
                        debug(F111,"CONNECT APC complete",apcbuf,apclength);
                        ckcputf();      /* Force screen update */
@@ -2244,20 +2276,29 @@ conect() {
 
                        ) {
                        c &= cmdmsk;    /* Apply command mask. */
+
+                       /* Handle bare carriage returns and linefeeds */
+
                        if (c == CR && tt_crd) { /* SET TERM CR-DISPLA CRLF? */
                            ckcputc(c); /* Yes, output CR */
-                           if (seslog && !sessft) logchar((char)c);
+                           if (seslog && !sessft) LOGCHAR((char)c);
                            c = LF;     /* and insert a linefeed */
                        }
+                       if (c == LF && tt_lfd) { /* SET TERM CR-DISPLA CRLF? */
+                           ckcputc(CR); /* Yes, output CR */
+                           if (seslog && !sessft) LOGCHAR((char)CR);
+                       }
+#ifndef NOESCSEQ
                        if (dontprint)  { /* Do transparent printing. */
                            dontprint = 0;
                            continue;
                        } else
-
+#endif /* NOESCSEQ */
                        ckcputc(c);     /* Write character to screen */
                    }
-                   if (seslog && !sessft) /* Handle session log. */
-                     logchar((char)c);
+                   if (seslog && !sessft) { /* Handle session log. */
+                       LOGCHAR((char)c);
+                   }
 #ifdef XPRINT
                    if (printing && !inesc[0]) {
                        /* zchout() can't be used because */
index bd866fe..776682d 100644 (file)
--- a/ckucon.c
+++ b/ckucon.c
@@ -1,13 +1,13 @@
 #include "ckcsym.h"
 
-char *connv = "CONNECT Command for UNIX:fork(), 8.0.114, 29 Nov 2002";
+char *connv = "CONNECT Command for UNIX:fork(), 9.0.116, 1 Mar 2010";
 
 /*  C K U C O N  --  Terminal connection to remote system, for UNIX  */
 /*
   Author: Frank da Cruz <fdc@columbia.edu>,
   Columbia University Academic Information Systems, New York City.
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2010,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -106,7 +106,8 @@ extern struct ck_p ptab[];
 
 extern int local, escape, duplex, parity, flow, seslog, sessft, debses,
  mdmtyp, ttnproto, cmask, cmdmsk, network, nettype, deblog, sosi, tnlm,
- xitsta, what, ttyfd, ttpipe, quiet, backgrd, pflag, tt_crd, tn_nlm, ttfdflg,
+ xitsta, what, ttyfd, ttpipe, quiet, backgrd, pflag, tt_crd, tt_lfd,
+ tn_nlm, ttfdflg,
  tt_escape, justone, carrier, hwparity;
 
 extern long speed;
@@ -234,10 +235,9 @@ static PID_T pid = (PID_T) 0;      /* Process ID of child */
 
 static int unicode = 0;
 
-static int
-  escseq = 0,                          /* 1 = Recognizer is active */
-  inesc = 0,                           /* State of sequence recognizer */
-  oldesc = -1;                         /* Previous state of recognizer */
+static int escseq = 0;                 /* 1 = Recognizer is active */
+int inesc = 0;                         /* State of sequence recognizer */
+int oldesc = -1;                       /* Previous state of recognizer */
 
 #define OUTXBUFSIZ 15
 static CHAR inxbuf[OUTXBUFSIZ+1];      /* Host-to-screen expansion buffer */
@@ -1450,6 +1450,10 @@ concld (
                              logchar((char)c);
                            c = LF;     /* and insert a linefeed */
                        }
+                       if (c == LF && tt_lfd) { /* SET TERM CR-DISPLA CRLF? */
+                           ckcputc(CR); /* Yes, output CR */
+                           if (seslog && !sessft) logchar((char)CR);
+                       }
                        ckcputc(c);     /* Write character to screen */
                    }
                    if (seslog && !sessft) /* Handle session log */
index 2f0fbfe..587a0d1 100644 (file)
--- a/ckudia.c
+++ b/ckudia.c
@@ -1,10 +1,10 @@
 #include "ckcsym.h"
-char *dialv = "Dial Command, 8.0.160, 29 Apr 2002";
+char *dialv = "Dial Command, 9.0.160, 16 Oct 2009";
 
 /*  C K U D I A         --  Module for automatic modem dialing. */
 
 /*
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2009,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -5524,7 +5524,7 @@ _dodial(threadinfo) VOID * threadinfo;
                     );
 #endif /* COMMENT */
        }
-       debug(F101,"ckudia xx_ok","",xx_ok);
+       /* debug(F101,"ckudia xx_ok","",xx_ok); */
        if (x && xx_ok) {                       /* Look for OK response */
            debug(F100,"ckudia calling xx_ok for EC","",0);
            x = (*xx_ok)(5,1);
index 298c48e..d860757 100644 (file)
--- a/ckufio.c
+++ b/ckufio.c
@@ -3,21 +3,22 @@
 #define CK_NONBLOCK                     /* See zoutdump() */
 
 #ifdef aegis
-char *ckzv = "Aegis File support, 8.0.200, 4 Mar 2004";
+char *ckzv = "Aegis File support, 9.0.215, 13 Jun 2011";
 #else
 #ifdef Plan9
-char *ckzv = "Plan 9 File support, 8.0.200, 4 Mar 2004";
+char *ckzv = "Plan 9 File support, 9.0.215, 13 Jun 2011";
 #else
-char *ckzv = "UNIX File support, 8.0.200, 4 Mar 2004";
+char *ckzv = "UNIX File support, 9.0.215, 13 Jun 2011";
 #endif /* Plan9 */
 #endif /* aegis */
 /*
   Author: Frank da Cruz <fdc@columbia.edu>,
   Columbia University Academic Information Systems, New York City,
   and others noted in the comments below.  Note: CUCCA = Previous name of
-  Columbia University Academic Information Systems.
+  Columbia University Academic Information Systems.  Note: AcIS = Previous
+  of Columbia University Information Technology.
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2011,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -45,6 +46,17 @@ char *ckzv = "UNIX File support, 8.0.200, 4 Mar 2004";
 #include "ckcxla.h"
 #endif /* NOCSETS */
 
+/* To avoid pulling in all of ckuusr.h so we copy the few needed prototypes */
+
+struct mtab {                          /* Macro table, like keyword table */
+    char *kwd;                         /* But with pointers for vals */
+    char *mval;                                /* instead of ints. */
+    short flgs;
+};
+_PROTOTYP( int mlook, (struct mtab [], char *, int) );
+_PROTOTYP( int dodo, (int, char *, int) );
+_PROTOTYP( int parser, ( int ) );
+
 #ifdef COMMENT
 /* This causes trouble in C-Kermit 8.0.  I don't remember the original */
 /* reason for this being here but it must have been needed at the time... */
@@ -237,6 +249,8 @@ extern long timezone;
 #include <sys/stat.h>
 #endif /* CIE */
 
+
+
 /* Macro to alleviate isdir() calls internal to this module */
 
 static struct stat STATBUF;
@@ -490,6 +504,9 @@ extern char * anonroot;
 static char guestpass[GUESTPASS] = { NUL, NUL }; /* Anonymous "password" */
 static int logged_in = 0;               /* Set when user is logged in */
 static int askpasswd = 0;               /* Have OK user, must ask for passwd */
+#ifdef CK_PAM
+extern int gotemptypasswd;
+#endif /* CK_PAM */
 #endif /* CK_LOGIN */
 
 #ifdef CKROOT
@@ -500,6 +517,9 @@ int ckrooterr = 0;
 
 _PROTOTYP( VOID ignorsigs, (void) );
 _PROTOTYP( VOID restorsigs, (void) );
+#ifdef SELECT
+_PROTOTYP( int ttwait, (int, int) );   /* ckutio.c */
+#endif /* SELECT */
 
 /*
   Change argument to "(const char *)" if this causes trouble.
@@ -555,7 +575,11 @@ _PROTOTYP( struct passwd * getpwent, (void) );
 #include <shadow.h>
 #endif /* CK_SHADOW */
 #ifdef CK_PAM                           /* PAM... */
+#ifdef MACOSX
+#include <pam/pam_appl.h>
+#else /* MACOSX */
 #include <security/pam_appl.h>
+#endif /* MACOSX */
 #ifndef PAM_SERVICE_TYPE                /* Defines which PAM service we are */
 #define PAM_SERVICE_TYPE "kermit"
 #endif /* PAM_SERVICE_TYPE */
@@ -861,11 +885,15 @@ static int maxnames = MAXWLD;
 #endif /* PROVX1 */
 static char sspace[SSPACE];             /* Buffer for generating filenames */
 #else /* is DYNAMIC */
+#ifdef CK_64BIT
+#define SSPACE 2000000000              /* Two billion bytes */
+#else
 #ifdef BIGBUFOK
-#define SSPACE 500000
+#define SSPACE 10000000                        /* Ten million */
 #else
-#define SSPACE 10000
+#define SSPACE 10000                   /* Ten thousand */
 #endif /* BIGBUFOK */
+#endif /* CK_64BIT */
 char *sspace = (char *)0;
 #endif /* DYNAMIC */
 static int ssplen = SSPACE;            /* Length of string space buffer */
@@ -1048,6 +1076,12 @@ logwtmp __P ((__const char *__ut_line, __const char *__ut_name,
 #endif /* HAVEUTMPX */
 #endif /* UTMPBUG */
 
+#ifdef HAVEUTMPX
+#define UTMPSTRUCT utmpx
+#else
+#define UTMPSTRUCT utmp
+#endif /* HAVEUTMPX */
+
 #ifndef WTMPFILE
 #ifdef QNX
 #define WTMPFILE "/usr/adm/wtmp.1"
@@ -1095,11 +1129,7 @@ logwtmp(const char * line, const char * name, const char * host)
 logwtmp(line, name, host) char *line, *name, *host;
 #endif /* CK_ANSIC */
 /* logwtmp */ {
-#ifdef HAVEUTMPX
-    struct utmpx ut;                    /* Needed for ut_host[] */
-#else
-    struct utmp ut;
-#endif /* HAVEUTMPX */
+    struct UTMPSTRUCT ut;
     struct stat buf;
     /* time_t time(); */
 
@@ -1143,11 +1173,20 @@ logwtmp(line, name, host) char *line, *name, *host;
             ut.ut_time = zz;
         }
 #else
+#ifdef CK_64BIT
+        {
+           /* Now (Jan 2006) we can do this for any 64-bit build */
+            time_t zz;
+            time(&zz);
+            ut.ut_time = zz;
+        }
+#else
         time(&ut.ut_time);
+#endif /* CK_64BIT */
 #endif /* LINUX */
 #endif /* HAVEUTMPX */
-        if (write(wtmpfd, (char *)&ut, sizeof(struct utmp)) !=
-            sizeof(struct utmp)) {
+        if (write(wtmpfd, (char *)&ut, sizeof(struct UTMPSTRUCT)) !=
+            sizeof(struct UTMPSTRUCT)) {
 #ifndef NOFTRUNCATE
 #ifndef COHERENT
             ftruncate(wtmpfd, buf.st_size); /* Error, undo any partial write */
@@ -1227,9 +1266,9 @@ extern char zinbuffer[], zoutbuffer[];
 #endif /* DYNAMIC */
 extern char *zinptr, *zoutptr;
 extern int zincnt, zoutcnt;
-extern int wildxpand;
+extern int wildxpand, wildena;         /* Wildcard handling */
 
-static long iflen = -1L;                /* Input file length */
+static CK_OFF_T iflen = (CK_OFF_T)-1;  /* Input file length */
 
 static PID_T pid = 0;                   /* pid of child fork */
 static int fcount = 0;                  /* Number of files in wild group */
@@ -1398,9 +1437,9 @@ zopeni(n,name) int n; char *name; {
     }
 #endif /* CKROOT */
     fp[n] = fopen(name,"r");            /* Real file, open it. */
-    debug(F111,"zopeni fopen", name, fp[n]);
+    /* debug(F111,"zopeni fopen", name, fp[n]); */
 #ifdef ZDEBUG
-    printf("ZOPENI fp[%d]=%ld\n",n,fp[n]);
+    /* printf("ZOPENI fp[%d]=%ld\n",n,fp[n]); */
 #endif /* ZDEBUG */
     ispipe[n] = 0;
 
@@ -1448,6 +1487,7 @@ zopeno(n,name,zz,fcb)
 
     char p[8];
     int append = 0;
+    int istty = 0, filefd = 0;
 
 /* As of Version 5A, the attribute structure and the file information */
 /* structure are included in the arglist. */
@@ -1474,10 +1514,12 @@ zopeno(n,name,zz,fcb)
        fp[n] = stdout;
         ispipe[n] = 0;
 #endif /* COMMENT */
+#ifdef COMMENT
 #ifdef DEBUG
         if (n != ZDFILE)
           debug(F101,"zopeno fp[n]=stdout","",fp[n]);
 #endif /* DEBUG */
+#endif /* COMMENT */
         zoutcnt = 0;
         zoutptr = zoutbuffer;
         return(1);
@@ -1501,7 +1543,6 @@ zopeno(n,name,zz,fcb)
             append = 1;
         }
     }
-
     if (xferlog
 #ifdef CKSYSLOG
         || ((ckxsyslog >= SYSLG_FC) && ckxlogging)
@@ -1510,8 +1551,37 @@ zopeno(n,name,zz,fcb)
         getfullname(name);
         debug(F110,"zopeno fullname",fullname,0);
     }
+    {
+    /* Allow tty devices to opened as output files 2009/10/20 */
+       int fd, mode = 0;
+       debug(F110,"zopeno attempting to open",name,0);
+#ifdef O_NONBLOCK
+       mode = O_NONBLOCK;
+#else
+#ifdef O_NDELAY
+       mode = O_NDELAY;
+#else
+#ifdef FNDELAY
+       mode = FNDELAY;
+#endif /* FNDELAY */
+#endif /* O_NDELAY */
+#endif /* O_NONBLOCK */
+       debug(F111,"zopeno open mode",name,mode);
+       fd = open(name,O_WRONLY,mode);
+       debug(F111,"zopeno open",name,fd); 
+       if (fd > -1) {
+           if (isatty(fd)) {
+               filefd = fd;
+               istty++;
+           }
+       }
+    }
+    debug(F111,"zopeno istty",name,istty);
     debug(F110,"zopeno fopen arg",p,0);
-    fp[n] = fopen(name,p);              /* Try to open the file */
+    if (istty)
+      fp[n] = fdopen(filefd,p);
+    else
+      fp[n] = fopen(name,p);           /* Try to open the file */
     ispipe[ZIFILE] = 0;
 
 #ifdef ZDEBUG
@@ -1520,6 +1590,7 @@ zopeno(n,name,zz,fcb)
 
     if (fp[n] == NULL) {                /* Failed */
         debug(F101,"zopeno failed errno","",errno);
+       if (istty) close(filefd);
 #ifdef CKSYSLOG
         if (ckxsyslog >= SYSLG_FC && ckxlogging)
           syslog(LOG_INFO, "file[%d] %s: %s failed (%m)",
@@ -1585,7 +1656,7 @@ zopeno(n,name,zz,fcb)
 int
 zclose(n) int n; {
     int x = 0, x2 = 0;
-    extern long ffc;
+    extern CK_OFF_T ffc;
 
     debug(F101,"zclose file number","",n);
     if (chkfn(n) < 1) return(0);        /* Check range of n */
@@ -1599,7 +1670,7 @@ zclose(n) int n; {
         x = EOF;
 #endif /* NOPUSH */
         debug(F101,"zclose zclosf","",x);
-        debug(F101,"zclose zclosf fp[n]","",fp[n]);
+        /* debug(F101,"zclose zclosf fp[n]","",fp[n]); */
     } else {
         if ((fp[n] != stdout) && (fp[n] != stdin))
           x = fclose(fp[n]);
@@ -1656,11 +1727,11 @@ zclose(n) int n; {
                         "%.24s [BUFFER WOULD OVERFLOW]\n",ctime(&timenow));
                else
                  sprintf(iksdmsg,      /* SAFE */
-                        "%.24s %d %s %ld %s %c %s %c %c %s %s %d %s\n",
+                        "%.24s %d %s %s %s %c %s %c %c %s %s %d %s\n",
                         ctime(&timenow),        /* date/time */
                         gtimer(),               /* elapsed secs */
                         s,                      /* peer name */
-                        ffc,                    /* byte count */
+                       ckfstoa(ffc),           /* byte count */
                         fnam,                  /* full pathname of file */
                         (binary ? 'b' : 'a'),   /* binary or ascii */
                         "_",                    /* options = none */
@@ -1886,7 +1957,7 @@ zinfill() {
         }
 #endif /* USE_MEMCPY */
        ckstrncpy(zinbuffer,"zinbuffer is a valid buffer",INBUFSIZE);
-       debug(F111,"ZINFILL about to call fread",zinbuffer,zinbuffer);
+       /* debug(F111,"ZINFILL about to call fread",zinbuffer,zinbuffer); */
     }
 #endif /* DEBUG */
 
@@ -1945,6 +2016,8 @@ zinfill() {
 
 /*  Z S O U T  --  Write a string out to the given file, buffered.  */
 
+/*  Returns 0 on success, -1 on failure */
+
 int
 zsout(n,s) int n; char *s; {
     int rc = 0;
@@ -1969,8 +2042,12 @@ zsout(n,s) int n; char *s; {
     }
 #endif /* IKSD */
 
-    if (n == ZSFILE)
-      return(write(fileno(fp[n]),s,(int)strlen(s)));
+    if (n == ZSFILE) {
+       int k;
+       k = strlen(s);
+       rc = write(fileno(fp[n]),s,k);
+       return((rc == k) ? 0 : -1);
+    }
     rc = fputs(s,fp[n]) == EOF ? -1 : 0;
     if (n == ZWFILE)
       fflush(fp[n]);
@@ -1979,6 +2056,8 @@ zsout(n,s) int n; char *s; {
 
 /*  Z S O U T L  --  Write string to file, with line terminator, buffered  */
 
+/*  Returns 0 on success, -1 on failure */
+
 int
 zsoutl(n,s) int n; char *s; {
     if (zsout(n,s) < 0)
@@ -1995,7 +2074,7 @@ zsoutl(n,s) int n; char *s; {
 #endif /* IKSD */
 
     if (n == ZSFILE)                    /* Session log is unbuffered */
-      return(write(fileno(fp[n]),"\n",1));
+      return(write(fileno(fp[n]),"\n",1) == 1 ? 0 : -1);
     else if (fputs("\n",fp[n]) == EOF)
       return(-1);
     if (n == ZDIFIL || n == ZWFILE)     /* Flush connection log records */
@@ -2005,8 +2084,14 @@ zsoutl(n,s) int n; char *s; {
 
 /*  Z S O U T X  --  Write x characters to file, unbuffered.  */
 
+/*  Returns number of characters written on success, -1 on failure */
+
 int
 zsoutx(n,s,x) int n, x; char *s; {
+    int k;
+    if (!s) return(0);
+    if (!*s) return(0);
+
 #ifdef IKSD
     if (inserver && !local && (n == ZCTERM || n == ZSTDIO)) {
 #ifdef COMMENT
@@ -2017,6 +2102,7 @@ zsoutx(n,s,x) int n, x; char *s; {
     }
 #endif /* IKSD */
 
+    if ((k = (int)strlen(s)) > x) x = k; /* Nothing else would make sense */
 #ifdef COMMENT
     if (chkfn(n) < 1) return(-1);
     return(write(fp[n]->_file,s,x));
@@ -2166,11 +2252,11 @@ char linkname[CKMAXPATH+1];
 #endif /* _IFLNK */
 #endif /* CKSYMLINK */
 
-long
+CK_OFF_T
 zgetfs(name) char *name; {
     struct stat buf;
     char fnam[CKMAXPATH+4];
-    long size = -1L;
+    CK_OFF_T size = (CK_OFF_T)-1;
     int x;
     int needrlink = 0;
     char * s;
@@ -2312,7 +2398,7 @@ zgetfs(name) char *name; {
   For Berkeley Unix, a file must be of type "regular" to be readable.
   Directory files, special files, and symbolic links are not readable.
 */
-long
+CK_OFF_T
 zchki(name) char *name; {
     struct stat buf;
     char * s;
@@ -2408,7 +2494,7 @@ zchki(name) char *name; {
 int
 zchko(name) char *name; {
     int i, x, itsadir = 0;
-    char *s;
+    char *s = NULL;
     char * oname;
     extern int zchkod;                  /* Used by IF WRITEABLE */
 
@@ -2456,16 +2542,52 @@ zchko(name) char *name; {
   zchkod is a global flag meaning we're checking not to see if the directory
   file is writeable, but if it's OK to create files IN the directory.
 */
-    if (!zchkod && isdir(name))         /* Directories are not writeable */
-      return(-1);
-
+    if (!zchkod && isdir(name)) {      /* Directories are not writeable */
+       debug(F111,"zchko isdir",name,1);
+       return(-1);
+    }
     s = malloc(x+3);                    /* Must copy because we can't */
     if (!s) {                           /* write into our argument. */
         fprintf(stderr,"zchko: Malloc error 46\n");
         return(-1);
     }
     ckstrncpy(s,name,x+3);
-
+#ifdef UNIX
+#ifdef NOUUCP
+    {                                  /* 2009/10/20 */
+    /* Allow tty devices to opened as output files */
+       int fd, istty = 0, mode = 0;
+       debug(F110,"zchko attempting to open",name,0);
+       /* Don't block on lack of Carrier or other modem signals */
+#ifdef O_NONBLOCK
+       mode = O_NONBLOCK;
+#else
+#ifdef O_NDELAY
+       mode = O_NDELAY;
+#else
+#ifdef FNDELAY
+       mode = FNDELAY;
+#endif /* FNDELAY */
+#endif /* O_NDELAY */
+#endif /* O_NONBLOCK */
+       debug(F111,"zchko open mode",name,mode);
+       fd = open(name,O_WRONLY,mode);  /* Must attempt to open it */
+       debug(F111,"zchko open",name,fd); 
+       if (fd > -1) {                  /* to get a file descriptor */
+           if (isatty(fd))             /* for isatty() */
+             istty++;
+           debug(F111,"zchko isatty",name,istty);
+           fd = close(fd);
+           if (istty) {
+               goto doaccess;
+           }
+       } else {
+           debug(F101,"zchko open errno","",errno); 
+           x = -1;
+       }
+    }
+#endif /* NOUUCP */
+#endif /* UNIX */
     for (i = x; i > 0; i--) {           /* Strip filename from right. */
         if (ISDIRSEP(s[i-1])) {
             itsadir = 1;
@@ -2519,6 +2641,8 @@ zchko(name) char *name; {
     if (!s[0])
       ckstrncpy(s,".",x+3);
 
+  doaccess:
+
 #ifdef SW_ACC_ID
     debug(F100,"zchko swapping ids for access()","",0);
     priv_on();
@@ -2535,7 +2659,7 @@ zchko(name) char *name; {
       debug(F111,"zchko access failed:",s,errno);
     else
       debug(F111,"zchko access ok:",s,x);
-    free(s);                            /* Free temporary storage */
+    if (s) free(s);                    /* Free temporary storage */
 
     return((x < 0) ? -1 : 0);           /* and return. */
 }
@@ -3220,7 +3344,7 @@ zxcmd(filnum,comand) int filnum; char *comand; {
         shpath = getenv("SHELL");       /* What shell? */
         if (shpath == NULL) {
             p = getpwuid( real_uid() ); /* Get login data */
-            debug(F111,"zxcmd shpath","getpwuid()",p);
+            /* debug(F111,"zxcmd shpath","getpwuid()",p); */
             if (p == (struct passwd *)NULL || !*(p->pw_shell))
               shpath = defshell;
             else shpath = p->pw_shell;
@@ -3297,8 +3421,8 @@ zclosf(filnum) int filnum; {
         return((x != 0) ? -1 : 1);
     }
 #endif /* NOPOPEN */
-    debug(F101,"zclosf fp[filnum]","", fp[filnum]);
-    debug(F101,"zclosf fp[ZSYSFN]","", fp[ZSYSFN]);
+    /* debug(F101,"zclosf fp[filnum]","", fp[filnum]); */
+    /* debug(F101,"zclosf fp[ZSYSFN]","", fp[ZSYSFN]); */
 
     if (pid != (PID_T) 0) {
         debug(F101,"zclosf killing pid","",pid);
@@ -3327,7 +3451,7 @@ zclosf(filnum) int filnum; {
     fp[filnum] = fp[ZSYSFN] = NULL;
 
     ispipe[filnum] = 0;
-    debug(F101,"zclosf fp[filnum]","",fp[filnum]);
+    /* debug(F101,"zclosf fp[filnum]","",fp[filnum]); */
 #ifdef CK_CHILD
     return(pexitstat == 0 ? 1 : -1);
 #else
@@ -3358,6 +3482,9 @@ zclosf(filnum) int filnum; {
 
   Depends on external variable wildxpand: 0 means we expand wildcards
   internally, nonzero means we call the shell to do it.
+  
+  AND in C-Kermit 8.0.212 and later, on extern wildena: 1 means wildcards
+  are enabled, 0 means disabled, the characters are taken literally.
 */
 static int xdironly = 0;
 static int xfilonly = 0;
@@ -3537,34 +3664,28 @@ zxpand(fnarg) char *fnarg; {
             fn[x] = '\0';
         }
     }
-    debug(F111,"zxpand fn 3",fn,haveonedir);
+    debug(F111,"zxpand fn 3 haveonedir",fn,haveonedir);
 /*
   The following allows us to parse a single directory name without opening
   the directory and looking at its contents.  The diractive flag is a horrible
   hack (especially since DIR /NORECURSIVE turns it off), but otherwise we'd
   have to change the API.
 */
+    debug(F111,"zxpand fn 3 diractive",fn,diractive);
     if (!diractive && haveonedir) {
-#ifdef COMMENT
-       fcount = (mtchs == NULL &&
-                 (mtchs = (char **)malloc(maxnames * sizeof(*mtchs))) == NULL)
-         ? 0 : 1;
-#else
        fcount = 0;
        if (!mtchs) {
            mtchs = (char **)malloc(maxnames * sizeof(*mtchs));
-           if (mtchs)
-             fcount = 1;
-           if (!fcount)
+           if (!mtchs)
              return(nxpand = fcount);
        }
-#endif /* COMMENT */
+       fcount = 1;
        debug(F110,"zxpand haveonedir A1",fnarg,0);
        initspace(mtchs,ssplen);
        addresult(fnarg,1);
        if (numfnd < 0) return(-1);
        mtchptr = mtchs;                /* Save pointer for next. */
-       debug(F110,"zxpand haveonedir A2",*mtchptr,0);
+       debug(F111,"zxpand haveonedir A2",*mtchptr,numfnd);
        return(nxpand = fcount);
     }
 
@@ -3713,9 +3834,9 @@ znext(fn) char *fn; {
 /*ARGSUSED*/
 int
 #ifdef CK_ANSIC
-zchkspa(char *f, long n)
+zchkspa(char *f, CK_OFF_T n)
 #else
-zchkspa(f,n) char *f; long n;
+zchkspa(f,n) char *f; CK_OFF_T n;
 #endif /* CK_ANSIC */
 /* zchkspa() */ {
     /* In UNIX there is no good (and portable) way. */
@@ -4448,12 +4569,12 @@ ziperms(f) char *f; {
 
 int
 zsattr(xx) struct zattr *xx; {
-    long k; int x;
+    CK_OFF_T k; int x;
     struct stat buf;
 
-    k = iflen % 1024L;                  /* File length in K */
-    if (k != 0L) k = 1L;
-    xx->lengthk = (iflen / 1024L) + k;
+    k = iflen % 1024;                  /* File length in K */
+    if (k) k = 1L;
+    xx->lengthk = (iflen / 1024) + k;
     xx->type.len = 0;                   /* File type can't be filled in here */
     xx->type.val = "";
     if (*nambuf) {
@@ -4887,7 +5008,9 @@ zstrdt(date,len) char * date; int len; {
             }
 #else
 #ifndef BSD44
+#ifndef NOTIMEZONE
             tmx += timezone;
+#endif /* NOTIMEZONE */
 #endif /* BSD44 */
 #endif /* Plan9 */
 #endif /* ultrix */
@@ -5224,9 +5347,6 @@ zstime(f,yy,x)
     if (!*f) return(-1);
     if (!yy) return(-1);
 
-    debug(F110,"zstime",f,0);
-    debug(F111,"zstime date",yy->date.val,yy->date.len);
-
 #ifdef CKROOT
     debug(F111,"zstime setroot",ckroot,ckrootset);
     if (ckrootset) if (!zinroot(f)) {
@@ -5724,7 +5844,7 @@ splitpath(p) char *p; {
 
     while (*p) {
         cur = (struct path *) malloc(sizeof (struct path));
-        debug(F101,"splitpath malloc","",cur);
+        /* debug(F101,"splitpath malloc","",cur); */
         if (cur == NULL) {
             debug(F100,"splitpath malloc failure","",0);
             prv -> fwd = NULL;
@@ -6086,7 +6206,7 @@ traverse(pl,sofar,endcur) struct path *pl; char *sofar, *endcur; {
     debug(F111,"traverse sofar 2",sofar,0);
 
     segisdir = ((pl -> fwd) == NULL) ? 0 : 1;
-    itswild = iswild(pl -> npart);
+    itswild = wildena ? (iswild(pl -> npart)) : 0; /* 15 Jun 2005 */
 
     debug(F111,"traverse segisdir",sofar,segisdir);
     debug(F111,"traverse itswild ",pl -> npart,itswild);
@@ -6165,7 +6285,7 @@ traverse(pl,sofar,endcur) struct path *pl; char *sofar, *endcur; {
         debug(F101,"traverse directory open() failed","",errno);
         return;
     }
-    while (read(fd, (char *)dirbuf, sizeof dir_entry))
+    while (read(fd, (char *)dirbuf, sizeof dir_entry) > 0)
 #endif /* OPENDIR */
       {                         /* Read each entry in this directory */
           int exists;
@@ -6570,17 +6690,24 @@ whoami() {
     struct passwd *p;
     _PROTOTYP(extern char * getlogin, (void) );
 
+    debug(F111,"whoami ruid A",realname,ruid);
+
     if (ruid != -1)
       return(realname);
 
     ruid = real_uid();                  /* get our uid */
+    debug(F101,"whoami ruid B","",ruid);
+    if (ruid < 0) ruid = getuid();
+    debug(F101,"whoami ruid C","",ruid);
 
   /* how about $USER or $LOGNAME? */
     if ((c = getenv(NAMEENV)) != NULL) { /* check the env variable */
         ckstrncpy(envname, c, 255);
+       debug(F110,"whoami envname",envname,0);
         if ((p = getpwnam(envname)) != NULL) {
             if (p->pw_uid == ruid) {    /* get passwd entry for envname */
                 ckstrncpy(realname, envname, UIDBUFLEN); /* uid's are same */
+               debug(F110,"whoami realname",realname,0);
                 return(realname);
             }
         }
@@ -6590,6 +6717,7 @@ whoami() {
 
     if ((c =  getlogin()) != NULL) {    /* name from utmp file */
         ckstrncpy (loginname, c, UIDBUFLEN);
+       debug(F110,"whoami loginname",loginname,0); 
         if ((p = getpwnam(loginname)) != NULL) /* get passwd entry */
           if (p->pw_uid == ruid)        /* for loginname */
             ckstrncpy(realname, envname, UIDBUFLEN); /* if uid's are same */
@@ -6598,11 +6726,13 @@ whoami() {
   /* Use first name we get for ruid */
 
     if ((p = getpwuid(ruid)) == NULL) { /* name for uid */
+       debug(F101,"whoami no username for ruid","",ruid); 
         realname[0] = '\0';             /* no user name */
         ruid = -1;
         return(NULL);
     }
     ckstrncpy(realname, p->pw_name, UIDBUFLEN);
+    debug(F110,"whoami realname from getpwuid",realname,0);
     return(realname);
 #else
     return(NULL);
@@ -6627,17 +6757,22 @@ tilde_expand(dirname) char *dirname; {
 
     debug(F111,"tilde_expand",dirname,dirname[0]);
 
-    if (dirname[0] != '~')              /* Not a tilde...return param */
-      return(dirname);
+    if (dirname[0] != '~') {              /* Not a tilde...return param */
+       debug(F000,"tilde_expand NOT TILDE","",dirname[0]);
+       return(dirname);
+    }
     if (!strcmp(olddir,dirname)) {      /* Same as last time */
-      return(oldrealdir);               /* so return old answer. */
+       debug(F110,"tilde_expand same as previous",oldrealdir,0);
+       return(oldrealdir);               /* so return old answer. */
     } else {
+       debug(F110,"tilde_expand working...","",0);
         j = (int)strlen(dirname);
         for (i = 0; i < j; i++)         /* find username part of string */
           if (!ISDIRSEP(dirname[i]))
             temp[i] = dirname[i];
           else break;
         temp[i] = '\0';                 /* tie off with a NULL */
+       debug(F111,"tilde_expand first part",temp,i);
         if (i == 1) {                   /* if just a "~" */
 #ifdef IKSD
             if (inserver)
@@ -6646,14 +6781,20 @@ tilde_expand(dirname) char *dirname; {
 #endif /* IKSD */
             {
                 char * p = whoami();
-                if (p)
-                 user = getpwnam(p);
-                else
-                 user = NULL;
+               debug(F110,"tilde_expand p",p,0);
+                if (p) {
+                   user = getpwnam(p);
+                   debug(F110,"tilde_expand getpwpam ~",user,0);
+               } else {
+                   user = NULL;
+               }
             }
         } else {
+           debug(F110,"tilde_expand ~user",&temp[1],0);
             user = getpwnam(&temp[1]);  /* otherwise on the specified user */
+           debug(F110,"tilde_expand getpwpam user",user,0);
         }
+
     }
     if (user != NULL) {                 /* valid user? */
         ckstrncpy(olddir, dirname, BUFLEN); /* remember the directory */
@@ -6782,6 +6923,9 @@ zshcmd(s) char *s; {
     return(0);
 #else
     if (nopush) return(-1);
+    if (!s) return(-1);
+    while (*s == ' ') s++;
+
     debug(F110,"zshcmd command",s,0);
 
 #ifdef aegis
@@ -6817,12 +6961,23 @@ zshcmd(s) char *s; {
 /* This allows user to specify a different shell. */
         shpath = getenv("SHELL");       /* What shell? */
        debug(F110,"zshcmd SHELL",shpath,0);
-        if (shpath == NULL) {
-            p = getpwuid( real_uid() ); /* Get login data */
-            if (p == (struct passwd *)NULL || !*(p->pw_shell))
-              shpath = defshell;
-            else shpath = p->pw_shell;
-           debug(F110,"zshcmd shpath",shpath,0);
+       {
+           int x = 0;
+           if (!shpath) {
+               x++;
+           } else if (!*shpath) {
+               x++;
+           }
+           if (x) {
+               debug(F100,"zshcmd SHELL not defined","",0);
+               p = getpwuid( real_uid() ); /* Get login data */
+               if (p == (struct passwd *)NULL || !*(p->pw_shell)) {
+                   shpath = defshell;
+               } else {
+                   shpath = p->pw_shell;
+               }
+               debug(F110,"zshcmd shpath from getpwuid",shpath,0);
+           }
         }
 #endif /* COMMENT */
 #endif /* aegis */
@@ -6831,12 +6986,17 @@ zshcmd(s) char *s; {
           if (*shptr++ == DIRSEP)
             shname = shptr;
        restorsigs();                   /* Restore ignored signals */
-       debug(F110,"zshcmd shname",shname,0);
+       debug(F110,"zshcmd execl shpath",shpath,0);
+       debug(F110,"zshcmd execl shname",shname,0);
         if (s == NULL || *s == '\0') {  /* Interactive shell requested? */
+           debug(F100,"zshcmd execl interactive","",0);
             execl(shpath,shname,"-i",NULL); /* Yes, do that */
         } else {                        /* Otherwise, */
+           debug(F110,"zshcmd execl command",s,0);
             execl(shpath,shname,"-c",s,NULL); /* exec the given command */
         }                               /* If execl() failed, */
+        debug(F101,"zshcmd errno","",errno);
+       perror(shpath);                 /* print reason and */
         exit(BAD_EXIT);                 /* return bad return code. */
 
     } else {                            /* Parent */
@@ -6852,6 +7012,7 @@ zshcmd(s) char *s; {
         istat = signal(SIGINT,SIG_IGN); /* Let the fork handle keyboard */
         qstat = signal(SIGQUIT,SIG_IGN); /* interrupts itself... */
 
+       debug(F110,"zshcmd parent waiting for child",s,0);
 #ifdef CK_CHILD
         while (((wstat = wait(&child)) != pid) && (wstat != -1))
 #else
@@ -6874,7 +7035,7 @@ zshcmd(s) char *s; {
 
 /*
   Returns:
-    0 if argument is empty or is the name of a single file;
+    0 wildcards disabled or argument is empty or is the name of a single file;
     1 if it contains wildcard characters.
   Note: must match the algorithm used by match(), hence no [a-z], etc.
 */
@@ -6882,7 +7043,9 @@ int
 iswild(filespec) char *filespec; {
     char c, *p, *f; int x;
     int quo = 0;
-    if (!filespec)
+    if (!filespec)                     /* Safety */
+      return(0);
+    if (!wildena)                      /* Wildcards disabled - 12 Jun 2005 */
       return(0);
     f = filespec;
     if (wildxpand) {                   /* Shell handles wildcarding */
@@ -6949,12 +7112,34 @@ clrdircache() {
 #endif /* ISDIRCACHE */
 
 int
+isalink(s) char *s; {
+#ifndef CKSYMLINK
+    return(0);
+#else
+    int r = 0;
+    char filbuf[CKMAXPATH+4];
+    if (readlink(s,filbuf,CKMAXPATH) > -1)
+      r = 1;
+    debug(F110,"isalink readlink",s,r);
+    return(r);
+#endif /* CKSYMLINK */
+}
+
+int
 isdir(s) char *s; {
     int x, needrlink = 0, islink = 0;
     struct stat statbuf;
     char fnam[CKMAXPATH+4];
 
     if (!s) return(0);
+    debug(F110,"isdir entry",s,0);
+#ifdef DTILDE                          /* 2005-08-13 */
+    if (*s == '~') {                   /* Starts with tilde? */
+        s = tilde_expand(s);           /* Attempt to expand tilde */
+        if (!s) s = "";
+       debug(F110,"isdir tilde_expand",s,0);
+    }
+#endif /* DTILDE */
     if (!*s) return(0);
 
 #ifdef ISDIRCACHE
@@ -7169,7 +7354,7 @@ zrmdir(path) char *path; {
 /* Z F S E E K  --  Position input file pointer */
 /*
    Call with:
-    Long int, 0-based, indicating desired position.
+    CK_OFF_T (32 or 64 bits), 0-based, indicating desired position.
    Returns:
     0 on success.
    -1 on failure.
@@ -7177,19 +7362,25 @@ zrmdir(path) char *path; {
 #ifndef NORESEND
 int
 #ifdef CK_ANSIC
-zfseek(long pos)
+zfseek(CK_OFF_T pos)
 #else
-zfseek(pos) long pos;
+zfseek(pos) CK_OFF_T pos;
 #endif /* CK_ANSIC */
 /* zfseek */ {
     zincnt = -1;                        /* Must empty the input buffer */
     debug(F101,"zfseek","",pos);
-    return(fseek(fp[ZIFILE], pos, 0)?-1:0);
+    return(CKFSEEK(fp[ZIFILE], pos, 0)?-1:0);
 }
 #endif /* NORESEND */
 
 /*  Z F N Q F P  --  Convert filename to fully qualified absolute pathname */
 
+/*
+  Given a possibly unqualified or relative file specification fn, zfnqfp()
+  returns the fully qualified filespec for the same file, returning a struct
+  that contains the length (len) of the result, a pointer (fpath) to the
+  whole result, and a pointer (fname) to where the filename starts.
+*/
 static struct zfnfp fnfp = { 0, NULL, NULL };
 
 struct zfnfp *
@@ -7586,9 +7777,10 @@ sgetpwnam(name) char *name; {
 
 #ifdef CK_SHADOW
     sp = getspnam(name);
-    debug(F111,"sgetpwnam","getspnam()",sp);
-    if (sp == NULL)
-      return (NULL);
+    if (sp == NULL) {
+        debug(F110,"sgetpwnam","getspnam() fails",0);
+       return (NULL);
+    }
 #endif /* CK_SHADOW */
 
 #ifdef HPUX10_TRUSTED
@@ -7597,7 +7789,7 @@ sgetpwnam(name) char *name; {
 #endif /* HPUX10_TRUSTED */
 
     p = getpwnam(name);
-    debug(F111,"sgetpwnam","getpwnam()",p);
+    /* debug(F111,"sgetpwnam","getpwnam()",p); */
     if (p == NULL)
       return(NULL);
     if (save.pw_name) {
@@ -7673,8 +7865,11 @@ zvuser(name) char *name; {
     int x;
     char *shell;
 #ifdef GETUSERSHELL
-    char *getusershell();
+_PROTOTYP(char * getusershell, (void) );
 #endif /* GETUSERSHELL */
+#ifndef NODCLENDUSERSHELL
+_PROTOTYP(VOID endusershell, (void) );
+#endif /* NODCLENDUSERSHELL */
 
 #ifdef CK_PAM
     int pam_status;
@@ -7768,11 +7963,15 @@ zvuser(name) char *name; {
 #ifdef GETUSERSHELL
         while ((cp = getusershell()) != NULL) {
             debug(F110,"zvuser getusershell",cp,0);
-            if (strcmp(cp, shell) == 0)
+            if ((int)strcmp(cp, shell) == 0)
               break;
         }
         debug(F100,"zvuser endusershell 1","",0);
+#ifndef NODCLENDUSERSHELL
+        (VOID) endusershell();
+#else
         endusershell();
+#endif /* NODCLENDUSERSHELL */
         debug(F100,"zvuser endusershell 2","",0);
 #else /* GETUSERSHELL */
         cp = "";                        /* Do not refuse if we cannot check */
@@ -7886,7 +8085,7 @@ checkuser(name) char *name; {
       return(1);
 
     fd = fopen(userfile ? userfile : _PATH_FTPUSERS, "r");
-    debug(F111,"checkuser userfile",userfile,fd);
+    /* debug(F111,"checkuser userfile",userfile,fd); */
     if (fd) {
         line[0] = '\0';
         while (fgets(line, sizeof(line), fd)) {
@@ -7996,8 +8195,18 @@ zsyslog() {
 #define AUTH_VALID 4
 #endif /* AUTH_VALID */
 
+#ifdef __FreeBSD__                     /* 299 This was necessary in */
+#ifndef NODCLINITGROUPS                        /* FreeBSD 4.4, don't know */
+#define NODCLINITGROUPS                        /* about other versions... */
+#endif /* NODCLINITGROUPS */            
+#endif /*  __FreeBSD__ */
+
 int
 zvpass(p) char *p; {
+#ifndef NODCLINITGROUPS
+_PROTOTYP(int initgroups, (const char *, gid_t) );
+#endif /* NODCLINITGROUPS */
+
     char *xpasswd, *salt;
     char * dir = NULL;
 #ifdef CK_PAM
@@ -8043,8 +8252,22 @@ zvpass(p) char *p; {
             }
         }
         debug(F110,"zvpass","calling pam_authenticate",0);
+#ifdef COMMENT
         if (*p)
          pam_pw = p;
+#else
+/*
+  Make IKSD authentication (using PAM) ask for a password when an
+  invalid username has been given, to avoid disclosing which account
+  names are valid. See #417247 (Debian).
+*/
+        if (*p
+#ifdef CK_LOGIN
+           || gotemptypasswd
+#endif /* CK_LOGIN */
+           )
+           pam_pw = p;
+#endif /* COMMENT */
         if ((pam_status = pam_authenticate(pamh, 0)) != PAM_SUCCESS) {
             reply = pam_strerror(pamh, pam_status);
             debug(F110,"zvpass PAM failure",reply,0);
diff --git a/ckuins.txt b/ckuins.txt
deleted file mode 100644 (file)
index 86448a3..0000000
+++ /dev/null
@@ -1,3519 +0,0 @@
-
-C-Kermit 8.0 Unix Installation Instructions
-
-   [ [1]Contents ] [ [2]C-Kermit ] [ [3]Kermit Home ]
-
-   Frank da Cruz
-   The Kermit Project
-   Columbia University
-
-      As of C-Kermit version: 8.0.211, 10 April 2004
-      This file last updated: Tue Apr 13 10:14:33 2004 (New York City
-   time)
-
-   IF YOU ARE READING A PLAIN-TEXT version of this document, note that
-   this file is a plain-text dump of a Web page. You can visit the
-   original (and possibly more up-to-date) Web page here:
-
-[4]http://www.columbia.edu/kermit/ckuins.html
-  __________________________________________________________________________
-
-CONTENTS
-
-     [5]OVERVIEW
-
-    1. [6]INTERNET QUICK START
-    2. [7]INSTALLING FROM PACKAGES
-    3. [8]INSTALLING PREBUILT BINARIES
-    4. [9]BUILDING FROM SOURCE CODE
-    5. [10]INSTALLING THE KERMIT FILES
-    6. [11]INSTALLING UNIX C-KERMIT FROM DOS-FORMAT DISKETTES
-    7. [12]CHECKING THE RESULTS
-    8. [13]REDUCING THE SIZE OF THE EXECUTABLE PROGRAM IMAGE
-    9. [14]UNIX VERSIONS
-   10. [15]DIALING OUT AND COORDINATING WITH UUCP
-   11. [16]RUNNING UNIX C-KERMIT SETUID OR SETGID
-   12. [17]CONFIGURING UNIX WORKSTATIONS
-   13. [18]BIZARRE BEHAVIOR AT RUNTIME
-   14. [19]CRASHES AND CORE DUMPS
-   15. [20]SYSLOGGING
-   16. [21]BUILDING SECURE VERSIONS OF C-KERMIT 8.0
-   17. [22]INSTALLING C-KERMIT AS AN SSH SERVER SUBSYSTEM
-  __________________________________________________________________________
-
-OVERVIEW
-
-   [ [23]Top ] [ [24]Contents ] [ [25]Next ]
-
-     WARNING: This document contains notes that have been accumulating
-     since the early 1980s. Many of the products and Unix versions
-     mentioned here have not been heard of in a long while, but that
-     does not necessarily mean they are not still running in some
-     obscure nook. 
-
-   This file contains Unix-specific information. A lot of it. Unlike most
-   other packages, C-Kermit tries very hard to be portable to every Unix
-   variety (and every release of each one) known to exist, including many
-   that are quite old, as well as to other platforms like VMS, AOS/VS,
-   VOS, OS-9, the BeBox, the Amiga, etc.
-
-   Since C-Kermit gets so deeply into the file system, i/o system, and
-   other areas that differ radically from one Unix platform to the next,
-   this means that a lot can go wrong when you try to install C-Kermit on
-   (for example) a new release of a particular variety of Unix, in which
-   certain things might have changed that C-Kermit depended upon.
-
-   This file concentrates on installation. For a description of general
-   configuration options for C-Kermit, please read the [26]Configurations
-   Options document. For troubleshooting after installation, see the
-   [27]General Hints and Tips and [28]Unix-Specific Hints and Tips
-   documents. The latter, in particular, contains lots of information on
-   lots of specific Unix platforms. If you want to work on the source
-   code, see the [29]C-Kermit Program Logic Manual
-
-   You may install C-Kermit:
-
-     * From an "[30]install package", if one is available.
-     * As a [31]prebuilt binary, if available, plus accompanying text
-       files.
-     * By building from [32]source code.
-  __________________________________________________________________________
-
-1. INTERNET QUICK START
-
-   [ [33]Top ] [ [34]Contents ] [ [35]Next ] [ [36]Previous ]
-
-   If your Unix computer is on the Internet and it has a C compiler,
-   here's how to download, build, and install C-Kermit directly from the
-   "tarballs" or Zip archives:
-
-    1. Make a fresh directory and cd to it.
-    2. Download the C-Kermit source code:
-       [37]ftp://kermit.columbia.edu/kermit/archives/cku211.tar.Z
-       (compress format) or
-       [38]ftp://kermit.columbia.edu/kermit/archives/cku211.tar.gz
-       (gunzip format).
-    3. Uncompress the compressed tar file with "uncompress" or "gunzip",
-       according to which type of compressed file you downloaded. (If you
-       don't understand this, you could download a (much larger)
-       uncompressed tar archive directly:
-       [39]ftp://kermit.columbia.edu/kermit/archives/cku211.tar
-    4. Now type "tar xvf cku211.tar" to unpack the individual files from
-       the tar archive.
-    5. Type "rm cku211.tar" to get rid of the tar archive, which is no
-       longer needed.
-    6. Read the comments at the top of the makefile to find out which
-       target to use and then type the appropriate "make" command, such
-       as "make linux", "make solaris8", etc.
-    7. This produces a binary in your current directory called "wermit".
-       Start it by typing "./wermit" and [40]try it out to make sure it
-       works. Then read [41]Section 5 for how to install it, or simply
-       copy the wermit binary to the desired public directory, rename it
-       to kermit, and give it the needed permissions (and, if it is going
-       to be used to dial out, give it the same group and owner and
-       permissions as the cu, tip, or minicom program).
-
-   For secure installations, see [42]Sections 5 and [43]16.
-  __________________________________________________________________________
-
-2. INSTALLING FROM PACKAGES
-
-   [ [44]Top ] [ [45]Contents ] [ [46]Next ] [ [47]Previous ]
-
-   Various Unix varieties -- Linux, Solaris, AIX, etc -- now incorporate
-   the idea of "install packages", and many users expect to find all new
-   applications in this format. A selection of install packages might be
-   available for any given release of C-Kermit, but there is a tradeoff
-   between convenience and safety. Unix presents several notable problems
-   to the builder of install packages:
-
-    a. Since C-Kermit is portable to many non-Unix platforms (VMS, VOS,
-       AOS/VS, etc), some of the files in the C-Kermit distribution do
-       not fit into the Unix application model. In particular, C-Kermit
-       includes some plain text files (described in [48]Section 5) and
-       Unix has no standard place to put such files. Typical Unix package
-       managers do not allow for them. Where should they go, and how will
-       the user know where to find them?
-    b. Installation of any program that will be used to make modem calls
-       requires some important decisions from the installer regarding
-       security and privilege.
-
-   Item (b) is discussed at length in [49]Sections 10 and [50]11 of this
-   document, but the package-related aspects are also given here. The
-   basic problem is that Unix dialout devices and the UUCP "lock files"
-   that regulate contention for them (described in [51]Section 10) are
-   usually protected against "world". Therefore, the install procedure
-   must either run as root in order to give the Kermit binary the
-   required permissions, group, and/or owner, or else the dialout devices
-   and associated directories must be open for group or world reading and
-   writing. Otherwise, the Kermit program just installed WILL NOT WORK
-   for dialing out.
-
-   Thus, a well-crafted installation procedure should present the options
-   and allow the installer to choose the method, if any, for regulating
-   access to the dialout devices:
-
-    a. Check the permissions of the lockfile directory and the dialout
-       devices. If they do not allow group or world R/W access, then:
-    b. "Your UUCP lockfile directory and/or dialout devices require
-       privilege to access. You must either change their permissions or
-       install Kermit with privileges."
-    c. "If you wish to install Kermit with privileges, it will be given
-       the same owner, group, and permissions as the cu program so it can
-       use the dialout devices."
-    d. If they choose (c) but the user is not root, give a message that
-       the install procedure can be run only by root and then quit.
-
-   It should go without saying, of course, that any binaries that are to
-   be included in an install package should be built fresh on the exact
-   platform (e.g. Red Hat 8.0 on Intel) for which the package is
-   targeted; prebuilt binaries ([52]next section) from other sites are
-   likely to have library mismatches. [53]CLICK HERE for more about
-   building C-Kermit install packages.
-
-   The Kermit Project does not have the resources or the expertise to
-   make install packages for every platform. Most install packages,
-   therefore, are contributed by others, and they do not necessarily
-   follow the guidelines given above. Pay attention to what they do.
-
-   If you are an end user who has obtained a C-Kermit install package for
-   a particular platform, you should be aware that some additional steps
-   might needed if you want to use Kermit to dial out. Read [54]Section
-   10 for details.
-  __________________________________________________________________________
-
-3. INSTALLING PREBUILT BINARIES
-
-   [ [55]Top ] [ [56]Contents ] [ [57]Next ] [ [58]Previous ]
-
-   Hundreds of prebuilt C-Kermit binaries are available on the CDROM in
-   the BINARY tree [NOTE: The C-Kermit CDROM is still for version 7.0],
-   and at our ftp site in the [59]kermit/bin area (with names starting
-   with "ck"), also accessible on the [60]C-Kermit website. To install a
-   prebuilt binary:
-
-    a. Rename the binary to "wermit".
-    b. Make sure it works; some tests are suggested in [61]Section 7.
-    c. Follow steps (b) through (e) in [62]Section 4.
-    d. Install related files as described in [63]Section 5.
-
-   But first... Please heed the following cautions:
-
-    a. If you pick the wrong binary, it won't work (or worse).
-    b. Even when you pick the appropriate binary, it still might not work
-       due to shared-library mismatches, etc. (see [64]Section 4.0).
-    c. Don't expect a binary built on or for version n of your OS to work
-       on version n - x (where x > 0). However, it is usually safe to run
-       a binary built on (or for) an older OS release on a newer one.
-
-   Therefore, it is better to build your own binary from source code
-   ([65]next section) if you can. But since it is increasingly for Unix
-   systems (not to mention VMS and other OS's) to be delivered without C
-   compilers, it is often impractical. In such cases, try the most
-   appropriate prebuilt binary or binaries, and if none of them work,
-   [66]contact us and we'll see what we can do to help.
-  __________________________________________________________________________
-
-4. BUILDING FROM SOURCE CODE
-
-   [ [67]Top ] [ [68]Contents ] [ [69]Next ] [ [70]Previous ]
-
-   Also see: [71]Section 8 and [72]Section 9.
-
-   C-Kermit is designed to be built and used on as many platforms as
-   possible: Unix and non-Unix, old and new (and ancient), ANSI C and
-   K&R. The Unix version does not use or depend on any external tools for
-   building except the "make" utility, the C compiler, and the linker. It
-   does not use any automated configuration tools such as configure,
-   autoconf, automake, libtool, etc. Everything in C-Kermit has been
-   built by hand based on direct experience or reports or contributions
-   from users of each platform.
-
-   The [73]C-Kermit makefile contains the rules for building the program
-   for each of the hundreds of different kinds of Unix systems that
-   C-Kermit attempts to support. It covers all Unix variations since
-   about 1980 -- pretty much everything after Unix V6. Separate makefiles
-   are used for [74]Plan 9 and [75]2.x BSD.
-
-   Prerequisites:
-
-     * The C compiler, linker, and make program must be installed.
-     * The C libraries and header files must be installed (*).
-     * The C-Kermit source code and makefile in your current directory.
-     * The C-Kermit text files ([76]Section 5) in your current directory.
-
-     * This is becoming problematic in this new age of "selective
-       installs" e.g. of Linux packages. C-Kermit builds will often fail
-       because replying "no" to some obscure Linux installation option
-       will result in missing libraries or header files. Ditto on
-       platforms like AIX and Solaris that don't come with C compilers,
-       and then later have gcc installed, but are still missing crucial
-       libraries, like libm (math).
-
-   Plus:
-
-     * For TCP/IP networking support, the sockets library and related
-       header files must be installed.
-     * The math library for floating-point arithmetic support (can be
-       deselected by adding -DNOFLOAT to CFLAGS and removing -lm from
-       LIBS).
-     * Many and varied security libraries for building a secure version
-       (Kerberos, SSL/TLS, SRP, Zlib,...) These are required only if you
-       select a secure target.
-     * For the curses-based fullscreen file-ransfer display, the curses
-       or ncurses header file(s) and library, and probably also the
-       termcap and/or termlib library. Note that the names and locations
-       of these files and libraries are likely to change capriciously
-       with every new release of your Unix product. If you discover that
-       the C-Kermit build procedure fails because your curses and/or
-       termxxx headers or libraries are not named or located as expected,
-       please [77]let us know. In the meantime, work around by installing
-       symlinks.
-     * IMPORTANT: Modern Linux distributions might give you the choice
-       during installation of whether to install the "ncurses development
-       package" (perhaps called "ncurses-devel"). If you did not install
-       it, you won't be able to build C-Kermit with curses support
-       included. In this case, either go back and install ncurses, or
-       else choose (or create) a non-curses makefile target for your
-       platform. To install the ncurses developers tools in Red Hat
-       Linux, do:
-
-mount redhat cdrom
-goto RedHat/RPMS
-rpm -ivh ncurses-devel*.rpm
-or to have the exact name ls ncurse* and load as
-rpm -ivh filename
-then leave the cdrom and unmount it.
-
-     * In AIX you might have to go back and install any or all of:
-
-bos.adt.base
-bos.adt.include
-bos.adt.lib
-bos.adt.libm
-bos.adt.utils
-
-       from the first installation CD.
-
-   The makefile might need to be renamed from ckuker.mak to makefile.
-   Directions:
-
-    a. Type "make xxx" where xxx is the name of the makefile target most
-       appropriate to your platform, e.g. "make linux", "make aix43",
-       etc. Read the [78]comments at the top of the makefile for a
-       complete list of available targets (it's a long list).
-    b. Test the resulting 'wermit' file (see [79]Section 7 for
-       suggestions). If it's OK, proceed; otherwise [80]notify us.
-
-     NOTE: steps (c) through (e) can be accomplished using the
-     [81]makefile 'install' target as described in [82]Section 5.4. 
-    c. Rename the 'wermit' file to 'kermit', copy it to the desired
-       binary directory (such as /usr/local/bin or /opt/something), and
-       if it is to be used for dialing out, give it the same owner,
-       group, and permissions as the 'cu' program (IMPORTANT: read
-       [83]Sections 10 and [84]11 for details).
-    d. Install the man page, ckuker.nr, with your other man pages.
-    e. Install the accompanying text files (see [85]Section 5).
-    f. If you want C-Kermit to also offer a Telnet command-line
-       personality, make a symbolic link as follows:
-
-cd directory-where-kermit-binary-is
-ln -s kermit telnet
-
-       If you want C-Kermit to be the default Telnet client, make sure
-       the directory in which you created the symlink is in the PATH
-       ahead of the where the regular Telnet client is.
-    g. If you want C-Kermit to also offer an FTP command-line
-       personality, make a symlink called "ftp" as in (f).
-    h. If you want C-Kermit to also offer an FTTP command-line
-       personality, make a symlink called "http" as in (f).
-    i. If you want to offer an Internet Kermit Service, follow the
-       directions in the [86]IKSD Administrator's Guide.
-    ________________________________________________________________________
-
-  4.0. Special Considerations for C-Kermit 8.0
-
-   [ [87]Top ] [ [88]Contents ] [ [89]Next ]
-
-   Also see: [90]C-Kermit Configuration Options
-
-   SECTION CONTENTS
-
-4.1. [91]The Unix Makefile
-4.2. [92]The C-Kermit Initialization File
-4.3. [93]The 2.x BSD Makefile
-4.4. [94]The Plan 9 Makefile
-4.5. [95]Makefile Failures
-
-   (Also see the [96]Configurations Options document, [97]Section 8).
-
-   Lots of new features have been added in versions 7.0 and 8.0 that
-   require access to new symbols, APIs, libraries, etc, and this will no
-   doubt cause problems in compiling, linking, or execution on platforms
-   where 6.0 and earlier built without incident. This section contains
-   what we know as of the date of this file.
-
-   The first category concerns the new Kermit Service Daemon (IKSD; see
-   the [98]IKSD Administrator's Guide for details):
-
-   The wtmp File
-          When C-Kermit is started as an IKSD (under inetd), it makes
-          syslog and wtmp entries, and also keeps its own ftpd-like log.
-          The code assumes the wtmp log is /var/log/wtmp on Linux and
-          /usr/adm/wtmp elsewhere. No doubt this assumption will need
-          adjustment. Use -DWTMPFILE=path to override at compile time
-          (there is also a runtime override). See [99]iksd.html for
-          details.
-
-   UTMP, utsname(), etc
-          C-Kermit 7.0 gets as much info as it can about its job --
-          mainly for IKSD logging -- from utmp. But of course utmp
-          formats and fields differ, and for that matter, there can be
-          two different header files, <utmp.h> and <utmpx.h>. Look for
-          HAVEUTMPX and HAVEUTHOST in [100]ckufio.c and let me know of
-          any needed adjustments.
-
-   Password lookup
-          IKSD needs to authenticate incoming users against the password
-          list. In some cases, this requires the addition of -lcrypt
-          (e.g. in Unixware 2.x). In most others, the crypt functions are
-          in the regular C library. If you get "crypt" as an unresolved
-          symbol at link time, add -lcrypt to LIBS. If your site has
-          local replacement libraries for authentication, you might need
-          a special LIBS clause such as "LIBS=-L/usr/local/lib -lpwent".
-
-          These days most Unix systems take advantage of shadow password
-          files or Plugable Authentication Modules (PAM). If your system
-          uses shadow passwords you must add -DCK_SHADOW to the CFLAGS
-          list. If your system requires PAM you must add -DCK_PAM to the
-          CFLAGS and -lpam -ldl to LIBS.
-
-   getusershell()
-          This is called by the IKSD at login time to see if a user has
-          been "turned off". But many Unix platforms lack this function.
-          In that case, you will get unresolved symbol reports at link
-          time for _getusershell, _endusershell; to work around, add
-          -DNOGETUSERSHELL.
-
-   initgroups()
-          This is called by IKSD after successful authentication. But
-          some platforms do not have this function, so obviously it can't
-          be called there, in which case add -DNOINITGROUPS.
-
-   setreuid(), setreuid(), setregid() not found or "deprecated"
-          Find out what your Unix variety wants you to use instead, and
-          make appropriate substitutions in routine zvpass(), module
-          [101]ckufio.c, and [102]let us know.
-
-   printf()
-          IKSD installs a printf() substitute to allow redirection of
-          printf-like output to the connection. However, this can
-          conflict with some curses libraries. In this case, separate
-          binaries must be built for IKSD and non-IKSD use.
-
-   If you encounter difficulties with any of the above, and you are not
-   interested in running C-Kermit as an IKSD, then simply add NOIKSD to
-   CFLAGS and rebuild. Example:
-
-make sco286
-(get lots of errors)
-make clean
-make sco286 "KFLAGS=-DNOIKSD"
-
-   Some non-IKSD things to watch out for:
-
-   Return type of main()
-          The main() routine is in [103]ckcmai.c. If you get complaints
-          about "main: return type is not blah", define MAINTYPE on the
-          CC command line, e.g.:
-
-make xxx "KFLAGS=-DMAINTYPE=blah
-
-          (where blah is int, long, or whatever). If the complaint is
-          "Attempt to return a value from a function of type void" then
-          add -DMAINISVOID:
-
-make xxx "KFLAGS=-DMAINISVOID=blah
-
-   DNS Service Records
-          This feature allows a remote host to redirect C-Kermit to the
-          appropriate socket for the requested service; e.g. if C-Kermit
-          requests service "telnet" and the host offers Telnet service on
-          port 999 rather than the customary port 23. If you get
-          compile-time complaints about not being able to find
-          <resolv.h>, <netdb.h>, or <arpa/nameser.h>, add -DNO_DNS_SRV to
-          CFLAGS. If you get link-time complaints about unresolved
-          symbols res_search or dn_expand, try adding -lresolve to LIBS.
-
-   \v(ipaddress)
-          If "echo \v(ipaddress)" shows an empty string rather than your
-          local IP address, add -DCKGHNLHOST to CFLAGS and rebuild.
-
-   <sys/wait.h>
-          If this file can't be found at compile time, add -DNOREDIRECT
-          to CFLAGS. This disables the REDIRECT and PIPE commands and
-          anything else that needs the wait() system service.
-
-   syslog()
-          C-Kermit can now write syslog records. Some older platforms
-          might not have the syslog facility. In that case, add
-          -DNOSYSLOG. Others might have it, but require addition of
-          -lsocket to LIBS (SCO OSR5 is an example). See [104]Section 15.
-
-   putenv()
-          If "_putenv" comes up as an undefined symbol, add -DNOPUTENV to
-          CFLAGS and rebuild.
-
-   "Passing arg1 of 'time' from incompatible pointer"
-          This is a mess. See the mass of #ifdefs in the appropriate
-          module, [105]ckutio.c or [106]ckufio.c.
-
-   gettimeofday()
-          Wrong number of arguments. On most platforms, gettimeofday()
-          takes two arguments, but on a handful of others (e.g. Motorola
-          System V/88 V4, SNI Reliant UNIX 5.43, etc) it takes one. If
-          your version of gettimeofday() is being called with two args
-          but wants one, add -DGTODONEARG.
-
-   "Assignment makes pointer from integer without a cast"
-          This warning might appear in [107]ckutio.c or [108]ckufio.c.
-          (or elsewhere), and usually can be traced to the use of a
-          system or library function that returns a pointer but that is
-          not declared in the system header files even though it should
-          be. Several functions are commonly associated with this error:
-
-          + getcwd(): Add -DDCLGETCWD to CFLAGS and rebuild.
-          + popen() : Add -DDCLPOPEN to CFLAGS and rebuild.
-          + fdopen(): Add -DDCLFDOPEN to CFLAGS and rebuild.
-
-   "Operands of = have incompatible types"
-   "Incompatible types in assignment"
-          If this comes from [109]ckcnet.c and comes from a statement
-          involving inet_addr(), try adding -DINADDRX to CFLAGS. If that
-          doesn't help, then try adding -DNOMHHOST.
-
-   Complaints about args to get/setsockopt(), getpeername(),
-          getsockname()
-          These are all in [110]ckcnet.c. Different platforms and OS's
-          and versions of the same OS change this all the time: int,
-          size_t, unsigned long, etc. All the affected variables are
-          declared according to #ifdefs within ckcnet.c, so find the
-          declarations and adjust the #ifdefs accordingly.
-
-   size_t
-          In case of complaints about "unknown type size_t", add
-          -DSIZE_T=int (or other appropriate type) to CFLAGS.
-
-   'tz' undefined
-   Use of undefined enum/struct/union 'timezone'
-          Left of 'tv_sec' specifies undefined struct/union 'timeval' And
-          similar complaints in [111]ckutio.c: Add -DNOGFTIMER and/or
-          -DNOTIMEVAL.
-
-   Symlinks
-          The new built-in DIRECTORY command should show symlinks like
-          "ls -l" does. If it does not, check to see if your platform has
-          the lstat() and readlink() functions. If so, add -DUSE_LSTAT
-          and -DCKSYMLINK to CFLAGS and rebuild. On the other hand, if
-          lstat() is unresolved at link time, add -DNOLSTAT to CFLAGS. If
-          readlink() is also unresolved, add -DNOSYMLINK.
-
-   realpath()
-          Link-time complains about realpath() -- find the library in
-          which it resides and add it to LIBS (example for Unixware 7.1:
-          "-lcudk70") or add -DNOREALPATH to CFLAGS and rebuild. If built
-          with realpath() but debug log file is truncated or mangled,
-          ditto (some realpath() implementations behave differently from
-          others). If built with realpath() and seemingly random core
-          dumps occur during file path resolution, ditto.
-
-   Failure to locate header file <term.h>
-          Usually happens on Linux systems that have the C compiler
-          installed, but not the ncurses package (see comments about
-          selective installs above). Go back and install ncurses, or use
-          "make linuxnc" (Linux No Curses).
-
-   "Can't find shared library libc.so.2.1"
-   "Can't find shared library libncurses.so.3.0", etc...
-          You are trying to run a binary that was built on a computer
-          that has different library versions than your computer, and
-          your computer's loader is picky about library version numbers.
-          Rebuild from source on your computer.
-
-   Time (struct tm) related difficulties:
-          Errors like the following:
-
-"ckutio.c", line 11994: incomplete struct/union/enum tm: _tm
-"ckutio.c", line 11995: error: cannot dereference non-pointer type
-"ckutio.c", line 11995: error: assignment type mismatch
-"ckutio.c", line 11997: warning: using out of scope declaration: localtime
-"ckutio.c", line 11997: error: unknown operand size: op "="
-"ckutio.c", line 11997: error: assignment type mismatch
-"ckutio.c", line 11998: error: undefined struct/union member: tm_year
-"ckutio.c", line 12000: error: undefined struct/union member: tm_mon
-"ckutio.c", line 12001: error: undefined struct/union member: tm_mday
-"ckutio.c", line 12002: error: undefined struct/union member: tm_hour
-"ckutio.c", line 12003: error: undefined struct/union member: tm_min
-"ckutio.c", line 12004: error: undefined struct/union member: tm_sec
-
-          are due to failure to include the appropriate time.h header
-          files. Unix platforms generally have one or more of the
-          following: <time.h>, <sys/time.h>, and <sys/timeb.h>. Any
-          combination of these might be required. Defaults are set up for
-          each makefile target. The defaults can be corrected on the CC
-          command line by adding the appropriate definition from the
-          following list to CFLAGS:
-
--DTIMEH         Include <time.h>
--DNOTIMEH       Don't include <time.h>
--DSYSTIMEH      Include <sys/time.h>
--DNOSYSTIMEH    Don't include <sys/time.h>
--DSYSTIMEBH     Include <sys/timeb.h>
--DNOSYSTIMEBH   Don't include <sys/timeb.h>
-
-          Note that <sys/timeb.h> is relatively scarce in the System V
-          and POSIX environments; the only platform of recent vintage
-          where it was/is used is OSF/1 and its derivatives (Digital Unix
-          and Tru64 Unix).
-
-   Struct timeval and/or timezone not declared:
-          In some cases, merely including the appropriate time.h header
-          files is still not enough. POSIX.1 does not define the timeval
-          struct, and so the items we need from the header are protected
-          against us by #ifndef _POSIX_SOURCE or somesuch. In this case,
-          we have to declare the timeval (and timezone) structs
-          ourselves. To force this, include -DDCLTIMEVAL in CFLAGS.
-
-   Warnings about dn_expand() Argument #4
-          WARNING: argument is incompatible with prototyp. It's the old
-          char versus unsigned char stupidity again. Try to find a
-          compiler switch like GCC's "-funsigned-char". Failing that, add
-          -DCKQUERYTYPE=xxx to CFLAGS, where xxx is whatever 'man
-          dn_expand' tells you the type of the 4th argument should be
-          (presumably either char or unsigned char; in the latter case
-          use CHAR to avoid confusion caused by multiple words.
-
-   Switch Table Overflow (in [112]ckcuni.c)
-          Add -DNOUNICODE to CFLAGS.
-
-   Compile-time warnings about ck_out() or tgetstr() or tputs():
-          Easy solution: Add -DNOTERMCAP to CFLAGS. But then you lose the
-          SCREEN function. Real solution: Try all different combinations
-          of the following CFLAGS:
-
--DTPUTSARGTYPE=char    -DTPUTSFNTYPE=int
--DTPUTSARGTYPE=int     -DTPUTSFNTYPE=void
-
-          Until the warnings go away, except maybe "ck_outc: return with
-          a value in a function returning void", and in that case also
-          add -DTPUTSISVOID.
-
-   "Passing arg 1 of to tputs() makes pointer from integer without a
-          cast":
-          Add -DTPUTSARG1CONST to CFLAGS.
-
-   "Undefined symbol: dup2"
-          Add -DNOZEXEC to CFLAGS.
-
-   "header file 'termcap.h' not found"
-          Add -DNOHTERMCAP to CFLAGS.
-
-   Other difficulties are generally of the "where is curses.h and what is
-   it called this week?" variety (most easily solved by making symlinks
-   in the include and lib directories), or overzealous complaints
-   regarding type mismatches in function calls because of the totally
-   needless and silly signed versus unsigned char conflict (*), etc. In
-   any case, please send any compilation or linking warnings or errors to
-   the author, preferably along with fixes.
-
-     * C-Kermit does not use the signed property of chars at all
-       anywhere, ever. So if all chars and char *'s can be made unsigned
-       at compile time, as they can in gcc with "-funsigned-char", they
-       should be.
-
-   IMPORTANT: If you find any of these hints necessary for a particular
-   make target (or you hit upon others not listed here), PLEASE SEND A
-   REPORT TO:
-
-[113]kermit-support@columbia.edu
-    ________________________________________________________________________
-
-  4.1. The Unix Makefile
-
-   [ [114]Top ] [ [115]Contents ] [ [116]Section Contents ] [ [117]Next ]
-   [ [118]Previous ]
-
-   If your distribution does not contain a file with the name "makefile"
-   or "Makefile", then rename the file called ckuker.mak to makefile:
-
-mv ckuker.mak makefile
-
-   Then type "make xxx", where xxx is the platform you want to build
-   C-Kermit for. These are listed in the [119]comments at the top of the
-   makefile. For example, to build C-Kermit for Linux, type:
-
-make linux
-
-   Here are some typical examples:
-
-     Target    Description
-     linux     Linux, any version on any hardware platform
-     openbsd   OpenBSD, any version on any hardware platform
-     aix43     AIX 4.3
-     aix43g    AIX 4.3, built with gcc
-     solaris9  Solaris 9
-     solaris9g Solaris 9 built with gcc
-     hpux1100  HP-UX 11-point-anything
-
-   The makefile is quite long, and at least two versions of Unix, SCO
-   Xenix/286 and 2.x BSD, cannot cope with its length. An attempt to
-   "make sco286" gives the message "Make: Cannot alloc mem for env..
-   Stop". Solution: edit away some or all of the nonrelevant material
-   from the makefile. (A separate version of the makefile is provided for
-   BSD 2.x: ckubs2.mak but C-Kermit 8.0 can't be built for BSD 2.x -- it
-   has simply grown too large.)
-
-   Some make programs reportedly cannot handle continued lines (lines
-   ending in backslash (\)). If you have a problem with the makefile, try
-   editing the makefile to join the continued lines (remove the
-   backslashes and the following linefeed).
-
-   Other makefile troubles may occur because tabs in the makefile have
-   somehow been converted to spaces. Spaces and tabs are distinct in Unix
-   makefiles.
-
-   Similarly, carriage returns might have been added to the end of each
-   line, which also proves confusing to most Unix versions of make.
-
-   Check to see if there are comments about your particular version in
-   its makefile target itself. In a text editor such as EMACS or VI,
-   search for the make entry name followed by a colon, e.g. "linux:" (if
-   you really are building C-Kermit for Linux, do this now).
-
-   Check to see if there are comments about your particular version in
-   the [120]ckubwr.txt file ([121]CLICK HERE for the Web version).
-
-   If you have trouble with building [122]ckwart.c, or running the
-   resulting wart preprocessor program on [123]ckcpro.w:
-
-    1. Just "touch" the [124]ckcpro.c file that comes in the distribution
-       and then give the "make" command again, or:
-    2. Compile ckwart.c "by hand": cc -o wart ckwart.c, or:
-    3. Try various other tricks. E.g. one Linux user reported that that
-       adding the "static" switch to the rule for building wart fixed
-       everything:
-
-wart: ckwart.$(EXT)
-        $(CC) -static -o wart ckwart.$(EXT) $(LIBS)
-
-   If your compiler supports a compile-time option to treat ALL chars
-   (and char *'s, etc) as unsigned, by all means use it -- and send me
-   email to let me know what it is (I already know about gcc
-   -funsigned-char).
-
-   To add compilation options (which are explained later in this
-   document) to your makefile target without editing the makefile,
-   include "KFLAGS=..." on the make command line, for example:
-
-make linux KFLAGS=-DNODEBUG
-make bsd "KFLAGS=-DKANJI -DNODEBUG -DNOTLOG -DDYNAMIC -UTCPSOCKET"
-
-   Multiple options must be separated by spaces. Quotes are necessary if
-   the KFLAGS= clause includes spaces. The KFLAGS are added to the end of
-   the CFLAGS that are defined in the selected makefile target. For
-   example, the "bsd" entry includes -DBSD4 -DTCPSOCKET, so the second
-   example above compiles Kermit with the following options:
-
--DBSD4 -DTCPSOCKET -DKANJI -DNODEBUG -DNOTLOG -DDYNAMIC -UTCPSOCKET
-
-   (Notice how "-UTCPSOCKET" is used to negate the effect of the
-   "-DTCPSOCKET" option that is included in the makefile target.)
-
-   WARNING: Be careful with KFLAGS. If you build C-Kermit, change some
-   files, and then run make again using the same make entry but
-   specifying different KFLAGS than last time, make won't detect it and
-   you could easily wind up with inconsistent object modules, e.g. some
-   of them built with a certain option, others not. When in doubt, "make
-   clean" first to make sure all your object files are consistent.
-   Similarly, if you change CFLAGS, LIBS, or any other items in the
-   makefile, or you rebuild using a different makefile target, "make
-   clean" first.
-
-   If you create a new makefile target, use static linking if possible.
-   Even though this makes your C-Kermit binary bigger, the resulting
-   binary will be more portable. Dynamically linked binaries tend to run
-   only on the exact configuration and version where they were built; on
-   others, invocation tends to fail with a message like:
-
-Can't find shared library "libc.so.2.1"
-    ________________________________________________________________________
-
-  4.2. The C-Kermit Initialization File
-
-   [ [125]Top ] [ [126]Contents ] [ [127]Section Contents ] [ [128]Next ]
-   [ [129]Previous ]
-
-   (This section is obsolete.) Read [130]Section 5 about the
-   initialization file.
-    ________________________________________________________________________
-
-  4.3. The 2.x BSD Makefile
-
-   [ [131]Top ] [ [132]Contents ] [ [133]Section Contents ] [ [134]Next ]
-   [ [135]Previous ]
-
-     This section is obsolete. C-Kermit 6.0 was the last release that
-     could be built on PDP-11 based BSD versions.
-    ________________________________________________________________________
-
-  4.4. The Plan 9 Makefile
-
-   [ [136]Top ] [ [137]Contents ] [ [138]Section Contents ] [ [139]Next ]
-   [ [140]Previous ]
-
-   Use the separate makefile [141]ckpker.mk. NOTE: The Plan 9 version of
-   C-Kermit 8.0 has not yet been built. There should be no impediment to
-   building it. However, even when built successfully, certain key
-   features are missing, notably TCP/IP networking.
-    ________________________________________________________________________
-
-  4.5. Makefile Failures
-
-   [ [142]Top ] [ [143]Contents ] [ [144]Section Contents ] [
-   [145]Previous ]
-
-   First, be sure the source files are stored on your current disk and
-   directory with the right names (in lowercase). Second, make sure that
-   the makefile itself does not contain any lines with leading spaces:
-   indented lines must all start with horizontal TAB, and no spaces.
-
-   Then make sure that your Unix PATH is defined to find the appropriate
-   compiler for your makefile target. For example, on SunOS systems,
-   "make sunos41" builds C-Kermit for the BSD environment, and assumes
-   that /usr/ucb/cc will be used for compilation and linking. If your
-   PATH has /usr/5bin ahead of /usr/ucb, you can have problems at compile
-   or link time (a commonly reported symptom is the inability to find
-   "ftime" during linking). Fix such problems by redefining your Unix
-   PATH, or by specifying the appropriate "cc" in CC= and CC2= statements
-   in your makefile target.
-
-   During edits 166-167, considerable effort went into making C-Kermit
-   compilable by ANSI C compilers. This includes prototyping all of
-   C-Kermit's functions, and including the ANSI-defined system header
-   files for system and library functions, as defined in K&R, second
-   edition: <string.h>, <stdlib.h>, <unistd.h> (except in NeXTSTEP this
-   is <libc.h>), and <sys/stdtypes.h>. If you get warnings about any of
-   these header files not being found, or about argument mismatches
-   involving pid_t, uid_t, or gid_t, look in ckcdeb.h and make
-   amendments. C-Kermit assumes it is being compiled by an ANSI-compliant
-   C compiler if __STDC__ is defined, normally defined by the compiler
-   itself. You can force ANSI compilation without defining __STDC__
-   (which some compilers won't let you define) by including -DCK_ANSIC on
-   the cc command line.
-
-   On the other hand, if your compiler defines __STDC__ but still
-   complains about the syntax of Kermit's function prototypes, you can
-   disable the ANSI-style function prototyping by including -DNOANSI on
-   the command line.
-
-   For SCO OpenServer, UNIX, ODT, and XENIX compilations, be sure to pick
-   the most appropriate [146]makefile target, and be sure you have
-   installed an SCO development system that is keyed to your exact SCO
-   operating system release, down to the minor version (like 2.3.1).
-
-   Also note that SCO distributes some of its libraries in encrypted
-   form, and they must be decrypted before C-Kermit can be linked with
-   them. If not, you might see a message like:
-
-ld: file /usr/lib/libsocket.a is of unknown type: magic number = 6365
-
-   To decrypt, you must supply a key (password) that came with your
-   license. Call SCO for further info.
-
-   If your compiler uses something other than int for the pid (process
-   id) data type, put -DPID_T=pid_t or whatever in your CFLAGS.
-
-   If you get complaints about unknown data types uid_t and gid_t, put
-   -DUID_T=xxx -DGID_T=yyy in your CFLAGS, where xxx and yyy are the
-   appropriate types.
-
-   If your compilation fails because of conflicting or duplicate
-   declarations for sys_errlist, add -DUSE_STRERROR or -DNDSYSERRLIST to
-   CFLAGS.
-
-   If your compilation dies because getpwnam() is being redeclared (or
-   because of "conflicting types for getwpnam"), add -DNDGPWNAM to your
-   CFLAGS. If that doesn't work, then add -DDCGPWNAM to your CFLAGS (see
-   ckufio.c around line 440).
-
-   If the compiler complains about the declaration of getpwnam() during
-   an ANSI C compilation, remove the declaration from ckufio.c or change
-   the argument in the prototype from (char *) to (const char *).
-
-   If you get complaints that getpwuid() is being called with an improper
-   type, put -DPWID_T=xx in your CFLAGS.
-
-   If you get compile-time warnings that t_brkc or t_eofc (tchars
-   structure members, used in BSD-based versions) are undefined, or
-   structure-member- related warnings that might be traced to this fact,
-   add -DNOBRKC to CFLAGS.
-
-   If you get a linker message to the effect that _setreuid or _setregid
-   is not defined, add -DNOSETREU to CFLAGS, or add -DCKTYP_H=blah to
-   CFLAGS to make C-Kermit read the right <types.h>-kind-of-file to pick
-   up these definitions.
-
-   If you get a message that _popen is undefined, add -DNOPOPEN to
-   CFLAGS.
-
-   If you get a complaint at compile time about an illegal
-   pointer-integer combination in ckufio.c involving popen(), or at link
-   time that _popen is an undefined symbol, add the declaration "FILE
-   *popen();" to the function zxcmd() in ckufio.c (this declaration is
-   supposed to be in <stdio.h>). If making this change does not help,
-   then apparently your Unix does not have the popen() function, so you
-   should add -DNOPOPEN to your make entry, in which case certain
-   functions involving "file" i/o to the standard input and output of
-   subprocesses will not be available.
-
-   If your linker complains that _getcwd is undefined, you can add a
-   getcwd() function to ckufio.c, or add it to your libc.a library using
-   ar:
-
-#include <stdio.h>
-
-char *
-getcwd(buf,size) char *buf; int size; {
-#ifndef NOPOPEN
-#ifdef DCLPOPEN
-    FILE *popen();
-#endif
-    FILE *pfp;
-
-    if (!buf) return(NULL);
-    if (!(pfp = popen("pwd","r"))) return(NULL);
-    fgets(buf,size-2,pfp);
-    pclose(pfp);
-    buf[strlen(buf)-1] = '\0';
-    return((char *)buf);
-#else
-    buf[0] = '\0';
-    return(NULL);
-#endif /* NOPOPEN */
-}
-
-#ifdef NOPOPEN
-FILE *popen(s,t) char *s,*t; {
-    return(NULL);
-}
-#endif /* NOPOPEN */
-
-   If you get complaints about NPROC having an invalid value, add a valid
-   definition for it (depends on your system), as in the cray entry.
-
-   If you get some symbol that's multiply defined, it probably means that
-   a variable name used by Kermit is also used in one of your system
-   libraries that Kermit is linked with. For example, under PC/IX some
-   library has a variable or function called "data", and the variable
-   "data" is also used extensively by Kermit. Rather than edit the Kermit
-   source files, just put a -D in the make entry CFLAGS to change the
-   Kermit symbol at compile time. In this example, it might be
-   -Ddata=xdata.
-
-   Some symbol is defined in your system's header files, but it produces
-   conflicts with, or undesired results from, Kermit. Try undefining the
-   symbol in the makefile target's CFLAGS, for example -UFIONREAD.
-
-   Some well-known symbol is missing from your system header files. Try
-   defining in the makefile target's CFLAGS, for example -DFREAD=1.
-
-   You get many warnings about pointer mismatches. This probably means
-   that Kermit is assuming an int type for signal() when it should be
-   void, or vice-versa. Try adding -DSIG_I (for integer signal()) or
-   -DSIG_V (for void) to CFLAGS. Or just include KFLAGS=-DSIG_V (or
-   whatever) in your "make" command, for example:
-
-make bsd KFLAGS=-DSIG_V
-
-   You get many messages about variables that are declared and/or set but
-   never used. It is difficult to avoid these because of all the
-   conditional compilation in the program. Ignore these messages.
-
-   Some of C-Kermit's modules are so large, or contain so many character
-   string constants, or are so offensive in some other way, that some C
-   compilers give up and refuse to compile them. This is usually because
-   the -O (optimize) option is included in the make entry. If this
-   happens to you, you can (a) remove the -O option from the make entry,
-   which will turn off the optimizer for ALL modules; or (b) compile the
-   offending module(s) by hand, including all the switches from make
-   entry except for -O, and then give the appropriate "make" command
-   again; or (c) increase the value of the -Olimit option, if your
-   compiler supports this option; or (d) change the [147]makefile target
-   to first compile each offending module explicitly without
-   optimization, then compile the others normally (with optimization),
-   for example:
-
-#Fortune 32:16, For:Pro 2.1 (mostly like 4.1bsd)
-ft21:
-        @echo 'Making C-Kermit $(CKVER) for Fortune 32:16 For:Pro 2.1...'
-        $(MAKE) ckuusx.$(EXT) "CFLAGS= -DNODEBUG -DBSD4 -DFT21 -DNOFILEH \
-        -SYM 800 \ -DDYNAMIC -DNOSETBUF -DCK_CURSES $(KFLAGS) -DPID_T=short"
-        $(MAKE) ckuxla.$(EXT) "CFLAGS= -DNODEBUG -DBSD4 -DFT21 -DNOFILEH \
-        -SYM 800 \ -DDYNAMIC -DNOSETBUF -DCK_CURSES $(KFLAGS) -DPID_T=short"
-        $(MAKE) ckudia.$(EXT) "CFLAGS= -DNODEBUG -DBSD4 -DFT21 -DNOFILEH \
-        -SYM 800 \ -DDYNAMIC -DNOSETBUF -DCK_CURSES $(KFLAGS) -DPID_T=short"
-        $(MAKE) wermit "CFLAGS= -O -DNODEBUG -DBSD4 -DFT21 -DNOFILEH -SYM 800 \
-        -DDYNAMIC -DNOSETBUF -DCK_CURSES $(KFLAGS) -DPID_T=short" \
-        "LNKFLAGS= -n -s" "LIBS= -lcurses -ltermcap -lv -lnet"
-
-   As an extreme example, some compilers (e.g. gcc on the DG AViiON) have
-   been known to dump core when trying to compile ckwart.c with
-   optimization. So just do this one "by hand":
-
-cc -o wart ckwart.c
-
-   or:
-
-touch ckcpro.c
-
-   and then give the "make" command again.
-
-   Speaking of wart, it is unavoidable that some picky compilers might
-   generate "statement unreachable" messages when compiling ckcpro.c.
-   Unreachable statements can be generated by the wart program, which
-   generates ckcpro.c automatically from [148]ckcpro.w, which translates
-   lex-like state/input constructions into a big switch/case
-   construction.
-
-   Some function in Kermit wreaks havoc when it is called. Change all
-   invocations of the function into a macro that evaluates to the
-   appropriate return code that would have been returned by the function
-   had it been called and failed, for example: -Dzkself()=0. Obviously
-   not a good idea if the function is really needed.
-
-   If you have just installed SunOS 4.1.2 or 4.1.3, you might find that
-   C-Kermit (and any other C program) fails to link because of unresolved
-   references from within libc. This is because of a mistake in Sun's
-   /usr/lib/shlib.etc files for building the new libc. Change the libc
-   Makefile so that the "ld" lines have "-ldl" at the end. Change the
-   README file to say "mv xccs.multibyte. xccs.multibyte.o" and follow
-   that instruction.
-  __________________________________________________________________________
-
-5. INSTALLING THE KERMIT FILES
-
-   [ [149]Top ] [ [150]Contents ] [ [151]Next ] [ [152]Previous ]
-
-   SECTION CONTENTS
-
-5.1. [153]The C-Kermit Initialization File
-5.2. [154]Text Files
-5.3. [155]Installing the Kermit Files
-5.4. [156]The Makefile Install Target
-
-   The C-Kermit executable does not need any external files to run.
-   Unlike, say, the cu program, which on most platforms is useless unless
-   you (as root) edit the /usr/spool/uucp/Systems and
-   /usr/spool/uucp/Devices files to supply whatever obscure and
-   undocumented syntax is required to match some supposedly user-friendly
-   mnemonic to the real pathname of whatever device you want to use,
-   Kermit runs on its own without needing any external configuration
-   files, and lets you refer to device (and network hosts and services)
-   by their own natural undisguised names.
-
-   Nevertheless, a number of external files can be installed along with
-   the C-Kermit executable if you wish. These include configuration and
-   customization files that are read by Kermit as well as documentation
-   files to be read by people. All of this material is (a) optional, and
-   (b) available on the Kermit website:
-
-[157]http://www.columbia.edu/kermit/
-
-   and usually in a more pleasant form, perhaps also with updated
-   content. So if your computer is on the Internet, there is no need to
-   install anything but the Kermit executable if users know how to find
-   the Kermit website (and if they don't, Kermit's "help" command tells
-   them).
-
-  5.1. The C-Kermit Initialization File
-
-   In C-Kermit 7.0 and earlier, the standard initialization file was a
-   key C-Kermit component because:
-
-    a. It "loaded" the dialing and network directories.
-    b. It defined all the macros and variables for the services
-       directory.
-    c. It defined macros for quickly changing Kermit's file-transfer
-       performance tuning.
-
-   The standard initialization file is quite long (more than 600 lines)
-   and requires noticeable processing time (the slower the computer, the
-   more noticeable), yet few people actually use the services directory,
-   whose definition takes up most of its bulk. Meanwhile, in C-Kermit
-   8.0, many of the remaining functions of the standard initialization
-   file are now built in; for example, the FAST, CAUTIOUS, and ROBUST
-   commands.
-
-   More to the point, many of the settings that could be made only in the
-   initialization and customization files can now be picked up from
-   environment variables. The first group identifies initialization and
-   directory files:
-
-   CKERMIT_INI
-          The path of your Kermit initialization file, if any. This
-          overrides the built-in search for $HOME/.kermrc.
-
-   K_CHARSET
-          The character set used for encoding local text files.
-          Equivalent to SET FILE CHARACTER-SET.
-
-   K_DIAL_DIRECTORY
-          The full pathname of one or more Kermit dialing directory
-          files. Equivalent to SET DIAL DIRECTORY.
-
-   K_NET_DIRECTORY
-          The full pathname of one or more Kermit network directory
-          files. Equivalent to SET NETWORK DIRECTORY.
-
-   K_INFO_DIRECTORY
-   K_INFO_DIR
-          The full pathname of a directory containing Kermit (if any)
-          containing ckubwr.txt and other Kermit text files. Overrides
-          Kermit's built-in search for this directory.
-
-   The next group is related to dialing modems:
-
-   K_COUNTRYCODE
-          The telephonic numeric country code for this location, e.g. 1
-          for North America or 39 for Italy. It is recommended that this
-          one be set for all users, system-wide. Not only is it used to
-          process portable-format dialing directory entries, but it is
-          also compared against Kermit's built-in list of "tone
-          countries" to see if tone dialing can be used. Equivalent to
-          Kermit's SET DIAL COUNTRY-CODE command.
-
-   K_AREACODE
-          The telephonic numeric area code for this location, e.g. 212
-          for Manhattan, New York, USA. Recommend this one also be set
-          system-wide, so shared portable-format dialing directories will
-          work automatically for everybody. Equivalent to Kermit's SET
-          DIAL AREA-CODE command.
-
-   K_DIAL_METHOD
-          TONE or PULSE. Equivalent to Kermit's SET DIAL METHOD command.
-          If a dial method is not set explicitly (or implicitly from the
-          country code), Kermit does not specify a dialing method, and
-          uses the modem's default method, which tends to be pulse.
-
-   K_INTL_PREFIX
-          The telephonic numeric international dialing prefix for this
-          location. Equivalent to Kermit's SET DIAL INTL-PREFIX command.
-
-   K_LD_PREFIX
-          The telephonic numeric long-distance dialing prefix for this
-          location. Equivalent to Kermit's SET DIAL LD-PREFIX command.
-
-   K_PBX_ICP
-          The telephonic numeric PBX internal call prefix for this
-          location. Equivalent to Kermit's SET DIAL PBX-INSIDE-PREFIX
-          command.
-
-   K_PBX_OCP
-          The telephonic numeric PBX external call prefix for this
-          location. Equivalent to Kermit's SET DIAL PBX-OUTSIDE-PREFIX
-          command.
-
-   K_PBX_XCH
-          The telephonic numeric PBX exchange (first part of the
-          subscriber number). Equivalent to Kermit's SET DIAL
-          PBX-EXCHANGE command.
-
-   K_TF_AREACODE
-          A list of one or more telephonic numeric toll-free area codes.
-
-   K_TF_PREFIX
-          The telephonic numeric toll-free dialing prefix, in case it is
-          different from the long-distance prefix. Equivalent to Kermit's
-          SET DIAL TF-PREFIX command.
-
-   The final group includes well-known environment variables that are
-   also used by Kermit:
-
-   CDPATH
-          Where the CD command should look for relative directory names.
-
-   SHELL
-          The path of your Unix shell. Used by the RUN (!) command to
-          choose the shell to execute its arguments.
-
-   USER
-          Your Unix username.
-
-   EDITOR
-          The name or path of your preferred editor (used by the EDIT
-          command). Equivalent to SET EDITOR.
-
-   BROWSER
-          The name or path of your preferred web browser (used by the
-          BROWSE command). Equivalent to Kermit's SET BROWSER command.
-
-   Does this mean the initialization file can be abolished? I think so.
-   Here's why:
-
-     * Kermit already does everything most people want it to do without
-       one.
-     * Important site-specific customizations can be done with global
-       environment variables.
-     * There is no longer any need for everybody to have to use the
-       standard initialization file.
-     * This means that your initialization file, if you want one, can
-       contain your own personal settings, definitions, and preferences,
-       rather than 600 lines of "standard" setups.
-     * If you still want the services directory, you can either TAKE the
-       standard initialization file (which must be named anything other
-       than $HOME/.kermrc to avoid being executed automatically every
-       time you start Kermit), or you can make it a kerbang script and
-       execute it "directly" (the [158]makefile install target does this
-       for you by putting ckermit.ini in the same directory as the Kermit
-       binary, adding the appropriate Kerbang line to the top, and giving
-       it execute permission).
-
-   In fact, you can put any number of kerbang scripts in your PATH to
-   start up C-Kermit in different ways, to have it adopt certain
-   settings, make particular connections, execute complicated scripts,
-   whatever you want.
-
-  5.2. Text Files
-
-   These are entirely optional. Many of them are to be found at the
-   Kermit website in HTML form (i.e. as Web pages with clickable links,
-   etc), and very likely also more up to date. Plain-text files that
-   correspond to Web pages were simply "dumped" by Lynx from the website
-   to plain ASCII text. The format is whatever Lynx uses for this
-   purpose. If you wish, you can install them on your computer as
-   described in the [159]next section.
-
-   [160]COPYING.TXT
-          Copyright notice, permissions, and disclaimer.
-
-   [161]ckermit.ini
-          The standard initialization file, intended more for reference
-          (in most cases) than actual use; see [162]Section 5.1.
-
-   [163]ckermod.ini
-          A sample customization file.
-
-   [164]ckermit70.txt
-          Supplement to [165]Using C-Kermit for version 7.0. Available on
-          the Kermit website as:
-          [166]http://www.columbia.edu/kermit/ckermit70.html
-
-   [167]ckermit80.txt
-          Supplement to [168]Using C-Kermit for version 8.0. Available on
-          the Kermit website as:
-          [169]http://www.columbia.edu/kermit/ckermit80.html
-
-   [170]ckcbwr.txt
-          The general C-Kermit hints and tips ("beware") file. Available
-          on the Kermit website as:
-          [171]http://www.columbia.edu/kermit/ckcbwr.html
-
-   [172]ckubwr.txt
-          The Unix-specific C-Kermit hints and tips file. Available on
-          the Kermit website as:
-          [173]http://www.columbia.edu/kermit/ckubwr.html
-
-   [174]ckuins.txt
-          Unix C-Kermit Installation Instructions (this file). Available
-          on the Kermit website as:
-          [175]http://www.columbia.edu/kermit/ckuins.html
-
-   [176]ckccfg.txt
-          C-Kermit compile-time configuration options. Available on the
-          Kermit website as:
-          [177]http://www.columbia.edu/kermit/ckccfg.html
-
-   [178]ckcplm.txt
-          The C-Kermit program logic manual. Available on the Kermit
-          website as:
-          [179]http://www.columbia.edu/kermit/ckcplm.html
-
-   [180]ca_certs.pem
-          Certificate Authority certificates for secure connections (see
-          [181]Section 16).
-
-  5.3. Installing the Kermit Files
-
-   There is an "install" target in the [182]makefile that you can use if
-   you wish. However, since every site has its own layout and
-   requirements, it is often better to install the Kermit files by hand.
-   You don't have to use the makefile install target to install C-Kermit.
-   This is especially true since not all sites build C-Kermit from
-   source, and therefore might not even have the makefile. But you should
-   read this section in any case.
-
-     If your computer already has an older version of C-Kermit
-     installed, you should rename it (e.g. to "kermit6" or "kermit7") so
-     in case you have any trouble with the new version, the old one is
-     still available.
-
-   In most cases, you need to be root to install C-Kermit, if only to
-   gain write access to directories in which the binary and manual page
-   are to be copied. The C-Kermit binary should be installed in a
-   directory that is in the users' PATH, but that is not likely to be
-   overwritten when you install a new version of the operating system. A
-   good candidate would be the /usr/local/bin/ directory, but the
-   specific choice is site dependent. Example (assuming the appropriate
-   Kermit binary is stored in your current directory as "wermit", e.g.
-   because you just built it from source and that's the name the makefile
-   gave it):
-
-mv wermit /usr/local/bin/kermit
-chmod 755 /usr/local/bin/kermit
-
-   or (only after you finish reading this section!) simply:
-
-make install
-
-   IMPORTANT: IF C-KERMIT IS TO BE USED FOR DIALING OUT, you must also do
-   something to give it access to the dialout devices and lockfile
-   directories. The 'install' target does not attempt to set Kermit's
-   owner, group, and permissions to allow dialing out. This requires
-   privileges, open eyes, and human decision-making. Please read
-   [183]Sections 10 and [184]11 below, make the necessary decisions, and
-   then implement them by hand as described in those sections.
-
-   You should also install the man page, which is called ckuker.nr, in
-   the man page directory for local commands, such as /usr/man/man1/,
-   renamed appropriately, e.g. to kermit.1. This is also taken care of by
-   "make install".
-
-   Optionally, the text files listed in the [185]previous section can be
-   placed in a publicly readable directory. Suggested directory names
-   are:
-
-/usr/local/doc/kermit/
-/usr/local/lib/kermit/
-/usr/share/lib/kermit/
-/opt/kermit/doc/
-
-   (or any of these without the "/kermit"). Upon startup, C-Kermit checks
-   the following environment variables whose purpose is to specify the
-   directory where the C-Kermit text files are, in the following order:
-
-K_INFO_DIRECTORY
-K_INFO_DIR
-
-   If either of these is defined, C-Kermit checks for the existence of
-   the ckubwr.txt file (Unix C-Kermit Hints and Tips). If not found, it
-   checks the directories listed above (both with and without the
-   "/kermit") plus several others to see if they contain the ckubwr.txt
-   file. If found, various C-Kermit messages can refer the user to this
-   directory.
-
-   Finally, if you want to put the source code files somewhere for people
-   to look at, you can do that too.
-
-  5.4. The Makefile Install Target
-
-   The makefile "install" target does almost everything for you if you
-   give it the information it needs by setting the variables described
-   below. You can use this target if:
-
-     * You downloaded the [186]complete C-Kermit archive and built
-       C-Kermit from source; or:
-     * You downloaded an [187]individual C-Kermit binary and the
-       [188]C-Kermit text-file archive, and your computer has a "make"
-       command.
-
-   Here are the parameters you need to know:
-
-   BINARY
-          Name of the binary you want to install as "kermit". Default:
-          "wermit".
-
-   prefix
-          (lower case) If you define this variable, its value is
-          prepended to all the following xxxDIR variables (8.0.211 and
-          later).
-
-   DESTDIR
-          If you want to install the Kermit files in a directory
-          structure like /opt/kermit/bin/, /opt/kermit/doc/,
-          /opt/kermit/src/, then define DESTIR as the root of this
-          structure; for example, /opt/kermit. The DESTDIR string should
-          not end with a slash. By default, DESTDIR is not defined. If it
-          is defined, but the directory does not exist, the makefile
-          attempts to create it, which might require you to be root. Even
-          so, this can fail if any segments in the path except the last
-          one do not already exist. WARNING: If the makefile creates any
-          directories, it gives them a mode of 755, and the default owner
-          and group. Modify these by hand if necessary.
-
-   BINDIR
-          Directory in which to install the Kermit binary (and the
-          standard C-Kermit initialization file, if it is found, as a
-          Kerbang script). If DESTDIR is defined, BINDIR must start with
-          a slash. BINDIR must not end with a slash. If DESTDIR is
-          defined, BINDIR is a subdirectory of DESTDIR. If BINDIR does
-          not exist, the makefile attempts to create it as with DESTDIR.
-          Default: /usr/local/bin.
-
-   MANDIR
-          Directory in which to install the C-Kermit manual page as
-          "kermit" followed by the manual-chapter extension (next item).
-          Default: /usr/man/man1. If MANDIR is defined, the directory
-          must already exist.
-
-   MANEXT
-          Extension for the manual page. Default: 1 (digit one).
-
-   SRCDIR
-          Directory in which to install the C-Kermit source code. If
-          DESTDIR is defined, this is a subdirectory of DESTDIR. Default:
-          None.
-
-   CERTDIR
-          For secure builds only: Directory in which to install the
-          ca_certs.pem file. This must be the verification directory used
-          by programs that use the SSL libraries at your site. Default:
-          none. Possibilities include: /usr/local/ssl, /opt/ssl,
-          /usr/lib/ssl, . . .     If CERTDIR is defined, the directory
-          must already exist.
-
-   INFODIR
-          Directory in which to install the C-Kermit text files. If
-          DESTDIR is defined, this is a subdirectory of DESTDIR. Default:
-          None. If INFODIR is defined but does not exist, the makefile
-          attempts to create it, as with DESTDIR.
-
-   Examples:
-
-   make install
-          Installs "wermit" as /usr/local/bin/kermit with permissions
-          755, the default owner and group, and no special privileges.
-          The manual page is installed as /usr/man/man1/kermit.1. Text
-          files are not copied anywhere, nor are the sources.
-
-   make MANDIR= install
-          Just like "make install" but does not attempt to install the
-          manual page.
-
-   make DESTDIR=/opt/kermit BINDIR=/bin SRCDIR=/src INFODIR=/doc install
-          Installs the Kermit binary "wermit" as /opt/kermit/bin/kermit,
-          puts the source code in /opt/kermit/src, and puts the text
-          files in /opt/kermit/doc, creating the directories if they
-          don't already exist, and puts the man page in the default
-          location.
-
-   make BINDIR=/usr/local/bin CERTDIR=/usr/local/ssl install
-          Installs the Kerberized Kermit binary "wermit" as
-          /usr/local/bin/kermit, puts the CA Certificates file in
-          /usr/local/ssl/, and the man page in the normal place.
-
-   For definitive information, see the makefile. The following is
-   excerpted from the 8.0.211 makefile:
-
-# The following symbols are used to specify library and header file locations
-# Redefine them to the values used on your system by:
-# . editing this file
-# . defining the values on the command line
-# . defining the values in the environment and use the -e option
-#
-prefix  = /usr/local
-srproot = $(prefix)
-sslroot = $(prefix)
-manroot = $(prefix)
-
-K4LIB=-L/usr/kerberos/lib
-K4INC=-I/usr/kerberos/include
-K5LIB=-L/usr/kerberos/lib
-K5INC=-I/usr/kerberos/include
-SRPLIB=-L$(srproot)/lib
-SRPINC=-I$(srproot)/include
-SSLLIB=-L$(sslroot)/ssl/lib
-SSLINC=-I$(sslroot)/ssl/include
-...
-WERMIT = makewhat
-BINARY = wermit
-DESTDIR =
-BINDIR = $(prefix)/bin
-MANDIR = $(manroot)/man/man1
-MANEXT = 1
-SRCDIR =
-INFODIR =
-CERTDIR =
-  __________________________________________________________________________
-
-6. INSTALLING UNIX C-KERMIT FROM DOS-FORMAT DISKETTES
-
-   [ [189]Top ] [ [190]Contents ] [ [191]Next ] [ [192]Previous ]
-
-     This section is obsolete. We don't distribute C-Kermit on diskettes
-     any more because (a)there is no demand, and (b) it no longer fits. 
-
-   If you received a DOS-format diskette containing a binary executable
-   C-Kermit program plus supporting text files, be sure to chmod +x the
-   executable before attempting to run it.
-
-   In version 5A(190) and later, all the text files on the C-Kermit
-   DOS-format diskettes are in Unix format: LF at the end of each line
-   rather than CRLF. This means that no conversions are necessary when
-   copying to your Unix file system, and that all the files on the
-   diskette, text and binary, can be copied together. The following
-   comments apply to the DOS-format diskettes furnished with version
-   5A(189) and earlier or to other DOS-format diskettes you might have
-   obtained from other sources.
-
-   If you have received C-Kermit on MS-DOS format diskettes (such as
-   those distributed by Columbia University), you should make sure that
-   your DOS-to-Unix conversion utility (such as "dosread") both: (1)
-   changes line terminators in all files from carriage-return linefeed
-   (CRLF) to just linefeed (LF) (such as "dosread -a") and remove any
-   Ctrl-Z's, and (2) that all filenames are converted from uppercase to
-   lowercase. If these conversions were not done, you can use the
-   following shell script on your Unix system to do them:
-
----(cut here)---
-#!/bin/sh
-#
-# Shell script to convert C-Kermit DOS-format files into Unix format.
-# Lowercases the filenames, strips out carriage returns and Ctrl-Z's.
-#
-x=$1 # the name of the source directory
-y=$2 # the name of the target directory if [ $# -lt 2 ]; then
-  echo "usage: $0 source-directory target-directory"
-  exit 1
-fi
-if cd $1 ; then
-  echo "Converting files from $1 to $2"
-else
-  echo "$0: cannot cd to $1"
-  exit 1
-fi
-for i in *; do
-  j=`echo $i | tr 'A-Z' 'a-z'`
-  echo $x/$i =\> $y/$j
-  tr -d '\015\032' < $i > $y/$j
-done
----(cut here)---
-
-   Cut out this shell script, save it as "convert.sh" (or any other name
-   you prefer), then "chmod +x convert.sh". Then, create a new, empty
-   directory to put the converted files in, and then "convert.sh /xxx
-   /yyy" where /xxx is the name of the directory where the PC-format
-   files are, and /yyy is the name of the new, empty directory. The
-   converted files will appear in the new directory.
-  __________________________________________________________________________
-
-7. CHECKING THE RESULTS
-
-   [ [193]Top ] [ [194]Contents ] [ [195]Next ] [ [196]Previous ]
-
-   First some quick checks for problems that can be easily corrected by
-   recompiling with different options:
-
-   DIRECTORY listing is garbage
-          Permissions, size, and date are random garbage (but the
-          filenames are correct) in a C-Kermit DIRECTORY listing. On some
-          platforms, the lstat() function is present but simply doesn't
-          work; try adding -DNOLSTAT to CFLAGS and rebuild. If that
-          doesn't fix it, also add -DNOLINKBITS. If it's still not fixed,
-          remove -DNOLSTAT and -DNOLINKBITS and add -DNOSYMLINK.
-
-   curses
-          When you make a connection with C-Kermit and transfer files
-          using the fullscreen (curses) file-transfer display, and then
-          get the C-Kermit> prompt back afterwards, do characters echo
-          when you type them? If not, the curses library has altered the
-          buffering of /dev/tty. Try rebuilding with KFLAGS=-DCK_NEWTERM.
-          If it already has -DCK_NEWTERM in CFLAGS, try removing it. If
-          that doesn't help, then rebuild with -DNONOSETBUF (yes, two
-          NO's). If none of this works (and you can't fix the code), then
-          either don't use the fullscreen display, or rebuild with
-          -DNOCURSES.
-
-   Ctrl-L or any SCREEN command crashes C-Kermit:
-          Rebuild with -DNOTERMCAP.
-
-   No prompt after CONNECT:
-          After escaping back from CONNECT mode, does your C-Kermit>
-          prompt disappear? (Yet, typing "?" still produces a command
-          list, etc) In that case, add -DCKCONINTB4CB to CFLAGS and
-          rebuild.
-
-   Here is a more thorough checklist can use to tell whether your version
-   of C-Kermit was built correctly for your Unix system, with hints on
-   how to fix or work around problems:
-
-    a. Start C-Kermit (usually by typing "./wermit" in the directory
-       where you ran the makefile). Do you see the C-Kermit> prompt? If
-       not, C-Kermit incorrectly deduced that it was running in the
-       background. The test is in conbgt() in [197]ckutio.c. If you can
-       fix it for your system, please send in the fix (Hint: read about
-       "PID_T" below). Otherwise, you can force C-Kermit to foreground
-       mode by starting it with the -z command line option, as in "kermit
-       -z", or giving the interactive command SET BACKGROUND OFF.
-    b. When you type characters at the C-Kermit prompt, do they echo
-       immediately? If not, something is wrong with concb() and probably
-       the other terminal mode settings routines in [198]ckutio.c. Be
-       sure you have used the most appropriate make entry.
-    c. At the C-Kermit> prompt, type "send ./?". C-Kermit should list all
-       the files in the current directory. If not, it was built for the
-       wrong type of Unix file system. Details below. In the meantime,
-       try SET WILDCARD-EXPANSION SHELL as a workaround.
-    d. CD to a directory that contains a variety of files, symlinks, and
-       subdirectories and give a DIRECTORY command at the C-Kermit>
-       prompt. Do the permissions, size, and date appear correct? If not
-       see [199]Section 4.0.
-    e. Assuming your platform supports long file names, create a file
-       with a long name in your current directory, e.g.:
-
-$ touch thisisafilewithaveryveryveryveryveryveryveryverylooooooooongname
-
-       (you might need to make it longer than this, perhaps as long as
-       257 or even 1025 characters).
-       Check with ls to see if your version of Unix truncated the name.
-       Now start C-Kermit and type "send thisis<ESC>". Does Kermit
-       complete the name, showing the same name as ls did? If not, wrong
-       filesystem. Read on.
-    f. Make sure that Kermit has the maximum path length right. Just type
-       SHOW FILE and see what it says about this. If it is too short,
-       there could be some problems at runtime. To correct, look in
-       [200]ckcdeb.h to see how the symbol CKMAXPATH is set and make any
-       needed adjustments.
-    g. Send a file to your new Kermit program from a different Kermit
-       program that is known to work. Is the date/timestamp of the new
-       file identical to the original? If not, adjustments are needed in
-       zstrdt() in [201]ckufio.c.
-    h. Go to another computer (Computer B) from which you can send files
-       to C-Kermit. Connect Computer B to the computer (A) where you are
-       testing C-Kermit. Then:
-    i. Send a file from B to A. Make sure it transferred OK and was
-       created with the the right name.
-    j. Send a file from B to A, specifying an "as-name" that is very,
-       very long (longer than the maximum name length on computer A).
-       Check to make sure that the file was received OK and that its name
-       was truncated to Computer A's maximum length. If not, check the
-       MAXNAMLEN definition in [202]ckufio.c.
-    k. Tell C-Kermit on Computer A to "set receive pathnames relative"
-       and then send it a file from Computer B specifying an as-name that
-       contains several directory segments:
-
-send foo dir1/dir2/dir3/foo
-
-       Check to make sure that dir1/dir2/dir3/foo was created in Computer
-       A's current directory (i.e. that three levels of directories were
-       created).
-    l. Repeat step k, but make each path segment in the pathname longer
-       than Computer A's maximum name length. Make sure each directory
-       name, and the final filename, were truncated properly.
-    m. Type Ctrl-C (or whatever your Unix interrupt character is) at the
-       prompt. Do you get "^C..." and a new prompt? If instead, you get a
-       core dump (this shouldn't happen any more) "rm core" and then
-       rebuild with -DNOCCTRAP added to your CFLAGS. If it did work, then
-       type another Ctrl-C. If this does the same thing as the first one,
-       then Ctrl-C handling is OK. Otherwise, the SIGINT signal is either
-       not getting re-armed (shouldn't happen) or is being masked off
-       after the first time it is caught, in which case, if your Unix is
-       POSIX-based, try rebuilding C-Kermit with -DCK_POSIX_SIG.
-    n. Type Ctrl-Z (or whatever your Unix suspend character is) to put
-       C-Kermit in the background. Did it work? If nothing happened, then
-       (a)your version of Unix does not support job control, or (b) your
-       version of C-Kermit was probably built with -DNOJC. If your
-       session became totally frozen, then you are probably running
-       C-Kermit on a Unix version that supports job control, but under a
-       shell that doesn't. If that's not the case, look in the congm()
-       and psuspend() routines in [203]ckutio.c and see if you can figure
-       out what's wrong. If you can't, rebuild with -DNOJC.
-    o. Give a SET LINE command for a dialout device, e.g. "set line
-       /dev/tty00". If you got some kind of permission or access denied
-       message, go read [204]Section 10 and then come back here.
-    p. After giving a successful SET LINE command, type "show comm" to
-       see the communication parameters. Do they make sense?
-    q. Type "set speed ?" and observe the list of available speeds. Is it
-       what you expected? If not, see [205]Section 2) of the
-       [206]Configurations Options document.
-    r. Give a SET SPEED command to change the device's speed. Did it
-       work? (Type "show comm" again to check.)
-    s. Try dialing out: SET MODEM TYPE , SET LINE , SET SPEED , DIAL . If
-       it doesn't work, keep reading. After dialing, can you REDIAL?
-    t. If your version was built with TCP/IP network support, try the
-       TELNET command.
-    u. Transfer some files in remote mode on incoming asynchronous serial
-       (direct or modem) connections, and on incoming network (telnet,
-       rlogin, terminal server) connections. If you get lots of errors,
-       try different SET FLOW settings on the remote Kermit program.
-    v. Establish a serial connection from C-Kermit to another computer
-       (direct or dialed) and transfer some files. If you have network
-       support, do the same with a network connection.
-    w. If your version was built with fullscreen file transfer display
-       support, check that it works during local-mode file transfer.
-       Also, check C-Kermit's operation afterwards: is the echoing funny?
-       etc etc. If there are problems, see [207]Section 4.
-    x. If your version was built with script programming language
-       support, TAKE the ckedemo.ksc file to give it a workout.
-    y. Does C-Kermit interlock correctly with UUCP-family programs (cu,
-       tip, uucp, etc)? If not, read the section [208]DIALING OUT AND
-       COORDINATING WITH UUCP below.
-    z. Modem signals... Give a SET LINE command to a serial device and
-       then type the SHOW MODEM command. If it says "Modem signals
-       unavailable in this version of Kermit", then you might want to
-       look at the ttgmdm() routine in [209]ckutio.c and add the needed
-       code -- if indeed your version of Unix provides a way to get modem
-       signals (some don't; e.g. modem signals are a foreign concept to
-       POSIX, requiring politically incorrect workarounds).
-   aa. If it says "Modem signals unavailable", then it is likely that the
-       API for getting modem signals is provided, but it doesn't actually
-       do anything (e.g. ioctl(ttyfd,TIOCMGET,&x) returns EINVAL).
-   ab. In any case, it still should be able to manipulate the DTR signal.
-       To test, SET LINE , SET MODEM NONE, and HANGUP. The DTR light
-       should go out momentarily. If it doesn't, see if you can add the
-       needed code for your system to the tthang() routine in
-       [210]ckutio.c.
-   ac. If your version of Kermit has the SET FLOW RTS/CTS command, check
-       to see if it works: give Kermit this command, set your modem for
-       RTS/CTS, transfer some files (using big packet and window sizes)
-       and watch the RTS and CTS lights on the modem. If they go on and
-       off (and Kermit does not get packet errors), then it works. If
-       your version of Kermit does not have this command, but your
-       version of Unix does support hardware flow control, take a look at
-       the tthflow() command in [211]ckutio.c and see if you can add the
-       needed code (see the section on [212]HARDWARE FLOW CONTROL below).
-       (And please [213]send back any added code, so that others can
-       benefit from it and it can be carried forward into future
-       releases.)
-   ad. If C-Kermit starts normally and issues its prompt, echoing is
-       normal, etc, but then after returning from a CONNECT session, the
-       prompt no longer appears, try rebuilding with -DCKCONINTB4CB.
-   ae. (8.0.206 or later) Type some commands at the C-Kermit prompt. Can
-       you use the Up-arrow and Down-arrow keys on your keyboard to
-       access Kermit's command history? If not, and you're a programmer,
-       take a look at the USE_ARROWKEYS sections of ckucmd.c.
-  __________________________________________________________________________
-
-8. REDUCING THE SIZE OF THE EXECUTABLE PROGRAM IMAGE
-
-   [ [214]Top ] [ [215]Contents ] [ [216]Next ] [ [217]Previous ]
-
-   Also see: [218]C-Kermit Configuration Options
-
-    a. Many of C-Kermit's options and features can be deselected at
-       compile time. The greatest savings at the least sacrifice in
-       functionality is to disable the logging of debug information by
-       defining NODEBUG during compilation. See the [219]Configurations
-       Options document for further information.
-    b. Use shared libraries rather than static linking. This is the
-       default on many Unix systems anyway. However, executables built
-       for dynamic linking with shared libraries are generally not
-       portable away from the machine they were built on, so this is
-       recommended if the binary is for your use only.
-    c. Most Unix systems have a "strip" command to remove symbol table
-       information from an executable program image. "man strip" for
-       further information. The same effect can be achieved by including
-       "-s" among the link flags when building C-Kermit.
-    d. SCO, Interactive, and some other Unix versions have an "mcs"
-       command. "mcs -d wermit" can be used to delete the contents of the
-       ".comment" section from the executable program image.
-    e. Many modern optimizers can be instructed to optimize for space
-       rather than execution efficiency. Check the CFLAGS in the makefile
-       target, adjust as desired.
-  __________________________________________________________________________
-
-9. UNIX VERSIONS
-
-   [ [220]Top ] [ [221]Contents ] [ [222]Next ] [ [223]Previous ]
-
-   SECTION CONTENTS
-
-9.1 [224]Standards
-     9.1.1. [225]POSIX
-     9.1.2. [226]ANSI C
-     9.1.3. [227]Other Standards
-9.2. [228]Library Issues
-9.3. [229]Unix File System Peculiarities
-9.4. [230]Hardware Flow Control
-9.5. [231]Terminal Speeds
-9.6. [232]Millisecond Sleeps
-9.7. [233]Nondestructive Input Buffer Peeking
-9.8. [234]Other System-Dependent Features
-9.9. [235]Terminal Interruption
-
-   There are several major varieties of Unix: Bell Laboratories Seventh
-   Edition, AT&T System V, Berkeley Standard Distribution (BSD), and
-   POSIX. Each has many, many subvarieties and descendents, and there are
-   also hybrids that exhibit symptoms of two or more varieties, plus
-   special quirks of their own.
-
-   Seventh edition versions of C-Kermit include the compile-time option
-   -DV7 in the CFLAGS string in the makefile target. Various V7-based
-   implementations are also supported: -DCOHERENT, -DMINIX, etc.
-
-   AT&T-based versions of Unix Kermit include the compile-time option
-   -DATTSV (standing for AT&mp;T Unix System V). This applies to System
-   III and to System V up to and including Release 2. For System V
-   Release 3, the flag -DSVR3 should be used instead (which also implies
-   -DATTSV). This is because the data type of signal() and several other
-   functions was changed between SVR2 and SVR3. For System V Release 4,
-   include -DSVR4 because of changes in UUCP lockfile conventions; this
-   also implies -DSVR3 and -DATTSV.
-
-   For BSD, the flag -BSDxx must be included, where xx is the BSD version
-   number, for example BSD4 (for version 4.2 or later, using only 4.2
-   features), -DBSD41 (for BSD 4.1 only), -DBSD43 (for 4.3), -DBSD29 (BSD
-   2.9 for DEC PDP-11s). -DBSD44 is for 4.4BSD, which is the basis of
-   FreeBSD, NetBSD, OpenBSD, BSDI, and Mac OS X, and which contains many
-   POSIX features, and has little relation to 4.3BSD and earlier.
-
-   For POSIX, include the flag -DPOSIX. POSIX defines a whole new set of
-   terminal i/o functions that are not found in traditional AT&T or
-   Berkeley implementations, and also defines the symbol _POSIX_SOURCE,
-   which is used in many system and library header files, mainly to
-   disable non-POSIX (i.e. useful) features.
-
-   Note (circa 1997): In order to enable serial speeds higher than 38400
-   bps, it is generally necessary to add -DPOSIX (among other things),
-   since the older terminal APIs can not accommodate the new speeds --
-   out o' bits. But this often also means wholesale conversion to POSIX
-   APIs. In general, just try adding -DPOSIX and then see what goes
-   wrong. Be wary of features disappearing: when _POSIX_SOURCE is
-   defined, all sorts of things that were perfectly OK before suddenly
-   become politically incorrect -- like reading modem signals, doing
-   hardware flow control, etc. POSIX was evidently not designed with
-   serial communication in mind!
-
-   Case in point: In UnixWare 7.0, #define'ing POSIX causes strictness
-   clauses in the header files to take effect. These prevent <sys/time.h>
-   from defining the timeval and timezone structs, which are needed for
-   all sorts of things (like select()). Thus, if we want the high serial
-   speeds, we have to circumvent the POSIX clauses.
-
-   Similarly in SCO OpenServer R5.0.4 where, again, we must use the POSIX
-   APIs to get at serial speeds higher than 38400, but then doing so
-   removes hardware flow control -- just when we need it most! In cases
-   like this, dirty tricks are the only recourse (search for SCO_OSR504
-   in [236]ckutio.c for examples).
-
-   For reasons like this, Unix implementations tend to be neither pure
-   AT&T nor pure BSD nor pure POSIX, but a mixture of two or more of
-   these, with "compatibility features" allowing different varieties of
-   programs to be built on the same computer. In general, Kermit tries
-   not to mix and match but to keep a consistent repertoire throughout.
-   However, there are certain Unix implementations that only work when
-   you mix and match. For example, the Silicon Graphics IRIX operating
-   system (prior to version 3.3) is an AT&T Unix but with a BSD file
-   system. The only way you can build Kermit successfully for this
-   configuration is to include -DSVR3 plus the special option -DLONGFN,
-   meaning "pretend I was built with -DBSDxx when it's time to compile
-   file-related code". See the "iris" makefile target.
-    ________________________________________________________________________
-
-  9.1. Standards
-
-   [ [237]Top ] [ [238]Section Contents ] [ [239]Contents ] [ [240]Next ]
-
-   SUBSECTION CONTENTS
-
-9.1.1. [241]POSIX
-9.1.2. [242]ANSI C
-9.1.3. [243]Other Standards
-
-   In edits 166-167 (1988-89), C-Kermit was heavily modified to try to
-   keep abreast of new standards while still remaining compatible with
-   old versions of C and Unix. There are two new standards of interest:
-   ANSI C (as described in Kernighan and Ritchie, "The C Programming
-   Language", Second Edition, Prentice Hall, 1988) and POSIX.1 (IEEE
-   Standard 1003.1 and ISO/IEC 9945-1, 1990, "Portable Operating System
-   Interface"). These two standards have nothing to do with each other:
-   you can build C-Kermit with a non-ANSI compiler for a POSIX system, or
-   for a non-POSIX system with with an ANSI compiler.
-
-    9.1.1. POSIX
-
-   POSIX.1 defines a repertoire of system functions and header files for
-   use by C language programs. Most notably, the ioctl() function is not
-   allowed in POSIX; all ioctl() functions have been replaced by
-   device-specific functions like tcsetattr(), tcsendbreak(), etc.
-
-   Computer systems that claim some degree of POSIX compliance have made
-   some attempt to put their header files in the right places and give
-   them the right names, and to provide system library functions with the
-   right names and calling conventions. Within the header files,
-   POSIX-compliant functions are supposed to be within #ifdef
-   _POSIX_SOURCE..#endif conditionals, and non-POSIX items are not within
-   these conditionals.
-
-   If Kermit is built with neither -D_POSIX_SOURCE nor -DPOSIX, the
-   functions and header files of the selected version of Unix (or VMS,
-   etc) are used according to the CFLAGS Kermit was built with.
-
-   If Kermit is built with -D_POSIX_SOURCE but not -DPOSIX, then one of
-   the -DBSD or -DATTSV flags (or one that implies them) must also be
-   defined, but it still uses only the POSIX features in the system
-   header files. This allows C-Kermit to be built on BSD or AT&T systems
-   that have some degree of POSIX compliance, but still use BSD or AT&T
-   specific features.
-
-   The dilimma is this: it is often necessary to define _POSIX_SOURCE to
-   get at new or modern features, such as high serial speeds and the APIs
-   to deal with them. But defining _POSIX_SOURCE also hides other APIs
-   that Kermit needs, for example the ones dealing with modem signals
-   (others are listed just below). Thus all sorts of hideous contortions
-   are often required to get a full set of features.
-
-   The POSIX standard does not define anything about uucp lockfiles.
-   "make posix" uses NO (repeat, NO) lockfile conventions. If your
-   POSIX-compliant Unix version uses a lockfile convention such as
-   HDBUUCP (see below), use the "posix" entry, but include the
-   appropriate lockfile option in your KFLAGS on the "make" command line,
-   for example:
-
-make posix "KFLAGS=-DHDBUUCP"
-
-   POSIX.1 also lacks certain other features that Kermit needs. For
-   example:
-
-     * There is no defined way for an application to do wildcard matching
-       of filenames. Kermit uses the inode in the directory structure,
-       but POSIX.1 does not include this concept. (Later POSIX revisions
-       include functions named (I think) glob() and fnmatch(), but these
-       functions are not yet in Kermit, and might not be appropriate in
-       any case.)
-     * There is no POSIX mechanism for sensing or controlling modem
-       signals, nor to enable RTS/CTS or other hardware flow control.
-     * There is no select() for multiplexing i/o, and therefore no
-       TCP/IP.
-     * There is no way to check if characters are waiting in a
-       communications device (or console) input buffer, short of trying
-       to read them -- no select(), ioctl(fd,FIONREAD,blah), rdchk(),
-       etc. This is bad for CONNECT mode and bad for sliding windows.
-     * No way to do a millisecond sleep (no nap(), usleep(), select(),
-       etc).
-     * There is no popen().
-
-   So at this point, there cannot be one single fully functional POSIX
-   form of C-Kermit unless it also has "extensions", as do Linux, QNX,
-   etc.
-
-   More on POSIX (quoting from a newsgroup posting by Dave Butenhof):
-
-     Standards tend to look at themselves as "enabling". So POSIX
-     standards say that, in order to use POSIX functions, a program must
-     define some macro that will put the development environment in
-     "POSIX mode". For the ancient POSIX 1003.1-1990, the symbol is
-     _POSIX_SOURCE. For recent revisions, it's _POSIX_C_SOURCE with an
-     appropriate value. POSIX 1003.1-1996 says that, to use its features
-     in a portable manner, you must define _POSIX_C_SOURCE=199506L
-     before including any header files.
-
-     But for Solaris, or Digital Unix, the picture is different. POSIX
-     is one important but small part of the universe. Yet POSIX
-     unconditionally and unambiguously REQUIRES that, when
-     _POSIX_C_SOURCE=199506L, ALL of the functions and definitions
-     required by the standard, and NO others (except in specific
-     restricted namespaces, specifically "_" followed by an uppercase
-     letter or "__" followed by a lowercase letter) shall be visible.
-     That kinda puts a cramp on BSD and SVID support, because those
-     require names that are not in the "protected" POSIX namespaces.
-     It's ILLEGAL to make those symbols visible, unless you've done
-     something else that's beyond the scope of POSIX to allow the system
-     to infer that you didn't really mean it.
-
-     In most cases, you should just compile, with no standards-related
-     macros defined. The system will make available every interface and
-     definition that isn't incompatible with the "main stream". There
-     may indeed be cases where two standards cross, and you really can't
-     use both together. But, in general, they play nicely together as
-     long as you don't do anything rash -- like telling the system that
-     it's not allowed to let them.
-
-     In the area of threads, both Solaris and Digital Unix support
-     incompatible thread APIs. We have POSIX and DCE, they have POSIX
-     and UI. The nasty areas are in the _r routines and in some aspects
-     of signal behavior. You cannot compile a single source file that
-     uses both semantics. That's life. It sounds as if Solaris defaults
-     to the UI variants, but allows you to define this
-     _POSIX_THREAD_SEMANTICS to get around it. We default to POSIX, and
-     allow you to define _PTHREAD_USE_D4 (automatically defined by the
-     cc "-threads" switch) to select the DCE thread variants. That
-     default, because you're operating outside of any individual
-     standard, is really just a marketing decision.
-      ______________________________________________________________________
-
-    9.1.2. ANSI C
-
-   [ [244]Top ] [ [245]Contents ] [ [246]Section Contents ] [
-   [247]Subsection Contents ] [ [248]Next ] [ [249]Previous ]
-
-   The major difference between ANSI C and earlier C compilers is
-   function prototyping. ANSI C allows function arguments to be checked
-   for type agreement, and (when possible) type coercion in the event of
-   a mismatch. For this to work, functions and their arguments must be
-   declared before they are called. The form for function declarations is
-   different in ANSI C and non-ANSI C (ANSI C also accepts the earlier
-   form, but then does not do type checking).
-
-   As of edit 167, C-Kermit tries to take full advantage of ANSI C
-   features, especially function prototyping. This removes many bugs
-   introduced by differing data types used or returned by the same
-   functions on different computers. ANSI C features are automatically
-   enabled when the symbol __STDC__ is defined. Most ANSI C compilers,
-   such as GNU CC and the new DEC C compiler define this symbol
-   internally.
-
-   On the downside, ANSI C compilation increases the
-   administrative/bureacratic burden, spewing out countless unneeded
-   warnings about mismatched types, especially when we are dealing with
-   signed and unsigned characters, requiring casts everywhere to shut up
-   the mindless complaints -- there is no use for signed chars in Kermit
-   (or probably anywhere else). Some compilers, mercifully, include a
-   "treat all chars as unsigned" option, and when available it should be
-   used -- not only to stop the warnings, but also to avoid unhelpful
-   sign extension on high-bit characters.
-
-   To force use of ANSI C prototypes, include -DCK_ANSIC on the cc
-   command line. To disable the use of ANSI prototypes, include -DNOANSI.
-      ______________________________________________________________________
-
-    9.1.3. Other Standards
-
-   [ [250]Top ] [ [251]Contents ] [ [252]Section Contents ] [
-   [253]Subsection Contents ] [ [254]Next ] [ [255]Previous ]
-
-   As the years go by, standards with-which-all-must-comply continue to
-   pile up: AES, XPG2, XPG3, XPG4, FIPS 151-2, successive generations of
-   POSIX, OSF/1, X/Open, Spec 1170, UNIX95, Open Group UNIX98, ISO/IEC
-   9945 parts 1-4, ISO 9899, 88Open, OS 99, Single Unix Specification
-   (SUS, [256]IEEE 1003.1-2001, not to mention "mature standards" like
-   V7, 4.2/4.3BSD, System V R3 and R4 (SVID2 and SVID3), 4.4BSD (the
-   basis for BSDI, OpenBSD, NetBSD, FreeBSD, Mac OS X etc), /usr/group,
-   plus assorted seismic pronouncements of the neverending series of
-   ephemeral corporate consortia, not to mention the libc-vs-glibc
-   turmoil in the Linux arena and who knows what else.
-
-   None of these standards simplifies life for portable applications like
-   C-Kermit -- each one is simply one more environment to support (or
-   circumvent, as in many cases these standards do more harm than good by
-   denying access to facilities we need, e.g. as noted in above in
-   [257]9.1.1).
-    ________________________________________________________________________
-
-  9.2. Library Issues
-
-   [ [258]Top ] [ [259]Contents ] [ [260]Section Contents ] [
-   [261]Subsection Contents ] [ [262]Next ] [ [263]Previous ]
-
-   On most modern platforms, applications are -- and often must be --
-   dynamically linked. This has numerous advantages (smaller executables,
-   ability to patch a library and thereby patch all applications that use
-   it, etc), but also causes some headaches: most commonly, the library
-   ID built into the executable at link time does not match the ID of the
-   corresponding library on the target system, and so the loader refuses
-   to let the application run.
-
-   This problem only gets worse over time. In the Linux and *BSD world,
-   we also have totally different libraries (each with their own names
-   and numbering systems) that cover the same territory; for example,
-   curses vs ncurses, libc versus glibc. Combinations proliferate and any
-   given Unix computer might have any combination. For this reason it is
-   becoming increasingly difficult to produce a "Linux binary" for a
-   given architecture (e.g. PC or Alpha). There has to be a separate
-   binary for (at least) every combination of curses vs ncurses and libc
-   vs glibc.
-
-   In such cases, the best advice is for every user to build C-Kermit
-   from source code on the system where it will run. Too bad most
-   commercial Unix vendors have stopped including C compilers with the
-   operating system!
-    ________________________________________________________________________
-
-  9.3. Unix File System Peculiarities
-
-   [ [264]Top ] [ [265]Contents ] [ [266]Section Contents ] [ [267]Next ]
-   [ [268]Previous ]
-
-   Normally, including a BSD, System-V, POSIX, or DIRENT flag in the make
-   entry selects the right file system code. But some versions of Unix
-   are inconsistent in this regard, and building in the normal way either
-   gives compiler or linker errors, or results in problems at runtime,
-   typically failure to properly expand wildcard file specifications when
-   you do something like "send *.*", or failure to recognize long
-   filenames, as in "send filewithaveryveryveryveryverylongname".
-
-   C-Kermit is supposed to know about all the various styles of Unix file
-   systems, but it has to be told which one to use when you build it,
-   usually in the makefile target CFLAGS as shown below, but you might
-   also have to add something like -I/usr/include/bsd to CFLAGS, or
-   something like -lbsd to LIBS.
-
-   C-Kermit gives you the following CFLAGS switches to adapt to your file
-   system's peculiarities:
-
--DDIRENT   - #include <dirent.h>
--DSDIRENT  - #include <sys/dirent.h>
--DNDIR     - #include <ndir.h>
--DXNDIR    - #include <sys/ndir.h>
--DRTU      - #include "/usr/lib/ndir.h", only if NDIR and XNDIR not defined.
--DSYSUTIMH - #include <sys/utime.h> for setting file creation dates.
--DUTIMEH   - #include <utime.h> for setting file creation dates.
-
-   (Note, RTU should only be used for Masscomp RTU systems, because it
-   also selects certain other RTU-specific features.)
-
-   If none of these is defined, then <sys/dir.h> is used. IMPORTANT: If
-   your system has the file /usr/include/dirent.h then be sure to add
-   -DDIRENT to your makefile target's CFLAGS. "dirent" should be used in
-   preference to any of the others, because it supports all the features
-   of your file system, and the others probably don't.
-
-   Having selected the appropriate directory header file, you might also
-   need to tell Kermit how to declare the routines and variables it needs
-   to read the directory. This happens most commonly on AT&T System-V
-   based UNIXes, particularly System V R3 and earlier, that provide long
-   file and directory names (longer than 14 characters). Examples include
-   certain releases of HP-UX, DIAB DNIX, older versions of Silicon
-   Graphics IRIX, and perhaps also MIPS. In this case, try adding
-   -DLONGFN to your makefile target.
-
-   Another problem child is <sys/file.h>. Most Unix C-Kermit versions
-   need to #include this file from within [269]ckufio.c and
-   [270]ckutio.c, but some not only do not need to include it, but MUST
-   not include it because (a) it doesn't exist, or (b) it has already
-   been included by some other header file and it doesn't protect itself
-   against multiple inclusion, or (c) some other reason that prevents
-   successful compilation. If you have compilation problems that seem to
-   stem from including this file, then add the following switch to CFLAGS
-   in your makefile target:
-
--DNOFILEH
-
-   There are a few odd cases where <sys/file.h> must be included in one
-   of the cku[ft]io.c files, but not the other. In that case, add the
-   aforementioned switch, but go into the file that needs <sys/file.h>
-   and add something like this:
-
-#ifdef XXX       /* (where XXX is a symbol unique to your system) */
-#undef NOFILEH
-#endif /* XXX */
-
-   before the section that includes <sys/file.h>.
-
-   Kermit's SEND command expands wildcard characters "?" and "*" itself.
-   Before version 5A, commands like "send *" would send all regular
-   (non-directory) files, including "hidden files" (whose names start
-   with "."). In version 5A, the default behavior is to match like the
-   Bourne shell or the ls command, and not include files whose names
-   start with dot. Such files can still be sent if the dot is included
-   explicitly in the SEND command: "send .oofa, send .*". To change back
-   to the old way and let leading wildcard characters match dot files,
-   include the following in your CFLAGS:
-
--DMATCHDOT
-
-   (In C-Kermit 6.0, there is also a command to control this at runtime.)
-
-   Complaints about data-type mismatches:
-
-     * If you get compile-time complaints about data type mismatches for
-       process-ID related functions like getpid(), add -DPID_T=pid_t.
-     * If you get compile-time complaints about data type mismatches for
-       user ID related functions like getuid(), add -DUID_T=uid_t.
-     * If you get compile-time complaints about data type mismatches for
-       user-ID related functions like getgid(), add -DGID_T=gid_t.
-     * If you get compile-time complaints about data type mismatches for
-       getpwuid(), add -DPWID_T=uid_t (or whatever it should be).
-
-   File creation dates: C-Kermit attempts to set the creation date/time
-   of an incoming file according to the date/time given in the file's
-   attribute packet, if any. If you find that the dates are set
-   incorrectly, you might need to build Kermit with the -DSYSUTIMEH flag,
-   to tell it to include <sys/utime.h>. If that doesn't help, look at the
-   code in zstrdt() in [271]ckufio.c.
-    ________________________________________________________________________
-
-  9.4. Hardware Flow Control
-
-   [ [272]Top ] [ [273]Contents ] [ [274]Section Contents ] [ [275]Next ]
-   [ [276]Previous ]
-
-   Hardware flow control is a problematic concept in many popular Unix
-   implementations. Often it is lacking altogether, and when available,
-   the application program interface (API) to it is inconsistent from
-   system to system. Here are some examples:
-
-    a. POSIX does not support hardware flow control.
-    b. RTS/CTS flow control support MIGHT be available for System V R3
-       and later if /usr/include/termiox.h exists (its successful
-       operation also depends on the device driver, and the device
-       itself, not to mention the cable, etc, actually supporting it). If
-       your SVR3-or-later Unix system does have this file, add:
-
--DTERMIOX
-
-       to your CFLAGS. If the file is in /usr/include/sys instead, add:
-
--DSTERMIOX
-
-       Note that the presence of this file does not guarantee that
-       RTS/CTS will actually work -- that depends on the device-driver
-       implementation (reportedly, many Unix versions treat
-       hardware-flow-control related ioctl's as no-ops).
-    c. Search ("grep -i") through /usr/include/*.h and
-       /usr/include/sys/*.h for RTS or CTS and see what turns up. For
-       example, in SunOS 4.x we find "CRTSCTS". Figuring out how to use
-       it is another question entirely! In IBM AIX RS/6000 3.x, we have
-       to "add" a new "line discipline" (and you won't find uppercase RTS
-       or CTS symbols in the header files).
-    d. NeXTSTEP and IRIX, and possibly others, support hardware flow
-       control, but do not furnish an API to control it, and thus on
-       these systems Kermit has no command to select it -- instead, a
-       special device name must be used. (NeXTSTEP: /dev/cufa instead of
-       /dev/cua; IRIX: /dev/ttyf00)
-
-   See the routine tthflow() in [277]ckutio.c for details. If you find
-   that your system offers hardware flow control selection under program
-   control, you can add this capability to C-Kermit as follows:
-
-    a. See if it agrees with one of the methods already used in
-       tthflow(). if not, add new code, appropriately #ifdef'd.
-    b. Add -DCK_RTSCTS to the compiler CFLAGS in your makefile target or
-       define this symbol within the appropriate #ifdefs in
-       [278]ckcdeb.h.
-
-   To illustrate the difficulties with RTS/CTS, here is a tale from Jamie
-   Watson <jw@adasoft.ch>, who added the RTS/CTS code for the RS/6000,
-   about his attempts to do the same for DEC ULTRIX:
-
-     "The number and type of hardware signals available to/from a serial
-     port vary between different machines and different types of serial
-     interfaces on each machine. This means that, for example, there are
-     virtually no hardware signals in or out available on the DECsystem
-     3000/3100 series; on the DECsystem 5000/2xx series all modem
-     signals in/out are present on both built-in serial ports; on the
-     DECsystem 5100 some ports have all signals and some only have some;
-     and so on... It looks to me as if this pretty well rules out any
-     attempt to use hardware flow control on these platforms, even if we
-     could figure out how to do it. The confusion on the user level
-     about whether or not it should work for any given platform or port
-     would be tremendous. And then it isn't clear how to use the
-     hardware signals even in the cases where the device supports them."
-    ________________________________________________________________________
-
-  9.5. Terminal Speeds
-
-   [ [279]Top ] [ [280]Contents ] [ [281]Section Contents ] [ [282]Next ]
-   [ [283]Previous ]
-
-   The allowable speeds for the SET SPEED command are defined in
-   [284]ckcdeb.h. If your system supports speeds that are not listed in
-   "set speed ?", you can add definitions for them to ckcdeb.h.
-
-   Then if the speed you are adding is one that was never used before in
-   Kermit, such as 921600, you'll also need to add the appropriate
-   keywords to spdtab[] in [285]ckuus3.c, and the corresponding case to
-   ttsspd() in [286]ckutio.c.
-    ________________________________________________________________________
-
-  9.6. Millisecond Sleeps
-
-   [ [287]Top ] [ [288]Contents ] [ [289]Section Contents ] [ [290]Next ]
-   [ [291]Previous ]
-
-   There is no standard for millisecond sleeps, but at least five
-   different functions have appeared in various Unix versions that can be
-   used for this purpose: nap() (mostly in System V), usleep() (found at
-   least in SunOS and NeXT OS), select() (found in 4.2BSD and later, and
-   part of any TCP/IP sockets library), nanosleep(), and sginap(). If you
-   have any of these available, pick one (in this order of preference, if
-   you have more than one):
-
--DSELECT: Include this in CFLAGS if your system has the select() function.
--DNAP:    Include this in CFLAGS if your system has the nap() function.
--USLEEP:  Include this in CFLAGS if your system has the usleep() function.
-
-   NOTE: The nap() function is assumed to be a function that puts the
-   process to sleep for the given number of milliseconds. If your
-   system's nap() function does something else or uses some other units
-   of time (like the NCR Tower 32, which uses clock-ticks), do not
-   include -DNAP.
-
-   Reportedly, all versions of System V R4 for Intel-based computers, and
-   possibly also SVR3.2, include nap() as a kernel call, but it's not in
-   the library. To include code to use it via syscall(3112,x), without
-   having to include Xenix compatibility features, include the following
-   compile-time option:
-
--DNAPHACK
-    ________________________________________________________________________
-
-  9.7. Nondestructive Input Buffer Peeking
-
-   [ [292]Top ] [ [293]Contents ] [ [294]Section Contents ] [ [295]Next ]
-   [ [296]Previous ]
-
-   Some AT&T Unix versions have no way to check if input is waiting on a
-   tty device, but this is a very important feature for Kermit. Without
-   it, sliding windows might not work very well (or at all), and you also
-   have to type your escape character to get Kermit's attention in order
-   to interrupt a local-mode file transfer. If your system offers an
-   FIONREAD ioctl, the build procedure should pick that up automatically
-   and use it, which is ideal.
-
-   If your system lacks FIONREAD but has a select() function, this can be
-   used instead. If the build procedure fails to include it (SHOW
-   FEATURES will list SELECT), then you can add it to your CFLAGS:
-
--DSELECT
-
-   Conversely, if the build procedure tries to use select() when it
-   really is not there, add:
-
--DNOSELECT
-
-   Note: select() is not part of System V nor of POSIX, but it has been
-   added to various System-V- and POSIX-based systems as an extension.
-
-   Some System-V variations (SCO Xenix/UNIX/ODT and DIAB DNIX) include a
-   rdchk() function that can be used for buffer peeking. It returns 0 if
-   no characters are waiting and 1 if characters are waiting (but unlike
-   FIONREAD, it does not tell the actual number). If your system has
-   rdchk(), add:
-
--DRDCHK:  Include this in CFLAGS if your system has the rdchk() function.
-
-   Otherwise, if your version of Unix has the poll() function (and the
-   /usr/include/poll.h file) -- which appears to be a standard part of
-   System V going back to at least SVR3, include:
-
--DCK_POLL
-    ________________________________________________________________________
-
-  9.8. Other System-Dependent Features
-
-   [ [297]Top ] [ [298]Contents ] [ [299]Section Contents ] [ [300]Next ]
-   [ [301]Previous ]
-
-   Systems with <termios.h> might have the symbol IEXTEN defined. This is
-   used to turn "extended features" in the tty device driver on and off,
-   such as Ctrl-O to toggle output flushing, Ctrl-V to quote input
-   characters, etc.
-
-   In most Unix implementations, it should be turned off during Kermit
-   operation, so if [302]ckutio.c finds this symbol, it uses it. This is
-   necessary, at least, on BSDI. On some systems, however, IEXTEN is
-   either misdefined or misimplemented. The symptom is that CR, when
-   typed to the command processor, is echoed as LF, rather than CRLF.
-   This happens (at least) on Convex/OS 9.1. The solution is to add the
-   following symbol to the makefile target's CFLACS:
-
--DNOIEXTEN
-
-   However, in at least one Unix implementation, QNX 4.21, IEXTEN must be
-   set before hardware flow control can be used.
-
-   In edits 177 and earlier, workstation users noticed a "slow screen
-   writing" phenomenon during interactive command parsing. This was
-   traced to a setbuf() call in [303]ckutio.c that made console (stdout)
-   writes unbuffered. This setbuf() call has been there forever, and
-   could not be removed without some risk. Kermit's operation was tested
-   on the NeXT in edit 178 with the setbuf() call removed, and the
-   slow-writing symptom was cured, and everything else (command parsing,
-   proper wakeup on ?, ESC, Ctrl-U, and other editing characters,
-   terminal emulation, remote-mode and local-mode file transfer, etc)
-   seemed to work as well as or better than before. In subsequent edits,
-   this change was made to many other versions too, with no apparent ill
-   effects. To remove the setbuf() call for your version of Kermit, add:
-
--DNOSETBUF
-
-   Later reports indicate that adding -DNOSETBUF has other beneficial
-   effects, like cutting down on swapping when Kermit is run on
-   workstations with small memories. But BEWARE: on certain small Unix
-   systems, notably the AT&T 6300 and 3B1 (the very same ones that
-   benefit from NOSETBUF), NOSETBUF seems to conflict with CK_CURSES. The
-   program builds and runs OK, but after once using the curses display,
-   echoing is messed up. In this case, we use a System-V specific
-   variation in the curses code, using newterm() to prevent System V from
-   altering the buffering. See makefile entries for AT&T 6300 and 3B1.
-
-   The Unix version of C-Kermit includes code to switch to file
-   descriptor zero (stdin) for remote-mode file transfer. This code is
-   necessary to prevent Kermit from giving the impression that it is
-   "idle" during file transfers, which, at some sites, can result in the
-   job being logged out in the middle of an active file transfer by
-   idle-job monitors.
-
-   However, this feature can interfere with certain setups; for example,
-   there is a package which substitutes a pty/tty pair for /dev/tty and
-   sets file descriptor 0 to be read-only, preventing Kermit from sending
-   packets. Or... When a Unix shell is invoked under the PICK
-   environment, file descriptor 0 is inoperative.
-
-   To remove this feature and allow Kermit to work in such environments,
-   add the compile-time option:
-
--DNOFDZERO
-
-   On some versions of Unix, earlier releases of C-Kermit were reported
-   to render a tty device unusable after a hangup operation. Examples
-   include IBM AIX on the RT PC and RS/6000. A typical symptom of this
-   phenomenon is that the DIAL command doesn't work, but CONNECTing to
-   the device and dialing manually do work. A further test is to SET DIAL
-   HANGUP OFF, which should make dialing work once by skipping the
-   pre-dial hangup. However, after the connection is broken, it can't be
-   used any more: subsequent attempts to DIAL the same device don't work.
-   The cure is usually to close and reopen the device as part of the
-   hangup operation. To do this, include the following compile-time
-   option:
-
--DCLSOPN
-
-   Similarly, there is a section of code in ttopen(), which does another
-   close(open()) to force the O_NDELAY mode change. On some systems, the
-   close(open()) is required to make the mode change take effect, and
-   apparently on most others it does no harm. But reportedly on at least
-   one System V R4 implementation, and on SCO Xenix 3.2, the
-   close(open()) operation hangs if the device lacks carrier, EVEN THOUGH
-   the CLOCAL characteristic has just been set to avoid this very
-   problem. If this happens to you, add this to your CFLAGS:
-
--DNOCOTFMC
-
-   or, equivalently, in your KFLAGS on the make command line. It stands
-   for NO Close(Open()) To Force Mode Change.
-
-   C-Kermit renames files when you give a RENAME command and also
-   according to the current SET FILE COLLISION option when receiving
-   files. The normal Unix way to rename a file is via two system calls:
-   link() and unlink(). But this leaves open a window of vulnerability.
-   Some Unix systems also offer an atomic rename(oldname,newname)
-   function. If your version of Unix has this function, add the following
-   to your CFLAGS:
-
--DRENAME
-
-   C-Kermit predefines the RENAME for several Unix versions in
-   [304]ckcdeb.h (SVR4, SUNOS41, BSD44, AIXRS, etc). You can tell if
-   rename() is being used if the SHOW FEATURES command includes RENAME in
-   the compiler options list. If the predefined RENAME symbol causes
-   trouble, then add NORENAME to your CFLAGS. Trouble includes:
-
-    a. Linker complains that _rename is an unresolved symbol.
-    b. Linking works, but Kermit's RENAME command doesn't work (which
-       happens because older versions of rename() might have their
-       arguments reversed).
-
-   If rename() is not used, then Kermit uses link()/unlink(), which is
-   equivalent except it is not atomic: there is a tiny interval in which
-   some other process might "do something" to one of the files or links.
-
-   Some Unix systems (Olivetti X/OS, Amdahl UTS/V, ICL SVR3, etc) define
-   the S_ISREG and S_ISDIR macros incorrectly. This is compensated for
-   automatically in [305]ckufio.c. Other systems might have this same
-   problem. If you get a compile-time error message regarding S_ISREG
-   and/or S_ISDIR, add the following to your CFLAGS:
-
--DISDIRBUG
-
-   Finally, here's a symbol you should NEVER define:
-
--DCOMMENT
-
-   It's used for commenting out blocks of code. If for some reason you
-   find that your compiler has COMMENT defined, then add -UCOMMENT to
-   CFLAGS or KFLAGS! Similarly, some header files have been known to
-   define COMMENT, in which case you must add "#undef COMMENT" to each
-   C-Kermit source module, after all the #includes.
-    ________________________________________________________________________
-
-  9.9. Terminal Interruption
-
-   [ [306]Top ] [ [307]Contents ] [ [308]Section Contents ] [ [309]Next ]
-   [ [310]Previous ]
-
-   When C-Kermit enters interactive command mode, it sets a Control-C
-   (terminal keyboard interrupt = SIGINT) trap to allow it to return to
-   the command prompt whenever the user types Control-C (or whatever is
-   assigned to be the interrupt character). This is implemented using
-   setjmp() and longjmp(). On some systems, depending on the machine
-   architecture and C compiler and who knows what else, you might get
-   "Memory fault (coredump)" or "longjmp botch" instead of the desired
-   effect (this should not happen in 5A(190) and later). In that case,
-   add -DNOCCTRAP to your CFLAGS and rebuild the program.
-
-   Job control -- the ability to "suspend" C-Kermit on a Unix system by
-   typing the "susp" character (normally Ctrl-Z) and then resume
-   execution later (with the "fg" command) -- is a tricky business.
-   C-Kermit must trap suspend signals so it can put the terminal back
-   into normal mode when you suspend it (Kermit puts the terminal into
-   various strange modes during interactive command parsing, CONNECT, and
-   file transfer). Supporting code is compiled into C-Kermit
-   automatically if <signal.h> includes a definition for the SIGTSTP
-   signal. HOWEVER... some systems define this signal without supporting
-   job control correctly. You can build Kermit to ignore SIGTSTP signals
-   by including the -DNOJC option in CFLAGS. (You can also do this at
-   runtime by giving the command SET SUSPEND OFF.)
-
-     NOTE: As of version 5A(190), C-Kermit makes another safety check.
-     Even if job control is available in the operating system (according
-     to the numerous checks made in congm()), it will still disable the
-     catching of SIGTSTP signals if SIGTSTP was set to SIG_IGN at the
-     time C-Kermit was started.
-
-   System V R3 and earlier systems normally do not support job control.
-   If you have an SVR3 system that does, include the following option in
-   your CFLAGS:
-
--DSVR3JC
-
-   On systems that correctly implement POSIX signal handling, signals can
-   be handled more reliably than in Bell, Berkeley, or AT&T Unixes. On
-   systems (such as QNX) that are "strictly POSIX", POSIX signal handling
-   *must* be used, otherwise no signal will work more than once. If you
-   have POSIX-based system and you find that your version of Kermit
-   responds to Ctrl-C (SIGINT) or Ctrl-Z (SIGTSTP) only once, then you
-   should add the following option to your CFLAGS:
-
--DCK_POSIX_SIG
-
-   But be careful; some POSIX implementations, notably 4.4BSD, include
-   POSIX signal handling symbols and functions as "stubs" only, which do
-   nothing. Look in <signal.h> for sigsetjmp and siglongjmp and read the
-   comments.
-  __________________________________________________________________________
-
-10. DIALING OUT AND COORDINATING WITH UUCP
-
-   [ [311]Top ] [ [312]Contents ] [ [313]Next ] [ [314]Previous ]
-
-     NOTE: Red Hat Linux 7.2 and later include a new API that allows
-     serial-port arbitration by non-setuid/gid programs. This API has
-     not yet been added to C-Kermit. If C-Kermit is to be used for
-     dialing out on Red Hat 7.2 or later, it must still be installed as
-     described in this section and the next. 
-
-   The short version:
-
-     In order for C-Kermit to be able to dial out from your Unix
-     computer, you need to give it the same owner, group, and
-     permissions as your other dialout programs, such as cu, tip,
-     minicom, uucp, seyon, etc.
-
-   The long version:
-
-   Make sure your dialout line is correctly configured for dialing out
-   (as opposed to login). The method for doing this is different for each
-   kind of Unix. Consult your system documentation for configuring lines
-   for dialing out (for example, Sun SPARCstation IPC users should read
-   the section "Setting up Modem Software" in the Desktop SPARC Sun
-   System and Network Manager's Guide, or the Terminals and Modems
-   section of the HP manual, "Configuring HP-UX for Peripherals" (e.g.
-   /usr/sbin/sam => Peripheral Devices => Terminals and Modems => Add
-   Modem).
-
-   Unlike most other multiuser, multitasking operating systems, Unix
-   allows multiple users to access the same serial device at the same
-   time, even though there is no earthly reason why two users should do
-   this. When they do, user A will read some of the incoming characters,
-   and user B will read the others. In all likelihood, neither user will
-   see them all. Furthermore, User B can hang up User A's call, etc.
-
-   Rather than change Unix to enforce exclusive access to serial devices
-   such as ttys, Unix developers chose instead to use a "lock file". Any
-   process that wants to open a tty device should first check to see if a
-   file of a certain name exists, and if so, not to open the device. If
-   the file does not exist, the process creates the file and then opens
-   the device. When the process closes the device, it destroys the
-   lockfile. This procedure was originated for use with Unix's UUCP, CU,
-   and TIP programs, and so these lockfiles are commonly called "UUCP
-   lockfiles" (UUCP = Unix-to-Unix Copy Program).
-
-   As you can imagine, this method is riddled with pitfalls:
-
-     * If a process does not observe the prevailing lockfile convention,
-       then it can interfere with other "polite" processes. And in fact,
-       very few Unix applications or commands handle lockfiles at all; an
-       original design goal of Unix was that "everything is a file", and
-       countless utilities operate on files directly (by opening them) or
-       indirectly through redirection of standard i/o, without creating
-       or looking for lockfiles.
-     * If a process crashes while it has the device open, the lockfile is
-       left behind, preventing further processes from using the device.
-     * Various versions of Unix use different names for the lockfiles,
-       put them in different directories, with different owners and
-       groups and permissions, and specify their contents differently.
-     * On a given platform, the lockfile conventions may change from one
-       Unix release to the next (for example, SunOS 4.0 to 4.1) or, in
-       the case of Linux, across different distributions.
-     * The same tty device might have more than one name, and most
-       lockfile conventions don't allow for this. Similarly for symbolic
-       links.
-
-   In an attempt to address the problem of "stale" lockfiles, most UUCP
-   implementations put the PID (Process ID) of the creating process in
-   the lockfile. Thus, another process that wants to open the
-   corresponding device can check not only for the lockfile itself, but
-   also can check the PID for validity. But this doesn't work well
-   either:
-
-     * PIDs are stored in diverse formats that change with every new
-       release (short, integer, long, or string in any of various
-       formats). If the reading program does not follow the same
-       convention as the writing program, it can diagnose a valid PID to
-       be invalid, and therefore not honor the lock.
-     * PIDs recycle. If the lockfile was created by PID 1234, which later
-       crashed without removing the lockfile, and then a new process 1234
-       exists a the time the lockfile is checked, the lockfile will be
-       improperly taken as valid, and access to the device denied
-       unnecessarily.
-
-   Several techniques address the problem of multiple names for the same
-   device:
-
-     * Multiple lockfiles. For example, if the user opens a device
-       through a symlink, a lockfile is created for both the symlink name
-       and the true name (obtained from readlink()). However, when
-       multiple drivers are installed for the same device (e.g. /dev/cua,
-       /dev/cufa, etc), this approach won't work unless all applications
-       *know* all the different names for the same device and make
-       lockfiles for all of them, which is obviously not practical.
-     * Lockfiles whose names are not based on the device name. These
-       lockfiles generally have names like LK.inode/major/minor, where
-       inode, major, and minor are numbers, which will always be the same
-       for any physical device, no matter what its name. This form of
-       lockfile is used in System V R4 and its derivatives, such as
-       Solaris, UnixWare, etc. If lockfiles must be used (as opposed to,
-       say, kernel-based locks), this would seem to be the most effective
-       form.
-
-   Most versions of Unix were not designed to accommodate third-party
-   communications software; thus vendors of these Unix products feel no
-   compunction about changing lockfile conventions from release to
-   release, since they also change their versions of the cu, uucp, tip,
-   etc, programs at the same time to match. And since the source code to
-   these programs might not be published, it is difficult for makers of
-   third-party products like C-Kermit to find out what the new
-   conventions are. It also forces release of new versions of C-Kermit
-   whenever the OS vendor makes a change like this.
-
-   Some Unix vendors have taken a small step to simplify communications
-   application development for their products: the inclusion of lockfile
-   routines in the standard system C runtime libraries to shield the
-   application from the details of lockfile management (IBM AIX is an
-   example). When such routines are used, communications applications do
-   not need modification when lockfile conventions change (although they
-   will need recompiling if the routines are statically linked into the
-   application). In the AIX example, the simple function calls ttylock(),
-   ttyunlock(), and ttylocked() replace hundreds of lines of ugly code in
-   C-Kermit that attempts to keep pace with every release of every Unix
-   product over the last 20 years. Inclusion of ttylock() code occurs
-   when:
-
--DUSETTYLOCK
-
-   is included in the CFLAGS.
-
-   If such routines are available, they should be used. The rest of this
-   section applies when they are not.
-
-   To fit in with UUCP and other Unix-based communication software,
-   C-Kermit must have the same idea as your system's uucp, cu, and tip
-   programs about what the UUCP lock directory is called, what the
-   lockfile itself is called, and what its contents should be. In most
-   cases, C-Kermit preprocessor flags create the appropriate
-   configuration at compile time if the appropriate makefile target was
-   used (see [315]ckutio.c). The following CFLAGS options can be used to
-   override the built-in configuration:
-
-   -DLCKDIR
-          Tells Kermit that the UUCP lock directory is
-          /usr/spool/uucp/LCK.
-
-   -DACUCNTRL
-          Tells Kermit to use the BSD 4.3 acucntrl() program to turn off
-          getty (login) on the line before using it, and restore getty
-          when done.
-
-   -DHDBUUCP
-          Include this if your system uses Honey DanBer UUCP, in which
-          the lockfile directory and format are relatively standardized.
-
-   -DLOCK_DIR=\\\"/xxx/yyy\\\"
-          Gives the lock directory name explicitly. The triple quoting is
-          necessary. For example:
-
-CFLAGS= -DBSD4 -DLOCK_DIR=\\\"/usr/local/locks\\\" -DNODEBUG
-
-          (NOTE: The triple quoting assumes this is a "top-level" make
-          entry, and not a make entry that calls another one.)
-
-   -DLFDEVNO The lockfile name uses the tty device inode and major and
-          minor
-          numbers: LK.dev.maj.min, as in Sys V R4, e.g. LK.035.044.008.
-
-   When the LK.inode.major.minor form is used, a single lockfile is
-   enough. Otherwise, a single lockfile rarely suffices. For example, in
-   Linux, it is common to have a /dev/modem symbolic link to an actual
-   dialout device, like /dev/cua0 or /dev/ttyS0, whose purpose is to hide
-   the details of the actual driver from the user. So if one user opens
-   /dev/modem, a lockfile called LCK..modem is created, which does not
-   prevent another user from simulataneously opening the same device by
-   its real name.
-
-   On SCO Unix platforms, we have a slightly different problem: the same
-   device is, by convention, known by "lowercase" and "uppercase" names,
-   depending on whether it has modem control. So by convention,
-   communications programs are supposed to create the lockfiles based on
-   the lowercase name. But some programs don't follow this convention. In
-   HP-UX, we have several different names for each serial device. And so
-   on.
-
-   For this reason, on platforms where the LK.inode.major.minor form is
-   not used, C-Kermit also creates a secondary lockfile (which is simply
-   a link to the first) if:
-
-    a. The given device name is a symbolic link. The secondary link is
-       based on the device's real name.
-    b. On SCO: The device name is not a symbolic link, but it contains
-       uppercase letters. The primary link is based on the lowercase
-       name; the secondary link is based on the name that was given.
-    c. On HP-UX: The device name starts with "cu". The primary link is
-       based on the name that was given; the secondary link is based on
-       the corresponding "ttyd" device, e.g. "LCK..cua0p0" and
-       "LCK..ttyd0p0".
-
-   NOTE: symlinks are not handled in HP-UX.
-
-   Honey DanBer (HDB) UUCP, which is becoming increasingly popular, has
-   two characteristics:
-
-    a. Lockfiles are kept in /usr/spool/locks/ (usually).
-    b. A lockfile contains the process id (pid) in ASCII, rather than as
-       an int.
-
-   Non-HDB selections assume the lockfile contains the pid in int form
-   (or, more precisely, in PID_T form, where PID_T is either int or
-   pid_t, depending on your system's C library and header files). (b), by
-   the way, is subject to interpretation: the numeric ASCII string may or
-   may not be terminated by a newline, it may or may not have leading
-   spaces (or zeros), and the number of leading spaces or zeros can
-   differ, and the differences can be significant.
-
-   Even if you build the program with the right lockfile option, you can
-   still have problems when you try to open the device. Here are the
-   error messages you can get from SET LINE, and what they mean:
-
-    a. "Timed out, no carrier." This one is not related to lockfiles. It
-       means that you have SET CARRIER ON xx, where xx is the number of
-       seconds to wait for carrier, and carrier did not appear within xx
-       seconds. Solution: SET CARRIER AUTO or OFF.
-    b. "Sorry, access to lock denied." Kermit has been configured to use
-       lockfiles, but (a)the lockfile directory is write-protected
-       against you, or (b) it does not exist. The "access to lock denied"
-       message will tell you the reason. If the directory does not exist,
-       check to make sure Kermit is using the right name. Just because
-       version n of your Unix used a certain lockfile directory is no
-       gurantee that version n.1 does not use a different one.
-       Workaround: ask the system administrator to install a symbolic
-       link from the old name to the new name. Other solutions: (see
-       below)
-    c. "Sorry, access to tty device denied." The tty device that you
-       specified in your SET LINE command is read/write protected against
-       you. Solution: (see below)
-    d. "Sorry, device is in use." The tty device you have specified is
-       currently being used by another user. A prefatory message gives
-       you an "ls -l" listing of the lockfile, which should show the
-       username of the person who created it, plus a message "pid = nnn"
-       to show you the process id of the user's program. Solutions: try
-       another device, wait until the other user is finished, ask the
-       other user to hurry up, or ask the system manager for help.
-    e. "Sorry, can't open connection: reason". The device cannot be
-       opened for some other reason, which is listed.
-    f. "sh: /usr/lib/uucp/acucntrl: not found". This means your Kermit
-       program was built with the -DACUCNTRL switch, but your computer
-       system does not have the BSD 4.3 acucntrl program. Solution:
-       install the acucntrl program if you have it, or rebuild Kermit
-       without the -DACUCNTRL switch.
-
-   There are two solutions for problems (b) and (c), both of which
-   involve intervention by your Unix system administrator (superuser):
-
-    a. Have the superuser change the permission of the lockfile directory
-       and to the tty devices so that everyone on the system has
-       read/write permission.
-
-su% chmod 777 /usr/spool/locks (or whatever the path is)
-su% chmod 666 /dev/ttyXX
-
-       One risk here is that people can write lots of junk into the
-       lockfile directory, delete other people's files in the lockfile
-       directory, and intercept other people's data as it goes in and out
-       of the tty device. The major danger here would be intercepting a
-       privileged password. Of course, any user could write a short,
-       ordinary, unprivileged program to do exactly the same thing if the
-       tty device was world read/writeable. The other risk as that
-       telephone calls are not controlled -- anybody on your system can
-       make them, without having to belong to any particular group, and
-       this could run up your phone bill.
-    b. Use groups to regulate access. Normally the lockfile directory and
-       and the dialout devices will have the same group (such as uucp).
-       If so, then put everybody who's allowed to dial out into that
-       group, and make sure that the lockfile directory and the tty
-       devices have group read AND write permission. Example:
-
-su% chmod 770 /usr/spool/locks (or whatever the path is)
-su% chmod 660 /dev/ttyXX
-
-       User whatever tool is available on your platform to add users to
-       the appropropriate group (e.g. edit the /etc/group file).
-    c. Have the superuser change Kermit to run setuid and/or setgid to
-       the owner and/or group of the lockfile directory and the tty
-       devices if necessary), typically uucp (see [316]next section), but
-       NOT root. Example:
-
-su% chown uucp kermit          - or -  chgrp uucp kermit
-su% chmod u+s kermit (setuid)  - or -  chmod g+s kermit (setgid)
-
-       and then make sure the lockfile directory, and the tty devices,
-       have owner (setuid) and/or group (setgid) write permission. For
-       example:
-
-su% chmod o+rwx /usr/spool/uucp
-su% chown uucp /dev/ttyXX ; chmod 600 /dev/ttyXX
-
-       In some cases, the owner and group must be distinct; the key point
-       is that read/write access is required to both the UUCP lockfile
-       directory and the tty itself.
-
-   If you make C-Kermit setuid or setgid to root, it refuses to run:
-
-Fatal: C-Kermit setuid to root!
-
-   Example:
-
-crw-r-----   1 uucp     uucp       5,  67 Feb 11 06:23 /dev/cua3
-drwxrwxr-x   3 root     uucp         1024 Feb 11 06:22 /var/lock
-
-   requires suid uucp to get read/write access on /dev/cua3 and sgid to
-   get read/write access on /var/lock (since you can't set Kermit's uid
-   or gid to root).
-
-     The reason Kermit can't be setuid or setgid to root has to do with
-     the fact that some Unix OS's can't switch user or group IDs in that
-     case. Unfortunately, the prohibition against making Kermit setuid
-     or setgid to root means that Unix C-Kermit can't be used to make
-     rlogin connections by non-root users. (The rlogin port is
-     privileged, which is why the regular rlogin command is setuid root
-     -- which is safe because the rlogin program never has to create or
-     access files like Kermit does.)
-
-   For the lockfile mechanism to achieve its desired purpose --
-   prevention of access to the same tty device by more than one process
-   at a time -- ALL programs on a given computer that open, read or
-   write, and close tty devices must use the SAME lockfile conventions.
-   Unfortunately, this is often not the case. Here is a typical example
-   of how this can go wrong: In SunOS 4.0 and earler, the lockfile
-   directory was /usr/spool/uucp; in 4.1 it was changed to
-   /var/spool/locks in the quest for political correctness. Consequently,
-   any third-party programs (such as C-Kermit) that were not modified to
-   account for this change, recompiled, and reinstalled, did not use the
-   same lockfiles as uucp, tip, etc, and so the entire purpose of the
-   lockfile is defeated.
-
-   What if your Unix system does not have UUCP installed? For example,
-   you have a Unix workstation, and you do not use uucp, cu, or tip, or
-   UUCP was not even supplied with your version of Unix (QNX is an
-   example). In this case, you have two choices:
-
-    a. If there may be more than one person running Kermit at the same
-       time, competing for the same tty device, then create a special
-       lockfile directory just for Kermit, for example,
-       /usr/spool/kermit, and make sure you have read/write access to it.
-       Then add the following to your makefile target CFLAGS, as shown
-       earlier:
-
--DLOCK_DIR=\\\"/usr/spool/kermit\\\"
-
-    b. If you are the only user on your workstation, and no other
-       processes will ever be competing with Kermit for the dialout tty
-       device, then add -DNOUUCP to your makefile target's CFLAGS and
-       rebuild Kermit.
-  __________________________________________________________________________
-
-11. RUNNING UNIX C-KERMIT SETUID OR SETGID
-
-   [ [317]Top ] [ [318]Contents ] [ [319]Next ] [ [320]Previous ]
-
-   Even if you don't intend to run C-Kermit setuid, somebody else might
-   come along and chown and chmod it after it has been built. You should
-   be sure that it is built correctly to run setuid on your system. For
-   POSIX and AT&T Unix based versions, you don't have to do anything
-   special.
-
-   For 4.2 and 4.3 BSD-based Unix versions, you normally need not add
-   anything special to the makefile. The program assumes that the
-   setreuid() and setregid() functions are available, without which we
-   cannot switch back and forth between real and effective uids. If
-   "make" complains that _setreuid or _setregid is/are not defined, add
-   -DNOSETREU to CFLAGS. In this case it is very likely (but not certain)
-   that you cannot protect ttys and lockfiles against people and have
-   them run Kermit setuid.
-
-   If make does not complain about this, you should find out whether your
-   BSD version (4.3 or other systems like SunOS 4.x that claim to include
-   BSD 4.3 compatibility) includes the saved-setuid feature (see long
-   notes under edit 146 in ckc178.upd). If it does, then add -DSAVEDUID
-   to CFLAGS.
-
-     IMPORTANT NOTE: Most Unix system documentation will not give you
-     the required information. To determine whether your Unix system
-     supplies the the saved-original-effective-user/group-id feature,
-     use the ckuuid.c program. Read and follow the instructions in the
-     comments at the beginning.
-
-   C-Kermit for 4.4BSD-based systems automatically use sete[ug]id(). See
-   [321]ckutio.c.
-
-   If you have a version of Unix that is not BSD-based, but which
-   supplies the setreuid() and setregid() functions, and these are the
-   only way to switch between real and effective uid, add -DSETREUID to
-   your makefile target.
-
-     WARNING: There are two calls to access() in [322]ckufio.c, by which
-     Kermit checks to see if it can create an output file. These calls
-     will not work correctly when (a)you have installed C-Kermit setuid
-     or setgid on a BSD-based Unix system, and (b) the
-     saved-original-effective-uid/gid feature is not present, and (c)
-     the access() function always checks what it believes to be the real
-     ID rather than the effective ID. This is the case, for example, in
-     Olivetti X/OS and in NeXTSTEP. In such cases, you can force correct
-     operation of access() calls by defining the symbol SW_ACC_ID at
-     compile time in CFLAGS.
-
-   If you have a version of Unix that does not allow a process to switch
-   back and forth between its effective and real user and group ids
-   multiple times, you probably should not attempt to run Kermit setuid,
-   because once having given up its effective uid or gid (which it must
-   do in order to transfer files, fork a shell, etc) it can never get it
-   back, and so it can not use the original effective uid or gid to
-   create or delete uucp lockfiles. In this case, you'll either have to
-   set the permissions on your lockfile directory to make them publicly
-   read/writable, or dispense with locking altogether.
-
-   MORAL: Are you thoroughly sickened and/or frightened by all that you
-   have just read? You should be. What is the real answer? Simple. Serial
-   devices -- such as ttys and magnetic tapes -- in Unix should be opened
-   with exclusive access only, enforced by the Unix kernel. Shared access
-   has no conceivable purpose, legitimate or otherwise, except by
-   privileged system programs such as getty. The original design dates
-   from the late 1960s, when Unix was developed for laboratory use under
-   a philosophy of trust by people within shouting distance of each other
-   -- but even then, no useful purpose was served by this particular form
-   of openness; it was probably more of a political statement. Since the
-   emergence of Unix from the laboratory into the commercial market, we
-   have seen every vestige of openness -- but this one -- stripped away.
-   I'd like to see some influential Unix maker take the bold step of
-   making the simple kernel change required to enforce exclusive access
-   to serial devices. (Well, perhaps not so simple when bidirectionality
-   must also be a goal -- but then other OS's like VMS solved this
-   problem decades ago.)
-  __________________________________________________________________________
-
-12. CONFIGURING UNIX WORKSTATIONS
-
-   [ [323]Top ] [ [324]Contents ] [ [325]Next ] [ [326]Previous ]
-
-   On desktop workstations that are used by only the user at the console
-   keyboard, C-Kermit is always used in local mode. But as delivered,
-   C-Kermit runs in remote mode by default. To put it in local mode at
-   startup, you can put a SET LINE command in your .mykermrc.
-
-   You can also build C-Kermit to start up in local mode by default. To
-   do this, include the following in the CFLAGS in your makefile target:
-
--DDFTTY=\\\"/dev/ttyxx\\\"
-
-   where ttyxx is the name of the device you will be using for
-   communications. Presently there is no way of setting the default modem
-   type at compile time, so use this option only for direct lines.
-
-   C-Kermit does not work well on certain workstations if it is not run
-   from within a terminal window. For example, you cannot start C-Kermit
-   on a NeXT by launching it directly from NeXTstep. Similarly for Sun
-   workstations in the Open Windows environment. Run Kermit in a terminal
-   window.
-  __________________________________________________________________________
-
-13. BIZARRE BEHAVIOR AT RUNTIME
-
-   [ [327]Top ] [ [328]Contents ] [ [329]Next ] [ [330]Previous ]
-
-   See the "beware file",
-
-   [331]ckubwr.txt, for hints about runtime misbehavior. This section
-   lists some runtime problems that can be cured by rebuilding C-Kermit.
-
-   The program starts, but there is no prompt, and certain operations
-   don't work (you see error messages like "Kermit command error in
-   background execution"). This is because Kermit thinks it is running in
-   the background. See conbgt() in [332]ckutio.c. Try rebuilding Kermit
-   with:
-
- -DPID_T=pid_t
-
-   added to your CFLAGS. If that doesn't help, find out the actual data
-   type for pids (look in types.h or similar file) and use it in place of
-   "pid_t", for example:
-
- -DPID_T=short
-
-   Unexplainable and inappropriate error messages ("Sockets not supported
-   on this device", etc) have been traced in at least one case to a lack
-   of agreement between the system header files and the actual kernel.
-   This happened because the GNU C compiler (gcc) was being used. gcc
-   wants to have ANSI-C-compliant header files, and so part of the
-   installation procedure for gcc is (or was) to run a shell script
-   called "fixincludes", which translates the system's header files into
-   a separate set of headers that gcc likes. So far so good. Later, a new
-   version of the operating system is installed and nobody remembers to
-   run fixincludes again. From that point, any program compiled with gcc
-   that makes use of header files (particularly ioctl.h) is very likely
-   to misbehave. Solution: run fixincludes again, or use your system's
-   regular C compiler, libraries, and header files instead of gcc.
-  __________________________________________________________________________
-
-14. CRASHES AND CORE DUMPS
-
-   [ [333]Top ] [ [334]Contents ] [ [335]Next ] [ [336]Previous ]
-
-   If C-Kermit constitently dumps core at the beginning of a file
-   transfer, look in SHOW FEATURES for CKREALPATH. If found, rebuild with
-   -DNOREALPATH and see if that fixes the problem (some UNIXes have
-   realpath() but it doesn't work).
-
-   Total failure of the Kermit program can occur because of bad memory
-   references, bad system calls, or problems with dynamic memory
-   allocation. First, try to reproduce the problem with debugging turned
-   on: run Kermit with the -d command-line option (for example, "wermit
-   -d") and then examine the resulting debug.log file. The last entry
-   should be in the vicinity of the crash. In VMS, a crash automatically
-   produces a "stack dump" which shows the routine where the crash
-   occurs. In some versions of Unix, you can get a stack dump with "adb"
-   -- just type "adb wermit core" and then give the command "$c", then
-   Ctrl-D to quit (note: replace "wermit" by "kermit" or by the full
-   pathname of the executable that crashed if it is not in the current
-   directory). Or use gdb to get a backtrace, etc.
-
-   In edit 186, one implementation, UNISYS 5000/95 built with "make
-   sys5r3", has been reported to run out of memory very quickly (e.g.
-   while executing a short initialization file that contains a SET DIAL
-   DIRECTORY command). Debug logs show that malloc calls are failing,
-   reason unknown. For this and any other implementation that gives error
-   messages about "malloc failure" or "memory allocation failure",
-   rebuild the program *without* the -DDYNAMIC CFLAGS definition, for
-   example:
-
-make sys5r3 KFLAGS=-UDYNAMIC
-
-   As of edit 169, C-Kermit includes a malloc() debugging package which
-   you may link with the Kermit program to catch runtime malloc errors.
-   See the makefile entries for sunos41md and nextmd for examples of how
-   to select malloc debugging. Once you have linked Kermit with the
-   malloc debugger, it will halt with an informative message if a
-   malloc-related error occurs and, if possible, dump core. For this
-   reason, malloc-debugging versions of Kermit should be built without
-   the "-s" link option (which removes symbols, preventing analysis of
-   the core dump). You have several ways to track down the malloc error:
-   Analyze the core dump with adb. Or reproduce the problem with "log
-   debug" and then look at the code around the last debug.log entry. If
-   you have gcc, build the program with "-g" added to CFLAGS and then
-   debug it with gdb, e.g.
-
-gdb wermit
-break main
-run
-.. set other breakpoints or watchpoints
-continue
-
-   Watchpoints are especially useful for finding memory leaks, but they
-   make the program run about a thousand times slower than usual, so
-   don't set them until the last possible moment. When a watchpoint is
-   hit, you can use the "where" command to find out which C-Kermit source
-   statement triggered it.
-
-   If you have the Pure Software Inc "Purify" product, see the sunos41cp
-   makefile entry for an example of how to use it to debug C-Kermit.
-  __________________________________________________________________________
-
-15. SYSLOGGING
-
-   [ [337]Top ] [ [338]Contents ] [ [339]Next ] [ [340]Previous ]
-
-   "Syslogging" means recording selected in the system log via the Unix
-   syslog() facility, which is available in most Unix versions.
-   Syslogging is not done unless C-Kermit is started with:
-
---syslog:n
-
-   on the command-line, where n is a number greater than 0 to indicate
-   the level of syslogging. See [341]Section 4.2 of the [342]IKSD
-   Administrator's Guide for details.
-
-   Obviously you can't depend on users to include --syslog:3 (or
-   whatever) on the command line every time they start C-Kermit, so if
-   you want certain kinds of records to be recorded in the system log,
-   you can build C-Kermit with forced syslogging at the desired level,
-   e.g.:
-
-make linux KFLAGS=-DSYSLOGLEVEL=2
-
-   Levels 2 and 3 are the most likely candidates for this treatment.
-   Level 2 forces logging of all successful dialout calls (e.g. for
-   checking against or phone bills), and level 3 records all connections
-   (SET LINE or SET HOST / TELNET / RLOGIN, etc) so you can see who is
-   connecting out from your system, and to where.
-
-   Level 2 and 3 records are equivalent to those in the connection log;
-   see the [343]C-Kermit 7.0 Supplement) for a detailed description of
-   the connection log.
-  __________________________________________________________________________
-
-16. BUILDING SECURE VERSIONS OF C-KERMIT 8.0
-
-   [ [344]Top ] [ [345]Contents ] [ [346]Next ] [ [347]Previous ]
-
-   C-Kermit 7.0 and later may be built with Kerberos(TM) and/or SRP(TM)
-   (Secure Remote Password) and/or SSL/TLS security for strong
-   authentication and encryption of Internet connections. These security
-   methods require external libraries that, in their binary forms, are
-   restricted from export by USA law. See the [348]Kermit Security
-   Reference) for details. C-Kermit binaries themselves are likewise
-   restricted; the C-Kermit binaries that are available for public
-   download on the Internet are not allowed to contain the security
-   options.
-
-   Sample makefile entries are provided for Linux and many other
-   operating systems. A list of secure makefile entries is included in
-   the Makefile. Complete instructions on building C-Kermit 8.0 with MIT
-   Kerberos; Secure Remote Password; and/or OpenSSL can be found in the
-   [349]Kermit Security Reference.
-
-   C-Kermit 8.0 comes with a current list of Certificate Authority
-   certificates, including one for the Kermit Project that can be used
-   for authentication to Columbia's [350]Internet Kermit Service (IKSD).
-   You can use C-Kermit 7.0 or later to access Columbia's IKSD securely
-   by installing the Kermit Project certificate in
-   /usr/local/ssl/cert.pem (or the appropriate location based upon the
-   installation of OpenSSL on your system). You can find a copy of the
-   certificates file at:
-
-[351]ftp://kermit.columbia.edu/kermit/c-kermit/ca_certs.pem
-  __________________________________________________________________________
-
-17. INSTALLING C-KERMIT AS AN SSH SERVER SUBSYSTEM
-
-   [ [352]Top ] [ [353]Contents ] [ [354]Previous ]
-
-   This requires C-Kermit 8.0.206 or later and an SSH v2 server. If you
-   list C-Kermit as a Subsystem in the SSH v2 server configuration file
-   (as, for example, SFTP is listed), users can make SSH connections
-   direct to a Kermit server as explained here:
-
-[355]http://www.columbia.edu/kermit/skermit.html
-
-   The name and location of the SSH server configuration file depends on
-   your platform, which SSH product(s) you have, etc. C-Kermit itself
-   must be referred to in this file as "kermit-sshsub". On the host,
-   install the C-Kermit 8.0.211 binary in the normal way. Then, in the
-   same directory as the C-Kermit binary, make a symbolic link:
-
-ln -s kermit kermit-sshsub
-
-   (Note: the "make install" makefile target does this for you.) Then in
-   the sshd configuration file, add a line:
-
-Subsystem  kermit   /some/path/kermit-sshsub
-
-   (where /some/path is the fully specified directory where the symlink
-   is.) This is similar to the line that sets up the SFTP susbsystem.
-   Example:
-
-Subsystem   sftp    /usr/local/libexec/sftp-server
-Subsystem   kermit  /usr/local/bin/kermit-sshsub
-
-   The mechanics might vary for other SSH servers; "man sshd" for
-   details. The method shown here is used because the OpenSSH server does
-   not permit the subsystem invocation to include command-line options.
-   C-Kermit would have no way of knowing that it should enter Server mode
-   if it were not called by a special name.
-
-   [ [356]Top ] [ [357]Contents ] [ [358]C-Kermit Home ] [ [359]C-Kermit
-   8.0 Overview ] [ [360]Kermit Home ]
-     _________________________________________________________________
-
-
-    C-Kermit 8.0 Unix Installation Instructions / The Kermit Project /
-    Columbia University / 10 April 2004
-
-References
-
-   1. http://www.columbia.edu/kermit/ckuins.html#contents
-   2. http://www.columbia.edu/kermit/ckermit.html
-   3. http://www.columbia.edu/kermit/index.html
-   4. http://www.columbia.edu/kermit/ckuins.html
-   5. http://www.columbia.edu/kermit/ckuins.html#x0
-   6. http://www.columbia.edu/kermit/ckuins.html#x1
-   7. http://www.columbia.edu/kermit/ckuins.html#x2
-   8. http://www.columbia.edu/kermit/ckuins.html#x3
-   9. http://www.columbia.edu/kermit/ckuins.html#x4
-  10. http://www.columbia.edu/kermit/ckuins.html#x5
-  11. http://www.columbia.edu/kermit/ckuins.html#x6
-  12. http://www.columbia.edu/kermit/ckuins.html#x7
-  13. http://www.columbia.edu/kermit/ckuins.html#x8
-  14. http://www.columbia.edu/kermit/ckuins.html#x9
-  15. http://www.columbia.edu/kermit/ckuins.html#x10
-  16. http://www.columbia.edu/kermit/ckuins.html#x11
-  17. http://www.columbia.edu/kermit/ckuins.html#x12
-  18. http://www.columbia.edu/kermit/ckuins.html#x13
-  19. http://www.columbia.edu/kermit/ckuins.html#x14
-  20. http://www.columbia.edu/kermit/ckuins.html#x15
-  21. http://www.columbia.edu/kermit/ckuins.html#x16
-  22. http://www.columbia.edu/kermit/ckuins.html#x16
-  23. http://www.columbia.edu/kermit/ckuins.html#top
-  24. http://www.columbia.edu/kermit/ckuins.html#contents
-  25. http://www.columbia.edu/kermit/ckuins.html#x1
-  26. http://www.columbia.edu/kermit/ckccfg.html
-  27. http://www.columbia.edu/kermit/ckcbwr.html
-  28. http://www.columbia.edu/kermit/ckubwr.html
-  29. http://www.columbia.edu/kermit/ckcplm.html
-  30. http://www.columbia.edu/kermit/ckuins.html#x2
-  31. http://www.columbia.edu/kermit/x3
-  32. http://www.columbia.edu/kermit/ckuins.html#x4
-  33. http://www.columbia.edu/kermit/ckuins.html#top
-  34. http://www.columbia.edu/kermit/ckuins.html#contents
-  35. http://www.columbia.edu/kermit/ckuins.html#x2
-  36. http://www.columbia.edu/kermit/ckuins.html#x0
-  37. ftp://kermit.columbia.edu/kermit/archives/cku211.tar.Z
-  38. ftp://kermit.columbia.edu/kermit/archives/cku211.tar.gz
-  39. ftp://kermit.columbia.edu/kermit/archives/cku211.tar
-  40. http://www.columbia.edu/kermit/ckuins.html#x7
-  41. http://www.columbia.edu/kermit/ckuins.html#x5
-  42. http://www.columbia.edu/kermit/ckuins.html#x5
-  43. http://www.columbia.edu/kermit/ckuins.html#x16
-  44. http://www.columbia.edu/kermit/ckuins.html#top
-  45. http://www.columbia.edu/kermit/ckuins.html#contents
-  46. http://www.columbia.edu/kermit/ckuins.html#x3
-  47. http://www.columbia.edu/kermit/ckuins.html#x1
-  48. http://www.columbia.edu/kermit/ckuins.html#x5
-  49. http://www.columbia.edu/kermit/ckuins.html#X10
-  50. http://www.columbia.edu/kermit/ckuins.html#x11
-  51. http://www.columbia.edu/kermit/ckuins.html#x10
-  52. http://www.columbia.edu/kermit/ckuins.html#x3
-  53. http://www.columbia.edu/kermit/ck80packages.html
-  54. http://www.columbia.edu/kermit/ckuins.html#x10
-  55. http://www.columbia.edu/kermit/ckuins.html#top
-  56. http://www.columbia.edu/kermit/ckuins.html#contents
-  57. http://www.columbia.edu/kermit/ckuins.html#x4
-  58. http://www.columbia.edu/kermit/ckuins.html#x2
-  59. ftp://kermit.columbia.edu/kermit/bin/
-  60. http://www.columbia.edu/kermit/ck80binaries.html
-  61. http://www.columbia.edu/kermit/ckuins.html#x7
-  62. http://www.columbia.edu/kermit/ckuins.html#build
-  63. http://www.columbia.edu/kermit/ckuins.html#x5
-  64. http://www.columbia.edu/kermit/ckuins.html#x4
-  65. http://www.columbia.edu/kermit/ckuins.html#x4
-  66. mailto:kermit@columbia.edu
-  67. http://www.columbia.edu/kermit/ckuins.html#top
-  68. http://www.columbia.edu/kermit/ckuins.html#contents
-  69. http://www.columbia.edu/kermit/ckuins.html#x5
-  70. http://www.columbia.edu/kermit/ckuins.html#x3
-  71. http://www.columbia.edu/kermit/ckuins.html#x8
-  72. http://www.columbia.edu/kermit/ckuins.html#x9
-  73. ftp://kermit.columbia.edu/kermit/c-kermit/makefile
-  74. ftp://kermit.columbia.edu/kermit/c-kermit/ckpker.mk
-  75. ftp://kermit.columbia.edu/kermit/c-kermit/ckubsd.mak
-  76. http://www.columbia.edu/kermit/ckuins.html#x5
-  77. mailto:kermit-support@columbia.edu
-  78. ftp://kermit.columbia.edu/kermit/c-kermit/makefile
-  79. http://www.columbia.edu/kermit/ckuins.html#x7
-  80. mailto:kermit-support@columbia.edu
-  81. ftp://kermit.columbia.edu/kermit/c-kermit/makefile
-  82. http://www.columbia.edu/kermit/ckuins.html#x5.4
-  83. http://www.columbia.edu/kermit/ckuins.html#x10
-  84. http://www.columbia.edu/kermit/ckuins.html#x11
-  85. http://www.columbia.edu/kermit/ckuins.html#x5
-  86. http://www.columbia.edu/kermit/iksd.html
-  87. http://www.columbia.edu/kermit/ckuins.html#top
-  88. http://www.columbia.edu/kermit/ckuins.html#contents
-  89. http://www.columbia.edu/kermit/ckuins.html#x4.1
-  90. http://www.columbia.edu/kermit/ckccfg.html
-  91. http://www.columbia.edu/kermit/ckuins.html#x4.1
-  92. http://www.columbia.edu/kermit/ckuins.html#x4.2
-  93. http://www.columbia.edu/kermit/ckuins.html#x4.3
-  94. http://www.columbia.edu/kermit/ckuins.html#x4.4
-  95. http://www.columbia.edu/kermit/ckuins.html#x4.5
-  96. http://www.columbia.edu/kermit/ckccfg.html
-  97. http://www.columbia.edu/kermit/ckccfg.html#x8
-  98. http://www.columbia.edu/kermit/iksd.html
-  99. http://www.columbia.edu/kermit/iksd.html
- 100. ftp://kermit.columbia.edu/kermit/c-kermit/ckufio.c
- 101. ftp://kermit.columbia.edu/kermit/c-kermit/ckufio.c
- 102. mailto:kermit-support@columbia.edu
- 103. ftp://kermit.columbia.edu/kermit/c-kermit/ckcmai.c
- 104. http://www.columbia.edu/kermit/ckuins.html#x15
- 105. ftp://kermit.columbia.edu/kermit/c-kermit/ckutio.c
- 106. ftp://kermit.columbia.edu/kermit/c-kermit/ckufio.c
- 107. ftp://kermit.columbia.edu/kermit/c-kermit/ckutio.c
- 108. ftp://kermit.columbia.edu/kermit/c-kermit/ckufio.c
- 109. ftp://kermit.columbia.edu/kermit/c-kermit/ckcnet.c
- 110. ftp://kermit.columbia.edu/kermit/c-kermit/ckcnet.c
- 111. ftp://kermit.columbia.edu/kermit/c-kermit/ckutio.c
- 112. ftp://kermit.columbia.edu/kermit/c-kermit/ckcuni.c
- 113. mailto:kermit-support@columbia.edu
- 114. http://www.columbia.edu/kermit/ckuins.html#top
- 115. http://www.columbia.edu/kermit/ckuins.html#contents
- 116. http://www.columbia.edu/kermit/ckuins.html#x4
- 117. http://www.columbia.edu/kermit/ckuins.html#x4.2
- 118. http://www.columbia.edu/kermit/ckuins.html#x4.0
- 119. ftp://kermit.columbia.edu/kermit/c-kermit/makefile
- 120. ftp://kermit.columbia.edu/kermit/c-kermit/ckubwr.txt
- 121. http://www.columbia.edu/kermit/ckubwr.html
- 122. ftp://kermit.columbia.edu/kermit/c-kermit/ckwart.c
- 123. ftp://kermit.columbia.edu/kermit/c-kermit/ckcpro.w
- 124. ftp://kermit.columbia.edu/kermit/c-kermit/ckcpro.c
- 125. http://www.columbia.edu/kermit/ckuins.html#top
- 126. http://www.columbia.edu/kermit/ckuins.html#contents
- 127. http://www.columbia.edu/kermit/ckuins.html#x4
- 128. http://www.columbia.edu/kermit/ckuins.html#x4.3
- 129. http://www.columbia.edu/kermit/ckuins.html#x4.1
- 130. http://www.columbia.edu/kermit/ckuins.html#x5
- 131. http://www.columbia.edu/kermit/ckuins.html#top
- 132. http://www.columbia.edu/kermit/ckuins.html#contents
- 133. http://www.columbia.edu/kermit/ckuins.html#x4
- 134. http://www.columbia.edu/kermit/ckuins.html#x4.4
- 135. http://www.columbia.edu/kermit/ckuins.html#x4.2
- 136. http://www.columbia.edu/kermit/ckuins.html#top
- 137. http://www.columbia.edu/kermit/ckuins.html#contents
- 138. http://www.columbia.edu/kermit/ckuins.html#x4
- 139. http://www.columbia.edu/kermit/ckuins.html#x4.5
- 140. http://www.columbia.edu/kermit/ckuins.html#x4.3
- 141. ftp://kermit.columbia.edu/kermit/c-kermit/ckpker.mk
- 142. http://www.columbia.edu/kermit/ckuins.html#top
- 143. http://www.columbia.edu/kermit/ckuins.html#contents
- 144. http://www.columbia.edu/kermit/ckuins.html#x4
- 145. http://www.columbia.edu/kermit/ckuins.html#x4.4
- 146. ftp://kermit.columbia.edu/kermit/c-kermit/makefile
- 147. ftp://kermit.columbia.edu/kermit/c-kermit/makefile
- 148. ftp://kermit.columbia.edu/kermit/c-kermit/ckcpro.w
- 149. http://www.columbia.edu/kermit/ckuins.html#top
- 150. http://www.columbia.edu/kermit/ckuins.html#contents
- 151. http://www.columbia.edu/kermit/ckuins.html#x6
- 152. http://www.columbia.edu/kermit/ckuins.html#x4
- 153. http://www.columbia.edu/kermit/ckuins.html#x5.1
- 154. http://www.columbia.edu/kermit/ckuins.html#x5.2
- 155. http://www.columbia.edu/kermit/ckuins.html#x5.3
- 156. http://www.columbia.edu/kermit/ckuins.html#x5.4
- 157. http://www.columbia.edu/kermit/
- 158. http://www.columbia.edu/kermit/ckuins.html#x5.4
- 159. http://www.columbia.edu/kermit/ckuins.html#x5.3
- 160. ftp://kermit.columbia.edu/kermit/c-kermit/COPYING.TXT
- 161. ftp://kermit.columbia.edu/kermit/c-kermit/ckermit.ini
- 162. http://www.columbia.edu/kermit/ckuins.html#x5.1
- 163. ftp://kermit.columbia.edu/kermit/c-kermit/ckermod.ini
- 164. ftp://kermit.columbia.edu/kermit/c-kermit/ckermit70.txt
- 165. http://www.columbia.edu/kermit/ck60manual
- 166. http://www.columbia.edu/kermit/ckermit70.html
- 167. ftp://kermit.columbia.edu/kermit/c-kermit/ckermit80.txt
- 168. http://www.columbia.edu/kermit/ck60manual
- 169. http://www.columbia.edu/kermit/ckermit80.html
- 170. ftp://kermit.columbia.edu/kermit/c-kermit/ckcbwr.txt
- 171. http://www.columbia.edu/kermit/ckcbwr.html
- 172. ftp://kermit.columbia.edu/kermit/c-kermit/ckubwr.txt
- 173. http://www.columbia.edu/kermit/ckubwr.html
- 174. ftp://kermit.columbia.edu/kermit/c-kermit/ckuins.txt
- 175. http://www.columbia.edu/kermit/ckuins.html
- 176. ftp://kermit.columbia.edu/kermit/c-kermit/ckccfg.txt
- 177. http://www.columbia.edu/kermit/ckccfg.html
- 178. ftp://kermit.columbia.edu/kermit/c-kermit/ckcplm.txt
- 179. http://www.columbia.edu/kermit/ckcplm.html
- 180. ftp://kermit.columbia.edu/kermit/c-kermit/ca_certs.pem
- 181. http://www.columbia.edu/kermit/ckuins.html#x16"
- 182. ftp://kermit.columbia.edu/kermit/c-kermit/makefile
- 183. http://www.columbia.edu/kermit/ckuins.html#x?
- 184. http://www.columbia.edu/kermit/ckuins.html#x11
- 185. http://www.columbia.edu/kermit/ckuins.html#x5.2
- 186. http://www.columbia.edu/kermit/ckermit.html#download
- 187. http://www.columbia.edu/kermit/ck80binaries.html
- 188. http://www.columbia.edu/kermit/ckermit.html#download
- 189. http://www.columbia.edu/kermit/ckuins.html#top
- 190. http://www.columbia.edu/kermit/ckuins.html#contents
- 191. http://www.columbia.edu/kermit/ckuins.html#x7
- 192. http://www.columbia.edu/kermit/ckuins.html#x5
- 193. http://www.columbia.edu/kermit/ckuins.html#top
- 194. http://www.columbia.edu/kermit/ckuins.html#contents
- 195. http://www.columbia.edu/kermit/ckuins.html#x8
- 196. http://www.columbia.edu/kermit/ckuins.html#x6
- 197. ftp://kermit.columbia.edu/kermit/c-kermit/ckutio.c
- 198. ftp://kermit.columbia.edu/kermit/c-kermit/ckutio.c
- 199. http://www.columbia.edu/kermit/ckuins.html#x4.0
- 200. ftp://kermit.columbia.edu/kermit/c-kermit/ckcdeb.h
- 201. ftp://kermit.columbia.edu/kermit/c-kermit/ckufio.c
- 202. ftp://kermit.columbia.edu/kermit/c-kermit/ckufio.c
- 203. ftp://kermit.columbia.edu/kermit/c-kermit/ckutio.c
- 204. http://www.columbia.edu/kermit/ckuins.html#x10
- 205. http://www.columbia.edu/kermit/ckccfg.html#x2
- 206. http://www.columbia.edu/kermit/ckccfg.html
- 207. http://www.columbia.edu/kermit/ckuins.html#x4
- 208. http://www.columbia.edu/kermit/ckuins.html#x10
- 209. ftp://kermit.columbia.edu/kermit/c-kermit/ckutio.c
- 210. ftp://kermit.columbia.edu/kermit/c-kermit/ckutio.c
- 211. ftp://kermit.columbia.edu/kermit/c-kermit/ckutio.c
- 212. http://www.columbia.edu/kermit/ckuins.html#x9.4
- 213. mailto:kermit-support@columbia.edu
- 214. http://www.columbia.edu/kermit/ckuins.html#top
- 215. http://www.columbia.edu/kermit/ckuins.html#contents
- 216. http://www.columbia.edu/kermit/ckuins.html#x9
- 217. http://www.columbia.edu/kermit/ckuins.html#x7
- 218. http://www.columbia.edu/kermit/ckccfg.html
- 219. http://www.columbia.edu/kermit/ckccfg.html
- 220. http://www.columbia.edu/kermit/ckuins.html#top
- 221. http://www.columbia.edu/kermit/ckuins.html#contents
- 222. http://www.columbia.edu/kermit/ckuins.html#x10
- 223. http://www.columbia.edu/kermit/ckuins.html#x8
- 224. http://www.columbia.edu/kermit/ckuins.html#x9.1
- 225. http://www.columbia.edu/kermit/ckuins.html#x9.1.1
- 226. http://www.columbia.edu/kermit/ckuins.html#x9.1.2
- 227. http://www.columbia.edu/kermit/ckuins.html#x9.1.3
- 228. http://www.columbia.edu/kermit/ckuins.html#x9.2
- 229. http://www.columbia.edu/kermit/ckuins.html#x9.3
- 230. http://www.columbia.edu/kermit/ckuins.html#x9.4
- 231. http://www.columbia.edu/kermit/ckuins.html#x9.5
- 232. http://www.columbia.edu/kermit/ckuins.html#x9.6
- 233. http://www.columbia.edu/kermit/ckuins.html#x9.7
- 234. http://www.columbia.edu/kermit/ckuins.html#x9.8
- 235. http://www.columbia.edu/kermit/ckuins.html#x9.9
- 236. ftp://kermit.columbia.edu/kermit/c-kermit/ckutio.c
- 237. http://www.columbia.edu/kermit/ckuins.html#top
- 238. http://www.columbia.edu/kermit/ckuins.html#x9
- 239. http://www.columbia.edu/kermit/ckuins.html#contents
- 240. http://www.columbia.edu/kermit/ckuins.html#x9.2
- 241. http://www.columbia.edu/kermit/ckuins.html#x9.1.1
- 242. http://www.columbia.edu/kermit/ckuins.html#x9.1.2
- 243. http://www.columbia.edu/kermit/ckuins.html#x9.1.3
- 244. http://www.columbia.edu/kermit/ckuins.html#top
- 245. http://www.columbia.edu/kermit/ckuins.html#contents
- 246. http://www.columbia.edu/kermit/ckuins.html#x9
- 247. http://www.columbia.edu/kermit/ckuins.html#x9.1
- 248. http://www.columbia.edu/kermit/ckuins.html#x9.1.3
- 249. http://www.columbia.edu/kermit/ckuins.html#x9.1.1
- 250. http://www.columbia.edu/kermit/ckuins.html#top
- 251. http://www.columbia.edu/kermit/ckuins.html#contents
- 252. http://www.columbia.edu/kermit/ckuins.html#x9
- 253. http://www.columbia.edu/kermit/ckuins.html#x9.1
- 254. http://www.columbia.edu/kermit/ckuins.html#x9.2
- 255. http://www.columbia.edu/kermit/ckuins.html#x9.1.2
- 256. http://www.opengroup.org/onlinepubs/007904975/
- 257. http://www.columbia.edu/kermit/ckuins.html#x9.1.1
- 258. http://www.columbia.edu/kermit/ckuins.html#top
- 259. http://www.columbia.edu/kermit/ckuins.html#contents
- 260. http://www.columbia.edu/kermit/ckuins.html#x9
- 261. http://www.columbia.edu/kermit/ckuins.html#x9.1
- 262. http://www.columbia.edu/kermit/ckuins.html#x9.3
- 263. http://www.columbia.edu/kermit/ckuins.html#x9.1
- 264. http://www.columbia.edu/kermit/ckuins.html#top
- 265. http://www.columbia.edu/kermit/ckuins.html#contents
- 266. http://www.columbia.edu/kermit/ckuins.html#x9
- 267. http://www.columbia.edu/kermit/ckuins.html#x9.4
- 268. http://www.columbia.edu/kermit/ckuins.html#x9.2
- 269. ftp://kermit.columbia.edu/kermit/c-kermit/ckufio.c
- 270. ftp://kermit.columbia.edu/kermit/c-kermit/ckutio.c
- 271. ftp://kermit.columbia.edu/kermit/c-kermit/ckufio.c
- 272. http://www.columbia.edu/kermit/ckuins.html#top
- 273. http://www.columbia.edu/kermit/ckuins.html#contents
- 274. http://www.columbia.edu/kermit/ckuins.html#x9
- 275. http://www.columbia.edu/kermit/ckuins.html#x9.5
- 276. http://www.columbia.edu/kermit/ckuins.html#x9.3
- 277. ftp://kermit.columbia.edu/kermit/c-kermit/ckutio.c
- 278. ftp://kermit.columbia.edu/kermit/c-kermit/ckcdeb.h
- 279. http://www.columbia.edu/kermit/ckuins.html#top
- 280. http://www.columbia.edu/kermit/ckuins.html#contents
- 281. http://www.columbia.edu/kermit/ckuins.html#x9
- 282. http://www.columbia.edu/kermit/ckuins.html#x9.6
- 283. http://www.columbia.edu/kermit/ckuins.html#x9.4
- 284. ftp://kermit.columbia.edu/kermit/c-kermit/ckcdeb.h
- 285. ftp://kermit.columbia.edu/kermit/c-kermit/ckuus3.c
- 286. ftp://kermit.columbia.edu/kermit/c-kermit/ckutio.c
- 287. http://www.columbia.edu/kermit/ckuins.html#top
- 288. http://www.columbia.edu/kermit/ckuins.html#contents
- 289. http://www.columbia.edu/kermit/ckuins.html#x9
- 290. http://www.columbia.edu/kermit/ckuins.html#x9.7
- 291. http://www.columbia.edu/kermit/ckuins.html#x9.5
- 292. http://www.columbia.edu/kermit/ckuins.html#top
- 293. http://www.columbia.edu/kermit/ckuins.html#contents
- 294. http://www.columbia.edu/kermit/ckuins.html#x9
- 295. http://www.columbia.edu/kermit/ckuins.html#x9.8
- 296. http://www.columbia.edu/kermit/ckuins.html#x9.6
- 297. http://www.columbia.edu/kermit/ckuins.html#top
- 298. http://www.columbia.edu/kermit/ckuins.html#contents
- 299. http://www.columbia.edu/kermit/ckuins.html#x9
- 300. http://www.columbia.edu/kermit/ckuins.html#x9.9
- 301. http://www.columbia.edu/kermit/ckuins.html#x9.7
- 302. ftp://kermit.columbia.edu/kermit/c-kermit/ckutio.c
- 303. ftp://kermit.columbia.edu/kermit/c-kermit/ckutio.c
- 304. ftp://kermit.columbia.edu/kermit/c-kermit/ckcdeb.h
- 305. ftp://kermit.columbia.edu/kermit/c-kermit/ckufio.c
- 306. http://www.columbia.edu/kermit/ckuins.html#top
- 307. http://www.columbia.edu/kermit/ckuins.html#contents
- 308. http://www.columbia.edu/kermit/ckuins.html#x9
- 309. http://www.columbia.edu/kermit/ckuins.html#x10
- 310. http://www.columbia.edu/kermit/ckuins.html#x9.8
- 311. http://www.columbia.edu/kermit/ckuins.html#top
- 312. http://www.columbia.edu/kermit/ckuins.html#contents
- 313. http://www.columbia.edu/kermit/ckuins.html#x11
- 314. http://www.columbia.edu/kermit/ckuins.html#x9
- 315. ftp://kermit.columbia.edu/kermit/c-kermit/ckutio.c
- 316. http://www.columbia.edu/kermit/ckuins.html#x11
- 317. http://www.columbia.edu/kermit/ckuins.html#top
- 318. http://www.columbia.edu/kermit/ckuins.html#contents
- 319. http://www.columbia.edu/kermit/ckuins.html#x12
- 320. http://www.columbia.edu/kermit/ckuins.html#x10
- 321. ftp://kermit.columbia.edu/kermit/c-kermit/ckutio.c
- 322. ftp://kermit.columbia.edu/kermit/c-kermit/ckufio.c
- 323. http://www.columbia.edu/kermit/ckuins.html#top
- 324. http://www.columbia.edu/kermit/ckuins.html#contents
- 325. http://www.columbia.edu/kermit/ckuins.html#x13
- 326. http://www.columbia.edu/kermit/ckuins.html#x11
- 327. http://www.columbia.edu/kermit/ckuins.html#top
- 328. http://www.columbia.edu/kermit/ckuins.html#contents
- 329. http://www.columbia.edu/kermit/ckuins.html#x14
- 330. http://www.columbia.edu/kermit/ckuins.html#x12
- 331. ftp://kermit.columbia.edu/kermit/c-kermit/ckubwr.txt
- 332. ftp://kermit.columbia.edu/kermit/c-kermit/ckutio.c
- 333. http://www.columbia.edu/kermit/ckuins.html#top
- 334. http://www.columbia.edu/kermit/ckuins.html#contents
- 335. http://www.columbia.edu/kermit/ckuins.html#x15
- 336. http://www.columbia.edu/kermit/ckuins.html#x13
- 337. http://www.columbia.edu/kermit/ckuins.html#top
- 338. http://www.columbia.edu/kermit/ckuins.html#contents
- 339. http://www.columbia.edu/kermit/ckuins.html#x16
- 340. http://www.columbia.edu/kermit/ckuins.html#x14
- 341. http://www.columbia.edu/kermit/iksd.html#x4.2
- 342. http://www.columbia.edu/kermit/iksd.html
- 343. http://www.columbia.edu/kermit/ckermit2.html
- 344. http://www.columbia.edu/kermit/ckuins.html#top
- 345. http://www.columbia.edu/kermit/ckuins.html#contents
- 346. http://www.columbia.edu/kermit/ckuins.html#x17
- 347. http://www.columbia.edu/kermit/ckuins.html#x15
- 348. http://www.columbia.edu/kermit/security.html
- 349. http://www.columbia.edu/kermit/security80.html
- 350. http://www.columbia.edu/kermit/cuiksd.html
- 351. ftp://kermit.columbia.edu/kermit/c-kermit/ca_certs.pem
- 352. http://www.columbia.edu/kermit/ckuins.html#top
- 353. http://www.columbia.edu/kermit/ckuins.html#contents
- 354. http://www.columbia.edu/kermit/ckuins.html#x16
- 355. http://www.columbia.edu/kermit/skermit.html
- 356. http://www.columbia.edu/kermit/ckuins.html#top
- 357. http://www.columbia.edu/kermit/ckuins.html#contents
- 358. http://www.columbia.edu/kermit/ckermit.html
- 359. http://www.columbia.edu/kermit/ck80.html
- 360. http://www.columbia.edu/kermit/index.html
index b26801d..b93227d 100644 (file)
--- a/ckuker.nr
+++ b/ckuker.nr
@@ -1,31 +1,32 @@
-.\" @(#) kermit.1 8.0.211 2004/04/10 Columbia University
-.TH KERMIT 1 "APRIL 2004" "User Manuals"
+.\" @(#) kermit.1 8.0.211 2011/06/07 Columbia University
+.TH KERMIT 1 "JUNE 2011" "User Manuals"
 .na
 .SH NAME
 kermit \-
-.B C-Kermit 8.0:
-transport- and platform-independent
+.B C\(hyKermit 9.0:
+transport\(hy and platform\(hyindependent
 interactive and scriptable communications software.
 .IP
 
-This document is intended to give the beginner sufficient information to make
-basic (if not advanced) use of C-Kermit 8.0.  Although it might be rather long
-for a Unix manual page, it's still far shorter than the C-Kermit manual, which
-should be consulted for advanced topics such as customization, character-sets,
-scripting, etc. We also attempt to provide a clear structural overview of
-C-Kermit's many capabilities, functional areas, states, and modes and their
-interrelation, that should be helpful to beginners and veterans alike, as well
-as to those upgrading to version 8.0 from earlier releases.
+This document is intended to give the beginner sufficient information to
+make basic (if not advanced) use of C\(hyKermit 9.0.  Although it might be
+rather long for a Unix manual page, it's still far shorter than the
+C\(hyKermit manual, which should be consulted for advanced topics such as
+customization, character\(hysets, scripting, etc. We also attempt to provide
+a clear structural overview of C\(hyKermit's many capabilities, functional
+areas, states, and modes and their interrelation, that should be helpful to
+beginners and veterans alike, as well as to those upgrading to version 9.0
+from earlier releases.
 .PP
 This document is also available as a Web page at:
 .IP
 http://www.columbia.edu/kermit/ckututor.html
 .SH DESCRIPTION
-C-Kermit is an all-purpose communications software package from the Kermit
+C\(hyKermit is an all\(hypurpose communications software package from the Kermit
 Project at Columbia University that:
 .PP
 .nf
-\(bu   Is portable to many platforms, Unix and non-Unix alike.
+\(bu   Is portable to many platforms, Unix and non\(hyUnix alike.
 .br
 \(bu   Can make both serial and network connections.
 .br
@@ -35,39 +36,39 @@ Project at Columbia University that:
 .br
 \(bu   Can convert character sets in the terminal session.
 .br
-\(bu   Can convert character sets during text-file file transfer.
+\(bu   Can convert character sets during text\(hyfile file transfer.
 .br
 \(bu   Is customizable in every aspect of its operation.
 .fi
 .PP
-C-Kermit is a modem program, a Telnet client, an Rlogin client, an FTP
+C\(hyKermit is a modem program, a Telnet client, an Rlogin client, an FTP
 client, an HTTP client, and on selected platforms, also an X.25 client. It
-can make its own secure Internet connections using IETF-approved security
+can make its own secure Internet connections using IETF\(hyapproved security
 methods including Kerberos IV, Kerberos V, SSL/TLS, and SRP and it can also
 make SSH connections through your external SSH client application. It can
-be the far-end file-transfer or client/server partner of your desktop
+be the far\(hyend file\(hytransfer or client/server partner of your desktop
 Kermit client. It can also accept incoming dialed and network connections.
 It can even be installed as an Internet service on its own standard TCP
 socket, 1649 [RFC2839, RFC2840].
 .PP
 And perhaps most important, everything you can do "by hand" (interactively)
-with C-Kermit, can be "scripted" (automated) using its built-in
-cross-platform transport-independent script programming language, which
+with C\(hyKermit, can be "scripted" (automated) using its built\(hyin
+cross\(hyplatform transport\(hyindependent script programming language, which
 happens to be identical to its interactive command language.
 .PP
-This manual page offers an overview of C-Kermit 8.0 for Unix ("Unix" is an
-operating system family that includes AIX, DG/UX, FreeBSD, HP-UX, IRIX,
+This manual page offers an overview of C\(hyKermit 9.0 for Unix ("Unix" is an
+operating system family that includes AIX, DG/UX, FreeBSD, HP\(hyUX, IRIX,
 Linux, Mac OS X, NetBSD, OpenBSD, Open Server, Open Unix, QNX, Solaris,
 SunOS, System V R3, System V R4, Tru64 Unix, Unixware, Xenix, and many
-others). For thorough coverage, please consult the published C-Kermit
+others). For thorough coverage, please consult the published C\(hyKermit
 manual and supplements (see DOCUMENTATION below). For further information
-about C-Kermit, Kermit software for other platforms, and Kermit manuals,
+about C\(hyKermit, Kermit software for other platforms, and Kermit manuals,
 visit the Kermit Project website:
 .PP
   http://www.columbia.edu/kermit/
 .PP
-This is a longer-than-average manual page, and yet it barely scratches the
-surface. Don't be daunted. C-Kermit is a large and complex package,
+This is a longer\(hythan\(hyaverage manual page, and yet it barely scratches the
+surface. Don't be daunted. C\(hyKermit is a large and complex package,
 evolving over decades of practice and experience, but that doesn't mean
 it's hard to learn or use. Its most commonly used functions are explained
 here with pointers to additional information elsewhere.
@@ -76,7 +77,7 @@ here with pointers to additional information elsewhere.
 .I filename
 .B ] [
 .I options
-.B ] [ {=,--,+}
+.B ] [ {=,\-\-,+}
 .I text
 .B ] ]
 .PP
@@ -85,12 +86,12 @@ or:
 .B kermit 
 .I URL
 .PP
-If the first command-line argument is the name of a file, interactive-mode
-commands are executed from the file. The '=' (or "--") argument tells
+If the first command\(hyline argument is the name of a file, interactive\(hymode
+commands are executed from the file. The '=' (or "\-\-") argument tells
 Kermit not to parse the remainder of the command line, but to make the
 words following '=' available as \e%1, \e%2, ... \e%9. The "+" argument is
 like "=" but for use in "kerbang scripts" (explained below). A second
-command-line format allows the one and only argument to be a Telnet, FTP,
+command\(hyline format allows the one and only argument to be a Telnet, FTP,
 HTTP, or IKSD URL.
 .PP
 Order of execution:
@@ -100,338 +101,338 @@ The command file (if any).
 .TP
 .nf
  2.
-The initialization file, if any, unless suppressed with -Y.
+The initialization file, if any, unless suppressed with \-Y.
 .fi
 .TP
  3.
 The customization file (if it is executed by the initialization file).
 .TP
  4.
-The command-line URL (if any, and if so, execution stops here).
+The command\(hyline URL (if any, and if so, execution stops here).
 .TP
  5.
-Command-line options (if any).
+Command\(hyline options (if any).
 .TP
  6.
 Interactive commands.
 .PP
-Some command-line options can cause actions (such as -s to send a file);
+Some command\(hyline options can cause actions (such as \-s to send a file);
 others just set parameters. If any action options are included on the
-command line, Kermit exits when finished unless also given the -S ("stay")
+command line, Kermit exits when finished unless also given the \-S ("stay")
 option. If no action options are given, no initialization or command files
 contained an EXIT or QUIT command, and no fatal errors occurred, Kermit
 issues its prompt and waits for you to type commands.
 .IP
-Bear in mind that C-Kermit can be built with selected features
+Bear in mind that C\(hyKermit can be built with selected features
 disabled, and also that certain features are not available on all
-platforms. For example, C-Kermit can't be built with TCP/IP
+platforms. For example, C\(hyKermit can't be built with TCP/IP
 support on a platform that does not have TCP/IP header files and
 libraries (and even if Kermit does include TCP/IP support, it
 can't be used to make TCP/IP connections on a computer that does
 not have a TCP/IP stack installed). If your version of lacks
-C-Kermit a feature mentioned here, use its SHOW FEATURES command to
+C\(hyKermit a feature mentioned here, use its SHOW FEATURES command to
 see what might have been excluded.
 .PP
-C-Kermit has three kinds of commands: regular single-letter command-line
-options, extended-format command-line options, and interactive commands.
+C\(hyKermit has three kinds of commands: regular single\(hyletter command\(hyline
+options, extended\(hyformat command\(hyline options, and interactive commands.
 .PP
-Like most Unix commands, C-Kermit can be be given options on the command
-line. But C-Kermit also can be used interactively by giving it commands
-composed of words, which are more intuitive than cryptic command-line
+Like most Unix commands, C\(hyKermit can be be given options on the command
+line. But C\(hyKermit also can be used interactively by giving it commands
+composed of words, which are more intuitive than cryptic command\(hyline
 options, and more flexible too. In other words, you don't have to use
-C-Kermit's command-line options, but they are available if you want to. (By
-the same token, you don't have to use its interactive commands either --
+C\(hyKermit's command\(hyline options, but they are available if you want to. (By
+the same token, you don't have to use its interactive commands either \(hy\(hy
 you can use either or both in any combination.)
 .PP
-C-Kermit is generally installed in the PATH as "kermit", and therefore is
+C\(hyKermit is generally installed in the PATH as "kermit", and therefore is
 invoked by typing the word "kermit" (lowercase) at the shell prompt, and
-then pressing the Return or Enter key. If you wish to include command-line
+then pressing the Return or Enter key. If you wish to include command\(hyline
 options, put them after the word "kermit" but before pressing Return or
 Enter, separated by spaces, for example:
 .PP
-  $ kermit -s ckermit.tar.gz
+  $ kermit \-s ckermit.tar.gz
 .PP
-('$' is the shell prompt; "kermit -s ckermit.tar.gz" is what you type,
+('$' is the shell prompt; "kermit \-s ckermit.tar.gz" is what you type,
 followed by Return or Enter.)
 .SH OPTIONS
-Here is a list of C-Kermit's single-letter command-line options, which
-start with a single dash (-), in ASCII ("alphabetical") order. Alphabetic
-case is significant (-A is not the same as -a).  Action options are 
+Here is a list of C\(hyKermit's single\(hyletter command\(hyline options, which
+start with a single dash (\-), in ASCII ("alphabetical") order. Alphabetic
+case is significant (\-A is not the same as \-a).  Action options are 
 tagged "ACTION".
 .TP
--0
+\-0
 (digit zero)  100% transparent Connect state for
-"in-the-middle" operation: 8 bits, no parity, no
+"in\(hythe\(hymiddle" operation: 8 bits, no parity, no
 escape character, everything passes through.
 .TP
--8
-(digit eight)  Connection is 8-bit clean (this is the
-default in C-Kermit 8.0). Equivalent to the EIGHTBIT
+\-8
+(digit eight)  Connection is 8\(hybit clean (this is the
+default in C\(hyKermit 8.0 and later). Equivalent to the EIGHTBIT
 command, which in turn is a shortcut for SET TERMINAL
 BYTESIZE 8, SET COMMAND BYTESIZE 8, SET PARITY NONE.
 .TP
--9 arg
+\-9 arg
 (digit nine)  Make a connection to an FTP server.
 Equivalent to the FTP OPEN command.
-Argument: IP-address-or-hostname[:optional-TCP-port].
-NOTE: C-Kermit also has a separate FTP command-line
-personality, with regular FTP-like command-line
+Argument: IP\(hyaddress\(hyor\(hyhostname[:optional\(hyTCP\(hyport].
+NOTE: C\(hyKermit also has a separate FTP command\(hyline
+personality, with regular FTP\(hylike command\(hyline
 syntax. More about this below.
 .TP
--A
+\-A
 Kermit is to be started as an Internet service (IKSD)
 (only from inetd.conf).
 .TP
--B
+\-B
 Kermit is running in Batch or Background (no
 controlling terminal). To be used in case Kermit
 doesn't automatically sense its background status.
 Equivalent to the SET BACKGROUND ON command.
 .TP
--C arg
-Interactive-mode Commands to be executed.
+\-C arg
+Interactive\(hymode Commands to be executed.
 Argument: Commands separated by commas, list in
 doublequotes.
 .TP
--D arg
+\-D arg
 Delay before starting to send in Remote mode.
 Equivalent to the SET DELAY command.
 Argument: Number of seconds.
 .TP
--E
+\-E
 Exit automatically when connection closes. Equivalent
-to SET EXIT ON-DISCONNECT ON.
+to SET EXIT ON\-DISCONNECT ON.
 .TP
--F arg
+\-F arg
 Use an open TCP connection.
 Argument: Numeric file descriptor of open TCP
 connection.
-Also see: -j, -J.
+Also see: \-j, \-J.
 .TP
--G arg
+\-G arg
 (ACTION) Get file(s) from server, send contents to standard
 output, which normally would be piped to another
 process.
 Argument: Remote file specification, in quotes if it
 contains metacharacters.
-Also see: -g, -k.
+Also see: \-g, \-k.
 .TP
--H
+\-H
 Suppress program startup Herald and greeting.
 .TP
--I
+\-I
 Tell Kermit it has a reliable connection, to force streaming to be used where
 it normally would not be.  Equivalent to the SET RELIABLE ON command.
 .TP
--J arg
-(ACTION) "Be like Telnet." Like -j but implies -E.  Argument: IP
-hostname/address optionally followed by service.  NOTE: C-Kermit also has a
-separate Telnet command-line personality, with regular Telnet-like
-command-line syntax. More about this below.
+\-J arg
+(ACTION) "Be like Telnet." Like \-j but implies \-E.  Argument: IP
+hostname/address optionally followed by service.  NOTE: C\(hyKermit also has a
+separate Telnet command\(hyline personality, with regular Telnet\(hylike
+command\(hyline syntax. More about this below.
 .TP
--L
-Recursive directory descent for files in -s option.
+\-L
+Recursive directory descent for files in \-s option.
 .TP
--M arg
+\-M arg
 My user name (for use with Telnet, Rlogin, FTP, etc).
 Equivalent to the SET LOGIN USER command.
 Argument: Username string.
 .TP
--O
+\-O
 (ACTION) (Uppercase letter O) Be a server for One command only.
-Also see: -x.
+Also see: \-x.
 .TP
--P
+\-P
 Don't convert file (Path) names of transferred files.
 Equivalent to SET FILE NAMES LITERAL.
 .TP
--Q
+\-Q
 Quick Kermit protocol settings. Equivalent to the FAST
-command. This is the default in C-Kermit 7.0 and later.
+command. This is the default in C\(hyKermit 7.0 and later.
 .TP
--R
-Remote-only (this just makes IF REMOTE true).
+\-R
+Remote\(hyonly (this just makes IF REMOTE true).
 .TP
--S
+\-S
 Stay (enter command parser after action options).
 .TP
--T
-Force Text mode for file transfer; implies -V.
+\-T
+Force Text mode for file transfer; implies \-V.
 Equivalent to SET TRANSFER MODE MANUAL, SET FILE TYPE TEXT.
 .TP
--V
-Disable automatic per-file text/binary switching.
+\-V
+Disable automatic per\(hyfile text/binary switching.
 Equivalent to SET TRANSFER MODE MANUAL.
 .TP
--Y
+\-Y
 Skip (don't execute) the initialization file.
 .TP
--a arg
-As-name for file(s) in -s, -r, or -g.
-Argument: As-name string (alternative filename). When
+\-a arg
+As\(hyname for file(s) in \-s, \-r, or \-g.
+Argument: As\(hyname string (alternative filename). When
 receiving files, this can be a directory name.
 .TP
--b arg
+\-b arg
 Speed for serial device. Equivalent to SET SPEED.
 Argument: Numeric Bits per second for serial
 connections.
 .TP
--c
+\-c
 (ACTION) Enter Connect state before transferring files.
 .TP
--d
+\-d
 Create a debug.log file with detailed debugging
-information (a second -d adds timestamps). Equivalent
+information (a second \-d adds timestamps). Equivalent
 to LOG DEBUG but takes effect sooner.
 .TP
--e arg
-Maximum length for incoming Kermit file-transfer
-packets. Equivalent to SET RECEIVE PACKET-LENGTH.
+\-e arg
+Maximum length for incoming Kermit file\(hytransfer
+packets. Equivalent to SET RECEIVE PACKET\-LENGTH.
 Argument: Length in bytes.
 .TP
--f
+\-f
 (ACTION) Send a FINISH command to a Kermit server.
 .TP
--g arg
+\-g arg
 Get file(s) from a Kermit server.
 Argument: File specification on other computer, in
 quotes if it contains metacharacters. Equivalent to
-GET. Also see: -a, -G, -r.
+GET. Also see: \-a, \-G, \-r.
 .TP
--h
-(ACTION) Print Help text for single-letter command-line options
+\-h
+(ACTION) Print Help text for single\(hyletter command\(hyline options
 (pipe thru 'more' to prevent scrolling).
 .TP
--i
+\-i
 Force binary (Image) mode for file transfer; implies
--V. Equivalent to SET TRANSFER MODE MANUAL, SET FILE
+\-V. Equivalent to SET TRANSFER MODE MANUAL, SET FILE
 TYPE BINARY.
 .TP
--j arg
+\-j arg
 Make a TCP/IP connection.
 Argument: IP host name/address and optional service
 name or number. Equivalent to the TELNET command.
-Also see: -J, -F.
+Also see: \-J, \-F.
 .TP
--k
+\-k
 (ACTION) Receive file(s) to standard output, which normally 
 would be piped to another process.
-Also see: -r, -G.
+Also see: \-r, \-G.
 .TP
--l arg
+\-l arg
 (Lowercase letter L) Make a connection on the given
 serial communications device. Equivalent to the SET
 LINE (SET PORT) command.
 Argument: Serial device name, e.g. /dev/ttyS0.
 .TP
--m arg
-Modem type for use with the -l device. Equivalent to
+\-m arg
+Modem type for use with the \-l device. Equivalent to
 the SET MODEM TYPE command.
 Argument: Modem name as in SET MODEM TYPE command,
 e.g. "usrobotics".
 .TP
--n
+\-n
 (ACTION) Enter Connect state after transferring files (historical).
 .TP
--p arg
+\-p arg
 Parity. Equivalent to the SET PARITY command.
 Argument: One of the following: e(ven), o(dd), m(ark),
 n(one), s(pace).
 .TP
--q
+\-q
 Quiet (suppress most messages). Equivalent to SET QUIET ON.
 .TP
--r
+\-r
 (ACTION) Receive file(s). Equivalent to the RECEIVE command.
-Argument: (none, but see -a)
+Argument: (none, but see \-a)
 .TP
--s arg
+\-s arg
 Send file(s).
 Argument: One or more local file specifications.
 Equivalent to the SEND command.
-Also see: -a.
+Also see: \-a.
 .TP
--t
-(Historical) Xon (Ctrl-Q) Turnaround character for
-half-duplex connections (used on serial linemode
+\-t
+(Historical) Xon (Ctrl\-Q) Turnaround character for
+half\(hyduplex connections (used on serial linemode
 connections to old mainframes). Equivalent to SET
 DUPLEX HALF, SET HANDSHAKE XON.
 .TP
--v arg
+\-v arg
 Window size for Kermit protocol (ignored when
-streaming). Equivalanet to SET WINDOW-SIZE.
+streaming). Equivalanet to SET WINDOW\-SIZE.
 Argument: Number, 1 to 32.
 .TP
--w
+\-w
 Incoming files Write over existing files. Equivalent
 to SET FILE COLLISION OVERWRITE.
 .TP
--x
+\-x
 (ACTION) Enter server mode. Equivalent to the SERVER command.
-Also see: -O.
+Also see: \-O.
 .TP
--y arg
+\-y arg
 Alternative initialization file.
 Argument: Filename.
 .TP
--z
+\-z
 Force foreground behavior. To be used in case Kermit
 doesn't automatically sense its foreground status.
 Equivalent to the SET BACKGROUND OFF command.
 .PP
-Extended command-line options (necessary because single-letter ones are
-about used up) start with two dashes (--), with words rather than single
+Extended command\(hyline options (necessary because single\(hyletter ones are
+about used up) start with two dashes (\-\-), with words rather than single
 letters as option names. If an extended option takes an argument, it is
 separated from the option word by a colon (:). Extended options include:
 
 .TP
--bannerfile:filename
\-\-bannerfile:filename
 File to display upon startup or IKSD login.
 .TP
--cdfile:filename
\-\-cdfile:filename
 File to be sent for display to the client when
 server changes directory (filename is relative to
-the changed-to directory).
+the changed\(hyto directory).
 .TP
--cdmessage:{on,off}
\-\-cdmessage:{on,off}
 Enable/disable the server CD message feature.
 .TP
--help
\-\-help
 Prints usage message for extended options.
 .TP
--helpfile:filename
\-\-helpfile:filename
 Designates a file containing custom text to
-replace the top-level HELP command.
+replace the top\(hylevel HELP command.
 .TP
--nointerrupts
\-\-nointerrupts
 Disables keyboard interrupts.
 .TP
--noperms
\-\-noperms
 Disables the Kermit protocol file Permissions
 attribute, to prevent transmission of file
 permissions (protection) from sender to receiver.
 .TP
--version
-(ACTION) C-Kermit prints its version number.
\-\-version
+(ACTION) C\(hyKermit prints its version number.
 .PP
-Plus several other IKSD-Only options described at:
+Plus several other IKSD\(hyOnly options described at:
 .PP
   http://www.columbia.edu/kermit/iksd.html
 .PP
-See the file-transfer section for examples of command-line invocation.
+See the file\(hytransfer section for examples of command\(hyline invocation.
 .SH COMMAND LANGUAGE
-C-Kermit's interactive command language is the subject of a 622-page book
+C\(hyKermit's interactive command language is the subject of a 622\(hypage book
 and another several hundred pages of updates, far too much for a manual
 page. But it's not hard to get started. At the shell prompt, just type
-"kermit" to get C-Kermit's interactive command prompt:
+"kermit" to get C\(hyKermit's interactive command prompt:
 .PP
 .nf
   $ kermit
-  (/current/directory) C-Kermit>
+  (/current/directory) C\-Kermit>
 .fi
 .PP
 Begin by typing "help" (and then press the Return or Enter key) for a
-top-level overview, read it, and go from there. Your second command should
+top\(hylevel overview, read it, and go from there. Your second command should
 probably be "intro" (introduction). Note the prompt shows your current
 directory (unless you tell Kermit to prompt you with something else).
 .PP
@@ -448,11 +449,11 @@ which sets Kermit's "transfer mode" to "automatic" (whatever that means).
 .PP
 While typing commands, you can abbreviate, ask for help (by pressing the
 "?" key anywhere in a command), complete keywords or filenames (with the
-Tab or Esc key), and edit your typing with Backspace or Delete, Ctrl-W,
-Ctrl-U, etc. You can also recall previous commands, save your command
+Tab or Esc key), and edit your typing with Backspace or Delete, Ctrl\-W,
+Ctrl\-U, etc. You can also recall previous commands, save your command
 history, and who knows what else. Give the INTRO command for details.
 .PP
-C-Kermit has hundreds of commands, and they can be issued in infinite
+C\(hyKermit has hundreds of commands, and they can be issued in infinite
 variety and combinations, including commands for:
 .nf
 .PP
@@ -485,15 +486,15 @@ variety and combinations, including commands for:
 .fi
 And of course QUIT or EXIT to get out and HELP to get help, and for
 programmers: loops, decision making, variables, arrays, associative arrays,
-integer and floating point arithmetic, macros, built-in and user-defined
+integer and floating point arithmetic, macros, built\(hyin and user\(hydefined
 functions, string manipulation, pattern matching, block structure, scoping,
-recursion, and all the rest. To get a list of all C-Kermit's commands, type
+recursion, and all the rest. To get a list of all C\(hyKermit's commands, type
 a question mark (?) at the prompt. To get a description of any command,
 type HELP followed by the name of the command, for example:
 .PP
   help send
 .PP
-The command interruption character is Ctrl-C (hold down the Ctrl key and
+The command interruption character is Ctrl\-C (hold down the Ctrl key and
 press the C key).
 .PP
 The command language "escape character", used to introduce variable names,
@@ -505,7 +506,7 @@ literal backslash in a command, type two of them, e.g.:
 A file containing Kermit commands is called a Kermit command file or Kermit
 script. It can be executed with Kermit's TAKE command:
 .PP
-  (/current/dir) C-Kermit> take commandfile
+  (/current/dir) C\-Kermit> take commandfile
 .PP
 (where "commandfile" is the name of the command file). Please don't pipe a
 command file into Kermit's standard input (which might or might not work);
@@ -599,16 +600,16 @@ scripts that depend on the initialization file, include the command
 .PP
   take \ev(home).kermrc
 .PP
-at the desired spot in the script. By the way, \ev(xxx) is a built-in
+at the desired spot in the script. By the way, \ev(xxx) is a built\(hyin
 variable (xxx is the variable name, "home" in this case). To see what
-built-in variables are available, type "show variables" at the C-Kermit
+built\(hyin variables are available, type "show variables" at the C\(hyKermit
 prompt. To see what else you can show, type "show ?". \em(xxx) is a user
 defined variable (strictly speaking, it is a macro used as a variable).
 .SS Command List
-C-Kermit has more than 200 top-level commands, and some of these, such as
+C\(hyKermit has more than 200 top\(hylevel commands, and some of these, such as
 SET, branch off into hundreds of subcommands of their own, so it's not
 practical to describe them all here. Instead, here's a concise list of the
-most commonly used top-level commands, grouped by category. To learn about
+most commonly used top\(hylevel commands, grouped by category. To learn about
 each command, type "help" followed by the command name, e.g. "help set".
 Terms such as Command state and Connect state are explained in subsequent
 sections.
@@ -620,7 +621,7 @@ are (optional) switches like /PAGE, /NOPAGE, /QUIET, etc, listed in the
 HELP text for each command. Example:
 .PP
 .nf
-  send /recursive /larger:10000 /after:-1week /except:*.txt *
+  send /recursive /larger:10000 /after:\-1week /except:*.txt *
 .fi
 .PP
 which can be read as "send all the files in this directory and all the ones
@@ -631,19 +632,19 @@ Basic Commands
 .RS
 .TP
 HELP
-Requests top-level help.
+Requests top\(hylevel help.
 .TP
 HELP command
 Requests help about the given command.
 .TP
 INTRODUCTION
-Requests a brief introduction to C-Kermit.
+Requests a brief introduction to C\(hyKermit.
 .TP
 LICENSE
-Displays the C-Kermit software copyright and license.
+Displays the C\(hyKermit software copyright and license.
 .TP
 VERSION
-Displays C-Kermit's version number.
+Displays C\(hyKermit's version number.
 .TP
 EXIT [ number ]
 Exits from Kermit with the given
@@ -667,13 +668,13 @@ Shows settings in a given category.
 STATUS
 Tells whether previous command succeeded or failed.
 .TP
-DATE [ date-and/or-time ]
-Shows current date-time or interprets given date-time.
+DATE [ date\(hyand/or\(hytime ]
+Shows current date\(hytime or interprets given date\(hytime.
 .TP
-RUN [ extern-command [ parameters... ]                 
+RUN [ extern\(hycommand [ parameters... ]                 
 Runs the given external command. Synonym: !.
 .TP
-EXEC [ extern-command [ params... ]
+EXEC [ extern\(hycommand [ params... ]
 Kermit overlays itself with the given command.
 .TP
 SUSPEND
@@ -703,7 +704,7 @@ Displays lines from files that match
 the pattern. Synonym: FIND.
 .TP
 DIRECTORY [ options ] [filespec ]
-Lists files (built-in, many options).
+Lists files (built\(hyin, many options).
 .TP
 LS [ options ] [ filespec ]   
 Lists files (runs external "ls" command).
@@ -799,10 +800,10 @@ Opens an FTP connection to the host.
 HTTP [ options ] OPEN host
 Opens an HTTP connection to the host.
 .TP
-PTY external-command
+PTY external\(hycommand
 Runs the command on a pseudoterminal as if it were a connection.
 .TP
-PIPE external-command
+PIPE external\(hycommand
 Runs the command through a pipe as if it were a connection.
 .RE
 .SS
@@ -818,24 +819,24 @@ Redirects the given external command over the connection.
 TELOPT command
 Sends a Telnet protocol command (Telnet connections only).
 .TP
-Ctrl-\eC
+Ctrl\-\eC
 "Escapes back" from Connect state to Command state.
 .TP
-Ctrl-\eB
+Ctrl\-\eB
 (In Connect state) Sends a BREAK signal (serial or Telnet).
 .TP
-Ctrl-\e!
+Ctrl\-\e!
 (In Connect state) Enters inferior shell; "exit" to return.
 .TP
-Ctrl-\e?
-(In Connect state) Shows a menu of other escape-level options.
+Ctrl\-\e?
+(In Connect state) Shows a menu of other escape\(hylevel options.
 .TP
-Ctrl-\eCtrl-\e
+Ctrl\-\eCtrl\-\e
 (In Connect state) Type two
-Ctrl-Backslashes to send one of them.
+Ctrl\-Backslashes to send one of them.
 .TP
 SET ESCAPE [ character ]
-Changes Kermit's Connect-state escape character.
+Changes Kermit's Connect\(hystate escape character.
 .RE
 .SS
 Closing Connections
@@ -843,18 +844,18 @@ Closing Connections
 .TP
 HANGUP
 Hangs up the currently open
-serial-port or network connection.
+serial\(hyport or network connection.
 .TP
 CLOSE
 Closes the currently open
-serial-port or network connection.
+serial\(hyport or network connection.
 .TP
 SET LINE (with no devicename)
 Closes the currently open
-serial-port or network connection.
+serial\(hyport or network connection.
 .TP
 SET HOST (with no hostname)
-Closes the currently open serial-port or network connection.
+Closes the currently open serial\(hyport or network connection.
 .TP
 FTP CLOSE
 Closes the currently open FTP connection.
@@ -872,29 +873,29 @@ Suppresses warning about open connections on exit or close.
 File Transfer
 .RS
 .TP
-SEND [ options ] filename [ as-name ]
+SEND [ options ] filename [ as\(hyname ]
 Sends the given file. Synonym: S.
 .TP
 SEND [ options ] filespec
 Sends all files that match.
 .TP
 RESEND [ options ] filespec
-Resumes an interupted SEND from the point of failure.
+Resumes an interrupted SEND from the point of failure.
 .TP
-RECEIVE [ options ] [ as-name ]                    
+RECEIVE [ options ] [ as\(hyname ]                    
 Waits passively for files to arrive. Synonym: R.
 .TP
 LOG TRANSACTIONS [ filename ]
 Keeps a record of file transfers.
 .TP
 FAST
-Use fast file-transfer settings (default).
+Use fast file\(hytransfer settings (default).
 .TP
 CAUTIOUS
-Use cautious and less fast file-transfer settings.
+Use cautious and less fast file\(hytransfer settings.
 .TP
 ROBUST
-Use ultra-conservative and slow file-transfer settings.
+Use ultra\(hyconservative and slow file\(hytransfer settings.
 .TP
 STATISTICS [ options ] 
 Gives statistics about the most recent file transfer.
@@ -909,7 +910,7 @@ LOG SESSION [ filename ]
 Captures remote text or files without protocol.
 .TP
 SET PROTOCOL [ name... ]
-Tells Kermit to use an external file-transfer protocol.
+Tells Kermit to use an external file\(hytransfer protocol.
 .TP
 FTP { PUT, MPUT, GET, MGET, ... }
 FTP client commands.
@@ -940,19 +941,19 @@ Logs in to a Kermit server or IKSD that requires it.
 [ REMOTE ] LOGOUT
 Logs out from a Kermit server or IKSD.
 .TP
-SEND [ options ] filename [ as-name ]                   
+SEND [ options ] filename [ as\(hyname ]                   
 Sends the given file to the server. Synonyms: S, PUT.
 .TP
 SEND [ options ] filespec
 Sends all files that match.
 .TP
 RESEND [ options ] filespec
-Resumes an interupted SEND from the point of failure.
+Resumes an interrupted SEND from the point of failure.
 .TP
-GET [ options ] remote-filespec
+GET [ options ] remote\(hyfilespec
 Asks the server to send the given files. Synonym: G.
 .TP
-REGET [ options ] remote-filespec
+REGET [ options ] remote\(hyfilespec
 Resumes an interrupted GET from the point of failure.
 .TP
 REMOTE CD [ directory ]
@@ -972,7 +973,7 @@ REMOTE [ command... ]
 (Many other commands: "remote ?" for a list).
 .TP
 MAIL [ options ] filespec
-Sends file(s) to be delivered as e-mail (Kermit only).
+Sends file(s) to be delivered as e\(hymail (Kermit only).
 .TP
 FINISH
 Asks the server to exit server state (Kermit only).
@@ -1005,21 +1006,21 @@ Use question mark to feel your way through an unfamiliar command, as in
 this example:
 .PP
 .nf
-  C-Kermit> remote ? One of the following:
+  C\-Kermit> remote ? One of the following:
    assign     directory  kermit     print      rmdir
    cd         exit       login      pwd        set
    copy       help       logout     query      space
    delete     host       mkdir      rename     type
-  C-Kermit> remote set ? One of the following:
+  C\-Kermit> remote set ? One of the following:
    attributes   file         retry        transfer
-   block-check  receive      server       window
-  C-Kermit> remote set file ? One of the following:
-   character-set  incomplete     record-length
+   block\-check  receive      server       window
+  C\-Kermit> remote set file ? One of the following:
+   character\-set  incomplete     record\-length
    collision      names          type
-  C-Kermit> remote set file names ? One of the following:
+  C\-Kermit> remote set file names ? One of the following:
    converted  literal
-  C-Kermit> remote set file names literal
-  C-Kermit>
+  C\-Kermit> remote set file names literal
+  C\-Kermit>
 .PP
 .fi
 This is called menu on demand: you get a menu when you want one, but menus
@@ -1030,25 +1031,25 @@ in the middle of a keyword or filename, not just at the beginning. For
 example, "send x?" lists all the files in the current directory whose names
 start with 'x'.
 .SH INITIALIZATION FILE
-In its default configuration, C-Kermit executes commands from a file 
+In its default configuration, C\(hyKermit executes commands from a file 
 called .kermrc in your home directory when it starts, unless it is given the
--Y or -y command-line option. Custom configurations might substitute a shared
-system-wide initialization file. The SHOW FILE command tells what
+\-Y or \-y command\(hyline option. Custom configurations might substitute a shared
+system\(hywide initialization file. The SHOW FILE command tells what
 initialization file, if any, was used. The standard initialization file
 "chains" to an individual customization file, .mykermc, in the home directory,
 in which each user can establish her/his own preferences, define macros, and
 so on.
 .PP
 Since execution of the initialization file (at least the standard one)
-makes C-Kermit take longer to start, it might be better not to have an
+makes C\(hyKermit take longer to start, it might be better not to have an
 initialization file, especially now that Kermit's default startup
-configuration is well attuned to modern computing and networking -- in
+configuration is well attuned to modern computing and networking \(hy\(hy in
 other words, you no longer have do anything special to make Kermit
 transfers go fast. So instead of having an initialization file that is
 executed every time Kermit starts, you might consider making one or more
 kerbang scripts (with names other that .kermrc) that do NOT include an
 "exit" command, and invoke those when you need the settings, macro
-definitions, and/or scripted actions they contain, and invoke C-Kermit
+definitions, and/or scripted actions they contain, and invoke C\(hyKermit
 directly when you don't.
 .PP
 To put it another way... We still distribute the standard initialization
@@ -1068,7 +1069,7 @@ remote computer, it is said to be in Remote mode (as long as it has not
 made any connections of its own). The local Kermit communicates over the
 communications device or network connection, acting as a conduit between
 the the remote computer and your keyboard and screen. The remote Kermit is
-the file-transfer partner to the local Kermit and communicates only through
+the file\(hytransfer partner to the local Kermit and communicates only through
 its standard input and output.
 .PP
 At any moment, a Kermit program can be in any of the following states. It's
@@ -1091,7 +1092,7 @@ state with the SERVER command. The TAKE command tells Kermit to read
 and execute commands from a file. The (perhaps implied) DO command
 tells Kermit to read and execute commands from a macro definition.
 While in Command state, you can interrupt any command, macro, or
-command file by typing Ctrl-C (hold down the Ctrl key and press the C
+command file by typing Ctrl\-C (hold down the Ctrl key and press the C
 key); this normally brings you back to the prompt.
 .TP
 Shell state
@@ -1111,24 +1112,24 @@ you give a CONNECT, DIAL, TELNET, RLOGIN, or IKSD command. You can
 return to command state by logging out of the remote computer, or by
 typing:
 .sp
-  Ctrl-\ec
+  Ctrl\-\ec
 .sp
 That is: Hold down the Ctrl key and press the backslash key, then let
 go of the Ctrl key and press the C key. This is called escaping back.
-Certain other escape-level commands are also provided; type Ctrl-\e?
+Certain other escape\(hylevel commands are also provided; type Ctrl\-\e?
 for a list. For example, you can enter Shell state with:
 .sp
-  Ctrl-\e!
+  Ctrl\-\e!
 .sp
-To send a Ctrl-\e to the host while in Connect state, type two of them
+To send a Ctrl\-\e to the host while in Connect state, type two of them
 in a row. See HELP CONNECT and HELP SET ESCAPE for more info.
 .TP
-Local file-transfer state
+Local file\(hytransfer state
 In this state, Kermit is sending packets back and forth with the other
 computer in order to transfer a file or accomplish some other
-file-related task. And at the same time, it is displaying its progress
+file\(hyrelated task. And at the same time, it is displaying its progress
 on your screen and watching your keyboard for interruptions. In this
-state, the following single-keystroke commands are accepted:
+state, the following single\(hykeystroke commands are accepted:
 .sp
 .RS
 .TP
@@ -1141,61 +1142,61 @@ Interrupt the current file and skip all the rest.
 E
 Like Z but uses a "stronger" protocol (use if X or Z don't work).
 .TP
-Ctrl-C
-Interrupt file-transfer mode (use if Z or E don't work).
+Ctrl\-C
+Interrupt file\(hytransfer mode (use if Z or E don't work).
 .sp
 .RE
 Kermit returns to its previous state (Command or Connect) when the
 transfer is complete or when interrupted successfully by X, Z, E, or
-Ctrl-C (hold down the Ctrl key and press the C key).
+Ctrl\-C (hold down the Ctrl key and press the C key).
 .TP
-Remote file-transfer state
-In this state, Kermit is exchanging file-transfer packets with its
+Remote file\(hytransfer state
+In this state, Kermit is exchanging file\(hytransfer packets with its
 local partner over its standard i/o. It leaves this state
 automatically when the transfer is complete. In case you find your
-local Kermit in Connect state and the remote one in File-transfer
+local Kermit in Connect state and the remote one in File\(hytransfer
 state (in which it seems to ignore your keystrokes), you can usually
-return it to command state by typing three Ctrl-C's in a row. If that
-doesn't work, return your local Kermit to Command state (Ctrl-\e C) and
-type "e-packet" and then press the Return or Enter key; this forces a
+return it to command state by typing three Ctrl\-C's in a row. If that
+doesn't work, return your local Kermit to Command state (Ctrl\-\e C) and
+type "e\(hypacket" and then press the Return or Enter key; this forces a
 fatal Kermit protocol error.
 .TP
 Remote Server state
-This is like Remote File-transfer state, except it never returns
+This is like Remote File\(hytransfer state, except it never returns
 automatically to Command state. Rather, it awaits further instructions
 from the client program; that is, from your Local Kermit program. You
 can return the Remote Server to its previous state by issuing a
 "finish" command to the client, or if you are in Connect state, by
-typing three Ctrl-C's in a row. You can tell the server job to log out
+typing three Ctrl\-C's in a row. You can tell the server job to log out
 and break the connection by issuing a "bye" command to the client.
 .TP
 Local Server state
-Like Remote-Server state, but in local mode, and therefore with its
-file-transfer display showing, and listening for single-key commands,
-as in Local File-transfer state. Usually this state is entered
+Like Remote\(hyServer state, but in local mode, and therefore with its
+file\(hytransfer display showing, and listening for single\(hykey commands,
+as in Local File\(hytransfer state. Usually this state is entered
 automatically when a remote Kermit program gives a GET command.
 .sp
-C-Kermit, Kermit 95, and MS-DOS Kermit all can switch automatically from
-Connect state to Local File-transfer state when you initiate a file
+C\(hyKermit, Kermit 95, and MS\(hyDOS Kermit all can switch automatically from
+Connect state to Local File\(hytransfer state when you initiate a file
 transfer from the remote computer by starting Kermit and telling it to send
 or get a file, in which case, Connect state is automatically resumed after
 the file transfer is finished.
 .sp
-Note that C-Kermit is not a terminal emulator. It is a communications
+Note that C\(hyKermit is not a terminal emulator. It is a communications
 application that you run in a terminal window (e.g. console or Xterm). The
 specific emulation, such as VT100, VT220, Linux Console, or Xterm, is
-provided by the terminal window in which you are running C-Kermit. Kermit
-95 and MS-DOS Kermit, on the other hand, are true terminal emulators. Why
-is C-Kermit not a terminal emulator? CLICK HERE to read about it.
+provided by the terminal window in which you are running C\(hyKermit. Kermit
+95 and MS\(hyDOS Kermit, on the other hand, are true terminal emulators. Why
+is C\(hyKermit not a terminal emulator? CLICK HERE to read about it.
 .SH MAKING CONNECTIONS
 Here is how to make different kinds of connections using interactive Kermit
-commands (as noted above, you can also make connections with command-line
+commands (as noted above, you can also make connections with command\(hyline
 options). Note that you don't have to make connections with Kermit. It can
 also be used on the far end of a connection as the remote file transfer and
 management partner of your local communications software.
 .TP
 Making a Telnet Connection
-At the C-Kermit command prompt, simply type:
+At the C\(hyKermit command prompt, simply type:
 .sp
 .nf
   telnet foo.bar.com
@@ -1224,10 +1225,10 @@ Rlogin uses a privileged TCP port:
 More info: HELP RLOGIN.
 .TP
 Making an SSH Connection
-Unlike Telnet and Rlogin, SSH connections are not built-in, but
+Unlike Telnet and Rlogin, SSH connections are not built\(hyin, but
 handled by running your external SSH client through a pseudoterminal.
-Using C-Kermit to control the SSH client gives you all of Kermit's
-features (file transfer, character-set conversion, scripting, etc)
+Using C\(hyKermit to control the SSH client gives you all of Kermit's
+features (file transfer, character\(hyset conversion, scripting, etc)
 over SSH.
 .sp
   ssh foo.bar.com
@@ -1236,7 +1237,7 @@ More info: HELP SSH, HELP SET SSH.
 .TP
 Dialing with a Modem
 If it's an external modem, make sure it is connected to a usable
-serial port on your computer with a regular (straight-through) modem
+serial port on your computer with a regular (straight\(hythrough) modem
 cable, and to the telephone jack with a telephone cable, and that it's
 turned on. Then use these commands:
 .sp
@@ -1251,7 +1252,7 @@ turned on. Then use these commands:
 .sp
 Type "set modem type ?" for a list of supported modem types. If you
 omit the SET MODEM TYPE command, the default type is
-"generic-high-speed", which should work for most modern AT-command-set
+"generic\(hyhigh\(hyspeed", which should work for most modern AT\(hycommand\(hyset
 modems. If the line is busy, Kermit redials automatically. If the call
 does not succeed, use "set dial display on" and try it again to watch
 what happens. If the call succeeds, Kermit enters Connect state
@@ -1262,34 +1263,34 @@ You can also dial from a modem that is accessible by Telnet, e.g. to a
 reverse terminal server. In this case the command sequence is:
 .sp
 .nf
-  set host ts.xxx.com 2000   ; Terminal-server and port
+  set host ts.xxx.com 2000   ; Terminal\(hyserver and port
   set modem type usrobotics  ; Or other supported type
   set dial method tone       ; (or pulse)
   dial 7654321               ; Dial the desired number
 .fi
 .sp
 If the terminal server supports the Telnet Com Port Option, RFC 2217,
-you can also give serial-port related commands such as SET SPEED, SET
+you can also give serial\(hyport related commands such as SET SPEED, SET
 PARITY, and so on, and Kermit relays them to the terminal server using
 the protocol specified in the RFC.
 .sp
 More info: HELP SET MODEM, HELP SET LINE, HELP SET SPEED, HELP SET
 FLOW, HELP DIAL, HELP SET DIAL, HELP SET MODEM, HELP SET 
-CARRIER-WATCH, SHOW COMMUNICATIONS, SHOW MODEM, SHOW DIAL.
+CARRIER\-WATCH, SHOW COMMUNICATIONS, SHOW MODEM, SHOW DIAL.
 .TP
 Direct Serial Port
 Connect the two computers, A and B, with a null modem cable (or two
-modem cables interconnected with a null-modem adapter or modem
+modem cables interconnected with a null\(hymodem adapter or modem
 eliminator). From Computer A:
 .sp
 .nf
   set modem type none   ; There is no modem
   set line /dev/ttyS0   ; Specify device name
-  set carrier-watch off ; If DTR CD are not cross-connected
+  set carrier\-watch off ; If DTR CD are not cross\(hyconnected
   set speed 57600       ; Or other desired speed
-  set flow rts/cts      ; If RTS and CTS are cross-connected
+  set flow rts/cts      ; If RTS and CTS are cross\(hyconnected
   set parity even       ; (or "mark" or "space", if necessary)
-  set stop-bits 2       ; (rarely necessary)
+  set stop\-bits 2       ; (rarely necessary)
   set flow xon/xoff     ; If you can't use RTS/CTS
   connect               ; Enter Connect (terminal) state
 .fi
@@ -1299,25 +1300,25 @@ can run a copy of Kermit on Computer B and follow approximately the
 same directions. More info: As above plus HELP CONNECT.
 .PP
 With modems or direct serial connections, you might also have to "set
-parity even" (or "mark" or "space") if it's a 7-bit connection.
+parity even" (or "mark" or "space") if it's a 7\(hybit connection.
 .PP
 Of the connection types listed above, only one can be open at a time.
 However, any one of these can be open concurrently with an FTP or HTTP
 session. Each connection type can be customized to any desired degree,
 scripted, logged, you name it. See the manual.
 .PP
-NOTE: On selected platforms, C-Kermit also can make X.25 connections. See
+NOTE: On selected platforms, C\(hyKermit also can make X.25 connections. See
 the manual for details.
 .SH TRANSFERRING FILES WITH KERMIT
 There is a widespread and persistent belief that Kermit is a slow protocol.
 This is because, until recently, it used conservative tuning by default to
 make sure file transfers succeeded, rather than failing because they
-overloaded the connection. Some extra commands (or command-line options,
-like -Q) were needed to make it go fast, but nobody bothered to find out
-about them. Also, it takes two to tango: most non-Kermit-Project Kermit
-protocol implementations really ARE slow. The best file-transfer partners
-for C-Kermit are: another copy of C-Kermit (7.0 or later) and Kermit 95.
-These combinations work well and they work fast by default. MS-DOS Kermit
+overloaded the connection. Some extra commands (or command\(hyline options,
+like \-Q) were needed to make it go fast, but nobody bothered to find out
+about them. Also, it takes two to tango: most non\(hyKermit\(hyProject Kermit
+protocol implementations really ARE slow. The best file\(hytransfer partners
+for C\(hyKermit are: another copy of C\(hyKermit (7.0 or later) and Kermit 95.
+These combinations work well and they work fast by default. MS\(hyDOS Kermit
 is good too, but you have to tell it to go fast (by giving it the FAST
 command).
 .PP
@@ -1326,50 +1327,50 @@ Furthermore, all three of these Kermit programs support "autodownload" and
 packet comes in from the remote, they automatically switch into file
 transfer mode.
 .PP
-And plus, C-Kermit and K95 also switch automatically between text and
+And plus, C\(hyKermit and K95 also switch automatically between text and
 binary mode for each file, so there is no need to "set file type binary" or
 "set file type text", or to worry about files being corrupted because they
 were transferred in the wrong mode.
 .PP
-What all of these words add up to is that now, when you use up-to-date
+What all of these words add up to is that now, when you use up\(hyto\(hydate
 Kermit software from the Kermit Project, file transfer is not only fast,
 it's ridiculously easy. You barely have to give any commands at all.
 .TP
 Downloading Files
-Let's say you have Kermit 95, C-Kermit, or MS-DOS Kermit on your
+Let's say you have Kermit 95, C\(hyKermit, or MS\(hyDOS Kermit on your
 desktop computer, with a connection to a Unix computer that has
-C-Kermit installed as "kermit". To download a file (send it from Unix
+C\(hyKermit installed as "kermit". To download a file (send it from Unix
 to your desktop computer), just type the following command at your
 Unix shell prompt:
 .sp
-  kermit -s oofa.txt
+  kermit \-s oofa.txt
 .sp
 (where oofa.txt is the filename). If you want to send more than one
 file, you can put as many filenames as you want on the command line,
 and they can be any combination of text and binary:
 .sp
-  kermit -s oofa.txt oofa.zip oofa.html oofa.tar.gz
+  kermit \-s oofa.txt oofa.zip oofa.html oofa.tar.gz
 .sp
 and/or you can use wildcards to send groups of files:
 .sp
-  kermit -s oofa.*
+  kermit \-s oofa.*
 .sp
 If you want to send a file under an assumed name, use:
 .sp
-  kermit -s friday.txt -a today.txt
+  kermit \-s friday.txt \-a today.txt
 .sp
 This sends the file friday.txt but tells the receiving Kermit that its
 name is today.txt. In all cases, as noted, when the file transfer is
 finished, your desktop Kermit returns automatically to Connect state.
-No worries about escaping back, re-connecting, text/binary mode
+No worries about escaping back, re\(hyconnecting, text/binary mode
 switching. Almost too easy, right?
 .TP
 Uploading Files
 To upload files (send them from your desktop computer to the remote
-Unix computer) do the same thing, but use the -g (GET) option instead
-of -s:
+Unix computer) do the same thing, but use the \-g (GET) option instead
+of \-s:
 .sp
-  kermit -g oofa.txt
+  kermit \-g oofa.txt
 .sp
 This causes your local Kermit to enter server mode; then the remote
 Kermit program requests the named file and the local Kermit sends it
@@ -1379,27 +1380,27 @@ If you want to upload multiple files, you have have use shell quoting
 rules, since these aren't local files:
 .sp
 .nf
-  kermit -g "oofa.txt oofa.zip oofa.html oofa.tar.gz"
-  kermit -g "oofa.*"
+  kermit \-g "oofa.txt oofa.zip oofa.html oofa.tar.gz"
+  kermit \-g "oofa.*"
 .fi
 .sp
 If you want to upload a file but store it under a different name, use:
 .sp
-  kermit -g friday.txt -a today.txt
+  kermit \-g friday.txt \-a today.txt
 .TP
-Kermit Transfers the Old-Fashioned Way
+Kermit Transfers the Old\(hyFashioned Way
 If your desktop communications software does not support autoupload or
 autodownload, or it does not include Kermit server mode, the procedure
 requires more steps.
 .sp
 To download a file, type:
 .sp
-  kermit -s filename
+  kermit \-s filename
 .sp
 on the host as before, but if nothing happens automatically in
 response to this command, you have to switch your desktop
 communications software into Kermit Receive state. This might be done
-by escaping back using keyboard characters or hot keys (Alt-x is
+by escaping back using keyboard characters or hot keys (Alt\-x is
 typical) and/or with a command (like RECEIVE) or a menu. When the file
 transfer is complete, you have to go back to Connect state, Terminal
 emulation, or whatever terminology applies to your desktop
@@ -1407,11 +1408,11 @@ communications software.
 .sp
 To upload a file, type:
 .sp
-  kermit -r
+  kermit \-r
 .sp
-on the host (rather than "kermit -g"). This tells C-Kermit to wait
+on the host (rather than "kermit \-g"). This tells C\(hyKermit to wait
 passively for a file to start arriving. Then regain the attention of
-your desktop software (Alt-x or whatever) and instruct it to send the
+your desktop software (Alt\-x or whatever) and instruct it to send the
 desired file(s) with Kermit protocol. When the transfer is finished,
 return to the Connect or Terminal screen.
 .TP
@@ -1422,8 +1423,8 @@ for troubleshooting:
 .RS
 .TP
 FAST
-Use fast file-transfer settings. This has been the default since
-C-Kermit 7.0 now that most modern computers and connections
+Use fast file\(hytransfer settings. This has been the default since
+C\(hyKermit 7.0 now that most modern computers and connections
 support it. If transfers fail with fast settings, try . . .
 .TP
 CAUTIOUS
@@ -1434,21 +1435,21 @@ ROBUST
 Use the most robust, resilient, conservative, safe, and reliable
 settings. File transfers will almost certainly work, but they
 will be quite slow (of course this is a classic tradeoff; ROBUST
-was C-Kermit's default tuning in versions 6.0 and earlier, which
+was C\(hyKermit's default tuning in versions 6.0 and earlier, which
 made everybody think Kermit protocol was slow). If ROBUST doesn't
 do the trick, try again with SET PARITY SPACE first in case it's
-not an 8-bit connection.
+not an 8\(hybit connection.
 .RE
 .sp
 Obviously the success and performance of a file transfer also depends
-on C-Kermit's file transfer partner. Up-to-date, real Kermit Project
+on C\(hyKermit's file transfer partner. Up\(hyto\(hydate, real Kermit Project
 partners are recommended because they contain the best Kermit protocol
 implementations and because we can support them in case of trouble.
 .sp
-If you still have trouble, consult Chapter 10 of Using C-Kermit, or
-send email to kermit-support@columbia.edu.
+If you still have trouble, consult Chapter 10 of Using C\(hyKermit, or
+send email to kermit\(hysupport@columbia.edu.
 .TP
-Advanced Kermit File-Transfer Features
+Advanced Kermit File\(hyTransfer Features
 Obviously there is a lot more to Kermit file transfer, including all
 sorts of interactive commands, preferences, options, logging,
 debugging, troubleshooting, and anything else you can imagine but
@@ -1460,10 +1461,10 @@ commands:
 Logging transfers:
 LOG TRANSACTIONS (HELP LOG)
 .TP
-Automatic per-file text/binary mode switching:
+Automatic per\(hyfile text/binary mode switching:
 SET TRANSFER MODE { AUTOMATIC, MANUAL } (HELP SET TRANSFER).
 .TP
-Cross-platform recursive directory tree transfer:
+Cross\(hyplatform recursive directory tree transfer:
 SEND /RECURSIVE, GET /RECURSIVE (HELP SEND, HELP GET).
 .TP
 File collision options:
@@ -1478,14 +1479,14 @@ Filename selection patterns:
 Flexible file selection:
 SEND (or GET) /BEFORE /AFTER /LARGER /SMALLER /TYPE /EXCEPT, ...
 .TP
-Character-set conversion:
-SET { FILE, TRANSFER } CHARACTER-SET, ASSOCIATE, ...
+Character\(hyset conversion:
+SET { FILE, TRANSFER } CHARACTER\-SET, ASSOCIATE, ...
 .TP
 File/Pathname control:
 SET { SEND, RECEIVE } PATHNAMES, SET FILE NAMES.
 .TP
 Atomic file movement:
-SEND (or GET) /DELETE /RENAME /MOVE-TO
+SEND (or GET) /DELETE /RENAME /MOVE\-TO
 .TP
 Transferring to/from standard i/o of other commands:
 SEND (or GET) /COMMAND
@@ -1494,8 +1495,8 @@ Recovery of interrupted transfer from point of failure:
 RESEND, REGET (HELP RESEND, HELP REGET).
 .RE
 .TP
-Non-Kermit File Transfer
-You can also use C-Kermit to transfer files with FTP or HTTP Internet
+Non\(hyKermit File Transfer
+You can also use C\(hyKermit to transfer files with FTP or HTTP Internet
 protocols; see below.
 .sp
 On a regular serial or Telnet connection where the other computer
@@ -1510,10 +1511,10 @@ Kermit can use them as external protocols. HELP SET PROTOCOL for
 details.
 .sp
 You can also capture "raw" data streams from the other computer with
-LOG SESSION (HELP LOG and HELP SET SESSION-LOG for details), and you
+LOG SESSION (HELP LOG and HELP SET SESSION\-LOG for details), and you
 can upload files without any protocol at all with TRANSMIT (HELP
 TRANSMIT, HELP SET TRANSMIT).
-.SH KERMIT'S BUILT-IN FTP AND HTTP CLIENTS
+.SH KERMIT'S BUILT\(hyIN FTP AND HTTP CLIENTS
 Kermit's FTP client is like the regular Unix FTP client that you're used
 to, but with some differences:
 .TP
@@ -1542,7 +1543,7 @@ client is thoroughly documented at the Kermit Project website:
   http://www.columbia.edu/kermit/ftpclient.html
 .sp
 You also can use HELP FTP and HELP SET FTP to get descriptions of Kermit's
-FTP-related commands.
+FTP\(hyrelated commands.
 .PP
 The HTTP client is similar to the FTP one, except you prefix each command
 with HTTP instead of FTP: HTTP OPEN, HTTP GET, HTTP PUT, HTTP CLOSE, etc.
@@ -1551,12 +1552,12 @@ HTTP connections can be open at the same time as regular serial or Telnet
 connections and FTP connections. So Kermit can manage up to three types
 connections simultaneously.
 .SH INTERNET KERMIT SERVICE
-C-Kermit can be configured and run as an Internet service (called IKSD),
+C\(hyKermit can be configured and run as an Internet service (called IKSD),
 similar to an FTP server (FTPD) except you can (but need not) interact with
 it directly, plus it does a lot more than an FTP server can do. The TCP
-port for IKSD is 1649. It uses Telnet protocol. C-Kermit can be an Internet
+port for IKSD is 1649. It uses Telnet protocol. C\(hyKermit can be an Internet
 Kermit Server, or it can be a client of an IKSD. You can make connections
-from C-Kermit to an IKSD with any of the following commands:
+from C\(hyKermit to an IKSD with any of the following commands:
 .sp
 .nf
   telnet foo.bar.edu 1649
@@ -1574,8 +1575,8 @@ the system administrator). For instructions, see:
 .sp
   http://www.columbia.edu/kermit/iksd.html
 .SH SECURITY
-All of C-Kermit's built-in TCP/IP networking methods (Telnet, Rlogin, IKSD,
-FTP, and HTTP) can be secured by one or more of the following IETF-approved
+All of C\(hyKermit's built\(hyin TCP/IP networking methods (Telnet, Rlogin, IKSD,
+FTP, and HTTP) can be secured by one or more of the following IETF\(hyapproved
 methods:
 .PP
 \(bu   MIT Kerberos IV
@@ -1590,43 +1591,43 @@ For complete instructions see:
 .PP
   http://www.columbia.edu/kermit/security.html
 .PP
-And as noted previously, you can also make SSH connections with C-Kermit if
+And as noted previously, you can also make SSH connections with C\(hyKermit if
 you already have an SSH client installed.
-.SH ALTERNATIVE COMMAND-LINE PERSONALITIES
+.SH ALTERNATIVE COMMAND\(hyLINE PERSONALITIES
 When invoked as "kermit" or any other name besides "ftp" or "telnet",
-C-Kermit has the command-line options described above in the OPTIONS
-section. However, if you invoke C-Kermit as "telnet" or "ftp", it changes
-its command-line personality to match. This can be done (among other ways)
-with symbolic links (symlinks). For example, if you want C-Kermit to be
+C\(hyKermit has the command\(hyline options described above in the OPTIONS
+section. However, if you invoke C\(hyKermit as "telnet" or "ftp", it changes
+its command\(hyline personality to match. This can be done (among other ways)
+with symbolic links (symlinks). For example, if you want C\(hyKermit to be
 your regular Telnet client, or the Telnet helper of your Web browser, you
 can create a link like the following in a directory that lies in your PATH
 ahead of the regular telnet program:
 .sp
-  ln -s /usr/local/bin/kermit telnet
+  ln \-s /usr/local/bin/kermit telnet
 .sp
 Now when you give a "telnet" command, you are invoking Kermit instead, but
-with its Telnet command-line personality so, for example:
+with its Telnet command\(hyline personality so, for example:
 .sp
   telnet xyzcorp.com
 .sp
 Makes a Telnet connection to xyzcorp.com, and Kermit exits automatically
 when the connection is closed (just like the regular Telnet client). Type
-"telnet -h" to get a list of Kermit's Telnet-personality command-line
+"telnet \-h" to get a list of Kermit's Telnet\(hypersonality command\(hyline
 options, which are intended to be as compatible as possible with the
 regular Telnet client.
 .PP
 Similarly for FTP:
 .sp
-  ln -s /usr/local/bin/kermit ftp
+  ln \-s /usr/local/bin/kermit ftp
 .sp
-And now type "ftp -h" to see its command-line options, and command lines
+And now type "ftp \-h" to see its command\(hyline options, and command lines
 just like you would give your regular FTP client:
 .sp
   ftp xyzcorp.com
 .sp
 but with additional options allowing an entire session to be specified on
 the command line. Finally, if Kermit's
-first command-line option is a Telnet, FTP, IKSD, or HTTP URL, Kermit
+first command\(hyline option is a Telnet, FTP, IKSD, or HTTP URL, Kermit
 automatically makes the appropriate kind of connection and, if indicated by
 the URL, takes the desired action:
 .TP
@@ -1649,19 +1650,19 @@ kermit http://www.columbia.edu/kermit/index.html
 Grabs a web page
 .fi
 .SH LICENSE
-C-Kermit has an unusual license, but a fair and sensible one since the
+C\(hyKermit has an unusual license, but a fair and sensible one since the
 Kermit Project must support itself out of revenue: it's not a BSD license,
 not GPL, not Artistic, not commercial, not shareware, not freeware. It can
-be summed up like this: if you want C-Kermit for your own use, you can
+be summed up like this: if you want C\(hyKermit for your own use, you can
 download and use it without cost or license (but we'd appreciate it if you
-would purchase the manual). But if you want to sell C-Kermit or bundle it
+would purchase the manual). But if you want to sell C\(hyKermit or bundle it
 with a product or otherwise distribute it in a commercial setting EXCEPT
-WITH AN OPEN-SOURCE OPERATING SYSTEM DISTRIBUTION such as Linux, FreeBSD,
+WITH AN OPEN\(hySOURCE OPERATING SYSTEM DISTRIBUTION such as Linux, FreeBSD,
 NetBSD, or OpenBSD, you must license it. To see the complete license, give
 the LICENSE command at the prompt, or see the COPYING.TXT file distributed
-with C-Kermit 7.0 or later, or download it from
+with C\(hyKermit 7.0 or later, or download it from
 .sp
-  ftp://kermit.columbia.edu/kermit/c-kermit/COPYING.TXT
+  ftp://kermit.columbia.edu/kermit/c\-kermit/COPYING.TXT
 .sp
 Send licensing inquiries to kermit@columbia.edu.
 .SH BUGS
@@ -1669,27 +1670,27 @@ See the following files for listings of known bugs, limitations,
 workarounds, hints and tips:
 .TP
 ckcbwr.txt
-General C-Kermit bugs, hints, tips.
+General C\(hyKermit bugs, hints, tips.
 .TP
 ckubwr.txt
-Unix-specific C-Kermit bugs, hints, tips.
+Unix\(hyspecific C\(hyKermit bugs, hints, tips.
 .PP
 Report bugs and problems by email to:
 .sp
-   kermit-support@columbia.edu.
+   kermit\-support@columbia.edu.
 .sp
 Before requesting technical support, please read the hints here:
 .sp
   http://www.columbia.edu/kermit/support.html
 .sp
-and also read the C-Kermit Frequently Asked Questions:
+and also read the C\(hyKermit Frequently Asked Questions:
 .sp
   http://www.columbia.edu/kermit/ckfaq.html
 .SH OTHER TOPICS
-There's way more to C-Kermit than we've touched on here -- troubleshooting,
+There's way more to C\(hyKermit than we've touched on here \(hy\(hy troubleshooting,
 customization, character sets, dialing directories, sending pages, script
 writing, and on and on, all of which are covered in the manual and updates
-and supplements. For the most up-to-date information on documentation (or
+and supplements. For the most up\(hyto\(hydate information on documentation (or
 updated documentation itself) visit the Kermit Project website:
 .sp
   http://www.columbia.edu/kermit/
@@ -1698,21 +1699,24 @@ There you will also find Kermit software packages for other platforms:
 different Unix varieties, Windows, DOS, VMS, IBM mainframes, and many
 others: 20+ years' worth.
 .SH DOCUMENTATION AND UPDATES
-The manual for C-Kermit is:
+The manual for C\(hyKermit is:
 .TP
 .I
-Using C-Kermit
+Using C\(hyKermit
 Frank da Cruz and Christine M. Gianone,
-Second Edition, Digital Press / Butterworth-Heinemann, Woburn, MA, 1997, 622
-pages, ISBN 1-55558-164-1. This is a printed book. It covers C-Kermit 6.0.
+Second Edition, Digital Press / Butterworth\(hyHeinemann, Woburn, MA, 1997, 622
+pages, ISBN 1\-55558\-164\-1. This is a printed book. It covers C\(hyKermit 6.0.
 .TP
-The C-Kermit 7.0 Supplement
-http://www.columbia.edu/kermit/ckermit2.html
+The C\(hyKermit 7.0 Supplement
+http://www.columbia.edu/kermit/ckermit70.html
 .TP
-The C-Kermit 8.0 Supplement
-http://www.columbia.edu/kermit/ckermit3.html
+The C\(hyKermit 8.0 Supplement
+http://www.columbia.edu/kermit/ckermit80.html
+.TP
+The C\(hyKermit 9.0 Supplement
+http://www.columbia.edu/kermit/ckermit90.html
 .PP
-Visit C-Kermit home page:
+Visit C\(hyKermit home page:
 .sp
   http://www.columbia.edu/kermit/ckermit.html
 .sp
@@ -1727,13 +1731,13 @@ http://www.columbia.edu/kermit/newfaq.html
 The Kermit FAQ (Frequently Asked Questions about Kermit)
 .TP
 http://www.columbia.edu/kermit/ckfaq.html
-The C-Kermit FAQ (Frequently Asked Questions about C-Kermit)
+The C\(hyKermit FAQ (Frequently Asked Questions about C\(hyKermit)
 .TP
 http://www.columbia.edu/kermit/telnet.html
-C-Kermit Telnet client documentation
+C\(hyKermit Telnet client documentation
 .TP
 http://www.columbia.edu/kermit/security.html
-C-Kermit security documentation (Kerberos, SSL/TLS, etc)
+C\(hyKermit security documentation (Kerberos, SSL/TLS, etc)
 .TP
 http://www.columbia.edu/kermit/cuiksd.html
 Internet Kermit Service user documentation
@@ -1755,7 +1759,7 @@ The Kermit newsgroup (unmoderated).
 .SH FILES
 .TP
 COPYING.TXT
-C-Kermit license.
+C\(hyKermit license.
 .TP
 ~/.kermrc
 Initialization file.
@@ -1780,16 +1784,16 @@ Installation instructions for Unix.  Also at
 http://www.columbia.edu/kermit/ckuins.html.
 .TP
 ckcbwr.txt
-General C-Kermit bugs, hints, tips.
+General C\(hyKermit bugs, hints, tips.
 .TP
 ckubwr.txt
-Unix-specific C-Kermit bugs, hints, tips.
+Unix\(hyspecific C\(hyKermit bugs, hints, tips.
 .TP
 ckcplm.txt
-C-Kermit program logic manual.
+C\(hyKermit program logic manual.
 .TP
 ckccfg.txt
-C-Kermit compile-time configuration options.
+C\(hyKermit compile\(hytime configuration options.
 .TP
 ssh
 (in your PATH) SSH connection helper.
@@ -1804,21 +1808,21 @@ UUCP lockfile for dialing out (see installation instructions).
 Software
 Frank da Cruz and Jeffrey E Altman,
 .br
-1985-present, with contributions from hundreds of others all over the
+1985\(hypresent, with contributions from hundreds of others all over the
 world.
 .TP
 Documentation
-Frank da Cruz and Christine M Gianone
+Frank da Cruz
 .TP
 Address
 .nf
-The Kermit Project - Columbia Univerity
+The Kermit Project \(hy Columbia Univerity
 612 West 115th Street
-New York NY 10025-7799
+New York NY 10025\-7799
 USA
 .fi
 .TP
-E-Mail
+E\(hyMail
 kermit@columbia.edu
 .TP
 Web
index 705914c..9906555 100644 (file)
--- a/ckupty.c
+++ b/ckupty.c
@@ -1,5 +1,9 @@
+char *ckptyv = "Pseudoterminal support, 9.0.101, 13 Jun 2011";
+
 /*  C K U P T Y  --  C-Kermit pseudoterminal control functions for UNIX  */
 
+/* Last update: Mon Jun 13 11:32:52 2011 */
+
 /*
   Copyright 1995 by the Massachusetts Institute of Technology.
 
   Jeffrey Altman <jaltman@secure-endpoints.com>
   Secure Endpoints Inc., New York City
   November 1999
+
+  Parameterized for pty file descriptor and function code,
+  Frank da Cruz, Columbia University, New York City
+  Dec 2006 - Sep 2009
 */
 
 /*
@@ -31,7 +39,9 @@
    . HP-UX 9.00 and later
    . IRIX 6.0 and later
    . Linux
+   . Mac OS X 10.4
    . NeXTSTEP 3.x
+   . OpenBSD
    . QNX 4.25 (except PTY process termination not detected)
    . SCO OSR5.0.5
    . SCO Unixware 7
@@ -39,9 +49,6 @@
    . Solaris 2.x and 7
    . SunOS 4.1.3
 
-  Included but not tested yet in:
-   . Macintosh OSX, OpenBSD, and any other BSD44-based system not listed above
-
   Failures include:
    . SCO UNIX 3.2v4.2 (compile fails with syntax error in <memory.h>)
    . HP-UX 8.00 and earlier (no vhangup or ptsname routines)
@@ -56,7 +63,7 @@ char * ptyver = "No PTY support";
 
 #else  /* (rest of this module...) */
 
-char * ptyver = "PTY support 8.0.014, 20 Aug 2002";
+char * ptyver = "PTY support 8.0.016, 22 Aug 2007";
 
 /* These will no doubt need adjustment... */
 
@@ -67,6 +74,10 @@ char * ptyver = "PTY support 8.0.014, 20 Aug 2002";
 #define HAVE_TTYNAME
 #define HAVE_WAITPID
 
+#ifdef SUNOS41
+#define BSD44ORPOSIX
+#endif /* SUNOS41 */
+
 #ifndef USE_TERMIO
 #ifdef LINUX
 #define USE_TERMIO
@@ -292,6 +303,7 @@ char * ptyver = "PTY support 8.0.014, 20 Aug 2002";
 #ifdef HAVE_TTY_H
 #include <tty.h>
 #endif /* HAVE_TTY_H */
+
 /*
   Because of the way ptyibuf is used with streams messages, we need
   ptyibuf+1 to be on a full-word boundary.  The following weirdness
@@ -380,9 +392,21 @@ static int spty = -1;
 
 #endif /* USE_TERMIO */
 
-extern int ttyfd;                       /* Standard Kermit usage */
+#ifdef QNX                             /* 299 */
+#ifndef IXANY
+#define IXANY 0
+#endif /* IXANY */
+#endif /* QNX */
+
 static int msg = 0;
 
+/* Variables available to other modules */
+
+int pty_fork_active = 0;               /* pty fork is active */
+PID_T pty_fork_pid = -1;               /* pty fork pid */
+int pty_slave_fd = -1;                 /* pty slave file descriptor */
+int pty_master_fd = -1;                        /* pty master file descriptor */
+
 /* termbuf routines (begin) */
 /*
   init_termbuf()
@@ -395,8 +419,33 @@ static int msg = 0;
   set_termbuf() writes the structure into the kernel.
 */
 VOID
-init_termbuf() {
+init_termbuf(fd) int fd; {
+    int ttyfd;
     int rc = 0;
+
+    ttyfd = fd;
+
+#ifdef HAVE_STREAMS
+    debug(F100,"init_termbuf HAVE_STREAMS","",0);
+#else
+    debug(F100,"init_termbuf HAVE_STREAMS NOT DEFINED","",0);
+#endif /* HAVE_STREAMS */
+#ifdef STREAMSPTY
+    debug(F100,"init_termbuf STREAMSPTY","",0);
+#else
+    debug(F100,"init_termbuf STREAMSPTY NOT DEFINED","",0);
+#endif /* STREAMSPTY */
+#ifdef INIT_SPTY
+    debug(F100,"init_termbuf INIT_SPTY","",0);
+#else
+    debug(F100,"init_termbuf INIT_SPTY NOT DEFINED","",0);
+#endif /* INIT_SPTY */
+
+    debug(F101,"init_termbuf ttyfd","",ttyfd);
+#ifdef INIT_SPTY
+    debug(F101,"init_termbuf spty","",spty);
+#endif /* INIT_SPTY */
+
     memset(&termbuf,0,sizeof(termbuf));
     memset(&termbuf2,0,sizeof(termbuf2));
 #ifndef        USE_TERMIO
@@ -431,8 +480,18 @@ copy_termbuf(cp, len) char *cp; int len; {
 #endif /* TIOCPKT_IOCTL */
 
 VOID
-set_termbuf() {                                /* Only make the necessary changes. */
+set_termbuf(fd) int fd; {              /* Only make the necessary changes. */
+    int x;
+    int ttyfd;
+    ttyfd = fd;
+
+    debug(F101,"set_termbuf ttyfd","",ttyfd);
+#ifdef INIT_SPTY
+    debug(F101,"set_termbuf spty","",spty);
+#endif /* INIT_SPTY */
+
 #ifndef        USE_TERMIO
+    debug(F100,"set_termbuf USE_TERMIO","",0);
     if (memcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, sizeof(termbuf.sg)))
       ioctl(ttyfd, TIOCSETN, (char *)&termbuf.sg);
     if (memcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, sizeof(termbuf.tc)))
@@ -443,13 +502,18 @@ set_termbuf() {                           /* Only make the necessary changes. */
     if (termbuf.lflags != termbuf2.lflags)
       ioctl(ttyfd, TIOCLSET, (char *)&termbuf.lflags);
 #else  /* USE_TERMIO */
-    if (memcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf))) {
+    x = memcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf));
+    debug(F101,"set_termbuf !USE_TERMIO memcmp","",x);
+    x = 1;                             /* Force this */
+    if (x) {
        int x;
        errno = 0;
 #ifdef INIT_SPTY
+       debug(F100,"set_termbuf INIT_SPTY","",0);
        x = tcsetattr(spty, TCSANOW, &termbuf);
        debug(F111,"set_termbuf tcsetattr(spty)",ckitoa(x),errno);
 #else
+       debug(F100,"set_termbuf !INIT_SPTY","",0);
        x = tcsetattr(ttyfd, TCSANOW, &termbuf);
        debug(F111,"set_termbuf tcsetattr(ttyfd)",ckitoa(x),errno);
 #endif /* INIT_SPTY */
@@ -481,7 +545,7 @@ ptyint_vhangup() {
 
 /*
   This routine is called twice.  It's not particularly important that the
-  setsid() or TIOCSTTY ioctls succeed (they may not the second time), but
+  setsid() or TIOCSCTTY ioctls succeed (they may not the second time), but
   rather that we have a controlling terminal at the end.  It is assumed that
   vhangup doesn't exist and confuse the process's notion of controlling
   terminal on any system without TIOCNOTTY.  That is, either vhangup() leaves
@@ -587,7 +651,7 @@ pty_cleanup(slave, pid, update_utmp) char *slave; int pid; int update_utmp; {
             return errno;
          case 0:
             ptyint_void_association();
-            if (retval = (pty_open_ctty(slave, &fd)))
+            if (retval = (pty_open_ctty(slave, &fd, -1)))
              exit(retval);
             ptyint_vhangup();
             exit(0);
@@ -636,6 +700,7 @@ pty_getpty(fd, slave, slavelength) int slavelength; int *fd; char *slave; {
 #ifdef HAVE_OPENPTY
     int slavefd;
 
+    pty_master_fd = -1;
     debug(F100,"HAVE_OPENPTY","",0);
     if (openpty(fd,
                &slavefd,
@@ -643,8 +708,10 @@ pty_getpty(fd, slave, slavelength) int slavelength; int *fd; char *slave; {
                (struct termios *)0,
                (struct winsize *)0
                )
-       )
-      return(1);
+       ) {
+       pty_master_fd = *fd;
+       return(1);
+    }
     close(slavefd);
     return(0);
 
@@ -699,7 +766,11 @@ pty_getpty(fd, slave, slavelength) int slavelength; int *fd; char *slave; {
         debug(F110,"pty_getpty()","open(/dev/pty) success",0);
 
   have_fd:
+    /* This would be the pty master */
+    debug(F101,"pty_getpty fd(A)","",*fd);
     if (*fd >= 0) {
+       pty_master_fd = *fd;
+
 #ifdef HAVE_GRANTPT
 #ifdef HAVE_PTMX
         debug(F100,"HAVE_GRANTPT","",0);
@@ -718,7 +789,7 @@ pty_getpty(fd, slave, slavelength) int slavelength; int *fd; char *slave; {
        p = ttyname(*fd);
         debug(F110,"pty_getpty() ttyname()",p,0);
 #else
-       /* XXX If we don't have either what do we do? */
+       /* If we don't have either what do we do? */
        return(PTY_GETPTY_NOPTY);       /* punt */
 #endif /* HAVE_TTYNAME */
 #endif /* HAVE_PTSNAME */
@@ -754,18 +825,23 @@ pty_getpty(fd, slave, slavelength) int slavelength; int *fd; char *slave; {
              break;
            for (i = 0; i < 16; i++) {
                slavebuf[sizeof("/dev/ptyp") - 1] = "0123456789abcdef"[i];
+               errno = 0;
                *fd = open(slavebuf, O_RDWR|O_NDELAY);
-               if (*fd < 0)
-                 continue;
-                debug(F110,"pty_getpty() found pty master",slavebuf,0);
+               if (*fd < 0) {
+                   debug(F111,"pty_getpty() pty master open error",
+                         slavebuf,errno);
+                   continue;
+               }
+                debug(F111,"pty_getpty() found pty master",slavebuf,*fd);
                slavebuf[sizeof("/dev/") - 1] = 't'; /* got pty */
                if (strlen(slavebuf) > slavelength -1) {
                    close(*fd);
                    *fd = -1;
                    return(PTY_GETPTY_SLAVE_TOOLONG);
                }
-                debug(F110,"pty_getpty() slavebuf [2]",slavebuf,0);
                ckstrncpy(slave, slavebuf, slavelength);
+                debug(F110,"pty_getpty slave name",slave,0);
+               pty_master_fd = *fd;
                return(0);
            }
        }
@@ -925,7 +1001,7 @@ pty_logwtmp (tty, user, host) char *user, *tty, *host; {
 
 /*
   This routine is called twice.  It's not particularly important that the
-  setsid() or TIOCSTTY ioctls succeed (they may not the second time), but
+  setsid() or TIOCSCTTY ioctls succeed (they may not the second time), but
   rather that we have a controlling terminal at the end.  It is assumed that
   vhangup doesn't exist and confuse the process's notion of controlling
   terminal on any system without TIOCNOTTY.  That is, either vhangup() leaves
@@ -935,7 +1011,7 @@ pty_logwtmp (tty, user, host) char *user, *tty, *host; {
   effect controlling terminals, so this condition is met.
 */
 long
-pty_open_ctty(slave, fd) char * slave; int *fd; {
+pty_open_ctty(slave, fd, fc) char * slave; int *fd; int fc; {
     int retval;
 
     debug(F110,"pty_open_ctty() slave",slave,0);
@@ -950,41 +1026,63 @@ pty_open_ctty(slave, fd) char * slave; int *fd; {
              );
        return(retval);
     }
-
 #ifdef MUST_SETPGRP
 /*
   The Ultrix (and other BSD tty drivers) require the process group
   to be zero in order to acquire the new tty as a controlling tty.
 */
     setpgrp(0,0);
+    debug(F101,"pty_open_ctty MUST_SETPGRP setpgrp(0,0)","",errno);
 #endif /* MUST_SETPGRP */
 
     errno = 0;
     *fd = open(slave, O_RDWR);
+    debug(F111,"pty_open_ctty open(slave) fd",slave,*fd);
     if (*fd < 0) {
        debug(F111,"pty_open_ctty() open failure", slave, errno);
        return(PTY_OPEN_SLAVE_OPENFAIL);
     }
+#ifdef SOLARIS
+    /* This forces the job to have a controlling terminal. */
+    close(*fd);
+    *fd = open(slave, O_RDWR);
+    debug(F111,"pty_open_ctty close/open(slave) fd",slave,*fd);
 #ifdef DEBUG
-    else if (deblog) {
-       debug(F110, "pty_open_ctty() open ok", slave, 0);
+    /* This shows that /dev/tty exists */
+if (deblog) {
+       int x;
+       x = open("/dev/tty", O_RDWR);
+       debug(F111,"pty_open_ctty open(/dev/tty) fd",slave,x);
+       if (x < 0) debug(F111,"pty_open_ctty open(/dev/tty) errno","",errno);
+       debug(F110,"pty_open_ctty ttyname(/dev/tty)",ttyname(x),0);
+       if (x > -1) close(x);
     }
-#endif /* DEBUG */
+#endif /* DEBUG */
+#endif /* SOLARIS */
 
 #ifdef MUST_SETPGRP
     setpgrp(0, getpid());
 #endif /* MUST_SETPGRP */
 
 #ifdef TIOCSCTTY
-    errno = 0;
-    retval = ioctl(*fd, TIOCSCTTY, 0); /* Don't check return.*/
-    debug(F111,"pty_open_ctty() ioctl TIOCSCTTY",ckitoa(retval),errno);
-#endif /* TIOCSTTY */
+    if (
+#ifdef COMMENT
+       fc == 0
+#else
+       1
+#endif /* COMMENT */
+       ) {
+       /* TIOCSCTTY = Make this the job's controlling terminal */
+       errno = 0;
+       retval = ioctl(*fd, TIOCSCTTY, 0); /* Don't check return.*/
+       debug(F111,"pty_open_ctty() ioctl TIOCSCTTY",ckitoa(retval),errno);
+    }
+#endif /* TIOCSCTTY */
     return(0L);
 }
 
 long
-pty_open_slave(slave, fd) char *slave; int *fd; {
+pty_open_slave(slave, fd, fc) char *slave; int *fd; int fc; {
     int vfd, testfd;
     long retval;
 #ifdef CK_POSIX_SIG
@@ -1003,7 +1101,7 @@ pty_open_slave(slave, fd) char *slave; int *fd; {
   use a descriptor if we can.
 */
 #ifdef VHANG_FIRST
-    if ((retval = pty_open_ctty(slave, &vfd)) != 0) {
+    if ((retval = pty_open_ctty(slave, &vfd, fc)) != 0) {
         debug(F111,
              "pty_open_slave() VHANG_FIRST",
              "pty_open_ctty() failed",
@@ -1059,28 +1157,24 @@ pty_open_slave(slave, fd) char *slave; int *fd; {
 
 /* Open the pty for real. */
 
-    retval = pty_open_ctty(slave, fd);
+    retval = pty_open_ctty(slave, fd, fc);
+    debug(F111,"pty_open_slave retval",slave,retval);
+    debug(F111,"pty_open_slave fd",slave,*fd);
     if (retval != 0) {
         debug(F111,"pty_open_slave()","pty_open_ctty() failed",retval);
        return(PTY_OPEN_SLAVE_OPENFAIL);
     }
+    pty_slave_fd = *fd;                   /* This is not visible to the upper fork */
+    debug(F111,"pty_open_slave fd ctty'd",slave,pty_slave_fd);
     retval = pty_initialize_slave(*fd);
+    debug(F111,"pty_open_slave fd init'd",slave,pty_slave_fd);
     if (retval) {
         debug(F111,"pty_open_slave()","pty_initialize_slave() failed",retval);
         return(retval);
     }
-#ifndef NO_DEVTTY
-    errno = 0;
-    testfd = open("/dev/tty", O_RDWR|O_NDELAY);
-    if (testfd < 0) {
-        debug(F111,"pty_open_slave() open failed","/dev/tty",errno);
-       close(*fd);
-       *fd = -1;
-       return(PTY_OPEN_SLAVE_NOCTTY);
-    }
-    close(testfd);
-#endif /* NO_DEVTTY */
-    debug(F110,"pty_open_slave()","success",0);
+    /* (VOID)pty_make_raw(*fd); */
+
+    debug(F100,"pty_open_slave OK","",*fd);
     return(0L);
 }
 
@@ -1409,20 +1503,35 @@ ptyint_update_wtmp(ent,host,user) struct utmp *ent; char *host; char *user; {
        close(fd);
     }
 #endif /* HAVE_UPDWTMP */
-    return(0); /* no current failure cases; file not found is not failure!*/
+    return(0); /* no current failure cases; file not found is not failure! */
 }
 #endif /* WANT_UTMP */
 
-static char Xline[17] = { 0, 0 };
-int pty_fork_pid = -1;
+/* This is for ancient Unixes that don't have these tty symbols defined. */
+
+#ifndef PENDIN
+#define PENDIN ICANON
+#endif /* PENDIN */
+#ifndef FLUSHO
+#define FLUSHO ICANON
+#endif /* FLUSHO */
+#ifndef IMAXBEL
+#define IMAXBEL ICANON
+#endif /* IMAXBEL */
+#ifndef EXTPROC
+#define EXTPROC ICANON
+#endif /* EXTPROC */
 
+static char Xline[17] = { 0, 0 };
 /*
   getptyslave()
   Open the slave side of the pty, and do any initialization that is necessary.
-  The return value is a file descriptor for the slave side.
+  The return value fd is a file descriptor for the slave side.
+  fc = function code from do_pty() (q.v.)
 */
 int
-getptyslave() {
+getptyslave(fd, fc) int * fd, fc; {
+    int ttyfd;
     int t = -1;
     long retval;
 #ifdef TIOCGWINSZ
@@ -1430,8 +1539,8 @@ getptyslave() {
     extern int cmd_rows, cmd_cols;
 #endif /* TIOCGWINSZ */
 
-    debug(F100,"getptyslave()","",0);
-
+    ttyfd = *fd;
+    debug(F111,"getptyslave()","ttyfd",ttyfd);
     /*
      * Opening the slave side may cause initilization of the
      * kernel tty structure.  We need remember the state of:
@@ -1440,17 +1549,16 @@ getptyslave() {
      *      terminal speed
      * so that we can reset them if we need to.
      */
-    if ((retval = pty_open_slave(Xline, &t)) != 0) {
+    if ((retval = pty_open_slave(Xline, &t, fc)) != 0) {
        perror(Xline);
        msg++;
         debug(F111,"getptyslave()","Unable to open slave",retval);
         return(-1);
     }
-
-    debug(F111,"getptyslave","ttyfd",ttyfd);
     debug(F111,"getptyslave","t",t);
 #ifdef INIT_SPTY
     spty = t;
+    debug(F111,"getptyslave","spty",spty);
 #endif /* INIT_SPTY */
 #ifdef STREAMSPTY
     if (ioctl(t,I_PUSH,"pckt") < 0) {
@@ -1462,78 +1570,178 @@ getptyslave() {
 #endif /* STREAMSPTY */
 
     /* Set up the tty modes as we like them to be. */
-    init_termbuf();
+#ifdef COMMENT
+    /* Originally like this... But this is the master - we want the slave */
+    /* Anyway, this fails on Solaris and probably other System V OS's */
+    init_termbuf(ttyfd);
+#else
+    init_termbuf(t);
+#endif /* COMMENT */
 #ifdef TIOCGWINSZ
     if (cmd_rows || cmd_cols) {
         memset((char *)&ws, 0, sizeof(ws));
         ws.ws_col = cmd_cols;
         ws.ws_row = cmd_rows;
+       debug(F101,"getptyslave() doing TIOCSWINSZ...","",t);
         ioctl(t, TIOCSWINSZ, (char *)&ws);
     }
 #endif /* TIOCGWINSZ */
 
-    /* Settings for sgtty based systems */
+    /* For external protocols, put the pty in no-echo mode */
+    if (fc == 1) {
+       debug(F100,"getptyslave() setting rawmode","",0);
+       /* iflags */
+       termbuf.c_iflag &= ~(PARMRK|ISTRIP|BRKINT|INLCR|IGNCR|ICRNL);
+       termbuf.c_iflag &= ~(INPCK|IGNPAR|IMAXBEL|IXANY|IXON|IXOFF);
+       termbuf.c_iflag |= IGNBRK;
+#ifdef IUCLC
+       termbuf.c_iflag &= ~IUCLC;
+#endif /* IUCLC */
+
+       /* oflags */
+       termbuf.c_oflag &= ~OPOST;
+#ifdef OXTABS
+       termbuf.c_oflag &= ~OXTABS;
+#endif /* OXTABS */
+#ifdef ONOCR
+       termbuf.c_oflag &= ~ONOCR;
+#endif /* ONOCR */
+#ifdef ONLRET
+       termbuf.c_oflag &= ~ONLRET;
+#endif /* ONLRET */
+#ifdef ONLCR
+       termbuf.c_oflag &= ~ONLCR;
+#endif /* ONLCR */
+
+       /* lflags */
+       termbuf.c_lflag &= ~ECHO;
+#ifdef ECHOE
+       termbuf.c_lflag &= ~ECHOE;
+#endif /* ECHOE */
+#ifdef ECHONL
+       termbuf.c_lflag &= ~ECHONL;
+#endif /* ECHONL */
+#ifdef ECHOPRT
+       termbuf.c_lflag &= ~ECHOPRT;
+#endif /* ECHOPRT */
+#ifdef ECHOKE
+       termbuf.c_lflag &= ~ECHOKE;
+#endif /* ECHOKE */
+#ifdef ECHOCTL
+       termbuf.c_lflag &= ~ECHOCTL;
+#endif /* ECHOCTL */
+#ifdef ALTWERASE
+       termbuf.c_lflag &= ~ALTWERASE;
+#endif /* ALTWERASE */
+#ifdef EXTPROC
+       termbuf.c_lflag &= ~EXTPROC;
+#endif /* EXTPROC */
+       termbuf.c_lflag &= ~(ICANON|ISIG|IEXTEN|TOSTOP|FLUSHO|PENDIN);
+
+#ifdef NOKERNINFO
+       termbuf.c_lflag |= NOKERNINFO;
+#endif /* NOKERNINFO */
+       /* termbuf.c_lflag |= NOFLSH; */
+       termbuf.c_lflag &= ~NOFLSH;
+
+       /* cflags */
+       termbuf.c_cflag &= ~(CSIZE|PARENB|PARODD);
+       termbuf.c_cflag |= CS8|CREAD;
+#ifdef VMIN
+       termbuf.c_cc[VMIN] = 1;
+#endif /* VMIN */
+    } else {                           /* Regular interactive use */
+       debug(F100,"getptyslave() setting cooked mode","",0);
+
+       /* Settings for sgtty based systems */
 
 #ifndef USE_TERMIO
-    termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS;
+       termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS;
 #endif /* USE_TERMIO */
 
 #ifndef OXTABS
 #define OXTABS 0
 #endif /* OXTABS */
 
-    /* Settings for UNICOS and HPUX */
+       /* Settings for UNICOS and HPUX */
 
 #ifdef CRAY
-    termbuf.c_oflag = OPOST|ONLCR|TAB3;
-    termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
-    termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
-    termbuf.c_cflag = EXTB|HUPCL|CS8;
+       termbuf.c_oflag = OPOST|ONLCR|TAB3;
+       termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
+       termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
+       termbuf.c_cflag = EXTB|HUPCL|CS8;
 #else /* CRAY */
 #ifdef HPUX
-    termbuf.c_oflag = OPOST|ONLCR|TAB3;
-    termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
-    termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
-    termbuf.c_cflag = EXTB|HUPCL|CS8;
+       termbuf.c_oflag = OPOST|ONLCR|TAB3;
+       termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
+       termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
+       termbuf.c_cflag = EXTB|HUPCL|CS8;
 #else /* HPUX */
 #ifdef USE_TERMIO
-    /*
-    Settings for all other termios/termio based systems, other than 4.4BSD.
-    In 4.4BSD the kernel does the initial terminal setup.
-    */
+       /*
+         Settings for all other termios/termio based systems, other than 
+         4.4BSD.  In 4.4BSD the kernel does the initial terminal setup.
+       */
 #ifdef BSD42
 #ifndef BSD44
-    termbuf.c_lflag |= ECHO|ICANON|IEXTEN|ISIG;
-    termbuf.c_oflag |= ONLCR|OXTABS|OPOST;
-    termbuf.c_iflag |= ICRNL|IGNPAR;
-    termbuf.c_cflag |= HUPCL;
-    termbuf.c_iflag &= ~IXOFF;
+       termbuf.c_lflag |= ECHO|ICANON|IEXTEN|ISIG;
+       termbuf.c_oflag |= ONLCR|OXTABS|OPOST;
+       termbuf.c_iflag |= ICRNL|IGNPAR;
+       termbuf.c_cflag |= HUPCL;
+       termbuf.c_iflag &= ~IXOFF;
 #endif /* BSD44 */
 #else /* BSD42 */
-    termbuf.c_lflag |= ECHO|ICANON|IEXTEN|ISIG;
-    termbuf.c_oflag |= ONLCR|OXTABS|OPOST;
-    termbuf.c_iflag |= ICRNL|IGNPAR;
-    termbuf.c_cflag |= HUPCL;
-    termbuf.c_iflag &= ~IXOFF;
+       termbuf.c_lflag |= ECHO|ICANON|IEXTEN|ISIG;
+       termbuf.c_oflag |= ONLCR|OXTABS|OPOST;
+       termbuf.c_iflag |= ICRNL|IGNPAR;
+       termbuf.c_cflag |= HUPCL;
+       termbuf.c_iflag &= ~IXOFF;
 #endif /* BSD42 */
 #endif /* USE_TERMIO */
 #endif /* HPUX */
 #endif /* CRAY */
+    }
 
-    set_termbuf();  /* Set the tty modes, and make this our controlling tty. */
+    /* Set the tty modes, and make this our controlling tty. */
+#ifdef COMMENT
+    /* But this is the master - we want the slave */
+    set_termbuf(ttyfd);
+#else
+    set_termbuf(t);
+#endif /* COMMENT */
 
     if (t != 0)
       dup2(t, 0);
     if (t != 1)
       dup2(t, 1);
-    if (t != 2)
-      dup2(t, 2);
+    if (t != 2) {
+       if (fc == 0) {
+           dup2(t, 2);
+       } else if (fc == 1) {
+           /* For external protocols, send stderr to /dev/null */
+#ifdef COMMENT
+           int xx;
+#ifndef COMMENT
+           char * s = "/dev/null";
+           errno = 0;
+           xx = open(s, O_WRONLY);
+#else
+           char * s = "pty.log";
+           errno = 0;
+           xx = open(s, O_CREAT, 0644);
+#endif /* COMMENT */
+           debug(F111,"getptyslave redirect stderr",s,errno);
+           dup2(xx,2);
+#endif /* COMMENT */
+       }
+    }
     if (t > 2)
       close(t);
 
     if (ttyfd > 2) {
        close(ttyfd);
         ttyfd = -1;
+       *fd = ttyfd;
     }
     return(0);
 }
@@ -1606,20 +1814,53 @@ exec_cmd(s) char * s; {
     if (!q) return;
 
     args = q->a_head + 1;
+
+#ifdef DEBUG    
+    {
+       int i, n;
+       n = q->a_size;
+       for (i = 0; i <= n; i++) {
+           if (!args[i]) {
+               debug(F111,"exec_cmd arg","NULL",i);
+               break;
+           } else {
+               debug(F111,"exec_cmd arg",args[i],i);
+               if (i == n && args[i]) {
+                   debug(F101,"exec_cmd SUBSTITUTING NULL","",i);
+                   if (strlen(args[i]) == 0)
+                     makestr(&(args[i]),NULL);
+               }
+
+           }
+       }           
+    }
+#endif /* DEBUG */
+
     execvp(args[0],args);
 }
 
 /* Get a pty, scan input lines. */
+/* fc = 0 for interactive access; fc = 1 for running external protocols */
+
+static int pty_fc = -1;                        /* Global copy of fc */
 
 int
-do_pty(cmd) char * cmd; {
+do_pty(fd, cmd, fc) int * fd; char * cmd; int fc; {
     long retval;
     int syncpipe[2];
-    int i;
+    int i, ttyfd;
 #ifdef HAVE_PTYTRAP
     int x;
 #endif /* HAVE_PTYTRAP */
 
+    debug(F101,"CKUPTY.C do_pty fc","",fc);
+
+    ttyfd = *fd;
+
+    pty_master_fd = -2;
+    pty_slave_fd = -2;
+    pty_fork_pid = -2;
+
     msg = 0;                           /* Message counter */
     pty_init();                                /* Find an available pty to use. */
     errno = 0;
@@ -1628,9 +1869,11 @@ do_pty(cmd) char * cmd; {
        if (msg++ == 0)
          perror(Xline);
         debug(F111,"do_pty()","pty_getpty() fails",retval);
+       *fd = ttyfd;
         return(-1);
     }
-    debug(F110,"do_pty() Xline",Xline,0);
+    *fd = ttyfd;
+    debug(F111,"do_pty() Xline",Xline,ttyfd);
 
 #ifdef SIGTTOU
 /*
@@ -1671,6 +1914,7 @@ do_pty(cmd) char * cmd; {
             return(-1);
         }
         pty_fork_pid = i;              /* So we can clean it up later */
+       pty_fork_active = 1;
        debug(F101,"do_pty pty_fork_pid","",pty_fork_pid);
 #ifdef HAVE_PTYTRAP
         /* HPUX does not allow the master to read end of file.  */
@@ -1683,8 +1927,13 @@ do_pty(cmd) char * cmd; {
         debug(F111,"do_pty()","synchronized - pty_fork_pid",pty_fork_pid);
         close(syncpipe[0]);
     } else {
+       int x;
+       debug(F101,"do_pty getptyslave ttyfd A","",ttyfd);
         debug(F110,"do_pty()","Slave starts",0);
-        if (getptyslave() == 0) {
+       x = getptyslave(&ttyfd,fc);
+       debug(F101,"do_pty getptyslave","",x);
+        if (x == 0) {
+           debug(F101,"do_pty getptyslave ttyfd B","",ttyfd);
 #ifdef WANT_UTMP
             pty_update_utmp(PTY_USER_PROCESS,
                            getpid(),
@@ -1700,23 +1949,31 @@ do_pty(cmd) char * cmd; {
             close(syncpipe[0]);
             close(syncpipe[1]);
 
+           debug(F110,"do_pty cmd",cmd,"");
             exec_cmd(cmd);
             debug(F111,"do_pty()","exec_cmd() returns - why?",errno);
         }
+       *fd = ttyfd;
         debug(F110,"do_pty()","getptyslave() fails - exiting",0);
         exit(1);
     }
-    return(0);
+    *fd = ttyfd;
+    pty_fc = fc;
+    return(getpid());
 } /* end of do_pty() */
 
 
 VOID
 end_pty() {
     msg = 0;                           /* Message counter */
+    debug(F101,"end_pty pty_fork_pid","",pty_fork_pid);
     if (Xline[0] && pty_fork_pid >= 0) {
         pty_cleanup(Xline,pty_fork_pid,1);
         Xline[0] = '\0';
         pty_fork_pid = -1;
+       pty_fork_active = 0;
+       debug(F101,"end_pty pty_fork_active","",pty_fork_active);
     }
+    pty_fc = -1;
 }
 #endif /* NETPTY */
index 6749bec..374c508 100644 (file)
--- a/ckupty.h
+++ b/ckupty.h
@@ -37,7 +37,9 @@
 #include <stdio.h>
 
 #include <sys/stat.h>
+#ifndef SUNOS41
 #include <sys/ioctl.h>
+#endif /* SUNOS41 */
 #include <sys/file.h>
 #include <sys/time.h>
 #include <ctype.h>
 #endif /* HAVE_SYS_PTYVAR_H */
 #endif /* HAVE_STREAMS */
 
+#ifdef COMMENT
+/* This block moved to ckcdeb.h */
+#ifndef NO_OPENPTY
+/* For NetBSD, see makefile */
+#ifndef HAVE_OPENPTY
+#ifdef __FreeBSD__
+#define HAVE_OPENPTY
+#else
+#ifdef MACOSX10
+#define HAVE_OPENPTY
+#endif /* MACOSX10 */
+#endif /* __FreeBSD__ */
+#endif /* HAVE_OPENPTY */
+#endif /* NO_OPENPTY */
+#endif /* COMMENT */
+
 #ifdef HAVE_VHANGUP
 #ifndef OPEN_CTTY_ONLY_ONCE
 /*
@@ -142,8 +160,8 @@ _PROTOTYP(long ptyint_update_wtmp, (struct utmp *, char *, char *));
 
 _PROTOTYP(long pty_init,(void));
 _PROTOTYP(long pty_getpty, ( int *, char *, int));
-_PROTOTYP(long pty_open_slave, (char *, int *));
-_PROTOTYP(long pty_open_ctty, (char *, int *));
+_PROTOTYP(long pty_open_slave, (char *, int *, int));
+_PROTOTYP(long pty_open_ctty, (char *, int *, int));
 _PROTOTYP(long pty_initialize_slave, (int));
 #ifdef WANT_UTMP
 _PROTOTYP(long pty_update_utmp, (int, int, char *, char *, char *, int));
@@ -172,3 +190,4 @@ extern struct error_table et_pty_error_table;
 
 #define __LIBPTY_H__
 #endif /* __LIBPTY_H__ */
+
index 98d2fd6..7a2d9b7 100644 (file)
--- a/ckuscr.c
+++ b/ckuscr.c
@@ -2,12 +2,12 @@
 
 #ifndef NOICP
 #ifndef NOSCRIPT
-char *loginv = "Script Command, 8.0.032, 20 Dec 2001";
+char *loginv = "Script Command, 9.0.032, 16 Oct 2009";
 
 /*  C K U S C R  --  expect-send script implementation  */
 
 /*
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2009,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
index 9f60b96..e4556e5 100644 (file)
--- a/ckusig.c
+++ b/ckusig.c
@@ -1,10 +1,12 @@
+char *ckusigv = "Signal support, 9.0.100, 16 Oct 2009";
+
 /* C K U S I G  --  Kermit signal handling for Unix and OS/2 systems */
 
 /*
   Author: Jeffrey Altman (jaltman@secure-endpoints.com),
             Secure Endpoints Inc., New York City.
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2009,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
index bf61e38..3482900 100644 (file)
--- a/ckusig.h
+++ b/ckusig.h
@@ -6,7 +6,7 @@
   Author: Jeffrey E Altman (jaltman@secure-endpoints.com),
             Secure Endpoints Inc., New York City.
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2009,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
index 4c517cc..d3354be 100644 (file)
--- a/ckutio.c
+++ b/ckutio.c
@@ -1,10 +1,12 @@
+#define CKUTIO_C
+
 #ifdef aegis
-char *ckxv = "Aegis Communications support, 8.0.303, 17 Apr 2004";
+char *ckxv = "Aegis Communications support, 9.0.323, 10 June 2011";
 #else
 #ifdef Plan9
-char *ckxv = "Plan 9 Communications support, 8.0.303, 17 Apr 2004";
+char *ckxv = "Plan 9 Communications support, 9.0.323, 10 June 2011";
 #else
-char *ckxv = "UNIX Communications support, 8.0.303, 17 Apr 2004";
+char *ckxv = "UNIX Communications support, 9.0.323, 10 June 2011";
 #endif /* Plan9 */
 #endif /* aegis */
 
@@ -16,7 +18,7 @@ char *ckxv = "UNIX Communications support, 8.0.303, 17 Apr 2004";
   Author: Frank da Cruz (fdc@columbia.edu),
   Columbia University Academic Information Systems, New York City.
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2011,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -33,6 +35,7 @@ char *ckxv = "UNIX Communications support, 8.0.303, 17 Apr 2004";
 */
 
 extern int nettype;                    /* Defined in ckcmai.c */
+extern int duplex;
 
 /* Includes */
 
@@ -197,6 +200,20 @@ bzero(s,n) char *s; int n; {
 #endif /* FT21 */
 #endif /* MAXNAMLEN */
 #endif /* BSD4 */
+
+#ifdef SUNOS41                         /* From Christian Corti */
+#define BSD44ORPOSIX                   /* Uni Stuttgart */
+#define SVORPOSIX                      /* February 2010 */
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <limits.h>
+#endif /* SUNOS41 */
+
+#ifdef SNI542
+#include <sys/filio.h>                 /* 299 for FIONREAD */
+#endif /* SNI542 */
+
 /*
   Minix 2.0 support added by Terry McConnell,
   Syracuse University <tmc@barnyard.syr.edu>
@@ -204,10 +221,11 @@ bzero(s,n) char *s; int n; {
 */
 #ifdef MINIX2
 #define _MINIX   /* Needed for some Minix header files */
-#undef MINIX     /* Old minix 1.0: used sgtty interface */
 #define BSD44ORPOSIX
 #define SVORPOSIX
+#ifndef MINIX3
 #define DCLTIMEVAL
+#endif /* MINIX3 */
 #define NOFILEH
 #include <sys/types.h>
 #include <sys/ioctl.h>
@@ -301,19 +319,49 @@ char unm_ver[CK_SYSNMLN+1] = { '\0', '\0' };
 #include <sys/stat.h>
 #endif /* CIE */
 
+#ifdef QNX                             /* 299 */
+#ifndef IXANY
+#define IXANY 0
+#endif /* IXANY */
+#endif /* QNX */
+
 /* UUCP lockfile material... */
 
 #ifndef NOUUCP
 #ifdef USETTYLOCK
+#ifdef HAVE_LOCKDEV                    /* Red Hat baudboy/lockdev */
+/*
+  Watch out: baudboy.h references open() without making sure it has been
+  declared, resulting in warnings on at least Red Hat 7.3.  It's declared in
+  fcntl.h, but we don't include that until later.  In this case only, we
+  include it here, and then the second include is harmless because in Red Hat
+  Linux (the only place where you find baudboy.h) fcntl.h is protected from
+  multiple inclusion by _FCNTL_H.   - fdc, 10 May 2004.
+
+  NOTE: Although Linux /usr/sbin/lockdev obviates the need for setuid or
+  setgid bits to access the lockfile, C-Kermit will still need them to access
+  the serial port itself unless the port is open for world read/write.
+  Normally setgid uucp does the trick.
+
+  Extra: HAVE_LOCKDEV has been added als openSuSE >= 11.3 doesn't use baudboy
+  but ttylock.  - jb, 26 Jul 2010
+*/
+#include <fcntl.h>                     /* This has to come before baudboy */
 #ifdef HAVE_BAUDBOY                    /* Red Hat baudboy/lockdev */
 #include <baudboy.h>
-#else
+#else  /* !HAVE_BAUDBOY */             /* openSuSE lock via ttylock */
+#include <ttylock.h>
+#endif  /* HAVE_BAUDBOY */
+#define LOCK_DIR "/var/lock"           /* (even though we don't care) */
+
+#else  /* !HAVE_LOCKDEV */
+
 #ifdef USE_UU_LOCK
 #ifdef __FreeBSD__
 #include <libutil.h>                   /* FreeBSD */
 #else
 #include <util.h>                      /* OpenBSD */
-#endif /* HAVE_BAUDBOY */
+#endif /* HAVE_LOCKDEV */
 #endif /* __FreeBSD */
 #endif /* USE_UU_LOCK */
 #else  /* USETTYLOCK */
@@ -932,6 +980,18 @@ struct timezone {
 #define O_RDONLY 000
 #endif /* O_RDONLY */
 
+/* This is for ancient Unixes that don't have these tty symbols defined. */
+
+#ifndef PENDIN
+#define PENDIN ICANON
+#endif /* PENDIN */
+#ifndef FLUSHO
+#define FLUSHO ICANON
+#endif /* FLUSHO */
+#ifndef EXTPROC
+#define EXTPROC ICANON
+#endif /* EXTPROC */
+
 #ifdef SVORPOSIX
 /*
   Modem signals are also forbidden in the POSIX world.  But some POSIX-based
@@ -1148,6 +1208,9 @@ static CHAR le_buf[LEBUFSIZ];
 static int le_start = 0, le_end = 0, le_data = 0;
 #endif /* TTLEBUF */
 
+#define MSGBUF_SIZE 1024               /* For debugging */
+static char msgbuf[MSGBUF_SIZE];
+
 static int gotsigs = 0;
 
 static time_t tcount = (time_t)0;      /* Elapsed time counter */
@@ -1209,6 +1272,11 @@ int ttyfd = -1;                          /* TTY file descriptor */
 int ttpipe = 0;                                /* NETCMD: Use pipe instead of ttyfd */
 int ttpty  = 0;                         /* NETPTY: Use pty instead of ttfyd */
 
+#ifdef NETPTY                          /* These are in ckupty.c */
+extern PID_T pty_fork_pid;
+extern int pty_master_fd, pty_slave_fd;
+#endif /* NETPTY */
+
 #ifdef NETCMD
 #ifdef NETCONN
 static int pipe0[2], pipe1[2];         /* Pipes for net i/o */
@@ -1465,6 +1533,7 @@ _PROTOTYP( static int ttrpid, (char *) );
 _PROTOTYP( static int ttchkpid, (char *) );
 _PROTOTYP( static int ttlock, (char *) );
 _PROTOTYP( static int ttunlck, (void) );
+_PROTOTYP( static VOID sigchld_handler, (int) );
 _PROTOTYP( int mygetbuf, (void) );
 _PROTOTYP( int myfillbuf, (void) );
 _PROTOTYP( VOID conbgt, (int) );
@@ -1547,7 +1616,7 @@ timerh(foo) int foo; {
 /*ARGSUSED*/
 SIGTYP
 xtimerh(foo) int foo; {                        /* Like timerh() but does */
-#ifdef BEOSORBEBOX                     /* not reset the timer itslef */
+#ifdef BEOSORBEBOX                     /* not reset the timer itself */
 /* #ifdef BE_DR_7 */
     alarm_expired();
 /* #endif */ /* BE_DR_7 */
@@ -1677,7 +1746,7 @@ le_puts(s,n) CHAR * s; int n;
     int rc = 0;
     int i = 0;
     CHAR * p = (CHAR *)"le_puts";
-    hexdump(p,s,n);
+    ckhexdump(p,s,n);
     for (i = 0; i < n; i++)
       rc = le_putchar((char)s[i]);
     debug(F101,"le_puts","",rc);
@@ -1694,7 +1763,7 @@ le_putstr(s) CHAR * s;
     CHAR * p;
     int rc = 0;
     p = (CHAR *)"le_putstr";
-    hexdump(p,s,(int)strlen((char *)s));
+    ckhexdump(p,s,(int)strlen((char *)s));
     for (p = s; *p && !rc; p++)
       rc = le_putchar(*p);
     return(rc);
@@ -1809,14 +1878,15 @@ ttgwsiz() {
 }
 
 
+#ifdef RLOGCODE
+_PROTOTYP( int rlog_naws, (void) );
+#endif /* RLOGCODE */
+
 #ifndef NOSIGWINCH
 #ifdef SIGWINCH
 SIGTYP
 winchh(foo) int foo; {                 /* SIGWINCH handler */
     int x = 0;
-#ifdef NETPTY
-    extern int pty_fork_pid;
-#endif /* NETPTY */
 #ifdef CK_TTYFD
 #ifndef VMS
     extern int ttyfd;
@@ -2022,6 +2092,10 @@ sysinit() {
 #endif /* SIGWINCH */
 #endif /* NOSIGWINCH */
 
+#ifdef SIGXFSZ
+    signal(SIGXFSZ,SIG_IGN);           /* Ignore writing past file limit */ 
+#endif /* SIGXFSZ */
+
 #ifndef NOJC
 /*
   Get the initial job control state.
@@ -2429,7 +2503,7 @@ ttopen(ttname,lcl,modem,timo) char *ttname; int *lcl, modem, timo; {
                 netconn = 1;            /* but we don't use network i/o */
                 ttpty = 1;
                 debug(F110,"ttopen PTY",ttname,0);
-               x = do_pty(ttname);
+               x = do_pty(&ttyfd,ttname,0);
                if (x > -1) {
                    ckstrncpy(ttnmsv,ttname,DEVNAMLEN);
                    xlocal = *lcl = 1;  /* It's local */
@@ -3581,6 +3655,26 @@ ttclos(foo) int foo; {                   /* Arg req'd for signal() prototype */
                x = tthang();           /* Hang up first, then... */
                debug(F101,"ttclos tthang()","",x);
            }
+#ifndef CK_NOHUPCL
+/*
+  Oct 2006 - Leave DTR on if SET EXIT HANGUP OFF.
+  Suggested by Soewono Effendi.
+*/
+#ifdef HUPCL
+           else {
+               ttold.c_cflag &= ~HUPCL; /* Let's see how this travels */
+#ifdef BSD44ORPOSIX
+               tcsetattr(ttyfd,TCSANOW,&ttold);
+#else /* !BSD44ORPOSIX */
+#ifdef ATTSV
+               ioctl(ttyfd,TCSETAW,&ttold);            
+#else  /* !ATTSV */
+               stty(ttyfd,&ttold);
+#endif /* ATTSV */
+#endif /* BSD44ORPOSIX */
+           }
+#endif /* HUPCL */
+#endif /* CK_NOHUPCL */
        }
        /* Put back device modes as we found them */
 
@@ -5834,7 +5928,19 @@ _PROTOTYP( int tcsetattr, (int, int, struct termios *) );
                x = tcsetattr(ttyfd,TCSANOW,&temp);
                debug(F111,"tthflow POSIX_CRTSCTS OFF tcsetattr",
                      ckitoa(x),errno);
-           }
+           } else {                    /* John Dunlap 2010-01-26 */
+               debug(F001,
+                     "tthflow before forcing off attrs CRTSCTS",
+                     "",
+                     attrs->c_cflag&CRTSCTS
+                     );
+               attrs->c_cflag &= ~CRTSCTS; /* force it off if !status */
+               debug(F001,
+                     "tthflow after forcing off attrs CRTSCTS",
+                     "",
+                     attrs->c_cflag&CRTSCTS
+                     );
+               }
        } else {                        /* Turn hard flow on */
            if (
 #ifdef COMMENT
@@ -6650,6 +6756,81 @@ ttpkt(speed,xflow,parity) long speed; int xflow, parity;
 #ifdef BEOSORBEBOX
     ttraw.c_cc[VMIN] = 0;              /* DR7 can only poll. */
 #endif /* BEOSORBEBOX */
+
+#define TESTING234
+#ifdef TESTING234
+    if (1) {
+       debug(F100,"ttpkt TESTING234 rawmode","",0);
+
+       /* iflags */
+       ttraw.c_iflag &= ~(PARMRK|ISTRIP|BRKINT|INLCR|IGNCR|ICRNL);
+       ttraw.c_iflag &= ~(INPCK|IGNPAR|IXON|IXOFF);
+       ttraw.c_iflag |= IGNBRK;
+#ifdef IMAXBEL
+       ttraw.c_iflag &= ~IMAXBEL;
+#endif /* IMAXBEL */
+#ifdef IXANY
+       ttraw.c_iflag &= ~IXANY;
+#endif /* IXANY */
+#ifdef IUCLC
+       ttraw.c_iflag &= ~IUCLC;
+#endif /* IUCLC */
+
+       /* oflags */
+       ttraw.c_oflag &= ~OPOST;
+#ifdef OXTABS
+       ttraw.c_oflag &= ~OXTABS;
+#endif /* OXTABS */
+#ifdef ONOCR
+       ttraw.c_oflag &= ~ONOCR;
+#endif /* ONOCR */
+#ifdef ONLRET
+       ttraw.c_oflag &= ~ONLRET;
+#endif /* ONLRET */
+#ifdef ONLCR
+       ttraw.c_oflag &= ~ONLCR;
+#endif /* ONLCR */
+
+       /* lflags */
+       ttraw.c_lflag &= ~ECHO;
+#ifdef ECHOE
+       ttraw.c_lflag &= ~ECHOE;
+#endif /* ECHOE */
+#ifdef ECHONL
+       ttraw.c_lflag &= ~ECHONL;
+#endif /* ECHONL */
+#ifdef ECHOPRT
+       ttraw.c_lflag &= ~ECHOPRT;
+#endif /* ECHOPRT */
+#ifdef ECHOKE
+       ttraw.c_lflag &= ~ECHOKE;
+#endif /* ECHOKE */
+#ifdef ECHOCTL
+       ttraw.c_lflag &= ~ECHOCTL;
+#endif /* ECHOCTL */
+#ifdef ALTWERASE
+       ttraw.c_lflag &= ~ALTWERASE;
+#endif /* ALTWERASE */
+#ifdef EXTPROC
+       ttraw.c_lflag &= ~EXTPROC;
+#endif /* EXTPROC */
+       ttraw.c_lflag &= ~(ICANON|ISIG|IEXTEN|TOSTOP|FLUSHO|PENDIN);
+#ifdef NOKERNINFO
+       ttraw.c_lflag |= NOKERNINFO;
+#endif /* NOKERNINFO */
+       /* ttraw.c_lflag |= NOFLSH; */
+       ttraw.c_lflag &= ~NOFLSH;
+
+       /* cflags */
+       ttraw.c_cflag &= ~(CSIZE|PARENB|PARODD);
+       ttraw.c_cflag |= CS8|CREAD;
+#ifdef VMIN
+       ttraw.c_cc[VMIN] = 1;           /* Supposedly needed for AIX */
+#endif /* VMIN */
+
+    }
+#endif /* TESTING234 */
+
     debug(F100,"ttpkt calling tcsetattr(TCSETAW)","",0);
     x = tcsetattr(ttyfd,TCSADRAIN,&ttraw);
     debug(F101,"ttpkt BSD44ORPOSIX tcsetattr","",x);
@@ -7337,10 +7518,6 @@ ttsspd(cps) int cps; {
 
 #else  /* Not USETCSETSPEED */
 
-#ifdef MINIX2        /* Hack alert */
-#define MINIX        /* Use pre-2.0 speed selection for Minix 2.0 as well */
-#endif /* MINIX2 */
-
     /* First check that the given speed is valid. */
 
     switch (cps) {
@@ -7965,11 +8142,6 @@ ttgspd() {                               /* Get current serial device speed */
 #endif /* EXTA */
 #endif /* B19200 */
 
-#ifdef MINIX2
-/* End of hack to make MINIX2 use MINIX1 speed setting */
-#undef MINIX
-#endif /* MINIX2 */
-
 #ifndef MINIX
 #ifdef B38400
       case B38400:
@@ -8019,7 +8191,7 @@ ttgspd() {                                /* Get current serial device speed */
 #endif /* B460800 */
 #endif /* HPUX */
 #ifdef B921600
-      case 92160: ss = 921600L; break;
+      case B921600: ss = 921600L; break;
 #endif /* B921600 */
       default:
        ss = -1; break;
@@ -8126,6 +8298,10 @@ ttpeek() {
 
 /* myread() -- Efficient read of one character from communications line.
  *
+ * NOTE: myread() and its helpers mygetbuf() and myfillbuf() return raw
+ * bytes from connection, so when the connection is encrypted, these bytes
+ * must be decrypted.
+ *
  * Uses a private buffer to minimize the number of expensive read() system
  * calls.  Essentially performs the equivalent of read() of 1 character, which
  * is then returned.  By reading all available input from the system buffers
@@ -8165,16 +8341,20 @@ ttpeek() {
  * that guarantees that there is space for at least one character.  If push
  * back was really needed after EOF, a small addition could provide that.
  *
- * myunrd() is currently not called from anywhere inside kermit...
+ * As of 02/2007 myunrd() is used by ttinl().
  */
-#ifdef COMMENT /* not used */
-myunrd(ch) CHAR ch; {
+VOID
+#ifdef CK_ANSIC
+myunrd(CHAR ch)
+#else
+myunrd(ch) CHAR ch;
+#endif /* CK_ANSIC */
+{
     if (my_item >= 0) {
        mybuf[my_item--] = ch;
        ++my_count;
     }
 }
-#endif /* COMMENT */
 
 /*  T T P U S H B A C K  --  Put n bytes back into the myread buffer */
 
@@ -8246,7 +8426,7 @@ mygetbuf() {
 #ifdef COMMENT
     if (deblog) debug(F101, "mygetbuf read", "", my_count);
 #else /* COMMENT */
-    if (deblog) hexdump("mygetbuf read", mybuf, my_count);
+    ckhexdump("mygetbuf read", mybuf, my_count);
 #endif /* COMMENT */
 #endif /* DEBUG */
     x = my_count;
@@ -8347,7 +8527,7 @@ myfillbuf() {
     }
 #else /* BEOSORBEBOX */
     errno = 0;
-    debug(F100,"SVORPOSIX myfillbuf calling read()","",0);
+    /* debug(F101,"SVORPOSIX myfillbuf calling read() fd","",fd); */
 #ifdef IBMX25
     if (netconn && (nettype == NET_IX25)) {
        /* can't use sizeof because mybuf is a pointer, and not an array! */
@@ -8358,6 +8538,7 @@ myfillbuf() {
 #ifdef CK_SSL
       if (ssl_active_flag || tls_active_flag) {
          int error, n = 0;
+         debug(F100,"myfillbuf calling SSL_read() fd","",0);
          while (n == 0) {
              if (ssl_active_flag)
                 n = SSL_read(ssl_con, (char *)mybuf, sizeof(mybuf));
@@ -8393,7 +8574,8 @@ myfillbuf() {
 #ifdef KRB4
 #ifdef RLOGCODE
     if (ttnproto == NP_EK4LOGIN) {
-        if ((n = krb4_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
+       debug(F101,"myfillbuf calling krb4_des_read() fd","",ttyfd);
+        if ((n = krb4_des_read(ttyfd,(char *)mybuf,sizeof(mybuf))) < 0)
          return(-3);
         else
          return(n);
@@ -8403,7 +8585,8 @@ myfillbuf() {
 #ifdef KRB5
 #ifdef RLOGCODE
     if (ttnproto == NP_EK5LOGIN) {
-        if ((n = krb5_des_read(ttyfd,mybuf,sizeof(mybuf),0)) < 0)
+       debug(F101,"myfillbuf calling krb5_des_read() fd","",ttyfd);
+        if ((n = krb5_des_read(ttyfd,(char *)mybuf,sizeof(mybuf),0)) < 0)
          return(-3);
         else
          return(n);
@@ -8411,7 +8594,8 @@ myfillbuf() {
 #endif /* RLOGCODE */
 #ifdef KRB5_U2U
     if (ttnproto == NP_K5U2U) {
-        if ((n = krb5_u2u_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
+       debug(F101,"myfillbuf calling krb5_u2u_read() fd","",ttyfd);
+        if ((n = krb5_u2u_read(ttyfd,(char *)mybuf,sizeof(mybuf))) < 0)
          return(-3);
         else
          return(n);
@@ -8425,6 +8609,7 @@ myfillbuf() {
     /* Special handling for HP-UX pty i/o */
   ptyread:
     if (ttpty && pty_trap_pending(ttyfd) > 0) {
+       debug(F101,"myfillbuf calling pty_trap_handler() fd","",ttyfd);
         if (pty_trap_handler(ttyfd) > 0) {
             ttclos(0);
             return(-3);
@@ -8432,10 +8617,11 @@ myfillbuf() {
     }
 #endif /* HAVE_PTYTRAP */
 #endif /* NETPTY */
+    debug(F101,"myfillbuf calling read() fd","",ttyfd);
     n = read(fd, mybuf, sizeof(mybuf));
-    debug(F101,"SVORPOSIX myfillbuf","",n);
-    debug(F101,"SVORPOSIX myfillbuf ttcarr","",ttcarr);
+    debug(F101,"SVORPOSIX myfillbuf read","",n);
     debug(F101,"SVORPOSIX myfillbuf errno","",errno);
+    debug(F101,"SVORPOSIX myfillbuf ttcarr","",ttcarr);
     if (n < 1) {
 #ifdef NETPTY
 #ifdef HAVE_PTYTRAP
@@ -8605,7 +8791,7 @@ myfillbuf() {
        debug(F101,"myfillbuf read","",x);
        debug(F101,"myfillbuf read errno","",errno);
         if (x > 0)
-         hexdump("myfillbuf mybuf",mybuf,x);
+         ckhexdump("myfillbuf mybuf",mybuf,x);
     }
 #endif /* DEBUG */
     if (x < 1) x = -3;                 /* read 0 == connection loss */
@@ -8698,10 +8884,6 @@ myfillbuf() {
 
 #endif /* MYREAD */
 
-#ifdef MINIX2
-#undef MINIX
-#endif /* MINIX2 */
-
 /*  T T _ T N O P T  --  Handle Telnet negotions in incoming data */
 /*
   Call with the IAC that was encountered.
@@ -8720,7 +8902,6 @@ tt_tnopt(n) int n; {                      /* Handle Telnet options */
     if (n == IAC &&
        ((xlocal && netconn && IS_TELNET()) ||
         (!xlocal && sstelnet))) {
-       extern int duplex;
        extern int server;
        int tx = 0;
        debug(F100,"ttinl calling tn_doop()","",0);
@@ -8809,7 +8990,7 @@ ttflux() {                                /* But first... */
            ch = myread();
 #ifdef CK_ENCRYPTION
             if (TELOPT_U(TELOPT_ENCRYPTION))
-             ck_tn_decrypt(&ch,1);
+             ck_tn_decrypt((char *)&ch,1);
 #endif /* CK_ENCRYPTION */
             if (ch == IAC)
              x = tt_tnopt(ch);
@@ -9063,6 +9244,10 @@ conbgt(flag) int flag; {
 #undef PGROUP_T
 #endif /* MIPS */
 
+#ifdef MINIX
+#undef PGROUP_T
+#endif /* MINIX */
+
 #ifdef PGROUP_T
 /*
   Semi-reliable process-group test.  Check whether this process's group is
@@ -9122,9 +9307,11 @@ conbgt(flag) int flag; {
 #endif /* POSIX */
 #endif /* SVR3 */
 
-#ifdef MINIX2
-#undef BSD44ORPOSIX
-#endif /* MINIX2 */
+#ifdef MINIX
+    /* MINIX does not support job control so Kermit is always in foreground */
+    x = 0;
+
+#else  /* Not MINIX */
 
 /* Now get controlling tty's process group */
 #ifdef BSD44ORPOSIX
@@ -9135,15 +9322,12 @@ conbgt(flag) int flag; {
    /* debug(F101,"non-POSIX conbgt terminal process group","",(int) ctpgrp); */
 #endif /* BSD44ORPOSIX */
 
-#ifdef MINIX2
-#define BSD44ORPOSIX
-#endif /* MINIX2 */
-
     if ((mypgrp > (PID_T) 0) && (ctpgrp > (PID_T) 0))
       x = (mypgrp == ctpgrp) ? 0 : 1;  /* If they differ, then background. */
     else x = -1;                       /* If error, remember. */
     debug(F101,"conbgt process group test","",x);
 #endif /* PGROUP_T */
+#endif /* MINIX */
 
 /* Try to see if job control is available */
 
@@ -9241,8 +9425,8 @@ conbgt(flag) int flag; {
        osigint = signal(SIGINT,SIG_IGN);       /* What is SIGINT set to? */
        sigint_ign = 1;
        x = (osigint == SIG_IGN) ? 1 : 0;       /* SIG_IGN? */
-       debug(F101,"conbgt osigint","",osigint);
-       debug(F101,"conbgt signal test","",x);
+       /* debug(F101,"conbgt osigint","",osigint); */
+       /* debug(F101,"conbgt signal test","",x); */
     }
 
 /* Also check to see if we're running with redirected stdio. */
@@ -10120,7 +10304,10 @@ ttol(s,n) int n; CHAR *s; {
     if (ttyfd < 0)                     /* Not open? */
       return(-3);
 #ifdef DEBUG
-    if (deblog) hexdump("ttol s",s,n);
+    if (deblog) {
+       /* debug(F101,"ttol ttyfd","",ttyfd); */
+       ckhexdump("ttol s",s,n);
+    }
 #endif /* DEBUG */
 
 #ifdef NETCMD
@@ -10153,7 +10340,7 @@ ttol(s,n) int n; CHAR *s; {
            s[n] = '\0';
        }
 #ifdef DEBUG
-        if (deblog) hexdump("ttol doubled s",s,n);
+        ckhexdump("ttol doubled s",s,n);
 #endif /* DEBUG */
     }
 #endif /* CKXXCHAR */
@@ -10255,12 +10442,12 @@ ttol(s,n) int n; CHAR *s; {
 #ifdef KRB5
 #ifdef RLOGCODE
             if (ttnproto == NP_EK5LOGIN) {
-                return(krb5_des_write(ttyfd,s,n,0));
+                return(krb5_des_write(ttyfd,(char *)s,n,0));
             } else
 #endif /* RLOGCODE */
 #ifdef KRB5_U2U
             if (ttnproto == NP_K5U2U) {
-                return(krb5_u2u_write(ttyfd,s,n));
+                return(krb5_u2u_write(ttyfd,(char *)s,n));
             } else
 #endif /* KRB5_U2U */
 #endif /* KRB5 */
@@ -10429,7 +10616,7 @@ ttoc(c) char c;
 #ifdef KRB4
 #ifdef RLOGCODE
          if (ttnproto == NP_EK4LOGIN) {
-             rc = (krb4_des_write(ttyfd,&c,1) == 1);
+             rc = (krb4_des_write(ttyfd,(char *)&c,1) == 1);
          } else
 #endif /* RLOGCODE */
 #endif /* KRB4 */
@@ -10461,7 +10648,7 @@ ttoc(c) char c;
 
 /*  T T I N L  --  Read a record (up to break character) from comm line.  */
 /*
-  Reads up to "max" characters from the communication line, terminating on:
+  Reads up to "max" characters from the connection, terminating on:
     (a) the packet length field if the "turn" argument is zero, or
     (b) on the packet-end character (eol) if the "turn" argument is nonzero
     (c) a certain number of Ctrl-C's in a row
@@ -10472,13 +10659,21 @@ ttoc(c) char c;
     -2 on user interruption (c);
     -3 on fatal error like connection lost.
 
-  The characters that were input are copied into "dest" with their parity bits
-  stripped if parity was selected.  Returns the number of characters read.
-  Characters after the eol are available upon the next call to this function.
+  The name of this routine dates from the early days when Kermit packets
+  were, indeed, always lines of text.  That was before control-character
+  unprefixing and length-driven packet framing were introduced, which this
+  version handle.  NB: this routine is ONLY for reading incoming Kermit
+  packets, nothing else.  To read other kinds of incoming material, use
+  ttinc() or ttxin().
+
+  The bytes that were input are copied into "dest" with their parity bits
+  stripped if parity was selected.  Returns the number of bytes read.
+  Bytes after the eol are available upon the next call to this function.
 
   The idea is to minimize the number of system calls per packet, and also to
   minimize timeouts.  This function is the inner loop of the protocol and must
-  be as efficient as possible.  The current strategy is to use myread().
+  be as efficient as possible.  The current strategy is to use myread(), a
+  macro to manage buffered (and generally nonblocking) reads.
 
   WARNING: This function calls parchk(), which is defined in another module.
   Normally, ckutio.c does not depend on code from any other module, but there
@@ -10494,10 +10689,10 @@ ttoc(c) char c;
   (a) to allow Kermit to be built without the automatic parity sensing feature
   (b) one of each type for ANSI C, one for non-ANSI.
 */
+#ifndef NOXFER
 
-static int csave = -1;
+static int pushedback = 0;
 
-#ifndef NOXFER
 int
 #ifdef PARSENSE
 #ifdef CK_ANSIC
@@ -10510,7 +10705,7 @@ ttinl(dest,max,timo,eol,start,turn) int max,timo,turn; CHAR *dest, eol, start;
 ttinl(CHAR *dest, int max,int timo, CHAR eol)
 #else
 ttinl(dest,max,timo,eol) int max,timo; CHAR *dest, eol;
-#endif /* __SDTC__ */
+#endif /* CK_ANSIC */
 #endif /* PARSENSE */
 /* ttinl */ {
 
@@ -10538,7 +10733,17 @@ ttinl(dest,max,timo,eol) int max,timo; CHAR *dest, eol;
 #endif /* STREAMING */
 
     if (ttyfd < 0) return(-3);          /* Not open. */
-
+/*
+  In February 2007 I fixed ttinl() to work better under the truly awful
+  conditions encountered by the AM-APEX oceanographic floats that gather
+  hurricane data and phone home using Iridium satellite modems, which under
+  certain conditions, can send two packets back to back after a long pause.
+  In this case the second packet would be ignored because the SOH was skipped
+  due to the ttflui() call.  But the reworked lookahead/pushback logic broke
+  Kermit transfers on encrypted connections.  This was fixed 12-13 August
+  2007.  All of this happened after 8.0.212 Dev.27 was released and before
+  Dev.28, so no harm done other than the delay.
+*/
     debug(F101,"ttinl max","",max);
     debug(F101,"ttinl timo","",timo);
 
@@ -10592,21 +10797,11 @@ ttinl(dest,max,timo,eol) int max,timo; CHAR *dest, eol;
 
        while (i < max-1) {
 #ifdef MYREAD
-           /* debug(F101,"ttinl i","",i); */
            errno = 0;
-           if (csave > -1) {
-               n = csave;
-               debug(F101,"ttinl unsaving","",n);
-           } else
-#ifdef COMMENT
-             if (xlocal && conchk() > 0) {
-                 /* Here we could catch keyboard interruptions. */
-                 /* But this would be VERY expensive. */
-                 /* We could also do it in myread() but it would be */
-                 /* expensive there too -- even if done with select()... */
-             }
-#endif /* COMMENT */
-             if ((n = myread()) < 0) { /* Timeout or i/o error? */
+           /* On encrypted connections myread returns encrypted bytes */
+           n = myread();
+           debug(F000,"TTINL myread char","",n);
+           if (n < 0) {        /* Timeout or i/o error? */
 #ifdef DEBUG
                if (deblog) {
                    debug(F101,"ttinl myread failure, n","",n);
@@ -10643,29 +10838,27 @@ ttinl(dest,max,timo,eol) int max,timo; CHAR *dest, eol;
            }
 
 #else /* not MYREAD (is this code used anywhere any more?) */
-
-           if (csave > -1)             /* Char saved from last time */
-             ch = csave;
-           else if ((n = read(fd, &ch, 1)) < 1)
+/*
+  The non-MYREAD code dates from the 1980s and was needed on certain platforms
+  where there were no nonblocking reads.  -fdc, 2007/02/22.
+*/
+           if ((n = read(fd, &n, 1)) < 1)
              break;                    /* Error - break out of while loop */
-           n = ch;
 
 #endif /* MYREAD */
 
            /* Get here with char in n */
 
 #ifdef CK_ENCRYPTION
-           /* If csave > -1 we already decrypted this character */
-           /* So don't decrypt it again */
-           if (TELOPT_U(TELOPT_ENCRYPTION) && csave == -1) {
+           if (TELOPT_U(TELOPT_ENCRYPTION) && !pushedback) {
                CHAR ch = n;
-               ck_tn_decrypt(&ch,1);
+               ck_tn_decrypt((char *)&ch,1);
                n = ch;
+               debug(F000,"TTINL decryp char","",n);
            }
+           pushedback = 0;
 #endif /* CK_ENCRYPTION */
 
-           csave = -1;                 /* Unflag that we unsaved a char */
-
 #ifdef TCPSOCKET
            if (n == IAC &&             /* Handle Telnet options */
                ((xlocal && netconn && IS_TELNET()) ||
@@ -10681,12 +10874,12 @@ ttinl(dest,max,timo,eol) int max,timo; CHAR *dest, eol;
                  continue;
            }                           /* Quoted IAC - keep going */
 #endif /* TCPSOCKET */
+
 #ifdef CKXXCHAR
            if (ignflag)
              if (dblt[(unsigned) n] & 1) /* Character to ignore? */
                continue;
 #endif /* CKXXCHAR */
-
 /*
   Use parity mask, rather than always stripping parity, to check for
   cancellation.  Otherwise, runs like \x03\x83\x03 in a packet could cancel
@@ -10708,27 +10901,41 @@ ttinl(dest,max,timo,eol) int max,timo; CHAR *dest, eol;
            } else ccn = 0;             /* No cancellation, reset counter, */
 
 #ifdef PARSENSE
-           if (flag == 0) {            /* Find the Start-Of-Packet. */
-               if ((n & sopmask) == start) { /* Got it */
-                   flag = 1;
-               } else {                /* Keep looking... */
-                   debug(F000,"ttinl skipping","",n);
-                   continue;
-               }
+/*
+  Restructured code allows for a new packet to appear somewhere in the
+  middle of a previous one.  -fdc, 24 Feb 2007.
+*/
+           if ((n & sopmask) == start) { /* Start of Packet */
+               debug(F101,"ttinl SOP i","",i);
+               flag = 1;               /* Flag that we are in a packet */
+               havelen = 0;            /* Invalidate previous length */
+               pktlen = -1;            /* (if any) in case we were */
+               lplen = 0;              /* alread processand a packet */
+               i = 0;                  /* and reset the dest buffer pointer */
+           }
+           if (flag == 0) {            /* No SOP yet... */
+               debug(F000,"ttinl skipping","",n);
+               continue;
            }
            dest[i++] = n & ttpmsk;
 /*
-  If we have not been instructed to wait for a turnaround character, we
-  can go by the packet length field.  If turn != 0, we must wait for the
-  end of line (eol) character before returning.  This is an egregious
-  violation of all principles of layering...
+  If we have not been instructed to wait for a turnaround character, we can go
+  by the packet length field.  If turn != 0, we must wait for the end of line
+  (eol) character before returning.  This is an egregious violation of all
+  principles of layering...  (Less egregious in C-Kermit 9.0, in which we go
+  by the length field but also look for the eol in case it arrives early,
+  e.g. if the length field was corrupted upwards.)
 */
            if (!havelen) {
                if (i == 2) {
+                   if ((dest[1] & 0x7f) < 32) /* Garbage in length field */
+                     return(-1);       /* fdc - 13 Apr 2010 */
                    pktlen = xunchar(dest[1] & 0x7f);
+                    if (pktlen > 94)   /* Rubout in length field */
+                     return(-1);       /* fdc - 13 Apr 2010 */
                    if (pktlen > 1) {
                        havelen = 1;
-                       debug(F101,"ttinl length","",pktlen);
+                       debug(F101,"ttinl pktlen value","",pktlen);
                    }
                } else if (i == 5 && pktlen == 0) {
                    lplen = xunchar(dest[4] & 0x7f);
@@ -10781,7 +10988,9 @@ ttinl(dest,max,timo,eol) int max,timo; CHAR *dest, eol;
     /* Check for end of packet */
 
            if (
+               ((n & ttpmsk) == eol)   /* Always break on the eol char */
 #ifdef PARSENSE
+                ||                     /* fdc - see notes of 13 Apr 2010 */
 /*
   Purely length-driven if SET HANDSHAKE NONE (i.e. turn == 0).
   This allows packet terminators and handshake characters to appear
@@ -10789,49 +10998,73 @@ ttinl(dest,max,timo,eol) int max,timo; CHAR *dest, eol;
 */
                (havelen && (i > pktlen+1) &&
                 (!turn || (turn && (n & 0x7f) == turn))) /* (turn, not eol) */
-#else /* !PARSENSE */
-/*
-  Built without PARSENSE, so just look for packet terminator.
-*/
-               ((n & 0x7f) == eol)
+
 #endif /* PARSENSE */
                ) {
+/*
+  Here we have either read the last byte of the packet based on its length
+  field, or else we have read the packet terminator (eol) or the half-duplex
+  line-turnaround char (turn).
+*/
 #ifndef PARSENSE
                debug(F101,"ttinl got eol","",eol); /* (or turn) */
                dest[i] = '\0';         /* Yes, terminate the string, */
                /* debug(F101,"ttinl i","",i); */
-#else
+
+#else  /* PARSENSE */
+
 #ifdef DEBUG
                if (deblog) {
-                   if ((n & 0x7f) != eol) {
+                   if ((n & ttpmsk) != eol) {
                        debug(F101,"ttinl EOP length","",pktlen);
-                       debug(F101,"ttinl i","",i);
+                       debug(F000,"ttinl EOP current char","",n);
+                       debug(F101,"ttinl EOP packet buf index","",i);
+                   } else debug(F101,"ttinl got eol","",eol);
+               }
+#endif /* DEBUG */
+
 #ifdef MYREAD
-#ifdef PARSENSE
 /*
-  We read a packet based on its length.  This leaves the EOP character still
-  unread, and so ttchk() will always return at least 1 because of this.  But
-  if we know it is there, we can safely get rid of it.  So...
-*/
-                       {
-                           int x;
-                           while (my_count > 0) {
-                               x = ttinc(0);
-                               /* Start of next packet */
-                               if (x == start) { /* Save for next time */
-                                   csave = (unsigned)((unsigned)x & 0xff);
-                                   debug(F000,"ttinl csaved","",x);
-                                   break;
-                               }
-                               debug(F000,"ttinl removed","",x);
-                           }
+  The packet was read based on its length.  This leaves the packet terminator
+  unread, and so ttchk() will always return at least 1 because of this,
+  possibly giving a false positive to the "is there another packet waiting?"
+  test.  But if we know the terminator (or any other interpacket junk) is
+  there, we can safely get rid of it.
+
+  NOTE: This code reworked to (a) execute even if the debug log isn't active;
+  and (b) actually work.  -fdc, 2007/02/22.  And again 2007/08/12-13 to also
+  work on encrypted connections.
+*/     
+               debug(F101,"TTINL my_count","",my_count);
+               if ((n & ttpmsk) != eol) { /* Not the packet terminator */
+                   int x;
+                   while (my_count > 0) {
+                       x = myread();      /* (was ttinc(0) */
+                       debug(F000,"TTINL lkread char","",x);
+#ifdef CK_ENCRYPTION
+                       if (TELOPT_U(TELOPT_ENCRYPTION)) {
+                           CHAR ch = x;
+                           ck_tn_decrypt((char *)&ch,1);
+                           x = ch;
+                           debug(F000,"TTINL lkdecr char","",x); 
                        }
-#endif /* PARSENSE */
+#endif /* CK_ENCRYPTION */
+                       /*
+                         Note: while it might seem more elegant to simply
+                         push back the encrypted byte, that desynchronizes
+                         the decryption stream; the flag is necessary so we
+                         don't try to decrypt the same byte twice.
+                       */
+                       if ((x & ttpmsk) == start) { /* Start of next packet */
+                           myunrd(x);  /* Push back the decrypted byte */
+                           pushedback = 1; /* And set flag */
+                           debug(F000,"TTINL lkpush char","",x);
+                           break;
+                       }
+                   }
+               }
 #endif /* MYREAD */
 
-                   } else debug(F101,"ttinl got eol","",eol); /* (or turn) */
-               }
-#endif /* DEBUG */
                dest[i] = '\0';         /* Terminate the string, */
                if (needpchk) {         /* Parity checked yet? */
                    if (ttprty == 0) {  /* No, check. */
@@ -10845,21 +11078,18 @@ ttinl(dest,max,timo,eol) int max,timo; CHAR *dest, eol;
                            debug(F110,"ttinl packet after ",dest,0);
                        } else ttprty = 0; /* Restore if parchk error */
                    }
-                   sopmask = ttprty;
+                   sopmask = ttpmsk;
                    needpchk = 0;
                }
 #endif /* PARSENSE */
-               if (timo) {             /* Turn off timer. */
-                   ttimoff();
-               }
-#ifdef COMMENT
-               debug(F011,"ttinl got", dest, (i < 60) ? i : -60);
-#else /* COMMENT */
-                hexdump("ttinl got",dest,i);
-#endif /* COMMENT */
+
+               if (timo)               /* Turn off timer if it was on */
+                 ttimoff();
+                ckhexdump("ttinl got",dest,i);
+
 #ifdef STREAMING
                /* ttinl() was called because there was non-packet */
-               /* data sitting int the channel.  Ignore it.       */
+               /* data sitting in the back channel.  Ignore it.   */
                if (streaming && sndtyp == 'D')
                  return(-1);
 #endif /* STREAMING */
@@ -10934,7 +11164,7 @@ ttinc(timo) int timo; {
        /* debug(F101,"ttinc u_encrypt","",TELOPT_U(TELOPT_ENCRYPTION)); */
        if (TELOPT_U(TELOPT_ENCRYPTION) && n >= 0) {
            ch = n;
-           ck_tn_decrypt(&ch,1);
+           ck_tn_decrypt((char *)&ch,1);
            n = ch;
        }
 #endif /* CK_ENCRYPTION */
@@ -11009,7 +11239,7 @@ ttinc(timo) int timo; {
 
 #ifdef CK_ENCRYPTION
            if (TELOPT_U(TELOPT_ENCRYPTION) && n >= 0) {
-               ck_tn_decrypt(&ch,1);
+               ck_tn_decrypt((char *)&ch,1);
            }
 #endif /* CK_ENCRYPTION */
            if (n >= 0)
@@ -11927,7 +12157,7 @@ concb(char esc)
 concb(esc) char esc;
 #endif /* CK_ANSIC */
 /* concb */ {
-    int x;
+    int x, y = 0;
     debug(F101,"concb constate","",constate);
     debug(F101,"concb cgmf","",cgmf);
     debug(F101,"concb backgrd","",backgrd);
@@ -12070,23 +12300,9 @@ concb(esc) char esc;
 #ifdef COHERENT
 #undef SVORPOSIX
 #endif /* COHERENT */
+
     debug(F101,"concb x","",x);
     debug(F101,"concb errno","",errno);
-#ifdef NONOSETBUF
-    if (x > -1) {
-       setbuf(stdout,NULL);    /* Make console unbuffered. */
-       debug(F100,"concb setbuf A","",0);
-    }
-#else
-#ifndef aegis
-#ifndef NOSETBUF
-    if (x > -1) {
-       setbuf(stdout,NULL);    /* Make console unbuffered. */
-       debug(F100,"concb setbuf B","",0);
-    }
-#endif /* NOSETBUF */
-#endif /* aegis */
-#endif /* NONOSETBUF */
 
 #ifdef  V7
 #ifndef MINIX
@@ -12414,7 +12630,7 @@ conol(s) char *s; {
                nxpacket = 0;
            }
            len = len > 10240 ? len : 10240;
-           xpacket = (char *)malloc(len);
+           xpacket = (CHAR *)malloc(len);
            if (!xpacket) {
                fprintf(stderr,"ttol malloc failure\n");
                return(-1);
@@ -12422,7 +12638,7 @@ conol(s) char *s; {
              nxpacket = len;
        }
        memcpy(xpacket,s,len);
-       s = xpacket;
+       s = (char *)xpacket;
        ck_tn_encrypt(s,len);
     }
 #endif /* CK_ENCRYPTION */
@@ -12482,7 +12698,7 @@ conoll(s) char *s; {
 #ifdef IKSD
 #ifdef CK_ENCRYPTION
     if (inserver && TELOPT_ME(TELOPT_ENCRYPTION))
-      ck_tn_encrypt(buf,2);
+      ck_tn_encrypt((char *)buf,2);
 #endif /* CK_ENCRYPTION */
 #endif /* IKSD */
 
@@ -12594,7 +12810,7 @@ coninc(timo) int timo; {
 #ifdef CK_ENCRYPTION
                 debug(F100,"coninc decrypt 1","",0);
                 if (inserver && !local && TELOPT_U(TELOPT_ENCRYPTION))
-                 ck_tn_decrypt(&ch,1);
+                 ck_tn_decrypt((char *)&ch,1);
 #endif /* CK_ENCRYPTION */
 #endif /* IKSD */
                return((unsigned)(ch & 0xff)); /* return the character. */
@@ -12678,7 +12894,7 @@ coninc(timo) int timo; {
 #ifdef CK_ENCRYPTION
         debug(F100,"coninc decrypt 2","",0);
         if (inserver && !local && TELOPT_U(TELOPT_ENCRYPTION))
-         ck_tn_decrypt(&ch,1);
+         ck_tn_decrypt((char *)&ch,1);
 #endif /* CK_ENCRYPTION */
 #endif /* IKSD */
        return((unsigned)(ch & 0xff));  /* Return it. */
@@ -13395,15 +13611,21 @@ psuspend(flag) int flag; {
 #ifndef PS2AIX10
 #ifndef sequent
 #ifndef HPUX9
+#ifndef HPUX10
 #ifndef COHERENT
 #ifndef NOGETID_PROTOS
-extern UID_T getuid(), geteuid(), getreuid();
-extern GID_T getgid(), getegid(), getregid();
+_PROTOTYP( UID_T getuid, (void) );
+_PROTOTYP( UID_T geteuid, (void) );
+_PROTOTYP( UID_T getreuid, (void) );
+_PROTOTYP( UID_T getgid, (void) );
+_PROTOTYP( UID_T getegid, (void) );
+_PROTOTYP( UID_T getregid, (void) );
 #endif /* NOGETID_PROTOS */
 #else
-extern UID_T getreuid();
-extern GID_T getregid();
+_PROTOTYP( UID_T getreuid, (void) );
+_PROTOTYP( UID_T getregid, (void) );
 #endif /* COHERENT */
+#endif /* HPUX10 */
 #endif /* HPUX9 */
 #endif /* sequent */
 #endif /* PS2AIX10 */
@@ -13509,7 +13731,7 @@ int
 priv_ini() {
     int err = 0;
 
-#ifndef HAVE_BAUDBOY
+#ifndef HAVE_LOCKDEV
 
     /* Save real ID:s. */
     realuid = getuid();
@@ -13590,7 +13812,7 @@ priv_ini() {
        err &= ~1;                      /* System V R0 does not save UID */
 #endif /* ATT7300 */
     }
-#endif /* HAVE_BAUDBOY */
+#endif /* HAVE_LOCKDEV */
     return(err);
 }
 
@@ -13668,7 +13890,7 @@ priv_ini() {
  */
 int
 priv_on() {
-#ifndef HAVE_BAUDBOY
+#ifndef HAVE_LOCKDEV
     if (privgid != (GID_T) -1)
       if (switchgid(realgid,privgid))
         return(2);
@@ -13679,7 +13901,7 @@ priv_on() {
            switchgid(privgid,realgid);
          return(1);
       }
-#endif /* HAVE_BAUDBOY */
+#endif /* HAVE_LOCKDEV */
     return(0);
 }
 
@@ -13695,7 +13917,7 @@ priv_on() {
 int
 priv_off() {
     int err = 0;
-#ifndef HAVE_BAUDBOY
+#ifndef HAVE_LOCKDEV
     if (privuid != (UID_T) -1)
        if (switchuid(privuid,realuid))
          err |= 1;
@@ -13703,7 +13925,7 @@ priv_off() {
     if (privgid != (GID_T) -1)
        if (switchgid(privgid,realgid))
        err |= 2;
-#endif /* HAVE_BAUDBOY */
+#endif /* HAVE_LOCKDEV */
     return(err);
 }
 
@@ -13719,7 +13941,7 @@ priv_off() {
  */
 int
 priv_can() {
-#ifndef HAVE_BAUDBOY
+#ifndef HAVE_LOCKDEV
 #ifdef SETREUID
     int err = 0;
     if (privuid != (UID_T) -1)
@@ -13759,7 +13981,7 @@ priv_can() {
 #endif /* SETREUID */
 #else
     return(0);
-#endif /* HAVE_BAUDBOY */
+#endif /* HAVE_LOCKDEV */
 }
 
 /* P R I V _ O P N  --  For opening protected files or devices. */
@@ -13820,9 +14042,1279 @@ ttimoff() {                          /* Turn off any timer interrupts */
     }
 }
 
-/* T T R U N C M D  --  Redirect an external command over the connection. */
+
+int
+tt_is_secure() {         /* Tells whether the current connection is secure */
+
+    if (ttyfd == -1)
+      return(0);
+
+    if (0
+#ifdef SSHBUILTIN
+       || IS_SSH()
+#endif /* SSHBUILTIN */
+#ifdef CK_ENCRYPTION
+       || ck_tn_encrypting() && ck_tn_decrypting()
+#endif /* CK_ENCRYPTION */
+#ifdef CK_SSL
+       || tls_active_flag || ssl_active_flag
+#endif /* CK_SSL */
+#ifdef RLOGCODE
+#ifdef CK_KERBEROS
+#ifdef CK_ENCRYPTION
+       || ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN
+#endif /* CK_ENCRYPTION */
+#endif /* CK_KERBEROS */
+#endif /* RLOGCODE */
+       )
+      return(1);
+    return(0);
+}
 
 #ifdef CK_REDIR
+  
+/* External protocol handler parameters from ckuus3.c */
+extern int exp_handler, exp_stderr, exp_timo;
+
+#ifdef SELECT
+#ifdef NETPTY
+
+/* The right size is 24576 */
+
+#ifndef PTY_PBUF_SIZE                  /* Size of buffer to read from pty */
+#define PTY_PBUF_SIZE 24576            /* and write to net. */
+#endif /* PTY_PBUF_SIZE */
+
+#ifndef PTY_TBUF_SIZE                  /* Size of buffer to read from net */
+#define PTY_TBUF_SIZE 24576            /* and write to pty. */
+#endif /* PTY_TBUF_SIZE */
+
+#ifdef O_NDELAY                                /* Whether to use nonblocking */
+#ifndef PTY_NO_NDELAY                  /* reads on the pseudoterminal */
+#ifndef PTY_USE_NDELAY
+#define PTY_USE_NDELAY
+#endif /* PTY_USE_NDELAY */
+#endif /* PTY_NO_NDELAY */
+#endif /* O_NDELAY */
+
+#ifndef HAVE_OPENPTY
+#ifndef USE_CKUPTY_C
+#define USE_CKUPTY_C
+#endif /* USE_CKUPTY_C */
+#endif /* HAVE_OPENPTY */
+
+VOID
+pty_make_raw(fd) int fd; {
+    int x = -23, i;
+
+#ifdef BSD44ORPOSIX                    /* POSIX */
+    struct termios tp;
+#else
+#ifdef ATTSV                           /* AT&T UNIX */
+#ifdef CK_ANSIC
+    struct termio tp = {0};
+#else
+    struct termio tp;
+#endif /* CK_ANSIC */
+#else
+    struct sgttyb tp;                  /* Traditional */
+#endif /* ATTSV */
+#endif /* BSD44ORPOSIX */
+
+    debug(F101,"pty_make_raw fd","",fd);
+    errno = 0;
+
+#ifdef BSD44ORPOSIX                    /* POSIX */
+    x = tcgetattr(fd,&tp);
+    debug(F101,"pty_make_raw tcgetattr","",x);
+#else
+#ifdef ATTSV                           /* AT&T UNIX */
+    x = ioctl(fd,TCGETA,&tp);
+    debug(F101,"pty_make_raw TCGETA ioctl","",x);
+#else
+    x = gtty(fd,&tp);
+    debug(F101,"pty_make_raw ttty","",x);
+#endif /* ATTSV */
+#endif /* BSD44ORPOSIX */
+    debug(F101,"pty_make_raw GET errno","",errno);
+
+#ifdef USE_CFMAKERAW
+    errno = 0;
+    cfmakeraw(&tp);
+    debug(F101,"pty_make_raw cfmakeraw errno","",errno);
+#else  /* USE_CFMAKERAW */
+
+#ifdef COMMENT
+
+/* This very simple version recommended by Serg Iakolev doesn't work */
+
+    tp.c_lflag &= ~(ECHO|ICANON|IEXTEN|ISIG);
+    tp.c_iflag &= ~(BRKINT|ICRNL|INPCK|ISTRIP|IXON);
+    tp.c_cflag &= ~(CSIZE|PARENB);
+    tp.c_cflag |= CS8;
+    tp.c_oflag &= ~(OPOST);
+    tp.c_cc[VMIN] = 1;
+    tp.c_cc[VTIME] = 0;
+
+    debug(F101,"pty_make_raw 1 c_cc[] NCCS","",NCCS);
+    debug(F101,"pty_make_raw 1 iflags","",tp.c_iflag);
+    debug(F101,"pty_make_raw 1 oflags","",tp.c_oflag);
+    debug(F101,"pty_make_raw 1 lflags","",tp.c_lflag);
+    debug(F101,"pty_make_raw 1 cflags","",tp.c_cflag);
+
+#else
+#ifdef COMMENT
+/*
+  In this version we unset everything and then set only the
+  bits we know we need.
+*/
+    /* iflags */
+    tp.c_iflag = 0L;
+    tp.c_iflag |= IGNBRK;
+#ifdef IMAXBEL
+    tp.c_iflag |= IMAXBEL;
+#endif /* IMAXBEL */
+
+    /* oflags */
+    tp.c_oflag = 0L;
+
+    /* lflags */
+    tp.c_lflag = 0L;
+#ifdef NOKERNINFO
+    tp.c_lflag |= NOKERNINFO;
+#endif /* NOKERNINFO */
+
+    /* cflags */
+    tp.c_cflag = 0L;
+    tp.c_cflag |= CS8|CREAD;
+
+    for (i = 0; i < NCCS; i++) {       /* No special characters */
+       tp.c_cc[i] = 0;
+    }
+#ifdef VMIN
+    tp.c_cc[VMIN] = 1;                 /* But always wait for input */
+#endif /* VMIN */
+    debug(F101,"pty_make_raw 2 c_cc[] NCCS","",NCCS);
+    debug(F101,"pty_make_raw 2 iflags","",tp.c_iflag);
+    debug(F101,"pty_make_raw 2 oflags","",tp.c_oflag);
+    debug(F101,"pty_make_raw 2 lflags","",tp.c_lflag);
+    debug(F101,"pty_make_raw 2 cflags","",tp.c_cflag);
+
+#else  /* COMMENT */
+/*
+  In this version we set or unset every single flag explicitly.  It works a
+  bit better than the simple version just above, but it's still far from
+  adequate.
+*/
+    /* iflags */
+    tp.c_iflag &= ~(PARMRK|ISTRIP|BRKINT|INLCR|IGNCR|ICRNL);
+    tp.c_iflag &= ~(INPCK|IGNPAR|IXANY|IXON|IXOFF);
+    tp.c_iflag |= IGNBRK;
+#ifdef IMAXBEL
+#ifdef COMMENT
+    tp.c_iflag |= IMAXBEL;
+#else
+    tp.c_iflag &= ~IMAXBEL;
+#endif /* COMMENT */
+#endif /* IMAXBEL */
+#ifdef IUCLC
+    tp.c_iflag &= ~IUCLC;
+#endif /* IUCLC */
+
+    /* oflags */
+#ifdef BSDLY
+    tp.c_oflag &= ~BSDLY;
+#endif /* BSDLY */
+#ifdef CRDLY
+    tp.c_oflag &= ~CRDLY;
+#endif /* CRDLY */
+#ifdef FFDLY
+    tp.c_oflag &= ~FFDLY;
+#endif /* FFDLY */
+#ifdef NLDLY
+    tp.c_oflag &= ~NLDLY;
+#endif /* NLDLY */
+#ifdef TABDLY
+    tp.c_oflag &= ~TABDLY;
+#endif /* TABDLY */
+#ifdef VTDLY
+    tp.c_oflag &= ~VTDLY;
+#endif /* VTDLY */
+#ifdef OFDEL
+    tp.c_oflag &= ~OFDEL;
+#endif /* OFDEL */
+#ifdef OFILL
+    tp.c_oflag &= ~OFILL;
+#endif /* OFILL */
+#ifdef OLCUC
+    tp.c_oflag &= ~OLCUC;
+#endif /* OLCUC */
+#ifdef CMSPAR
+    tp.c_oflag &= ~CMSPAR;
+#endif /* CMSPAR */
+    tp.c_oflag &= ~OPOST;
+#ifdef OXTABS
+    tp.c_oflag &= ~OXTABS;
+#endif /* OXTABS */
+#ifdef COMMENT
+#ifdef ONOCR
+    tp.c_oflag &= ~ONOCR;              /* Maybe should be |=? */
+    tp.c_oflag |= ONOCR;               /* makes no difference either way */
+#endif /* ONOCR */
+#endif /* COMMENT */
+#ifdef ONOEOT
+    tp.c_oflag &= ~ONOEOT;
+#endif /* ONOEOT */
+#ifdef ONLRET
+    tp.c_oflag &= ~ONLRET;
+#endif /* ONLRET */
+#ifdef ONLCR
+    tp.c_oflag &= ~ONLCR;
+#endif /* ONLCR */
+#ifdef OCRNL
+    tp.c_oflag &= ~OCRNL;
+#endif /* OCRNL */
+
+    /* lflags */
+    tp.c_lflag &= ~ECHO;
+#ifdef ECHOE
+    tp.c_lflag &= ~ECHOE;
+#endif /* ECHOE */
+#ifdef ECHONL
+    tp.c_lflag &= ~ECHONL;
+#endif /* ECHONL */
+#ifdef ECHOPRT
+    tp.c_lflag &= ~ECHOPRT;
+#endif /* ECHOPRT */
+#ifdef ECHOKE
+    tp.c_lflag &= ~ECHOKE;
+#endif /* ECHOKE */
+#ifdef ECHOCTL
+    tp.c_lflag &= ~ECHOCTL;
+#endif /* ECHOCTL */
+#ifdef XCASE
+    tp.c_lflag &= ~XCASE;
+#endif /* XCASE */
+#ifdef ALTWERASE
+    tp.c_lflag &= ~ALTWERASE;
+#endif /* ALTWERASE */
+#ifdef EXTPROC
+    tp.c_lflag &= ~(ICANON|ISIG|IEXTEN|TOSTOP|FLUSHO|PENDIN|EXTPROC);
+#else
+    tp.c_lflag &= ~(ICANON|ISIG|IEXTEN|TOSTOP|FLUSHO|PENDIN);
+#endif /* EXTPROC */
+#ifdef NOKERNINFO
+    tp.c_lflag |= NOKERNINFO;
+#endif /* NOKERNINFO */
+#ifndef COMMENT
+    tp.c_lflag &= ~NOFLSH;             /* TRY IT THE OTHER WAY? */
+#else
+    tp.c_lflag |= NOFLSH;              /* No, this way is worse */
+#endif /* COMMENT */
+
+    /* cflags */
+    tp.c_cflag &= ~(CSIZE|PARENB|PARODD);
+    tp.c_cflag |= CS8|CREAD;
+
+#ifdef MDMBUF
+    tp.c_cflag &= ~(MDMBUF);
+#else
+#ifdef CCAR_OFLOW
+    tp.c_cflag &= ~(CCAR_OFLOW);       /* two names for the same thing */
+#endif /* CCAR_OFLOW */
+#endif /* MDMBUF */
+
+#ifdef CCTS_OFLOW
+    tp.c_cflag &= ~(CCTS_OFLOW);
+#endif /* CCTS_OFLOW */
+#ifdef CDSR_OFLOW
+    tp.c_cflag &= ~(CDSR_OFLOW);
+#endif /* CDSR_OFLOW */
+#ifdef CDTR_IFLOW
+    tp.c_cflag &= ~(CDTR_IFLOW);
+#endif /* CDTR_IFLOW */
+#ifdef CRTS_IFLOW
+    tp.c_cflag &= ~(CRTS_IFLOW);
+#endif /* CRTS_IFLOW */
+#ifdef CRTSXOFF
+    tp.c_cflag &= ~(CRTSXOFF);
+#endif /* CRTSXOFF */
+#ifdef CRTSCTS
+    tp.c_cflag &= ~(CRTSCTS);
+#endif /* CRTSCTS */
+#ifdef CLOCAL
+    tp.c_cflag &= ~(CLOCAL);
+#endif /* CLOCAL */
+#ifdef CSTOPB
+    tp.c_cflag &= ~(CSTOPB);
+#endif /* CSTOPB */
+#ifdef HUPCL
+    tp.c_cflag &= ~(HUPCL);
+#endif /* HUPCL */
+
+    for (i = 0; i < NCCS; i++) {       /* No special characters */
+       tp.c_cc[i] = 0;
+    }
+#ifdef VMIN
+    tp.c_cc[VMIN] = 1;                 /* But always wait for input */
+#endif /* VMIN */
+    debug(F101,"pty_make_raw 3 c_cc[] NCCS","",NCCS);
+    debug(F101,"pty_make_raw 3 iflags","",tp.c_iflag);
+    debug(F101,"pty_make_raw 3 oflags","",tp.c_oflag);
+    debug(F101,"pty_make_raw 3 lflags","",tp.c_lflag);
+    debug(F101,"pty_make_raw 3 cflags","",tp.c_cflag);
+#endif /* COMMENT */
+#endif /* COMMENT */
+
+    errno = 0;
+#ifdef BSD44ORPOSIX                    /* POSIX */
+    x = tcsetattr(fd,TCSANOW,&tp);
+    debug(F101,"pty_make_raw tcsetattr","",x);
+#else
+#ifdef ATTSV                           /* AT&T UNIX */
+    x = ioctl(fd,TCSETA,&tp);
+    debug(F101,"pty_make_raw ioctl","",x);
+#else
+    x = stty(fd,&tp);                  /* Traditional */
+    debug(F101,"pty_make_raw stty","",x);
+#endif /* ATTSV */
+#endif /* BSD44ORPOSIX */
+    debug(F101,"pty_make_raw errno","",errno);
+
+#endif /* __NetBSD__ */
+}
+
+static int
+pty_chk(fd) int fd; {
+    int x, n = 0;
+    errno = 0;
+#ifdef FIONREAD
+    x = ioctl(fd, FIONREAD, &n);       /* BSD and most others */
+    ckmakmsg(msgbuf,500,
+            "pty_chk ioctl FIONREAD errno=",
+            ckitoa(errno),
+            " count=",
+            ckitoa(n));
+    debug(F100,msgbuf,"",0);
+#else
+    n = rdchk(fd);
+    debug(F101,"pty_chk rdchk","",n);
+#ifdef RDCHK
+#endif /* RDCHK */
+#endif /* FIONREAD */
+    return((n > -1) ? n : 0);
+}
+
+static int
+pty_get_status(fd,pid) int fd; PID_T pid; {
+    int x, status = -1;
+    PID_T w;
+
+    debug(F101,"pty_get_status fd","",fd);
+    debug(F101,"pty_get_status pid","",pid);
+
+    if (pexitstat > -1)
+      return(pexitstat);
+
+#ifdef COMMENT
+    /* Not only unnecessary but harmful */
+    errno = 0;
+    x = kill(pty_fork_pid,0);
+    debug(F101,"pty_get_status kill value","",x);
+    debug(F101,"pty_get_status kill errno","",errno);
+    if (x > -1 && errno != ESRCH)
+      return(-1);                      /* Fork still there */
+    /* Fork seems to be gone */
+#endif /* COMMENT */
+
+    errno = 0;
+    x = waitpid(pty_fork_pid,&status,WNOHANG);
+    debug(F111,"pty_get_status waitpid",ckitoa(errno),x);
+    if (x <= 0 && errno == 0) {
+       debug(F101,"pty_get_status waitpid return","",-1);
+       return(-1);
+    }
+    if (x > 0) {
+       if (x != pty_fork_pid)
+         debug(F101,
+               "pty_get_status waitpid pid doesn't match","",pty_fork_pid); 
+       debug(F101,"pty_get_status waitpid status","",status);
+       debug(F101,"pty_get_status waitpid errno","",errno);
+       if (WIFEXITED(status)) {
+           debug(F100,"pty_get_status WIFEXITED","",0);
+           status = WEXITSTATUS(status);
+           debug(F101,"pty_get_status fork exit status","",status);
+#ifdef COMMENT
+           end_pty();
+#endif /* COMMENT */
+           close(fd);
+           pexitstat = status;
+       } else {
+           debug(F100,"pty_get_status waitpid unexpected status","",0);
+       }
+    }
+    debug(F101,"pty_get_status return status","",status);
+    return(status);
+}
+
+/* t t p t y c m d  --  Run command on pty and forward to net */
+
+/*
+  Needed for running external protocols on secure connections.
+  For example, if C-Kermit has made an SSL/TLS or Kerberos Telnet
+  connection, and then needs to transfer a file with Zmodem, which is
+  an external program, this routine reads Zmodem's output, encrypts it,
+  and then forwards it out the connection, and reads the encrypted data
+  stream coming in from the connection, decrypts it, and forwards it to
+  Zmodem.
+
+  Works like a TCP/IP port forwarder except one end is a pty rather
+  than a socket, which introduces some complications:
+
+   . On most platforms, select() always indicates the output side of
+     the pty has characters waiting to be read, even when it doesn't,
+     even when the pty process has already exited.
+
+   . Nonblocking reads must be used on the pty, because there is no
+     way on certain platforms (e.g. NetBSD) to find out how many characters
+     are available to be read (the FIONREAD ioctl always says 0).  The code
+     also allows for blocking reads (if O_NDELAY and O_NONBLOCK are not
+     defined, or if PTY_NO_NDELAY is defined), but on some platforms this can
+     result in single-byte reads and writes (NetBSD again).
+
+   . Testing for "EOF" on the pty is problematic.  select() never gives
+     any indication.  After the pty process has exited and the fork has
+     disappeared, read() can still return with 0 bytes read but without an
+     error (NetBSD); no known test on the pty file descriptor will indicate
+     that it is no longer valid.  The process ID of the pty fork can be
+     tested on some platforms (NetBSD, luckily) but not others (Solaris,
+     Linux).
+
+  On the network side, we use ttinc() and ttoc(), which, for network 
+  connections, handle any active security methods.
+
+  Call with s = command.
+  Returns 0 on failure, 1 on success.
+  fdc - December 2006 - August 2007.
+
+  NOTE: This code defaults to nonblocking reads if O_NDELAY or O_NONBLOCK are
+  defined in the header files, which should be true of every recent Unix
+  platform.  If this causes trouble somewhere, define PTY_NO_NDELAY, e.g. when
+  building C-Kermit:
+
+    touch ckutio.c
+    make platformname KFLAGS=-DPTY_NO_NODELAY
+*/
+static int have_pty = 0;               /* Do we have a pty? */
+
+static SIGTYP (*save_sigchld)() = NULL;        /* For catching SIGCHLD */
+
+static VOID
+sigchld_handler(sig) int sig; {
+    have_pty = 0;                      /* We don't have a pty */
+#ifdef DEBUG
+    if (save_sigchld) {
+       (VOID) signal(SIGCHLD,save_sigchld);
+       save_sigchld = NULL;
+    }
+    if (deblog) {
+       debug(F100,"**************","",0);
+       debug(F100,"SIGCHLD caught","",0);
+       debug(F100,"**************","",0);
+    }
+#endif /* DEBUG */
+}
+#define HAVE_IAC 1
+#define HAVE_CR  2
+
+int
+ttptycmd(s) char *s; {
+    CHAR tbuf[PTY_TBUF_SIZE];          /* Read from net, write to pty */
+    int tbuf_avail = 0;                        /* Pointers for tbuf */
+    int tbuf_written = 0;
+    static int in_state = 0;           /* For TELNET IAC and NVT in */
+    static int out_prev = 0;           /* Simpler scheme for out */
+
+    CHAR pbuf[PTY_PBUF_SIZE];          /* Read from pty, write to net */
+    CHAR dbuf[PTY_PBUF_SIZE + PTY_PBUF_SIZE + 1]; /* Double-size buffer */
+    int pbuf_avail = 0;                        /* Pointers for pbuf */
+    int pbuf_written = 0;
+
+    int ptyfd = -1;                    /* Pty file descriptor */
+    int have_net = 0;                  /* We have a network connection */
+    int pty_err = 0;                   /* Got error on pty */
+    int net_err = 0;                   /* Got error on net */
+    int status = -1;                   /* Pty process exit status */
+    int rc = 0;                                /* Our return code */
+
+    int x1 = 0, x2 = 0;                        /* Workers... */
+    int c, n, m, t, x;                 /* Workers */
+
+    long seconds_to_wait = 0L;         /* select() timeout */
+    struct timeval tv, *tv2;           /* For select() */
+#ifdef INTSELECT
+    int in, out, err;                  /* For select() */
+#else
+    fd_set in, out, err;
+#endif /* INTSELECT */
+    int nfds = 0;                      /* For select() */
+
+    int pset = 0, tset = 0, pnotset = 0, tnotset = 0; /* stats/debuggin only */
+    int read_net_bytes = 0;            /* Stats */
+    int write_net_bytes = 0;           /* Stats */
+    int read_pty_bytes = 0;            /* Stats */
+    int write_pty_bytes = 0;           /* Stats */
+    int is_tn = 0;                     /* TELNET protocol is active */
+
+    int masterfd = -1;
+    int slavefd = -1;
+#ifndef USE_CKUPTY_C
+    struct termios term;
+    struct winsize twin;
+    struct stringarray * q;
+    char ** args = NULL;
+#endif /* USE_CKUPTY_C */
+
+    in_state = 0;                      /* No previous character yet */
+
+    if (ttyfd == -1) {
+       printf("?Sorry, communication channel is not open\n");
+       return(0);
+    } else {
+       have_net = 1;
+    }
+    if (nopush) {
+       debug(F100,"ttptycmd fail: nopush","",0);
+       return(0);
+    }
+    if (!s) s = "";                    /* Defense de bogus arguments */
+    if (!*s) return(0);
+    pexitstat = -1;                    /* Fork process exit status */
+
+#ifdef TNCODE
+    is_tn = (xlocal && netconn && IS_TELNET()) || /* Telnet protocol active */
+           (!xlocal && sstelnet);
+#endif /* TNCODE */
+
+    debug(F110,"ttptycmd command",s,0);
+    debug(F101,"ttptycmd ttyfd","",ttyfd);
+    debug(F101,"ttptycmd is_tn","",is_tn);
+    debug(F101,"ttptycmd ckermit pid","",getpid());
+
+#ifdef USE_CKUPTY_C
+    /* Call ckupty.c module to get and set up the pty fork */
+    /* fc 1 == "run an external protocol" */
+    debug(F100,"ttptycmd using ckupty.c","",0);
+    if (do_pty(&ptyfd,s,1) < 0) {      /* Start the command on a pty */
+       debug(F100,"ttptycmd do_pty fails","",0);
+       return(0);
+    }
+    masterfd = ptyfd;
+    pty_master_fd = ptyfd;
+#ifdef COMMENT
+    slavefd = pty_slave_fd;            /* This is not visible to us */
+#endif /* COMMENT */
+    debug(F111,"ttptycmd ptyfd","USE_CKUPTY_C",ptyfd);
+    debug(F111,"ttptycmd masterfd","USE_CKUPTY_C",masterfd);
+    debug(F111,"ttptycmd fork pid","USE_CKUPTY_C",pty_fork_pid);
+#ifndef SOLARIS
+    /* "ioctl inappropriate on device" for pty master */
+    pty_make_raw(masterfd);
+#endif /* SOLARIS */
+
+#else /* USE_CKUPTY_C */
+
+    debug(F100,"ttptycmd OPENPTY","",0);
+    if (tcgetattr(0, &term) == -1) {   /* Get controlling terminal's modes */
+       perror("tcgetattr");
+       return(0);
+    }
+    if (ioctl(0, TIOCGWINSZ, (char *) &twin) == -1) { /* and window size */
+       perror("ioctl TIOCGWINSZ");
+       return(0);
+    }
+    if (openpty(&masterfd, &slavefd, NULL, NULL, NULL) == -1) {
+       debug(F101,"ttptycmd openpty failed errno","",errno);
+       perror("opentpy");
+       return(0);
+    }
+    debug(F101,"ttptycmd openpty masterfd","",masterfd);
+    debug(F101,"ttptycmd openpty slavefd","",slavefd);
+    pty_master_fd = masterfd;
+    pty_slave_fd = slavefd;
+    debug(F101,"ttptycmd openpty pty_master_fd","",pty_master_fd);
+
+    /* Put pty master in raw mode but let forked app control the slave */
+    pty_make_raw(masterfd);
+
+#ifdef COMMENT
+#ifdef TIOCREMOTE
+    /* TIOCREMOTE,0 = disable all termio processing */
+    x = ioctl(masterfd, TIOCREMOTE, 1);
+    debug(F111,"ttptycmd ioctl TIOCREMOTE",ckitoa(x),errno);
+#endif /* TIOCREMOTE */
+#ifdef TIOCTTY
+    /* TIOCTTY,0 = disable all termio processing */
+    x = ioctl(masterfd, TIOCTTY, 0);
+    debug(F111,"ttptycmd ioctl TIOCTTY",ckitoa(x),errno);
+#endif /* TIOCTTY */
+#endif /* COMMENT */
+
+    have_pty = 1;                      /* We have an open pty */
+    save_sigchld = signal(SIGCHLD, sigchld_handler); /* Catch fork quit */
+
+    pty_fork_pid = fork();             /* Make fork for external protocol */
+    debug(F101,"ttptycmd pty_fork_pid","",pty_fork_pid);
+    if (pty_fork_pid == -1) {
+       perror("fork");
+       return(0);
+    } else if (pty_fork_pid == 0) {    /* In new fork */
+       int x;
+       debug(F101,"ttptycmd new fork pid","",getpid());
+       close(masterfd);                /* Slave quarters no masters allowed */
+       x = setsid();
+       debug(F101,"ttptycmd new fork setsid","",x);
+       if (x == -1) {
+           perror("ttptycmd setsid");
+           exit(1);
+       }
+       signal(SIGINT,SIG_IGN);         /* Let upper fork catch this */
+       
+#ifdef COMMENT
+#ifdef TIOCSCTTY
+       /* Make pty the controlling terminal for the process */
+       /* THIS CAUSES AN INFINITE SIGWINCH INTERRUPT LOOP */
+       x = ioctl(slavefd, TIOCSCTTY, NULL);
+       debug(F101,"ttptycmd TIOCSCTTY","",x);
+#endif /* TIOCSCTTY */
+#endif /* COMMENT */
+
+       /* Initialize slave pty modes and size to those of our terminal */
+       if (tcsetattr(slavefd, TCSANOW, &term) == -1) {
+           perror("ttptycmd tcsetattr");
+           exit(1);
+       }
+       if (ioctl(slavefd, TIOCSWINSZ, &twin) == -1) {
+           perror("ttptycmd ioctl");
+           exit(1);
+       }
+#ifdef COMMENT
+#ifdef TIOCNOTTY
+       /* Disassociate this process from its terminal */
+       /* THIS HAS NO EFFECT */
+       x = ioctl(slavefd, TIOCNOTTY, NULL);
+       debug(F101,"ttptycmd TIOCNOTTY","",x);
+#endif /* TIOCNOTTY */
+#endif /* COMMENT */
+
+#ifdef COMMENT
+#ifdef SIGTTOU 
+       /* Ignore terminal output interrupts */
+       /* THIS HAS NO EFFECT */
+       debug(F100,"ttptycmd ignoring SIGTTOU","",0);
+       signal(SIGTTOU, SIG_IGN);
+#endif /* SIGTTOU */
+#ifdef SIGTSTP 
+       /* Ignore terminal output interrupts */
+       /* THIS HAS NO EFFECT */
+       debug(F100,"ttptycmd ignoring SIGTSTP","",0);
+       signal(SIGTSTP, SIG_IGN);
+#endif /* SIGTSTP */
+#endif /* COMMENT */
+
+       pty_make_raw(slavefd);          /* Put it in rawmode */
+
+       errno = 0;
+       if (dup2(slavefd, STDIN_FILENO) != STDIN_FILENO ||
+           dup2(slavefd, STDOUT_FILENO) != STDOUT_FILENO) {
+           debug(F101,"ttptycmd new fork dup2 error","",errno);
+           perror("ttptycmd dup2");
+           exit(1);
+       }
+       debug(F100,"ttptycmd new fork dup2 ok","",0);
+
+       /* Parse external protocol command line */
+       q = cksplit(1,0,s,NULL,"\\%[]&$+-/=*^_@!{}/<>|.#~'`:;?",7,0,0);
+       if (!q) {
+           debug(F100,"ttptycmd cksplit failed","",0);
+           exit(1);
+       } else {
+           int i, n;
+           debug(F100,"ttptycmd cksplit ok","",0);
+           n = q->a_size;
+           args = q->a_head + 1;
+           for (i = 0; i <= n; i++) {
+               if (!args[i]) {
+                   break;
+               } else {
+                   /* sometimes cksplit() doesn't terminate the list */
+                   if ((i == n) && args[i]) {
+                       if ((int)strlen(args[i]) == 0)
+                         makestr(&(args[i]),NULL);
+                   }
+               }
+           }       
+       }
+#ifdef COMMENT
+/*
+  Putting the slave pty in rawmode should not be necessary because the
+  external protocol program is supposed to do that itself.  Yet doing this
+  here cuts down on Zmodem binary-file transmission errors by 30-50% but
+  still doesn't eliminate them.
+*/
+       pty_make_raw(STDIN_FILENO);
+       pty_make_raw(STDOUT_FILENO);
+#endif /* COMMENT */
+
+       debug(F100,"ttptycmd execvp'ing external protocol","",0);
+       execvp(args[0],args);
+       perror("execvp failed");
+       debug(F101,"ttptycmd execvp failed","",errno);
+       close(slavefd);
+       exit(1);
+    } 
+    /* (there are better ways to do this...) */
+    msleep(1000);                /* Make parent wait for child to be ready */
+    ptyfd = masterfd;                  /* We talk to the master */
+
+#endif /* USE_CKUPTY_C */
+
+    debug(F101,"ttptycmd ptyfd","",ptyfd);
+    if (ptyfd < 0) {
+       printf("?Failure to get pty\n");
+       return(-9);
+    }
+    have_pty = 1;            /* We have an open pty or we wouldn't he here */
+
+    debug(F101,"ttptycmd PTY_PBUF_SIZE","",PTY_PBUF_SIZE);
+    debug(F101,"ttptycmd PTY_TBUF_SIZE","",PTY_TBUF_SIZE);
+
+#ifdef PTY_USE_NDELAY
+    /* 
+       NOTE: If select() and ioctl(ptyfd,FIONREAD,&n) return true indications
+       on the pty, we don't need nonblocking reads.  Performance of either
+       method seems to be about the same, so use whatever works.
+    */
+    errno = 0;
+    x = fcntl(ptyfd,F_SETFL,fcntl(ptyfd,F_GETFL, 0)|O_NDELAY);
+    ckmakmsg(msgbuf,500,
+            "ttptycmd set O_NDELAY errno=",
+            ckitoa(errno),
+            " fcntl=",
+            ckitoa(x));
+    debug(F100,msgbuf,"",0);
+#endif /* PTY_USE_NDELAY */
+
+#ifdef COMMENT
+/* Not necessary, the protocol module already did this */
+
+#ifdef USE_CFMAKERAW
+    if (tcgetattr(ttyfd, &term) > -1) {
+       cfmakeraw(&term);
+       debug(F101,"ttptycmd net cfmakeraw errno","",errno);
+       x tcsetattr(ttyfd, TCSANOW, &term);
+       debug(F101,"ttptycmd net tcsetattr","",x);
+       debug(F101,"ttptycmd net tcsetattr","",errno);
+    }
+#else
+    if (local)                         /* Put network connection in */
+      ttpkt(ttspeed,ttflow,ttprty);    /* "packet mode". */
+    else
+      conbin((char)escchr);            /* OR... pty_make_raw(0) */
+#endif /* USE_CFMAKERAW */
+#endif /* COMMENT */
+
+#ifdef TNCODE
+    if (is_tn) {
+      debug(F101,"<<< ttptycmd TELOPT_ME_BINARY","",TELOPT_ME(TELOPT_BINARY));
+      debug(F101,"<<< ttptycmd TELOPT_U_BINARY","",TELOPT_U(TELOPT_BINARY));
+    }
+#endif /* TNCODE */
+
+    debug(F101,"ttptycmd entering loop - seconds_to_wait","",seconds_to_wait);
+
+    while (have_pty || have_net) {
+       FD_ZERO(&in);                   /* Initialize select() structs */
+       FD_ZERO(&out);
+       FD_ZERO(&err);                  /* (not used because useless) */
+       nfds = -1;
+
+       debug(F101,"ttptycmd loop top have_pty","",have_pty);
+       debug(F101,"ttptycmd loop top have_net","",have_net);
+
+       /* Pty is open and we have room to read from it? */
+       if (have_pty && pbuf_avail < PTY_PBUF_SIZE) {
+           debug(F100,"ttptycmd FD_SET ptyfd in","",0);
+            FD_SET(ptyfd, &in);
+           nfds = ptyfd;
+        }
+       /* Network is open and we have room to read from it? */
+        if (have_net && have_pty && tbuf_avail < PTY_TBUF_SIZE) {
+           debug(F100,"ttptycmd FD_SET ttyfd in","",0);
+            FD_SET(ttyfd, &in);
+           if (ttyfd > nfds) nfds = ttyfd;
+        }
+       /* Pty is open and we have stuff to write to it? */
+        if (have_pty && tbuf_avail - tbuf_written > 0) {
+           debug(F100,"ttptycmd FD_SET ptyfd out","",0);
+            FD_SET (ptyfd, &out);
+           if (ptyfd > nfds) nfds = ptyfd;
+        }
+       /* Net is open and we have stuff to write to it? */
+       debug(F101,"ttptycmd pbuf_avail-pbuf_written","",
+             pbuf_avail - pbuf_written);
+        if (have_net && pbuf_avail - pbuf_written > 0) {
+           debug(F100,"ttptycmd FD_SET ttyfd out","",0);
+            FD_SET (ttyfd, &out);
+           if (ttyfd > nfds) nfds = ttyfd;
+        }
+       /* We don't use err because it's not really for errors, */
+       /* but for out of band data on the TCP socket, which, if it is */
+       /* to be handled at all, is handled in the tt*() routines */
+
+       nfds++;                         /* 0-based to 1-based */
+       debug(F101,"ttptycmd nfds","",nfds);
+       if (!nfds) {
+           debug(F100,"ttptycmd NO FDs set for select","",0);
+           if (have_pty) {
+               /* This is not right -- sleeping won't accomplish anything */
+               debug(F101,"ttptycmd msleep","",100);
+               msleep(100);        
+           } else {
+               debug(F100,"ttptycmd no pty - quitting loop","",0);
+               break;
+           }
+       }
+       errno = 0;
+
+       if (seconds_to_wait > 0L) {     /* Timeout in case nothing happens */
+           tv.tv_sec = seconds_to_wait; /* for a long time */
+           tv.tv_usec = 0L;            
+           tv2 = &tv;
+        } else {
+            tv2 = NULL;
+       }
+       x = select(nfds, &in, &out, NULL, tv2);
+       debug(F101,"ttptycmd select","",x);
+       if (x < 0) {
+           if (errno == EINTR)
+             continue;
+           debug(F101,"ttptycmd select error","",errno);
+           break;
+       }
+       if (x == 0) {
+           debug(F101,"ttptycmd +++ select timeout","",seconds_to_wait); 
+           if (have_pty) {
+               status = pty_get_status(ptyfd,pty_fork_pid);
+               debug(F101,"ttptycmd pty_get_status A","",status);
+               if (status > -1) pexitstat = status;
+               have_pty = 0;
+           }
+           break;
+       }
+       /* We want to handle any pending writes first to make room */
+       /* for new incoming. */
+
+       if (FD_ISSET(ttyfd, &out)) {    /* Can write to net? */
+           CHAR * s;
+           s = pbuf + pbuf_written;    /* Current spot for sending */
+#ifdef TNCODE
+           if (is_tn) {                /* ttol() doesn't double IACs */
+               CHAR c;                 /* Rewrite string with IACs doubled */
+               int i;
+               s = pbuf + pbuf_written; /* Source */
+               x = 0;                   /* Count */
+               for (i = 0; i < pbuf_avail - pbuf_written; i++) {
+                   c = s[i];           /* Next character */
+                   if (c == IAC) {     /* If it's IAC */
+                       dbuf[x++] = c;  /* put another one */
+                       debug(F000,">>> QUOTED IAC","",c);
+                   } else if (c != 0x0a && out_prev == 0x0d) { /* Bare CR */
+                       if (!TELOPT_ME(TELOPT_BINARY)) { /* NVT rule */
+                           c = 0x00;
+                           dbuf[x++] = c;
+                           debug(F000,">>> CR-NUL","",c);
+                       }                       
+                   }
+                   dbuf[x++] = c;      /* Copy and count it */
+                   debug(F000,">>> char",ckitoa(in_state),c);
+                   out_prev = c;
+               }
+               s = dbuf;               /* New source */
+           } else
+#endif /* TNCODE */
+             x = pbuf_avail - pbuf_written; /* How much to send */
+
+           debug(F101,"ttptycmd bytes to send","",x);
+           x = ttol(s, x);
+           debug(F101,">>> ttol","",x);
+           if (x < 0) {
+               net_err++;
+               debug(F111,"ttptycmd ttol error",ckitoa(x),errno);
+               x = 0;
+           }
+           write_net_bytes += x;
+           pbuf_written += x;
+       }
+       if (FD_ISSET(ptyfd, &out)) {    /* Can write to pty? */
+           debug(F100,"ttptycmd FD_ISSET ptyfd out","",0);
+           errno = 0;
+#ifndef COMMENT
+           x = write(ptyfd,tbuf + tbuf_written,tbuf_avail - tbuf_written);
+#else
+           /* Byte loop to rule out data overruns in the pty */
+           /* (it makes no difference) */
+           {
+               char *p = tbuf+tbuf_written;
+               int n = tbuf_avail - tbuf_written;
+               for (x = 0; x < n; x++) {
+                   msleep(10);
+                   if (write(ptyfd,&(p[x]),1) < 0)
+                     break;
+               }
+           }
+#endif /* COMMENT */
+           debug(F111,"ttptycmd ptyfd write",ckitoa(errno),x);
+           if (x > 0) {
+               tbuf_written += x;
+               write_pty_bytes += x;
+           } else {
+               x = 0;
+               pty_err++;
+               if (pexitstat < 0) {
+                   status = pty_get_status(ptyfd,pty_fork_pid);
+                   debug(F101,"ttptycmd pty_get_status B","",status);
+                   if (status > -1) pexitstat = status;
+                   have_pty = 0;
+               }
+               debug(F100,"ttptycmd +++ ptyfd write error","",0);
+           }
+       }
+       if (FD_ISSET(ttyfd, &in)) {     /* Can read from net? */
+           tset++;
+           debug(F100,"ttptycmd FD_ISSET ttyfd in","",0);
+           n = in_chk(1,ttyfd);
+           debug(F101,"ttptycmd in_chk(ttyfd)","",n); 
+           if (n < 0 || ttyfd == -1) {
+               debug(F101,"ttptycmd +++ ttyfd errno","",errno);
+               net_err++;
+           } else if (n > 0) {
+               if (n > PTY_TBUF_SIZE - tbuf_avail)
+                 n = PTY_TBUF_SIZE - tbuf_avail;
+               debug(F101,"ttptycmd net read size adjusted","",n); 
+               if (xlocal && netconn) {
+                   /*
+                     We have to use a byte loop here because ttxin()
+                     does not decrypt or, for that matter, handle Telnet.
+                   */
+                   int c;
+                   CHAR * p;
+                   p = tbuf + tbuf_avail;
+                   for (x = 0; x < n; x++) {
+                       if ((c = ttinc(0)) < 0)
+                         break;
+                       if (!is_tn) {   /* Not Telnet - keep all bytes */
+                           *p++ = (CHAR)c;
+                           debug(F000,"<<< char","",c);
+#ifdef TNCODE
+                       } else {        /* Telnet - must handle IAC and NVT */
+                           debug(F000,"<<< char",ckitoa(in_state),c);
+                           switch (c) {
+                             case 0x00: /* NUL */
+                               if (in_state == HAVE_CR) {
+                                   debug(F000,"<<< SKIP","",c);
+                               } else {
+                                   *p++ = c;
+                                   debug(F000,"<<< Keep","",c);
+                               }
+                               in_state = 0;
+                               break;
+                             case 0x0d: /* CR */
+                               if (!TELOPT_U(TELOPT_BINARY))
+                                 in_state = HAVE_CR;
+                               *p++ = c;
+                               debug(F000,"<<< Keep","",c);
+                               break;
+#ifdef COMMENT
+                             case 0x0f: /* Ctrl-O */
+                             case 0x16: /* Ctrl-V */
+                               *p++ = 0x16;
+                               *p++ = c;
+                               debug(F000,"<<< QUOT","",c);
+                               break;
+#endif /* COMMENT */
+                             case 0xff: /* IAC */
+                               if (in_state == HAVE_IAC) {
+                                   debug(F000,"<<< KEEP","",c);
+                                   *p++ = c;
+                                   in_state = 0;
+                               } else {
+                                   debug(F000,"<<< SKIP","",c);
+                                   in_state = HAVE_IAC;
+                               }
+                               break;
+                             default:  /* All others */
+                               if (in_state == HAVE_IAC) {
+#ifdef COMMENT
+/*
+  tn_doop() will consume an unknown number of bytes and we'll overshoot
+  the for-loop.  The only Telnet command I've ever seen arrive here is
+  a Data Mark, which comes when the remote protocol exits and the remote
+  job returns to its shell prompt.  On the assumption it's a 1-byte command,
+  we don't write out the IAC or the command, and we clear the state.  If
+  we called tn_doop() we'd have no way of knowing how many bytes it took
+  from the input stream.
+*/
+                                   int xx;
+                                   xx = tn_doop((CHAR)c,duplex,ttinc);
+                                   debug(F111,"<<< DOOP",ckctoa(c),xx);
+#else
+                                   debug(F101,"<<< DOOP","",c);
+#endif /* COMMENT */
+                                   in_state = 0;
+                               } else {
+                                   *p++ = c;
+                                   debug(F000,"<<< keep","",c);
+                                   in_state = 0;
+                               }
+                           }
+#endif /* TNCODE */
+                       }
+                   }
+                   ckmakmsg(msgbuf,500,
+                            "ttptycmd read net [ttinc loop] errno=",
+                            ckitoa(errno),
+                            " count=",
+                            ckitoa(x));
+                   debug(F100,msgbuf,"",0);
+               } else {
+                   x = ttxin(n,tbuf+tbuf_avail);
+                   debug(F101,"ttptycmd ttxin x","",x); 
+               }
+
+               if (x < 0) {
+                   debug(F101,"ttptycmd read net error","",x);
+                   net_err++;
+               }
+               tbuf_avail += x;
+               read_net_bytes += x;
+           }
+
+       } else
+         tnotset++;
+
+       if (FD_ISSET(ptyfd, &in)) {     /* Read from pty? */
+           pset++;
+           debug(F100,"ttptycmd FD_ISSET ptyfd in","",0);
+#ifdef PTY_USE_NDELAY
+           n = PTY_PBUF_SIZE;
+#else
+           /*
+             This does not work on nonblocking channels
+             on certain platforms such as NetBSD.
+           */
+           n = pty_chk(ptyfd);
+#endif /* PTY_USE_NDELAY */
+           debug(F101,"ttptycmd pty_chk() n","",n); 
+
+           if (n < 0)
+             n = 0;
+           if (n > 0) {
+               if (n > PTY_PBUF_SIZE - pbuf_avail)
+                 n = PTY_PBUF_SIZE - pbuf_avail;
+               debug(F101,"ttptycmd pty read size adjusted","",n); 
+               errno = 0;
+               x = read(ptyfd,pbuf+pbuf_avail,n);
+#ifdef DEBUG
+               if (deblog) {
+                   ckmakmsg(msgbuf,500,
+                            "ttptycmd read pty errno=",
+                            ckitoa(errno),
+                            " count=",
+                            ckitoa(x));
+                   debug(F100,msgbuf,"",0);
+               }
+#endif /* DEBUG */
+
+               if (x < 0 && errno == EAGAIN)
+                 x = 0;
+
+               if (x < 0) {            /* This works on Solaris and Linux */
+                   pty_err++;          /* but not NetBSD */
+                   debug(F100,"TERMINATION TEST A","",0);
+#ifdef COMMENT
+                   if (errno == EIO)
+                     rc = 1;
+#endif /* COMMENT */
+                   if (pexitstat < 0) {
+                       status = pty_get_status(ptyfd,pty_fork_pid);
+                       debug(F101,"ttptycmd pty_get_status C","",status);
+                       if (status > -1) pexitstat = status;
+                   }
+                   have_pty = 0;
+                   x = 0;
+               }
+               if (x == 0 && !pty_err) { /* This works on NetBSD but */
+                   debug(F100,"TERMINATION TEST B","",0);
+                   status = pexitstat > -1 ? pexitstat :
+                       pty_get_status(ptyfd,pty_fork_pid);
+                   debug(F101,"ttptycmd pty_get_status D","",status);
+                   if (status > -1) {
+                       pexitstat = status;
+                       pty_err++;
+                       have_pty = 0;
+                   } else {            /* Select() lied */
+                       pty_err = 0;    /* pty still there but has nothing */
+                       msleep(100);    /* sleep a bit */
+                   }
+                   x = 0;
+               } 
+               /* Hopefully the next two are no longer needed... */
+               if (!pty_err && (
+#ifndef PTY_USE_NDELAY
+                   x < 1 || errno
+#else
+                   errno != 0 && errno != EAGAIN
+#endif /* PTY_USE_NDELAY */
+                   )) {
+                   debug(F100,"TERMINATION TEST C","",0);
+                   pty_err++;
+                   debug(F101,"ttptycmd SET pty_err","",pty_err);
+                   if (errno == EIO)   /* errno == EIO is like EOF */
+                     rc = 1;
+                   if (x < 0)
+                     x = 0;
+               }
+#ifdef COMMENT
+#ifdef DEBUG
+               if (deblog) {
+                   pbuf[pbuf_avail + x] = '\0';
+                   debug(F111,"ttptycmd added to pty buffer",
+                         pbuf+pbuf_avail,x);
+               }
+#endif /* DEBUG */
+#endif /* COMMENT */
+               pbuf_avail += x;
+               read_pty_bytes += x;
+           } else {                    /* n == 0 with blocking reads */
+               debug(F100,
+                     "PTY READ RETURNED ZERO BYTES - SHOULD NOT HAPPEN",
+                     "",0);
+           }
+       } else
+         pnotset++;
+
+       /* If writes have caught up to reads, reset the buffers */
+
+       if (pbuf_written == pbuf_avail)
+         pbuf_written = pbuf_avail = 0;
+       if (tbuf_written == tbuf_avail)
+         tbuf_written = tbuf_avail = 0;
+
+       /* See if we can exit */
+
+       x1 = pbuf_avail - pbuf_written; 
+       x2 = tbuf_avail - tbuf_written;
+
+       debug(F101,"ttptycmd pty_err LOOP EXIT TEST pty_err","",pty_err);
+       debug(F101,"ttptycmd pty_err LOOP EXIT TEST x1 [write to net]","",x1);
+       debug(F101,"ttptycmd pty_err LOOP EXIT TEST x2 [write to pty]","",x2);
+       debug(F101,"ttptycmd pty_err LOOP EXIT TEST rc","",rc);
+       debug(F101,"ttptycmd pty_err LOOP EXIT TEST status","",status);
+       debug(F101,"ttptycmd pty_err LOOP EXIT TEST pexitstat","",pexitstat);
+
+       if (net_err) {                  /* Net error? */
+           debug(F101,"ttptycmd net_err LOOP EXIT TEST net_err","",net_err);
+           if (have_net) {
+               if (local) {
+                   ttclos(0);
+                   printf("?Connection closed\n");
+               }
+               have_net = 0;
+           }
+           debug(F101,"ttptycmd net_err LOOP EXIT TEST x1","",x1);
+           if (x1 == 0)
+             break;
+       }
+       if (pty_err) {                  /* Pty error? */
+           if (have_pty) {
+               if (pexitstat < 0) {            
+                   status = pty_get_status(ptyfd,pty_fork_pid);
+                   debug(F101,"ttptycmd pty_get_status E","",status);
+                   if (status > -1) pexitstat = status;
+               }
+               have_pty = 0;
+           }
+           if (x1 == 0 && x2 == 0) {   /* If buffers are caught up */
+               rc = 1;                 /* set preliminary return to success */
+               debug(F101,"ttptycmd pty_err LOOP EXIT TEST rc 2","",rc);
+               break;                  /* and exit the loop */
+           }
+       }
+    }
+    debug(F101,"ttptycmd +++ have_pty","",have_pty);
+    if (have_pty) {                    /* In case select() failed */
+#ifdef USE_CKUPTY_C
+       end_pty();
+       close(ptyfd);
+#else
+       close(slavefd);
+       close(masterfd);
+#endif /* USE_CKUPTY_C */
+    }
+    pty_master_fd = -1;
+    debug(F101,"ttptycmd +++ pexitstat","",pexitstat);
+    if (pexitstat < 0) {               /* Try one last time to get status */
+       status = pty_get_status(ptyfd,pty_fork_pid);
+       debug(F101,"ttptycmd pty_get_status F","",status);
+       if (status > -1) pexitstat = status;
+    }
+    debug(F101,"ttptycmd +++ final pexitstat","",pexitstat);
+    if (deblog) {                      /* Stats for debug log */
+       debug(F101,"ttptycmd +++ pset   ","",pset);
+       debug(F101,"ttptycmd +++ pnotset","",pnotset);
+       debug(F101,"ttptycmd +++ tset   ","",tset);
+       debug(F101,"ttptycmd +++ tnotset","",tnotset);
+
+       debug(F101,"ttptycmd +++  read_pty_bytes","",read_pty_bytes);
+       debug(F101,"ttptycmd +++ write_net_bytes","",write_net_bytes);
+       debug(F101,"ttptycmd +++  read_net_bytes","",read_net_bytes);
+       debug(F101,"ttptycmd +++ write_pty_bytes","",write_pty_bytes);
+    }
+/*
+  If we got the external protocol's exit status from waitpid(), we use that
+  to set our return code.  If not, we fall back on whatever rc was previously
+  set to, namely 1 (success) if the pty fork seemed to terminate, 0 otherwise.
+*/
+    if (save_sigchld) {                        /* Restore this if we changed it */
+       (VOID) signal(SIGCHLD,save_sigchld);
+       save_sigchld = NULL;
+    }
+    msleep(500);
+    x = kill(pty_fork_pid,SIGHUP);     /* In case it's still there */
+    pty_fork_pid = -1;
+    debug(F101,"ttptycmd fork kill SIGHUP","",x);
+    if (pexitstat > -1)
+      rc = (pexitstat == 0 ? 1 : 0);
+    debug(F101,"ttptycmd +++ rc","",rc);
+    if (!local) {                      /* If in remote mode */
+       conres();                       /* restore console to CBREAK mode */
+       concb((char)escchr);
+    }
+    return(rc);
+}
+#endif /* NETPTY */
+#endif /* SELECT */
+
+/* T T R U N C M D  --  Redirect an external command over the connection. */
+
+/*
+  TTRUNCMD is the routine that was originally used for running external
+  protocols.  It is very simple and works fine provided (a) the connection
+  is not encrypted, and (b) the external protocol uses standard i/o
+  (file descriptors 0 and 1) for file transfer.
+*/
+
 int
 ttruncmd(s) char *s; {
     PID_T pid;                         /* pid of lower fork */
@@ -13838,6 +15330,36 @@ ttruncmd(s) char *s; {
        debug(F100,"ttruncmd fail: nopush","",0);
        return(0);
     }
+
+#ifdef NETPTY
+/***************
+  It might also be necessary to use the pty routine for other reasons,
+  e.g. because the external program does not use stdio.
+*/
+#ifdef NETCONN
+/*
+  If we have a network connection we use a different routine because
+  (a) if the connection is encrypted, the mechanism used here can't deal
+  with it; and (b) it won't handle any network protocols either, e.g.
+  Telnet, Rlogin, K5 U-to-U, etc.  However, this routine works much
+  better (faster, more transparent) on serial connections and when
+  C-Kermit is in remote mode (i.e. is on the far end).
+*/
+    /* For testing always use this */
+    if (netconn)
+      return(ttptycmd(s));
+#endif /* NETCONN */
+
+/***************/
+#else  /* NETPTY */
+    if (tt_is_secure()) {
+       printf("?Sorry, \
+external protocols over secure connections not supported in this OS.\n"
+              );
+        return(0);
+    }
+#endif /* NETPTY */
+
     conres();                          /* Make console normal  */
     pexitstat = -4;
     if ((pid = fork()) == 0) {         /* Make a child fork */
@@ -13875,7 +15397,7 @@ ttruncmd(s) char *s; {
     concb((char)escchr);               /* Restore console to CBREAK mode */
     return(statusp == 0 ? 1 : 0);
 }
-#endif /* CK_REDIR */
+#endif /* CK_REDIR */
 
 struct tm *
 #ifdef CK_ANSIC
@@ -14186,7 +15708,11 @@ conprint(char *fmt, ...) {
 #ifdef CK_ANSIC
 #include <stdarg.h>
 #else /* CK_ANSIC */
+#ifdef __GNUC__
+#include <stdarg.h>
+#else
 #include <varargs.h>
+#endif /* __GNUC__ */
 #endif /* CK_ANSIC */
 #ifdef fprintf
 #undef fprintf
@@ -14471,8 +15997,11 @@ ckxperror(str) char * str;
 
 #ifdef MINIX2
 
-/* Minix doesn't have a gettimeofday call. We fake one here using time(2) */
+/* Minix doesn't have a gettimeofday call (but MINIX3 does).
+ * We fake one here using time(2)
+ */
 
+#ifndef MINIX3
 int
 gettimeofday(struct timeval *tp, struct timezone *tzp) {
     tp->tv_usec = 0L;                  /* Close enough for horseshoes */
@@ -14480,13 +16009,14 @@ gettimeofday(struct timeval *tp, struct timezone *tzp) {
       return(-1);
     return(0);
 }
+#endif /* MINIX3 */
 
-/* Minix does not support symbolic links. We implement a version of
-   readlink that always fails */
-
+#ifndef MINIX3
 int
 readlink(const char *path, void *buf, size_t bufsiz) {
     errno = ENOSYS;
     return(-1);
 }
+#endif /* MINIX3 */
+
 #endif /* MINIX2 */
diff --git a/ckututor.txt b/ckututor.txt
deleted file mode 100644 (file)
index 9448126..0000000
+++ /dev/null
@@ -1,1959 +0,0 @@
-
-C-KERMIT 8.0 UNIX MANUAL PAGE AND TUTORIAL
-
-     Frank da Cruz, Christine M. Gianone
-     [1]The Kermit Project, [2]Columbia University
-     
-   [ [3]PDF version ] [ [4]Nroff version ]
-   
-     This document is intended to give the beginner sufficient
-     information to make basic (if not advanced) use of C-Kermit 8.0.
-     Although it might be rather long for a Unix manual page (about 1600
-     lines), it's still far shorter than the C-Kermit manual, which
-     should be consulted for advanced topics such as customization,
-     character-sets, scripting, etc. We also attempt to provide a clear
-     structural overview of C-Kermit's many capabilities, functional
-     areas, states, and modes and their interrelation, that should be
-     helpful to beginners and veterans alike, as well as to those
-     upgrading to the new release. 
-     
-   Most recent update: 24 October 2002
-    ________________________________________________________________________
-  
-  CONTENTS
-     * [5]DESCRIPTION
-     * [6]SYNOPSIS
-     * [7]OPTIONS
-     * [8]COMMAND LANGUAGE
-     * [9]INITIALIZATION FILE
-     * [10]MODES OF OPERATION
-     * [11]MAKING CONNECTIONS
-     * [12]TRANSFERRING FILES WITH KERMIT
-     * [13]KERMIT CLIENT/SERVER CONNECTIONS
-     * [14]KERMIT'S BUILT-IN FTP AND HTTP CLIENTS
-     * [15]INTERNET KERMIT SERVICE
-     * [16]SECURITY
-     * [17]ALTERNATIVE COMMAND-LINE PERSONALITIES
-     * [18]LICENSE
-     * [19]OTHER TOPICS
-     * [20]DOCUMENTATION AND UPDATES
-     * [21]FILES
-     * [22]AUTHORS
-     _________________________________________________________________
-   
-   DESCRIPTION [ [23]Top ] [ [24]Contents ] [ [25]Next ]
-   
-   [26]C-Kermit is an all-purpose communications software package from
-   the [27]Kermit Project at [28]Columbia University that:
-   
-     * Is portable to many platforms, Unix and non-Unix alike.
-     * Can make both serial and network connections.
-     * Can conduct interactive terminal sessions over its connection.
-     * Can transfer text or binary files over the same connection.
-     * Can convert text-file character sets in terminal mode or file
-       transfer.
-     * Is customizable in every aspect of its operation.
-       
-   C-Kermit is a modem program, a Telnet client, an Rlogin client, an FTP
-   client, an HTTP client, and on selected platforms, also an X.25
-   client. It can make its own secure Internet connections using
-   IETF-approved security methods including Kerberos IV, Kerberos V,
-   SSL/TLS, and SRP and it can also make SSH (Secure Shell) connections
-   through your external SSH client application. It can be the far-end
-   file-transfer or client/server partner of your desktop Kermit client.
-   It can also accept incoming dialed and network connections. It can
-   even be installed as an Internet service on its own standard TCP
-   socket, 1649 [[29]RFC2839, [30]RFC2840].
-   
-   And perhaps most important, everything you can do "by hand"
-   (interactively) with C-Kermit, can be "scripted" (automated) using its
-   built-in cross-platform transport-independent script programming
-   language, which happens to be identical to its interactive command
-   language.
-   
-   This manual page offers an overview of C-Kermit 8.0 for Unix ("Unix"
-   is an operating system family that includes AIX, DG/UX, FreeBSD,
-   HP-UX, IRIX, Linux, Mac OS X, NetBSD, OpenBSD, Open Server, Open Unix,
-   QNX, Solaris, SunOS, System V R3, System V R4, Tru64 Unix, Unixware,
-   Xenix, and many others). For thorough coverage, please consult the
-   published C-Kermit manual and supplements (see [31]DOCUMENTATION
-   below). For further information about C-Kermit, Kermit software for
-   other platforms, and Kermit manuals, visit the Kermit Project website:
-   
-  [32]http://www.columbia.edu/kermit/
-
-   This is a longer-than-average manual page, and yet it barely scratches
-   the surface. Don't be daunted. C-Kermit is a large and complex
-   package, evolving over decades of practice and experience, but that
-   doesn't mean it's hard to learn or use. Its most commonly used
-   functions are explained here with pointers to additional information
-   elsewhere.
-   
-   [ [33]Kermit Home ] [ [34]C-Kermit Home ] [ [35]C-Kermit FAQ ]
-    ________________________________________________________________________
-  
-  SYNOPSIS [ [36]Top ] [ [37]Contents ] [ [38]Next ] [ [39]Previous ]
-  
-   Usage:  kermit [filename] [-x arg [-x arg]...[-yyy]..] [ {=,--,+} text
-   ] ]
-   Or:    kermit URL
-   
-     * -x is an option requiring an argument;
-     * -y is an option with no argument.
-       
-   If the first command-line argument is the name of a file,
-   interactive-mode commands are executed from the file. The '=' (or
-   "--") argument tells Kermit not to parse the remainder of the command
-   line, but to make the words following '=' available as \%1, \%2, ...
-   \%9. The "+" argument is like "=" but for use in "kerbang scripts"
-   (explained [40]below). A second command-line format allows the one and
-   only argument to be a [41]Telnet, FTP, HTTP, or IKSD URL.
-   
-   Order of execution:
-   
-    1. [42]The command file (if any).
-    2. [43]The initialization file, if any, unless suppressed with -Y.
-    3. [44]The customization file (if it is executed by the
-       initialization file).
-    4. [45]The command-line URL (if any, and if so, execution stops
-       here).
-    5. [46]Command-line options (if any).
-    6. [47]Interactive commands.
-       
-   Some command-line options can cause actions (such as -s to send a
-   file); others just set parameters. If any action options are included
-   on the command line, Kermit exits when finished unless also given the
-   -S ("stay") option. If no action options are given, no initialization
-   or command files contained an EXIT or QUIT command, and no fatal
-   errors occurred, Kermit issues its prompt and waits for you to type
-   commands.
-   
-     Bear in mind that C-Kermit can be built with selected features
-     disabled, and also that certain features are not available on all
-     platforms. For example, C-Kermit can't be built with TCP/IP support
-     on a platform that does not have TCP/IP header files and libraries
-     (and even if Kermit does include TCP/IP support, it can't be used
-     to make TCP/IP connections on a computer that does not have a
-     TCP/IP stack installed). If your version of C-Kermit lacks a
-     feature mentioned here, use its SHOW FEATURES command to see what
-     might have been excluded. 
-     
-   C-Kermit has three kinds of commands: regular single-letter
-   command-line options, extended-format command-line options, and
-   interactive commands.
-   
-   [ [48]Kermit Home ] [ [49]C-Kermit Home ] [ [50]C-Kermit FAQ ]
-    ________________________________________________________________________
-  
-  OPTIONS [ [51]Top ] [ [52]Contents ] [ [53]Next ] [ [54]Previous ]
-  
-   Like most Unix commands, C-Kermit can be be given options on the
-   command line. But C-Kermit also can be used interactively by giving it
-   [55]commands composed of words, which are more intuitive than cryptic
-   command-line options, and more flexible too. In other words, you don't
-   have to use C-Kermit's command-line options, but they are available if
-   you want to. (By the same token, you don't have to use its interactive
-   commands either -- you can use either or both in any combination.)
-   
-   C-Kermit is generally installed in the PATH as "kermit", and therefore
-   is invoked by typing the word "kermit" (lowercase) at the shell
-   prompt, and then pressing the Return or Enter key. If you wish to
-   include command-line options, put them after the word "kermit" but
-   before pressing Return or Enter, separated by spaces, for example:
-   
-  $ kermit -s ckermit.tar.gz
-
-   ('$' is the shell prompt; "kermit -s ckermit.tar.gz" is what you type,
-   followed by Return or Enter.)
-   
-   Here is a list of C-Kermit's single-letter command-line options, which
-   start with a single dash (-), in ASCII ("alphabetical") order.
-   Alphabetic case is significant (-A is not the same as -a). The Action?
-   column contains Y for action options and N for non-action options.
-   Option Action? Description
-   -0 N (digit zero) 100% transparent Connect state for "in-the-middle"
-   operation: 8 bits, no parity, no escape character, everything passes
-   through.
-   -8 N (digit eight) Connection is 8-bit clean (this is the default in
-   C-Kermit 8.0). Equivalent to the EIGHTBIT command, which in turn is a
-   shortcut for SET TERMINAL BYTESIZE 8, SET COMMAND BYTESIZE 8, SET
-   PARITY NONE.
-   -9 arg N (digit nine) Make a connection to an FTP server. Equivalent
-   to the FTP OPEN command.
-   Argument: IP-address-or-hostname[:optional-TCP-port].
-   NOTE: C-Kermit also has a separate FTP command-line personality, with
-   regular FTP-like command-line syntax. [56]More about this below.
-   -A N Kermit is to be started as an Internet service (IKSD) (only from
-   inetd.conf).
-   -B N Kermit is running in Batch or Background (no controlling
-   terminal). To be used in case Kermit doesn't automatically sense its
-   background status. Equivalent to the SET BACKGROUND ON command.
-   -C arg N Interactive-mode Commands to be executed.
-   Argument: Commands separated by commas, list in doublequotes.
-   -D arg N Delay before starting to send in Remote mode. Equivalent to
-   the SET DELAY command.
-   Argument: Number of seconds.
-   -E N Exit automatically when connection closes. Equivalent to SET EXIT
-   ON-DISCONNECT ON.
-   -F arg N Use an open TCP connection.
-   Argument: Numeric file descriptor of open TCP connection.
-   Also see: -j, -J.
-   -G arg Y Get file(s) from server, send contents to standard output,
-   which normally would be piped to another process.
-   Argument: Remote file specification, in quotes if it contains
-   metacharacters.
-   Also see: -g, -k.
-   -H N Suppress program startup Herald and greeting.
-   -I N Tell Kermit it has a reliable connection, to force streaming to
-   be used where it normally would not be. Equivalent to the SET RELIABLE
-   ON command.
-   -J arg N "Be like Telnet." Like -j but implies -E.
-   Argument: IP hostname/address optionally followed by service.
-   NOTE: C-Kermit also has a separate Telnet command-line personality,
-   with regular Telnet-like command-line syntax. [57]More about this
-   below.
-   -L N Recursive directory descent for files in -s option.
-   -M arg N My user name (for use with Telnet, Rlogin, FTP, etc).
-   Equivalent to the SET LOGIN USER command.
-   Argument: Username string.
-   -O Y (Uppercase letter O) Be a server for One command only. Also see:
-   -x.
-   -P N Don't convert file (Path) names of transferred files. Equivalent
-   to SET FILE NAMES LITERAL.
-   -Q N Quick Kermit protocol settings. Equivalent to the FAST command.
-   This is the default in C-Kermit 7.0 and later.
-   -R N Remote-only (this just makes IF REMOTE true).
-   -S N Stay (enter command parser after action options).
-   -T N Force Text mode for file transfer; implies -V. Equivalent to SET
-   TRANSFER MODE MANUAL, SET FILE TYPE TEXT.
-   -V N Disable automatic per-file text/binary switching. Equivalent to
-   SET TRANSFER MODE MANUAL.
-   -Y N Skip (don't execute) the initialization file.
-   -a arg N As-name for file(s) in -s, -r, or -g.
-   Argument: As-name string (alternative filename). When receiving files,
-   this can be a directory name.
-   -b arg N Speed for serial device. Equivalent to SET SPEED.
-   Argument: Numeric Bits per second for serial connections.
-   -c Y Enter Connect state before transferring files.
-   -d N Create a debug.log file with detailed debugging information (a
-   second -d adds timestamps). Equivalent to LOG DEBUG but takes effect
-   sooner.
-   -e arg N Maximum length for incoming Kermit file-transfer packets.
-   Equivalent to SET RECEIVE PACKET-LENGTH.
-   Argument: Length in bytes.
-   -f Y Send a FINISH command to a Kermit server.
-   -g arg N Get file(s) from a Kermit server.
-   Argument: File specification on other computer, in quotes if it
-   contains metacharacters. Equivalent to GET.
-   Also see: -a, -G, -r.
-   -h Y Print Help text for single-letter command-line options (pipe thru
-   'more' to prevent scrolling).
-   -i N Force binary (Image) mode for file transfer; implies -V.
-   Equivalent to SET TRANSFER MODE MANUAL, SET FILE TYPE BINARY.
-   -j arg N Make a TCP/IP connection.
-   Argument: IP host name/address and optional service name or number.
-   Equivalent to the TELNET command.
-   Also see: -J, -F.
-   -k Y Receive file(s) to standard output, which normally would be piped
-   to another process.
-   Also see: -r, -G.
-   -l arg N (Lowercase letter L) Make a connection on the given serial
-   communications device. Equivalent to the SET LINE (SET PORT) command.
-   Argument: Serial device name, e.g. /dev/ttyS0.
-   -m arg N Modem type for use with the -l device. Equivalent to the SET
-   MODEM TYPE command.
-   Argument: Modem name as in SET MODEM TYPE command, e.g. "usrobotics".
-   -n Y Enter Connect state after transferring files (historical).
-   -p arg N Parity. Equivalent to the SET PARITY command.
-   Argument: One of the following: e(ven), o(dd), m(ark), n(one),
-   s(pace).
-   -q N Quiet (suppress most messages). Equivalent to SET QUIET ON.
-   -r Y Receive file(s). Equivalent to the RECEIVE command.
-   Argument: (none, but see -a)
-   -s arg N Send file(s).
-   Argument: One or more local file specifications. Equivalent to the
-   SEND command.
-   Also see: -a.
-   -t N (Historical) Xon (Ctrl-Q) Turnaround character for half-duplex
-   connections (used on serial linemode connections to old mainframes).
-   Equivalent to SET DUPLEX HALF, SET HANDSHAKE XON.
-   -v arg N Window size for Kermit protocol (ignored when streaming).
-   Equivalanet to SET WINDOW-SIZE.
-   Argument: Number, 1 to 32.
-   -w N Incoming files Write over existing files. Equivalent to SET FILE
-   COLLISION OVERWRITE.
-   -x Y Enter server mode. Equivalent to the SERVER command. Also see:
-   -O.
-   -y arg N Alternative initialization file.
-   Argument: Filename.
-   -z N Force foreground behavior. To be used in case Kermit doesn't
-   automatically sense its foreground status. Equivalent to the SET
-   BACKGROUND OFF command.
-   
-   Extended command-line options (necessary because single-letter ones
-   are about used up) start with two dashes (--), with words rather than
-   single letters as option names. If an extended option takes an
-   argument, it is separated from the option word by a colon (:).
-   Extended options include:
-   Option Description
-   --bannerfile:filename File to display upon startup or IKSD login.
-   --cdfile:filename File to be sent for display to the client when
-   server changes directory (filename is relative to the changed-to
-   directory).
-   --cdmessage:{on,off} Enable/disable the server CD message feature.
-   --help Prints usage message for extended options.
-   --helpfile:filename Designates a file containing custom text to
-   replace the top-level HELP command.
-   --nointerrupts Disables keyboard interrupts.
-   --noperms Disables the Kermit protocol file Permissions attribute, to
-   prevent transmission of file permissions (protection) from sender to
-   receiver.
-   
-   Plus several other [58]IKSD-Only options.
-   
-   See the [59]file-transfer section for examples of command-line
-   invocation.
-    ________________________________________________________________________
-  
-  COMMAND LANGUAGE [ [60]Top ] [ [61]Contents ] [ [62]Next ] [ [63]Previous ]
-  
-     * [64]Command Files, Macros, and Scripts
-     * [65]Command List
-       
-   C-Kermit's interactive command language is the subject of a
-   [66]622-page book and another several hundred pages of updates, far
-   too much for a manual page. But it's not hard to get started. At the
-   shell prompt, just type "kermit" to get C-Kermit's interactive command
-   prompt:
-   
-  $ kermit
-  (/current/directory) C-Kermit>
-
-   Begin by typing "help" (and then press the Return or Enter key) for a
-   top-level overview, read it, and go from there. Your second command
-   should probably be "intro" (introduction). Note the prompt shows your
-   current directory (unless you tell Kermit to prompt you with something
-   else).
-   
-   Interactive commands are composed mainly of regular English words,
-   usually in the form of imperative sentences, such as:
-   
-  send oofa.txt
-
-   which tells Kermit to send (transfer) the file whose name is oofa.txt,
-   or:
-   
-  set transfer mode automatic
-
-   which sets Kermit's "transfer mode" to "automatic" (whatever that
-   means).
-   
-   While typing commands, you can abbreviate, ask for help (by pressing
-   the "?" key anywhere in a command), complete keywords or filenames
-   (with the Tab or Esc key), and edit your typing with Backspace or
-   Delete, Ctrl-W, Ctrl-U, etc. You can also recall previous commands,
-   save your command history, and who knows what else. Give the INTRO
-   command for details.
-   
-   C-Kermit has hundreds of commands, and they can be issued in infinite
-   variety and combinations, including commands for:
-   
-     * Making connections (SET LINE, DIAL, TELNET, SSH, FTP, CONNECT,
-       ...)
-     * Breaking connections (HANGUP, CLOSE)
-     * Transferring files (SEND, GET, RECEIVE, MOVE, RESEND, ...)
-     * Establishing preferences (SET)
-     * Displaying preferences (SHOW)
-     * Managing local files (CD, DELETE, MKDIR, DIRECTORY, RENAME, TYPE,
-       ...)
-     * Managing remote files (RCD, RDEL, RMKDIR, RDIR, ...)
-     * Using local files (FOPEN, FCLOSE, FREAD, FWRITE)
-     * Programming (TAKE, DEFINE, IF, FOR, WHILE, SWITCH, DECLARE, ...)
-     * Interacting with the user (ECHO, ASK, ...)
-     * Interacting with a remote computer (INPUT, OUTPUT, ...)
-     * Interacting with local programs (RUN, EXEC, PTY, ...)
-     * Logging things (LOG SESSION, LOG PACKETS, LOG DEBUG, ...)
-       
-   And of course QUIT or EXIT to get out and HELP to get help, and for
-   programmers: loops, decision making, variables, arrays, associative
-   arrays, integer and floating point arithmetic, macros, built-in and
-   user-defined functions, string manipulation, pattern matching, block
-   structure, scoping, recursion, and all the rest. To get a list of all
-   C-Kermit's commands, type a question mark (?) at the prompt. To get a
-   description of any command, type HELP followed by the name of the
-   command, for example:
-   
-  help send
-
-   The command interruption character is Ctrl-C (hold down the Ctrl key
-   and press the C key).
-   
-   The command language "escape character", used to introduce variable
-   names, function invocations, and so on, is backslash (\). If you need
-   to include a literal backslash in a command, type two of them, e.g.:
-   
-  get c:\\k95\\k95custom.ini
-
-  Command Files, Macros, and Scripts
-  
-   A file containing Kermit commands is called a Kermit command file or
-   Kermit script. It can be executed with Kermit's TAKE command:
-   
-  (/current/dir) C-Kermit> take commandfile
-
-   (where "commandfile" is the name of the command file). Please don't
-   pipe a command file into Kermit's standard input (which might or might
-   not work); if you have Kermit commands in a file, tell Kermit to TAKE
-   the file.
-   
-   In Unix only, a Kermit command file can also be executed directly by
-   including a "kerbang" line as the first line of the file:
-   
-  #!/usr/local/bin/kermit +
-
-   That is, a top line that starts with "#!", followed immediately by the
-   full path of the Kermit executable, and then, if the Kermit script is
-   to be given arguments on the command line, a space and a plus sign.
-   The script file must also have execute permission:
-   
-  chmod +x commandfile
-
-   Except for the " +" part, this is exactly the same as you would do for
-   a shell script, a Perl script, etc. Here's a simple but useless
-   example script that regurgitates its arguments (up to three of them):
-   
-  #!/usr/local/bin/kermit +
-  if defined \%1 echo "Argument 1: \%1"
-  if defined \%2 echo "Argument 2: \%2"
-  if defined \%3 echo "Argument 3: \%3"
-  if defined \%4 echo "etc..."
-  exit
-
-   If this file is stored in your current directory as "commandfile",
-   then:
-   
-  ./commandfile one two three four five
-
-   prints:
-   
-  Argument 1: one
-  Argument 2: two
-  Argument 3: three
-  etc...
-
-   This illustrates the basic structure of a standalone Kermit script:
-   the "kerbang line", then some commands. It should end with "exit"
-   unless you want the Kermit prompt to appear when it is finished. \%1
-   is the first argument, \%2 the second, and so on.
-   
-   You can also create your own commands by defining named macros
-   composed of other Kermit commands (or macros). Here's a simple
-   example:
-   
-  define mydial {
-      set modem type usrobotics
-      set port /dev/ttyS0
-      if fail end 1
-      set speed 57600
-      dial \%1
-      if success connect
-  }
-
-   This shows how you can combine many commands into one command,
-   "mydial" in this case (you can use any name you like, provided it does
-   not clash with the name of a built-in command). When this macro
-   definition is in effect, you can type commands like:
-   
-  mydial 7654321
-
-   and it executes all the commands in macro definition, substituting the
-   first operand ("7654321") for the formal parameter ("\%1") in the
-   definition. This saves you from having to type lots of commands every
-   time you want to make a modem call.
-   
-   One way to have the macro definition in effect is to type the
-   definition at the Kermit prompt. Another way is to store the
-   definition in a file and TAKE the file. If you want the the definition
-   to be in effect automatically every time you start Kermit, put the
-   definition in your initialization or customization file (explained
-   [67]below).
-   
-   Here's a somewhat more ambitious example:
-   
-  define mydelete {
-      local trash
-      assign trash \v(home)trashcan/
-      if not defined \%1 end 1 "Delete what?"
-      if wild \%1 end 1 "Deleting multiple files is too scary"
-      if not exist \%1 end 1 "I can't find \%1"
-      if not directory \m(trash) {
-          mkdir \m(trash)
-          if fail end 1 "No trash can"
-      }
-      rename /list \%1 \m(trash)
-  }
-  define myundelete {
-      local trash
-      assign trash \v(home)trashcan/
-      if not defined \%1 end 1 "Undelete what?"
-      if wild \%1 end 1 "Undeleting multiple files is too hard"
-      if not directory \m(trash) end 1 "No trash can"
-      if not exist \m(trash)\%1 end 1 "I can't find \%1 in trash can"
-      rename /list \m(trash)\%1 .
-  }
-
-   These macros are not exactly production quality (they don't handle
-   filenames that include path segments, they don't handle multiple
-   files, etc), but you get the idea: you can pass arguments to macros,
-   they can check them and make other kinds of decisions, and the
-   commands themselves are relatively intuitive and intelligible.
-   
-   If you put the above lines into your initialization or customization
-   file, you'll have MYDELETE and MYUNDELETE commands available every
-   time you start Kermit, at least as long as you don't suppress
-   execution of the initialization file. (Exercise for the reader: Make
-   these macros generally useful: remove limitations, add trashcan
-   display, browsing, emptying, etc.)
-   
-   Kerbang scripts execute without the initialization file. This to keep
-   them portable and also to make them start faster. If you want to write
-   Kerbang scripts that depend on the initialization file, include the
-   command
-   
-  take \v(home).kermrc
-
-   at the desired spot in the script. By the way, \v(xxx) is a built-in
-   variable (xxx is the variable name, "home" in this case). To see what
-   built-in variables are available, type "show variables" at the
-   C-Kermit prompt. To see what else you can show, type "show ?". \m(xxx)
-   is a user defined variable (strictly speaking, it is a macro used as a
-   variable).
-   
-  Command List
-  
-   C-Kermit has more than 200 top-level commands, and some of these, such
-   as SET, branch off into hundreds of subcommands of their own, so it's
-   not practical to describe them all here. Instead, here's a concise
-   list of the most commonly used top-level commands, grouped by
-   category. To learn about each command, type "help" followed by the
-   command name, e.g. "help set". Terms such as Command state and Connect
-   state are explained in subsequent sections.
-   
-   Optional fields are shown in [ italicized brackets ]. filename means
-   the name of a single file. filespec means a file specification that is
-   allowed to contain wildcard characters like '*' to match groups of
-   files. options are (optional) switches like /PAGE, /NOPAGE, /QUIET,
-   etc, listed in the HELP text for each command. Example:
-   
-  send /recursive /larger:10000 /after:-1week /except:*.txt *
-
-   which can be read as "send all the files in this directory and all the
-   ones underneath it that are larger than 10000 bytes, no more than one
-   week old, and whose names don't end with ".txt".
-   
-   Basic Commands
-          HELP Requests top-level help.
-          HELP command Requests help about the given command.
-          INTRODUCTION Requests a brief introduction to C-Kermit.
-          LICENSE Displays the C-Kermit software copyright and license.
-          VERSION Displays C-Kermit's version number.
-          EXIT [ number ] Exits from Kermit with the given status code.
-          Synonyms: QUIT, E, Q.
-          TAKE filename [ parameters... ] Executes commands from the
-          given file.
-          LOG item [ filename ] Keeps a log of the given item in the
-          given file.
-          [ DO ] macro [ parameters... ]    Executes commands from the
-          given macro.
-          SET parameter value Sets the given parameter to the given
-          value.
-          SHOW category Shows settings in a given category.
-          STATUS Tells whether previous command succeeded or failed.
-          DATE [ date-and/or-time ] Shows current date-time or interprets
-          given date-time.
-          RUN [ extern-command [ parameters... ] Runs the given external
-          command. Synonym: !.
-          EXEC [ extern-command [ params... ] Kermit overlays itself with
-          the given command.
-          SUSPEND Stops Kermit and puts it in the background. Synonym: Z.
-          
-   Local File Management
-          TYPE [ options ] filename Displays the contents of the given
-          file.
-          MORE [ options ] filename Equivalent to TYPE /PAGE (pause after
-          each screenful).
-          CAT [ options ] filename Equivalent to TYPE /NOPAGE.
-          HEAD [ options ] filename Displays the first few lines of a
-          given file.
-          TAIL [ options ] filename Displays the last few lines of a
-          given file.
-          GREP [ options ] pattern filespec Displays lines from files
-          that match the pattern. Synonym: FIND.
-          DIRECTORY [ options ] [ filespec ] Lists files (built-in, many
-          options).
-          LS [ options ] [ filespec ] Lists files (runs external "ls"
-          command).
-          DELETE [ options ] [ filespec ] Deletes files. Synonym: RM.
-          PURGE [ options ] [ filespec ] Removes backup (*.~n~) files.
-          COPY [ options ] [ filespecs... ] Copies files. Synonym: CP.
-          RENAME [ options ] [ filespecs... ] Renames files. Synonym: MV.
-          CHMOD [ options ] [ filespecs... ] Changes permissions of
-          files.
-          TRANSLATE filename charsets filename ] Converts file's
-          character set. Synonym: XLATE.
-          CD Changes your working directory to your home directory.
-          CD directory Changes your working directory to the one given.
-          CDUP Changes your working directory one level up.
-          PWD Displays your working directory.
-          BACK Returns to your previous working directory.
-          MKDIR [ directory ] Creates a directory.
-          RMDIR [ directory ] Removes a directory.
-          
-   Making Connections
-          SET LINE [ options ] devicename        Opens the named serial
-          port. Synonym: SET PORT.
-          OPEN LINE [ options ] devicename Same as SET LINE. Synonym:
-          OPEN PORT.
-          SET MODEM TYPE [ name ] Tells Kermit what kind of modem is on
-          the port.
-          DIAL [ number ] Tells Kermit to dial the given phone number
-          with the modem.
-          REDIAL Redials the most recently dialed phone number.
-          ANSWER Waits for and answers an incoming call on the modem.
-          AUTHENTICATE [ parameters... ] Performs secure authentication
-          on a TCP/IP connection.
-          SET NETWORK TYPE { TCP/IP, X.25, ... } Selects network type for
-          subsequent SET HOST commands.
-          SET HOST [ options ] host [ port ] Opens a network connection
-          to the given host and port.
-          SET HOST [ options ] * port Waits for an incoming TCP/IP
-          connection on the given port.
-          TELNET [ options ] host Opens a Telnet connection to the host
-          and enters Connect state.
-          RLOGIN [ options ] host Opens an Rlogin connection to the host
-          and enters Connect state.
-          IKSD [ options ] host Opens a connection to an Internet Kermit
-          Service.
-          SSH [ options ] host Opens an SSH connection to the host and
-          enters Connect state.
-          FTP OPEN host [ options ] Opens an FTP connection to the host.
-          HTTP [ options ] OPEN host Opens an HTTP connection to the
-          host.
-          PTY external-command Runs the command on a pseudoterminal as if
-          it were a connection.
-          PIPE external-command Runs the command through a pipe as if it
-          were a connection.
-          
-   Using Connections
-          CONNECT [ options ]                    Enters Connect
-          (terminal) state. Synonym: C.
-          REDIRECT command Redirects the given external command over the
-          connection.
-          TELOPT command Sends a Telnet protocol command (Telnet
-          connections only).
-          Ctrl-\C "Escapes back" from Connect state to Command state.
-          Ctrl-\B (In Connect state) Sends a BREAK signal (serial or
-          Telnet).
-          Ctrl-\! (In Connect state) Enters inferior shell; "exit" to
-          return.
-          Ctrl-\? (In Connect state) Shows a menu of other escape-level
-          options.
-          Ctrl-\Ctrl-\ (In Connect state) Type two Ctrl-Backslashes to
-          send one of them.
-          SET ESCAPE [ character ] Changes Kermit's Connect-state escape
-          character.
-          
-   Closing Connections
-          HANGUP Hangs up the currently open serial-port or network
-          connection.
-          CLOSE Closes the currently open serial-port or network
-          connection.
-          SET LINE (with no devicename)          Closes the currently
-          open serial-port or network connection.
-          SET HOST (with no hostname) Closes the currently open
-          serial-port or network connection.
-          FTP CLOSE Closes the currently open FTP connection.
-          HTTP CLOSE Closes the currently open HTTP connection.
-          EXIT Also closes all connections. Synonym: QUIT.
-          SET EXIT WARNING OFF Suppresses warning about open connections
-          on exit or close.
-          
-   File Transfer
-          SEND [ options ] filename [ as-name ]  Sends the given file.
-          Synonym: S.
-          SEND [ options ] filespec Sends all files that match.
-          RESEND [ options ] filespec Resumes an interupted SEND from the
-          point of failure.
-          RECEIVE [ options ] [ as-name ] Waits passively for files to
-          arrive. Synonym: R.
-          LOG TRANSACTIONS [ filename ] Keeps a record of file transfers.
-          FAST Use fast file-transfer settings (default).
-          CAUTIOUS Use cautious and less fast file-transfer settings.
-          ROBUST Use ultra-conservative and slow file-transfer settings.
-          STATISTICS [ options ] Gives statistics about the most recent
-          file transfer.
-          WHERE After transfer: "Where did my files go?".
-          TRANSMIT [ options ] [ filename ] Sends file without protocol.
-          Synonym: XMIT.
-          LOG SESSION [ filename ] Captures remote text or files without
-          protocol.
-          SET PROTOCOL [ name... ] Tells Kermit to use an external
-          file-transfer protocol.
-          FTP { PUT, MPUT, GET, MGET, ... } FTP client commands.
-          HTTP { PUT, GET, HEAD, POST, ... } HTTP client commands.
-          
-   Kermit Server
-          ENABLE, DISABLE                        Controls which features
-          can be used by clients.
-          SET SERVER Sets parameters prior to entering Server state.
-          SERVER Enters Server state.
-          
-   Client of Kermit or FTP Server
-          [ REMOTE ] LOGIN [ user password ] Logs in to a Kermit server
-          or IKSD that requires it.
-          [ REMOTE ] LOGOUT Logs out from a Kermit server or IKSD.
-          SEND [ options ] filename [ as-name ]  Sends the given file to
-          the server. Synonyms: S, PUT.
-          SEND [ options ] filespec Sends all files that match.
-          RESEND [ options ] filespec Resumes an interupted SEND from the
-          point of failure.
-          GET [ options ] remote-filespec Asks the server to send the
-          given files. Synonym: G.
-          REGET [ options ] remote-filespec Resumes an interrupted GET
-          from the point of failure.
-          REMOTE CD [ directory ] Asks server to change its working
-          directory. Synonym: RCD.
-          REMOTE PWD [ directory ] Asks server to display its working
-          directory. Synonym: RPWD.
-          REMOTE DIRECTORY [ filespec... ] Asks server to send a
-          directory listing. Synonym: RDIR.
-          REMOTE DELETE [ filespec... ] Asks server to delete files.
-          Synonym: RDEL.
-          REMOTE [ command... ] (Many other commands: "remote ?" for a
-          list).
-          MAIL [ options ] filespec Sends file(s) to be delivered as
-          e-mail (Kermit only).
-          FINISH Asks the server to exit server state (Kermit only).
-          BYE Asks the server to log out and close the connection.
-          
-   Script Programming
-          DEFINE, DECLARE, UNDEFINE, UNDECLARE, ASSIGN, EVALUATE,
-          SEXPRESSION, ARRAY, SORT, INPUT, OUTPUT, IF, FOR, WHILE,
-          SWITCH, GOTO, ECHO, ASK, GETC, GETOK, ASSERT, WAIT, SLEEP,
-          FOPEN, FREAD, FWRITE, FCLOSE, STOP, END, RETURN, LEARN, SHIFT,
-          TRACE, VOID, INCREMENT, DECREMENT, ... For these and many more
-          you'll need to consult the [68]manual and supplements, and/or
-          visit the [69]Kermit Script Library, which also includes a
-          brief tutorial. Hint: HELP LEARN to find out how to get Kermit
-          to write simple scripts for you.
-          
-   Many of Kermit's commands have synonyms, variants, relatives, and so
-   on. For example, MSEND is a version of SEND that accepts a list of
-   file specifications to be sent, rather than just one file
-   specification, and MPUT is a synonym of MSEND. MOVE means to SEND and
-   then DELETE the source file if successful. MMOVE is like MOVE, but
-   accepts a list of filespecs, and so on. These are described in the
-   [70]full documentation.
-   
-   Use question mark to feel your way through an unfamiliar command, as
-   in this example (the part you type is underlined):
-   
-  C-Kermit> remote ? One of the following:
-   assign     delete     help       login      print      rename     space
-   cd         directory  host       logout     pwd        rmdir      type
-   copy       exit       kermit     mkdir      query      set        who
-  C-Kermit> remote set ? One of the following:
-   attributes   file         retry        transfer
-   block-check  receive      server       window
-  C-Kermit> remote set file ? One of the following:
-   character-set  incomplete     record-length
-   collision      names          type
-  C-Kermit> remote set file names ? One of the following:
-   converted  literal
-  C-Kermit> remote set file names literal
-  C-Kermit>
-
-   This is called menu on demand: you get a menu when you want one, but
-   menus are not forced on you even when know what you're doing. Note
-   that you can also abbreviate most keywords, and you can complete them
-   with the Tab or Esc key. Also note that ? works for filenames too, and
-   that you can use it in the middle of a keyword or filename, not just
-   at the beginning. For example, "send x?" lists all the files in the
-   current directory whose names start with 'x'.
-   
-   [ [71]Kermit Home ] [ [72]C-Kermit Home ] [ [73]C-Kermit FAQ ]
-    ________________________________________________________________________
-  
-  INITIALIZATION FILE [ [74]Top ] [ [75]Contents ] [ [76]Next ] [ [77]Previous
-  ]
-  
-   In its default configuration, C-Kermit executes commands from a file
-   called .kermrc in your home directory when it starts, unless it is
-   given the -Y or -y command-line option. Custom configurations might
-   substitute a shared system-wide initialization file. The SHOW FILE
-   command tells what initialization file, if any, was used. The standard
-   initialization file "chains" to an individual customization file,
-   .mykermc, in the home directory, in which each user can establish
-   her/his own preferences, define macros, and so on.
-   
-   Since execution of the initialization file (at least the standard one)
-   makes C-Kermit take longer to start, it might be better not to have an
-   initialization file, especially now that Kermit's default startup
-   configuration is well attuned to modern computing and networking -- in
-   other words, you no longer have do anything special to make Kermit
-   transfers go fast. So instead of having an initialization file that is
-   executed every time Kermit starts, you might consider making one or
-   more kerbang scripts (with names other that .kermrc) that do NOT
-   include an "exit" command, and invoke those when you need the
-   settings, macro definitions, and/or scripted actions they contain, and
-   invoke C-Kermit directly when you don't.
-   
-   To put it another way... We still distribute the standard
-   initialization file since it's featured in the manual and backwards
-   compatibility is important to us. But there's no harm in not using it
-   if you don't need the stuff that's in it (services directory, dialing
-   directory, network directory, and associated macro definitions). On
-   the other hand, if there are settings or macros you want in effect
-   EVERY time you use Kermit, the initialization file (or the
-   customization file it chains to) is the place to put them, because
-   that's the only place Kermit looks for them automatically each time
-   you start it.
-   
-   [ [78]Kermit Home ] [ [79]C-Kermit Home ] [ [80]C-Kermit FAQ ]
-    ________________________________________________________________________
-  
-  MODES OF OPERATION [ [81]Top ] [ [82]Contents ] [ [83]Next ] [ [84]Previous ]
-  
-   Kermit is said to be in Local mode if it has made a connection to
-   another computer, e.g. by dialing it or establishing a Telnet
-   connection to it. The other computer is remote, so if you start
-   another copy of Kermit on the remote computer, it is said to be in
-   Remote mode (as long as it has not made any connections of its own).
-   The local Kermit communicates over the communications device or
-   network connection, acting as a conduit between the the remote
-   computer and your keyboard and screen. The remote Kermit is the
-   file-transfer partner to the local Kermit and communicates only
-   through its standard input and output.
-   
-   At any moment, a Kermit program can be in any of the following states.
-   It's important to know what they are and how to change from one to the
-   other.
-   
-   Command state
-          
-          In this state, Kermit reads commands from:
-          
-          + Your keyboard; or:
-          + A file, or:
-          + A macro definition.
-            
-          You can exit from Command state back to Unix with the EXIT or
-          QUIT command (same thing). You can enter Connect state with any
-          of various commands (CONNECT, DIAL, TELNET, etc). You can enter
-          file transfer state with commands like SEND, RECEIVE, and GET.
-          You can enter Server state with the SERVER command. The TAKE
-          command tells Kermit to read and execute commands from a file.
-          The (perhaps implied) DO command tells Kermit to read and
-          execute commands from a macro definition. While in Command
-          state, you can interrupt any command, macro, or command file by
-          typing Ctrl-C (hold down the Ctrl key and press the C key);
-          this normally brings you back to the prompt.
-          
-   Shell state
-          
-          You can invoke an inferior shell or external command from the
-          Kermit command prompt by using the PUSH, RUN (!), EDIT, or
-          BROWSE command. While the inferior shell or command is active,
-          Kermit is suspended and does nothing. Return to Kermit Command
-          state by exiting from the inferior shell or application.
-          
-   Connect state
-          
-          In this state, which can be entered only when in Local mode
-          (i.e. when Kermit has made a connection to another computer),
-          Kermit is acting as a terminal to the remote computer. Your
-          keystrokes are sent to the remote computer and characters that
-          arrive over the communication connection are displayed on your
-          screen. This state is entered when you give a CONNECT, DIAL,
-          TELNET, RLOGIN, or IKSD command. You can return to command
-          state by logging out of the remote computer, or by typing:
-          
-  Ctrl-\c
-
-          That is: Hold down the Ctrl key and press the backslash key,
-          then let go of the Ctrl key and press the C key. This is called
-          escaping back. Certain other escape-level commands are also
-          provided; type Ctrl-\? for a list. For example, you can enter
-          Shell state with:
-          
-  Ctrl-\!
-
-          To send a Ctrl-\ to the host while in Connect state, type two
-          of them in a row. See HELP CONNECT and HELP SET ESCAPE for more
-          info.
-          
-   Local file-transfer state
-          
-          In this state, Kermit is sending packets back and forth with
-          the other computer in order to transfer a file or accomplish
-          some other file-related task. And at the same time, it is
-          displaying its progress on your screen and watching your
-          keyboard for interruptions. In this state, the following
-          single-keystroke commands are accepted:
-          
-            X Interrupt the current file and go on to the next (if any).
-            Z Interrupt the current file and skip all the rest.
-            E Like Z but uses a "stronger" protocol (use if X or Z don't
-          work).
-            Ctrl-C   Interrupt file-transfer mode (use if Z or E don't
-          work).
-          
-          Kermit returns to its previous state (Command or Connect) when
-          the transfer is complete or when interrupted successfully by X,
-          Z, E, or Ctrl-C (hold down the Ctrl key and press the C key).
-          
-   Remote file-transfer state
-          
-          In this state, Kermit is exchanging file-transfer packets with
-          its local partner over its standard i/o. It leaves this state
-          automatically when the transfer is complete. In case you find
-          your local Kermit in Connect state and the remote one in
-          File-transfer state (in which it seems to ignore your
-          keystrokes), you can usually return it to command state by
-          typing three Ctrl-C's in a row. If that doesn't work, return
-          your local Kermit to Command state (Ctrl-\ C) and type
-          "e-packet" and then press the Return or Enter key; this forces
-          a fatal Kermit protocol error.
-          
-   Remote Server state
-          
-          This is like Remote File-transfer state, except it never
-          returns automatically to Command state. Rather, it awaits
-          further instructions from the client program; that is, from
-          your Local Kermit program. You can return the Remote Server to
-          its previous state by issuing a "finish" command to the client,
-          or if you are in Connect state, by typing three Ctrl-C's in a
-          row. You can tell the server job to log out and break the
-          connection by issuing a "bye" command to the client.
-          
-   Local Server state
-          
-          Like Remote-Server state, but in local mode, and therefore with
-          its file-transfer display showing, and listening for single-key
-          commands, as in Local File-transfer state. Usually this state
-          is entered automatically when a remote Kermit program gives a
-          GET command.
-          
-   C-Kermit, Kermit 95, and MS-DOS Kermit all can switch automatically
-   from Connect state to Local File-transfer state when you initiate a
-   file transfer from the remote computer by starting Kermit and telling
-   it to send or get a file, in which case, Connect state is
-   automatically resumed after the file transfer is finished.
-   
-   Note that C-Kermit is not a terminal emulator. It is a communications
-   application that you run in a terminal window (e.g. console or Xterm).
-   The specific emulation, such as VT100, VT220, Linux Console, or Xterm,
-   is provided by the terminal window in which you are running C-Kermit.
-   Kermit 95 and MS-DOS Kermit, on the other hand, are true terminal
-   emulators. Why is C-Kermit not a terminal emulator? [85]CLICK HERE to
-   read about it.
-   
-   [ [86]Kermit Home ] [ [87]C-Kermit Home ] [ [88]C-Kermit FAQ ]
-    ________________________________________________________________________
-  
-  MAKING CONNECTIONS [ [89]Top ] [ [90]Contents ] [ [91]Next ] [ [92]Previous ]
-  
-   Here is how to make different kinds of connections using interactive
-   Kermit commands (as noted above, you can also make connections with
-   command-line options). Note that you don't have to make connections
-   with Kermit. It can also be used on the far end of a connection as the
-   remote file transfer and management partner of your local
-   communications software.
-   
-   Making a Telnet Connection
-          
-          At the C-Kermit command prompt, simply type:
-          
-  telnet foo.bar.com         ; Substitute desired host name or address.
-  telnet xyzcorp.com 3000    ; You can also include a port number.
-
-          If the connection is successful, Kermit automically enters
-          Connect state. When you logout from the remote host, Kermit
-          automatically returns to its prompt. More info: HELP TELNET,
-          HELP SET TELNET, HELP SET TELOPT. Also see the [93]IKSD section
-          below.
-          
-   Making an Rlogin connection
-          
-          This is just like Telnet, except you have to be root to do it
-          because Rlogin uses a privileged TCP port:
-          
-  rlogin foo.bar.com         ; Substitute desired host name or address.
-
-          More info: HELP RLOGIN.
-          
-   Making an SSH Connection
-          
-          Unlike Telnet and Rlogin, SSH connections are not built-in, but
-          handled by running your external SSH client through a
-          pseudoterminal. Using C-Kermit to control the SSH client gives
-          you all of Kermit's features (file transfer, character-set
-          conversion, scripting, etc) over SSH.
-          
-  ssh foo.bar.com            ; Substitute desired host name or address.
-
-          More info: HELP SSH, HELP SET SSH.
-          
-   Dialing with a Modem
-          
-          If it's an external modem, make sure it is connected to a
-          usable serial port on your computer with a regular
-          (straight-through) modem cable, and to the telephone jack with
-          a telephone cable, and that it's turned on. Then use these
-          commands:
-          
-  set modem type usrobotics  ; Or other supported type
-  set line /dev/ttyS0        ; Specify device name
-  set speed 57600            ; Or other desired speed
-  set flow rts/cts           ; Most modern modems support this
-  set dial method tone       ; (or pulse)
-  dial 7654321               ; Dial the desired number
-
-          Type "set modem type ?" for a list of supported modem types. If
-          you omit the SET MODEM TYPE command, the default type is
-          "generic-high-speed", which should work for most modern
-          AT-command-set modems. If the line is busy, Kermit redials
-          automatically. If the call does not succeed, use "set dial
-          display on" and try it again to watch what happens. If the call
-          succeeds, Kermit enters Connect state automatically and returns
-          to its prompt automatically when you log out from the remote
-          computer or the connection is otherwise lost.
-          
-          You can also dial from a modem that is accessible by Telnet,
-          e.g. to a reverse terminal server. In this case the command
-          sequence is:
-          
-  set host ts.xxx.com 2000   ; Terminal-server and port
-  set modem type usrobotics  ; Or other supported type
-  set dial method tone       ; (or pulse)
-  dial 7654321               ; Dial the desired number
-
-          If the terminal server supports the Telnet Com Port Option,
-          [94]RFC 2217, you can also give serial-port related commands
-          such as SET SPEED, SET PARITY, and so on, and Kermit relays
-          them to the terminal server using the protocol specified in the
-          RFC.
-          
-          More info: HELP SET MODEM, HELP SET LINE, HELP SET SPEED, HELP
-          SET FLOW, HELP DIAL, HELP SET DIAL, HELP SET MODEM, HELP SET
-          CARRIER-WATCH, SHOW COMMUNICATIONS, SHOW MODEM, SHOW DIAL.
-          
-   Direct Serial Port
-          
-          Connect the two computers, A and B, with a null modem cable (or
-          two modem cables interconnected with a null-modem adapter or
-          modem eliminator). From Computer A:
-          
-  set modem type none        ; There is no modem
-  set line /dev/ttyS0        ; Specify device name
-  set carrier-watch off      ; If DTR and CD are not cross-connected
-  set speed 57600            ; Or other desired speed
-  set flow rts/cts           ; If RTS and CTS are cross-connected
-  set flow xon/xoff          ; If you can't use RTS/CTS
-  set parity even            ; (or "mark" or "space", if necessary)
-  set stop-bits 2            ; (rarely necessary)
-  connect                    ; Enter Connect (terminal) state
-
-          This assumes Computer B is set up to let you log in. If it
-          isn't, you can run a copy of Kermit on Computer B and follow
-          approximately the same directions. More info: As above plus
-          HELP CONNECT.
-          
-   With modems or direct serial connections, you might also have to "set
-   parity even" (or "mark" or "space") if it's a 7-bit connection.
-   
-   Of the connection types listed above, only one can be open at a time.
-   However, any one of these can be open concurrently with an [95]FTP or
-   HTTP session. Each connection type can be customized to any desired
-   degree, scripted, logged, you name it. See the manual.
-   
-   NOTE: On selected platforms, C-Kermit also can make X.25 connections.
-   See the manual for details.
-   
-   [ [96]Kermit Home ] [ [97]C-Kermit Home ] [ [98]C-Kermit FAQ ]
-    ________________________________________________________________________
-  
-  TRANSFERRING FILES WITH KERMIT [ [99]Top ] [ [100]Contents ] [ [101]Next ] [
-  [102]Previous ]
-  
-     * [103]Downloading Files
-     * [104]Uploading Files
-     * [105]Kermit Transfers the Old-Fashioned Way
-     * [106]If File Transfer Fails
-     * [107]Advanced Kermit File Transfer Features
-     * [108]Non-Kermit File Transfer
-       
-   There is a [109]widespread and persistent belief that Kermit is a slow
-   protocol. This is because, until recently, it used conservative tuning
-   by default to make sure file transfers succeeded, rather than failing
-   because they overloaded the connection. Some extra commands (or
-   command-line options, like -Q) were needed to make it go fast, but
-   nobody bothered to find out about them. Also, it takes two to tango:
-   most non-Kermit-Project Kermit protocol implementations really ARE
-   slow. The best file-transfer partners for C-Kermit are: another copy
-   of [110]C-Kermit (7.0 or later) and [111]Kermit 95. These combinations
-   work well and they work fast by default. MS-DOS Kermit is good too,
-   but you have to tell it to go fast (by giving it the FAST command).
-   
-   Furthermore, all three of these Kermit programs support "autodownload"
-   and "autoupload", meaning that when they are in Connect state and a
-   Kermit packet comes in from the remote, they automatically switch into
-   file transfer mode.
-   
-   And plus, C-Kermit and K95 also switch automatically between text and
-   binary mode for each file, so there is no need to "set file type
-   binary" or "set file type text", or to worry about files being
-   corrupted because they were transferred in the wrong mode.
-   
-   What all of these words add up to is that now, when you use up-to-date
-   Kermit software from the Kermit Project, file transfer is not only
-   fast, it's ridiculously easy. You barely have to give any commands at
-   all.
-   
-   Downloading Files
-          
-          Let's say you have [112]Kermit 95, [113]C-Kermit, or
-          [114]MS-DOS Kermit on your desktop computer, with a connection
-          to a Unix computer that has C-Kermit installed as "kermit". To
-          download a file (send it from Unix to your desktop computer),
-          just type the following command at your Unix shell prompt:
-          
-  kermit -s oofa.txt
-
-          (where oofa.txt is the filename). If you want to send more than
-          one file, you can put as many filenames as you want on the
-          command line, and they can be any combination of text and
-          binary:
-          
-  kermit -s oofa.txt oofa.zip oofa.html oofa.tar.gz
-
-          and/or you can use wildcards to send groups of files:
-          
-  kermit -s oofa.*
-
-          If you want to send a file under an assumed name, use:
-          
-  kermit -s friday.txt -a today.txt
-
-          This sends the file friday.txt but tells the receiving Kermit
-          that its name is today.txt. In all cases, as noted, when the
-          file transfer is finished, your desktop Kermit returns
-          automatically to Connect state. No worries about escaping back,
-          re-connecting, text/binary mode switching. Almost too easy,
-          right?
-          
-   Uploading Files
-          
-          To upload files (send them from your desktop computer to the
-          remote Unix computer) do the same thing, but use the -g (GET)
-          option instead of -s:
-          
-  kermit -g oofa.txt
-
-          This causes your local Kermit to enter server mode; then the
-          remote Kermit program requests the named file and the local
-          Kermit sends it and returns automatically to Connect state when
-          done.
-          
-          If you want to upload multiple files, you have have use shell
-          quoting rules, since these aren't local files:
-          
-  kermit -g "oofa.txt oofa.zip oofa.html oofa.tar.gz"
-  kermit -g "oofa.*"
-
-          If you want to upload a file but store it under a different
-          name, use:
-          
-  kermit -g friday.txt -a today.txt
-
-   Kermit Transfers the Old-Fashioned Way
-          
-          If your desktop communications software does not support
-          autoupload or autodownload, or it does not include Kermit
-          server mode, the procedure requires more steps.
-          
-          To download a file, type:
-          
-  kermit -s filename
-
-          on the host as before, but if nothing happens automatically in
-          response to this command, you have to switch your desktop
-          communications software into Kermit Receive state. This might
-          be done by escaping back using keyboard characters or hot keys
-          (Alt-x is typical) and/or with a command (like RECEIVE) or a
-          menu. When the file transfer is complete, you have to go back
-          to Connect state, Terminal emulation, or whatever terminology
-          applies to your desktop communications software.
-          
-          To upload a file, type:
-          
-  kermit -r
-
-          on the host (rather than "kermit -g"). This tells C-Kermit to
-          wait passively for a file to start arriving. Then regain the
-          attention of your desktop software (Alt-x or whatever) and
-          instruct it to send the desired file(s) with Kermit protocol.
-          When the transfer is finished, return to the Connect or
-          Terminal screen.
-          
-   If File Transfer Fails
-          
-          Although every aspect of Kermit's operation can be finely
-          tuned, there are also three short and simple "omnibus tuning"
-          commands you can use for troubleshooting:
-          
-        FAST
-                Use fast file-transfer settings. This has been the
-                default since C-Kermit 7.0 now that most modern computers
-                and connections support it. If transfers fail with fast
-                settings, try . . .
-                
-        CAUTIOUS
-                Use cautious but not paranoid settings. File transfers,
-                if they work, will go at medium speed. If not, try . . .
-                
-        ROBUST
-                Use the most robust, resilient, conservative, safe, and
-                reliable settings. File transfers will almost certainly
-                work, but they will be quite slow (of course this is a
-                classic tradeoff; ROBUST was C-Kermit's default tuning in
-                versions 6.0 and earlier, which made everybody think
-                Kermit protocol was slow). If ROBUST doesn't do the
-                trick, try again with SET PARITY SPACE first in case it's
-                not an 8-bit connection.
-                
-          Obviously the success and performance of a file transfer also
-          depends on C-Kermit's file transfer partner. Up-to-date, real
-          [115]Kermit Project partners are recommended because they
-          contain the best Kermit protocol implementations and because
-          [116]we can support them in case of trouble.
-          
-          If you still have trouble, consult Chapter 10 of [117]Using
-          C-Kermit, or send email to [118]kermit-support@columbia.edu.
-          
-   Advanced Kermit File-Transfer Features
-          
-          Obviously there is a lot more to Kermit file transfer,
-          including all sorts of interactive commands, preferences,
-          options, logging, debugging, troubleshooting, and anything else
-          you can imagine but that's what the [119]manual and updates are
-          for. Here are a few topics you can explore if you're interested
-          by Typing HELP for the listed commands:
-          
-        Logging transfers:
-                LOG TRANSACTIONS (HELP LOG)
-                
-        Automatic per-file text/binary mode switching:
-                SET TRANSFER MODE { AUTOMATIC, MANUAL } (HELP SET
-                TRANSFER).
-                
-        Cross-platform recursive directory tree transfer:
-                SEND /RECURSIVE, GET /RECURSIVE (HELP SEND, HELP GET).
-                
-        File collision options:
-                SET FILE COLLISION { OVERWRITE, BACKUP, DISCARD, ... }
-                (HELP SET FILE).
-                
-        Update mode (only transfer files that changed since last time):
-                SET FILE COLLISION UPDATE (HELP SET FILE).
-                
-        Filename selection patterns:
-                (HELP WILDCARD).
-                
-        Flexible file selection:
-                SEND (or GET) /BEFORE /AFTER /LARGER /SMALLER /TYPE
-                /EXCEPT, ...
-                
-        Character-set conversion:
-                SET { FILE, TRANSFER } CHARACTER-SET, ASSOCIATE, ...
-                
-        File/Pathname control:
-                SET { SEND, RECEIVE } PATHNAMES, SET FILE NAMES.
-                
-        Atomic file movement:
-                SEND (or GET) /DELETE /RENAME /MOVE-TO
-                
-        Transferring to/from standard i/o of other commands:
-                SEND (or GET) /COMMAND
-                
-        Recovery of interrupted transfer from point of failure:
-                RESEND, REGET (HELP RESEND, HELP REGET).
-                
-   Non-Kermit File Transfer
-          
-          You can also use C-Kermit to transfer files with FTP or HTTP
-          Internet protocols; [120]see below.
-          
-          On a regular serial or Telnet connection where the other
-          computer doesn't support Kermit protocol at all, you have
-          several options. For example, if your desktop communications
-          software supports Zmodem, use "rz" and "sz" on the host rather
-          than Kermit. But if Kermit is your desktop software, and you
-          are using it to make calls or network connections to other
-          computers that don't support Kermit protocol (or that don't
-          have a good implementation of it), then if your computer also
-          has external X, Y, or Zmodem programs that are redirectable,
-          Kermit can use them as external protocols. HELP SET PROTOCOL
-          for details.
-          
-          You can also capture "raw" data streams from the other computer
-          with LOG SESSION (HELP LOG and HELP SET SESSION-LOG for
-          details), and you can upload files without any protocol at all
-          with TRANSMIT (HELP TRANSMIT, HELP SET TRANSMIT).
-          
-   [ [121]Kermit Home ] [ [122]C-Kermit Home ] [ [123]C-Kermit FAQ ]
-    ________________________________________________________________________
-  
-  KERMIT CLIENT/SERVER CONNECTIONS [ [124]Top ] [ [125]Contents ] [ [126]Next ]
-  [ [127]Previous ]
-  
-   On any kind of connection you can make with Kermit -- serial, TCP/IP,
-   X.25, etc -- you can set up a convenient client/server relationship
-   between your Kermit client (the one that made the connection) and the
-   Kermit program on the far end of the connection (the remote Kermit) by
-   putting the remote Kermit in server mode. This is normally done by
-   giving it a SERVER command, or by starting it with the -x command-line
-   option. In some cases ([128]Internet Kermit Service, SSH connections
-   to a Kermit subsystem, or specially configured hosts), there is
-   already a Kermit server waiting on the far end. Here is a quick
-   synopsis of the commands you can give to the client for interacting
-   with the server:
-   
-   SEND [ switches ] filename
-          Sends the named file to the server. The filename can include
-          wildcards. Lots of switches are available for file selection,
-          etc. Type HELP SEND at the client prompt for details.
-          
-   GET [ switches ] filename
-          Asks the server to send the named file. The filename can
-          include wildcards. Type HELP GET at the client prompt for
-          details.
-          
-   BYE
-          Terminates the server and closes your connection to it.
-          
-   FINISH
-          Terminates the server. If you started the server yourself, this
-          leaves the remote host at its shell prompt. If it was a
-          dedicated server (such as IKSD or an SSH subsystem), FINISH is
-          equivalent to BYE.
-          
-   SET LOCUS { LOCAL, REMOTE, AUTO }
-          (C-Kermit 8.0.201 and later, K95 1.1.21 and later) This tells
-          the client whether file-management commands like CD, PWD,
-          DIRECTORY, DELETE, MKDIR, etc, should be executed locally or by
-          the server. In this type of connection, the default is LOCAL.
-          Use SET LOCUS REMOTE if you want Kermit to behave like an FTP
-          client, in which case these commands are executed remotely, and
-          their local versions must have an L prefix: LCD, LPWD,
-          LDIRECTORY, etc. When LOCUS is LOCAL, then the remote versions
-          must have an R prefix: RCD, RPWD, RDIRECTORY, etc. HELP SET
-          LOCUS for details. SHOW COMMAND to see current locus.
-          
-   The following commands are affected by SET LOCUS:
-   
-   CD, LCD, RCD
-   Change (working, current) directory. HELP CD for details.
-   
-   CDUP, LCDUP, RCDUP
-   CD one level up.
-   
-   DIRECTORY, LDIRECTORY, RDIRECTORY
-   Produce a directory listing. Many options are available for local
-   listings. HELP DIRECTORY for details.
-   
-   DELETE, LDELETE, RDELETE
-   Deletes files or directories. Many options available, HELP DELETE.
-   
-   RENAME, LRENAME, RRENAME
-   Renames files or directories. Many options available, HELP RENAME.
-   
-   MKDIR, LMKDIR, RMKDIR
-   Creates a directory. HELP MKDIR.
-   
-   RMDIR, LRMDIR, RRMDIR
-   Removes a directory. HELP RMDIR. There are dozens -- maybe hundreds --
-   of other commands, described in the built-in help, on the website,
-   and/or in the published or online manuals. But even if you don't have
-   access to documentation, you can "set locus remote" and then use
-   pretty much the same commands you would use with any FTP client.
-   
-   [ [129]Kermit Home ] [ [130]C-Kermit Home ] [ [131]C-Kermit FAQ ]
-    ________________________________________________________________________
-  
-  KERMIT'S BUILT-IN FTP AND HTTP CLIENTS [ [132]Top ] [ [133]Contents ] [
-  [134]Next ] [ [135]Previous ]
-  
-   Kermit's FTP client is like the regular Unix FTP client that you're
-   used to, but with some differences:
-   
-     * It has lots more commands and features.
-     * You can have an FTP session and a regular Kermit serial or Telnet
-       session open at the same time.
-     * FTP sessions can be fully automated.
-       
-   By default Kermit's FTP client tries its best to present the same user
-   interface as a regular FTP client: PUT, GET, DIR, CD, BYE, etc, should
-   work the same, even though some of these commands have different
-   meaning in Kermit-to-Kermit connections; for example, CD, DIR, RENAME,
-   etc, in Kermit act locally, whereas in FTP they are commands for the
-   server. This might cause some confusion, but as in all things Kermit,
-   you have total control:
-   
-     * The [136]SET LOCUS command lets you specify where file management
-       commands should be executed -- locally or remotely -- for any kind
-       of connection.
-     * Any FTP command can be prefixed with the word "FTP" to remove any
-       ambiguity.
-       
-   Pending publication of the next edition of the manual, the Kermit FTP
-   client is thoroughly documented at the Kermit Project website:
-   
-  [137]http://www.columbia.edu/kermit/ftpclient.html
-
-   You also can use HELP FTP and HELP SET FTP to get descriptions of
-   Kermit's FTP-related commands.
-   
-   The HTTP client is similar to the FTP one, except you prefix each
-   command with HTTP instead of FTP: HTTP OPEN, HTTP GET, HTTP PUT, HTTP
-   CLOSE, etc. Type HELP HTTP for details, or visit the to view the
-   [138]manual supplements. HTTP connections can be open at the same time
-   as regular serial or Telnet connections and FTP connections. So Kermit
-   can manage up to three types connections simultaneously.
-   
-   [ [139]Kermit Home ] [ [140]C-Kermit Home ] [ [141]C-Kermit FAQ ] [
-   [142]FTP Client ] [ [143]HTTP Client ]
-    ________________________________________________________________________
-  
-  INTERNET KERMIT SERVICE [ [144]Top ] [ [145]Contents ] [ [146]Next ] [
-  [147]Previous ]
-  
-   C-Kermit can be configured and run as an Internet service (called
-   IKSD), similar to an FTP server (FTPD) except you can (but need not)
-   interact with it directly, plus it does a lot more than an FTP server
-   can do. The TCP port for IKSD is 1649. It uses Telnet protocol.
-   C-Kermit can be an Internet Kermit Server, or it can be a client of an
-   IKSD. You can make connections from C-Kermit to an IKSD with any of
-   the following commands:
-   
-  telnet foo.bar.edu 1649
-  telnet foo.bar.edu kermit   ; if "kermit" is listed in /etc/services
-  iksd foo.bar.edu
-
-   The IKSD command is equivalent to a TELNET command specifying port
-   1649. For more information about making and using connections to an
-   IKSD, see:
-   
-  [148]http://www.columbia.edu/kermit/cuiksd.html
-
-   You can run an Internet Kermit Service on your own computer too (if
-   you are the system administrator). For instructions, see:
-   
-  [149]http://www.columbia.edu/kermit/iksd.html
-
-   [ [150]Kermit Home ] [ [151]C-Kermit Home ] [ [152]C-Kermit FAQ ]
-    ________________________________________________________________________
-  
-  SECURITY [ [153]Top ] [ [154]Contents ] [ [155]Next ] [ [156]Previous ]
-  
-   All of C-Kermit's built-in TCP/IP networking methods (Telnet, Rlogin,
-   IKSD, FTP, and HTTP) can be secured by one or more of the following
-   IETF-approved methods:
-   
-     * MIT Kerberos IV
-     * MIT Kerberos V
-     * SSL/TLS
-     * Stanford SRP
-       
-   For complete instructions see:
-   
-  [157]http://www.columbia.edu/kermit/security.html
-
-   And as noted previously, you can also make SSH connections with
-   C-Kermit if you already have an SSH client installed.
-   
-   [ [158]Kermit Home ] [ [159]C-Kermit Home ] [ [160]C-Kermit FAQ ]
-    ________________________________________________________________________
-  
-  ALTERNATIVE COMMAND-LINE PERSONALITIES [ [161]Top ] [ [162]Contents ] [
-  [163]Next ] [ [164]Previous ]
-  
-   When invoked as "kermit" or any other name besides any of the special
-   ones, C-Kermit has the command-line options described above in the
-   [165]OPTIONS section. However, if you invoke C-Kermit using any of the
-   following names:
-   
-     telnet  Telnet client
-     ftp     FTP client
-     http    HTTP client
-     https   Secure HTTP client
-   
-   Kermit's command-line personality changes to match. This can be done
-   (among other ways) with symbolic links (symlinks). For example, if you
-   want C-Kermit to be your regular Telnet client, or the Telnet helper
-   of your Web browser, you can create a link like the following in a
-   directory that lies in your PATH ahead of the regular telnet program:
-   
-  ln -s /usr/local/bin/kermit telnet
-
-   Now when you give a "telnet" command, you are invoking Kermit instead,
-   but with its Telnet command-line personality so, for example:
-   
-  telnet xyzcorp.com
-
-   Makes a Telnet connection to xyzcorp.com, and Kermit exits
-   automatically when the connection is closed (just like the regular
-   Telnet client). Type "telnet -h" to get a list of Kermit's
-   Telnet-personality command-line options, which are intended to be as
-   compatible as possible with the regular Telnet client.
-   
-   Similarly for FTP:
-   
-  ln -s /usr/local/bin/kermit ftp
-
-   And now type "ftp -h" to see its command-line options, and use command
-   lines just like you would give your regular FTP client:
-   
-  ftp -n xyzcorp.com
-
-   but with additional options allowing an entire session to be specified
-   on the command line, as explained in the C-Kermit [166]FTP client
-   documentation.
-   
-   And similarly for HTTP:
-   
-  ln -s /usr/local/bin/kermit http
-  ./http -h
-  ./http www.columbia.edu -g kermit/index.html
-
-   Finally, if Kermit's first command-line option is a Telnet, FTP, IKSD,
-   or HTTP URL, Kermit automatically makes the appropriate kind of
-   connection and, if indicated by the URL, takes the desired action:
-   
-  kermit telnet:xyzcorp.com                            ; Opens a Telnet session
-  kermit telnet://olga@xyzcorp.com                     ; Ditto for user olga
-  kermit ftp://olga@xyzcorp.com/public/oofa.zip        ; Downloads a file
-  kermit kermit://kermit.columbia.edu/kermit/f/READ.ME ; Ditto for IKSD
-  kermit iksd://kermit.columbia.edu/kermit/f/READ.ME   ; (This works too)
-  kermit http://www.columbia.edu/kermit/index.html     ; Grabs a web page
-  kermit https://wwws.xyzcorp.com/secret/plan.html     ; Grabs a secure web pag
-e
-
-   [ [167]Kermit Home ] [ [168]C-Kermit Home ] [ [169]C-Kermit FAQ ]
-    ________________________________________________________________________
-  
-  LICENSE [ [170]Top ] [ [171]Contents ] [ [172]Next ] [ [173]Previous ]
-  
-   C-Kermit has an unusual license, but a fair and sensible one given
-   that the Kermit Project must support itself out of revenue: it's not a
-   BSD license, not GPL, not Artistic, not commercial, not shareware, not
-   freeware. It can be summed up like this: if you want C-Kermit for your
-   own use, you can download and use it without cost or license (but we'd
-   appreciate it if you would purchase the manual). But if you want to
-   sell C-Kermit or bundle it with a product or otherwise distribute it
-   in a commercial setting EXCEPT WITH AN OPEN-SOURCE OPERATING SYSTEM
-   DISTRIBUTION such as Linux, FreeBSD, NetBSD, or OpenBSD, you must
-   license it. To see the complete license, give the LICENSE command at
-   the prompt, or see the COPYING.TXT file distributed with C-Kermit 7.0
-   or later, or download it from
-   [174]ftp://kermit.columbia.edu/kermit/c-kermit/COPYING.TXT. Send
-   licensing inquiries to [175]kermit@columbia.edu.
-   
-   [ [176]Kermit Home ] [ [177]C-Kermit Home ] [ [178]C-Kermit FAQ ]
-    ________________________________________________________________________
-  
-  OTHER TOPICS [ [179]Top ] [ [180]Contents ] [ [181]Next ] [ [182]Previous ]
-  
-   There's way more to C-Kermit than we've touched on here --
-   troubleshooting, customization, character sets, dialing directories,
-   sending pages, script writing, and on and on, all of which are covered
-   in the manual and updates and supplements. For the most up-to-date
-   information on documentation (or updated documentation itself) visit
-   the Kermit Project website:
-   
-  [183]http://www.columbia.edu/kermit/
-
-   There you will also find [184]Kermit software packages for other
-   platforms: different Unix varieties, Windows, DOS, VMS, IBM
-   mainframes, and many others: 20+ years' worth.
-   
-   [ [185]Kermit Home ] [ [186]C-Kermit Home ] [ [187]C-Kermit FAQ ]
-    ________________________________________________________________________
-  
-  DOCUMENTATION AND UPDATES [ [188]Top ] [ [189]Contents ] [ [190]Next ] [
-  [191]Previous ]
-  
-   The manual for C-Kermit is:
-   
-    1. Frank da Cruz and Christine M. Gianone, [192]Using C-Kermit,
-       Second Edition, Digital Press / Butterworth-Heinemann, Woburn, MA,
-       1997, 622 pages, ISBN 1-55558-164-1. This is a printed book. It
-       covers C-Kermit 6.0.
-    2. The C-Kermit 7.0 Supplement:
-       [193]http://www.columbia.edu/kermit/ckermit70.html
-    3. The C-Kermit 8.0 Supplement:
-       [194]http://www.columbia.edu/kermit/ckermit80.html
-       
-   The C-Kermit home page is here:
-   
-  [195]http://www.columbia.edu/kermit/ckermit.html
-
-   Visit this page to learn about new versions, Beta tests, and other
-   news; to read case studies and tutorials; to download source code,
-   install packages, and [196]prebuilt binaries for many platforms. Also
-   visit:
-   
-   [197]http://www.columbia.edu/kermit/scriptlib.html
-          The Kermit script library and tutorial
-          
-   [198]http://www.columbia.edu/kermit/newfaq.html
-          The Kermit FAQ (Frequently Asked Questions about Kermit)
-          
-   [199]http://www.columbia.edu/kermit/ckfaq.html
-          The C-Kermit FAQ (Frequently Asked Questions about C-Kermit)
-          
-   [200]http://www.columbia.edu/kermit/security.html
-          The Kermit security reference.
-          
-   [201]http://www.columbia.edu/kermit/telnet.html
-          C-Kermit Telnet client documentation.
-          
-   [202]http://www.columbia.edu/kermit/studies.html
-          Case studies.
-          
-   [203]http://www.columbia.edu/kermit/ckcbwr.html
-          General C-Kermit Hints and Tips.
-          
-   [204]http://www.columbia.edu/kermit/ckubwr.html
-          Unix C-Kermit Hints and Tips.
-          
-   [205]http://www.columbia.edu/kermit/ckvbwr.html
-          VMS C-Kermit Hints and Tips.
-          
-   [206]http://www.columbia.edu/kermit/ckuins.html
-          Unix C-Kermit Installation Instructions
-          
-   [207]http://www.columbia.edu/kermit/ckvins.html
-          VMS C-Kermit Installation Instructions
-          
-   [208]http://www.columbia.edu/kermit/support.html
-          Technical support.
-          
-   [209]http://www.columbia.edu/kermit/k95tutorial.html
-          Kermit 95 tutorial (this document).
-          
-   [210]comp.protocols.kermit.misc
-          The Kermit newsgroup (unmoderated).
-          
-   [ [211]Kermit Home ] [ [212]C-Kermit Home ] [ [213]C-Kermit FAQ ]
-    ________________________________________________________________________
-  
-  FILES [ [214]Top ] [ [215]Contents ] [ [216]Next ] [ [217]Previous ]
-  
-   [218]COPYING.TXT
-          C-Kermit license.
-          
-   [219]~/.kermrc
-          Initialization file.
-          
-   [220]~/.mykermrc
-          Customization file.
-          
-   ~/.kdd
-          Kermit dialing directory (see manual).
-          
-   ~/.knd
-          Kermit network directory (see manual).
-          
-   ~/.ksd
-          Kermit services directory (see manual).
-          
-   [221]ckuins.html
-          Installation instructions for Unix.
-          
-   [222]ckcbwr.html
-          General C-Kermit bugs, hints, tips.
-          
-   [223]ckubwr.html
-          Unix-specific C-Kermit bugs, hints, tips.
-          
-   [224]ckcplm.html
-          C-Kermit program logic manual.
-          
-   [225]ckccfg.html
-          C-Kermit compile-time configuration options.
-          
-   ssh
-          (in your PATH) SSH connection helper.
-          
-   rz, sz, etc.
-          (in your PATH) external protocols for XYZmodem.
-          
-   /var/spool/locks (or whatever)
-          UUCP lockfile for dialing out (see [226]installation
-          instructions).
-          
-   [ [227]Kermit Home ] [ [228]C-Kermit Home ] [ [229]C-Kermit FAQ ]
-    ________________________________________________________________________
-  
-  AUTHORS [ [230]Top ] [ [231]Contents ] [ [232]Previous ]
-  
-     Frank da Cruz and Jeffrey E Altman
-     The Kermit Project - Columbia Univerity
-     612 West 115th Street
-     New York NY 10025-7799
-     USA
-     
-   1985-present, with contributions from hundreds of others all over the
-   world.
-     _________________________________________________________________
-   
-   
-    C-Kermit 8.0 Unix Manual Page and Tutorial /
-    [233]kermit@columbia.edu / 24 October 2002
-
-References
-
-   1. http://www.columbia.edu/kermit/
-   2. http://www.columbia.edu/
-   3. http://www.columbia.edu/kermit/ckututor.pdf
-   4. ftp://kermit.columbia.edu/kermit/test/text/ckuker.nr
-   5. http://www.columbia.edu/kermit/ckututor.html#description
-   6. http://www.columbia.edu/kermit/ckututor.html#synopsis
-   7. http://www.columbia.edu/kermit/ckututor.html#options
-   8. http://www.columbia.edu/kermit/ckututor.html#commands
-   9. http://www.columbia.edu/kermit/ckututor.html#initfile
-  10. http://www.columbia.edu/kermit/ckututor.html#modes
-  11. http://www.columbia.edu/kermit/ckututor.html#connections
-  12. http://www.columbia.edu/kermit/ckututor.html#transfer
-  13. http://www.columbia.edu/kermit/ckututor.html#server
-  14. http://www.columbia.edu/kermit/ckututor.html#ftp
-  15. http://www.columbia.edu/kermit/ckututor.html#iksd
-  16. http://www.columbia.edu/kermit/ckututor.html#security
-  17. http://www.columbia.edu/kermit/ckututor.html#personae
-  18. http://www.columbia.edu/kermit/ckututor.html#license
-  19. http://www.columbia.edu/kermit/ckututor.html#other
-  20. http://www.columbia.edu/kermit/ckututor.html#documentation
-  21. http://www.columbia.edu/kermit/ckututor.html#files
-  22. http://www.columbia.edu/kermit/ckututor.html#authors
-  23. http://www.columbia.edu/kermit/ckututor.html#top
-  24. http://www.columbia.edu/kermit/ckututor.html#contents
-  25. http://www.columbia.edu/kermit/ckututor.html#synopsis
-  26. http://www.columbia.edu/kermit/ckermit.html
-  27. http://www.columbia.edu/kermit/
-  28. http://www.columbia.edu/
-  29. ftp://ftp.isi.edu/in-notes/rfc2839.txt
-  30. ftp://ftp.isi.edu/in-notes/rfc2840.txt
-  31. http://www.columbia.edu/kermit/ckututor.html#documentation
-  32. http://www.columbia.edu/kermit/
-  33. http://www.columbia.edu/kermit/
-  34. http://www.columbia.edu/kermit/ckermit.html
-  35. http://www.columbia.edu/kermit/ckfaq.html
-  36. http://www.columbia.edu/kermit/ckututor.html#top
-  37. http://www.columbia.edu/kermit/ckututor.html#contents
-  38. http://www.columbia.edu/kermit/ckututor.html#options
-  39. http://www.columbia.edu/kermit/ckututor.html#synopsis
-  40. http://www.columbia.edu/kermit/ckututor.html#kerbang
-  41. http://www.columbia.edu/kermit/ckututor.html#personae
-  42. http://www.columbia.edu/kermit/ckututor.html#kerbang
-  43. http://www.columbia.edu/kermit/ckututor.html#initfile
-  44. http://www.columbia.edu/kermit/ckututor.html#initfile
-  45. http://www.columbia.edu/kermit/ckututor.html#personae
-  46. http://www.columbia.edu/kermit/ckututor.html#options
-  47. http://www.columbia.edu/kermit/ckututor.html#commands
-  48. http://www.columbia.edu/kermit/
-  49. http://www.columbia.edu/kermit/ckermit.html
-  50. http://www.columbia.edu/kermit/ckfaq.html
-  51. http://www.columbia.edu/kermit/ckututor.html#top
-  52. http://www.columbia.edu/kermit/ckututor.html#contents
-  53. http://www.columbia.edu/kermit/ckututor.html#commands
-  54. http://www.columbia.edu/kermit/ckututor.html#description
-  55. http://www.columbia.edu/kermit/ckututor.html#commands
-  56. http://www.columbia.edu/kermit/ckututor.html#personae
-  57. http://www.columbia.edu/kermit/ckututor.html#personae
-  58. http://www.columbia.edu/kermit/ckututor.html#iksd
-  59. http://www.columbia.edu/kermit/ckututor.html#transfer
-  60. http://www.columbia.edu/kermit/ckututor.html#top
-  61. http://www.columbia.edu/kermit/ckututor.html#contents
-  62. http://www.columbia.edu/kermit/ckututor.html#initfile
-  63. http://www.columbia.edu/kermit/ckututor.html#options
-  64. http://www.columbia.edu/kermit/ckututor.html#kerbang
-  65. http://www.columbia.edu/kermit/ckututor.html#cmdlist
-  66. http://www.columbia.edu/kermit/ckututor.html#documentation
-  67. http://www.columbia.edu/kermit/ckututor.html#initfile
-  68. http://www.columbia.edu/kermit/ckututor.html#documentation
-  69. http://www.columbia.edu/kermit/ckscripts.html
-  70. http://www.columbia.edu/kermit/ckututor.html#documentation
-  71. http://www.columbia.edu/kermit/
-  72. http://www.columbia.edu/kermit/ckermit.html
-  73. http://www.columbia.edu/kermit/ckfaq.html
-  74. http://www.columbia.edu/kermit/ckututor.html#top
-  75. http://www.columbia.edu/kermit/ckututor.html#contents
-  76. http://www.columbia.edu/kermit/ckututor.html#modes
-  77. http://www.columbia.edu/kermit/ckututor.html#commands
-  78. http://www.columbia.edu/kermit/
-  79. http://www.columbia.edu/kermit/ckermit.html
-  80. http://www.columbia.edu/kermit/ckfaq.html
-  81. http://www.columbia.edu/kermit/ckututor.html#top
-  82. http://www.columbia.edu/kermit/ckututor.html#contents
-  83. http://www.columbia.edu/kermit/ckututor.html#connections
-  84. http://www.columbia.edu/kermit/ckututor.html#initfile
-  85. http://www.columbia.edu/kermit/ckfaq.html#term
-  86. http://www.columbia.edu/kermit/
-  87. http://www.columbia.edu/kermit/ckermit.html
-  88. http://www.columbia.edu/kermit/ckfaq.html
-  89. http://www.columbia.edu/kermit/ckututor.html#top
-  90. http://www.columbia.edu/kermit/ckututor.html#contents
-  91. http://www.columbia.edu/kermit/ckututor.html#transfer
-  92. http://www.columbia.edu/kermit/ckututor.html#modes
-  93. http://www.columbia.edu/kermit/ckututor.html#iksd
-  94. ftp://ftp.isi.edu/in-notes/rfc2217.txt
-  95. http://www.columbia.edu/kermit/ckututor.html#ftp
-  96. http://www.columbia.edu/kermit/
-  97. http://www.columbia.edu/kermit/ckermit.html
-  98. http://www.columbia.edu/kermit/ckfaq.html
-  99. http://www.columbia.edu/kermit/ckututor.html#top
- 100. http://www.columbia.edu/kermit/ckututor.html#contents
- 101. http://www.columbia.edu/kermit/ckututor.html#server
- 102. http://www.columbia.edu/kermit/ckututor.html#connections
- 103. http://www.columbia.edu/kermit/ckututor.html#download
- 104. http://www.columbia.edu/kermit/ckututor.html#upload
- 105. http://www.columbia.edu/kermit/ckututor.html#oldfashioned
- 106. http://www.columbia.edu/kermit/ckututor.html#trouble
- 107. http://www.columbia.edu/kermit/ckututor.html#advanced
- 108. http://www.columbia.edu/kermit/ckututor.html#nonkermit
- 109. http://www.columbia.edu/kermit/kermit.html#notslow
- 110. http://www.columbia.edu/kermit/ckermit.html
- 111. http://www.columbia.edu/kermit/k95.html
- 112. http://www.columbia.edu/kermit/k95.html
- 113. http://www.columbia.edu/kermit/ckermit.html
- 114. http://www.columbia.edu/kermit/mskermit.html
- 115. http://www.columbia.edu/kermit/
- 116. http://www.columbia.edu/kermit/support.html
- 117. http://www.columbia.edu/kermit/ckmanual.html
- 118. mailto:kermit-support@columbia.edu
- 119. http://www.columbia.edu/kermit/ckututor.html#documentation
- 120. http://www.columbia.edu/kermit/ckututor.html#ftp
- 121. http://www.columbia.edu/kermit/
- 122. http://www.columbia.edu/kermit/ckermit.html
- 123. http://www.columbia.edu/kermit/ckfaq.html
- 124. http://www.columbia.edu/kermit/ckututor.html#top
- 125. http://www.columbia.edu/kermit/ckututor.html#contents
- 126. http://www.columbia.edu/kermit/ckututor.html#ftp
- 127. http://www.columbia.edu/kermit/ckututor.html#transfer
- 128. http://www.columbia.edu/kermit/ckututor.html#iksd
- 129. http://www.columbia.edu/kermit/
- 130. http://www.columbia.edu/kermit/ckermit.html
- 131. http://www.columbia.edu/kermit/ckfaq.html
- 132. http://www.columbia.edu/kermit/ckututor.html#top
- 133. http://www.columbia.edu/kermit/ckututor.html#contents
- 134. http://www.columbia.edu/kermit/ckututor.html#iksd
- 135. http://www.columbia.edu/kermit/ckututor.html#transfer
- 136. http://www.columbia.edu/kermit/ckututor.html#server
- 137. http://www.columbia.edu/kermit/ftpclient.html
- 138. http://www.columbia.edu/kermit/ckututor.html#documentation
- 139. http://www.columbia.edu/kermit/
- 140. http://www.columbia.edu/kermit/ckermit.html
- 141. http://www.columbia.edu/kermit/ckfaq.html
- 142. http://www.columbia.edu/kermit/ckermit3.html#x3
- 143. http://www.columbia.edu/kermit/ckermit3.html#x2.2
- 144. http://www.columbia.edu/kermit/ckututor.html#top
- 145. http://www.columbia.edu/kermit/ckututor.html#contents
- 146. http://www.columbia.edu/kermit/ckututor.html#security
- 147. http://www.columbia.edu/kermit/ckututor.html#ftp
- 148. http://www.columbia.edu/kermit/cuiksd.html
- 149. http://www.columbia.edu/kermit/iksd.html
- 150. http://www.columbia.edu/kermit/
- 151. http://www.columbia.edu/kermit/ckermit.html
- 152. http://www.columbia.edu/kermit/ckfaq.html
- 153. http://www.columbia.edu/kermit/ckututor.html#top
- 154. http://www.columbia.edu/kermit/ckututor.html#contents
- 155. http://www.columbia.edu/kermit/ckututor.html#personae
- 156. http://www.columbia.edu/kermit/ckututor.html#iksd
- 157. http://www.columbia.edu/kermit/security.html
- 158. http://www.columbia.edu/kermit/
- 159. http://www.columbia.edu/kermit/ckermit.html
- 160. http://www.columbia.edu/kermit/ckfaq.html
- 161. http://www.columbia.edu/kermit/ckututor.html#top
- 162. http://www.columbia.edu/kermit/ckututor.html#contents
- 163. http://www.columbia.edu/kermit/ckututor.html#license
- 164. http://www.columbia.edu/kermit/ckututor.html#iksd
- 165. http://www.columbia.edu/kermit/ckututor.html#options
- 166. http://www.columbia.edu/kermit/ckermit3.html#x3.1.2
- 167. http://www.columbia.edu/kermit/
- 168. http://www.columbia.edu/kermit/ckermit.html
- 169. http://www.columbia.edu/kermit/ckfaq.html
- 170. http://www.columbia.edu/kermit/ckututor.html#top
- 171. http://www.columbia.edu/kermit/ckututor.html#contents
- 172. http://www.columbia.edu/kermit/ckututor.html#other
- 173. http://www.columbia.edu/kermit/ckututor.html#personae
- 174. ftp://kermit.columbia.edu/kermit/c-kermit/COPYING.TXT
- 175. mailto:kermit@columbia.edu
- 176. http://www.columbia.edu/kermit/
- 177. http://www.columbia.edu/kermit/ckermit.html
- 178. http://www.columbia.edu/kermit/ckfaq.html
- 179. http://www.columbia.edu/kermit/ckututor.html#top
- 180. http://www.columbia.edu/kermit/ckututor.html#contents
- 181. http://www.columbia.edu/kermit/ckututor.html#documentation
- 182. http://www.columbia.edu/kermit/ckututor.html#license
- 183. http://www.columbia.edu/kermit/
- 184. http://www.columbia.edu/kermit/howtoget.html
- 185. http://www.columbia.edu/kermit/
- 186. http://www.columbia.edu/kermit/ckermit.html
- 187. http://www.columbia.edu/kermit/ckfaq.html
- 188. http://www.columbia.edu/kermit/ckututor.html#top
- 189. http://www.columbia.edu/kermit/ckututor.html#contents
- 190. http://www.columbia.edu/kermit/ckututor.html#files
- 191. http://www.columbia.edu/kermit/ckututor.html#other
- 192. http://www.columbia.edu/kermit/ckmanual.html
- 193. http://www.columbia.edu/kermit/ckermit70.html
- 194. http://www.columbia.edu/kermit/ckermit80.html
- 195. http://www.columbia.edu/kermit/ckermit.html
- 196. http://www.columbia.edu/kermit/ck80binaries.html
- 197. http://www.columbia.edu/kermit/scriptlib.html
- 198. http://www.columbia.edu/kermit/newfaq.html
- 199. http://www.columbia.edu/kermit/ckfaq.html
- 200. http://www.columbia.edu/kermit/security.html
- 201. http://www.columbia.edu/kermit/telnet.html
- 202. http://www.columbia.edu/kermit/studies.html
- 203. http://www.columbia.edu/kermit/ckcbwr.html
- 204. http://www.columbia.edu/kermit/ckubwr.html
- 205. http://www.columbia.edu/kermit/ckvbwr.html
- 206. http://www.columbia.edu/kermit/ckuins.html
- 207. http://www.columbia.edu/kermit/ckvins.html
- 208. http://www.columbia.edu/kermit/support.html
- 209. http://www.columbia.edu/kermit/k95tutorial.html
- 210. news:comp.protocols.kermit.misc
- 211. http://www.columbia.edu/kermit/
- 212. http://www.columbia.edu/kermit/ckermit.html
- 213. http://www.columbia.edu/kermit/ckfaq.html
- 214. http://www.columbia.edu/kermit/ckututor.html#top
- 215. http://www.columbia.edu/kermit/ckututor.html#contents
- 216. http://www.columbia.edu/kermit/ckututor.html#authors
- 217. http://www.columbia.edu/kermit/ckututor.html#documentation
- 218. ftp://kermit.columbia.edu/kermit/c-kermit/COPYING.TXT
- 219. ftp://kermit.columbia.edu/kermit/c-kermit/ckermit.ini
- 220. ftp://kermit.columbia.edu/kermit/c-kermit/ckermod.ini
- 221. http://www.columbia.edu/kermit/ckuins.html
- 222. http://www.columbia.edu/kermit/ckcbwr.html
- 223. http://www.columbia.edu/kermit/ckubwr.html
- 224. http://www.columbia.edu/kermit/ckcplm.html
- 225. http://www.columbia.edu/kermit/ckccfg.html
- 226. http://www.columbia.edu/kermit/ckuins.html
- 227. http://www.columbia.edu/kermit/
- 228. http://www.columbia.edu/kermit/ckermit.html
- 229. http://www.columbia.edu/kermit/ckfaq.html
- 230. http://www.columbia.edu/kermit/ckututor.html#top
- 231. http://www.columbia.edu/kermit/ckututor.html#contents
- 232. http://www.columbia.edu/kermit/ckututor.html#files
- 233. mailto:kermit@columbia.edu
index 1290763..b0dfb30 100644 (file)
--- a/ckuus2.c
+++ b/ckuus2.c
@@ -11,7 +11,7 @@
     Jeffrey E Altman <jaltman@secure-endpoints.com>
       Secure Endpoints Inc., New York City
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2011,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
 
   IMPORTANT: Character string constants longer than about 250 are not portable.
   Longer strings should be broken up into arrays of strings and accessed with
-  hmsga() rather than hmsg().
+  hmsga() rather than hmsg().  (This statement was true in the 1980s and
+  probably is not a big concern in the 21st Century, but you never know;
+  there still might exist some 16-bit platforms and C compilers that have
+  restrictions like this.
 */
 #include "ckcsym.h"
 #include "ckcdeb.h"
@@ -47,6 +50,8 @@
 #include "ckokey.h"
 #endif /* OS2 */
 
+extern char * ck_cryear;               /* For copyright notice */
+
 extern xx_strp xxstring;
 extern char * ccntab[];
 /*
@@ -144,12 +149,11 @@ static char *tophlp[] = {
 #ifndef OS2
 #ifdef MAC
 "Documentation for Command Window: \"Using C-Kermit\" by Frank da Cruz and",
-"Christine M. Gianone, Digital Press, 1997, ISBN: 1-55558-164-1.  To order,",
-"call +1 212 854-3703 or +1 800 366-2665.",
+"Christine M. Gianone, Digital Press, 1997, ISBN: 1-55558-164-1",
 #else
 "DOCUMENTATION: \"Using C-Kermit\" by Frank da Cruz and Christine M. Gianone,",
 "2nd Edition, Digital Press / Butterworth-Heinemann 1997, ISBN 1-55558-164-1,",
-"plus supplements at http://www.columbia.edu/kermit/ckermit.html.",
+"plus supplements at http://kermit.columbia.edu/ckermit.html#doc.",
 #endif /* MAC */
 #endif /* OS2 */
 #ifdef MAC
@@ -182,10 +186,8 @@ static char *tophlpi[] = {              /* Top-level help for IKSD */
 #endif /* NOHELP */
 " ",
 "DOCUMENTATION: \"Using C-Kermit\" by Frank da Cruz and Christine M. Gianone,",
-"2nd Edition, Digital Press / Butterworth-Heinemann 1997, ISBN 1-55558-164-1.",
-"To order: +1 212 854-3703 or +1 800 366-2665.  More info at the Kermit",
-
-"Project website, http://www.columbia.edu/kermit/.",
+"2nd Edition, Digital Press (1997), ISBN 1-55558-164-1.  More info at the",
+"Kermit Project website, http://kermit.columbia.edu/.",
 ""
 };
 #endif /* NOIKSD */
@@ -193,52 +195,45 @@ static char *tophlpi[] = {              /* Top-level help for IKSD */
 #ifndef NOHELP
 char *newstxt[] = {
 #ifdef OS2
-"Welcome to Kermit 95 2.1.3.  Major new features include:",
+"Welcome to Kermit 95 3.x.x.  Major new features since 2.1.3 include:",
 #else
-"Welcome to C-Kermit 8.0.206.  Major new features include:",
-#endif /* OS2 */
-#ifdef NT
-#ifdef KUI
-" . Runs in GUI window",
-#else
-" . GUI version available",
-#endif /* KUI */
-#endif /* NT */
-#ifdef SSHBUILTIN
-" . New built-in SSH v1 and v2 clients",
-#endif /* SSHBUILTIN */
-#ifdef NEWFTP
-" . A new built-in FTP client",
-#endif /* NEWFTP */
-#ifndef NOHTTP
-" . A new HTTP 1.1 client",
-#endif /* NOHTTP */
-#ifdef TN_COMPORT
-" . Telnet Com Port Option for dialing from Telnet modem servers",
-#endif /* TN_COMPORT */
-" . File scanning for automatic text/binary determination",
-#ifdef CKLEARN
-#ifndef OS2
-" . Learned scripts",
+"Welcome to C-Kermit 9.0.299.  New features since 8.0.211 include:",
 #endif /* OS2 */
-#endif /* CKLEARN */
-#ifndef NOSPL
-#ifndef NOSEXP
-" . LISP-like S-Expressions and natural floating-point arithmetic",
-#endif /* NOSEXP */
-" . Lots of script programming improvements",
-#endif /* NOSPL */
-" . Performance improvements and bug fixes",
+" . Open Source Simplified 3-Clause BSD License",
+" . Full 64-bit memory model on platforms that support it",
+" . Large file support (64-bit file size) on most platforms",
+" . Long integer variables and constants in commands and scripts",
+" . Bigger maximum command and macro lengths",
+" . Bigger filename expansion space",
+" . New super-flexible RENAME command",
+" . New COPY and DIRECTORY command options",
+" . New TOUCH command",
+" . Raw SSL/TLS connections for connecting to POP3 and similar services",
+" . At prompt, Ctrl-K recalls most recent filename",
+" . Scripting and performance improvements and bug fixes",
 " ",
 "Documentation:",
-" 1. \"Using C-Kermit\", second edition (1997), current with C-Kermit 6.0.",
-" 2. http://www.columbia.edu/kermit/ckermit70.html",
+" 1. http://kermit.columbia.edu/usingckermit.html",
+"    \"Using C-Kermit\", second edition (1997), current with C-Kermit 6.0.",
+" ",
+" 2. http://kermit.columbia.edu/ckermit70.html",
 "    which documents the new features of C-Kermit 7.0.",
-" 3. http://www.columbia.edu/kermit/ckermit80.html",
+" ",
+" 3. http://kermit.columbia.edu/ckermit80.html",
 "    which documents the new features of C-Kermit 8.0.",
 " ",
+" 4. http://kermit.columbia.edu/ckermit90.html",
+"    which documents the new features of C-Kermit 9.0.",
+" ",
 "If the release date shown by the VERSION command is long past, be sure to",
-"check with the Kermit Project to see if there have been updates.",
+"check with the Kermit website to see if there have been updates:",
+" ",
+#ifdef OS2
+"  http://kermit.columbia.edu/k95.html     (Kermit 95 home page)",
+#else
+"  http://kermit.columbia.edu/ckermit.html (C-Kermit home page)",
+#endif /* OS2 */
+"  http://kermit.columbia.edu/             (Kermit Project home page)",
 ""
 };
 #endif /* NOHELP */
@@ -366,10 +361,13 @@ char *introtxt[] = {
 " . CTRL-B:      Command recall - same as Ctrl-P.",
 " . CTRL-N:      Command recall - go forward in command recall buffer.",
 #endif /* CK_RECALL */
+#ifndef NOLASTFILE
+" . CTRL-K:      Insert the most recently entered local file specifiction.",
+#endif /* NOLASTFILE */
 
 " . ?            (question mark) Display a menu for the current command field."
 ,
-" . ESC          (or TAB) Attempt to complete the current field.",
+" . ESC          (or TAB or Ctrl-I) Attempt to complete the current field.",
 " . \\            (backslash) include the following character literally",
 #ifndef NOSPL
 "                or introduce a backslash code, variable, or function.",
@@ -536,27 +534,31 @@ Press the key or key-combination shown after \"Command:\" in the status line",
 "  SHOW COMMUNICATIONS, SHOW FILE, SHOW PROTOCOL, etc.",
 #endif /* NOLOCAL */
 " ",
+"The manual for C-Kermit is the book \"Using C-Kermit\".  For information",
+"about the manual, visit:",
+"  http://kermit.columbia.edu/usingckermit.html",
+" ",
 #ifdef OS2
 "For a Kermit 95 tutorial, visit:",
-"  http://www.columbia.edu/kermit/k95tutor.html",
+"  http://kermit.columbia.edu/k95tutor.html",
 " ",
 #endif /* OS2 */
-"For a C-Kermit tutorial, visit:",
-"  http://www.columbia.edu/kermit/ckututor.html",
+"For an online C-Kermit tutorial, visit:",
+"  http://kermit.columbia.edu/ckututor.html",
 " ",
 "To learn about script programming and automation:",
-"  Read the manual, \"Using C-Kermit\".  For a brief tutorial, visit:",
-"  http://www.columbia.edu/kermit/ckscripts.html",
+"  http://kermit.columbia.edu/ckscripts.html",
 " ",
 "For further information about a particular command, type HELP xxx,",
 "where xxx is the name of the command.  For documentation, news of new",
-"releases, and information about other Kermit software, contact:",
+"releases, and information about other Kermit software, visit the",
+"Kermit Project website:",
 " ",
-"  The Kermit Project         E-mail: kermit@columbia.edu",
-"  Columbia University        Web:    http://www.columbia.edu/kermit/",
-"  612 West 115th Street      Voice:  +1 (212) 854-3703",
-"  New York NY  10025-7799    Fax:    +1 (212) 662-6442",
-"  USA",
+"  http://kermit.columbia.edu/",
+" ",
+"For information about technical support please visit this page:",
+" ",
+"  http://kermit.columbia.edu/support.html",
 ""
 };
 
@@ -568,9 +570,29 @@ static char * hmxymatch[] = {
 ""
 };
 
+#ifndef NOSEXP
+static char * hmxysexp[] = {
+"SET SEXPRESSION { DEPTH-LIMIT, ECHO-RESULT, TRUNCATE-ALL-RESULTS }",
+"  DEPTH-LIMIT sets a limit on the depth of nesting or recursion in",
+"  S-Expressions to prevent the program from crashing from memory exhaustion.",
+"  ECHO-RESULT tells whether S-Expression results should be displayed as",
+"  a result of evaluating an expression; the default is to display only at",
+"  top (interactive) level; OFF means never display; ON means always display.",
+"  TRUNCATE-ALL-RESULTS ON means the results of all arithmetic operations",
+"  should be forced to integers (whole numbers) by discarding any fractional",
+"  part.  The default is OFF.  SHOW SEXPRESSION displays the current settings."
+,""
+};
+#endif /* NOSEXP */
+
 #ifdef OS2
 #ifdef KUI
 static char * hmxygui[] = {
+"SET GUI CLOSE OFF",
+"  Disables the System Menu Close and File->Exit functions which could be",
+"  used to exit Kermit.  Once disabled these functions cannot be re-enabled",
+"  and the only way to exit Kermit is via the Kermit Script EXIT command.",
+" ",
 "SET GUI DIALOGS { ON, OFF }",
 "  ON means that popups, alerts, use GUI dialogs; OFF means to use",
 "  text-mode popups or prompts.  ON by default.",
@@ -580,11 +602,21 @@ static char * hmxygui[] = {
 "  choices.  The size can be a whole number or can contain a decimal point",
 "  and a fraction (which is rounded to the nearest half point).",
 " ",
+"SET GUI MENUBAR OFF",
+"  Disables menubar functions which could be used to modify the Kermit",
+"  session configuration.  Once disabled the menubar functions cannot be",
+"  re-enabled.", 
+" ",
 "SET GUI RGBCOLOR colorname redvalue greenvalue bluevalue",
 "  Specifies the red-green-blue mixture to be used to render the given",
 "  color name.  Type \"set gui rgbcolor\" to see a list of colornames.",
 "  the RGB values are whole numbers from 0 to 255.",
 " ",
+"SET GUI TOOLBAR OFF", 
+"  Disables toolbar functions which could be used to modify the Kermit",
+"  session configuration.  Once disabled the toolbar functions cannot be",
+"  re-enabled.", 
+" ",
 "SET GUI WINDOW POSITION x y",
 "  Moves the K95 window to the given X,Y coordinates, pixels from top left.",
 "  (Not yet implemented -- use command-line options to do this.)",
@@ -940,6 +972,31 @@ static char *hmxylocus[] = {
 };
 #endif /* LOCUS */
 
+#ifdef UNIX
+#ifndef NOPUTENV
+static char *hmxxputenv[] = {
+"Syntax: PUTENV name value",
+"  Creates or modifies the environment variable with the given name to have",
+"  the given value.  Purpose: to pass parameters to subprocesses without",
+"  having them appear on the command line.  If the value is blank (empty),",
+"  the variable is deleted.  The result is visible to this instantiation of",
+"  C-Kermit via \\$(name) and to any inferior processes by whatever method",
+"  they use to access environment variables.  The value may be enclosed in",
+"  doublequotes or braces, but it need not be; if it is the outermost",
+"  doublequotes or braces are removed.",
+" ",
+"  Note the syntax:",
+"    PUTENV name value",
+"  not:",
+"    PUTENV name=value",
+" ",
+"  There is no equal sign between name and value, and the name itself may",
+"  not include an equal sign.",
+"",
+};
+#endif /* NOPUTENV */
+#endif /* UNIX */
+
 static char *hmxxtak[] = {
 "Syntax: TAKE filename [ arguments ]",
 "  Tells Kermit to execute commands from the named file.  Optional argument",
@@ -1221,22 +1278,38 @@ static char *hmxxscrn[] = {
 
 #ifndef NOSPL
 static char *hmfword[] = {
-"\\fword(s1,n1,s2,s3,n2,n3) - Extract word from string.",
-"    s1 = source string",
-"    n1 = word number (1-based)",
+"Function \\fword(s1,n1,s2,s3,n2,n3) - Extracts a word from a string.",
+"    s1 = source string.",
+"    n1 = word number (1-based) counting from left; if negative, from right.",
 "    s2 = optional break set.",
-"    s3 = optional include set.",
+"    s3 = optional include set (or ALL, CSV, or TSV).",
 "    n2 = optional grouping mask.",
 "    n3 = optional separator flag:",
-"       0 = collapse adjacent separators",
+"       0 = collapse adjacent separators;",
 "       1 = don't collapse adjacent separators.",
 " ",
-"  Default break set is all characters except ASCII letters and digits.",
-"  ASCII (C0) control characters are always treated as break characters.",
-"  Default include set is null.",
+"  \\fword() returns the n1th \"word\" of the string s1, according to the",
+"  criteria specified by the other parameters.",
+" ",
+"  The BREAK SET is the set of all characters that separate words. The",
+"  default break set is all characters except ASCII letters and digits.",
+"  ASCII (C0) control characters are treated as break characters by default,",
+"  as are spacing and punctuation characters, brackets, and so on, and",
+"  all 8-bit characters.",
+" ",
+"  The INCLUDE SET is the set of characters that are to be treated as ",
+"  parts of words even though they normally would be separators.  The",
+"  default include set is empty.  Three special symbolic include sets are",
+"  also allowed:",
+"   ",
+"    ALL (meaning include all bytes that are not in the break set)",
+"    CSV (special treatment for Comma-Separated-Value records)",
+"    TSV (special treatment for Tab-Separated-Value records)",
 " ",
-"  If grouping mask given and nonzero, words can be grouped by quotes or",
-"  brackets selected by the sum of the following:",
+"  For operating on 8-bit character sets, the include set should be ALL.",
+" ",
+"  If the GROUPING MASK is given and is nonzero, words can be grouped by",
+"  quotes or brackets selected by the sum of the following:",
 " ",
 "     1 = doublequotes:    \"a b c\"",
 "     2 = braces:          {a b c}",
@@ -1248,7 +1321,10 @@ static char *hmfword[] = {
 "  Nesting is possible with {}()[]<> but not with quotes or apostrophes.",
 " ",
 "Returns string:",
-"  Word number n, if there is one, otherwise an empty string.",
+"  Word number n1, if there is one, otherwise an empty string.",
+" ",
+"Also see:",
+"  HELP FUNCTION SPLIT",
 ""
 };
 
@@ -1266,21 +1342,69 @@ static char *hmxxprompt[] = {
 };
 
 static char *hxxinp[] = {
-"Syntax:  INPUT [ /NOMATCH ] { number-of-seconds, time-of-day } [ text ]",
-"Example: INPUT 5 Login:  or  INPUT 23:59:59 RING",
+"Syntax:  INPUT [ /COUNT:n /CLEAR /NOMATCH /NOWRAP ] \
+{ number-of-seconds, time-of-day } [ text ]",
+" ",
+"Examples:",
+"  INPUT 5 Login:",
+"  INPUT 23:59:59 RING",
+"  INPUT /NOMATCH 10",
+"  INPUT /CLEAR 10 \\13\\10",
+"  INPUT /CLEAR 10 \\13\\10$\32",
+"  INPUT /COUNT:256 10",
+"  INPUT 10 \\fpattern(<*@*.*>)",
+" ",
 "  Waits up to the given number of seconds, or until the given time of day,",
-"  for the given text to arrive on the connection.  If no text is given,",
-"  INPUT waits for any character.  If the /NOMATCH switch is included, INPUT",
-"  does not attempt to match any characters, but continues reading from the",
-"  communication connection until the timeout interval expires.  If the",
-"  timeout interval is 0, the INPUT command does not wait; i.e. the given",
-"  text must already be available for reading for the INPUT command to",
-"  succeed.  If the interval is negative, the INPUT command waits forever.",
-"  For use in script programs with IF FAILURE and IF SUCCESS.  Also see",
-"  MINPUT, REINPUT, SET INPUT.  See HELP PAUSE for details on time-of-day",
-"  format.  The text, if given, can be a \\pattern() invocation, in which",
-"  case it is treated as a pattern rather than a literal string (HELP",
-"  PATTERNS for details).",
+"  for the given text to arrive on the connection. For use in script programs",
+"  with IF FAILURE or IF SUCCESS, which tell whether the desired text arrived",
+"  within the given amount of time.",
+" ",
+"  The text, if given, can be a regular text or it can be a \\pattern()",
+"  invocation, in which case it is treated as a pattern rather than a literal",
+"  string (HELP PATTERNS for details).",
+" ",
+"  If the /COUNT: switch is included, INPUT waits for the given number of",
+"  characters to arrive.",
+" ",
+"  If no text is specified, INPUT waits for the first character that arrives",
+"  and makes it available in the \\v(inchar) variable.  This is equivalent to",
+"  including a /COUNT: switch with an argument of 1.",
+" ",
+"  If the /NOMATCH switch is included, INPUT does not attempt to match any",
+"  characters, but continues reading from the communication connection until",
+"  the timeout interval expires.  If the timeout interval is 0, the INPUT",
+"  command does not wait; i.e. the given text must already be available for",
+"  reading for the INPUT command to succeed.  If the interval is negative,",
+"  the INPUT command waits forever.",
+" ",
+"  The INPUT buffer, \\v(input), is normally circular.  Incoming material is",
+"  appended to it until it reaches the end, and then it wraps around to the",
+"  beginning.  If the /CLEAR switch is given, INPUT clears its buffer before",
+"  reading from the connection.",
+" ",
+"  Typical example of use:",
+" ",
+"    INPUT 10 login:",
+"    IF FAIL EXIT 1 \"Timed out waiting for login prompt\"",
+"    LINEOUT myuserid",
+"    INPUT 10 Password:",
+"    IF FAIL EXIT 1 \"Timed out waiting for Password prompt\"",
+"    LINEOUT xxxxxxx",
+" ",
+"  The /NOWRAP switch means that INPUT should return with failure status",
+"  and with \\v(instatus) set to 6 if its internal buffer fills up before",
+"  any of the other completion criteria are met.  This allows for capture",
+"  of the complete incoming data stream (except NUL bytes, which are",
+"  discarded).  CAUTION: if the search target (if any) spans the INPUT buffer",
+"  boundary, INPUT will not succeed.",
+" ",
+"  \
+\\v(instatus) values are: 0 (success), 1 (timed out), 2 (keyboard interrupt),",
+"  3 (internal error), 4 (I/O error or connection lost), 5 (INPUT disabled),",
+"  and 6 (buffer filled and /NOWRAP set); these are shown by \\v(inmessage).",
+" ",
+"  Also see OUTPUT, MINPUT, REINPUT, SET INPUT and CLEAR.  See HELP PAUSE for",
+"  details on time-of-day format and HELP PATTERNS for pattern syntax.",
 ""};
 
 static char *hxxout[] = {
@@ -1427,7 +1551,7 @@ static char *hxyxyz[] = {
 "Syntax: SET PROTOCOL { KERMIT, XMODEM, YMODEM, ZMODEM } [ s1 s2 [ s3 ] ]",
 "  Selects protocol to use for transferring files.  String s1 is a command to",
 "  send to the remote host prior to SENDing files with this protocol in",
-"  binary mode; string s2 is the same thing but for text mode.  Use \"%\" in",
+"  binary mode; string s2 is the same thing but for text mode.  Use \"%s\" in",
 "  any of these strings to represent the filename(s).  If the protocol is",
 "  KERMIT, you may also specify a string s3, the command to start a Kermit",
 "  server on the remote host when you give a GET, REGET, REMOTE, or other",
@@ -1573,6 +1697,9 @@ static char *hmxxsexp[] = {
 "  nil       False (empty)",
 "  pi        The value of Pi (3.1415926...)",
 " ",
+"If SET SEXPRESSION TRUNCATE-ALL-RESULTS is ON, all results are trunctated",
+"to integer values by discarding any fractional part.  Otherwise results",
+"are floating-point if there fractional part and integer otherwise.",
 "If SET SEXPRESSION ECHO-RESULT is AUTO (the default), the value of the",
 "S-Expression is printed if the S-Expression is given at top level; if ON,",
 "it is printed at any level; if OFF it is not printed.  At all levels, the",
@@ -1627,6 +1754,8 @@ static char *hmxxgrep[] = {
 "    Ignores case of letters (ASCII only) when comparing.",
 "  /NOMATCH",
 "    Searches for lines that do NOT match the pattern.",
+"  /EXCEPT:pattern",
+"    Exclude lines that match the main pattern that also match this pattern.",
 " ",
 "Display options:",
 "  /COUNT:variable-name",
@@ -1675,17 +1804,20 @@ static char *hmxxdir[] = {
 "   /ARRAY:&a        Store file list in specified array (e.g. \\%a[]).",
 "   /PAGE            Pause after each screenful.",
 "   /NOPAGE          Don't pause after each screenful.",
+"   /TOP:n           Only show the top n lines of the directory listing.",
 #ifdef UNIXOROSK
 "   /DOTFILES        Include files whose names start with dot (period).",
 "   /NODOTFILES    + Don't include files whose names start with dot.",
 "   /FOLLOWLINKS     Follow symbolic links.",
 "   /NOFOLLOWLINKS + Don't follow symbolic links.",
+"   /NOLINKS         Don't list symbolic links at all.",
 "   /BACKUP        + Include backup files (names end with .~n~).",
 "   /NOBACKUPFILES   Don't include backup files.",
 #endif /* UNIXOROSK */
 "   /OUTPUT:file     Store directory listing in the given file.",
 "   /HEADING         Include heading and summary.",
 "   /NOHEADING     + Don't include heading or summary.",
+"   /COUNT:var       Put the number of matching files in the given variable.",
 "   /SUMMARY         Print only count and total size of matching files.",
 "   /XFERMODE        Show pattern-based transfer mode (T=Text, B=Binary).",
 "   /TYPE:           Show only files of the specified type (text or binary).",
@@ -1705,7 +1837,8 @@ static char *hmxxdir[] = {
 " ",
 "Factory defaults are marked with +.  Default for paging depends on SET",
 "COMMAND MORE-PROMPTING.  Use SET OPTIONS DIRECTORY [ switches ] to change",
-"defaults; use SHOW OPTIONS to display customized defaults.",
+"defaults; use SHOW OPTIONS to display customized defaults.  Also see",
+"WDIRECTORY.",
 #else
 "Syntax: DIRECTORY [ filespec ]",
 "  Lists the specified file or files.  If no filespec is given, all files",
@@ -1713,6 +1846,14 @@ static char *hmxxdir[] = {
 #endif /* DOMYDIR */
 ""};
 
+static char *hmxxtouc[] = {
+"Syntax: TOUCH [ switches ] filespec",
+"  Updates the modification time of the given file or files to the current",
+"  date and time.  If the filespec is the name of a single file that does not",
+"  exist, the file is created.  The optional switches are the same as for",
+"  the DIRECTORY command.  TOUCH operates silently unless the /VERBOSE",
+"  switch is given, in which case it lists each file it affects.",
+""};
 
 #ifndef NOSPL
 static char *hmxxkcd[] = {
@@ -2270,7 +2411,8 @@ static char *hmxxpat[] = {
 #else
 "  with \"t\".  When typing commands at the prompt, you must precede any",
 "  question mark to be used for matching by a backslash (\\) to override the",
-"  normal function of question mark, which is providing menus and file lists.",
+"  normal function of question mark in interactive commands, which is to",
+"  provide menus and file lists.",
 #endif /* VMS */
 " ",
 #ifdef OS2ORUNIX
@@ -2297,7 +2439,7 @@ static char *hmxxpat[] = {
 #ifndef NOSPL
 " ",
 "To force a special pattern character to be taken literally, precede it with",
-"a backslash, e.g. [a\\-z] matches a, hyphen, and z rather than a through z.",
+"a backslash, e.g. [a\\-z] matches a, hyphen, or z rather than a through z.",
 " ",
 "A floating  pattern can also include the following special characters:",
 " ",
@@ -2321,11 +2463,13 @@ static char *hmxxpat[] = {
 "  \\fsearch(abc,xxabcxxx) succeeds because xxabcxx contains abc.",
 "  \\fsearch(^abc,xxabcxx) fails because xxabcxx does not start with abc.",
 " ",
-"All other commands and functions that use patterns use anchored patterns,",
-"meaning that ^ and $ are not treated specially, and * is not assumed at the",
-"beginning or end of the pattern.  This is true mainly of filename patterns",
-"(wildcards), since you would not want a command like \"delete x\" to delete",
-"all files whose names contained \"x\"!",
+
+"All other commands and functions use anchored patterns, meaning that ^ and $",
+"are not treated specially, and * is not assumed at the beginning or end of",
+"the pattern.  This is true mainly of filename patterns (wildcards), since",
+"you would not want a command like \"delete x\" to delete all files whose", 
+"names contained \"x\"!",
+
 " ",
 "You can use anchored patterns not only in filenames, but also in SWITCH",
 "case labels, in the INPUT and MINPUT commands, and in file binary- and",
@@ -2356,7 +2500,9 @@ static char *hmxxwild[] = {
 #else
 "  with \".c\".  When typing commands at the prompt, you must precede any",
 "  question mark to be used for matching by a backslash (\\) to override the",
-"  normal function of question mark, which is providing menus and file lists.",
+"  normal function of question mark in interactive commands, which is to",
+"  provide menus and file lists.  You don't, however, need to quote filename",
+"  question marks in command files (script programs).",
 #endif /* VMS */
 " ",
 #ifdef OS2ORUNIX
@@ -2382,7 +2528,9 @@ static char *hmxxwild[] = {
 #endif /* OS2ORUNIX */
 " ",
 "To force a special pattern character to be taken literally, precede it with",
-"a backslash, e.g. [a\\-z] matches a, hyphen, and z rather than a through z.",
+"a backslash, e.g. [a\\-z] matches a, hyphen, or z rather than a through z.",
+"Or tell Kermit to SET WILDCARD-EXPANSION OFF before entering or referring",
+"to the filename.",
 " ",
 #ifndef NOSPL
 "Similar notation can be used in general-purpose string matching.  Type HELP",
@@ -2566,21 +2714,18 @@ static char * hmxxlearn[] = {
 
 #ifdef CK_MINPUT
 static char *hmxxminp[] = {
-"Syntax:  MINPUT n [ string1 [ string2 [ ... ] ] ]",
+"Syntax:  MINPUT [ switches ] n [ string1 [ string2 [ ... ] ] ]",
 "Example: MINPUT 5 Login: {Username: } {NO CARRIER} BUSY RING",
 "  For use in script programs.  Waits up to n seconds for any one of the",
 "  strings to arrive on the communication device.  If no strings are given,",
 "  the command waits for any character at all to arrive.  Strings are",
-"  separated by spaces; use { braces } for grouping.  If any of the strings",
-"  is encountered within the timeout interval, the command succeeds and the",
-"  \\v(minput) variable is set to the number of the string that was matched:",
-"  1, 2, 3, etc.  If none of the strings arrives, the command times out,",
-"  fails, and \\v(minput) is set to 0.  If the timeout interval is 0 the",
-"  MINPUT command does not wait; i.e. the given text must already be",
-"  available for reading for the MINPUT command to succeed.  If the interval",
-"  is negative, the MINPUT command waits forever.",
-" ",
-"Also see: INPUT, REINPUT, SET INPUT.",
+"  separated by spaces; use {braces} or \"doublequotes\" for grouping.  If",
+"  any of the strings is encountered within the timeout interval, the command",
+"  succeeds and the \\v(minput) variable is set to the number of the string",
+"  that was matched: 1, 2, 3, etc.  If none of the strings arrives, the",
+"  command times out, fails, and \\v(minput) is set to 0.  In all other",
+"  respects, MINPUT is like INPUT.  See HELP INPUT for the available switches",
+"  and other details of operation.",
 "" };
 #endif /* CK_MINPUT */
 
@@ -2940,6 +3085,9 @@ static char * hmxxdate[] = {
 " ",
 "  The following shortcuts can also be used in place of dates:",
 " ",
+"  NOW",
+"    Stands for the current date and time.",
+" ",
 "  TODAY",
 "    Today's date, optionally followed by a time; 00:00:00 if no time given.",
 " ",
@@ -2950,12 +3098,13 @@ static char * hmxxdate[] = {
 "    Tomorrows's date, optionally followed by a time (default 00:00:00).",
 " ",
 "  Timezone specifications are similar to those used in e-mail and HTTP",
-"    headers, either a USA timezone name, e.g. EST or a signed four-digit",
+"    headers, either a USA timezone name, e.g. EST, or a signed four-digit",
 "    timezone offset, {+,-}hhmm, e.g., -0500; it is used to convert date-time,"
 ,
 "    a local time in that timezone, to GMT which is then converted to the",
 "    local time at the host.  If no timezone is given, the date-time is local."
-,
+,"    To convert local time (or a time in a specified timezone) to UTC (GMT),",
+"    use the function \futcdate().",
 " ",
 "  Delta times are given as {+,-}[number date-units][hh[:mm[:ss]]]",
 "    A date in the future/past relative to the date-time; date-units may be",
@@ -3259,10 +3408,10 @@ static char *hmxxrc[] = {
 #ifndef NORESEND
 static char *hmxxrsen = "\
 Syntax: RESEND filespec [name]\n\n\
-  Resend the file or files, whose previous transfer was interrupted.\n\
-  Picks up from where previous transfer left off, IF the receiver was told\n\
-  to SET FILE INCOMPLETE KEEP.  Only works for binary-mode transfers.\n\
-  Requires the other Kermit to have RESEND capability.";
+  Resends the file or files, whose previous transfer was interrupted.\n\
+  Picks up from where previous transfer left off, IF the receiver kept the\n\
+  partially received file.  Works only for binary-mode transfers.\n\
+  Requires file-transfer partner to support recovery.  Synonym: REPUT.";
 
 static char *hmxxrget = "\
 Syntax: REGET filespec\n\n\
@@ -3354,17 +3503,38 @@ static char *hmhskey[] = {
 ""};
 #endif /* NOSETKEY */
 
-static char *hmxychkt[] = { "Syntax: SET BLOCK-CHECK type",
+static char *hmxychkt[] = { "Syntax: SET BLOCK-CHECK number",
+" ",
+"Type of block check to be used for error detection on file-transfer",
+"packets: 1, 2, 3, 4, or 5.  This command must be given to the file",
+"sender prior to the transfer.",
+" ",
+"Type 1 is standard and supported by all Kermit protocol implementations,",
+"  but it's only a 6-bit checksum, represented in a single printable ASCII",
+"  character.  It's fine for reliable connections (error-correcting modems,",
+"  TCP/IP, etc) but type 3 is recommended for connections where errors can",
+"  occur.",
+" ",
+"Type 2 is a 12-bit checksum represented in two printable characters.",
 " ",
-"  Type of packet block check to be used for error detection, 1, 2, 3, or",
-"  BLANK-FREE-2.  Type 1 is standard, and catches most errors.  Types 2 and 3",
-"  specify more rigorous checking at the cost of higher overhead.  The",
-"  BLANK-FREE-2 type is the same as Type 2, but is guaranteed to contain no",
-"  blanks.",
+"Type 3 is a 16-bit cyclic redundancy check, the strongest error",
+"  detection method supported by Kermit protocol, represented in three",
+"  printable characters.",
+" ",
+"Type 4 (alias \"BLANK-FREE-2\") is a 12-bit checksum guaranteed to",
+"  contain no blanks in its representation; this is needed for connections",
+"  where trailing blanks are stripped from incoming lines of text.",
+" ",
+"Type 5 (alias \"FORCE-3\") means to force a Type 3 block check on",
+"  every packet, including the first packet, which normally has a type 1",
+"  block check.  This is for use in critical applications on noisy",
+"  connections.  As with types 2, 3, and 4, if the Kermit file",
+"  transfer partner does not support this type, the transfer fails",
+"  immediately at the beginning of the transfer.",
 "" };
 
 static char * hmxydeb[] = {
-"Syntax: SET DEBUG { SESSION, ON, OFF, TIMESTAMP }",
+"Syntax: SET DEBUG { SESSION, ON, OFF, TIMESTAMP, MESSAGES }",
 " ",
 "SET DEBUG ON",
 #ifdef DEBUG
@@ -3387,6 +3557,12 @@ static char * hmxydeb[] = {
 " ",
 "SET DEBUG TIMESTAMP { ON, OFF }",
 "  Enables/Disables timestamps on debug log entries.",
+" ",
+"SET DEBUG MESSAGES { ON, OFF, STDERR } [C-Kermit 9.0]",
+"  Enables/Disables messages printed by the DEBUG command.",
+"  SET DEBUG OFF causes DEBUG messages not to be printed.",
+"  SET DEBUG ON sends DEBUG messages to standard output (stdout);",
+"  SET DEBUG STDERR sends DEBUG messages to standard error (stderr);",
 "" };
 
 #ifdef CK_SPEED
@@ -3660,7 +3836,7 @@ static char *hmxydial[] = {
 " ",
 "SET DIAL RETRIES <number>",
 "  How many times to redial each number if the dialing result is busy or no",
-"  no answer, until the call is succesfully answered.  The default is 0",
+"  no answer, until the call is successfully answered.  The default is 0",
 "  because automatic redialing is illegal in some countries.",
 " ",
 "SET DIAL INTERVAL <number>",
@@ -3896,7 +4072,7 @@ static char *hmxyf[] = {
 "     the incoming file under the name it was sent with.",
 "   OVERWRITE - Overwrite (replace) the existing file.",
 "   APPEND - Append the incoming file to the end of the existing file.",
-"   DISCARD - Refuse and/or discard the incoming file.",
+"   REJECT - Refuse and/or discard the incoming file (= DISCARD).",
 "   RENAME - Give the incoming file a unique name.",
 "   UPDATE - Accept the incoming file only if newer than the existing file.",
 " ",
@@ -4208,6 +4384,9 @@ static char *ifhlp[] = { "Syntax: IF [NOT] condition commandlist",
 #ifdef CK_TMPDIR
 "  DIRECTORY string                  - The string is the name of a directory",
 #endif /* CK_TMPDIR */
+#ifdef UNIX
+"  LINK string                       - The string is a symbolic link",
+#endif /* UNIX */
 "  READABLE filename                 - Succeeds if the file is readable",
 "  WRITEABLE filename                - Succeeds if the file is writeable",
 #ifdef ZFCDAT
@@ -4328,13 +4507,19 @@ static char *hxxask[] = {
 " ",
 "Syntax:  ASKQ [ switches ] variablename [ prompt ]",
 "Example: ASKQ \\%p { Password:}",
-"  Like ASK except the response does not echo on the screen.",
+"  Like ASK except the response does not echo on the screen or, if specified",
+"  it echoes as asterisks or other specified character.",
 " ",
 "Switches:",
 " /DEFAULT:text",
 "  Text to supply if the user enters a blank response or the /TIMEOUT",
 "  limit expired with no response.",
 " ",
+" /ECHO:char",
+"  (ASKQ only) Character to be echoed each time the user presses a key",
+"  corresponding to a printable character.  This lets users see what they are",
+"  doing when they are typing (e.g.) passwords, and makes editing easier.",
+" ",
 #ifdef OS2
 " /POPUP",
 "  The prompt and response dialog takes place in a text-mode popup.",
@@ -4915,7 +5100,7 @@ static char *hxytapi[] = {
 "  other applications and Kermit performs dialing functions using its",
 "  built-in dialing and modem databases.  If TAPI MODEM-DIALING is ON, TAPI",
 "  handles all dialing functions and the port may be shared with other",
-"  applications when a call in not active.  When TAPI MODEM-DIALING is OFF,",
+"  applications when a call is not active.  When TAPI MODEM-DIALING is OFF,",
 "  SET MODEM TYPE TAPI Kermit uses the TAPI modem commands imported from the",
 "  Windows Registry during the previous SET TAPI LINE call.",
 " ",
@@ -5143,7 +5328,7 @@ static char * hxxdcl[] = {
 "  elements are discarded; if it is larger, new empty elements are added.",
 " ",
 "ARRAY COPY array1 array2",
-"  Copys array1 to array2.  If array2 has not been declared, it is created",
+"  Copies array1 to array2.  If array2 has not been declared, it is created",
 "  automatically.  Range specifiers may be given on one or both arrays.",
 " ",
 "ARRAY LINK array1 arra2",
@@ -5193,13 +5378,28 @@ static char * hmxxcpy[] = {
 "  be copied to the given directory.  Switches:",
 " ",
 "  /LIST",
-"    Print the filenames and status while copying.  Synonyms: /LOG, /VERBOSE",
+"    Print the filenames and status while copying.  Synonyms: /LOG, /VERBOSE.",
 " ",
 "  /NOLIST",
-"    Copy silently (default). Synonyms: /NOLOG, /QUIET",
+"    Copy silently (default). Synonyms: /NOLOG, /QUIET.",
+" ",
+"  /PRESERVE",
+"    Copy timestamp and permissions from source file to destination file.",
+" ",
+"  /OVERWRITE:{ALWAYS,NEVER,NEWER,OLDER}",
+"    When copying from one directory to another, this tells what to do when",
+"    the destination file already exists: overwrite it always; never; only if",
+"    the source file is newer; or only if the source file is older.",
+" ",
+"  /APPEND",
+"    Append the source file to the destination file.  In this case the source",
+"    file specification can contain wildcards, and all the matching source",
+"    files are appended, one after the other in alphabetical order by name,",
+"    to the destination file.",
 " ",
 "  /SWAP-BYTES",
-"    Swap bytes while copying.",
+"    Swap bytes while copying (e.g. for converting between Big-Endian and",
+"    Little-Endian binary data formats).",
 #ifndef NOSPL
 " ",
 "  /FROMB64",
@@ -5219,19 +5419,70 @@ static char * hmxxren[] = {
 "  this command is equivalent to REMOTE RENAME (RREN).  Otherwise:",
 " ",
 #endif /* LOCUS */
-"Syntax: RENAME [ switches ] name1 name2",
+"Syntax: RENAME [ switches ] name1 [ name2 ]",
 "  Renames the source file (name1) to the target name2.  If name2 is a",
 "  directory, name1 is allowed to contain wildcards, and the file(s) matching",
 "  name1 are moved to directory name2, subject to rules of the underlying",
-"  operating system regarding renaming across disk boundaries, etc.  If name2",
-"  is not a directory, name1 may not include wildcards, and the file whose",
-"  name is name1 is renamed to name2.  Switches:",
+"  operating system regarding renaming across disk boundaries, etc. Switches:",
 " ",
 "  /LIST",
 "    Print the filenames and status while renaming.  Synonyms: /LOG, /VERBOSE",
 " ",
 "  /NOLIST",
 "    Rename silently (default). Synonyms: /NOLOG, /QUIET",
+" ",
+"  /COLLISION:{FAIL,SKIP,OVERWRITE}",
+"    Tells what to do if a file with the given (or derived) new name already",
+"    exists: fail (and stop without renaming any files); skip this file",
+"    without renaming it and go on to the next one, if any; or overwrite (the",
+"    existing file).  PROCEED is a synonym for SKIP.",
+" ",
+"  /SIMULATE",
+"    Show what the effects of the RENAME command would be without actually",
+"    renaming any files.",
+" ",
+"  When any of the following switches is given, name2 must either be the",
+"  the name of a directory, or else omitted, and name1 is allowed to contain",
+"  contain wildcards, allowing multiple files to be renamed at once. If name2",
+"  is given, then all files matching name1 are moved to the name2 directory",
+"  after being renamed.",
+" ",
+"  /LOWER:{ALL,UPPER}",
+"    Converts letters in the filename to lowercase.  ALL means to convert",
+"    all matching filenames, UPPER means to convert only those filenames",
+"    that contain no lowercase letters.  The switch argument can be omitted,",
+"    in which case ALL filenames are converted.",
+" ",
+"  /UPPER:{ALL,LOWER}",
+"    Converts letters in the filename to uppercase.  ALL means to convert",
+"    all matching filenames, LOWER means to convert only those filenames",
+"    that contain no uppercase letters.  As with /LOWER, ALL is the default",
+"    switch argument.",
+" ",
+"  /FIXSPACES:s",
+"    Replaces all spaces in each matching filename by the string s, which may",
+"    be empty, a single character, or a string of characters.  The default",
+"    replacement (if no argument is given) is underscore (_).",
+" ",
+"  /REPLACE:{{string1}{string2}{options}}",
+"    Replaces all or selected occurrences of string1 with string2 in the",
+"    matching filenames.  The braces are part of the command.  The options",
+"    string can contain the following characters:",
+"     A: String matching is case-sensitive.",
+"     a: String matching is case-insensitive.",
+"     ^: String matching is anchored to the beginning of the filename.",
+"     $: String matching is anchored to the end of the filename.",
+"     1: Only the first occurrence of the string (if any) will be changed.",
+"     2: Only the second occurrence, and so on for all digits up to 9.",
+"     -: (before a digit) Occurrences are counted from the right.",
+"     ~: (before occurrence) All occurences BUT the one given are changed.",
+" ",
+"  /CONVERT:cset1:cset1",
+"    Converts each matching filename from character-set 1 to character-set 2.",
+"    Character sets are the same as for SET FILE CHARACTER-SET.",
+" ",
+"  Global values for /LIST and COLLISION can be set with SET RENAME and",
+"  displayed with SHOW RENAME.",
 ""
 };
 #endif /* NOFRILLS */
@@ -5322,6 +5573,7 @@ An option that does not require an argument can be bundled with other options:"
 ""
 };
 
+
 #ifndef NOHELP
 #ifndef NOCMDL
 int
@@ -5558,7 +5810,7 @@ static char * hxxf_op[] = {
 " ",
 "/WRITE",
 "  Open the file for writing.  If /READ was not also specified, this creates",
-"  a new file.  If /READ was specifed, the existing file is preserved, but",
+"  a new file.  If /READ was specified, the existing file is preserved, but",
 "  writing is allowed.  In both cases, the read/write pointer is initially",
 "  at the beginning of the file.",
 " ",
@@ -5658,12 +5910,17 @@ static char * hxxf_rw[] = {
 
 static char * hxxf_se[] = {
 "Syntax: FILE SEEK [ switches ] <channel> { [{+,-}]<number>, EOF }",
-"  Switches are /BYTE, /LINE, /RELATIVE, ABSOLUTE.",
+"  Switches are /BYTE, /LINE, /RELATIVE, /ABSOLUTE, and /FIND:pattern.",
 "  Moves the file pointer for this file to the given position in the",
 "  file.  Subsequent FILE READs or WRITEs will take place at that position.",
 "  If neither the /RELATIVE nor /ABSOLUTE switch is given, an unsigned",
 "  <number> is absolute; a signed number is relative.  EOF means to move to",
-"  the end of the file.  Synonym: FSEEK.  Also available as \\F_seek().",
+"  the end of the file.  If a /FIND: switch is included, Kermit seeks to the",
+"  specified spot (e.g. 0 for the beginning) and then begins searching line",
+"  by line for the first line that matches the given pattern.  To start",
+"  searching from the current file position specify a line number of +0.",
+"  To start searching from the line after the current one, use +1 (etc).",
+"  Synonym: FSEEK.",
 ""
 };
 
@@ -5784,7 +6041,7 @@ dohlp(xx) int xx; {
 #ifdef NOHELP
     if ((x = cmcfm()) < 0)
       return(x);
-    printf("\n%s, Copyright (C) 1985, 2004,",versio);
+    printf("\n%s, Copyright (C) 1985, %s,",versio, ck_cryear);
 #ifndef NOIKSD
     if (inserver)
       return(hmsga(tophlpi));
@@ -5941,6 +6198,12 @@ case XXUNDEF:                           /* UNDEFINE */
   Undefines a macro or variable."));
 #endif /* NOSPL */
 
+case XXMSG:
+    return(hmsg("Syntax: MESSAGE text-to-print-if-debugging\n\
+  Prints the given text to stdout if SET DEBUG MESSAGE is ON; prints it\n\
+  to stderr if SET DEBUG MESSAGE is STDERR; doesn't print it at all if SET\n\
+  DEBUG MESSAGE is OFF.  Synonym: MSG."));
+
 #ifndef NOFRILLS
 case XXLDEL:
     return(hmsg(
@@ -5978,6 +6241,19 @@ case XXLDIR:                            /* LDIRECTORY */
 case XXDIR:                             /* DIRECTORY */
     return(hmsga(hmxxdir));
 
+case XXTOUC:                           /* TOUCH */
+    return(hmsga(hmxxtouc));
+
+case XXWDIR:                           /* WDIRECTORY */
+  return(hmsg("  WDIRECTORY is shorthand for DIRECTORY /SORT:DATE /REVERSE;\n\
+  it produces a listing in reverse chronological order.  See the DIRECTORY\n\
+  command for further information."));
+
+case XXHDIR:                           /* HDIRECTORY */
+  return(hmsg("  HDIRECTORY is shorthand for DIRECTORY /SORT:SIZE /REVERSE;\n\
+  it produces a listing showing the biggest files first.  See the DIRECTORY\n\
+  command for further information."));
+
 case XXLMKD:                            /* LMKDIR */
     return(hmsg(
 "  LMKDIR is an alias for the MKDIR command forcing it to execute\n\
@@ -6116,19 +6392,22 @@ Hang up the phone or network connection."));
       return(x);
 
     if (helpfile) {
-        printf("\n%s, Copyright (C) 1985, 2004,\n\
-Trustees of Columbia University in the City of New York.\n\n",versio);
+        printf("\n%s, Copyright (C) 1985, %s,\n\
+Trustees of Columbia University in the City of New York.\n\n",
+              versio,
+              ck_cryear
+              );
         return(dotype(helpfile,xaskmore,3,0,NULL,0,NULL,0,0,NULL,0));
     } else {
-        printf("\n%s, Copyright (C) 1985, 2004,",versio);
+        printf("\n%s, Copyright (C) 1985, %s,",versio,ck_cryear);
         return(hmsga(tophlp));
     }
 
 case XXINT:
 #ifdef OS2
-    return(hmsg("Give a brief introduction to C-Kermit."));
+    return(hmsg("The INTRO command gives a brief introduction to Kermit 95."));
 #else
-    return(hmsg("Give a brief introduction to Kermit 95."));
+    return(hmsg("The INTRO command gives a brief introduction to C-Kermit."));
 #endif /* OS2 */
 
 #ifndef NOSPL
@@ -6475,11 +6754,25 @@ case XXVIEW:
     return(hmsg(
 "View the terminal emulation screen even when there is no connection."));
 
+#ifdef NEWFTP
 case XXASC:
-    return(hmsg("Synonym for SET FILE TYPE TEXT."));
-
+    return(hmsg(
+"Inhibits automatic transfer-mode switching and forces TEXT (ASCII) transfer\n\
+mode for all files in both Kermit and FTP protocols."));
 case XXBIN:
-    return(hmsg("Synonym for SET FILE TYPE BINARY."));
+    return(hmsg(
+"Inhibits automatic transfer-mode switching and forces BINARY transfer mode\n\
+for all files in both Kermit and FTP protocols."));
+#else
+case XXASC:
+    return(hmsg(
+"Inhibits automatic transfer-mode switching and forces TEXT (ASCII) transfer\n\
+mode for all files."));
+case XXBIN:
+    return(hmsg(
+"Inhibits automatic transfer-mode switching and forces BINARY transfer mode\n\
+for all files."));
+#endif /* NEWFTP */
 
 case XXDATE:
     return(hmsga(hmxxdate));
@@ -6725,6 +7018,11 @@ case XXMAN:
 case XXWILD:
     return(hmsga(hmxxwild));
 
+#ifdef LOCUS
+case XXLOCU:
+    return(hmsga(hmxylocus));
+#endif /* LOCUS */
+
 case XXPAT:
     return(hmsga(hmxxpat));
 
@@ -6766,6 +7064,8 @@ case XXPURGE:
     return(hmsg("  RKERMIT is a short form of REMOTE KERMIT."));
   case XXRMKD:
     return(hmsg("  RMKDIR is a short form of REMOTE MKDIR."));
+  case XXRMSG:
+    return(hmsg("  RMESSAGE and RMSG are short forms of REMOTE MESSAGE."));
   case XXRPRI:
     return(hmsg("  RPRINT is a short form of REMOTE PRINT."));
   case XXRPWD:
@@ -6859,6 +7159,17 @@ case XXPURGE:
     return(hmsg(" In a FOR or WHILE loop: continue the loop.\n\
  At the prompt: continue a script that has \"shelled out\" to the prompt."));
 
+  case XXREDO:
+    return(hmsg(" Syntax: REDO xxx (or) ^xxx\n\
+ Re-executes the most recent command starting with xxx."));
+
+#ifdef UNIX
+#ifndef NOPUTENV
+  case XXPUTE:
+    return(hmsga(hmxxputenv));
+#endif /* NOPUTENV */
+#endif /* UNIX */
+
   case XXNOTAV:
     return(hmsg(" This command is not configured in this version of Kermit."));
 
@@ -6943,6 +7254,76 @@ hmsga(s) char *s[]; {                   /* pausing at end of each screen. */
     return(0);
 }
 
+#ifndef NOFRILLS
+static char * supporttext[] = {
+
+"Live technical support for Kermit software is no longer available",
+"from Columbia University, as it was from mid-1981 until mid-2011 when",
+
+#ifdef OS2
+
+"the Kermit Project was cancelled.  Beginning with version 3.0, Kermit 95",
+
+#else
+
+"the Kermit Project was cancelled.  Beginning with version 9.0, C-Kermit",
+
+#endif /* OS2 */
+
+"is Open Source software.  The Kermit website is supposed remain open",
+"indefinitely at:",
+" ",
+"  http://kermit.columbia.edu/",
+" ",
+
+#ifdef OS2
+
+"The Kermit 95 page is here:",
+" ",
+"  http://kermit.columbia.edu/k95.html",
+" ",
+"The Kermit 95 manual is here:",
+" ",
+"  http://kermit.columbia.edu/k95manual/",
+" ",
+"The Kermit 95 Frequently Asked Questions page is here:",
+" ",
+"  http://kermit.columbia.edu/k95faq.html",
+" ",
+"and many other resources are listed on the Kermit 95 home page.",
+" ",
+
+#else
+
+"The C-Kermit home page is here:",
+" ",
+"  http://kermit.columbia.edu/ckermit.html",
+" ",
+"The documentation for C-Kermit is listed here:",
+" ",
+"  http://kermit.columbia.edu/ckermit.html#doc",
+" ",
+"The C-Kermit Frequently Asked Questions page is here:",
+" ",
+"  http://kermit.columbia.edu/ckfaq.html",
+" ",
+"and many other resources are listed on the C-Kermit home page.",
+" ",
+
+#endif /* OS2 */
+
+"Time will tell what sort of development and support structures arise",
+"in the Open Source community.",
+""
+};
+
+/* Do the BUG command */
+int
+dobug() {
+    return(hmsga(supporttext));
+}
+#endif /* NOFRILLS */
+
 #ifndef NOXMIT
 static char *hsetxmit[] = {
 "Syntax: SET TRANSMIT parameter value",
@@ -7035,6 +7416,12 @@ static char *hsetcmd[] = {
 " ",
 #endif /* OS2 */
 
+"SET COMMAND ERROR { 0,1,2,3 }",
+"  Sets the verbosity level of command error messages; the higher the number,",
+"  the more verbose the message.  The default is 1.  Higher values are",
+"  useful only for debugging scripts.",
+" ",
+
 #ifdef OS2
 #ifdef NT
 "SET COMMAND HEIGHT <number>",
@@ -7461,11 +7848,6 @@ static char *hxyterm[] = {
 "  Selects the cursor style and visibility for the terminal screen.",
 #endif /* KUI */
 " ",
-"SET TERMINAL DG-UNIX-MODE { ON, OFF }",
-"  Specifies whether the Data General emulations should accept control",
-"  sequences in Unix compatible format or in native DG format.  The",
-"  default is OFF, DG format.",
-" ",
 #endif /* OS2 */
 
 "SET TERMINAL DEBUG { ON, OFF }",
@@ -7475,6 +7857,9 @@ static char *hxyterm[] = {
 " ",
 #ifdef OS2
 "SET TERMINAL DG-UNIX-MODE { ON, OFF }",
+"  Specifies whether the Data General emulations should accept control",
+"  sequences in Unix compatible format or in native DG format.  The",
+"  default is OFF, DG format.",
 " ",
 #endif /* OS2 */
 
@@ -7549,11 +7934,9 @@ static char *hxyterm[] = {
 "  CONNECT mode; if no text is given a NUL (0) character is sent.",
 #ifdef TNCODE
 " ",
-"And for Telnet connections:",
-" ",
 "SET TERMINAL IDLE-ACTION { TELNET-NOP, TELNET-AYT }",
-"  Sends the indicated Telnet protocol message: No Operation (NOP) or",
-"  \"Are You There?\" (AYT).",
+"  For TELNET connections only: Sends the indicated Telnet protocol message:",
+"  No Operation (NOP) or \"Are You There?\" (AYT).",
 #endif /* TNCODE */
 " ",
 #endif /* CKTIDLE */
@@ -7603,6 +7986,16 @@ static char *hxyterm[] = {
 "  in a different mode than it's in, but did not send the escape sequence",
 "  to put it in the needed mode.",
 " ",
+
+#endif /* OS2 */
+
+"SET TERMINAL LF-DISPLAY { CRLF, NORMAL }",
+"  Specifies how incoming linefeed characters are to be displayed",
+"  on your screen.",
+" ",
+
+#ifdef OS2
+
 #ifdef KUI
 "SET TERMINAL LINE-SPACING <float>",
 "  Specifies the line spacing used when displaying text.  The default is 1.0.",
@@ -7766,7 +8159,7 @@ static char *hxyterm[] = {
 "  easily switch between the National Language character set and U.S. ASCII.",
 "  The default is ON which means to display characters as U.S. ASCII.  When",
 "  OFF the lanuage specified by SET TERMINAL SNI-LANUAGE is used to display",
-"  characters when 7-bit character sets are in use."
+"  characters when 7-bit character sets are in use.",
 " ",
 "SET TERMINAL SNI-FIRMWARE-VERSIONS <kbd-version> <terminal-version>",
 "  Specifies the Firmware Version number that should be reported to the host",
@@ -8781,15 +9174,34 @@ static char *hmxyprm[] = {
 
 #ifdef UNIX
 static char *hxywild[] = {
-"Syntax: SET WILDCARD-EXPANSION { KERMIT [ switch ], SHELL }",
+"Syntax: SET WILDCARD-EXPANSION { KERMIT [ switch ], SHELL, ON, OFF }",
 "  KERMIT (the default) means C-Kermit expands filename wildcards in SEND and",
 "  similar commands itself, and in incoming GET commands.  Optional switches",
-"  are /NO-MATCH-DOT-FILES (\"*\" and \"?\" should not match in initial",
+"  are /NO-MATCH-DOT-FILES (\"*\" and \"?\" should not match an initial",
 "  period in a filename; this is the default) and /MATCH-DOT-FILES if you",
 "  want files whose names begin with \".\" included.  SET WILDCARD SHELL",
 "  means that Kermit asks your preferred shell to expand wildcards (this",
 "  should not be necessary in C-Kermit 7.0 and later).  HELP WILDCARD for",
 "  further information.",
+" ",
+"  The ON and OFF choices allow you to disable and renable wildcard",
+"  processing independent of the KERMIT / SHELL choice.  Disabling wildcards",
+"  allows you to process an array or list of filenames without having to",
+"  consider whether the names might contain literal wildcard characters.",
+"  WARNING: SET WILD OFF also disables internal filename pattern-matching,",
+"  used (for example) in creating backup files.",
+"" };
+#else
+static char *hxywild[] = {
+"Syntax: SET WILDCARD-EXPANSION { ON, OFF }",
+"  ON (the default) means that filenames given to Kermit commands such as",
+"  SEND and DIRECTORY are automatically expanded into lists of filenames if",
+"  they contain special 'wildcard characters' such as '*'.  You can reference",
+"  files whose names contains such characters literally by preceding each",
+"  such character with a backslash '\\'.  When dealing programmatically with",
+"  a file list, however, you should SET WILDCARD-EXPANSION OFF to force",
+"  treat each name in the list as a literal name.  See HELP WILDCARDS for",
+"  details about wildcard syntax.",
 "" };
 #endif /* UNIX */
 
@@ -9000,6 +9412,7 @@ The template should include variables like \\v(filename) or \\v(filenumber).",
 "  throughout the transfer based on the packet rate.  Include the word FIXED",
 "  to use the \"number\" given throughout the transfer.  DYNAMIC is the",
 "  default.  After DYNAMIC you may include minimum and maximum values.",
+"  SET SEND TIMEOUT -1 FIXED means no timeouts.",
 #else
 "  retransmitting.",
 #endif /* CK_TIMERS */
@@ -9012,7 +9425,7 @@ The template should include variables like \\v(filename) or \\v(filenumber).",
 "" };
 
 static char *hxyxfer[] = {
-"Syntax: SET TRANSFER (or XFER) paramater value",
+"Syntax: SET TRANSFER (or XFER) parameter value",
 " ",
 "Choices:",
 " ",
@@ -9179,6 +9592,23 @@ static char *hmxybel[] = {
 #endif /* OS2 */
 ""};
 
+#ifdef OS2
+static char *hmxymsk[] = {
+"SET MSKERMIT FILE-RENAMING { ON, OFF }",
+"  ON enables the use of MS-DOS Kermit file renaming conventions instead of",
+"  C-Kermit conventions.  File renaming occurs during file transfers when",
+"  there is a file name collision and either BACKUP or RENAME collision",
+"  options are active.  C-Kermit conventions preserve the original file name",
+"  while appending .~num~ to the end.  MS-DOS Kermit conventions restrict",
+"  filenames to 8.3 notation and preserve the extension.  Unique numeric",
+"  values overwrite the right most portion of the file name's left hand side.",
+" ",
+"SET MSKERMIT KEYCODES { ON, OFF }",
+"  ON enables the use of MS-DOS Kermit compatible keycodes to provide script",
+"  portability.",
+""};
+#endif /* OS2 */
+
 static char *hmxycd[] = {
 "Syntax: SET CD { HOME <path>, PATH <path>, MESSAGE { ON, OFF, FILE <list> } }"
 ,
@@ -9461,6 +9891,13 @@ dohset(xx) int xx; {
         return(hmsga(hsetiks));
 #endif /* NOIKSD */
 
+case XY_REN:
+  return(hmsg("SET RENAME LIST { ON, OFF }\n\
+  Tells whether the RENAME command should list its results by default.\n\n\
+SET RENAME COLLISION { FAIL, PROCEED, OVERWRITE }\n\
+  Establishes the default action when renaming a file would destroy an\n\
+  existing file.  See HELP RENAME."));
+
 case XYATTR:
     return(hmsga(hsetat));
 
@@ -9475,6 +9912,9 @@ case XYPRTY:
     return(hmsg("SET PRIORITY { REGULAR, FOREGROUND-SERVER, TIME-CRITICAL }\n\
   Specifies at which priority level the communication and screen update\n\
   threads should operate.  The default value is FOREGROUND-SERVER."));
+
+case XYMSK:
+    return(hmsga(hmxymsk));
 #endif /* OS2 */
 
 #ifdef DYNAMIC
@@ -9740,7 +10180,8 @@ case XYRETR:
 case XYSESS:
 #ifdef UNIX
     return(hmsg(
-"Syntax: SET SESSION-LOG { BINARY, DEBUG, TEXT, TIMESTAMPED-TEXT }\n\
+"Syntax:\n\
+ SET SESSION-LOG { BINARY, DEBUG, NULL-PADDED, TEXT, TIMESTAMPED-TEXT }\n\
   If BINARY, record all CONNECT characters in session log.  If TEXT, strip\n\
   out CR, NUL, and XON/XOFF characters.  DEBUG is the same as BINARY but\n\
   also includes Telnet negotiations on TCP/IP connections."));
@@ -10052,6 +10493,20 @@ case XYTIMER:
   case XYMATCH:
     return(hmsga(hmxymatch));
 
+#ifndef NOSEXP
+  case XYSEXP:
+    return(hmsga(hmxysexp));
+#endif /* NOSEXP */
+
+#ifndef NOSPL
+  case XYVAREV:
+    return(hmsg("Syntax: SET VARIABLE-EVALUATION { RECURSIVE, SIMPLE }\n\
+  Tells Kermit weather to evaluate \\%x and \\&x[] variables recursively\n\
+  (which is the default for historical reasons) or by simple string\n\
+  replacement, which lets you use these variables safely to store strings\n\
+  (such as Windows pathnames) that might contain backslashes."));
+#endif /* NOSPL */
+
 default:
     printf("Not available - \"%s\"\n",cmdbuf);
     return(0);
@@ -10059,6 +10514,60 @@ default:
 }
 
 #ifndef NOSPL
+static char * hfsplit[] = {
+"Function \\fsplit(s1,&a,s2,s3,n2,n3) - Assigns string words to an array.",
+"  s1 = source string.",
+"  &a = array designator.",
+"  s2 = optional break set.",
+"  s3 = optional include set (or ALL, CSV, or TSV).",
+"  n2 = optional grouping mask.",
+"  n3 = optional separator flag:",
+"   0 = collapse adjacent separators;",
+"   1 = don't collapse adjacent separators.",
+" ",
+"  \\fsplit() breaks the string s1 into \"words\" as indicated by the other",
+"  parameters, assigning them to given array, if any.  If the specified",
+"  already exists, it is recycled; if no array is specified, the count is",
+"  returned but no array is created.  All arguments are optional",
+"  (\\fsplit() with no arguments returns 0).",
+" ",
+"  The BREAK SET is the set of all characters that separate words. The",
+"  default break set is all characters except ASCII letters and digits.",
+"  ASCII (C0) control characters are treated as break characters by default,",
+"  as are spacing and punctuation characters, brackets, and so on, and",
+"  all 8-bit characters.",
+" ",
+"  The INCLUDE SET is the set of characters that are to be treated as ",
+"  parts of words even though they normally would be separators.  The",
+"  default include set is empty.  Three special symbolic include sets are",
+"  also allowed:",
+" ",
+"    ALL (meaning include all bytes that are not in the break set)",
+"    CSV (special treatment for Comma-Separated-Value records)",
+"    TSV (special treatment for Tab-Separated-Value records)",
+" ",
+"  For operating on 8-bit character sets, the include set should be ALL.",
+" ",
+"  If the grouping mask is given and is nonzero, words can be grouped by",
+"  quotes or brackets selected by the sum of the following:",
+" ",
+"     1 = doublequotes:    \"a b c\"",
+"     2 = braces:          {a b c}",
+"     4 = apostrophes:     'a b c'",
+"     8 = parentheses:     (a b c)",
+"    16 = square brackets: [a b c]",
+"    32 = angle brackets:  <a b c>",
+" ",
+"  Nesting is possible with {}()[]<> but not with quotes or apostrophes.",
+" ",
+"Returns integer:",
+"  Number of words in source string.",
+" ",
+"Also see:",
+"  HELP FUNCTION WORD",
+""
+};
+
 /*  D O H F U N C  --  Give help for a function  */
 
 int
@@ -10080,10 +10589,11 @@ dohfunc(xx) int xx; {
     switch (xx) {
       case FN_IND:                      /* Index (of string 1 in string 2) */
       case FN_RIX:                      /* Rindex (index from right) */
-        printf("\\f%sindex(s1,s2,n1)\n\
+        printf("\\f%sindex(s1,s2,n1,n2)\n\
   s1 = string to look for.\n\
   s2 = string to look in.\n\
-  n1 = optional 1-based starting position, default = 1.\n",
+  n1 = optional 1-based starting position, default = 1.\n\
+  n2 = optional desired occurrence number, default = 1.\n",
                xx == FN_RIX ? "r" : ""
                );
         printf("Returns integer:\n\
@@ -10093,12 +10603,22 @@ dohfunc(xx) int xx; {
                xx == FN_IND ? "left" : "right"
         );
         break;
+      case FN_COUNT:                   /* Count occurrences of s1 in s2 */
+       printf("\\fcount(s1,s2,n1)\n\
+  s1 = string or character to look for.\n\
+  s2 = string to look in.\n\
+  n1 = optional 1-based starting position, default = 1.\n");
+       printf("Returns integer:\n\
+  Number of occurrences of s1 in s2, 0 or more.\n");
+        break;
+
       case FN_SEARCH:                   /* Search for pattern */
       case FN_RSEARCH:                  /* Search for pattern from right */
-        printf("\\f%ssearch(s1,s2,n1)\n\
+        printf("\\f%ssearch(s1,s2,n1,n2)\n\
   s1 = pattern to look for.\n\
   s2 = string to look in.\n\
-  n1 = optional 1-based offset, default = 1.\n",
+  n1 = optional 1-based offset, default = 1.\n\
+  n2 = optional desired occurrence of match, default = 1.\n",
                xx == FN_RSEARCH ? "r" : ""
                );
         printf("Returns integer:\n\
@@ -10400,11 +10920,22 @@ dohfunc(xx) int xx; {
         break;
 
       case FN_STL:                      /* Strip from left */
-        printf("\\flop(s1,c1)\n\
+        printf("\\flop(s1[,c1[,n1]])\n\
   s1 = string to look in.\n\
-  c1 = character to look for, default = \".\".\n");
+  c1 = character to look for, default = \".\".\n\
+  n1 = occurrence of c1, default = 1.\n");
         printf("Returns string:\n\
-  The part of s1 after the leftmost occurrence of character c1.\n"
+  The part of s1 after the n1th leftmost occurrence of character c1.\n"
+        );
+        break;
+
+      case FN_LOPX:                      /* Strip from right */
+        printf("\\flopx(s1,c1)\n\
+  s1 = string to look in.\n\
+  c1 = character to look for, default = \".\".\n\
+  n1 = occurrence of c1, default = 1.\n");
+        printf("Returns string:\n\
+  The part of s1 after the n1th rightmost occurrence of character c1.\n"
         );
         break;
 
@@ -10516,6 +11047,7 @@ dohfunc(xx) int xx; {
 #endif /* NORANDOM */
 
       case FN_SPLIT:                    /* Split */
+#ifdef COMMENT
         printf("\\fsplit(s1,&a,s2,s3,n2,n3) - \
 Assign string words to an array.\n\
   s1 = source string\n  &a = array designator\n  s2 = optional break set.\n");
@@ -10528,6 +11060,9 @@ Assign string words to an array.\n\
   if array not specified, the count is returned but no array is created.\n");
         printf("Returns integer:\n\
   Number of words in source string.\n");
+#else
+        hmsga(hfsplit);
+#endif /* COMMENT */
         break;
 
       case FN_DTIM:                     /* CVTDATE */
@@ -10541,7 +11076,9 @@ Assign string words to an array.\n\
         printf("  If n1 is given:\n\
   n1 = 1: yyyy-mmm-dd hh:mm:ss (mmm = English 3-letter month abbreviation)\n\
   n1 = 2: dd-mmm-yyyy hh:mm:ss (ditto)\n\
-  n1 = 3: yyyymmddhhmmss (all numeric)\n");
+  n1 = 3: yyyymmddhhmmss (all numeric)\n\
+  n1 = 4: Day Mon dd hh:mm:ss yyyy (asctime)\n\
+  Other:  yyyymmdd hh:mm:dd");
         break;
 
       case FN_JDATE:                    /* DOY */
@@ -11006,6 +11543,18 @@ Returns number:\n");
   Returns decimal equivalent.\n");
         break;
 
+      case FN_TOB64:
+        printf("\\b64encode(s)\n\
+  s = string containing no NUL bytes\n\
+  Returns Base-64 encoding of string.\n");
+        break;
+
+      case FN_FMB64:
+        printf("\\b64decode(s)\n\
+  s = string in Base-64 notation\n\
+  Returns the decoded string or an error code if s not valid.\n");
+        break;
+
       case FN_RADIX:
         printf("\\fradix(s,n1,n2)\n\
   s = number in radix n1\n\
@@ -11024,6 +11573,10 @@ Returns number:\n");
         printf("\
   Returns the (selected) elements of the array joined to together,\n\
   separated by the separator.\n");
+       printf("\n\
+  If s is CSV (literally), that means the array is to be transformed into a\n\
+  comma-separated list.  No other arguments are needed.  If s is TSV, then\n\
+  a tab-separated list is created.\n");
         break;
 
       case FN_SUBST:
@@ -11032,10 +11585,11 @@ Returns number:\n");
   s2 = List of characters to be translated.\n\
   s3 = List of characters to translate them to.\n");
         printf(
-"  Returns: s1, with each character that is in s2 translated to the\n\
+"  Returns: s1, with each character that is in s2 replaced by the\n\
   corresponding character in s3.  s2 and s3 can contain ASCII ranges,\n\
   like [a-z].  Any characters in s2 that don't have corresponding\n\
-  characters in s3 (after range expansion) are removed from the result.\n");
+  characters in s3 (after range expansion) are removed from the result.\n\
+  This function works only with single-byte character-sets\n");
         break;
 
 #ifndef NOSEXP
@@ -11134,16 +11688,18 @@ Returns number:\n");
 #endif /* FN_ERRMSG */
 
       case FN_KWVAL:
-        printf("\\fkeywordvalue(s1,c1)\n\
+        printf("\\fkeywordvalue(s1[,s2])\n\
   s1 = string of the form \"name=value\"\n\
-  c1 = separator character (default separator is \"=\")\n");
-        printf("    Assigns the value, if any, to the named macro.\n");
-        printf("    If s1 contains no separator, nothing happens.\n");
-        printf(
-"    If s1 contains a separator but no value, the macro is undefined.\n");
+  s2 = one more separator characters (default separator is \"=\")\n");
+        printf("    Assigns the value, if any, to the named macro and sets\n");
+        printf("    the \\v(lastkeywordvalue) to the macro name.\n");
+        printf("    If no value is given, the macro is undefined.\n");
         printf("Returns:\n");
-        printf("  0 on failure\n");
-        printf("  1 on success\n");
+        printf(" -1 on error\n");
+        printf("  0 if no keyword or value were found\n");
+        printf("  1 if a keyword was found but no value\n");
+        printf("  2 if a keyword and a value were found\n");
+        printf("Synonym: \\kwvalue(s1[,s2])\n");
         break;
 
 #ifdef COMMENT
@@ -11186,6 +11742,99 @@ Returns number:\n");
         break;
 #endif /* NT */
 
+      case FN_EMAIL:
+        printf("\\femailaddress(s)\n\
+  s = From: or Sender: header from an RFC2822-format email message\n");
+        printf("    Extracts and returns the email address.\n");
+        break;
+
+      case FN_PICTURE:
+        printf("\\fpictureinfo(s[,&a])\n\
+  s  = File specification of a JPG or GIF picture file.\n\
+  &a = Optional array name.\n\n");
+        printf("Returns integer:\n\
+  0 if file not found or not recognized;\n\
+  1 if orientation is landscape;\n\
+  2 if orientation is portrait.\n\n"); 
+       printf("  If an array name is included, element 1 is filled \
+in with the image width\n\
+  in pixels, and element 2 the image height.\n");
+       break;
+
+      case FN_PID:
+        printf("\\fgetpidinfo(n1)\n\
+ n1 = Numeric process ID\n");
+        printf("Returns integer:\n\
+ -1 on failure to get information;\n\
+  1 if n1 is the ID of an active process;\n\
+  0 if the process does not exist.\n"); 
+        break;
+
+      case FN_FUNC:
+       printf("\\ffunction(s1)\n\
+ s1 = name of function.\n");
+        printf("Returns integer:\n\
+  1 if s1 is the name of an available built-in function;\n\
+  0 otherwise.\n"); 
+        break;
+
+      case FN_RECURSE:
+       printf("\\frecurse(s1)\n\
+ s1 = name of \\&x or \\&x[] type variable\n");
+        printf("Returns the result of evaluating the variable recursively.\n");
+        break;
+
+      case FN_SQUEEZE:
+        printf("\\fsqueeze(s)\n\
+  s = string\n\
+    Returns string with leading and trailing whitespace removed, Tabs\n\
+    converted to Spaces, and multiple spaces converted to single spaces.\n");
+        break;
+
+#ifndef NOCSETS
+      case FN_XLATE:
+        printf("\\fcvtcset(s,cset1,cset2)\n\
+  s = string\n\
+    Returns string converted from character set cset1 to cset2, where cset1\n\
+    and cset2 are names of File Character-Sets \
+('set file char ?' for a list).\n");
+        break;
+#endif /* NOCSETS */
+
+      case FN_UNPCT:
+        printf("\\fdecodehex(s1[,s2])\n\
+  s1, s2 = strings\n\
+    Decodes a string s1 that contains prefixed hex bytes.  s2 is the prefix;\n\
+    the default is %%%%.  You can specify any other prefix one or two bytes\n\
+    long.  If the prefix contains letters (such as 0x), case is ingored.\n\
+    Returns string s1 with hex escapes replaced by the bytes they \
+represent.\n");
+        break;
+
+      case FN_STRINGT:
+        printf("\\fstringtype(s)\n\
+  s = string\n\
+    Returns a string representing the type of its string argument s1:\n\
+    7BIT, 8BIT, UTF8, TEXT, or BINARY.  TEXT means some kind of text\n\
+    other than 7BIT, 8BIT, or UTF8 (this probably will never appear).\n");
+        break;
+
+      case FN_STRCMP:
+        printf("\\fstrcmp(s1,s2[,case[,start[,length]]])\n\
+  s1, s2 = strings\n\
+  case, start, length = numbers or arithmetic expressions.\n\
+    case = 0 [default] means to do a case-independent comparison;\n\
+    nonzero case requests a case-sensitive comparison.\n\
+    The optional start and length arguments apply to both s1 and s2\n\
+    and allow specification of substrings if it is not desired to compare\n\
+    the whole strings.  Results for non-ASCII strings are implentation-\n\
+    and locale-dependent.\n\
+  Returns a number:\n\
+    -1: s1 is lexically less than s2;\n\
+     0: s1 and s2 are lexically equal;\n\
+     2: s1 is lexically greater than s2.\n");
+        break;
+
       default:
         printf("Sorry, help not available for \"%s\"\n",cmdbuf);
     }
@@ -13747,6 +14396,10 @@ case XZLGO:
   Logs out from a remote Kermit server to which you have previously logged in."
 ));
 
+case XZMSG:
+    return(hmsg("Syntax: REMOTE MESSAGE text\n\
+  Sends a short text message to the remote Kermit server."));
+
 case XZPRI:
     return(hmsg("Syntax: REMOTE PRINT filespec [ options ]\n\
   Sends the specified file(s) to the remote Kermit and ask it to have the\n\
index 8d2f8b6..f232159 100644 (file)
--- a/ckuus3.c
+++ b/ckuus3.c
@@ -13,7 +13,7 @@
     Jeffrey E Altman <jaltman@secure-endpoints.com>
       Secure Endpoints Inc., New York City
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2009,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -83,6 +83,10 @@ extern char * exedir;
 extern int cm_retry;
 #endif /* CK_RECALL */
 
+#ifdef NEWFTP
+extern int ftpisopen();
+#endif /* NEWFTP */
+
 extern int cmdint;
 extern int srvidl;
 
@@ -107,9 +111,16 @@ char browsurl[4096] = { NUL, NUL };
 #endif /*  NOFRILLS */
 #endif /* NOPUSH */
 
+#ifndef NOFRILLS
+#ifndef NORENAME
+_PROTOTYP(int setrename, (void));
+#endif /* NORENAME */
+#endif /* NOFRILLS */
+
 /* Variables */
 
 int cmd_quoting = 1;
+int cmd_err = 1;
 extern int hints, xcmdsrc;
 
 #ifdef CK_KERBEROS
@@ -133,7 +144,7 @@ extern int
   mdmtyp, network, quiet, nettype, carrier, debses, debtim, cdtimo, nlangs,
   bgset, pflag, msgflg, cmdmsk, xsuspend, techo, pacing, xitwarn, xitsta,
   outesc, cmd_cols, cmd_rows, ckxech, xaskmore, haveline, didsetlin, isguest,
-  mdmsav, clearrq, saveask;
+  mdmsav, clearrq, saveask, debmsg;
 
 extern int reliable, setreliable, matchdot, matchfifo, dir_dots;
 
@@ -290,7 +301,7 @@ extern CHAR myctlq;                     /* Control-character prefix */
 extern CHAR myrptq;                     /* Repeat-count prefix */
 
 extern int protocol, size, spsiz, spmax, urpsiz, srvtim, srvcdmsg, slostart,
-  srvdis, xfermode, ckdelay, keep, maxtry, unkcs, bctr, ebqflg, swcapr,
+  srvdis, xfermode, ckdelay, keep, maxtry, unkcs, bctr, bctf, ebqflg, swcapr,
   wslotr, lscapr, lscapu, spsizr, rptena, rptmin, docrc, xfrcan, xfrchr,
   xfrnum, xfrbel, xfrint, srvping, g_xfermode, xfrxla;
 
@@ -336,6 +347,7 @@ extern int tlevel;                      /* Take Command file level */
 #ifndef NOLOCAL
 extern int sessft;                      /* Session-log file type */
 extern int slogts;                      /* Session-log timestamps on/off */
+extern int slognul;                    /* Lines null-terminated */
 #endif /* NOLOCAL */
 
 char * tempdir = NULL;
@@ -385,9 +397,12 @@ struct keytab chktab[] = {              /* Block check types */
     "1", 1, 0,                          /* 1 =  6-bit checksum */
     "2", 2, 0,                          /* 2 = 12-bit checksum */
     "3", 3, 0,                          /* 3 = 16-bit CRC */
-    "4", 4, CM_INV,                     /* Same as B */
-    "blank-free-2", 4, 0                /* B = 12-bit checksum, no blanks */
+    "4", 4, 0,                         /* Same as B */
+    "5", 5, 0,                         /* Same as F */
+    "blank-free-2", 4, CM_INV,         /* B = 12-bit checksum, no blanks */
+    "force-3", 5, CM_INV               /* F = Force CRC on ALL packets */
 };
+static int nchkt = (sizeof(chktab) / sizeof(struct keytab));
 
 struct keytab rpttab[] = {              /* SET REPEAT */
     "counts",    0, 0,                  /* On or Off */
@@ -414,6 +429,17 @@ struct keytab ooatab[] = {              /* On/Off/Auto table */
     "on",        SET_ON,   0            /* 1 */
 };
 
+struct keytab ooetab[] = {              /* On/Off/Stderr table 2010/03/12 */
+    "off",       SET_OFF, 0,           /* for SET DEBUG MESSAGES */
+    "on",        SET_ON,  0,
+    "s",         2,       CM_ABR|CM_INV,
+    "st",        2,       CM_ABR|CM_INV,
+    "std",       2,       CM_ABR|CM_INV,
+    "stderr",    2,       0,
+    "stdout",    SET_ON,  CM_INV
+};
+static int nooetab = (sizeof(ooetab) / sizeof(struct keytab));
+
 struct keytab ooktab[] = {              /* On/Off/Ask table */
     "ask",       2,        0,           /* 2 */
     "off",       SET_OFF,  0,           /* 0 */
@@ -433,9 +459,13 @@ int nqvt = 2;
 #define DEB_SES  2
 #define DEB_TIM  3
 #define DEB_LEN  4
+#define DEB_MSG  5
 
 struct keytab dbgtab[] = {
     "linelength", DEB_LEN, CM_INV,
+    "m",          DEB_MSG, CM_ABR|CM_INV,
+    "message",    DEB_MSG, 0,
+    "msg",        DEB_MSG, CM_INV,
     "off",        DEB_OFF, 0,
     "on",         DEB_ON,  0,
     "session",    DEB_SES, 0,
@@ -655,6 +685,7 @@ static struct keytab sfttab[] = {       /* File types for SET SESSION-LOG */
     "ascii",     XYFT_T, CM_INV,
     "binary",    XYFT_B, 0,
     "debug",     XYFT_D, 0,
+    "null-padded-lines", 998, 0,
     "text",      XYFT_T, 0,
     "timestamped-text", 999, 0
 };
@@ -951,11 +982,21 @@ extern int tapiusecfg;
 
 #ifndef NOPUSH
 extern int nopush;
+extern int wildena;
 #ifdef UNIX
 struct keytab wildtab[] = {             /* SET WILDCARD-EXPANSION */
-    "kermit",  0, 0,
-    "shell",   1, 0
+#ifdef UNIX
+    "kermit",  WILD_KER, 0,            /* By Kermit */
+#endif /* UNIX */
+    "off",     WILD_OFF, 0,            /* Disabled */
+    "on",      WILD_ON,  0,            /* Enabled */
+#ifdef UNIX
+    "shell",   WILD_SHE, 0,            /* By Shell */
+#endif /* UNIX */
+    "", 0, 0
 };
+int nwild = (sizeof(wildtab) / sizeof(struct keytab)) - 1;
+
 struct keytab wdottab[] = {             /* cont'd */
     "/match-dot-files",    1, 0,
     "/no-match-dot-files", 0, 0
@@ -1019,6 +1060,10 @@ static struct keytab vbtab[] = {
     "brief",   0, 0,
 #ifdef OS2ORUNIX
     "ftp",     2, 0,
+#else
+#ifdef VMS
+    "ftp",     2, 0,
+#endif /* def VMS */
 #endif /* OS2ORUNIX */
     "verbose", 1, 0
 };
@@ -1189,6 +1234,8 @@ struct keytab scrtab[] = {
 #define SCMD_DBQ 13    /* DOUBLEQUOTING */
 #define SCMD_CBR 14    /* CBREAK */
 #define SCMD_BFL 15    /* BUFFER-SIZE (not used) */
+#define SCMD_ERR 16    /* ERROR */
+#define SCMD_VAR 17    /* VARIABLE-EVALUATION */
 
 static struct keytab scmdtab[] = {
 #ifdef CK_AUTODL
@@ -1211,6 +1258,7 @@ static struct keytab scmdtab[] = {
 #ifdef DOUBLEQUOTING
     "doublequoting",      SCMD_DBQ, 0,
 #endif /* DOUBLEQUOTING */
+    "error-display",      SCMD_ERR, 0,
     "height",             SCMD_HIG, 0,
     "interruption",       SCMD_INT, 0,
     "more-prompting",     SCMD_MOR, 0,
@@ -1227,6 +1275,7 @@ static struct keytab scmdtab[] = {
     "statusline",         SCMD_STA, 0,
 #endif /* ONETERMUPD */
 #endif /* OS2 */
+    "variable-evaluation", SCMD_VAR,0,
     "width",              SCMD_WID, 0
 };
 static int nbytt = (sizeof(scmdtab) / sizeof(struct keytab));
@@ -2085,7 +2134,7 @@ struct keytab ftrtab[] = {              /* Feature table */
 "xyzmodem",             0, 0,
 #else
 "xyzmodem",             1, 0,
-#endif /* NOXMIT */
+#endif /* CK_XYZ */
 
 "", 0, 0
 };
@@ -3224,7 +3273,8 @@ douchmod() {
 
 struct keytab sexptab[] = {
     "depth-limit", 1, 0,
-    "echo-result", 0, 0
+    "echo-result", 0, 0,
+    "truncate-all-results", 2
 };
 
 static int sexpmaxdep = 1000;           /* Maximum depth */
@@ -3307,18 +3357,18 @@ static struct keytab sexpops[] = {      /* Built-in operators */
     "not",     SX_NOT, SXF_ONE,         /* NOT */
     "mod",     SX_MOD, SXF_TWO,         /* Modulus */
 
-    "<",       SX_ALT, SXF_PRE|SXF_TWO, /* Comparisons */
-    ">",       SX_AGT, SXF_PRE|SXF_TWO,
-    "<=",      SX_ALE, SXF_PRE|SXF_TWO,
-    "=",       SX_AEQ, SXF_PRE|SXF_TWO,
-    ">=",      SX_AGE, SXF_PRE|SXF_TWO,
-    "!=",      SX_NEQ, SXF_PRE|SXF_TWO,
+    "<",       SX_ALT, SXF_PRE,                /* Comparisons */
+    ">",       SX_AGT, SXF_PRE,
+    "<=",      SX_ALE, SXF_PRE,
+    "=",       SX_AEQ, SXF_PRE,
+    ">=",      SX_AGE, SXF_PRE,
+    "!=",      SX_NEQ, SXF_PRE,
 
     "++",      SX_INC, SXF_ONE|SXF_TWO, /* Increment */
     "--",      SX_DEC, SXF_ONE|SXF_TWO, /* Decrement */
 
     "**",      SX_POW, SXF_TWO,         /* Common synonyms */
-    "==",      SX_AEQ, SXF_PRE|SXF_TWO,
+    "==",      SX_AEQ, SXF_PRE,
     "!",       SX_NOT, SXF_ONE,
     ".",       SX_EVA, 0,
 
@@ -3372,6 +3422,7 @@ static int nsexpconsts = (sizeof(sexpconsts) / sizeof(struct keytab)) - 1;
 
 int sexprc = 0;                         /* S-Expression error flag */
 int sexppv = -1;                        /* Predicate value */
+static int sexptrunc = 0;              /* Flag to force all results to int */
 
 #define SXMLEN 64                       /* Macro arg list initial length */
 #include <math.h>                       /* Floating-point functions */
@@ -3399,6 +3450,8 @@ shosexp() {
     printf(" maximum depth reached:   %d\n",sexpdmax);
     printf(" longest result returned: %d\n",sexprmax);
     printf("\n");
+    printf(" truncate all results:    %s\n",showoff(sexptrunc));
+    printf("\n");
     printf(" last sexpression:        %s\n",lastsexp ? lastsexp : "(none)");
     printf(" last value:              %s\n",sexpval ? sexpval : "(none)");
     printf("\n");
@@ -3431,9 +3484,10 @@ dosexp(s) char *s; {                    /* s = S-Expression */
     int linepos = 0;
     int quote = 0;                      /* LISP quote flag */
     char * s2;                          /* Workers */
-    int i, j, k, n = 0, x = 0, kw, kwflags, mx = 0;
-    int result = 0, not = 0, truncate = 0, builtin = 0;
+    int kw, kwflags, mx = 0, x = 0;
+    int not = 0, truncate = 0, builtin = 0;
     int fpflag = 0, quit = 0, macro = 0;
+    CK_OFF_T result = 0, i, j, k, n = 0;
     CKFLOAT fpj, fpresult = 0.0;        /* Floating-point results */
     int pflag = 0;                      /* Have predicate */
     int presult = 0;                    /* Predicate result */
@@ -3442,6 +3496,8 @@ dosexp(s) char *s; {                    /* s = S-Expression */
     sexppv = -1;                        /* Predicate value */
     s2 = "";                            /* Default return value */
 
+    debug(F111,sexpdebug("entry 1"),s,sexprc);
+
     if (++sexpdep > sexpmaxdep) {       /* Keep track of depth */
         printf("?S-Expression depth limit exceeded: %d\n",sexpmaxdep);
         sexprc++;
@@ -3453,14 +3509,13 @@ dosexp(s) char *s; {                    /* s = S-Expression */
     if (sexprc)                         /* Error, quit all levels */
       goto xdosexp;                     /* Always goto common exit point */
 
-    debug(F111,sexpdebug("entry"),s,sexprc);
+    debug(F111,sexpdebug("entry 2"),s,sexprc);
 
     if (!s) s = "";                     /* Null or empty arg */
 
     while (*s == SP) s++;               /* Strip leading spaces */
     if (!*s)                            /* so empty result */
       goto xdosexp;
-
 /*
   Allocate result stack upon first use, or after it has been resized with
   SET SEXP DEPTH-LIMIT.
@@ -3612,7 +3667,6 @@ dosexp(s) char *s; {                    /* s = S-Expression */
             }
             if (!x) {                   /* None of the above, look it up */
                 x = xlookup(sexpops,p[1],nsexpops,&kw);
-               debug(F111,"XXX",p[1],x);
                 if (x > 0) {
                     kwflags = sexpops[kw].flgs;
                     builtin = 1;
@@ -3640,7 +3694,7 @@ dosexp(s) char *s; {                    /* s = S-Expression */
     }
     if (n == 1) {                       /* Not an expression */
         if (builtin) {                  /* Built-in operand? */
-            switch (x) {                /* Operators with default values */
+            switch (x) {               /* Operators with default values */
               case SX_EVA:
                 s2 = "";
                 goto xdosexp;
@@ -3772,6 +3826,11 @@ dosexp(s) char *s; {                    /* s = S-Expression */
                 }
             }
             if (kwflags & SXF_PRE) {    /* Predicate? */
+               if (n < 2) {
+                   printf("?Too few operands - \"%s\"\n",s);
+                   sexprc++;
+                   goto xdosexp;
+               }
                 pflag = 1;
                 presult = 1;
             }
@@ -3849,7 +3908,7 @@ dosexp(s) char *s; {                    /* s = S-Expression */
                         goto xdosexp;
                     }
                     while (*s2 == '+') s2++;
-                    result = atoi(s2);
+                    result = ckatofs(s2);
                     fpresult = floatval;
                     if (k > 1 || fpresult != result)
                       fpflag++;
@@ -3883,7 +3942,7 @@ dosexp(s) char *s; {                    /* s = S-Expression */
                         goto xdosexp;
                     }
                     while (*s2 == '+') s2++;
-                    j = atoi(s2);
+                    j = ckatofs(s2);
                     if (k > 1) {
                         fpj = floatval;
                         fpflag++;
@@ -3897,8 +3956,11 @@ dosexp(s) char *s; {                    /* s = S-Expression */
                         result -= j;
                         fpresult -= fpj;
                     }
+#ifdef FNFLOAT
                     if (result != fpresult) fpflag++;
-                    s2 = fpflag ? fpformat(fpresult,0,0) : ckitoa(result);
+#endif /* FNFLOAT */
+                    s2 = (fpflag && !sexptrunc) ?
+                       fpformat(fpresult,0,0) : ckfstoa(result);
                 }
                 if (x == SX_LET && cmdlvl > 0) /* LET makes var local */
                   addlocal(p[i+1]);
@@ -3913,7 +3975,7 @@ dosexp(s) char *s; {                    /* s = S-Expression */
                     sexprc++;
                     goto xdosexp;
                 }
-                if (s2) result = atoi(s2);
+                if (s2) result = ckatofs(s2);
             }
             goto xdosexp;
         } else if (x == SX_IFC) {               /* Conditional expression */
@@ -3926,7 +3988,7 @@ dosexp(s) char *s; {                    /* s = S-Expression */
             s2 = dosexp(p[2]);
             if (sexprc) goto xdosexp;
             if (s2) {
-                j = atoi(s2);
+                j = ckatofs(s2);
                 if (xxfloat(s2,0) == 2) {
                     fpflag++;
                     fpresult = (CKFLOAT)result;
@@ -3941,7 +4003,7 @@ dosexp(s) char *s; {                    /* s = S-Expression */
             } else {
                 s2 = dosexp(true ? p[3] : p[4]);
                 if (sexprc) goto xdosexp;
-                j = s2 ? atoi(s2) : 0;
+                j = s2 ? ckatofs(s2) : 0;
                 if (xxfloat(s2,0) == 2) {
                     fpflag++;
                     fpresult = (CKFLOAT)result;
@@ -4098,7 +4160,7 @@ dosexp(s) char *s; {                    /* s = S-Expression */
             j = 0;
             fpj = 0.0;
         } else {
-            j = atoi(s2);
+            j = ckatofs(s2);
             /* Switch to floating-point upon encountering any f.p. arg */
             /* OR... if integer is too big */
             if (!fpflag) if (xxfloat(s2,0) == 2)
@@ -4108,6 +4170,9 @@ dosexp(s) char *s; {                    /* s = S-Expression */
         if (i == 1) {                   /* Initial result is first operand */
             result = (n == 2 && x == SX_SUB) ? 0-j : j;
             fpresult = (n == 2 && x == SX_SUB) ? -fpj : fpj;
+           if ((x == SX_AND && result == 0) || /* Short circuit */
+               (x == SX_LOR && result != 0))
+             quit++;
             if (!(kwflags & SXF_ONE))   /* Command with single arg */
               continue;
         }
@@ -4120,7 +4185,7 @@ dosexp(s) char *s; {                    /* s = S-Expression */
                 goto xdosexp;
             }
         }
-        switch (x) {                    /* Accumulate result */
+        switch (x) {                   /* Accumulate result */
 
           case SX_EVA:                  /* EVAL */
             result = j;
@@ -4130,22 +4195,28 @@ dosexp(s) char *s; {                    /* s = S-Expression */
           case SX_ADD:                  /* + */
             result += j;
             fpresult += fpj;
+#ifdef FNFLOAT
             if (result != fpresult)
               fpflag++;
+#endif /* FNFLOAT */
             break;
 
           case SX_SUB:                  /* - */
             result -= j;
             fpresult -= fpj;
+#ifdef FNFLOAT
             if (result != fpresult)
               fpflag++;
+#endif /* FNFLOAT */
             break;
 
           case SX_MUL:                  /* * */
             result *= j;
             fpresult *= fpj;
+#ifdef FNFLOAT
             if (result != fpresult)
               fpflag++;
+#endif /* FNFLOAT */
             break;
 
           case SX_AND:                  /* AND */
@@ -4172,10 +4243,20 @@ dosexp(s) char *s; {                    /* s = S-Expression */
             break;
 
           case SX_DIV:                  /* / */
-            result /= j;
-            fpresult /= fpj;
-            if (result != fpresult)
-              fpflag++;
+           if (j) {
+               result /= j;
+               fpresult /= fpj;
+#ifdef FNFLOAT
+               if (result != fpresult)
+                 fpflag++;
+#endif /* FNFLOAT */
+           } else {
+               fpresult /= fpj;
+               result = fpj;
+#ifdef FNFLOAT
+                 fpflag++;
+#endif /* FNFLOAT */
+           }
             break;
 
           case SX_AEQ:                  /* Test for equality */
@@ -4268,7 +4349,7 @@ dosexp(s) char *s; {                    /* s = S-Expression */
             if (j == 0) {
                 result = 1;
             } else {
-                int z, sign = 0;
+                CK_OFF_T z, sign = 0;
                 if (j < 0) {
                     if (result == 0) {
                         printf("?Divide by zero - \"%s\"\n",cmdbuf);
@@ -4284,8 +4365,10 @@ dosexp(s) char *s; {                    /* s = S-Expression */
                 if (sign)
                   result = 1 / result;
             }
+#ifdef FNFLOAT
             if (result != fpresult)
               fpflag++;
+#endif /* FNFLOAT */
             break;
 
 #ifdef FNFLOAT
@@ -4358,9 +4441,11 @@ dosexp(s) char *s; {                    /* s = S-Expression */
 
           case SX_ABS:                  /* Absolute value */
             result = (j < 0) ? 0 - j : j;
+#ifdef FNFLOAT
             fpresult = (fpj < 0.0) ? 0.0 - fpj : fpj;
             if (result != fpresult)
               fpflag++;
+#endif /* FNFLOAT */
             break;
 
           case SX_MAX:                  /* Max */
@@ -4482,12 +4567,12 @@ dosexp(s) char *s; {                    /* s = S-Expression */
         if (not) presult = presult ? 0 : 1;
         sexppv = presult;               /* So set predicate value (0 or 1) */
         s2 = presult ? "1" : "0";
-    } else if (fpflag) {                /* Result is floating-point */
+    } else if (fpflag && !sexptrunc) { /* Result is floating-point */
         if (not) fpresult = fpresult ? 0.0 : 1.0;
         s2 = fpformat(fpresult,0,0);
     } else if (x != SX_EVA) {
         if (not) result = result ? 0 : 1;
-        s2 = ckitoa(result);
+        s2 = ckfstoa(result);
     }
 
 /* Common exit point.  Always come here to exit. */
@@ -4611,7 +4696,6 @@ dologend() {                            /* Write record to connection log */
     if (autolocus) {
         int x = locus;
 #ifdef NEWFTP
-        extern int ftpisconnected();
        debug(F101,"dologend ftpisconnected","",ftpisconnected());
         setlocus(ftpisconnected() ? 0 : 1, 1);
 #else
@@ -4653,8 +4737,8 @@ dologend() {                            /* Write record to connection log */
         cx_prev = t2;
         p = hhmmss(t2);
         debug(F110,"dologend hhmmss",p,0);
-        strncat(cxlogbuf,"E=",CXLOGBUFL); /* Append to log record */
-        strncat(cxlogbuf,p,CXLOGBUFL);
+        ckstrncat(cxlogbuf,"E=",CXLOGBUFL); /* Append to log record */
+        ckstrncat(cxlogbuf,p,CXLOGBUFL);
         debug(F110,"dologend cxlogbuf 2",cxlogbuf,0);
     } else
       cx_prev = 0L;
@@ -4806,6 +4890,7 @@ dologshow(fc) int fc; {                 /* SHOW (current) CONNECTION */
             switch (c) {
               case 'T': printf(" Type:         %s\n", s); break;
               case 'N': printf(" To:           %s\n", s); break;
+              case 'P': printf(" Port:         %s\n", s); break;
               case 'H': printf(" From:         %s\n", s); break;
               case 'D': printf(" Device:       %s\n", s); break;
               case 'O': printf(" Origin:       %s\n", s); break;
@@ -4884,7 +4969,9 @@ dologline() {
 VOID
 dolognet() {
     char * p, * s = "NET", * uu = uidbuf;
-    int n, m;
+    char * port = "";
+    int n, m, tcp = 0;
+    char * h = NULL;
 
     dologend();                         /* Previous session not closed out? */
     cx_prev = 0L;
@@ -4892,8 +4979,13 @@ dolognet() {
     p = ckdate();
     n = ckstrncpy(cxlogbuf,p,CXLOGBUFL);
 #ifdef TCPSOCKET
-    if (nettype == NET_TCPB || nettype == NET_TCPA)
-      s = "TCP";
+    if (nettype == NET_TCPB || nettype == NET_TCPA) {
+       tcp++;
+       s = "TCP";
+    } else if (nettype == NET_SSH) {
+       s = "SSH";
+       tcp++;
+    }
 #endif /* TCPSOCKET */
 #ifdef ANYX25
     if (nettype == NET_SX25 || nettype == NET_VX25 || nettype == NET_IX25)
@@ -4924,19 +5016,37 @@ dolognet() {
 #endif /* STRATUS */
 #endif /* UNIX */
     }
+#ifdef TCPSOCKET
+    if (tcp) {
+       int k;
+       makestr(&h,myhost);
+       if ((k = ckindex(":",h,0,0,0)) > 0) {
+           h[k-1] = NUL;
+           port = &h[k];
+       } else {
+           int svcnum = gettcpport();
+           if (svcnum > 0)
+             port = ckitoa(svcnum);
+           else
+             port = "unk";
+       }
+    }
+#endif /* TCPSOCKET */
     m = strlen(uu) + strlen(myhost) + strlen(ttname) + strlen(s) + 32;
     if (n+m < CXLOGBUFL-1) {            /* SAFE */
         p = cxlogbuf+n;
-        sprintf(p," %s %s T=%s N=%s H=%s ",
+        sprintf(p," %s %s T=%s N=%s H=%s P=%s ",
                 uu,
                 ckgetpid(),
                 s,
                 ttname,
-                myhost
+                myhost,
+               port
                 );
     } else
       ckstrncpy(cxlogbuf,"LOGNET BUFFER OVERFLOW",CXLOGBUFL);
     debug(F110,"dolognet cxlogbuf",cxlogbuf,0);
+    if (h) makestr(&h,NULL);
 }
 #endif /* NETCONN */
 #endif /* CKLOGDIAL */
@@ -4971,7 +5081,7 @@ initmdm(x) int x; {
     m = usermdm ? usermdm : mdmtyp;
 
     p = modemp[m];                      /* Point to modem info struct, and */
-    debug(F101,"initmdm p","",p);
+    /* debug(F101,"initmdm p","",p); */
     if (p) {
         dialec = p->capas & CKD_EC;     /* set DIAL ERROR-CORRECTION, */
         dialdc = p->capas & CKD_DC;     /* DIAL DATA-COMPRESSION, and */
@@ -6175,6 +6285,37 @@ settapi() {
 #endif /* NOLOCAL */
 
 #ifndef NOSPL
+/* Method for evaluating \%x and \&x[] variables */
+
+static struct keytab varevaltab[] = {
+    { "recursive", 1, 0 },
+    { "simple",    0, 0 }
+};
+static int nvarevaltab = (sizeof(varevaltab) / sizeof(struct keytab));
+
+int
+setvareval() {
+    int x = 0, y = 0;
+    extern int vareval;
+#ifdef DCMDBUF
+    extern int * xvarev;
+#else
+    extern int xvarev[];
+#endif /* DCMDBUF */
+
+    if ((x = cmkey(varevaltab,
+                  nvarevaltab, 
+                  "Method for evaluating \\%x and \\&x[] variables",
+                  "",
+                  xxstring)) < 0)
+      return(x);
+    if ((y = cmcfm()) < 0)
+      return(y);
+    xvarev[cmdlvl] = x;
+    vareval = x;
+    return(success = 1);
+}
+
 #ifdef CK_ANSIC                         /* SET ALARM */
 int
 setalarm(long xx)
@@ -6576,6 +6717,21 @@ struct keytab protos[] = {
 };
 int nprotos =  (sizeof(protos) / sizeof(struct keytab));
 
+#ifndef XYZ_INTERNAL
+#ifndef NOPUSH
+#define EXP_HANDLER 1
+#define EXP_STDERR  2
+#define EXP_TIMO    3
+
+static struct keytab extprotab[] = {
+    { "handler",          EXP_HANDLER, 0 },
+    { "redirect-stderr",  EXP_STDERR, 0 },
+    { "timeout",          EXP_TIMO, 0 }
+};
+static int nxtprotab =  (sizeof(extprotab) / sizeof(struct keytab));
+#endif /* NOPUSH */
+#endif /* XYZ_INTERNAL */
+
 #define XPCMDLEN 71
 
 _PROTOTYP(static int protofield, (char *, char *, char *));
@@ -6728,6 +6884,65 @@ protoexit:                              /* Common exit from this routine */
     return(success = 1);
 }
 
+#ifndef NOPUSH
+#ifndef XYZ_INTERNAL
+
+#define DEF_EXP_TIMO 12         /* Default timeout for external protocol (seconds) */
+
+int exp_handler = 0;                   /* These are exported */
+int exp_timo = DEF_EXP_TIMO;
+int exp_stderr = SET_AUTO;
+
+VOID
+shoextern() {                          /* Invoked by SHOW PROTOCOL */
+    printf("\n External-protocol handler:         %s\n",
+          exp_handler ? (exp_handler == 1 ? "pty" : "system") : "automatic");
+#ifdef COMMENT
+    printf(" External-protocol redirect-stderr: %s\n", showooa(exp_stderr));
+#endif /* COMMENT */
+    printf(" External-protocol timeout:         %d (sec)\n", exp_timo);
+}
+
+static struct keytab setexternhandler[] = {
+    { "automatic", 0, 0 },
+    { "pty",       1, 0 },
+    { "system",    2, 0 }
+};
+
+int
+setextern() {                          /* SET EXTERNAL-PROTOCOL */
+    int x, y;
+    if ((x = cmkey(extprotab,nxtprotab,"","",xxstring)) < 0)
+      return(x);
+    switch (x) {
+      case EXP_HANDLER:
+       if ((x = cmkey(setexternhandler,3,"","automatic",xxstring)) < 0)
+         return(x);
+       if ((y = cmcfm()) < 0)
+         return(y);
+       exp_handler = x;
+       break;
+       
+#ifdef COMMENT
+      case EXP_STDERR:
+       if ((x = cmkey(ooatab,3,"","automatic",xxstring)) < 0)
+         return(x);
+       if ((y = cmcfm()) < 0)
+         return(y);
+       exp_stderr = x;
+       break;
+#endif /* COMMENT */
+
+      case EXP_TIMO:
+       y = cmnum("Inactivity timeout, seconds,",ckitoa(DEF_EXP_TIMO),
+                 10,&x,xxstring);
+        return(setnum(&exp_timo,x,y,-1));
+    }
+    return(success = 1);
+}
+#endif /* XYZ_INTERNAL */
+#endif /* NOPUSH */
+
 int
 setdest() {
     int x, y;
@@ -6821,10 +7036,7 @@ setprinter(xx) int xx; {
 #ifdef PRINTSWI
     int c, i, n, wild, confirmed = 0;   /* Workers */
     int getval = 0;                     /* Whether to get switch value */
-    struct stringint {                  /* Temporary array for switch values */
-        char * sval;
-        int ival;
-    } pv[PRN_MAX+1];
+    struct stringint pv[PRN_MAX+1];    /* Temporary array for switch values */
     struct FDB sw, of, cm;              /* FDBs for each parse function */
     int haveque = 0;
     int typeset = 0;
@@ -6856,6 +7068,7 @@ setprinter(xx) int xx; {
     for (i = 0; i <= PRN_MAX; i++) {    /* Initialize switch values */
         pv[i].sval = NULL;              /* to null pointers */
         pv[i].ival = -1;                /* and -1 int values */
+        pv[i].wval = (CK_OFF_T)-1;     /* and -1 wide values */
     }
     if (xx == XYBDCP) {                 /* SET BPRINTER == /BIDIRECTIONAL */
         pv[PRN_BID].ival = 1;
@@ -7196,7 +7409,7 @@ setprinter(xx) int xx; {
                        "auto-print/printscreen character-set",
                        "cp437",xxstring)) < 0)
                   goto xsetprn;
-              pv[n].ival = x;
+              pv[n].ival = y;
               break;
 #endif /* OS2 */
 
@@ -8184,7 +8397,7 @@ dosetssh() {
           case SSH2_UNH:
             if ((x = cmifi("Filename","",&s,&z,xxstring)) < 0) {
                 if (x != -3)
-                  return(y);
+                  return(x);
             } else {
                 ckstrncpy(line,s,LINBUFSIZ);
                 if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
@@ -8305,6 +8518,7 @@ extern ULONG RGBTable[16];
 #define GUI_DIA  4
 #define GUI_TLB  5
 #define GUI_MNB  6
+#define GUI_CLS  7
 
 #define GUIW_POS 1
 #define GUIW_RES 2
@@ -8317,6 +8531,7 @@ extern ULONG RGBTable[16];
 #define GUIWN_MAX 3
 
 static struct keytab guitab[] = {
+    { "close",       GUI_CLS,  0 },
     { "dialogs",     GUI_DIA,  0 },
     { "font",        GUI_FON,  0 },
     { "menubar",     GUI_MNB,  0 },
@@ -8565,6 +8780,12 @@ setguitoolbar(x) int x;
     KuiSetProperty(KUI_GUI_TOOLBAR, (long)x, 0L);
 }
 
+VOID
+setguiclose(x) int x;
+{
+    KuiSetProperty(KUI_GUI_CLOSE, (long)x, 0L);
+}
+
 int
 setgui() {
     int cx, x, rc;
@@ -8592,6 +8813,11 @@ setgui() {
         if (rc >= 0)
           setguimenubar(x);
         return(rc);
+      case GUI_CLS:
+        rc = seton(&x);
+        if (rc >= 0)
+          setguiclose(x);
+        return(rc);
       default:
         return(-2);
     }
@@ -8868,7 +9094,9 @@ necessary DLLs did not load.  Use SHOW NETWORK to check network status.\n");
               /* Construct default name  */
               if (z == NET_PIPE) {      /* Named pipe */
                   defnam = "kermit";    /* Default name is always "kermit" */
-              } else {                  /* NetBIOS */
+              } 
+#ifdef CK_NETBIOS
+             else {                    /* NetBIOS */
                   if (NetBiosName[0] != SP) { /* If there is already a name, */
                       char *p = NULL;
                       int n;            /* use it as the default. */
@@ -8885,7 +9113,8 @@ necessary DLLs did not load.  Use SHOW NETWORK to check network status.\n");
                   else                  /* Otherwise use "kermit" */
                     defnam = "kermit";
               }
-              if ((y = cmtxt((z == NET_PIPE) ? "pipe name" :
+#endif /* CK_NETBIOS */
+              if ((y = cmtxt((z == NET_PIPE) ? "name of named-pipe" :
                              "local NETBIOS name",
                              defnam, &s, xxstring)) < 0)
                 return(y);
@@ -9512,9 +9741,17 @@ necessary DLLs did not load.  Use SHOW NETWORK to check network status.\n");
       }
 
       case XYCHKT:                      /* BLOCK-CHECK */
-        if ((x = cmkey(chktab,4,"","3",xxstring)) < 0) return(x);
+        if ((x = cmkey(chktab,nchkt,"","3",xxstring)) < 0) return(x);
         if ((y = cmcfm()) < 0) return(y);
+       if (x == 5) {
+           bctf = 1;
+#ifdef COMMENT
+           printf("?5 - Not implemented yet\n");
+           return(success = 0);
+#endif /* COMMENT */
+       }
         bctr = x;                       /* Set local too even if REMOTE SET */
+
         if (rmsflg) {
             if (x == 4) {
                 tmpbuf[0] = 'B';
@@ -10283,11 +10520,7 @@ case XYCARR:                            /* CARRIER-WATCH */
               int i,len;
               if ((y = cmtxt("Prompt string","",&s,xxstring)) < 0)
                 return(y);
-              if (s == "") s = NULL;
-              if (s) {
-                  s = brstrip(s);
-                  if (s == "") s = NULL;
-              }
+             s = brstrip(s);
               /* we must check to make sure there are no % fields */
               len = strlen(s);
               for (i = 0; i < len; i++) {
@@ -10504,6 +10737,13 @@ case XYCARR:                            /* CARRIER-WATCH */
           }
 #endif /* DOUBLEQUOTING */
 
+         case SCMD_ERR:
+            y = cmnum("Error message verbosity level, 0-3","1",10,&x,xxstring);
+            return(setnum(&cmd_err,x,y,3));
+
+         case SCMD_VAR:
+           return(setvareval());
+
           default:
             return(-2);
         }
@@ -10569,6 +10809,12 @@ case XYDEBU:                            /* SET DEBUG { on, off, session } */
             setdebses(1);
 #endif /* NOLOCAL */
             return(success = 1);
+
+         case DEB_MSG:                 /* Debug messages 2010/03/12 */
+           if ((y = cmkey(ooetab,nooetab,"","on",xxstring)) < 0) return(y);
+           if ((x = cmcfm()) < 0) return(x);
+           debmsg = y;
+           return(1);
         }
         break;
 
@@ -11076,6 +11322,8 @@ case XYDEBU:                            /* SET DEBUG { on, off, session } */
         if (x == 999) {                 /* TIMESTAMPED-TEXT */
             sessft = XYFT_T;            /* Implies text */
             slogts = 1;                 /* and timestamps */
+       } else if (x == 998) {          /* NULL-PADDED-LINES */
+            slognul = 1;               /* adds NUL after ^J */
         } else {                        /* A regular type */
             sessft = x;                 /* The type */
             slogts = 0;                 /* No timestampes */
@@ -11243,7 +11491,7 @@ case XYDEBU:                            /* SET DEBUG { on, off, session } */
             lscapu = (y == 2) ? 2 : 0;  /* FORCED:  used = 1 */
             return(success = 1);
 
-#ifdef CK_XYZ
+/* #ifdef CK_XYZ */
           case XYX_PRO:                 /* Protocol */
 #ifndef OS2
             if (inserver) {
@@ -11252,7 +11500,7 @@ case XYDEBU:                            /* SET DEBUG { on, off, session } */
             }
 #endif /* OS2 */
             return(setproto());
-#endif /* CK_XYZ */
+/* #endif */ /* CK_XYZ */
 
           case XYX_MOD:                 /* Mode */
             if ((y = cmkey(xfrmtab,2,"","automatic",xxstring)) < 0)
@@ -11264,6 +11512,12 @@ case XYDEBU:                            /* SET DEBUG { on, off, session } */
             }
             g_xfermode = y;
             xfermode = y;
+#ifdef NEWFTP
+           if (ftpisopen()) {          /* If an FTP connection is open */
+               extern int ftp_xfermode; /* change its transfer mode too */
+               ftp_xfermode = xfermode;
+           }         
+#endif /* NEWFTP */
             return(success = 1);
 
 #ifndef NOLOCAL
@@ -11340,8 +11594,8 @@ case XYDEBU:                            /* SET DEBUG { on, off, session } */
 #ifndef NOPUSH
 #ifdef UNIX
       case XYWILD:                      /* WILDCARD-EXPANSION */
-        if ((y = cmkey(wildtab,2,
-                       "Who expands wildcards","kermit",xxstring)) < 0)
+        if ((y = cmkey(wildtab,nwild,
+                       "Wildcard expansion option","on",xxstring)) < 0)
           return(y);
         if ((z = cmkey(wdottab,
                        2,
@@ -11357,7 +11611,20 @@ case XYDEBU:                            /* SET DEBUG { on, off, session } */
                 return(success = 0);
             }
         }
-        wildxpand = y;
+       switch (y) {
+         case WILD_ON:
+           wildena = 1; 
+           break;
+         case WILD_OFF:
+           wildena = 0; 
+           break;
+         case WILD_KER:
+           wildxpand = 0;              /* These are the previous */
+           break;                      /* hardwired values */
+         case WILD_SHE:
+           wildxpand = 1; 
+           break;
+       }
         matchdot = z;
         return(success = 1);
 #endif /* UNIX */
@@ -12400,11 +12667,7 @@ case XYDEBU:                            /* SET DEBUG { on, off, session } */
                       krb4_autodel = z;
                     break;
                   case XYKRBPRM:        /* Prompt */
-                    if (s == "") s = NULL;
-                    if (s) {
-                        s = brstrip(s);
-                        if (s == "") s = NULL;
-                    }
+                   s = brstrip(s);
                     switch (z) {
                       case KRB_PW_PRM: { /* Password */
                           /* Check that there are no more than */
@@ -12487,11 +12750,7 @@ case XYDEBU:                            /* SET DEBUG { on, off, session } */
                   return(y);
                 switch (x) {            /* Copy value to right place */
                   case XYSRPPRM:        /* Prompt */
-                    if (s == "") s = NULL;
-                    if (s) {
-                        s = brstrip(s);
-                        if (s == "") s = NULL;
-                    }
+                   s = brstrip(s);
                     switch (z) {
                       case SRP_PW_PRM: { /* Password */
                           /* Check %s fields */
@@ -12997,7 +13256,7 @@ case XYDEBU:                            /* SET DEBUG { on, off, session } */
 #ifndef NOSPL
 #ifndef NOSEXP
       case XYSEXP: {
-          if ((x = cmkey(sexptab,2,"","", xxstring)) < 0)
+          if ((x = cmkey(sexptab,3,"","", xxstring)) < 0)
             return(x);
           switch (x) {
             case 0:
@@ -13026,6 +13285,8 @@ case XYDEBU:                            /* SET DEBUG { on, off, session } */
                 }
                 break;
             }
+           case 2:
+             return(seton(&sexptrunc));
           }
           return(success = 1);
       }
@@ -13082,6 +13343,27 @@ case XYDEBU:                            /* SET DEBUG { on, off, session } */
         return(setgui());
 #endif /* KUI */
 
+#ifndef NOFRILLS
+#ifndef NORENAME
+      case XY_REN:                     /* SET RENAME */
+       return(setrename());
+#endif /* NORENAME */
+#endif /* NOFRILLS */
+
+#ifndef NOPUSH
+#ifdef CK_REDIR
+#ifndef NOXFER
+      case XYEXTRN:                    /* SET EXTERNAL-PROTOCOL */
+       return(setextern());
+#endif /* NOXFER */
+#endif /* CK_REDIR */
+#endif /* NOPUSH */
+
+#ifndef NOSPL
+      case XYVAREV:                    /* SET VARIABLE-EVALUATION */
+       return(setvareval());
+#endif /* NOSPL */
+
       default:
          if ((x = cmcfm()) < 0) return(x);
          printf("Not implemented - %s\n",cmdbuf);
@@ -13173,6 +13455,9 @@ hupok(x) int x; {                       /* Returns 1 if OK, 0 if not OK */
                        && local
 #endif /* K95G */
                         )) {
+            if ( !needwarn )
+                ckstrncpy(warning, "No active connections", 256);
+
 #ifdef COMMENT
            printf("%s",warning);
             z = getyesno(x ? "OK to close? " : "OK to exit? ",0);
index a47de15..35cfa5f 100644 (file)
--- a/ckuus4.c
+++ b/ckuus4.c
@@ -9,7 +9,7 @@
     Jeffrey E Altman <jaltman@secure-endpoints.com>
       Secure Endpoints Inc., New York City
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2011,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -106,6 +106,8 @@ extern int tn_rem_echo;
 extern int tn_b_meu, tn_b_ume, tn_auth_krb5_des_bug;
 #endif /* TNCODE */
 
+static char * lastkwval = NULL;
+
 char * xferfile = NULL;
 int xferlog = 0;
 
@@ -185,6 +187,20 @@ extern char diafil[];
 #endif /* MAC */
 #endif /* AMIGA */
 
+#ifdef SV68                            /* July 2006 believe it or not */
+#ifndef SEEK_CUR
+#include <unistd.h>
+#endif /* SEEK_CUR */
+#endif /* SV68 */
+
+#ifdef SCO32                           /* June 2011 believe it or not... */
+#ifdef XENIX
+#ifndef SEEK_CUR
+#include <unistd.h>
+#endif /* SEEK_CUR */
+#endif /* XENIX */
+#endif /* SCO32 */
+
 #ifdef STRATUS                          /* Stratus Computer, Inc.  VOS */
 #ifdef putchar
 #undef putchar
@@ -278,9 +294,11 @@ extern int tcp_keepalive;
 extern char * floname[];
 
 #ifndef NOSPL
+extern int vareval;                    /* Variable evaluation method */
 extern int fndiags;                     /* Function diagnostics on/off */
 extern int divbyzero;
-int ispattern = 0;
+int itsapattern = 0;
+int isinbuflen = 0;
 int isjoin = 0;
 #ifdef CK_APC
 extern int apcactive;                   /* Nonzero = APC command was rec'd */
@@ -327,9 +345,6 @@ extern char rexxbuf[];
 
 extern int tfline[];
 
-/* These need to be internationalized... */
-
-static
 char *wkdays[] = {
     "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
 };
@@ -418,11 +433,11 @@ extern int recursive;
 #endif /* RECURSIVE */
 
 #ifdef VMS
-  extern int frecl;
+extern int frecl;
 #endif /* VMS */
 
-extern long
-  ffc, filcnt, rptn, speed, tfc, tlci, tlco, ccu, ccp, vernum, xvernum;
+extern CK_OFF_T ffc, tfc, tlci, tlco;
+extern long filcnt, rptn, speed,  ccu, ccp, vernum, xvernum;
 
 #ifndef NOSPL
 extern char fspec[], myhost[];
@@ -526,6 +541,8 @@ extern char * dialmsg[];
 
 #ifndef NOCSETS
 /* Translation stuff */
+extern int nfilc;
+extern struct keytab fcstab[];
 extern int fcharset, tcharset, tslevel, language, nlng, tcsr, tcsl;
 extern int dcset7, dcset8;
 extern struct keytab lngtab[];
@@ -562,6 +579,7 @@ struct keytab vartab[] = {
     { "authname",  VN_AUTHN, 0},        /* 196 */
     { "authstate", VN_AUTHS, 0},        /* 195 */
     { "authtype",  VN_AUTHT, 0},        /* 195 */
+    { "bits",      VN_BITS,  0},        /* 212 */
     { "blockcheck",VN_BLK,   0},        /* 195 */
 #ifdef BROWSER
     { "browser",   VN_BROWSR,0},        /* 193 */
@@ -614,6 +632,7 @@ struct keytab vartab[] = {
 #endif /* NT */
 #ifndef NODIAL
     { "dialcount", VN_DRTR,  0},        /* 195 */
+    { "dialmessage",VN_DMSG, 0},       /* 212 */
     { "dialnumber",VN_DNUM,  0},        /* 192 */
     { "dialresult",VN_MDMSG, 0},        /* 192 */
     { "dialstatus",VN_DIAL,  0},        /* 190 */
@@ -704,6 +723,7 @@ struct keytab vartab[] = {
     { "incount",   VN_ICNT,  0},
     { "inidir",    VN_INI,   0},        /* 192 */
     { "inmatch",   VN_MATCH, 0},        /* 196 */
+    { "inmessage", VN_INPMSG,0},        /* 212 */
     { "inscale",   VN_ISCALE,0},        /* 210 */
     { "instatus",  VN_ISTAT, 0},        /* 192 */
     { "intime",    VN_INTIME,0},        /* 193 */
@@ -730,11 +750,17 @@ struct keytab vartab[] = {
     { "krb5realm",     VN_K5RLM, 0},
     { "krb5service",   VN_K5SRV, 0},
 #endif /* CK_KERBEROS */
-    { "line",      VN_LINE,  0},
-    { "local",     VN_LCL,   0},
+    { "lastcommand",   VN_PREVCMD, 0}, /* 299 */
+#ifndef NOLASTFILE
+    { "lastfilespec",  VN_LASTFIL, 0}, /* 212 */
+#endif /* NOLASTFILE */
+    { "lastkeywordvalue",  VN_LASTKWV, 0}, /* 212 */
+    { "lastkwvalue",   VN_LASTKWV, CM_ABR|CM_INV}, /* 212 */
+    { "line",          VN_LINE,  0},
+    { "local",         VN_LCL,   0},
 #ifdef UNIX
-    { "lockdir",   VN_LCKDIR,0},        /* 195 */
-    { "lockpid",   VN_LCKPID,0},        /* 195 */
+    { "lockdir",       VN_LCKDIR,0},   /* 195 */
+    { "lockpid",       VN_LCKPID,0},   /* 195 */
 #endif /* UNIX */
     { "log_connection", VN_LOG_CON, 0}, /* 206 */
     { "log_debug", VN_LOG_DEB, 0},      /* 206 */
@@ -813,6 +839,7 @@ struct keytab vartab[] = {
     { "p_rpt",     VN_P_RPT, 0},        /* 193 */
     { "query",     VN_QUE,   0},        /* 190 */
 #endif /* NOXFER */
+    { "remoteip",  VN_HOSTIP,0},       /* 212 */
     { "return",    VN_RET,   0},
 #ifdef CK_REXX
     { "rexx",      VN_REXX,  0},        /* 190 */
@@ -886,6 +913,7 @@ struct keytab vartab[] = {
     { "url",       VN_URL,   CM_INV},   /* 193 */
 #endif /* BROWSER */
     { "userid",    VN_UID,   0},        /* 192 */
+    { "vareval",   VN_VAREVAL, 0},     /* 212 */
     { "version",   VN_VERS,  0},
 #ifndef NOXFER
     { "window",    VN_WINDO, 0},        /* 192 */
@@ -956,16 +984,19 @@ struct keytab fnctab[] = {              /* Function names */
     { "command",    FN_CMD,  0},        /* Output from a command */
 #endif /* NOPUSH */
     { "contents",   FN_CON,  0},        /* Definition (contents) of variable */
+    { "count",      FN_COUNT, 0},       /* Occurrences of string in string */
     { "crc16",      FN_CRC,  0},        /* CRC-16 */
 #ifdef OS2
     { "crypt",      FN_CRY, CM_INV},
 #endif /* OS2 */
+    { "cvtcset",    FN_XLATE, 0},      /* Convert character set */
     { "cvtdate",    FN_DTIM, 0},        /* Convert free date/time to std */
 #ifdef ZFCDAT
     { "date",       FN_FD,   0},        /* File modification/creation date */
 #endif /* ZFCDAT */
     { "day",        FN_DAY,  0},        /* Day of week */
     { "dayofyear",  FN_JDATE,0},        /* Date to Day of Year */
+    { "decodehex",  FN_UNPCT, 0},      /* Decode string with hex escapes */
     { "definition", FN_DEF,  0},        /* Return definition of given macro */
     { "delta2secs", FN_DELSEC, 0},      /* Delta time to seconds */
     { "deltatosecs", FN_DELSEC, CM_INV}, /* Delta time to seconds */
@@ -974,13 +1005,21 @@ struct keytab fnctab[] = {              /* Function names */
 #endif /* NODIAL */
     { "diffdates",  FN_DIFDATE,0},      /* Difference of two date-times */
     { "dimension",  FN_DIM,  0},        /* Dimension of array */
+    { "dir",        FN_DIR,  CM_INV|CM_ABR}, /* Abbreviation for direct.. */
+    { "dire",       FN_DIR,  CM_INV|CM_ABR}, /* Abbreviation for direct.. */
+    { "direc",      FN_DIR,  CM_INV|CM_ABR}, /* Abbreviation for direct.. */
+    { "direct",     FN_DIR,  CM_INV|CM_ABR}, /* Abbreviation for direct.. */
+    { "directo",    FN_DIR,  CM_INV|CM_ABR}, /* Abbreviation for direct.. */
+    { "director",   FN_DIR,  CM_INV|CM_ABR}, /* Abbreviation for direct.. */
     { "directories",FN_DIR,  0},        /* List of directories */
+    { "directory",  FN_DIR,  CM_INV},  /* List of directories */
     { "dirname",    FN_DNAM, 0},        /* Directory part of filename */
     { "dos2unixpath",FN_PC_DU, },       /* DOS to UNIX path */
     { "dostounixpath",FN_PC_DU, CM_INV}, /* DOS to UNIX path */
     { "doy",        FN_JDATE,CM_INV},   /* Date to Day of Year */
     { "doy2date",   FN_DATEJ,0},        /* Day of Year to date */
     { "doytodate",  FN_DATEJ,CM_INV},   /* Day of Year to date */
+    { "emailaddress",FN_EMAIL, 0},     /* Email address */
 #ifdef FN_ERRMSG
     { "errstring",  FN_ERRMSG,0},       /* Error code to message */
 #endif /* FN_ERRMSG */
@@ -1007,6 +1046,8 @@ struct keytab fnctab[] = {              /* Function names */
     { "fpsubtract", FN_FPSUB, 0},       /* FP subtract */
     { "fptangent",  FN_FPTAN, 0},       /* FP tangent */
 #endif /* FNFLOAT */
+    { "function",   FN_FUNC, 0 },       /* Test for existence of a function */
+    { "getpidinfo", FN_PID, 0  },       /* Get PID info */
     { "hex2ip",     FN_HEX2IP,0},       /* Hex to IP address */
     { "hextoip",    FN_HEX2IP,CM_INV},  /* Hex to IP address */
     { "hex2n",      FN_HEX2N, CM_INV},  /* Hex to decimal number */
@@ -1025,6 +1066,7 @@ struct keytab fnctab[] = {              /* Function names */
     { "krbtickets",    FN_KRB_TK, 0},
     { "krbtimeleft",   FN_KRB_TT, 0},
 #endif /* CK_KERBEROS */
+    { "kwvalue",    FN_KWVAL, CM_INV}, /* Keyword=Value */
     { "left",       FN_LEF,  0},        /* Leftmost n characters of string */
     { "length",     FN_LEN,  0},        /* Return length of argument */
     { "literal",    FN_LIT,  0},        /* Return argument literally */
@@ -1034,6 +1076,7 @@ struct keytab fnctab[] = {              /* Function names */
     { "longpathname",FN_FFN,CM_INV},
 #endif /* NT */
     { "lop",        FN_STL,  0},        /* Lop */
+    { "lopx",       FN_LOPX, 0},        /* Lopx */
     { "lower",      FN_LOW,  0},        /* Return lowercased argument */
     { "lpad",       FN_LPA,  0},        /* Return left-padded argument */
     { "ltrim",      FN_LTR,  0},        /* Left-Trim */
@@ -1067,7 +1110,8 @@ struct keytab fnctab[] = {              /* Function names */
 #else
     { "permissions",FN_PERM, CM_INV},   /* Permissions of file */
 #endif /* CK_PERMS */
-    { "radix",      FN_RADIX,0},        /* Radix conversion */
+    { "pictureinfo",FN_PICTURE, 0 },   /* Picture orientation/dimensions */
+    { "radix",      FN_RADIX, 0 },     /* Radix conversion */
 #ifndef NORANDOM
     { "random",     FN_RAND, 0},        /* Random number */
 #endif /* NORANDOM */
@@ -1076,6 +1120,9 @@ struct keytab fnctab[] = {              /* Function names */
 #endif /* NOPUSH */
 #ifdef RECURSIVE
     { "rdirectories", FN_RDIR, 0},      /* Recursive directory list */
+#endif /* RECURSIVE */
+    { "recurse",    FN_RECURSE, 0},    /* Recursive variable evaluation */
+#ifdef RECURSIVE
     { "rfiles",       FN_RFIL, 0},      /* Recursive file list */
 #endif /* RECURSIVE */
     { "rep",        FN_REP, CM_INV|CM_ABR},
@@ -1106,6 +1153,9 @@ struct keytab fnctab[] = {              /* Function names */
 #endif /* COMMENT */
     { "span",       FN_SPN,  0},        /* Span - like Snobol */
     { "split",      FN_SPLIT,0},        /* Split string into words */
+    { "squeeze",    FN_SQUEEZE,0},     /* Squeeze whitespace in string */
+    { "strcmp",     FN_STRCMP,0},      /* String comparison */
+    { "stringtype", FN_STRINGT,0},     /* String type (7-bit, 8-bit, UTF-8) */
     { "stripb",     FN_STB,  0},        /* Strip enclosing braces/brackets */
     { "stripn",     FN_STN,  0},        /* Strip n chars */
     { "stripx",     FN_STX,  0},        /* Strip suffix */
@@ -1480,6 +1530,12 @@ prescan(dummy) int dummy; {             /* Arg is ignored. */
     ckstrncpy(kermrc,KERMRC,KERMRCL);   /* Default init file name */
 #endif /* NOICP */
 
+#ifdef OS2
+    yp = getenv("K95STARTFLAGS");
+    if (yp) {
+        startflags = atoi(yp);
+    }
+#endif /* OS2 */
 
 #ifdef IKSD
     if (howcalled == I_AM_IKSD)         /* Internet Kermit Service daemon */
@@ -1546,6 +1602,11 @@ prescan(dummy) int dummy; {             /* Arg is ignored. */
                               case 'Y':
                                 noinit++;
                                 break;
+
+                              case 'q':
+                                quiet = 1;
+                                break;
+
                               case 'h':
                                   noinit = 1;
 #ifdef OS2
@@ -1645,6 +1706,11 @@ prescan(dummy) int dummy; {             /* Arg is ignored. */
                       case 'Y':
                         noinit++;
                         break;
+
+                      case 'q':
+                          quiet = 1;
+                          break;
+
                       case 'h':
                         noinit = 1;
 #ifdef OS2
@@ -1865,6 +1931,11 @@ prescan(dummy) int dummy; {             /* Arg is ignored. */
                     noinit = 1;
                     break;
 #endif /* NOICP */
+
+                  case 'q':
+                      quiet = 1;
+                      break;
+
                   case 'd':             /* = SET DEBUG ON */
 #ifdef DEBUG
                     if (debcount++ > 0)
@@ -2424,7 +2495,7 @@ static int outxcount = 0;               /* and count */
     int xlate:  nonzero = charset translation for text-mode xfer, 0 = skip.
     int binary: nonzero = transmit in binary mode, 0 = in text mode.
 */
-#define XBBUFSIZ 252                    /* For binary blasting */
+#define XBBUFSIZ 508                   /* For binary blasting */
 static CHAR xbbuf[XBBUFSIZ+4];
 
 int
@@ -2918,8 +2989,8 @@ transmit(s,t,xlate,binary,xxecho) char *s; char t; int xlate, binary, xxecho;
                     } else {
                         line[i++] = dopar((char)c);
 #ifdef TNCODE
-                        if (c == IAC && is_tn)
-                          line[i++] = IAC;
+                        if (c == (CHAR)IAC && is_tn)
+                          line[i++] = (CHAR)IAC;
 #endif /* TNCODE */
                     }
                 }
@@ -3402,8 +3473,6 @@ doxlate() {
 #ifdef UNIX
     extern char ** mtchs;               /* zxpand() file list */
 #endif /* UNIX */
-    extern int nfilc;
-    extern struct keytab fcstab[];
     int x, y, incs, outcs, multiple = 0, wild = 0, fc = 0, len = 0;
     int ofisdir = 0;
     char * s, * tocs = "";
@@ -3743,7 +3812,7 @@ pktopn(s,disp) char *s; int disp; {
             xx.lblopts = 0;
             pktlog = zopeno(ZPFILE,s,NULL,&xx);
         } else pktlog = zopeno(ZPFILE,s,NULL,NULL);
-        if (!pktlog)
+        if (!pktlog && !quiet)
           printf("?%s - %s\n",s,ck_errstr());
 #ifdef OS2ORUNIX
     }
@@ -3806,7 +3875,7 @@ traopn(s,disp) char *s; int disp; {
             tralog = zopeno(ZTFILE,s,NULL,&xx);
         } else tralog = zopeno(ZTFILE,s,NULL,NULL);
     }
-    if (!tralog)
+    if (!tralog && !quiet)
       printf("?%s - %s\n",s,ck_errstr());
     if (tralog > 0 && tlogfmt > 0) {
         ckstrncpy(trafil,s,CKMAXPATH);
@@ -3863,7 +3932,7 @@ sesopn(s,disp) char * s; int disp; {
             setseslog(zopeno(ZSFILE,s,NULL,&xx));
         } else
           setseslog(zopeno(ZSFILE,s,NULL,NULL));
-        if (!seslog)
+        if (!seslog && !quiet)
           printf("?%s - %s\n",s,ck_errstr());
 #ifdef OS2ORUNIX
     }
@@ -3918,7 +3987,7 @@ debopn(s,disp) char *s; int disp; {
             deblog = zopeno(ZDFILE,s,NULL,&xx);
         } else
           deblog = zopeno(ZDFILE,s,NULL,NULL);
-        if (!deblog)
+        if (!deblog && !quiet)
           printf("?%s - %s\n",s,ck_errstr());
 #ifdef OS2ORUNIX
     }
@@ -4622,7 +4691,7 @@ shoparc() {
 #endif /* NOUUCP */
         printf("\n");
     } else {
-        char * s, * ttglckdir();
+        char * s;
         s = ttglckdir();
         if (!s) s = "";
         printf(" Lockfile directory: %s\n", *s ? s : "(none)");
@@ -5597,6 +5666,7 @@ VOID
 shofil() {
     char *s; int i = 0, n = 1;
     extern char * ifdnam[];
+    extern int wildena;
 #ifdef UNIX
     extern int wildxpand;
 #endif /* UNIX */
@@ -5661,7 +5731,8 @@ shofil() {
     printf(" Match dot files:         %s\n", matchdot ? "yes" : "no");
     n++;
 #ifdef UNIX
-    printf(" Wildcard-expansion:      %s\n", wildxpand ? "shell" : "kermit");
+    printf(" Wildcard-expansion:      %s (%s)\n", showoff(wildena),
+          wildxpand ? "shell" : "kermit");
     n++;
 #endif /* UNIX */
 #endif /* UNIXOROSK */
@@ -6011,7 +6082,9 @@ shoparp() {                             /* Protocol */
         printf(" Autoreceive command (text):   %s\n", *s ? s : "(none)");
     }
 #else
+#ifndef NOPUSH
     if (protocol != PROTO_K) {
+       _PROTOTYP( VOID shoextern, (void) );
         printf("\nExecuted by external commands:\n\n");
         s = ptab[protocol].p_b_scmd;
         if (!s) s = "";
@@ -6031,7 +6104,9 @@ shoparp() {                             /* Protocol */
         s = ptab[protocol].h_t_init;
         if (!s) s = "";
         printf(" Autoreceive command (text):   %s\n", *s ? s : "(none)");
+       (VOID) shoextern();
     }
+#endif /* NOPUSH */
 #endif /* XYZ_INTERNAL */
 #endif /* CK_XYZ */
 }
@@ -6242,12 +6317,12 @@ dostat(brief) int brief; {
         printf(" files transferred      : %ld\n",filcnt - filrej);
         if (!ftp)
           printf(" files not transferred  : %ld\n",filrej);
-        printf(" characters last file   : %ld\n",ffc);
-        printf(" total file characters  : %ld\n",tfc);
+        printf(" characters last file   : %s\n",ckfstoa(ffc));
+        printf(" total file characters  : %s\n",ckfstoa(tfc));
         n += ftp ? 3 : 4;
         if (!ftp) {
-            printf(" communication line in  : %ld\n",tlci);
-            printf(" communication line out : %ld\n",tlco);
+            printf(" communication line in  : %s\n",ckfstoa(tlci));
+            printf(" communication line out : %s\n",ckfstoa(tlco));
             printf(" packets sent           : %d\n", spackets);
             printf(" packets received       : %d\n", rpackets);
             n += 4;
@@ -6405,6 +6480,7 @@ myflsh() {                              /* and session log output. */
 int instatus = -1;
 long inetime = -1L;
 int inwait = 0;
+int nowrap = 0;
 
 /* For returning the input sequence that matched */
 
@@ -6415,27 +6491,44 @@ int inwait = 0;
 #endif /* BIGBUFOK */
 static char * matchbuf = NULL;
 static int matchindex = 0;
+static int burst = 0;                      /* Chars remaining in input burst */
 /*
   timo = How long to wait:
          < 0 = Wait forever
-           0 = Don't wait
+           0 = Don't wait at all - material must already have arrived
          > 0 = Wait this many seconds
   ms   = Array of strings to wait for.
   mp   = Array of flags.
          If mp[i] == 0, ms[i] is literal, else it's a pattern.
-  flags = for now, 1 or 0.  If 1, then don't match anything.
+  flags = bit mask
+    INPSW_NOM = /NOMATCH = 1
+    INPSW_CLR = /CLEAR   = 2
+    INPSW_NOW = /NOWRAP  = 4
+    INPSW_COU = /COUNT   = 8
+  count = /COUNT: value if a /COUNT switch was given.
+
+ Returns:
+    0 on failure, 1 on success.
 */
+#ifndef ES_NORMAL
+#define ES_NORMAL 0
+#endif /* ES_NORMAL */
+extern int inesc[], oldesc[];
+
 int
-doinput(timo,ms,mp,flags) int timo; char *ms[]; int mp[]; int flags; {
+doinput(timo,ms,mp,flags,count)
+    int timo; char *ms[]; int mp[]; int flags; int count; {
     extern int inintr;
 #ifdef CK_AUTODL
     extern int inautodl;
 #endif /* CK_AUTODL */
-    int x, y, i, t, rt, icn, anychar, mi[MINPMAX];
+    int x, y, i, t, rt, icn, anychar = 0, mi[MINPMAX];
 #ifdef GFTIMER
     CKFLOAT fpt = 0.0;
 #endif /* GFTIMER */
+    int savecount = 0;
     int nomatch = 0;
+    int clearfirst = 0;
     int lastchar = 0;
     int waiting = 0;
     int imask = 0;
@@ -6451,34 +6544,57 @@ doinput(timo,ms,mp,flags) int timo; char *ms[]; int mp[]; int flags; {
     static int cr = 0;
 #endif /* TNCODE */
     int is_tn = 0;
-    int wrapped = 0;
 #ifdef SSHBUILTIN
     extern int ssh_cas;
     extern char * ssh_cmd;
 #endif /* SSHBUILTIN */
+    int noescseq = 0;                  /* Filter escape sequences */
+
+    debug(F101,"input count","",count);
+    debug(F101,"input flags","",flags);
 
-#define CK_BURST
 /*
-  This enables the INPUT speedup code, which depends on ttchk() returning
+  CK_BURST enables the INPUT speedup code, which depends on ttchk() returning
   accurate information.  If INPUT fails with this code enabled, change the
   above "#define" to "#undef".
 */
-#ifdef CK_BURST
-    int burst = 0;                      /* Chars remaining in input burst */
-#endif /* CK_BURST */
+#define CK_BURST
+
+/***** CHANGE THIS TO A SET INPUT PARAMETER *****/
+
+    noescseq = (sessft == XYFT_T);     /* Filter escape sequences */
 
     imask = cmask;
     if (parity) imask = 0x7f;
     inwait = timo;                      /* For \v(inwait) */
-    nomatch = flags & 1;
-    makestr(&inpmatch,NULL);
 
+    /* Options from command switches */
+
+    nowrap = flags & INPSW_NOW;                /* 4 = /NOWRAP */
+    nomatch = flags & INPSW_NOM;       /* 1 = /NOMATCH */
+    clearfirst = flags & INPSW_CLR;    /* 2 = /CLEAR */
+    savecount = count;
+
+    makestr(&inpmatch,NULL);
     if (!matchbuf) {
         matchbuf = malloc(MATCHBUFSIZ+1);
         matchbuf[0] = NUL;
     }
     matchindex = 0;
 
+    /* If last time through we returned because of /NOWRAP and buffer full */
+    /* now we have to clear the buffer to make room for another load. */
+
+    if (nowrap && instatus == INP_BF)
+      clearfirst = 1;
+
+    if (clearfirst) {                  /* INPUT /CLEAR */
+       int i;
+       myflsh();                       /* Flush screen and log buffers */
+       for (i = 0; i < inbufsize; i++)
+         inpbuf[i] = NUL;
+       inpbp = inpbuf;
+    }
     is_tn =
 #ifdef TNCODE
         (local && network && IS_TELNET()) || (!local && sstelnet)
@@ -6487,6 +6603,10 @@ doinput(timo,ms,mp,flags) int timo; char *ms[]; int mp[]; int flags; {
 #endif /* TNCODE */
           ;
 
+#ifdef CK_SSL
+    if (is_tn) if (ssl_raw_flag || tls_raw_flag) is_tn = 0;
+#endif /* CK_SSL */
+
     instatus = INP_IE;                  /* 3 = internal error */
     kbchar = 0;
 
@@ -6540,25 +6660,24 @@ doinput(timo,ms,mp,flags) int timo; char *ms[]; int mp[]; int flags; {
 
     debug(F111,"doinput ms[0]",ms[0],waiting);
 
-    if (!ms[0]) {                       /* If we were passed a NULL pointer */
-        anychar = 1;                    /*  ... */
-    } else {
-        y = (int)strlen(ms[0]);         /* Or if search string is empty */
-        anychar = (y < 1);              /* any input character will do. */
+    if (!ms[0] || isemptystring(ms[0])) { /* No search string was given nor */
+       if (count < 2)                    /* a /COUNT: switch so we just */
+         anychar = 1;                    /* wait for the first character */
     }
-    if (flags & 1) anychar = 0;                /* Don't match anything */
+    if (nomatch) anychar = 0;          /* Don't match anything */
 
     if (!anychar && waiting == 0 && timo == 0)
       return(0);
 
-
 #ifndef NODEBUG
     if (deblog) {
         char xbuf[24];
         debug(F101,"doinput anychar","",anychar);
         debug(F101,"doinput timo","",timo);
         debug(F101,"doinput echo","",inecho);
+#ifdef CK_BURST
         debug(F101,"doinput burst","",burst);
+#endif /* CK_BURST */
         y = -1;
         while (ms[++y]) {
             sprintf(xbuf,"doinput string %2d",y); /* SAFE (24) */
@@ -6588,14 +6707,13 @@ doinput(timo,ms,mp,flags) int timo; char *ms[]; int mp[]; int flags; {
     x = 0;                              /* Return code, assume failure */
     instatus = INP_TO;                  /* Status, assume timeout */
 
-    for (y = 0; y < MINPMAX; y++)
-      mi[y] = 0;                        /* String pattern match position */
+    for (y = 0; y < MINPMAX; y++)      /* Initialize... */
+      mi[y] = 0;                        /*  ..string pattern match position */
 
     if (!inpcas[cmdlvl]) {              /* INPUT CASE = IGNORE?  */
         y = -1;
-
-        while ((xp = ms[++y])) {
-            while (*xp) {               /* Convert to lowercase */
+        while ((xp = ms[++y])) {       /* Convert each target to lowercase */
+            while (*xp) {
                 if (isupper(*xp)) *xp = (char) tolower(*xp);
                 xp++;
             }
@@ -6727,7 +6845,12 @@ doinput(timo,ms,mp,flags) int timo; char *ms[]; int mp[]; int flags; {
                         continue;
 #endif /* IKS_OPTION */
                       case 6:           /* TELNET DO LOGOUT received */
-                      default: continue;
+                       continue;
+                     case 7:
+                     case 3:           /* A quoted IAC */
+                       break;
+                      default:
+                       continue;
                     }
                   case CR:
                     cr = 1;
@@ -6841,20 +6964,22 @@ doinput(timo,ms,mp,flags) int timo; char *ms[]; int mp[]; int flags; {
             if (c == '\0') {            /* NUL, we can't use it */
                 if (anychar) {          /* Except if any character will do? */
                     x = 1;              /* Yes, done. */
+                   instatus = INP_OK;
                     incount = 1;        /* This must be the first and only. */
                     break;
-                } else goto refill;     /* Otherwise continue INPUTting */
+                } else goto refill;    /* Otherwise continue INPUTting */
             }
             *inpbp++ = c;               /* Store char in circular buffer */
             incount++;                  /* Count it for \v(incount) */
 
-            /* Don't NUL-terminate here - it's a circular buffer. */
-
-            if (inpbp >= inpbuf + inbufsize) { /* Time to wrap around? */
-                wrapped++;
-                *inpbp = NUL ;          /* Make it null-terminated */
-                inpbp = inpbuf;         /* Yes. */
-            }
+           if (flags & INPSW_COU) {    /* INPUT /COUNT */
+               if (--count < 1) {
+                   x = 1;
+                   instatus = INP_OK;
+                    incount = savecount;
+                    break;
+               }
+           }
             if (matchbuf) {
                 if (matchindex < MATCHBUFSIZ) {
                     matchbuf[matchindex++] = c;
@@ -6877,18 +7002,33 @@ doinput(timo,ms,mp,flags) int timo; char *ms[]; int mp[]; int flags; {
 #endif /* MAC */
 #ifndef OS2
             if (seslog) {
+               int dummy = 0, skip = 0;
+#ifndef NOLOCAL
+               if (noescseq) {
+                   dummy = chkaes(c,0);
+                   if (inesc[0] != ES_NORMAL || oldesc[0] != ES_NORMAL)
+                     skip = 1;
+               }
+#endif /* NOLOCAL */
+#ifdef UNIXOROSK
+               if (sessft == XYFT_T) {
 #ifdef UNIX
-                if (sessft != 0 || c != '\r')
+                   if (c == '\r')
 #else
 #ifdef OSK
-                if (sessft != 0 || c != '\012')
+                   if (c == '\012')
 #endif /* OSK */
 #endif /* UNIX */
+                     skip = 1;
+               }
+#endif /* UNIXOROSK */
+               if (!skip)
                   sesbuf[sescnt++] = c; /* Buffer session log output */
             }
 #endif /* OS2 */
             if (anychar) {              /* Any character will do? */
                 x = 1;
+               instatus = INP_OK;
                 break;
             }
             if (!inpcas[cmdlvl]) {      /* Ignore alphabetic case? */
@@ -6911,6 +7051,7 @@ doinput(timo,ms,mp,flags) int timo; char *ms[]; int mp[]; int flags; {
                     for (j = 0; j < matchindex; j++) {
                         if (ckmatch(s,&matchbuf[j],1,1)) {
                             matchindex = j;
+                           instatus = INP_OK;
                             x = 1;
                             break;
                         }
@@ -6924,6 +7065,7 @@ doinput(timo,ms,mp,flags) int timo; char *ms[]; int mp[]; int flags; {
                     x = ckmatch(s,matchbuf,inpcas[cmdlvl],1+4);
                     if (x > 0) {
                         matchindex = x - 1;
+                       instatus = INP_OK;
                         x = 1;
                         break;
                     }
@@ -6950,20 +7092,31 @@ doinput(timo,ms,mp,flags) int timo; char *ms[]; int mp[]; int flags; {
                 if ((CHAR) s[i] == (CHAR) '\0') { /* Matched to end? */
                     ckstrncpy(matchbuf,ms[y],MATCHBUFSIZ);
                     matchindex = 0;
-                    x = 1;              /* Yes, */
+                   instatus = INP_OK;  /* Yes, */
+                    x = 1;            
                     break;              /* done. */
                 }
                 mi[y] = i;              /* No, remember match-position */
             }
             if (x == 1) {               /* Set \v(minput) result */
+               instatus = INP_OK;
                 m_found = y + 1;
                 break;
             }
+            if (inpbp >= inpbuf + inbufsize) { /* Reached end of buffer? */
+               if (nowrap) {           /* If /NOWRAP...*/
+                   instatus = INP_BF;  /* ...return indicating buffer full. */
+                   *inpbp = NUL;
+                   goto xinput;
+               }
+                *inpbp = NUL;           /* Make it null-terminated */
+                inpbp = inpbuf;         /* Yes. */
+            }
         }
 #ifdef CK_BURST
         else if (y <= -1 && burst > 0) {
             debug(F111,"doinput (y<=-1&&burst>0)","burst",burst);
-                                        /* a timo occurred so there can't   */
+                                        /* A timeout occurred so there can't */
             burst = 0;                  /* be data waiting; must check timo */
         }
       refill:
@@ -7023,7 +7176,8 @@ doinput(timo,ms,mp,flags) int timo; char *ms[]; int mp[]; int flags; {
         } else {
             debug(F111,"doinput (burst > 0)","burst",burst);
         }
-#else
+#else  /* CK_BURST */
+      refill:
         myflsh();                       /* Flush buffered output */
         /* Did not match, timer exceeded? */
         t = gtimer();
@@ -7035,10 +7189,15 @@ doinput(timo,ms,mp,flags) int timo; char *ms[]; int mp[]; int flags; {
           break;
 #endif /* CK_BURST */
     }                                   /* Still have time left, continue. */
-    if (nomatch) x = 1;                        /* Succeed if nomatch and timed out. */
-    myflsh();                           /* Flush buffered output. */
-    if (x > 0 && !nomatch)
-      instatus = 0;
+  xinput:
+    myflsh();                           /* Flush buffered output */
+    if (instatus == INP_BF) {          /* Buffer full and /NOWAIT */
+       x = 0;                          /* Must not succeed */
+    } else {                           /* Buffer full and /NOWAIT */
+       if (nomatch) x = 1;             /* Succeed if nomatch and timed out */
+       if (x > 0 && !nomatch)
+         instatus = 0;
+    }
 #ifndef NOLOCAL
 #ifdef OS2
     term_io = term_io_save;
@@ -7064,7 +7223,7 @@ doinput(timo,ms,mp,flags) int timo; char *ms[]; int mp[]; int flags; {
     inetime = (int)(gtimer() * 1000);
 #endif /* GFTIMER */
 
-    if (!nomatch)
+    if (x > 0)
       makestr(&inpmatch,&matchbuf[matchindex]); /* \v(inmatch) */
     return(x);                          /* Return the return code. */
 }
@@ -7652,50 +7811,72 @@ evalerr(fn) char * fn; {
     }
 }
 
-char *
-dokwval(s,sep) char * s, sep; {
+
+static int
+ckcindex(c,s) char c, *s; {
+    int rc;
+    if (!c || !s) return(0);
+    for (rc = 0; s[rc]; rc++) {
+       if (c == s[rc]) return(rc+1);
+    }
+    return(0);
+}
+
+static char *
+dokwval(s,sep) char * s, * sep; {
     char c = '\0', * p, * kw = NULL, * vp = NULL;
-    int x;
-    if (!s) return("0");
-    if (!*s) return("0");
+    char * rc = "0";                   /* Return code */
+    int x = 0;
+    if (!s) return(rc);
+    if (!*s) return(rc);
     debug(F110,"kwval arg",s,0);
-    debug(F110,"kwval sep",ckctoa(sep),0);
+    debug(F110,"kwval sep",sep,0);
     p = (char *)malloc((int)strlen(s)+1);
-    if (!p) return("0");
+    if (!p) goto xdokwval;
     strcpy(p,s);                        /* SAFE */
     s = p;
     while (*s < '!' && *s > '\0')       /* Get first nonblank */
       s++;
-    if (!*s) return("0");
-    if (*s == sep) return("0");
+    if (!*s) goto xdokwval;
+    if (ckcindex(*s,sep))              /* Separator but no keyword */
+      goto xdokwval;
     kw = s;                             /* Keyword */
     while (*s > ' ') {
-        if (*s == sep) {                /* keyword=... */
+       if (ckcindex(*s,sep)) {         /* keyword=... */
             c = *s;
             break;
         }
         s++;
     }
+    if (*kw) rc = "1";                 /* Have keyword, promote return code */
     *s++ = NUL;                         /* Terminate keyword */
     while (*s < '!' && *s > '\0')       /* Skip blanks */
       s++;
-    if (!c && *s == sep) {
+    if (!c && ckcindex(*s,sep)) {
         c = *s++;                       /* Have separator */
         while (*s < '!' && *s > '\0')   /* Skip blanks */
           s++;
     }
     if (c) {
         vp = s;
+       if (*vp) rc = "2";              /* Have value, another promotion */
+#ifdef COMMENT
         while (*s > ' ')                /* Skip to end */
           s++;
         *s = NUL;                       /* Terminate value */
+#endif /* COMMENT */
     }
     debug(F110,"kwval c",ckctoa(c),0);
     debug(F110,"kwval keyword",kw,0);
     debug(F110,"kwval value",vp,0);
-    x = c ? addmac(kw,vp) : -1;
-    free(p);
-    return((x < 0) ? "0" : "1");
+    makestr(&lastkwval,kw);
+    vp = brstrip(vp);
+    debug(F110,"kwval value",vp,0);
+    x = addmac(kw,vp);
+    debug(F111,"kwval addmac",kw,x);
+  xdokwval: 
+    if (p) free(p);
+    return((x < 0) ? "-1" : rc);
 }
 
 static int
@@ -7808,7 +7989,7 @@ fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
     if (deblog) {
         int j;
         for (j = 0; j < argn; j++)
-          debug(F111,"fneval arg",argp[j],j);
+         debug(F111,"fneval arg",argp[j],j);
     }
 #endif /* DEBUG */
     for (j = argn-1; j >= 0; j--) {     /* Uncount empty trailing args */
@@ -7834,6 +8015,7 @@ fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
 #endif /* COMMENT */
     if (cx == FN_CON) {                 /* Contents of variable, unexpanded. */
         char c;
+        int subscript = 0;        
         if (!(p = argp[0]) || !*p) {
             failed = 1;
             p = fnval;
@@ -7894,22 +8076,21 @@ fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
                   sprintf(fnval,"<ERROR:ARG_BAD_ARRAY:\\fcontents()>");
                 goto fnend;
             }
-            if (chkarray(vbi,d) > 0) {  /* Array is declared? */
+           subscript = chkarray(vbi,d); /* Check the array */
+            if (subscript >= 0) {      /* Array is declared? */
                 vbi -= ARRAYBASE;       /* Convert name to index */
                 if (a_dim[vbi] >= d) {  /* If subscript in range */
                     char **ap;
                     ap = a_ptr[vbi];    /* get data pointer */
                     if (ap) {           /* and if there is one */
-                        p = ap[d];
+                        p = ap[d];     /* return it */
                         goto fnend;
                     }
                 }
-            } else {
-                failed = 1;
-                p = fnval;
-                if (fndiags)
-                  sprintf(fnval,"<ERROR:ARG_NOT_ARRAY:\\fcontents()>");
-                goto fnend;
+            } else {                   /* Array not declared or element */
+                fnval[0] = NUL;                /* out of range - return null string */
+                p = fnval;             /* fdc 2010-12-30 */
+                goto fnend;    
             }
         } else {
             failed = 1;
@@ -7922,7 +8103,6 @@ fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
     p = fnval;                          /* Default result pointer */
     fnval[0] = NUL;                     /* Default result = empty string */
 
-
     for (i = 0; i < argn; i++) {        /* Loop to expand each argument */
         n = MAXARGLEN;                  /* Allow plenty of space */
         bp[i] = s = malloc(n+1);        /* Allocate space for this argument */
@@ -7987,6 +8167,27 @@ fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
         }
     }
 #endif /* DEBUG */
+    {
+       /* Adjust argn for empty trailing arguments. */
+       /* For example when an arg is a variable name but the */
+       /* variable has no value.   July 2006. */
+       int j, old; char *p;
+       old = argn;
+       for (j = argn - 1; j >= 0; j--) {
+           p = bp[j];
+           if (!p)
+             argn--;
+           else if (!*p)
+             argn--;
+           else
+             break;
+       }
+#ifdef DEBUG
+       if (argn != old)
+         debug(F101,"fneval adjusted argn","",argn);
+#endif /* DEBUG */
+    }  
+
 /*
   From this point on, bp[0..argn-1] are not NULL and all must be freed
   before returning.
@@ -8055,8 +8256,8 @@ fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
           case FN_HSTNAM:
 #endif /* TCPSOCKET */
           case FN_DELSEC:
-          case FN_KWVAL:
 #ifdef COMMENT
+          case FN_KWVAL:
           case FN_SLEEP:
           case FN_MSLEEP:
 #endif /* COMMENT */
@@ -8145,8 +8346,8 @@ fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
                 char *p = bp[0];        /* Reuse this space */
                 *p = NUL;               /* Make into dodo() arg list */
                 for (i = 1; i < argn; i++) {
-                    strncat(p,bp[i],MAXARGLEN);
-                    strncat(p," ",MAXARGLEN);
+                    ckstrncat(p,bp[i],MAXARGLEN);
+                    ckstrncat(p," ",MAXARGLEN);
                 }
                 s = bp[0];              /* Point to new list */
             }
@@ -8201,11 +8402,13 @@ fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
               goto fnend;
           }
           if (cx == FN_DIR || cx == FN_RDIR) { /* Only list directories */
+             debug(F100,"FN_DIR or FN_RDIR","",0);
               xflags |= ZX_DIRONLY;
 #ifdef OS2
               zxpn = 1;                 /* Use the alternate list */
 #endif /* OS2 */
           } else {                      /* List only files */
+             debug(F100,"Not FN_DIR or FN_RDIR","",0);
               xflags |= ZX_FILONLY;
 #ifdef OS2
               zxpn = 1;                 /* Use the alternate list */
@@ -8317,20 +8520,23 @@ fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
 #else
         if (flist)                      /* Others, use our own list. */
           if (flist[flistn])
-            p = flist[flistn++];
+           p = flist[flistn++];
 #endif /* OS2 */
         goto fnend;
 
     } /* Break up big switch... */
 
     switch (cx) {
-      case FN_IND:                      /* \findex(s1,s2,start) */
-      case FN_RIX:                      /* \frindex(s1,s2,start) */
-      case FN_SEARCH:                   /* \fsearch(pat,string,start) */
-      case FN_RSEARCH: {                /* \frsearch(pat,string,start) */
-        int i = 0, right = 0, search = 0;
+      case FN_IND:                      /* \findex(s1,s2,start,occurrence) */
+      case FN_RIX:                      /* \frindex(s1,s2,start,occurrence) */
+      case FN_SEARCH:                   /* \fsearch(pat,string,start,occ) */
+      case FN_RSEARCH:                 /* \frsearch(pat,string,start,occ) */
+      case FN_COUNT: {                 /* \fcount(s1,s2,start) */
+       int i = 0, right = 0, search = 0, count = 0;
+       int desired = 1;
         right = (cx == FN_RIX || cx == FN_RSEARCH);
         search = (cx == FN_SEARCH || cx == FN_RSEARCH);
+       count = (cx == FN_COUNT);
         p = "0";
         if (argn > 1) {                 /* Only works if we have 2 or 3 args */
             int start = 0;
@@ -8342,6 +8548,11 @@ fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
             start = right ? -1 : 0;     /* Default starting position */
             if (argn > 2) {
                 val1 = *(bp[2]) ? evalx(bp[2]) : "1";
+               if (argn > 3) {
+                   val2 = *(bp[3]) ? evalx(bp[3]) : "1";
+                   if (chknum(val2)) desired = atoi(val2);
+                   if (desired * len1 > len2) goto fnend;
+               }
                 if (chknum(val1)) {
                     int t;
                     t = atoi(val1);
@@ -8375,23 +8586,66 @@ fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
                     goto fnend;
                 }
             }
-            if (search) {               /* \fsearch() or \frsearch() */
+           if (count) {                /* \fcount() */
+               int j;
+               for (i = 0; start < len2; i++) {
+                   j = ckindex(pat,bp[1],start,0,inpcas[cmdlvl]);
+                   if (j == 0) break;
+                   start = j;
+               }
+
+           } else if (search) {        /* \fsearch() or \frsearch() */
+
                 if (right && pat[0] == '^') {
                     right = 0;
                     start = 0;
                 }
-                if (right) {
-                    if (start < 0) start = len2 - 1;
-                    for (i = start;
-                         i >= 0 && !ckmatch(pat,s+i,inpcas[cmdlvl],1+4);
-                         i--) ;
-                    if (i < 0) i = 0; else i++;
-                } else {
-                    i = ckmatch(pat,&s[start],inpcas[cmdlvl],1+4);
-                    if (start > 0) i += start;
+                if (right) {           /* From right */
+                   int k, j = 1;
+                    if (start < 0)
+                     start = len2 - 1;
+                   i = 0;
+                   while (start >= 0 && j <= desired) {
+                       for (i = start;
+                            (i >= 0) && 
+                                !(k = ckmatch(pat,s+i,inpcas[cmdlvl],1+4));
+                            i--) ;
+                       if (k < 1) {    /* No match */
+                           i = 0;
+                           break;
+                       }
+                       if (j == desired) { /* The match we want? */
+                           i += k;     /* Yes, return string index */
+                           break;
+                       }
+                       j++;            /* No, count this match */
+                       s[i] = NUL;     /* null it out */
+                       start = i-1;    /* move left and look again */
+                   }
+
+                } else {               /* From left */
+                   int j;
+                   i = 0;
+                   for (j = 1; j <= desired && start < len2; j++) {
+                       i = ckmatch(pat,&s[start],inpcas[cmdlvl],1+4);
+                       if (i == 0 || j == desired) break;
+                       start += i + 1;
+                   }                   
+                   if (j == desired && i != 0)
+                     i += start;
+                   else
+                     i = 0;
                 }
-            } else {
-                i = ckindex(pat,bp[1],start,right,inpcas[cmdlvl]);
+            } else {                   /* index or rindex */
+               int j = 0;
+               i = 0;
+               for (j = 1; j <= desired && start < len2; j++) {
+                   i = ckindex(pat,bp[1],start,right,inpcas[cmdlvl]);
+                   if (i == 0 || j == desired) break;
+                   start = (right) ? len2 - i + 1 : i;
+               }
+               if (j != desired)
+                 i = 0;
             }
             sprintf(fnval,"%d",i);      /* SAFE */
             p = fnval;
@@ -8758,30 +9012,31 @@ fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
     } /* Break up big switch... */
 
     switch (y) {
-      case FN_FS:                       /* \fsize(filename) */
-        p = fnval;
-        z = zchki(bp[0]);
-        if (z < 0) {
-            failed = 1;
-            if (fndiags) {
-                if (z == -1)
-                  ckmakmsg(fnval,FNVALL,
-                           "<ERROR:FILE_NOT_FOUND:\\f",fn,"()>",NULL);
-                else if (z == -2)
-                  ckmakmsg(fnval,FNVALL,
-                           "<ERROR:FILE_NOT_READABLE:\\f",fn,"()>",NULL);
-                else if (z == -3)
-                  ckmakmsg(fnval,FNVALL,
-                           "<ERROR:FILE_NOT_ACCESSIBLE:\\f",fn,"()>",NULL);
-                else
-                  ckmakmsg(fnval,FNVALL,
-                           "<ERROR:FILE_ERROR:\\f",fn,"()>",NULL);
-            }
-            goto fnend;
-        }
-        sprintf(fnval,"%ld",z);         /* SAFE */
-        goto fnend;
-
+      case FN_FS: {                    /* \fsize(filename) */
+         CK_OFF_T z;
+         p = fnval;
+         z = zchki(bp[0]);
+         if (z < (CK_OFF_T)0) {
+             failed = 1;
+             if (fndiags) {
+                 if (z == (CK_OFF_T)-1)
+                   ckmakmsg(fnval,FNVALL,
+                            "<ERROR:FILE_NOT_FOUND:\\f",fn,"()>",NULL);
+                 else if (z == (CK_OFF_T)-2)
+                   ckmakmsg(fnval,FNVALL,
+                            "<ERROR:FILE_NOT_READABLE:\\f",fn,"()>",NULL);
+                 else if (z == (CK_OFF_T)-3)
+                   ckmakmsg(fnval,FNVALL,
+                            "<ERROR:FILE_NOT_ACCESSIBLE:\\f",fn,"()>",NULL);
+                 else
+                   ckmakmsg(fnval,FNVALL,
+                            "<ERROR:FILE_ERROR:\\f",fn,"()>",NULL);
+             }
+             goto fnend;
+         }
+         ckstrncpy(fnval,ckfstoa(z),FNVALL);
+         goto fnend;
+      }
       case FN_VER:                      /* \fverify() */
        p = "-1";
        if (argn == 1)                  /* No second arg */
@@ -9297,22 +9552,57 @@ fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
         goto fnend;
 
       case FN_STL:                      /* \flop(string,c) */
-        if (!(s = bp[0]))               /* Make sure there is a string */
-          goto fnend;
-        c = '.';                        /* Character to strip to */
-        if (argn > 1) if (*bp[1]) c = *bp[1];
-        x = 0;
-        while (*s++) {
-            if (*(s-1) == c) {
-                x = 1;
-                break;
-            }
-        }
-        if (!x) s = bp[0];
-        ckstrncpy(fnval,s,FNVALL);
-        p = fnval;
-        goto fnend;
-
+      case FN_LOPX: {                  /* \flopx(string,c) */
+         int n = 1;
+         if (!(s = bp[0]))             /* Make sure there is a string */
+           goto fnend;
+         c = '.';                      /* Character to strip to */
+         if (argn > 1) if (*bp[1]) c = *bp[1];
+         if (argn > 2) if (*bp[2]) {
+#ifndef NOFLOAT
+             n = 0;
+             if (isfloat(bp[2],0)) {
+                 n = (int)floatval;
+                 if (n < 0) n = 0;
+             } else
+#endif /* NOFLOAT */
+               n = atoi(bp[2]);
+         }
+         x = 0;
+         if (cx == FN_LOPX) {          /* Lopx (from right) */
+             if (n == 0)
+               goto fnend;
+             s += strlen(s) - 1;       /* We already know it's > 0 */
+             while (s-- >= bp[0]) {
+                 if (*s == c) {
+                     n--;
+                     if (n == 0) {
+                         s++;
+                         x = 1;
+                         break;
+                     }
+                 }
+             }
+             if (!x) s = "";
+         } else {                      /* Lop (from left) */
+             if (n == 0) {
+                 p = bp[0];
+                 goto fnend;
+             }
+             while (*s++) {
+                 if (*(s-1) == c) {
+                     if (--n == 0) {
+                         x = 1;
+                         break;
+                     }
+                 }
+             }
+             if (!x) s = bp[0];
+         }
+         ckstrncpy(fnval,s,FNVALL);
+         p = fnval;
+         goto fnend;
+      }
       case FN_STN:                      /* \fstripn(string,n) */
         if (argn < 1)                   /* Remove n chars from right */
           goto fnend;
@@ -9368,7 +9658,7 @@ fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
                   }
               }
           }
-          c = *bp[1];
+         c = !bp[1] ? 0 : *bp[1];
           if (!c) c = s[0];
           if (argn > 2) if (*bp[2]) c2 = *bp[2];
           if (*s == c) {
@@ -9490,6 +9780,7 @@ fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
           struct stringarray * q = NULL;
 
           splitting = (cx == FN_SPLIT); /* Our job */
+         debug(F101,"FN_SPLIT splitting","",splitting);
 
           fnval[0] = splitting ? '0' : NUL; /* Initial return value */
           fnval[1] = NUL;
@@ -9797,9 +10088,9 @@ fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
           if (s[1] >= 64 && s[1] < 91)  /* Convert upper to lower */
             s[1] += 32;
           if (s[1] < 95 || s[1] > 122) { /* Check for a-z */
-              goto fnend;                       /* Bad */
+              goto fnend;               /* Bad */
           }
-          if ((max = chkarray(s[1],1)) < 1)
+          if ((max = chkarray(s[1],1)) < 1) /* (second arg was 1) */
             max = 0;
           failed = 0;                   /* Unset failure flag */
           sprintf(fnval,"%d",max);      /* SAFE */
@@ -9845,6 +10136,18 @@ fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
           p = ckdate();                 /* None, get today's date */
         else                            /* Some */
           p = bp[0];                    /* Use first */
+       {
+           char * s;
+           s = p;
+           while (*s) {
+               if (*s < 32) {
+                   *s = NUL;
+                   break;
+               }
+               s++;
+           }
+           /* do { if (*s < '!') *s = NUL; break; } while (*s++); */
+       }
         p = ckcvtdate(p,2);             /* Convert to standard form */
         if (*p == '<') {
             failed = 1;
@@ -9854,7 +10157,7 @@ fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
             p = fnval;
             goto fnend;
         }
-        if (argn > 1) {
+        if (argn > 1) {                        /* Format code */
             s = bp[1];
             if (!s) s = "";
             if (!*s) s = "0";
@@ -9867,7 +10170,7 @@ fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
                 goto fnend;
             }
             x = atoi(s);
-            if (x) p = shuffledate(p,x);
+            /* if (x) */ p = shuffledate(p,x);
         }
         if (cx == FN_TIME) {
             p += 9;
@@ -10203,7 +10506,7 @@ fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
           if ((x = dclarray(s[1],k)) < 0) /* Declare array to size */
             goto fnend;
           ap = a_ptr[x];                /* Point to array we just declared */
-          debug(F111,"aaconvert array 1",abuf,ap);
+          /* debug(F111,"aaconvert array 1",abuf,ap); */
           abuf[0] = NUL;
           if (argn > 2) {
               ckstrncpy(abuf,bp[2],16); /* Get value array reference */
@@ -10220,7 +10523,7 @@ fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
                 goto fnend;
               vp = a_ptr[x];            /* Point to array we just declared */
           }
-          debug(F111,"aaconvert array 2",abuf,vp);
+          /* debug(F111,"aaconvert array 2",abuf,vp); */
           makestr(&ap[0],ckitoa(k));
           if (vp) makestr(&vp[0],ckitoa(k));
           if (fndiags)
@@ -10612,8 +10915,14 @@ fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
             goto fnend;
         }
         if (argn < 1) {                 /* All file functions need channel */
-            if (fndiags)
-              ckmakmsg(fnval,FNVALL,"<ERROR:MISSING_ARG:\\f",fn,"()>",NULL);
+           if (cx == FN_FSTAT) {       /* Except f_status(), e.g. when */
+               fnval[0] = '0';         /* called with a variable that */
+               fnval[1] = NUL;         /* hasn't been defined yet. */
+               failed = 0;
+           } else {
+               if (fndiags)
+                ckmakmsg(fnval,FNVALL,"<ERROR:MISSING_ARG:\\f",fn,"()>",NULL);
+           }
             goto fnend;
         }
         if (rdigits(bp[0])) {           /* Channel must be numeric */
@@ -10648,12 +10957,12 @@ fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
         }
         switch (y) {                    /* Do the requested function */
           case FN_FPOS:                 /* Get position */
-            z = z_getpos(channel);
+            z = z_getpos(channel);     /* FIX THIS */
             sprintf(fnval,"%ld",z);     /* SAFE */
             goto fnend;
 
           case FN_NLINE:                /* Get line number */
-            z = z_getline(channel);
+            z = z_getline(channel);    /* FIX THIS */
             sprintf(fnval,"%ld",z);     /* SAFE */
             goto fnend;
 
@@ -10717,15 +11026,45 @@ fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
     }
 #endif /* CKCHANNELIO */
 
-    if (cx == FN_PATTERN) {             /* \fpattern() */
-        ispattern = 1;
+    if (cx == FN_SQUEEZE) {            /* String function \fsqueeze() */
+       /* Squeeze out whitespace */
+       /* Add options later for whether to trim leading and trailing blanks */
+        /* and what to do about control characters, 8-bit whitespace, etc */
+       int started = 0;                /* Flag for first non-whitespace */
+       int n = 0;                      /* Blank/Tab counter */
+        s = bp[0] ? bp[0] : "";
+        p = fnval;                     /* Result buffer */
+       while (*s) {                    /* While there is input */
+           if (!started && (*s == ' ' || *s == '\011')) {
+               s++;                    /* Skip past leading whitespace */
+               continue;
+           }
+           started++;                  /* Leading whitespace was skipped */
+           if (*s != ' ' && *s != '\011') { /* Have a nonspace char */
+               n = 0;                  /* reset space counter */
+               *p++ = *s++;            /* copy char to destination */
+               continue;
+           }               
+           if (n++ > 0) {              /* Have blank or tab */
+               s++;                    /* don't copy more than one */
+               continue;
+           }
+           *p++ = ' ';                 /* Deposit one space */
+           s++;                        /* and go to next source char */
+       }
+       if (*(p-1) == ' ') p--;         /* Remove trailing space */
+        *p = NUL;                      /* Terminate string */
+        p = fnval;                     /* point to beginning */
+        goto fnend;                    /* Done. */
+    }
+    if (cx == FN_PATTERN) {             /* \fpattern() for INPUT */
+        itsapattern = 1;
         if (argn > 0) {
             p = fnval;
             ckstrncpy(fnval,bp[0],FNVALL);
         } else p = "";
         goto fnend;
     }
-
     if (cx == FN_HEX2N || cx == FN_OCT2N) { /* \fhex2n(), \foct2n() */
         p = "0";
         if (argn < 1)
@@ -10831,11 +11170,14 @@ fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
         goto fnend;
     }
     if (cx == FN_JOIN) {
-        int i, x, y, z, flag, hi, lo, max, seplen, grouping = 0;
+        int i, x, y, z, flag, flag2, hi, lo, max, seplen, grouping = 0;
         char abuf[16], c, *s, *q, *sep = NULL;
         char * gr_opn = "\"{'([<";      /* Group open brackets */
         char * gr_cls = "\"}')]>";      /* Group close brackets */
         char lb[2], rb[2];              /* Selected left and right brackets */
+       int csv = 0, tsv = 0;           /* Function flags */
+       char specialchar = 0;           /* Field char that triggers grouping */
+       char *s2 = NULL;                /* Address of malloc'd storage */
 
         failed = 1;                     /* Assume failure */
         fnval[0] = NUL;
@@ -10876,15 +11218,30 @@ fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
         if (max < 1)
           goto fnend;
         sep = " ";                      /* Separator */
-        if (argn > 1)
-          if (bp[1])
-            if (*bp[1])
-              sep = bp[1];
-        lb[0] = NUL;
+        lb[0] = NUL;                   /* Group start char (as string) */
         rb[0] = NUL;
-        lb[1] = NUL;
+        lb[1] = NUL;                   /* Group end char as string */
         rb[1] = NUL;
-        if (argn > 2) {                 /* Grouping? */
+
+        if (argn > 1) {
+           if (bp[1]) if (*bp[1]) {    /* If arg1 given and not empty */
+               if (!strcmp(bp[1],"CSV")) { /* Special "CSV" symbolic arg */
+                   csv++;              /* Make a comma separated list */
+                   sep = ",";          /* Comma */
+                   specialchar = *sep; /* Separator is special character */
+                   grouping = 1;       /* Group with doublequotes */
+                   lb[0] = '"';        /* and here */
+                   rb[0] = '"';        /* they are */
+               } else if (!strcmp(bp[1],"TSV")) { /* "TSV" symbolic arg */
+                   tsv++;              /* Make a Tab separated list */
+                   sep = "\011";       /* Tab */
+                   specialchar = *sep;
+                   grouping = 0;       /* No grouping */
+               } else                  /* Normal case */
+                 sep = bp[1];          /* use the separator char specified */
+           }
+       }
+        if (argn > 2 && !csv && !tsv) {        /* Grouping? */
             char * bp2 = bp[2];
             if (!bp2) bp2 = "0";
             if (!*bp2) bp2 = "0";
@@ -10911,42 +11268,66 @@ fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
                 }
             }
         }
-        if (argn > 3)                   /* Nonzero 4th arg for no separator */
-          if (chknum(bp[3]))
-            if (atoi(bp[3]) > 0)
-              sep = NULL;
-        if (!sep) {
-            sep = "";
-            seplen = 0;
-        } else
-          seplen = strlen(sep);
+       if (!csv && !tsv) {             /* Normal case, not CSV or TSV */
+           specialchar = SP;           /* Special character is space */
+           if (argn > 3)               /* Nonzero 4th arg for no separator */
+             if (chknum(bp[3]))
+               if (atoi(bp[3]) > 0)
+                 sep = NULL;
+           if (!sep) {
+               sep = "";
+               seplen = 0;
+           } else
+             seplen = strlen(sep);
+       }
         for (i = lo; i <= hi; i++) {    /* Loop thru selected array elements */
             s = a_ptr[x][i];            /* Get next element */
             if (!s)
               s = "";
-            flag = 0;                   /* Buffer overrun flag */
+            flag = 0;                   /* Flag to indicate grouping needed */
+           flag2 = 0;                  /* Flag for internal doublequotes */
             if (grouping) {             /* Does this element need quoting? */
-                q = s;                  /* Look for spaces */
-                while ((c = *q++)) { if (c == SP) { flag++; break; } }
+                q = s;                  /* Look for special character */
+                while ((c = *q++)) {   /* If found */
+                   if (c == specialchar) /* grouping is required */
+                     flag++;
+                   if (csv && (c == '"')) /* Character that needs doubling */
+                     flag2++;             /* in comma-separated list */
+                   if (flag && !csv)   /* Exit early if no more to do */
+                     break;
+               }
             }
             y = strlen(s);              /* Get length of this element */
-            if (cx == 0 && grouping)    /* If empty it might need quoting */
-              flag = 1;
-            if (flag) {                 /* Add grouping if needed */
-                char * s2 = NULL;
-                y += 2;
-                if ((q = (char *)malloc(y+1))) {
-                    ckmakmsg(q,y+1,(char *)lb,s,(char *)rb,NULL);
-                    makestr(&s2,q);
-                    free(q);
-                    s = s2;
-                }
-            }
+           if ((y > 0) && csv && !flag) { /* CSV item needs grouping */
+               if (s[0] == SP || s[y-1] == SP || /* if it has leading */
+                   s[0] == HT || s[y-1] == HT) /* or trailing whitespace */
+                 flag++;               /* then it needs grouping */
+           }
+           if (flag || flag2) {        /* String needs grouping or quoting */
+               char *ss = s;
+                q = (char *)malloc(y + flag2 + 3); /* Make new buffer */
+               if (q) {
+                   s2 = q;             /* and this is what to free */
+                   if (flag)           /* If grouping */
+                     *q++ = lb[0];     /* put opening group quote */
+                   while (*ss) {       /* Loop through string */
+                       if (flag2 && (*ss == '"')) /* If CSV and this a '"' */
+                         *q++ = *ss;              /* double it. */
+                       *q++ = *ss++;   /* Copy the character */
+                   }
+                   if (flag)           /* If grouping */
+                     *q++ = rb[0];     /* add closing group quote */
+                   *q = NUL;           /* terminate the result. */
+                   s = s2;
+                   y = strlen(s);
+               }
+           }
             z = 0;                      /* Number of chars copied */
             flag = 0;                   /* flag is now buffer-overrun flag */
             if (y > 0)                  /* If this string is not empty */
               z = ckstrncat(fnval,s,FNVALL); /* copy it. */
-            if (z < y)                  /* Check for buffer overrun. */
+           if (s2) free(s2);           /* Free temp storage */
+            if (z < y)                  /* Now check for buffer overrun. */
               flag++;
             if (!flag && *sep && i < hi) { /* If buffer still has room */
                 z = ckstrncat(fnval,sep,FNVALL); /* copy delimiter */
@@ -11268,7 +11649,7 @@ fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
         goto fnend;
     }
     if (cx == FN_KWVAL) {               /* Keyword=Value */
-        p = dokwval(bp[0],bp[1]?*(bp[1]):'=');
+        p = dokwval(bp[0],bp[1]?bp[1]:"=");
         goto fnend;
     }
 #ifdef COMMENT
@@ -11304,6 +11685,518 @@ fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
     }
 #endif /* NT */
 
+/*
+  \femailaddress():
+  Picks the email address out of an RFC 2822 From: or Sender: header.
+  Added 26 Nov 2005.  Handles all common, and some uncommon, cases but
+  doesn't totally bother about nested comments.  Needed this for fetching
+  email from a POP server and then constructing the BSD "From " line.
+  Works with or without the "From: " or "Sender: " tag.
+*/
+    if (cx == FN_EMAIL) {
+        char c, * s = bp[0], * s2, * s3, * ap = "";
+       int k, state = 0, quote = 0, infield = 0;
+       int pc = 0;                     /* For nested comments */
+        if (!s) s = "";
+       if (!*s) goto xemail;
+
+       if (ckindex("From: ",s,0,0,0) == 1) s += 5;
+       if (ckindex("Sender: ",s,0,0,0) == 1) s += 7;
+
+       k = strlen(s);                  /* Strip junk from end */
+       if (k < 1) goto xemail;
+       k--;
+       while (k >= 0 && s[k] == CR || s[k] == LF)
+         s[k--] = NUL;
+       while (k >= 0 && s[k] == SP || s[k] == HT)
+         s[k--] = NUL;
+       if (k == 0)
+         goto xemail;
+
+#ifndef COMMENT                             /* Simple method if not 100% foolproof */
+       k = 0;
+       for (s2 = s; *s2; s2++) {       /* Find at-sign */
+           if (*s2 == '@') {
+               k++;                    /* If more than one use rightmost */
+               s3 = s2;
+           }
+       }
+       if (k < 1)                      /* No at-sign */
+         goto xemail;
+
+       for (ap = s3-1; ap >= s; ap--) { /* Back up to beginning of address */
+           if (isspace(*ap) || *ap == '<') {
+               ap++;
+               break;
+           }
+           if (ap == s)
+             break;
+       }
+       for (s2 = s3+1; *s2; s2++) {    /* Find end of address */
+           if (isspace(*s2) || *s2 == '>')
+             break;
+       }
+       *s2-- = NUL;
+       if (*ap == '[' && *s2 == ']') { /* Handle [blah@blah.blah] */
+           ap++;
+           *s2 = NUL;
+       }
+       if (!ckstrcmp(ap,"mailto:",7,0)) /* Handle mailto: URLs */
+         ap += 7;
+
+#else  /* Too complicated and error-prone */
+
+       k = 0;
+       for (s2 = s; *s2; s2++) {       /* Strip leading whitespace */
+           if (*s2 == SP || *s2 == HT) {
+               k = 1;
+               break;
+           }
+       }
+       if (!k) {                       /* Simple address */
+           ap = s;
+           goto xemail;
+       }
+       do {                            /* Not simple, have to extract it */
+           if (quote) {
+               quote = 0;
+               continue;
+           } else if (*s == '\\') {
+               quote = 1;
+               continue;
+           }
+           switch (state) {
+             case 0:
+               if (!infield && *s == '"') { /* Quoted string */
+                   infield = 1;
+                   c = '"';
+                   state = 1;
+               } else if (!infield && *s == '(') { /* Comment in parens */
+                   pc++;
+                   infield = 1;
+                   c = ')';
+                   if (*ap) *s = NUL;
+                   state = 1;
+               } else if (!infield && *s == '<') { /* Address */
+                   infield = 1;
+                   c = '>';
+                   ap = s+1;
+                   state = 2;
+               } else if (infield && (*s == SP || *s == HT)) {
+                   infield = 0;
+               } else {                /* One or more bare words */
+                   infield = 1;        /* Could be an address */
+                   if (!*ap) ap = s;   /* Could be comments */
+               }
+               continue;
+             case 1:                   /* In Quoted string or Comment */
+               if (infield && *s == c) { /* Look for end */
+                   infield = 0;
+                   *s++ = NUL;
+                   while (*s == SP || *s == HT) s++;
+                   if (!*ap)
+                     ap = s;
+                   state = 0;
+               }
+               continue;
+             case 2:                   /* In address */
+               if (infield && *s == c) { /* Looking for end */
+                   infield = 0;
+                   *s = NUL;
+                   break;
+               }
+           }
+       } while (*s++);
+
+      xemail:
+       if (*ap) {
+           while (*ap == SP || *ap == HT) ap++;
+       }
+       k = strlen(ap) - 1;
+       while (k >= 0 && (ap[k] == SP || ap[k] == HT))
+         ap[k--] = NUL;
+       if (*ap) {
+           failed = 0;
+           if (*ap == '<') {
+               k = strlen(ap);
+               if (*(ap+k-1) == '>') {
+                   ap[k-1] = NUL;
+                   ap++;
+               }
+           }
+       } else
+         failed = 1;
+       /* Here we might also want check against "*@*.*" */
+#endif /* COMMENt */
+      xemail:
+       ckstrncpy(fnval,ap,FNVALL);
+       goto fnend;
+    }
+
+/*
+   \fpicture():   Get dimensions of GIF or JPG image.
+   fdc June 2006
+*/
+    if (cx == FN_PICTURE) {
+       FILE *fp = NULL;
+       int c, x, w = 0, h = 0, eof = 0;
+       unsigned int i, j, k;
+       unsigned char buf[1024];
+       char abuf[16], * p, * s;
+       char ** ap = NULL;
+
+       p = fnval;                      /* Point to result */
+       failed = 1;                     /* Assume failure */
+       if (argn > 1) {
+           int xi;
+           ckstrncpy(abuf,bp[1],16);   /* Get array reference */
+           s = abuf;
+           if (*s == CMDQ) s++;
+           if (fndiags)                /* Default is this error message */
+             ckmakmsg(fnval,FNVALL,
+                      "<ERROR:ARG_BAD_ARRAY:\\f",fn,"()>",NULL);
+           if (s[0] != '&')            /* "Address" of array */
+             goto fnend;
+           if (s[2])
+             if (s[2] != '[' || s[3] != ']')
+               goto fnend;
+           if (s[1] >= 64 && s[1] < 91) /* Convert upper to lower */
+             s[1] += 32;
+           if ((xi = dclarray(s[1],2)) < 0) /* Two elements */
+             goto fnend;
+           ap = a_ptr[xi];             /* Point to array we just declared */
+       }
+       s = bp[0];                      /* Filename */
+       failed = 0;                     /* From here on we don't fail */
+       p[0] = '0';                     /* Default return value */
+       p[1] = NUL;
+       if (!ckmatch("*.{jpg,jpeg,gif}$",s,0,1+4)) /* Appropriate name? */
+         goto fnend;                   /* No, fail */
+       fp = fopen(s, "r");             /* Open it */
+       if (fp == NULL) {               /* Can't, fail */
+           p[0] = '-';
+           p[1] = '1';
+           p[2] = NUL;                 /* Return -1 */
+           goto fnend;
+       }
+       k = strlen(s);
+       if (!ckstrcmp(&s[k-4],".gif",4,0)) { /* GIF file */
+           if (fread(buf,1,10,fp) != 10) {
+               fclose(fp);
+               goto fnend;
+           }
+           /* Check signature */
+           if (ckstrcmp((char *)buf,"GIF87a",6,0) &&
+               ckstrcmp((char *)buf,"GIF89a",6,0)) {
+               fclose(fp);
+               goto fnend;
+           }
+           w = buf[6] + 256 * buf[7];
+           h = buf[8] + 256 * buf[9];
+           goto picend;
+       } else if (!ckstrcmp(&s[k-4],".jpg",4,0) || /* JPEG file */
+                  !ckstrcmp(&s[k-5],".jpeg",5,0)) {
+           if (fread(buf,1,2,fp) != 2) {
+               fclose(fp);
+               goto fnend;
+           }
+           if (buf[0] != 0xff || buf[1] != 0xd8) { /* Check signature */
+               fclose(fp);
+               goto fnend;
+           }
+           eof = 0;
+           while (!eof) {              /* Loop for each marker */
+               while (!eof) {          /* Find next marker */
+                   c = getc(fp);
+                   if (c == (unsigned int)EOF) {
+                       eof++;
+                       break;
+                   }
+                   if (c == 0xff) {
+                       buf[0] = c;
+                       c = getc(fp);
+                       if (c == (unsigned int)EOF) {
+                           eof++;
+                           break;
+                       }
+                       buf[1] = c;
+                       if (c == 0xd9)
+                         eof++;
+                       if (c >= 0xc0 && c <= 0xfe)
+                         break;
+                   }
+               }
+               if (eof) break;
+               x = buf[1];
+               if (x == 0xc0 || x == 0xc1 || x == 0xc2 || x == 0xc3 ||
+                   x == 0xc9 || x == 0xca || x == 0xcb) {
+                   if (fread(buf,1,7,fp) != 7) {
+                       fclose(fp);
+                       goto fnend;
+                   }
+                   h = buf[3] * 256 + buf[4];
+                   w = buf[5] * 256 + buf[6];
+                   goto picend;
+               } else {                /* Not a desired field */
+                   if (feof(fp)) {
+                       eof++;
+                       break;
+                   }
+                   if (fread(buf,1,2,fp) != 2) { /* Length of this field */
+                       fclose(fp);
+                       goto fnend;
+                   }
+                   j = 256 * buf[0] + buf[1] - 2; /* Skip next field */
+                   if (CKFSEEK(fp,(CK_OFF_T)j,SEEK_CUR) != 0) {
+                       fclose(fp);
+                       goto fnend;
+                   }
+               }
+           } 
+       }
+      picend:
+       fclose(fp);
+       if (ap) {
+           makestr(&(ap[0]),"2");
+           makestr(&(ap[1]),ckitoa(w));
+           makestr(&(ap[2]),ckitoa(h));
+       }
+       if (w > 0 && h > 0) {
+           if (w > h) p[0] = '1';
+           if (h >= w) p[0] = '2';
+       }
+       goto fnend;
+    }
+    if (cx == FN_PID) {
+       int x = -1;
+       if (chknum(bp[0])) {            /* Need numeric argument */
+           int pid;
+           pid = atoi(bp[0]);          /* Convert to int */
+#ifdef UNIX
+           if (kill(pid,0) < 0) {      /* Test it */
+               if (errno ==
+#ifdef ESRCH
+                   ESRCH               /* No such process */
+#else
+                   3
+#endif /* ESRCH */
+                   )
+                 x = 0;
+           } else                      /* Process exists */
+             x = 1;
+#endif /* UNIX */
+       }
+       sprintf(fnval,"%d",x);          /* SAFE */
+       goto fnend;
+    }
+
+    if (cx == FN_FUNC) {
+       char * s = bp[0];
+       p = "0";
+        debug(F111,"ffunc",s,argn);
+       if (argn > 0) {
+           int x, y;
+           for (p = s; *p; p++) {      /* Chop off trailing parens if any */
+               if (*p == '(') {
+                   *p = NUL;
+                   break;
+               }
+           }
+           /* Chop off leading "\\f" or "\f" or "f" */
+           p = s;
+           if (*p == CMDQ)             /* Allow for \\f... */
+             p++;
+           if (*p == CMDQ && (*(p+1) == 'f' || *(p+1) == 'F')) { /* or \f */
+               p += 2;
+           } else if (*p == 'f' || *p == 'F') { /* or just f */
+               p++;
+           }
+           y = lookup(fnctab,p,nfuncs,&x); /* Look up the result */
+           debug(F111,"ffunc",p,y);
+           p = (y > -1) ? "1" : "0";
+       }
+       goto fnend;
+    }
+    if (cx == FN_RECURSE) {
+       int t, n;
+       char * s;
+       fnval[0] = NUL;                 /* Default result is empty string */
+       s = bp[0];                      /* Check for null argument */
+       if (!s) s = "";                 /* or empty argument */
+       if (!*s) goto fnend;            /* in which case return empty string */
+        n = FNVALL;                    /* Not empty, max size for result */
+        s = fnval;                     /* Location of result */
+       {
+           /* Force VARIABLE-EVALUATION SIMPLE RECURSIVE */
+           /* NOTE: This is vulnerable to SIGINT and whatnot... */
+           int tmp = vareval;          /* Save VARIABLE-EVALUATION setting */
+           vareval = 1;                /* Force it to RECURSIVE */
+           zzstring(bp[0],&s,&n);      /* Expand arg into result space */ 
+           vareval = tmp;              /* Restore VARIABLE-EVALUATION */
+       }
+       goto fnend;
+    }
+
+    if (cx == FN_XLATE) {              /* f_cvtcset() */
+#ifdef NOFRILLS
+       ckstrncpy(fnval,bp[0],FNVALL);  
+#else
+#ifndef NOUNICODE
+       _PROTOTYP( char * cvtstring, (char *, int, int) );
+        char * string, * cset1, * cset2;
+       int id1, id2;
+#endif /* NOUNICODE */
+        fnval[0] = NUL;        
+#ifdef NOUNICODE
+       ckstrncpy(fnval,bp[0],FNVALL);  
+#else
+        string = bp[0] ? bp[0] : "";   /* String to convert */
+       if (!*string) goto fnend;       /* It's empty */
+
+        cset1 = bp[1] ? bp[1] : "ascii"; /* Current charset of string */
+        cset2 = bp[2] ? bp[2] : "ascii"; /* Charset to convert to */
+
+       id1 = lookup(fcstab,cset1,nfilc,NULL); /* Lookup 'from' set */
+       if (id1 < 0) {
+            failed = 1;
+           ckmakmsg(fnval,FNVALL,"<ERROR:UNKNOWN_CHARSET:\\f",fn,"()>",NULL);
+           goto fnend;
+        }
+       id2 = lookup(fcstab,cset2,nfilc,NULL); /* Lookup 'to' set */
+       if (id2 < 0) {
+            failed = 1;
+           ckmakmsg(fnval,FNVALL,"<ERROR:UNKNOWN_CHARSET:\\f",fn,"()>",NULL);
+           goto fnend;
+        }
+       string = cvtstring(string,id1,id2);
+       ckstrncpy(fnval,string,FNVALL);
+#endif /* NOUNICODE */
+#endif /* NOFRILLS */
+       goto fnend;
+    }
+
+/* Decode strings containing hex escapes */
+
+    if (cx == FN_UNPCT) {              /* \fdecodehex() */
+        char *s1, *s2;
+       char *prefix;                   /* Can be 1 or 2 chars */
+       char buf[3];
+       int n = 0, k;
+
+       p = fnval;
+       *p = NUL;
+        if (argn < 1) goto fnend;      /* Empty string */
+
+       s1 = bp[0] ? bp[0] : "";        /* Original string */
+       prefix = bp[1] ? bp[1] : "%%";  /* Hex byte prefix */
+       n = (int)strlen(prefix);        /* Length of prefix */
+       if (n < 1 || n > 2) {           /* must be 1 or 2 */
+           ckmakmsg(fnval,FNVALL,
+                      "<ERROR:INVALID_HEX_PREFIX:\\f",fn,"()>",NULL);
+           goto xunpct;
+       }
+        while (*s1) {
+           if (!ckstrcmp(s1,prefix,n,0)) { /* Case-independent */
+               if (!*(s1+n)) {
+                   ckmakmsg(fnval,FNVALL,
+                            "<ERROR:INCOMPLETE_SEQUENCE:\\f",fn,"()>",NULL);
+                   goto xunpct;
+               }
+               buf[0] = *(s1+n);       /* First hex character */
+               buf[1] = *(s1+n+1);     /* Second hex character */
+               buf[2] = NUL;
+               if ((k = ckhexbytetoint((char *)buf)) > -1) {
+                   *p++ = (char) k;    /* Deposit decoded result */
+                   s1 += 2+n;          /* and advance the source pointer */
+               } else {                /* Fail on conversion error */
+                   ckmakmsg(fnval,FNVALL,
+                            "<ERROR:NON_HEX_CHARS:\\f",fn,"()>",NULL);
+                   goto xunpct;
+               }
+           } else {                    /* Not a hex escape sequence */
+               *p++ = *s1++;           /* Just copy the character */
+           }
+        }
+       *p = NUL;                       /* Terminate the result string */
+        failed = 0;                    /* Say we didn't fail */
+        p = fnval;                     /* Set up result pointer */
+        goto fnend;                    /* and finish */
+
+      xunpct:                          /* Error exit */
+       p = fnval;
+       failed = 1;
+       goto fnend;
+    }
+
+/* Check a string for encoding family */
+
+    if (cx == FN_STRINGT) {            /* \fstringtype() */
+       p = "UNK";
+       switch (scanstring(bp[0])) {
+         case FT_7BIT: p = "7BIT"; break;
+         case FT_8BIT: p = "8BIT"; break;
+         case FT_UTF8: p = "UTF8"; break;
+         case FT_UCS2: p = "UCS2"; break;
+         case FT_TEXT: p = "TEXT"; break;
+         case FT_BIN:  p = "BINARY"; break;
+       }
+       ckstrncpy(fnval,p,FNVALL);
+       p = fnval;
+       goto fnend;
+    }
+
+/* String compare s1, s2, [ case ], [ start ] , [ len ] */
+
+    if (cx == FN_STRCMP) {
+        int docase = 0;                        /* Case matters or not */
+        int start = 0;                 /* Start of substring */
+       int len = -1;                   /* Length of substring to compare */
+       int x; char * s1, * s2;         /* workers */
+
+        p = "0";                       /* Return value */
+        if (argn == 0) {               /* Two null strings are equal */
+           ckstrncpy(fnval,p,FNVALL);
+           p = fnval;
+           goto fnend;
+       }
+        if (argn == 1) {               /* Non-null string > null string */
+           p = "1";
+           ckstrncpy(fnval,p,FNVALL);
+           p = fnval;
+           goto fnend;
+       }
+       if (argn > 2) {
+           s = *(bp[2]) ? evalx(bp[2]) : "0"; /* 0 = caseless */
+           if (chknum(s)) docase = atoi(s);
+           if (argn > 3) {
+               s = *(bp[3]) ? evalx(bp[3]) : "1"; /* start is 1-based */
+               if (chknum(s)) start = atoi(s);
+               if (argn > 4) {
+                   s = *(bp[4]) ? evalx(bp[4]) : "-1"; /* -1 = whole thing */
+                   if (chknum(s)) len = atoi(s);
+               }               
+           }        
+       }
+       if (start > 0) start--;         /* start is 0-based internally */
+       s1 = bp[0];                     /* Get length of first arg */
+       x = (int)strlen(s1);
+       if (x > start)                  /* Point to start position of s1 */
+         s1 += start;
+       else
+         s1 = "";
+       s2 = bp[1];                     /* Get length of second arg */
+       x = (int)strlen(s2);
+       if (x > start)                  /* Point to start position of s2 */
+         s2 += start;
+       else
+         s2 = "";
+       x = ckstrcmp(s,s2,len,docase);
+       p = ckitoa(x);
+       ckstrncpy(fnval,p,FNVALL);
+       p = fnval;
+       goto fnend;
+    }
+
 /* Note: when adding new functions remember to update dohfunc in ckuus2.c. */
 
     failed = 1;
@@ -11662,11 +12555,11 @@ nvlook(s) char *s; {
         return(p);
 
       case VN_FFC:                      /* Size of most recent file */
-        sprintf(vvbuf, "%ld", ffc);     /* SAFE */
+        sprintf(vvbuf, "%s", ckfstoa(ffc)); /* SAFE */
         return(vvbuf);
 
       case VN_TFC:                      /* Size of most recent file group */
-        sprintf(vvbuf, "%ld", tfc);     /* SAFE */
+        sprintf(vvbuf, "%s", ckfstoa(tfc)); /* SAFE */
         return(vvbuf);
 
       case VN_CPU:                      /* CPU type */
@@ -11691,6 +12584,8 @@ nvlook(s) char *s; {
             return((char *)unm_mch);
         }
 #else
+        p = getenv("HOSTTYPE");                /* 20091116 */
+       if (p) if (*p) return(p);
         return("unknown");
 #endif /* CK_UTSNAME */
 #endif /* CKCPU */
@@ -11778,6 +12673,14 @@ nvlook(s) char *s; {
                 );
         return(vvbuf);
 
+#ifndef NODIAL
+      case VN_DMSG:
+#ifdef BIGBUFOK
+       ckstrncpy(vvbuf,dialmsg[dialsta],VVBUFL); /* Safe if src == NULL */
+#endif /* BIGBUFOK */
+       return((char *)vvbuf);
+#endif /* NODIAL */
+
 #ifdef OS2
       case VN_KEYB:
         ckstrncpy(vvbuf,conkbg(),VVBUFL);
@@ -11911,9 +12814,9 @@ nvlook(s) char *s; {
                 if (ttnproto == NP_TELNET)
                   ckstrncpy(vvbuf,"tcp/ip_telnet",VVBUFL);
 #ifdef CK_SSL
-                else if (ttnproto == NP_SSL)
+                else if (ttnproto == NP_SSL || ttnproto == NP_SSL_RAW)
                   ckstrncpy(vvbuf,"tcp/ip_ssl",VVBUFL);
-                else if (ttnproto == NP_TLS)
+                else if (ttnproto == NP_TLS || ttnproto == NP_SSL_RAW)
                   ckstrncpy(vvbuf,"tcp/ip_tls",VVBUFL);
 #endif /* CK_SSL */
                 else
@@ -12061,7 +12964,6 @@ nvlook(s) char *s; {
       case VN_UID:
 #ifdef UNIX
         {
-            extern char * whoami();     /* From ckufio.c... */
 #ifdef IKSD
             if (inserver)
               return((char *)uidbuf);
@@ -12736,12 +13638,12 @@ nvlook(s) char *s; {
           return((char *)vvbuf);
       }
       case VN_K4ENO: {
-        extern char * krb4_errno;
+        extern int krb4_errno;
         sprintf(vvbuf,"%d",krb4_errno); /* SAFE */
         return((char *)vvbuf);
       }
       case VN_K5ENO: {
-        extern char * krb5_errno;
+        extern int krb5_errno;
         sprintf(vvbuf,"%d",krb5_errno); /* SAFE */
         return((char *)vvbuf);
       }
@@ -13026,6 +13928,12 @@ nvlook(s) char *s; {
     } /* Break up long switch statements... */
 
     switch(y) {
+#ifndef NOLASTFILE
+      case VN_LASTFIL: {
+         extern char * lastfile;
+         return(lastfile ? lastfile : "");
+      }
+#endif /* NOLASTFILE */
 #ifndef NOXFER
       case VN_XF_BC:
         sprintf(vvbuf,"%d",crunched);   /* SAFE */
@@ -13242,11 +14150,9 @@ nvlook(s) char *s; {
           return(ftp_host ? ftp_host : "");
       }
       case VN_FTP_X: {                  /* FTP Connected */
-          extern int ftpisconnected();
           return(ftpisconnected() ? "1" : "0");
       }
       case VN_FTP_L: {                  /* FTP Logged in */
-          extern int ftpisloggedin();
           return(ftpisloggedin() ? "1" : "0");
       }
       case VN_FTP_G: {                  /* FTP GET-PUT-REMOTE */
@@ -13279,6 +14185,38 @@ nvlook(s) char *s; {
         vvbuf[2] = NUL;
         return(vvbuf);                  /* and return it */
 
+      case VN_BITS:                    /* Bits (16, 32, 64) */
+       if (sizeof(long) > 4)
+         return(ckitoa(8*sizeof(long)));
+       else
+         return(ckitoa(8*sizeof(int)));
+
+      case VN_LASTKWV:                 /* 212 */
+       return(lastkwval ? lastkwval : "");
+
+      case VN_HOSTIP: {                        /* 212 */
+#ifdef TCPSOCKET
+         extern char hostipaddr[];
+         return((char *)hostipaddr);
+#else
+         return("");
+#endif /* TCPSOCKET */
+      }
+      case VN_INPMSG:
+       switch (instatus) {
+         case INP_OK:  return("SUCCESS");
+         case INP_TO:  return("Timed out");
+         case INP_UI:  return("Keyboard interrupt");
+         case INP_IE:  return("Internal error");
+         case INP_IO:  return("I/O error or connection lost");
+         case INP_IKS: return("INPUT disabled");
+         case INP_BF:  return("Buffer filled and /NOWRAP set");
+         default:      return("Unknown");
+       }
+
+      case VN_VAREVAL:                 /* 212 */
+       return(vareval ? "recursive" : "simple");
+
       case VN_LOG_CON:                 /* \v(...) for log files */
 #ifdef CKLOGDIAL
         return(diafil);
@@ -13309,6 +14247,10 @@ nvlook(s) char *s; {
 #else
         return("");
 #endif
+      case VN_PREVCMD: {
+         extern char * prevcmd;
+         return(prevcmd ?  prevcmd : "");
+      }
     }
 
 #ifndef NODIAL
@@ -13426,7 +14368,7 @@ nvlook(s) char *s; {
         fnsuccess = 0;
     }
     if (fndiags) {
-        if (!embuf)
+        if (!embuf[0])
           ckstrncpy(embuf,"<ERROR:NO_SUCH_VARIABLE>",EMBUFLEN);
         printf("?%s\n",embuf);
         return((char *)embuf);
@@ -13448,6 +14390,7 @@ nvlook(s) char *s; {
   Returns -1 on failure, 0 on success,
     with destination string null-terminated and s2 pointing to the
     terminating null, so that subsequent characters can be added.
+    Failure reasons include destination buffer is filled up.
 */
 
 #define XXDEPLIM 100                    /* Recursion depth limit */
@@ -13478,7 +14421,8 @@ zzstring(s,s2,n) char *s; char **s2; int *n; {
         d,                              /* Array dimension */
         vbi,                            /* Variable id (integer form) */
         argl,                           /* String argument length */
-        nx;                             /* Save original length */
+        nx,                             /* Save original length */
+       quoting = 0;                    /* 299 */
 
     char vb,                            /* Variable id (char form) */
         *vp,                            /* Pointer to variable definition */
@@ -13508,13 +14452,19 @@ zzstring(s,s2,n) char *s; char **s2; int *n; {
     n2 = *n;                            /* Make local copies of args */
     nx = n2;
 
+#ifdef COMMENT
+    /* This is always 32K in BIGBUFOK builds */
+    if (depth == 0)
+      debug(F101,"zzstring top-level n","",n2);
+#endif /* COMMENT */
+
     new = *s2;                          /* for one less level of indirection */
 #ifdef COMMENT
     old = new;
 #endif /* COMMENT */
 
 #ifndef NOSPL
-    ispattern = 0;                      /* For \fpattern() */
+    itsapattern = 0;                   /* For \fpattern() */
     isjoin = 0;                                /* For \fjoin() */
 #endif /* NOSPL */
     depth++;                            /* Sink to a new depth */
@@ -13621,14 +14571,29 @@ zzstring(s,s2,n) char *s; char **s2; int *n; {
 #ifdef COMMENT
             if (vp) {                   /* If definition not empty */
 #endif /* COMMENT */
-                debug(F010,"zzstring %n vp",vp,0);
-                if (zzstring(vp,&new,&n2) < 0) { /* call self to evaluate it */
-                    debug(F101,"zzstring fail 6","",depth);
+               if (vareval) {
+                   debug(F010,"zzstring %n vp",vp,0);
+                   /* call self to evaluate it */
+                   if (zzstring(vp,&new,&n2) < 0) {
+                       debug(F101,"zzstring fail 6","",depth);
 #ifdef DVNAMBUF
-                    if (vnambuf) free(vnambuf);
+                       if (vnambuf) free(vnambuf);
 #endif /* DVNAMBUF */
-                    return(-1);         /* Pass along failure */
-                }
+                       return(-1);     /* Pass along failure */
+                   }
+               } else {
+                   while ((*new++ = *vp++)) /* copy it to output string. */
+                     if (--n2 < 0) {
+                         if (q) free(q);
+                         debug(F101,"zzstring overflow 4.5","",depth);
+#ifdef DVNAMBUF
+                         if (vnambuf) free(vnambuf);
+#endif /* DVNAMBUF */
+                         return(-1);
+                     }
+                   new--;              /* Back up over terminating null */
+                   n2++;               /* to allow for further deposits. */
+               }
 #ifdef COMMENT
             } else {
                 debug(F110,"zzstring %n vp","(NULL)",0);
@@ -13658,57 +14623,43 @@ zzstring(s,s2,n) char *s; char **s2; int *n; {
 
             x = chkarray(vbi,d);        /* Array is declared? */
             debug(F101,"zzstring chkarray","",x);
-            if (x > 0) {
+            if (x > -1) {
 #ifdef COMMENT
                 char * s1 = NULL;
 #endif /* COMMENT */
                 vbi -= ARRAYBASE;       /* Convert name to index */
 
-#ifdef COMMENT
-                if (vbi == 0) {         /* Argument vector array */
-                    extern char ** toparg, ** m_xarg[];
-                    extern int n_xarg[];
-                    if (maclvl < 0) {
-                        if (topargc >= d) {
-                            s1 = toparg[d];
-                        }
-                    } else {
-                        if (n_xarg[maclvl] >= d) {
-                            s1 = m_xarg[maclvl][d];
-                        }
-                    }
-                    if (s1) {
-                        if (zzstring(s1,&new,&n2) < 0) { /* evaluate */
-                            debug(F101,"zzstring fail 7.5","",depth);
-#ifdef DVNAMBUF
-                            if (vnambuf) free(vnambuf);
-#endif /* DVNAMBUF */
-                            return(-1); /* Pass along failure */
-                        }
-                    } else {
-                        /* old = new; */
-                        n2 = nx;
-                    }
-                } else
-#endif /* COMMENT */
                   if (a_dim[vbi] >= d) { /* If subscript in range */
                     char **ap;
-#ifndef COMMENT
-                    debug(F110,"zzstring a_ptr[vbi]",a_ptr[vbi],0);
-                    debug(F110,"zzstring a_ptr[vbi][d]",a_ptr[vbi][d],0);
-#endif /* COMMENT */
                     ap = a_ptr[vbi];    /* get data pointer */
                     if (ap) {           /* and if there is one */
                         if (ap[d]) {    /* If definition not empty */
                             debug(F111,"zzstring ap[d]",ap[d],d);
-                            if (zzstring(ap[d],&new,&n2) < 0) { /* evaluate */
-                                debug(F101,"zzstring fail 8","",depth);
+                           if (vareval) {
+                               if (zzstring(ap[d],&new,&n2) < 0) {
+                                   debug(F101,"zzstring fail 8","",depth);
 #ifdef DVNAMBUF
-                                if (vnambuf) free(vnambuf);
+                                   if (vnambuf) free(vnambuf);
 #endif /* DVNAMBUF */
-                                return(-1); /* Pass along failure */
-                            }
-                        }
+                                   return(-1); /* Pass along failure */
+                               }
+                           } else {
+                               vp = ap[d];
+                               while ((*new++ = *vp++)) /* copy to result */
+                                 if (--n2 < 0) {
+                                     if (q) free(q);
+                                     debug(F101,
+                                           "zzstring overflow 8.5","",depth);
+#ifdef DVNAMBUF
+                                     if (vnambuf) free(vnambuf);
+#endif /* DVNAMBUF */
+                                     return(-1);
+                                 }
+                               new--;  /* Back up over terminating null */
+                               n2++;   /* to allow for further deposits. */
+                           }
+                       }
+
                     } else {
                         /* old = new; */
                         n2 = nx;
@@ -13812,6 +14763,12 @@ zzstring(s,s2,n) char *s; char **s2; int *n; {
                 }
             }
 #endif /* DEBUG */
+           {
+            /* In case the function name itself is constructed */
+               char buf[64]; char * p = buf; int n = 64; 
+               if (zzstring(vnambuf,&p,&n) > -1)
+                 ckstrncpy(vnambuf,buf,64);
+           }
             vp = fneval(vnambuf,argp,argn,r3); /* Evaluate the function. */
             if (vp) {                      /* If definition not empty */
                 while ((*new++ = *vp++)) { /* copy it to output string */
@@ -13831,6 +14788,8 @@ zzstring(s,s2,n) char *s; char **s2; int *n; {
             if (r2) { free(r2); r2 = NULL; }
             if (r3) { free(r3); r3 = NULL; }
             break;
+         case 'q':                     /* 299 String to be take literally */
+           quoting = 1;                /* 299 */
           case '$':                     /* An environment variable */
           case 'v':                     /* Or a named builtin variable. */
           case 'm':                     /* Or a macro /long variable */
@@ -13853,11 +14812,14 @@ zzstring(s,s2,n) char *s; char **s2; int *n; {
             p++;                        /* Point to 1st char of name */
             q = vnambuf;                /* Copy the name */
             y = 0;                      /* into a separate buffer */
+           debug(F110,">>>> \\q(ARG)",p,0);
             while (y++ < VNAML) {       /* Watch out for name too long */
                 if (*p == '(') {        /* Parens can be nested... */
-                    pp++;
+                   if (*(p-1) != CMDQ) /* 299 */
+                     pp++;
                 } else if (*p == ')') { /* Name properly terminated with ')' */
-                    pp--;
+                   if (*(p-1) != CMDQ) /* 299 */
+                     pp--;
                     if (pp == 0) {
                         p++;            /* Move source pointer past ')' */
                         break;
@@ -13878,7 +14840,7 @@ zzstring(s,s2,n) char *s; char **s2; int *n; {
             x3 = 0;
             while (*s3++) x3++;
             p = malloc(x3 + 1);         /* Make temporary space */
-            if (p) {                    /* If we got the space */
+            if (p && !quoting) {       /* If we got the space */
                 vp = vnambuf;           /* Point to original */
                 strcpy(p,vp);           /* (safe) Make a copy of it */
                 y = VNAML;              /* Length of name buffer */
@@ -13888,39 +14850,37 @@ zzstring(s,s2,n) char *s; char **s2; int *n; {
             }
             debug(F110,"zzstring vname",vnambuf,0);
             q = NULL;
-            if (x == '$') {             /* Look up its value */
+           if (x == 'q') {             /* 299 Quoting this string */
+               vp = vnambuf;           /* 299 */
+               debug(F110,">>> VP",vp,0);
+           } else if (x == '$') {      /* Look up its value */
                 vp = getenv(vnambuf);   /* This way for environment variable */
             } else if (x == 'm' || x == 's' || x == ':') { /* Macro / substr */
                 int k, x1 = -1, x2 = -1;
+               char c = NUL; 
                 k = strlen(vnambuf);
                 /* \s(name[n:m]) -- Compact substring notation */
                 if ((x == 's' || x == ':') && (k > 1)) { /* Substring wanted */
+                   int bprc;
                     if (vnambuf[k-1] == ']') {
                         int i;
-                        for (i = k-1; i > 0; i--) {
+                        for (i = 0; i < k-1; i++) {
                             if (vnambuf[i] == '[') {
-                                char * p = NULL;
-                                p = (char *)malloc(k - i + 8);
-                                if (p) {
-                                    /* Now this is a dirty trick... */
-                                    ckmakmsg(p,
-                                             k-i+8,
-                                             "\\&a",
-                                             &vnambuf[i],
-                                             NULL,
-                                             NULL
-                                             );
-                                    arraybounds(p,&x1,&x2);
-                                    if (x1 < 1) x1 = 1;
-                                    x1--; /* Adjust to 0-base */
-                                    free(p);
-                                    vnambuf[i] = NUL;
-                                }
+                               bprc = boundspair(vnambuf,":_",&x1,&x2,&c);
+                               debug(F111,"zzstring boundspair",vnambuf,bprc);
+                               debug(F000,"zzstring boundspair c","",c);
+                               if (bprc > -1) {
+                                   vnambuf[i] = NUL;
+                                   if (x1 < 1)
+                                     x1 = 1;
+                                   x1--;       /* Adjust to 0-base */
+                               }
+                               break;
                             }
                         }
-                    }
+                   }
                 }
-                if (x == ':') {
+                if (x == ':') {                /* Variable type (s or :) */
                     vp = vnambuf;
                 } else {
                    y = isaarray(vnambuf) ?
@@ -13932,6 +14892,8 @@ zzstring(s,s2,n) char *s; char **s2; int *n; {
                         vp = NULL;
                     }
                 }
+               debug(F111,"zzstring vp",vp,(vp==NULL)?0:strlen(vp));
+
                 if (vp) {
                     if ((x == 's' || x == ':') && (k > 1)) {
                         /* Compact substring notation */
@@ -13939,18 +14901,43 @@ zzstring(s,s2,n) char *s; char **s2; int *n; {
                             vp = NULL;
                         } else if (x1 > -1) { /* Start */
                             k = strlen(vp);
-                            if (x1 > k) {  /* If it's off the end, */
-                                vp = NULL; /* result is empty */
+                           debug(F101,">>> k","",k);
+                           /* If it's off the end, result is empty */
+                            if (x1 > k) {
+                                vp = NULL;
                             } else if (k > 0) {
+                               /* Stay in bounds */
+                               if (c == '_' && x2 > k) /* startpos_endpos */
+                                 x2 = k;
+                               if (c == ':' && x1 + x2 > k) /* start:length */
+                                 x2 = -1;
+                               debug(F101,">>> x2","",x2);
+                               debug(F000,">>> c","",c);
                                 if ((q = malloc(k+1))) {
                                     strcpy(q,vp); /* safe */
-                                    if ((x2 > -1) && ((x1 + x2) <= k)) {
-                                        q[x1+x2] = NUL;
-                                    }
-                                    vp = q+x1;
-                                }  else vp = NULL;
+                                   if (c == ':') { /* start:length */
+                                       if ((x2 > -1) && ((x1 + x2) <= k)) {
+                                           q[x1+x2] = NUL;
+                                       }
+                                       debug(F000,"XXX q",q,c);
+                                   } else if (c == '_') { /* start_endpos */
+                                       if (x1 >= x2) {
+                                           q[x1 = 0] = NUL;
+                                       } else if (x2 < k && x2 > -1) {
+                                           q[x2] = NUL;
+                                       }
+                                       debug(F000,"XXX q",q,c);
+                                   }
+                                   vp = q+x1;
+                                } else vp = NULL;
                             } else vp = NULL;
                         }
+
+                       debug(F110,"XXX vnambuf",vnambuf,0);
+                       debug(F000,"XXX c","",c);
+                       debug(F101,"XXX x1","",x1);
+                       debug(F101,"XXX x2","",x2);
+                       debug(F110,"XXX result",vp,0);
 #ifdef DEBUG
                         if (deblog) {
                             if (!vp) {
index 6110629..c93036f 100644 (file)
--- a/ckuus5.c
+++ b/ckuus5.c
@@ -15,7 +15,7 @@ int cmdsrc() { return(0); }
     Jeffrey E Altman <jaltman@secure-endpoints.com>
       Secure Endpoints Inc., New York City
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2011,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -49,6 +49,8 @@ char tmpbuf[TMPBUFSIZ+1];               /* Temporary buffer */
 #include "ck_ssl.h"
 #endif /* CK_SSL */
 
+extern char * ck_cryear;       /* (ckcmai.c) Latest C-Kermit copyright year */
+
 #ifdef OS2
 #include "ckoetc.h"
 #ifndef NT
@@ -79,6 +81,11 @@ extern int cursor_save ;
 extern bool cursorena[] ;
 #endif /* OS2 */
 
+/* 2010-03-09 SMS.  VAX C V3.1-051 needs <stat.h> for off_t. */
+#ifdef VMS
+#include <stat.h>
+#endif /* def VMS */
+
 /* For formatted screens, "more?" prompting, etc. */
 
 #ifdef FT18
@@ -103,7 +110,7 @@ extern int carrier, cdtimo, local, quiet, backgrd, bgset, sosi, xsuspend,
   inserver, diractive, tlevel, cwdf, nfuncs, msgflg, remappd, hints, mdmtyp,
   zincnt, cmask, rcflag, success, xitsta, pflag, tnlm, tn_nlm, xitwarn,
   debses, xaskmore, parity, saveask, wasclosed, whyclosed, cdactive,
-  rcdactive, keepallchars;
+  rcdactive, keepallchars, cmd_err;
 
 #ifdef LOCUS
 extern int locus, autolocus;
@@ -169,6 +176,12 @@ extern char browsurl[];
 #endif /*  NOFRILLS */
 #endif /* NOPUSH */
 
+#ifndef NOFRILLS
+#ifndef NORENAME
+_PROTOTYP(VOID shorename, (void));
+#endif /* NORENAME */
+#endif /* NOFRILLS */
+
 #ifndef NOSERVER
 extern char * x_user, * x_passwd, * x_acct;
 #endif /* NOSERVER */
@@ -183,7 +196,7 @@ extern int ckrooterr;
 #endif /* CKROOT */
 
 #ifndef NOSPL
-extern int cfilef, xxdot;
+extern int cfilef, xxdot, vareval;
 extern char cmdfil[];
 
 struct localvar * localhead[CMDSTKL];
@@ -201,7 +214,7 @@ _PROTOTYP( static VOID expr,     (void) );
 _PROTOTYP( static VOID simple,   (void) );
 _PROTOTYP( static VOID simpler,  (void) );
 _PROTOTYP( static VOID simplest, (void) );
-_PROTOTYP( static long xparse,   (void) );
+_PROTOTYP( static CK_OFF_T xparse,   (void) );
 #endif /* NOSPL */
 #ifndef NOSHOW
 _PROTOTYP( int sho_iks, (void) );
@@ -398,7 +411,7 @@ extern char savdir[];                   /* Temporary directory */
 #endif /* CK_TMPDIR */
 
 #ifndef NOLOCAL
-extern int tt_crd, tt_escape;
+extern int tt_crd, tt_lfd, tt_escape;
 #endif /* NOLOCAL */
 
 #ifndef NOCSETS
@@ -511,8 +524,10 @@ extern int isguest;                     /* Flag for anonymous user */
 
 #ifdef DCMDBUF
 int *xquiet = NULL;
+int *xvarev = NULL;
 #else
 int xquiet[CMDSTKL];
+int xvarev[CMDSTKL];
 #endif /* DCMDBUF */
 
 char * prstring[CMDSTKL];
@@ -751,7 +766,8 @@ static struct keytab kcdtab[] = {   /* Symbolic directory names */
     { "lockdir",  VN_LCKDIR,    0 },
 #endif /* UNIX */
 #ifdef NT
-    { "personal", VN_PERSONAL,  0 },
+    { "my_documents",VN_PERSONAL,  0 },
+    { "personal", VN_PERSONAL,  CM_INV },
 #endif /* NT */
     { "startup",  VN_STAR,      0 },
     { "textdir",  VN_TXTDIR,    0 },
@@ -762,9 +778,9 @@ static int nkcdtab = (sizeof(kcdtab) / sizeof(struct keytab));
 
 #ifndef NOSPL
 _PROTOTYP( VOID freelocal, (int) );
-_PROTOTYP( static long expon, (long, long) );
-_PROTOTYP( static long gcd, (long, long) );
-_PROTOTYP( static long fact, (long) );
+_PROTOTYP( static CK_OFF_T expon, (CK_OFF_T, CK_OFF_T) );
+_PROTOTYP( static CK_OFF_T gcd, (CK_OFF_T, CK_OFF_T) );
+_PROTOTYP( static CK_OFF_T fact, (CK_OFF_T) );
 
 int                     /* Initialize macro data structures. */
 macini() {              /* Allocate mactab and preset the first element. */
@@ -1131,7 +1147,7 @@ cmdini() {
 #ifndef NOSPL
     /* Allocate INPUT command buffer */
     if (!inpbuf) {
-        if (!(inpbuf = (char *) malloc(INPBUFSIZ+1)))
+        if (!(inpbuf = (char *) malloc(INPBUFSIZ+8)))
           fatal("cmdini: no memory for INPUT buffer");
     }
     for (x = 0; x < INPBUFSIZ; x++)     /* Initialize it */
@@ -1164,6 +1180,8 @@ cmdini() {
       fatal("cmdini: no memory for merror");
     if (!(xquiet = (int *) malloc(sizeof(int)*CMDSTKL)))
       fatal("cmdini: no memory for xquiet");
+    if (!(xvarev = (int *) malloc(sizeof(int)*CMDSTKL)))
+      fatal("cmdini: no memory for xvarev");
     if (!kermrc)
       if (!(kermrc = (char *) malloc(KERMRCL+1)))
         fatal("cmdini: no memory for kermrc");
@@ -1203,6 +1221,7 @@ cmdini() {
     takerr[0] = 0;
     merror[0] = 0;
     xquiet[0] = quiet;
+    xvarev[0] = vareval;
 #endif /* NOSPL */
 
 #ifndef NOSPL
@@ -1567,6 +1586,7 @@ extern int ckrooterr;
         takerr[cmdlvl] = takerr[cmdlvl-1];
         merror[cmdlvl] = merror[cmdlvl-1];
         xquiet[cmdlvl] = quiet;
+        xvarev[cmdlvl] = vareval;
 #endif /* NOSPL */
         debug(F110,"doinit init file",line,0);
     } else {
@@ -1647,8 +1667,8 @@ extern int ckrooterr;
 
 #ifdef USE_CUSTOM
     /* If no init file was found, execute the customization file */
-    debug(F110,"CUSTOM 1",line,0);
-    if (!line[0] || zchki(line) < 0) {
+    debug(F111,"CUSTOM 1",line,rcflag);
+    if ((!line[0] || zchki(line) < 0) && !rcflag) {
        int x;
 #ifdef OS2
        x = ckmakestr(line,LINBUFSIZ,GetAppData(1),"/","K95CUSTOM.INI",NULL);
@@ -1700,6 +1720,7 @@ extern int ckrooterr;
         takerr[cmdlvl] = takerr[cmdlvl-1];
         merror[cmdlvl] = merror[cmdlvl-1];
         xquiet[cmdlvl] = quiet;
+        xvarev[cmdlvl] = vareval;
         debug(F101,"doinit open ok","",cmdlvl);
         xcmdsrc = CMD_TF;
         cmdstk[cmdlvl].src = CMD_TF;
@@ -1735,6 +1756,7 @@ extern int ckrooterr;
             takerr[cmdlvl] = takerr[cmdlvl-1];
             merror[cmdlvl] = merror[cmdlvl-1];
             xquiet[cmdlvl] = quiet;
+           xvarev[cmdlvl] = vareval;
 #endif /* NOSPL */
         }
     }
@@ -1832,6 +1854,7 @@ doiksdinit() {
         takerr[cmdlvl] = takerr[cmdlvl-1];
         merror[cmdlvl] = merror[cmdlvl-1];
         xquiet[cmdlvl] = quiet;
+       xvarev[cmdlvl] = vareval;
 #endif /* NOSPL */
         debug(F110,"doiksdinit file ok",tfnam[tlevel],0);
     } else {
@@ -2054,7 +2077,7 @@ getnct(s,n,f,flag) char *s; int n; FILE *f; int flag; {
     int bc = 0;                         /* Block counter */
 
     s2 = s;                             /* Remember original pointer */
-    prev = s2;
+    prev = s2;                         /* Here too */
     buflen = n;                         /* Remember original buffer length */
 
     if (n < 0)
@@ -2073,7 +2096,7 @@ getnct(s,n,f,flag) char *s; int n; FILE *f; int flag; {
     if (!lpx) {                         /* Get new one */
         if (!(lpx = (char *) malloc(n))) {
             debug(F101,"getnct malloc failure","",0);
-            printf("?Memory allocation failure [getnct]\n");
+            printf("?Memory allocation failure [getnct:%d]\n",n);
             return(-2);
         }
         lpxlen = n;
@@ -2093,6 +2116,7 @@ getnct(s,n,f,flag) char *s; int n; FILE *f; int flag; {
             *s = NUL;                   /* Make destination be empty */
             return(-1);                 /* Return failure code */
         }
+
 #ifndef NODIAL
         if (flag)                       /* Count this line */
           dirline++;
@@ -2237,7 +2261,7 @@ getnct(s,n,f,flag) char *s; int n; FILE *f; int flag; {
 #endif /* COMMENT */
 
         if (bc > 0 && *lp3 == '}') {    /* First char on line is '}' */
-            bc--;                               /* Decrement block counter */
+            bc--;                      /* Decrement block counter */
         }
 
         if (bc == 0 &&                  /* Line is continued if bc > 0 */
@@ -2373,6 +2397,58 @@ shostack() {                            /* Dump the command stack */
       printf(" %2d. Prompt: (top level)\n",0);
 }
 
+/* For command error messages - avoid dumping out the contents of some */
+/* some huge FOR loop if it contains a syntax error. */
+
+static char *
+cmddisplay(s, cx) char * s; int cx; {
+    static char buf[80];
+    if ((int)strlen(s) > 70) {
+       sprintf(buf,"%.64s...",s);      /* SAFE */
+       s = buf;
+    }
+    return(s);
+}
+
+static VOID
+cmderr() {
+    if (xcmdsrc > 0) {
+       switch (cmd_err) {              /* SET COMMAND ERROR-DISPLAY */
+         case 0:
+           break;
+         case 1:
+         case 2:
+           if (tlevel > -1) {
+#ifndef NOSPL
+               if (xcmdsrc == 2)
+                 printf(
+"In macro or block defined in file: %s starting about line %d\n",
+                        tfnam[tlevel] ? tfnam[tlevel] : "", tfline[tlevel]
+                        );
+               else
+#endif /* NOSPL */
+                 printf("File: %s, Line: %d\n",
+                        tfnam[tlevel] ? tfnam[tlevel] : "", tfline[tlevel]
+                        );
+           }
+#ifndef NOSPL
+           if (cmd_err == 2) {
+               if (cmdstk[cmdlvl].src == CMD_MD) { /* Executing a macro? */
+                   int m;
+                   m = cmdstk[cmdlvl].lvl;
+                   if (mlook(mactab,m_arg[m][0],nmac) >= 0)
+                     printf("Macro name: %s\n", m_arg[m][0]);
+               }
+           }
+#endif /* NOSPL */
+           break;
+
+         case 3:
+           printf("Command stack:\n");
+           shostack();                     
+       }
+    }
+}
 
 /*  P A R S E R  --  Top-level interactive command parser.  */
 
@@ -2397,7 +2473,7 @@ parser(m) int m; {
 
 #ifndef NOSPL
     int inlevel;                        /* Level we were called at */
-    extern int askflag;
+    extern int askflag, echostars;
 #endif /* NOSPL */
     char *cbp;                          /* Command buffer pointer */
 #ifdef MAC
@@ -2408,8 +2484,6 @@ parser(m) int m; {
     extern int sndcmd, getcmd, fatalio, clearrq;
 #endif /* NOXFER */
 
-    debok = 1;                          /* Undisable debugging */
-
 #ifdef AMIGA
     reqres();                           /* Restore AmigaDOS requestors */
 #endif /* AMIGA */
@@ -2493,7 +2567,8 @@ parser(m) int m; {
     if (cdlost && !interrupted && (sndcmd || getcmd)) {
         printf("?Connection broken (carrier signal lost)\n");
     }
-    if (sndcmd && !success && hints && !interrupted && !fatalio && !xcmdsrc) {
+    if (sndcmd && protocol == PROTO_K &&
+       !success && hints && !interrupted && !fatalio && !xcmdsrc) {
         int x = 0, n = 0;
         printf("\n*************************\n");
         printf("SEND-class command failed.\n");
@@ -2559,28 +2634,28 @@ parser(m) int m; {
 
 #ifdef CK_SPEED
         if (prefixing != PX_ALL && rpackets > 2) {
-            printf(" . Try it again with SET PREFIXING ALL.\n");
+            printf(" . Try it again with: SET PREFIXING ALL\n");
             x++;
         }
 #endif /* CK_SPEED */
 #ifdef STREAMING
         if (streamed) {
-            printf(" . Try it again with SET STREAMING OFF.\n");
+            printf(" . Try it again with: SET STREAMING OFF\n");
             x++;
         } else if (reliable) {
-            printf(" . Try it again with SET RELIABLE OFF.\n");
+            printf(" . Try it again with: SET RELIABLE OFF\n");
             x++;
         }
 #endif /* STREAMING */
 
 #ifdef CK_SPEED
         if (clearrq > 0 && prefixing == PX_NON) {
-            printf(" . Try it again with SET CLEAR-CHANNEL OFF.\n");
+            printf(" . Try it again with: SET CLEAR-CHANNEL OFF\n");
             x++;
         }
 #endif /* CK_SPEED */
         if (!parity) {
-            printf(" . Try it again with SET PARITY SPACE.\n");
+            printf(" . Try it again with: SET PARITY SPACE\n");
             x++;
         }
         printf(" . %sive a ROBUST command and try again.\n",
@@ -2589,11 +2664,16 @@ parser(m) int m; {
         printf("Also:\n");
         printf(" . Be sure the source file has read permission.\n");
         printf(" . Be sure the target directory has write permission.\n");
+/*
+        if the file was 2G or larger make sure other Kermit supports LFs...
+*/
+        printf(" . Be sure the target disk has sufficient space.\n");
         printf("(Use SET HINTS OFF to suppress hints.)\n");
         printf("*************************\n\n");
     }
     debug(F101,"topcmd","",topcmd);
-    if (getcmd && !success && hints && !interrupted && !fatalio && !xcmdsrc) {
+    if (getcmd && protocol == PROTO_K &&
+       !success && hints && !interrupted && !fatalio && !xcmdsrc) {
         int x = 0;
         extern int urpsiz, wslotr;
         printf("\n*************************\n");
@@ -2642,15 +2722,15 @@ parser(m) int m; {
 #endif /* NOLOCAL */
 #ifdef STREAMING
         if (streamed) {
-            printf(" . Try it again with SET STREAMING OFF.\n");
+            printf(" . Try it again with: SET STREAMING OFF\n");
             x++;
         } else if (reliable && local) {
-            printf(" . Try it again with SET RELIABLE OFF.\n");
+            printf(" . Try it again with: SET RELIABLE OFF\n");
             x++;
         } else
 #endif /* STREAMING */
         if (!parity) {
-            printf(" . Try it again with SET PARITY SPACE.\n");
+            printf(" . Try it again with: SET PARITY SPACE\n");
             x++;
         }
         printf((x > 0) ?
@@ -2659,6 +2739,7 @@ parser(m) int m; {
                );
         printf("Also:\n");
         printf(" . Be sure the target directory has write permission.\n");
+        printf(" . Be sure the target disk has sufficient space.\n");
         printf(" . Try telling the %s to SET PREFIXING ALL.\n",
                topcmd == XXGET ? "server" : "sender"
                );
@@ -2712,13 +2793,6 @@ parser(m) int m; {
         makestr(&snd_rename,g_snd_rename);
         makestr(&rcv_rename,g_rcv_rename);
 #endif /* NOXFER */
-        xaskmore = saveask;             /* Restore global more-prompting */
-        diractive = 0;
-        cdactive = 0;
-
-#ifndef NOSPL
-        askflag = 0;
-#endif /* NOSPL */
 
     /* Take requested action if there was an error in the previous command */
 
@@ -2886,6 +2960,14 @@ parser(m) int m; {
         while (repars) {                /* Parse this cmd until entered. */
 
             debug(F101,"parser top of while loop","",0);
+           xaskmore = saveask;         /* Restore global more-prompting */
+           diractive = 0;              /* DIR command not active */
+           cdactive = 0;               /* CD command not active */
+#ifndef NOSPL
+           askflag = 0;                /* ASK command not active */
+           echostars = 0;              /* Nor ASKQ */
+           debok = 1;                  /* Undisable debugging */
+#endif /* NOSPL */
 
 #ifdef RECURSIVE
             /* In case of "send /recursive ./?<Ctrl-U>" etc */
@@ -2973,28 +3055,11 @@ parser(m) int m; {
 #endif /* NOSPL */
 
                   default:
-                    if (!quiet) {
-                        printf("\n?Invalid - \"%s\"\n",cmdbuf);
-#ifdef COMMENT
-#ifndef NOSPL
-                        if (maclvl > -1 && xcmdsrc == 2)
-                          printf("Macro: %s; ",
-                                 m_arg[maclvl][0] ?
-                                 m_arg[maclvl][0] : "");
-#endif /* NOSPL */
-                        if (tlevel > -1) {
-                            printf("Command file: %s, line %d\n",
-                                   tfnam[tlevel] ? tfnam[tlevel] : "",
-                                   tfline[tlevel]
-                                   );
-                        }
-#else
-                        if (xcmdsrc > 0) {
-                            printf("Command stack:\n");
-                            shostack();
-                        }
-#endif /* COMMENT */
-
+                    if (!quiet && !cmd_err) {
+                        printf("\n?Invalid - \"%s\"\n",
+                              cmddisplay((char *)cmdbuf,xx)
+                              );
+                       cmderr();
                     }
                     xx = -2;
                 }
@@ -3034,6 +3099,19 @@ parser(m) int m; {
             zz = docmd(xx);             /* Parse rest of command & execute. */
 
 #ifndef NOSPL
+           {                           /* For \v(lastcommand) */
+               extern char * prevcmd;
+               /* The exception list kind of a hack but let's try it... */
+               if (ckstrcmp(cmdbuf,"_getarg",7,0) &&
+                   ckstrcmp(cmdbuf,"if ",3,0) &&
+                   ckstrcmp(cmdbuf,"xif ",4,0) &&
+                   ckstrcmp(cmdbuf,"do _if",6,0) &&
+                   ckstrcmp(cmdbuf,"_assign _if",11,0))
+                 ckstrncpy(prevcmd,cmdbuf,CMDBL);
+           }
+#endif /* NOSPL */
+
+#ifndef NOSPL
             if (fnerror && !fnsuccess)
               success = 0;
 #endif /* NOSPL */
@@ -3067,126 +3145,74 @@ parser(m) int m; {
 
 #endif /* OS2 */
               case -6:                  /* Invalid command given w/no args */
-              case -2:                  /* Invalid command given w/args */
-#ifdef COMMENT
-#ifndef NOSPL
-                    /* This is going to be really ugly... */
-                    yy = mlook(mactab,atmbuf,nmac); /* Look in macro table */
-                    if (yy > -1) {                  /* If it's there */
-                        if (zz == -2) {             /* insert "do" */
-                            char *mp;
-                            mp = malloc((int)strlen(cmdbuf) + 5);
-                            if (!mp) {
-                                printf("?malloc error 1\n");
-                                return(-2);
-                            }
-                            sprintf(mp,"do %s ",cmdbuf); /* SAFE (checked) */
-                            ckstrncpy(cmdbuf,mp,CMDBL);
-                            free(mp);
-                            mp = NULL;
-                        } else {
-                            if (((int)strlen(atmbuf) + 5) < CMDBL)
-                              sprintf(cmdbuf,"do %s %c",atmbuf, CR); /* SAFE */
-                            else
-                              ckstrncpy(cmdbuf,"echo ?Too long\r",CMDBL);
-                        }
-                        if (ifcmd[cmdlvl] == 2) /* This one doesn't count! */
-                          ifcmd[cmdlvl]--;
-                        debug(F111,"stuff cmdbuf",cmdbuf,zz);
-                        repars = 1;     /* Go for reparse */
-                        continue;
-                    } else {
-                        char *p;
-                        int n;
-                        p = cmdbuf;
-                        lp = line;
-                        n = LINBUFSIZ;
-                        if (cmflgs == 0) printf("\n");
-                        if (zzstring(p,&lp,&n) > -1)
-                          printf("?Invalid: %s\n",line);
-                        else
-                          printf("?Invalid: %s\n",cmdbuf);
-                    } /* (fall thru...) */
-#else
-                    printf("?Invalid: %s\n",cmdbuf);
-#endif /* NOSPL */
-#else /* Not COMMENT */
-                    printf("?Invalid: %s\n",cmdbuf);
-#endif /* COMMENT */
-
-                case -9:                /* Bad, error message already done */
-                    success = 0;
-                    debug(F110,"top-level cmkey failed",cmdbuf,0);
-                    /* If in background w/ commands coming stdin, terminate */
-                    if (pflag == 0 && tlevel < 0)
-                      fatal("Kermit command error in background execution");
+              case -2: {               /* Invalid command given w/args */
+                 int x = 0;
+                 char * eol = "";
+                 x = strlen(cmdbuf);   /* Avoid blank line */
+                 if (x > 0) {
+                     if (cmdbuf[x-1] != LF)
+                       eol = "\n";
+                     printf("?Invalid: %s%s",
+                            cmddisplay(cmdbuf,xx),eol
+                            );
+                 } else
+                   printf("?Invalid\n");
+             }
+             case -9:                  /* Bad, error message already done */
+               success = 0;
+               debug(F110,"top-level cmkey failed",cmdbuf,0);
+               /* If in background w/ commands coming stdin, terminate */
+               if (pflag == 0 && tlevel < 0)
+                 fatal("Kermit command error in background execution");
 /*
   Command retry feature, edit 190.  If we're at interactive prompting level,
   reprompt the user with as much of the command as didn't fail.
 */
 #ifdef CK_RECALL
-                    if (cm_retry && !xcmdsrc) { /* If at top level */
-                        int len;
-                        char *p, *s;
-                        len = strlen(cmdbuf); /* Length of command buffer */
-                        p = malloc(len + 1);  /* Allocate space for copy */
-                        if (p) {              /* If we got the space copy */
-                            strcpy(p,cmdbuf); /* the command buffer (SAFE). */
-                            /* Chop off final field, the one that failed. */
-                            s = p + len - 1;          /* Point to end */
-                            while (*s == SP && s > p) /* Trim blanks */
-                              s--;
-                            while (*s != SP && s > p) /* Trim last field */
-                              s--;
-                            if (s > p)        /* Keep the space */
-                              s++;            /* after last good field */
-                            if (s >= p)       /* Cut off remainder */
-                              *s = NUL;
-                            cmini(ckxech);    /* Reinitialize the parser */
-                            ckstrncpy(cmdbuf,p,CMDBL); /* Copy result back */
-                            free(p);          /* Free temporary storage */
-                            p = NULL;
-                            prompt(xxstring); /* Reprint the prompt */
-                            printf("%s",cmdbuf); /* Reprint partial command */
-                            repars = 1;          /* Force reparse */
-                            continue;
-                        }
-                    } else
+               if (cm_retry && !xcmdsrc) { /* If at top level */
+                   int len;
+                   char *p, *s;
+                   len = strlen(cmdbuf); /* Length of command buffer */
+                   p = malloc(len + 1);  /* Allocate space for copy */
+                   if (p) {              /* If we got the space copy */
+                       strcpy(p,cmdbuf); /* the command buffer (SAFE). */
+                       /* Chop off final field, the one that failed. */
+                       s = p + len - 1;          /* Point to end */
+                       while (*s == SP && s > p) /* Trim blanks */
+                         s--;
+                       while (*s != SP && s > p) /* Trim last field */
+                         s--;
+                       if (s > p)        /* Keep the space */
+                         s++;            /* after last good field */
+                       if (s >= p)       /* Cut off remainder */
+                         *s = NUL;
+                       cmini(ckxech);    /* Reinitialize the parser */
+                       ckstrncpy(cmdbuf,p,CMDBL); /* Copy result back */
+                       free(p);          /* Free temporary storage */
+                       p = NULL;
+                       prompt(xxstring); /* Reprint the prompt */
+                       printf("%s",cmdbuf); /* Reprint partial command */
+                       repars = 1;          /* Force reparse */
+                       continue;
+                   }
+               } else
 #endif /* CK_RECALL */
-                      if (!quiet) {
-#ifdef COMMENT
-#ifndef NOSPL
-                          if (maclvl > -1)
-                            printf("Macro: %s; ",
-                                   m_arg[maclvl][0] ?
-                                   m_arg[maclvl][0] : "");
-#endif /* NOSPL */
-                          if (tlevel > -1)
-                            printf("Command file: %s, line %d\n",
-                                   tfnam[tlevel] ? tfnam[tlevel] : "",
-                                   tfline[tlevel]
-                                   );
-#else
-                          if (xcmdsrc > 0) {
-                              printf("Command stack:\n");
-                              shostack();
-                          }
-#endif /* COMMENT */
-                      }
-                      cmini(ckxech);    /* (fall thru) */
+                 cmderr();
 
-                case -3:                /* Empty command OK at top level */
-                    repars = 0;         /* Don't need to reparse. */
-                    continue;           /* Go back and get another command. */
+               cmini(ckxech);          /* (fall thru) */
 
-                default:                /* Command was successful. */
+             case -3:                  /* Empty command OK at top level */
+               repars = 0;             /* Don't need to reparse. */
+               continue;               /* Go back and get another command. */
+
+             default:                  /* Command was successful. */
 #ifndef NOSPL
-                    debug(F101,"parser preparing to continue","",maclvl);
+               debug(F101,"parser preparing to continue","",maclvl);
 #endif /* NOSPL */
-                    debug(F101,"parser success","",success);
-                    repars = 0;         /* Don't need to reparse. */
-                    continue;           /* Go back and get another command. */
-                }
+               debug(F101,"parser success","",success);
+               repars = 0;             /* Don't need to reparse. */
+               continue;               /* Go back and get another command. */
+           }
         }
 #ifndef NOSPL
         debug(F101,"parser breaks out of while loop","",maclvl);
@@ -3357,7 +3383,7 @@ vardef(s,isarray,x1,x2) char * s; int * isarray, * x1, * x2; {
             }
             if (x < 0)
               return(NULL);
-            if (chkarray(vbi,d) > 0) {  /* Array is declared? */
+            if (chkarray(vbi,d) >= 0) {        /* Array is declared? */
                 vbi -= ARRAYBASE;       /* Convert name to index */
                 if (a_dim[vbi] >= d) {  /* If subscript in range */
                     char **ap;
@@ -3479,13 +3505,30 @@ dooutput(s, cx) char *s; int cx; {
 #ifdef NOLOCAL
         goto outerr;
 #else
-        if (ttchk() < 0) {
-            printf("?Connection %s %s is not open.\n",
-                   network ? "to" : "on",
-                   ttname
-                   );
-            return(0);
-        }
+       if (ttchk() < 0) {
+           if (!network) {
+               if (carrier != CAR_OFF) {
+                   int x;
+                   x = ttgmdm();
+                   if ((x > -1) && ((x & BM_DCD) == 0)) {
+                       printf(
+"?Carrier signal required but not present - Try SET CARRIER-WATCH OFF.\n"
+                              );
+                       return(0);
+                   }
+               } else {
+                   printf(
+"?Problem with serial port or modem or cable - Try SHOW COMMUNICATIONS.\n"
+                          );
+                   return(0);
+               }
+           }
+           printf("?Connection %s %s is not open or not functioning.\n",
+                  network ? "to" : "on",
+                  ttname
+                  );
+           return(0);
+       }
         if (ttvt(speed,flow) < 0) {
             printf("?OUTPUT initialization error\n");
             return(0);
@@ -3735,6 +3778,10 @@ herald() {
     int x = 0, i;
     extern int srvcdmsg;
     extern char * cdmsgfile[];
+    char * ssl;
+    char * krb4;
+    char * krb5;
+
 #ifndef NOCMDL
     extern char * bannerfile;
     debug(F110,"herald bannerfile",bannerfile,0);
@@ -3762,10 +3809,11 @@ herald() {
     /* The following generates bad code in SCO compilers. */
     /* Observed in both OSR5 and Unixware 2 -- after executing this */
     /* statement when all conditions are false, x has a value of -32. */
-    if (noherald || bgset > 0 || (bgset != 0 && backgrd != 0)) x = 1;
+    if (noherald || quiet || bgset > 0 || (bgset != 0 && backgrd != 0))
+      x = 1;
 #else
     x = 0;
-    if (noherald)
+    if (noherald || quiet)
       x = 1;
     else if (bgset > 0)
       x = 1;
@@ -3773,6 +3821,21 @@ herald() {
       x = 1;
 #endif /* COMMENT */
 
+    ssl = "";
+    krb4 = "";
+    krb5 = "";
+#ifdef CK_AUTHENTICATION
+#ifdef CK_SSL    
+    ssl = "+SSL";
+#endif /* CK_SSL */
+#ifdef KRB4
+    krb4 = "+KRB4";
+#endif /* KRB4 */
+#ifdef KRB5
+    krb5 = "+KRB5";
+#endif /* KRB5 */
+#endif /* CK_AUTHENTICATION */
+
     if (x == 0) {
 #ifdef datageneral
         printf("%s, for%s\n",versio,ckxsys);
@@ -3780,10 +3843,14 @@ herald() {
 #ifdef OSK
         printf("%s, for%s\n",versio,ckxsys);
 #else
-        printf("%s, for%s\n\r",versio,ckxsys);
+#ifdef CK_64BIT
+        printf("%s, for%s%s%s%s (64-bit)\n\r",versio,ckxsys,ssl,krb4,krb5);
+#else
+        printf("%s, for%s%s%s%s\n\r",versio,ckxsys,ssl,krb4,krb5);
+#endif/* CK_64BIT */
 #endif /* OSK */
 #endif /* datageneral */
-        printf(" Copyright (C) 1985, 2004,\n");
+        printf(" Copyright (C) 1985, %s,\n", ck_cryear);
         printf("  Trustees of Columbia University in the City of New York.\n");
 #ifdef OS2
        shoreg();
@@ -4571,14 +4638,14 @@ popclvl() {                             /* Pop command level, return cmdlvl */
         /* Automatic arrays do not use the localhead list */
 
         for (i = 0; i < 28; i++) {      /* Free any local arrays */
-            if (aa_ptr[cmdlvl][i]) { /* Does this one exist? */
-                dclarray((char)(i+ARRAYBASE),0); /* Destroy global one */
+            if (aa_ptr[cmdlvl][i]) {   /* Does this one exist? */
+                dclarray((char)(i+ARRAYBASE),-1); /* Destroy global one */
                 a_ptr[i] = aa_ptr[cmdlvl][i];
                 a_dim[i] = aa_dim[cmdlvl][i];
                 aa_ptr[cmdlvl][i] = (char **)NULL;
                 aa_dim[cmdlvl][i] = 0;
             } else if (aa_dim[cmdlvl][i] == -23) { /* Secret code */
-                dclarray((char)(i+ARRAYBASE),0); /* (see pusharray()) */
+                dclarray((char)(i+ARRAYBASE),-1); /* (see pusharray()) */
                 aa_ptr[cmdlvl][i] = (char **)NULL;
                 aa_dim[cmdlvl][i] = 0;
             }
@@ -4606,6 +4673,7 @@ popclvl() {                             /* Pop command level, return cmdlvl */
             tlevel--;                   /* and pop take level */
             cmdlvl--;                   /* and command level */
             quiet = xquiet[cmdlvl];
+            vareval = xvarev[cmdlvl];
         } else
           tlevel = -1;
     } else if (cmdstk[cmdlvl].src == CMD_MD) { /* In a macro? */
@@ -4644,6 +4712,7 @@ popclvl() {                             /* Pop command level, return cmdlvl */
             debug(F010,"popclvl mac mrval[maclvl+1]",mrval[maclvl+2],0);
 
             quiet = xquiet[cmdlvl];
+           vareval = xvarev[cmdlvl];
             if (maclvl > -1) {
                 a_ptr[0] = m_xarg[maclvl];
                 a_dim[0] = n_xarg[maclvl] - 1;
@@ -5573,6 +5642,7 @@ shotrm() {
     int lines = 0;
 #ifdef KUI
     extern CKFLOAT tt_linespacing[];
+    extern tt_cursor_blink;
 #endif /* KUI */
 #ifdef PCFONTS
     int i;
@@ -5630,12 +5700,20 @@ shotrm() {
     printf(" %19s: %-13s  %13s: %-15s\n","Echo",
            duplex ? "local" : "remote","Locking-shift",showoff(sosi));
     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
-    printf(" %19s: %-13s  %13s: %-15s\n","Newline-mode",
-           showoff(tnlm),"Cr-display",tt_crd ? "crlf" : "normal");
+    printf(" %19s: %-13s  %13s: %-15s\n","Newline-mode", showoff(tnlm),
+          "Cr-display",tt_crd ? "crlf" : "normal");
     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
     printf(" %19s: %-13s  %13s: %-15s\n","Cursor",
+#ifdef KUI
+           (tt_cursor == 2) ? (tt_cursor_blink ? 
+                                "full (*)" : "full (.)") :
+           (tt_cursor == 1) ? (tt_cursor_blink ? 
+                                "half (*)" : "half (.)") :
+           (tt_cursor_blink ? "underline (*)" : "underline (.)"),
+#else /* KUI */
            (tt_cursor == 2) ? "full" :
            (tt_cursor == 1) ? "half" : "underline",
+#endif /* KUI */
 #ifdef CK_AUTODL
            "autodownload",autodl == TAD_ON ?
            (adl_err ? "on, error stop" : "on, error continue") : 
@@ -5752,7 +5830,7 @@ shotrm() {
            "Width",tt_cols[VTERM]);
     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
 #ifdef KUI
-    printf(" %19s: %-13f  %13s: %-15d\n","Line spacing",tt_linespacing[VTERM],
+    printf(" %19s: %-12f  %14s: %-15d\n","Line spacing",tt_linespacing[VTERM],
            "Display Height",VscrnGetDisplayHeight(VTERM));
     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
 #endif /* KUI */
@@ -5872,11 +5950,12 @@ shotrm() {
     printf("\n");
     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
     {
-        extern int trueblink, truereverse, trueunderline, trueitalic;
+        extern int trueblink, truedim, truereverse, trueunderline, trueitalic;
         printf(
-    " Attribute:  blink: %-3s  reverse: %-3s  underline: %-3s italic: %-3s\n",
-                trueblink?"on":"off", truereverse?"on":"off",
-                trueunderline?"on":"off", trueitalic?"on":"off");
+           " Attribute:  \
+blink: %-3s  dim: %-3s  italic: %-3s  reverse: %-3s  underline: %-3s\n",
+           trueblink?"on":"off", truedim?"on":"off", trueitalic?"on":"off", 
+           truereverse?"on":"off", trueunderline?"on":"off");
         if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
     }
     {
@@ -5927,9 +6006,10 @@ shotrm() {
 #ifdef CK_APC
     if (apcstatus == APC_ON) s = "on";
     else if (apcstatus == APC_OFF) s = "off";
-    else if (apcstatus == APC_ON|APC_UNCH) s = "unchecked";
-    else if (apcstatus == APC_ON|APC_NOINP) s = "no-input";
-    else if (apcstatus == APC_ON|APC_UNCH|APC_NOINP) s = "unchecked-no-input";
+    else if (apcstatus == (APC_ON|APC_UNCH)) s = "unchecked";
+    else if (apcstatus == (APC_ON|APC_NOINP)) s = "no-input";
+    else if (apcstatus == (APC_ON|APC_UNCH|APC_NOINP))
+      s = "unchecked-no-input";
     printf(" %19s: %-13s  %13s: %-15s\n",
            "APC", s,
 #ifdef CK_AUTODL
@@ -5954,17 +6034,20 @@ shotrm() {
            "Idle-action", getiact());
 #endif /* CKTIDLE */
 
-#ifndef NOTRIGGER
-    printf(" %19s: %-13s\n","Trigger",
-           tt_trigger[0] ? tt_trigger[0] : "(none)");
-#endif /* NOTRIGGER */
+    printf(" %19s: %-13s  ","Lf-display", tt_lfd ? "crlf" : "normal");
 #ifdef UNIX
 #ifndef NOJC
-    printf(" %19s: %-13s\n\n","Suspend", showoff(xsuspend));
+    printf("%13s: %-15s","Suspend", showoff(xsuspend));
 #endif /* NOJC */
 #endif /* UNIX */
+    printf("\n");
 
+#ifndef NOTRIGGER
+    printf(" %19s: %-13s\n","Trigger",
+           tt_trigger[0] ? tt_trigger[0] : "(none)");
+#endif /* NOTRIGGER */
     printf("\n");
+
     (VOID) shoesc(escape);
 #ifndef NOCSETS
     shotcs(tcsl,tcsr);          /* Show terminal character sets */
@@ -6813,6 +6896,7 @@ doshow(x) int x; {
 
 #ifndef NOSPL
       case SHBUI:                       /* Built-in variables */
+       line[0] = NUL;
         if ((y = cmtxt("Variable name or pattern","",&s,xxstring)) < 0)
           return(y);
         ckstrncpy(line,s,LINBUFSIZ);
@@ -7047,6 +7131,8 @@ doshow(x) int x; {
         printf(" Macro echo:             %s\n", showoff(mecho));
         printf(" Macro error:            %s\n", showoff(merror[cmdlvl]));
         printf(" Quiet:                  %s\n", showoff(quiet));
+        printf(" Variable evaluation:    %s [\\%%x and \\&x[] variables]\n",
+              vareval ? "recursive" : "simple");
         printf(" Function diagnostics:   %s\n", showoff(fndiags));
         printf(" Function error:         %s\n", showoff(fnerror));
 #ifdef CKLEARN
@@ -7295,6 +7381,7 @@ doshow(x) int x; {
 #ifdef PRINTSWI
           extern int printtimo, printertype, noprinter;
           extern char * printterm, * printsep;
+          extern int prncs;
 #ifdef BPRINT
           extern int printbidi;
 #endif /* BPRINT */
@@ -7358,6 +7445,7 @@ doshow(x) int x; {
           } else
             printf(" /END-OF-JOB-STRING:(none)\n");
           printf(" /JOB-HEADER-FILE:%s\n",printsep ? printsep : "(none)");
+          printf(" /CHARACTER-SET: %s\n",txrinfo[prncs]->keywd);
 #endif /* PRINTSWI */
           printf("\n");
           break;
@@ -7373,6 +7461,7 @@ doshow(x) int x; {
           printf(" Command autodownload: (not available)\n");
 #endif /* CK_AUTODL */
           printf(" Command bytesize: %d bits\n", (cmdmsk == 0377) ? 8 : 7);
+          printf(" Command error-display: %d\n", cmd_err);
 #ifdef CK_RECALL
           printf(" Command recall-buffer-size: %d\n",cm_recall);
 #else
@@ -7610,13 +7699,30 @@ doshow(x) int x; {
         }
 #endif /* IKSD */
 #ifdef DEBUG
-          printf("\n Debug log:       %s\n", deblog ? debfil : "(none)");
+          printf("\n Debug log:       %s", deblog ? debfil : "(none)");
+         {
+             extern int debtim;
+             if (debtim) printf(" (timestamps)");
+             printf("\n");
+         }
 #endif /* DEBUG */
 #ifndef NOXFER
           printf(" Packet log:      %s\n",   pktlog ? pktfil : "(none)");
 #endif /* NOXFER */
 #ifndef NOLOCAL
-          printf(" Session log:     %s\n",   seslog ? sesfil : "(none)");
+          printf(" Session log:     %s",   seslog ? sesfil : "(none)");
+         {
+             extern int sessft, slogts, slognul;
+             switch (sessft) {
+               case XYFT_T: printf(" (text)"); break;
+               case XYFT_B: printf(" (binary)"); break;
+               case XYFT_D: printf(" (debug)"); break;
+             }
+             if (slogts) printf("(timestamped)");
+             if (slognul) printf("(null-padded)");
+             printf("\n");
+         }
+
 #endif /* NOLOCAL */
 #ifdef TLOG
           printf(" Transaction log: %s (%s)\n",
@@ -7882,6 +7988,14 @@ doshow(x) int x; {
         break;
 #endif /* KUI */
 
+#ifndef NOFRILLS
+#ifndef NORENAME
+      case SHOREN:
+        (VOID) shorename();
+        break;
+#endif /* NORENAME */
+#endif /* NOFRILLS */
+
       default:
         printf("\nNothing to show...\n");
         return(-2);
@@ -8007,11 +8121,11 @@ int x_ifnum = 0;                        /* Flag for IF NUMERIC active */
 static int xerror = 0;
 int divbyzero = 0;
 static char *cp;
-static long tokval;
+static CK_OFF_T tokval;
 static char curtok;
-static long expval;
+static CK_OFF_T expval;
 
-#define LONGBITS (8*sizeof (long))
+#define LONGBITS (8*sizeof (CK_OFF_T))
 #define NUMBER 'N'
 #define N_EOT 'E'
 
@@ -8150,7 +8264,7 @@ gettok() {
         x = chknum(s);
 #endif /* CKFLOAT */
         if (x > 0) {
-            tokval = atoi(s);
+            tokval = ckatofs(s);
         } else {
             if (cmdlvl == 0 && !x_ifnum && !xerror)
               printf("Bad number - \"%s\"\n",tbuf);
@@ -8163,14 +8277,14 @@ gettok() {
 #endif /* COMMENT */
 }
 
-static long
+static CK_OFF_T
 #ifdef CK_ANSIC
-expon(long x, long y)
+expon(CK_OFF_T x, CK_OFF_T y)
 #else
-expon(x,y) long x,y;
+expon(x,y) CK_OFF_T x,y;
 #endif /* CK_ANSIC */
 /* expon */ {
-    long result = 1;
+    CK_OFF_T result = 1;
     int sign = 1;
     if (y < 0) return(0);
     if (x < 0) {
@@ -8191,7 +8305,7 @@ expon(x,y) long x,y;
  */
 static VOID
 factor() {
-    long oldval;
+    CK_OFF_T oldval;
     simple();
     if (curtok == '^') {
         oldval = expval;
@@ -8208,7 +8322,7 @@ factor() {
 static VOID
 termp() {
     while (curtok == '*' || curtok == '/' || curtok == '%' || curtok == '&') {
-        long oldval;
+        CK_OFF_T oldval;
         char op;
         op = curtok;
         curtok = gettok();              /* skip past operator */
@@ -8233,14 +8347,14 @@ termp() {
     }
 }
 
-static long
+static CK_OFF_T
 #ifdef CK_ANSIC
-fact(long x)
+fact(CK_OFF_T x)
 #else
-fact(x) long x;
+fact(x) CK_OFF_T x;
 #endif /* CK_ANSIC */
 /* fact */ {                            /* factorial */
-    long result = 1;
+    CK_OFF_T result = 1;
     while (x > 1)
       result *= x--;
     return(result);
@@ -8256,11 +8370,11 @@ term() {
     termp();
 }
 
-static long
+static CK_OFF_T
 #ifdef CK_ANSIC
-gcd(long x, long y)
+gcd(CK_OFF_T x, CK_OFF_T y)
 #else
-gcd(x,y) long x,y;
+gcd(x,y) CK_OFF_T x,y;
 #endif /* CK_ANSIC */
 /* gcd */ {                             /* Greatest Common Divisor */
     int nshift = 0;
@@ -8277,7 +8391,7 @@ gcd(x,y) long x,y;
         while (!(x & 1)) x >>= 1;       /* eliminate unnecessary */
         while (!(y & 1)) y >>= 1;       /* powers of 2 */
         if (x < y) {                    /* force x to be larger */
-            long t;
+            CK_OFF_T t;
             t = x;
             x = y;
             y = t;
@@ -8285,7 +8399,7 @@ gcd(x,y) long x,y;
         x -= y;
     }
     if (x == 0 || y == 0) return((x + y) << nshift); /* gcd is non-zero one */
-    else return((long) 1 << nshift);    /* else gcd is 1 */
+    else return((CK_OFF_T) 1 << nshift);    /* else gcd is 1 */
 }
 
 /*
@@ -8295,7 +8409,7 @@ gcd(x,y) long x,y;
 static VOID
 exprp() {
     while (windex("+-|<>#@",curtok) != NULL) {
-        long oldval;
+        CK_OFF_T oldval;
         char op;
         op = curtok;
         curtok = gettok();              /* skip past operator */
@@ -8323,7 +8437,7 @@ expr() {
     exprp();
 }
 
-static long
+static CK_OFF_T
 xparse() {
     curtok = gettok();
     expr();
@@ -8360,13 +8474,13 @@ evalx(s) char *s; {
 
 char *
 evala(s) char *s; {
-    long v;                             /* Numeric value */
+    CK_OFF_T v;                                /* Numeric value */
     if (!s) return("");
     xerror = 0;                         /* Start out with no error */
     divbyzero = 0;
     cp = s;                             /* Make the argument global */
     v = xparse();                       /* Parse the string */
-    return(xerror ? "" : ckltoa(v));    /* Return empty string on error */
+    return(xerror ? "" : ckfstoa(v));  /* Return empty string on error */
 }
 
 /*
@@ -8430,12 +8544,13 @@ simple() {
 /*
   Call with:
    char a = single character designator for the array, e.g. "a".
-   int  n = size of array.
+   int  n = size of array.  -1 means to undeclare the array.
   Returns:
    0 or greater on success, having created the requested array with
      with n+1 elements, 0..n.  If an array of the same name existed
      previously, it is destroyed.  The new array has all its elements
-     initialized to NULL pointers.
+     initialized to NULL pointers.  When an array is successfully created,
+     the return value is its index (0 = 'a', 1 = 'b', and so on.)
   -1 on failure (because 'a' out of range or malloc failure).
 */
 int
@@ -8458,7 +8573,7 @@ dclarray(a,n) char a; int n;
 
     c = a;
     a -= ARRAYBASE;                     /* Convert name to number */
-    rc = a;
+    rc = a;                            /* Array index will be return code */
     if ((p = a_ptr[a]) != NULL) {       /* Delete old array of same name */
         if (a_link[a] > -1) {           /* Is it a link? */
             if (n == 0) {               /* If we're just deleting it */
@@ -8489,9 +8604,9 @@ dclarray(a,n) char a; int n;
         a_ptr[a] = (char **) NULL;      /* Remove pointer to element list */
         a_dim[a] = 0;                   /* Set dimension at zero. */
         a_link[a] = -1;                 /* Unset link word */
-        if (n == 0)
-          return(0);                    /* If dimension 0, just deallocate. */
     }
+    if (n < 0)                         /* If only undeclaring, */
+      return(0);                       /*  we're done. */
     p = (char **) malloc((n+1) * sizeof(char **)); /* Allocate for new array */
     if (p == NULL) return(-1);          /* Check */
     a_ptr[a] = p;                       /* Save pointer to member list */
@@ -8528,6 +8643,7 @@ xarray(s) char * s; {
     buf[4] = (x > 1) ? s[2] : NUL;
     buf[5] = (x > 2) ? s[3] : NUL;
     buf[6] = NUL;
+    debug(F110,"xarray buf[3]",&buf[3],0);
     s = buf+2;
     if (*s == '&') {
         buf[1] = CMDQ;
@@ -8537,6 +8653,7 @@ xarray(s) char * s; {
         buf[1] = '&';
         s = buf;
     }
+    debug(F110,"xarray s",s,0);
     c = *(s+2);
     if (isupper(c))
       c = tolower(c);
@@ -8545,7 +8662,129 @@ xarray(s) char * s; {
     x = (int)c - ARRAYBASE;
     if (*(s+3) == '[')
       *(s+3) = NUL;
-    return((x < 0 || x > 'z' - ARRAYBASE || *(s+3)) ? -1 : x);
+    if (x < 0) {
+       return(-1);
+    }
+    if (x > ('z' - ARRAYBASE)) {
+       debug(F101,"xarray x out of range","",x);
+       return(-1);
+    }
+    if (*(s+3)) {
+       debug(F110,"xarray syntax",s,0);
+       return(-1);
+    }
+    return(x);
+}
+
+/*
+  boundspair() -- parses blah[n:m]
+
+  For use with array segment specifiers and compact substring notation.
+  Ignores the "blah" part, gets the values of n and m, which can be
+  numbers, variables, or arithmetic expressions; anything that resolves
+  to a number.
+
+  Call with:
+   s    - string to parse
+   sep  - array of permissible bounds separator chars
+   lo   - pointer to low-bound result (or -1)
+   hi   - pointer to hi-bound result (or -1)
+   zz   - pointer to separator char that was encountered (or NUL)
+  Returns:
+   -1 on failure
+    0 on success
+*/      
+
+int
+#ifdef CK_ANSIC
+boundspair(char *s, char *sep, int *lo, int *hi, char *zz)
+#else
+boundspair(s,sep,lo,hi,zz) char *s, *sep, *zz; int *lo, *hi;
+#endif /* CK_ANSIC */
+{
+    int i, x, y, range[2], bc = 0;
+    char c = NUL, *s2 = NULL, buf[256], *p, *q, *r, *e[2], *tmp = NULL;
+
+    debug(F110,"boundspair s",s,0);
+    debug(F110,"boundspair sep",sep,0);
+
+    *lo = -1;                           /* Default bounds */
+    *hi = -1;
+    *zz = 0;                           /* Default bounds separator */
+
+    range[0] = -1;                      /* It's OK -- get contents */
+    range[1] = -1;                      /* of subscript brackets */
+    if (!s) s = "";
+    if (!*s)
+      return(-1);
+    makestr(&tmp,s);                    /* Make a pokeable copy */
+    p = tmp;
+    q = NULL;
+    r = NULL;
+    for (p = s; *p; p++) {             /* Get the two elements */
+       if (*p == '[') {
+           bc++;
+           if (bc == 1 && !q) q = p+1;
+       } else if (*p == ']') {
+           bc--;
+           if (bc == 0 && q) *p = NUL;
+       } else if (bc == 1) {           /* Check for separator */
+           s2 = ckstrchr(sep,*p);
+           if (s2) {
+               debug(F000,"boundspair *s2","",*s2);
+               if (c) {        
+                   debug(F000,"boundspair","Too many separators",*s2);
+                   makestr(&tmp,NULL);
+                   return(-1);
+               }
+               c = *s2;
+               *p = NUL;
+               r = p+1;
+           }
+       }
+    }
+    if (bc == 0 && !q) {
+       /* This allows such constructions as "show array a" */
+       debug(F110,"boundspair","no brackets",0);
+       makestr(&tmp,NULL);
+       return(0);
+    }
+    if (bc != 0 || !q) {
+       debug(F110,"boundspair","unbalanced or missing brackets",0);
+       makestr(&tmp,NULL);
+       return(-1);
+    }
+    if (!*q) q = "-1";
+    if (!r) r = "-1";
+
+    e[0] = q;
+    e[1] = r;
+
+    debug(F000,"boundspair c","",c);
+    debug(F110,"boundspair q",q,0);
+    debug(F110,"boundspair r",r,0);
+
+    for (i = 0; i < 2 && e[i]; i++) {
+       y = 255;                        /* Expand variables, etc. */
+       s = buf;
+       zzstring(e[i],&s,&y);
+       s = evalx(buf);                 /* Evaluate it arithmetically */
+       if (s) if (*s)
+         ckstrncpy(buf,s,256);
+       if (!chknum(buf)) {             /* Did we get a number? */
+           debug(F110,"boundspair element not numeric",buf,0);
+           makestr(&tmp,NULL);         /* No, fail. */
+           return(-1);
+       }
+       range[i] = atoi(buf);
+    }
+    makestr(&tmp,NULL);                 /* Free temporary poked string */
+    *lo = range[0];                     /* Return what we got */
+    *hi = range[1];
+    *zz = c;
+    debug(F101,"boundspair lo","",*lo);
+    debug(F101,"boundspair hi","",*hi);
+    return(0);
 }
 
 /*  A R R A Y B O U N D S  --  Parse array segment notation \&a[n:m]  */
@@ -8561,7 +8800,7 @@ xarray(s) char * s; {
 int
 arraybounds(s,lo,hi) char * s; int * lo, * hi; {
     int i, x, y, range[2];
-    char buf[256], * p, * q;
+    char zz, buf[256], * p, * q;
     char * tmp = NULL;
 
     *lo = -1;                           /* Default bounds */
@@ -8573,52 +8812,14 @@ arraybounds(s,lo,hi) char * s; int * lo, * hi; {
 
     x = xarray(s);                      /* Check basic structure */
     debug(F111,"arraybounds xarray",s,x);
-
     if (x < 0)                          /* Not OK, fail. */
       return(-1);
-    range[0] = -1;                      /* It's OK -- get contents */
-    range[1] = -1;                      /* of subscript brackets */
-    makestr(&tmp,s);                    /* Make a pokeable copy */
-    s = tmp;
-    p = s;
-    for (p = s, q = NULL; *p; p++) {    /* First find the brackets */
-        if (*p == '[') {
-            q = p+1;
-        } else if (*p == ']')
-          break;
-    }
-    if (q && *p == ']') {               /* If we have brackets... */
-        int quitnow = 0;
-        for (i = 0; i < 2 && !quitnow; i++) { /* Loop thru their contents */
-            for (p = q; *p; p++) {
-                if ((i == 0 && *p == ':') || *p == ']') {
-                    if (*p == ']')
-                      quitnow = 1;
-                    *p = NUL;
-                    if (*q) {           /* We have something */
-                        y = 255;        /* Expand variables, etc. */
-                        s = buf;
-                        zzstring(q,&s,&y);
-                        s = evalx(buf); /* Evaluate it arithmetically */
-                        if (s) if (*s)
-                          ckstrncpy(buf,s,256);
-                        if (!chknum(buf)) { /* Did we get a number? */
-                            makestr(&tmp,NULL); /* No, fail. */
-                            return(-1);
-                        }
-                        q = (i == 0) ? p+1 : NULL; /* Point to next if any */
-                        range[i] = atoi(buf); /* Set this one */
-                    }
-                    break;
-                }
-            }
-        }
-    }
-    makestr(&tmp,NULL);                 /* Free temporary poked string */
-    *lo = range[0];                     /* Return what we got */
-    *hi = range[1];
+    y = boundspair(s,":",lo,hi,&zz);
+    debug(F111,"arraybounds boundspair",s,y);
     debug(F101,"arraybounds lo","",*lo);
     debug(F101,"arraybounds hi","",*hi);
+    if (y < 0)                         /* Get bounds */
+      return(-1);
     return(x);
 }
 
@@ -8703,10 +8904,17 @@ arraynam(ss,c,n) char *ss; int *c; int *n; {
       p++;
     sx = sxbuf;                         /* Where to put expanded subscript */
     y = 16;
-    zzstring(p,&sx,&y);                 /* Convert variables, etc. */
+    {
+       /* Even if VARIABLE-EVALUATION SIMPLE use RECURSIVE for subscripts */
+       /* NOTE: This is vulnerable to SIGINT and whatnot... */
+       int tmp = vareval;              /* Save VARIABLE-EVALUATION setting */
+       vareval = 1;                    /* Force it to RECURSIVE */
+       zzstring(p,&sx,&y);             /* Convert variables, etc. */
+       vareval = tmp;                  /* Restore VARIABLE-EVALUATION */
+    }
     sx = sxbuf;
     while (*sx == SP) sx++;
-    debug(F110,"arraynam sx","",sx);
+    /* debug(F110,"arraynam sx","",sx); */
     if (!*sx) {                         /* Empty brackets... */
         *n = -17;                       /* (Secret code :-) */
         return(-2);
@@ -8733,6 +8941,8 @@ arraynam(ss,c,n) char *ss; int *c; int *n; {
     return(0);
 }
 
+/* chkarray returns 0 or greater if array exists, negative otherwise */
+
 int
 chkarray(a,i) int a, i; {               /* Check if array is declared */
     int x;                              /* and if subscript is in range */
@@ -8872,7 +9082,7 @@ parsevar(s,c,i) char *s; int *c, *i; {
    -1 on failure (bad variable syntax, variable not defined or not numeric).
 */
 int
-varval(s,v) char *s; int *v; {
+varval(s,v) char *s; CK_OFF_T *v; {
     char valbuf[VALN+1];                /* s is pointer to variable name */
     char name[256];
     char *p;
@@ -8891,13 +9101,13 @@ varval(s,v) char *s; int *v; {
         valbuf[1] = NUL;
     }
     if (chknum(p)) {                    /* Convert numeric string to int */
-        *v = atoi(p);                   /* OK */
+        *v = ckatofs(p);               /* OK */
     } else {                            /* Not OK */
         p = evala(p);                   /* Maybe it's an expression */
         if (!chknum(p))                 /* Did it evaluate? */
           return(-1);                   /* No, failure. */
         else                            /* Yes, */
-          *v = atoi(p);                 /* success */
+          *v = ckatofs(p);             /* success */
     }
     return(0);
 }
@@ -8906,8 +9116,8 @@ varval(s,v) char *s; int *v; {
 /* Returns -1 on failure, 0 on success */
 
 int
-incvar(s,x,z) char *s; int x; int z; {  /* Increment a numeric variable */
-    int n;                              /* s is pointer to variable name */
+incvar(s,x,z) char *s; CK_OFF_T x; int z; {  /* Increment a numeric variable */
+    CK_OFF_T n;                                /* s is pointer to variable name */
                                         /* x is amount to increment by */
                                         /* z != 0 means add */
                                         /* z = 0 means subtract */
@@ -8917,7 +9127,7 @@ incvar(s,x,z) char *s; int x; int z; {  /* Increment a numeric variable */
       n += x;
     else                                /* or decrement as requested. */
       n -= x;
-    addmac(s,ckitoa(n));                /* Replace old variable */
+    addmac(s,ckfstoa(n));              /* Replace old variable */
     return(0);
 }
 
@@ -8987,6 +9197,7 @@ dodo(x,s,flags) int x; char *s; int flags; {
     takerr[cmdlvl] = takerr[cmdlvl-1];  /*   and TAKE ERROR */
     merror[cmdlvl] = merror[cmdlvl-1];  /*   and MACRO ERROR */
     xquiet[cmdlvl] = quiet;
+    xvarev[cmdlvl] = vareval;
     xcmdsrc = CMD_MD;
     cmdstk[cmdlvl].src = CMD_MD;        /* Say we're in a macro */
     cmdstk[cmdlvl].lvl = maclvl;        /* and remember the macro level */
@@ -9810,6 +10021,10 @@ initoptlist() {
     sprintf(line,"INPBUFSIZ=%d",INPBUFSIZ); /* SAFE */
     makestr(&(optlist[noptlist++]),line);
 #endif /* INPBUFSIZE */
+#ifdef LINBUFSIZ
+    sprintf(line,"LINBUFSIZ=%d",LINBUFSIZ); /* SAFE */
+    makestr(&(optlist[noptlist++]),line);
+#endif /* LINBUFSIZE */
 #ifdef INBUFSIZE
     sprintf(line,"INBUFSIZE=%d",INBUFSIZE); /* SAFE */
     makestr(&(optlist[noptlist++]),line);
@@ -9863,7 +10078,7 @@ initoptlist() {
 #endif /* WHATAMI */
 #ifdef DYNAMIC
     makestr(&(optlist[noptlist++]),"DYNAMIC");
-#endif /* IFDEBUG */
+#endif /* DYNAMIC */
 #ifndef NOSPL
     sprintf(line,"CMDDEP=%d",CMDDEP);   /* SAFE */
     makestr(&(optlist[noptlist++]),line);
@@ -9969,6 +10184,101 @@ initoptlist() {
     makestr(&(optlist[noptlist++]),line);
 #endif /* MAC_MAX */
 
+#ifdef _LARGEFILE_SOURCE
+    makestr(&(optlist[noptlist++]),"_LARGEFILE_SOURCE");
+#endif /* _LARGEFILE_SOURCE */
+
+#ifdef _FILE_OFFSET_BITS
+    sprintf(line,"_FILE_OFFSET_BITS=%d",_FILE_OFFSET_BITS); /* SAFE */
+    makestr(&(optlist[noptlist++]),line);
+#endif /* _FILE_OFFSET_BITS */
+
+#ifdef __USE_FILE_OFFSET64
+    makestr(&(optlist[noptlist++]),"__USE_FILE_OFFSET64");
+#endif /* __USE_FILE_OFFSET64 */
+
+#ifdef __USE_LARGEFILE64
+    makestr(&(optlist[noptlist++]),"__USE_LARGEFILE64");
+#endif /* __USE_LARGEFILE64 */
+
+#ifdef COMMENT
+#ifdef CHAR_MAX
+    sprintf(line,"CHAR_MAX=%llx",CHAR_MAX); /* SAFE */
+    makestr(&(optlist[noptlist++]),line);
+#endif /* CHAR_MAX */
+#ifdef UCHAR_MAX
+    sprintf(line,"UCHAR_MAX=%llx",UCHAR_MAX); /* SAFE */
+    makestr(&(optlist[noptlist++]),line);
+#endif /* UCHAR_MAX */
+#ifdef SHRT_MAX
+    sprintf(line,"SHRT_MAX=%llx",SHRT_MAX); /* SAFE */
+    makestr(&(optlist[noptlist++]),line);
+#endif /* SHRT_MAX */
+#ifdef USHRT_MAX
+    sprintf(line,"USHRT_MAX=%llx",USHRT_MAX); /* SAFE */
+    makestr(&(optlist[noptlist++]),line);
+#endif /* USHRT_MAX */
+#ifdef INT_MAX
+    sprintf(line,"INT_MAX=%llx",INT_MAX); /* SAFE */
+    makestr(&(optlist[noptlist++]),line);
+#endif /* INT_MAX */
+#ifdef UINT_MAX
+    sprintf(line,"UINT_MAX=%llx",UINT_MAX); /* SAFE */
+    makestr(&(optlist[noptlist++]),line);
+#endif /* UINT_MAX */
+#ifdef MAX_LONG
+    sprintf(line,"MAX_LONG=%llx",MAX_LONG); /* SAFE */
+    makestr(&(optlist[noptlist++]),line);
+#endif /* MAX_LONG */
+#ifdef LONG_MAX
+    sprintf(line,"LONG_MAX=%llx",LONG_MAX); /* SAFE */
+    makestr(&(optlist[noptlist++]),line);
+#endif /* LONG_MAX */
+#ifdef ULONG_MAX
+    sprintf(line,"ULONG_MAX=%llx",ULONG_MAX); /* SAFE */
+    makestr(&(optlist[noptlist++]),line);
+#endif /* ULONG_MAX */
+#ifdef MAXINT
+    sprintf(line,"MAXINT=%llx",MAXINT); /* SAFE */
+    makestr(&(optlist[noptlist++]),line);
+#endif /* MAXINT */
+#ifdef MAXLONG
+    sprintf(line,"MAXLONG=%llx",MAXLONG); /* SAFE */
+    makestr(&(optlist[noptlist++]),line);
+#endif /* MAXLONG */
+#ifdef NT
+#ifdef LLONG_MAX
+    sprintf(line,"LLONG_MAX=%I64x",LLONG_MAX); /* SAFE */
+    makestr(&(optlist[noptlist++]),line);
+#endif /* LLONG_MAX */
+#ifdef ULLONG_MAX
+    sprintf(line,"ULLONG_MAX=%I64x",ULLONG_MAX); /* SAFE */
+    makestr(&(optlist[noptlist++]),line);
+#endif /* ULLONG_MAX */
+#ifdef MAXLONGLONG
+    sprintf(line,"MAXLONGLONG=%I64x",MAXLONGLONG);  /* SAFE */
+    makestr(&(optlist[noptlist++]),line);
+#endif /* MAXLONGLONG */
+#else
+#ifdef LLONG_MAX
+    sprintf(line,"LLONG_MAX=%llx",LLONG_MAX); /* SAFE */
+    makestr(&(optlist[noptlist++]),line);
+#endif /* LLONG_MAX */
+#ifdef ULLONG_MAX
+    sprintf(line,"ULLONG_MAX=%llx",ULLONG_MAX); /* SAFE */
+    makestr(&(optlist[noptlist++]),line);
+#endif /* ULLONG_MAX */
+#ifdef MAXLONGLONG
+    sprintf(line,"MAXLONGLONG=%llx",MAXLONGLONG);  /* SAFE */
+    makestr(&(optlist[noptlist++]),line);
+#endif /* MAXLONGLONG */
+#endif
+#ifdef _INTEGRAL_MAX_BITS
+    sprintf(line,"_INTEGRAL_MAX_BITS=%d",_INTEGRAL_MAX_BITS);  /* SAFE */
+    makestr(&(optlist[noptlist++]),line);
+#endif /* _INTEGRAL_MAX_BITS */
+#endif /* COMMENT */
+
 #ifdef MINPUTMAX
     sprintf(line,"MINPUTMAX=%d",MINPUTMAX); /* SAFE */
     makestr(&(optlist[noptlist++]),line);
@@ -10001,6 +10311,7 @@ initoptlist() {
 #ifdef UNIX
     makestr(&(optlist[noptlist++]),"UNIX");
 #endif /* UNIX */
+
 #ifdef VMS
     makestr(&(optlist[noptlist++]),"VMS");
 #ifdef __VMS_VER
@@ -10010,7 +10321,6 @@ initoptlist() {
 #ifdef VMSV70
     makestr(&(optlist[noptlist++]),"VMSV70");
 #endif /* VMSV70 */
-#endif /* VMS */
 #ifdef OLD_VMS
     makestr(&(optlist[noptlist++]),"OLD_VMS");
 #endif /* OLD_VMS */
@@ -10029,6 +10339,8 @@ initoptlist() {
 #ifdef NOVMSSHARE
     makestr(&(optlist[noptlist++]),"NOVMSSHARE");
 #endif /* NOVMSSHARE */
+#endif /* VMS */
+
 #ifdef datageneral
     makestr(&(optlist[noptlist++]),"datageneral");
 #endif /* datageneral */
@@ -10056,54 +10368,70 @@ initoptlist() {
 #ifdef AUX
     makestr(&(optlist[noptlist++]),"AUX");
 #endif /* AUX */
+
 #ifdef OS2
     makestr(&(optlist[noptlist++]),"OS2");
 #ifdef NT
     makestr(&(optlist[noptlist++]),"NT");
 #endif /* NT */
 #endif /* OS2 */
+
 #ifdef OSK
     makestr(&(optlist[noptlist++]),"OS9");
 #endif /* OSK */
+
 #ifdef MSDOS
     makestr(&(optlist[noptlist++]),"MSDOS");
 #endif /* MSDOS */
+
 #ifdef DIRENT
     makestr(&(optlist[noptlist++]),"DIRENT");
 #endif /* DIRENT */
+
 #ifdef SDIRENT
     makestr(&(optlist[noptlist++]),"SDIRENT");
 #endif /* SDIRENT */
+
 #ifdef NDIR
     makestr(&(optlist[noptlist++]),"NDIR");
 #endif /* NDIR */
+
 #ifdef XNDIR
     makestr(&(optlist[noptlist++]),"XNDIR");
 #endif /* XNDIR */
+
 #ifdef SAVEDUID
     makestr(&(optlist[noptlist++]),"SAVEDUID");
 #endif /* SAVEDUID */
+
 #ifdef RENAME
     makestr(&(optlist[noptlist++]),"RENAME");
 #endif /* RENAME */
+
 #ifdef CK_TMPDIR
     makestr(&(optlist[noptlist++]),"CK_TMPDIR");
 #endif /* CK_TMPDIR */
+
 #ifdef NOCCTRAP
     makestr(&(optlist[noptlist++]),"NOCCTRAP");
 #endif /* NOCCTRAP */
+
 #ifdef NOCOTFMC
     makestr(&(optlist[noptlist++]),"NOCOTFMC");
 #endif /* NOCOTFMC */
+
 #ifdef NOFRILLS
     makestr(&(optlist[noptlist++]),"NOFRILLS");
 #endif /* NOFRILLS */
+
 #ifdef PARSENSE
     makestr(&(optlist[noptlist++]),"PARSENSE");
 #endif /* PARSENSE */
+
 #ifdef TIMEH
     makestr(&(optlist[noptlist++]),"TIMEH");
 #endif /* TIMEH */
+
 #ifdef NOTIMEH
     makestr(&(optlist[noptlist++]),"TIMEH");
 #endif /* NOTIMEH */
@@ -10111,6 +10439,7 @@ initoptlist() {
 #ifdef SYSTIMEH
     makestr(&(optlist[noptlist++]),"SYSTIMEH");
 #endif /* SYSTIMEH */
+
 #ifdef NOSYSTIMEH
     makestr(&(optlist[noptlist++]),"SYSTIMEH");
 #endif /* NOSYSTIMEH */
@@ -10118,12 +10447,15 @@ initoptlist() {
 #ifdef SYSTIMEBH
     makestr(&(optlist[noptlist++]),"SYSTIMEBH");
 #endif /* SYSTIMEBH */
+
 #ifdef NOSYSTIMEBH
     makestr(&(optlist[noptlist++]),"SYSTIMEBH");
 #endif /* NOSYSTIMEBH */
+
 #ifdef UTIMEH
     makestr(&(optlist[noptlist++]),"UTIMEH");
 #endif /* UTIMEH */
+
 #ifdef SYSUTIMEH
     makestr(&(optlist[noptlist++]),"SYSUTIMEH");
 #endif /* SYSUTIMEH */
@@ -10131,12 +10463,15 @@ initoptlist() {
 #ifdef CK_NEED_SIG
     makestr(&(optlist[noptlist++]),"CK_NEED_SIG");
 #endif /* CK_NEED_SIG */
+
 #ifdef CK_TTYFD
     makestr(&(optlist[noptlist++]),"CK_TTYFD");
 #endif /* CK_TTYFD */
+
 #ifdef NETCONN
     makestr(&(optlist[noptlist++]),"NETCONN");
 #endif /* NETCONN */
+
 #ifdef TCPSOCKET
     makestr(&(optlist[noptlist++]),"TCPSOCKET");
 #ifdef NOTCPOPTS
@@ -10296,9 +10631,18 @@ initoptlist() {
 #ifdef USE_UU_LOCK
     makestr(&(optlist[noptlist++]),"USE_UU_LOCK");
 #endif /* USE_UU_LOCK */
+#ifdef HAVE_LOCKDEV
+    makestr(&(optlist[noptlist++]),"HAVE_LOCKDEV");
+#endif /* HAVE_LOCKDEV */
 #ifdef HAVE_BAUDBOY
     makestr(&(optlist[noptlist++]),"HAVE_BAUDBOY");
 #endif /* HAVE_BAUDBOY */
+#ifdef HAVE_OPENPTY
+    makestr(&(optlist[noptlist++]),"HAVE_OPENPTY");
+#endif /* HAVE_OPENPTY */
+#ifdef TTPTYCMD
+    makestr(&(optlist[noptlist++]),"TTPTYCMD");
+#endif /* TTPTYCMD */
 #ifdef NOUUCP
     makestr(&(optlist[noptlist++]),"NOUUCP");
 #endif /* NOUUCP */
@@ -10445,6 +10789,18 @@ initoptlist() {
 #ifdef HPUX
     makestr(&(optlist[noptlist++]),"HPUX");
 #endif /* HPUX */
+#ifdef HPUX9
+    makestr(&(optlist[noptlist++]),"HPUX9");
+#endif /* HPUX9 */
+#ifdef HPUX10
+    makestr(&(optlist[noptlist++]),"HPUX10");
+#endif /* HPUX10 */
+#ifdef HPUX1000
+    makestr(&(optlist[noptlist++]),"HPUX1000");
+#endif /* HPUX1000 */
+#ifdef HPUX1100
+    makestr(&(optlist[noptlist++]),"HPUX1100");
+#endif /* HPUX1100 */
 #ifdef HPUXPRE65
     makestr(&(optlist[noptlist++]),"HPUXPRE65");
 #endif /* HPUXPRE65 */
@@ -10508,6 +10864,15 @@ initoptlist() {
 #ifdef MINIX
     makestr(&(optlist[noptlist++]),"MINIX");
 #endif /* MINIX */
+#ifdef MINIX2
+    makestr(&(optlist[noptlist++]),"MINIX2");
+#endif /* MINIX2 */
+#ifdef MINIX3
+    makestr(&(optlist[noptlist++]),"MINIX3");
+#endif /* MINIX3 */
+#ifdef MINIX315
+    makestr(&(optlist[noptlist++]),"MINIX315");
+#endif /* MINIX315 */
 #ifdef C70
     makestr(&(optlist[noptlist++]),"C70");
 #endif /* C70 */
@@ -10618,6 +10983,12 @@ initoptlist() {
 #ifdef SOLARIS8
     makestr(&(optlist[noptlist++]),"SOLARIS8");
 #endif /* SOLARIS8 */
+#ifdef SOLARIS9
+    makestr(&(optlist[noptlist++]),"SOLARIS9");
+#endif /* SOLARIS9 */
+#ifdef SOLARIS10
+    makestr(&(optlist[noptlist++]),"SOLARIS10");
+#endif /* SOLARIS10 */
 #endif /* SOLARIS */
 
 #ifdef SUNOS4
@@ -10718,8 +11089,14 @@ initoptlist() {
     makestr(&(optlist[noptlist++]),"MACOSX10");
 #endif
 #ifdef MACOSX103
+    makestr(&(optlist[noptlist++]),"MACOSX10e");
+#endif
+#ifdef COMMENT
+/* not used */
+#ifdef MACOSX103
     makestr(&(optlist[noptlist++]),"MACOSX103");
 #endif
+#endif /* COMMENT */
 
 #ifdef sgi
     makestr(&(optlist[noptlist++]),"sgi");
@@ -10802,12 +11179,63 @@ initoptlist() {
 #ifdef i386
     makestr(&(optlist[noptlist++]),"i386");
 #endif
+#ifdef __i386
+    makestr(&(optlist[noptlist++]),"__i386");
+#endif
+#ifdef __x86
+    makestr(&(optlist[noptlist++]),"__x86");
+#endif
+#ifdef __amd64
+    makestr(&(optlist[noptlist++]),"__amd64");
+#endif
+#ifdef _ILP32
+    makestr(&(optlist[noptlist++]),"_ILP32");
+#endif
+#ifdef _ILP64
+    makestr(&(optlist[noptlist++]),"_ILP64");
+#endif
+#ifdef _LP32
+    makestr(&(optlist[noptlist++]),"_LP32");
+#endif
+#ifdef _LP64
+    makestr(&(optlist[noptlist++]),"_LP64");
+#endif
+#ifdef __LP32__
+    makestr(&(optlist[noptlist++]),"__LP32__");
+#endif
+#ifdef __LP64__
+    makestr(&(optlist[noptlist++]),"__LP64__");
+#endif
+#ifdef _XGP4_2
+    makestr(&(optlist[noptlist++]),"_XGP4_2");
+#endif
+#ifdef __ppc__
+    makestr(&(optlist[noptlist++]),"__ppc__");
+#endif
+#ifdef __ppc32__
+    makestr(&(optlist[noptlist++]),"__ppc32__");
+#endif
+#ifdef __ppc64__
+    makestr(&(optlist[noptlist++]),"__ppc64__");
+#endif
+#ifdef CK_64BIT
+    makestr(&(optlist[noptlist++]),"CK_64BIT");
+#endif
 #ifdef i286
     makestr(&(optlist[noptlist++]),"i286");
 #endif
 #ifdef M_I286
     makestr(&(optlist[noptlist++]),"M_I286");
 #endif
+#ifdef __sparc
+    makestr(&(optlist[noptlist++]),"__sparc");
+#endif
+#ifdef __sparcv8
+    makestr(&(optlist[noptlist++]),"__sparcv8");
+#endif
+#ifdef __sparcv9
+    makestr(&(optlist[noptlist++]),"__sparcv9");
+#endif
 #ifdef mc68000
     makestr(&(optlist[noptlist++]),"mc68000");
 #endif
@@ -10949,6 +11377,9 @@ initoptlist() {
 #ifdef __STDC__
     makestr(&(optlist[noptlist++]),"__STDC__");
 #endif
+#ifdef cplusplus
+    makestr(&(optlist[noptlist++]),"cplusplus");
+#endif
 #ifdef __DECC
     makestr(&(optlist[noptlist++]),"__DECC");
 #ifdef __DECC_VER
@@ -11178,6 +11609,7 @@ initoptlist() {
     makestr(&(optlist[noptlist++]),"NOLOEARN");
 #endif /* NOLOEARN */
 #endif /* CKLEARN */
+
 #ifdef NOFLOAT
     makestr(&(optlist[noptlist++]),"NOFLOAT");
 #else
@@ -11211,8 +11643,12 @@ initoptlist() {
 #endif /* CK_TAPI */
 #ifdef CK_SSL
     makestr(&(optlist[noptlist++]),"CK_SSL");
+#ifdef OPENSSL_VERSION_TEXT
+    ckmakmsg(line,LINBUFSIZ,
+            "OPENSSL_VERSION_TEXT=","\"",OPENSSL_VERSION_TEXT,"\"");
+    makestr(&(optlist[noptlist++]),line);
+#endif /* OPENSSL_VERSION_TEXT */
 #endif /* CK_SSL */
-
     debug(F101,"initoptlist noptlist","",noptlist);
     sh_sort(optlist,NULL,noptlist,0,0,0);
 }
@@ -11229,6 +11665,7 @@ shofea() {
     printf("%s\n",versio);
     if (inserver)
       return(1);
+
     debug(F101,"shofea NOPTLIST","",NOPTLIST);
     initoptlist();
     debug(F101,"shofea noptlist","",noptlist);
@@ -11265,6 +11702,12 @@ shofea() {
     printf("Major optional features included:\n");
     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
 
+    if (sizeof(CK_OFF_T) == 8) {
+       printf(" Large files and large integers (64 bits)\n");
+        if (++lines > cmd_rows - 3) {
+           if (!askmore()) return(1); else lines = 0;
+       }
+    }
 #ifdef NETCONN
     printf(" Network support (type SHOW NET for further info)\n");
     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
@@ -11320,6 +11763,7 @@ shofea() {
     printf(" Telnet CAST Encryption\n");
     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
 #endif /* CK_CAST */
+
 #ifdef CK_KERBEROS
 #ifdef KRB5
 #ifdef ALLOW_KRB_3DES_ENCRYPT
@@ -11328,6 +11772,7 @@ shofea() {
 #endif /* ALLOW_KRB_3DES_ENCRYPT */
 #endif /* KRB5 */
 #endif /* CK_KERBEROS */
+
 #endif /* CK_ENCRYPTION */
 #endif /* CK_AUTHENTICATION */
 #ifdef CK_FORWARD_X
@@ -11468,6 +11913,13 @@ shofea() {
     printf("Major optional features not included:\n");
     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
 
+    if (sizeof(CK_OFF_T) <= 4) {
+       printf(" No large files or large integers\n");
+        if (++lines > cmd_rows - 3) {
+           if (!askmore()) return(1); else lines = 0;
+       }
+    }
+
 #ifdef NOXFER
     printf(" No file-transfer protocols\n");
     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
@@ -11608,6 +12060,8 @@ shofea() {
     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
     flag = 1;
 #endif /* CK_CAST */
+
+#ifdef COMMENT
 #ifdef CK_KERBEROS
 #ifdef KRB5
 #ifndef ALLOW_KRB_3DES_ENCRYPT
@@ -11616,6 +12070,8 @@ shofea() {
 #endif /* ALLOW_KRB_3DES_ENCRYPT */
 #endif /* KRB5 */
 #endif /* CK_KERBEROS */
+#endif /* COMMENT */
+
 #endif /* OS2 */
 #endif /* CK_ENCRYPTION */
 #endif /* CK_AUTHENTICATION */
@@ -11878,23 +12334,41 @@ shofea() {
              );
     if (!prtopt(&lines,line)) return(0);
     if (!prtopt(&lines,"")) return(0);  /* Start a new section */
-    sprintf(line,"sizeofs: int=%ld",sizeof(int)); /* SAFE */
+    sprintf(line,"sizeofs: int=%d",sizeof(int)); /* SAFE */
+    if (!prtopt(&lines,line)) return(0);
+    sprintf(line,"long=%d",sizeof(long)); /* SAFE */
     if (!prtopt(&lines,line)) return(0);
-    sprintf(line,"long=%ld",sizeof(long)); /* SAFE */
+
+#ifdef COMMENT
+#ifdef CK_LONGLONG
+    sprintf(line,"long long=%d",sizeof(long long)); /* SAFE */
     if (!prtopt(&lines,line)) return(0);
-    sprintf(line,"short=%ld",sizeof(short)); /* SAFE */
+#endif /* CK_LONGLONG */
+#endif /* COMMENT */
+
+#ifndef OS2
+    /* Windows doesn't have off_t */
+    sprintf(line,"off_t=%d",sizeof(off_t)); /* SAFE */
     if (!prtopt(&lines,line)) return(0);
-    sprintf(line,"char=%ld",sizeof(char)); /* SAFE */
+#endif /* OS2 */
+
+    sprintf(line,"CK_OFF_T=%d",sizeof(CK_OFF_T)); /* SAFE */
     if (!prtopt(&lines,line)) return(0);
-    sprintf(line,"char*=%ld",sizeof(char *)); /* SAFE */
+
+#ifdef BIGBUFOK
+    sprintf(line,"size_t=%d",sizeof(size_t)); /* SAFE */
     if (!prtopt(&lines,line)) return(0);
-#ifdef LONG_MAX
-    sprintf(line,"LONG_MAX=%d",LONG_MAX); /* SAFE */
-#endif /* LONG_MAX */
-#ifdef CKFLOAT
-    sprintf(line,"float=%ld",sizeof(float)); /* SAFE */
+#endif /* BIGBUFOK */
+
+    sprintf(line,"short=%d",sizeof(short)); /* SAFE */
     if (!prtopt(&lines,line)) return(0);
-    sprintf(line,"double=%ld",sizeof(double)); /* SAFE */
+    sprintf(line,"char=%d",sizeof(char)); /* SAFE */
+    if (!prtopt(&lines,line)) return(0);
+    sprintf(line,"char*=%d",sizeof(char *)); /* SAFE */
+    if (!prtopt(&lines,line)) return(0);
+    sprintf(line,"float=%d",sizeof(float)); /* SAFE */
+    if (!prtopt(&lines,line)) return(0);
+    sprintf(line,"double=%d",sizeof(double)); /* SAFE */
     if (!prtopt(&lines,line)) return(0);
 #ifdef FNFLOAT
     if (!prtopt(&lines,"")) return(0);  /* Start a new section */
@@ -11904,7 +12378,6 @@ shofea() {
     sprintf(line,"rounding=%d",fp_rounding); /* SAFE */
     if (!prtopt(&lines,line)) return(0);
 #endif /* FNFLOAT */
-#endif /* CKFLOAT */
 
     prtopt(&lines,"");
     return(0);
index 5dcd828..a4990c6 100644 (file)
--- a/ckuus6.c
+++ b/ckuus6.c
@@ -1,8 +1,6 @@
 #include "ckcsym.h"
 #ifndef NOICP
 
-/*  C K U U S 6 --  "User Interface" for Unix Kermit (Part 6)  */
-
 /*
   Authors:
     Frank da Cruz <fdc@columbia.edu>,
@@ -10,7 +8,7 @@
     Jeffrey E Altman <jaltman@secure-endpoints.com>
       Secure Endpoints Inc., New York City
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2011,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
 #include "ckcnet.h"                     /* Network symbols */
 #include <signal.h>
 
+#ifndef NOSTAT
+#ifdef VMS
+/* 2010-03-09 SMS.  VAX C needs help to find "sys".  It's easier not to try. */
+#include <stat.h>
+#else /* def VMS */
+#include <sys/stat.h>
+#endif /* def VMS [else] */
+#endif /* NOSTAT */
+
 #ifdef VMS
 #ifndef TCPSOCKET
 #include <errno.h>
@@ -49,7 +56,7 @@ extern int local, xitsta, binary, parity, escape, flow, cmd_rows, turn,
   zincnt, quiet, repars, techo, network, nzxopts, what, filepeek, recursive;
 
 extern int xaskmore, tt_rows, tt_cols, cmd_cols, g_matchdot, diractive,
-  xcmdsrc, nscanfile, reliable, nolinks;
+  xcmdsrc, nscanfile, reliable, nolinks, cmflgs;
 
 #ifdef VMSORUNIX
 extern int zgfs_dir, zgfs_link;
@@ -133,6 +140,7 @@ extern int nopush;
 
 #ifndef NOSPL
 int askflag = 0;                        /* ASK-class command active */
+int echostars = 0;                     /* ASKQ should echo asterisks */
 extern char **a_ptr[];
 extern int a_dim[];
 extern char **m_xarg[];
@@ -156,6 +164,8 @@ int getcmd = 0;                         /* GET-class command was given */
 
 extern int zchkod, zchkid;
 
+/*  C K U U S 6 --  "User Interface" for Unix Kermit (Part 6)  */
+
 struct keytab deltab[] = {              /* DELETE Command Options */
     { "/all",           DEL_ALL,  CM_INV },
     { "/after",         DEL_AFT,  CM_ARG },
@@ -206,6 +216,59 @@ struct keytab qvswtab[] = {
 };
 int nqvswtab = sizeof(qvswtab)/sizeof(struct keytab);
 
+static struct keytab renamsw[] = {
+    { "/collision",   REN_OVW,  CM_ARG },
+#ifndef NOUNICODE
+    { "/convert",     REN_XLA,  CM_ARG },
+#endif /* NOUNICODE */
+    { "/fixspaces",   REN_SPA,  CM_ARG },
+    { "/l",           DEL_LIS,  CM_INV|CM_ABR },
+    { "/list",        DEL_LIS,  0      },
+    { "/log",         DEL_LIS,  CM_INV },
+    { "/lower",       REN_LOW,  CM_ARG },
+    { "/nol",         DEL_NOL,  CM_INV|CM_ABR },
+    { "/nolist",      DEL_NOL,  0      },
+    { "/nolog",       DEL_NOL,  CM_INV },
+    { "/quiet",       DEL_QUI,  CM_INV },
+    { "/replace",     REN_RPL,  CM_ARG },
+    { "/simulate",    DEL_SIM,  0      },
+    { "/upper",       REN_UPP,  CM_ARG },
+    { "/verbose",     DEL_VRB,  CM_INV }
+};
+static int nrenamsw = sizeof(renamsw)/sizeof(struct keytab);
+
+static struct keytab renamset[] = {
+    { "collision",    REN_OVW,  0 },
+    { "list",         DEL_LIS,  0 }
+};
+static int nrenamset = sizeof(renamset)/sizeof(struct keytab);
+
+/* Args for RENAME /LOWER: and /UPPER: */
+
+static struct keytab r_upper[] = {
+    { "all",   1, 0 },
+    { "lower", 0, 0 }
+};
+
+static struct keytab r_lower[] = {
+    { "all",   1, 0 },
+    { "upper", 0, 0 }
+};
+
+/* Args for RENAME /COLLISION... */
+
+#define RENX_FAIL 0
+#define RENX_OVWR 1
+#define RENX_SKIP 2
+
+static struct keytab r_collision[] = {
+    { "fail",      RENX_FAIL, 0 },
+    { "overwrite", RENX_OVWR, 0 },
+    { "proceed",   RENX_SKIP, CM_INV },
+    { "skip",      RENX_SKIP, 0 }
+};
+static int nr_collision = sizeof(r_collision)/sizeof(struct keytab);
+
 struct keytab copytab[] = {
     { "/append",      998,      0 },
 #ifndef NOSPL
@@ -217,6 +280,10 @@ struct keytab copytab[] = {
     { "/nol",         DEL_NOL,  CM_INV|CM_ABR },
     { "/nolist",      DEL_NOL,  0 },
     { "/nolog",       DEL_NOL,  CM_INV },
+    { "/overwrite",   994,      CM_ARG },
+#ifndef NOXFER
+    { "/preserve",    995,      0 },
+#endif /* NOXFER */
     { "/quiet",       DEL_QUI,  CM_INV },
     { "/swap-bytes",  999,      0 },
 #ifndef NOSPL
@@ -226,6 +293,19 @@ struct keytab copytab[] = {
 };
 int ncopytab = sizeof(copytab)/sizeof(struct keytab);
 
+#define OVW_ALWAYS 0
+#define OVW_NEVER  1
+#define OVW_OLDER  2
+#define OVW_NEWER  3
+
+static struct keytab ovwtab[] = {
+    { "always", OVW_ALWAYS, 0 },
+    { "never",  OVW_NEVER, 0 },
+    { "newer",  OVW_NEWER, 0 },
+    { "older",  OVW_OLDER, 0 }
+};
+static int novwtab = 4;
+
 #ifndef NOXFER
 static struct keytab gettab[] = {       /* GET options */
     { "/as-name",         SND_ASN, CM_ARG },
@@ -431,6 +511,8 @@ int nopn = (sizeof(opntab) / sizeof(struct keytab));
 #define  XXIFVE 54      /* IF VERSION */
 #define  XXIFDC 55      /* IF DECLARED */
 #define  XXIFGU 56      /* IF GUI */
+#define  XXIFLN 57     /* IF LINK */
+#define  XXIFDB 58     /* IF DEBUG */
 
 struct keytab iftab[] = {               /* IF commands */
     { "!",          XXIFNO, 0 },
@@ -454,6 +536,7 @@ struct keytab iftab[] = {               /* IF commands */
     { "command",    XXIFCM, 0 },
     { "count",      XXIFCO, 0 },
     { "dcl",        XXIFDC, CM_INV },
+    { "debug",      XXIFDB, 0 },
     { "declared",   XXIFDC, 0 },
     { "defined",    XXIFDE, 0 },
 #ifdef CK_TMPDIR
@@ -492,6 +575,9 @@ struct keytab iftab[] = {               /* IF commands */
     { "kerbang",    XXIFKG, CM_INV },
 #endif /* UNIX */
     { "lgt",        XXIFLG, 0 },
+#ifdef UNIX
+    { "link",       XXIFLN, 0 },
+#endif /* UNIX */
     { "llt",        XXIFLL, 0 },
     { "local",      XXIFLO, 0 },
     { "match",      XXIFMA, 0 },
@@ -546,6 +632,10 @@ int niot = (sizeof(iotab) / sizeof(struct keytab));
 
 /* Variables and prototypes */
 
+_PROTOTYP(static int doymdir,(int));
+_PROTOTYP(static int renameone,(char *,char *,
+                               int,int,int,int,int,int,int,int,int,int,int));
+
 #ifdef NETCONN
 extern int nnetdir;                     /* How many network directories */
 #endif /* NETCONN */
@@ -647,10 +737,11 @@ int ifc,                                /* IF case */
     ifargs = 0;                         /* Count of IF condition words */
 char ifcond[IFCONDLEN];                 /* IF condition text */
 char *ifcp;                             /* Pointer to IF condition text */
+extern int vareval;
 #ifdef DCMDBUF
 extern int
  *ifcmd,  *count,  *iftest, *intime,
*inpcas, *takerr, *merror, *xquiet;
   *inpcas, *takerr, *merror, *xquiet, *xvarev;
 #else
 extern int ifcmd[];                     /* Last command was IF */
 extern int iftest[];                    /* Last IF was true */
@@ -660,6 +751,7 @@ extern int inpcas[];
 extern int takerr[];
 extern int merror[];
 extern int xquiet[];
+extern int xvarev[];
 #endif /* DCMDBUF */
 #else
 extern int takerr[];
@@ -731,6 +823,7 @@ int asktimedout = 0;
 #define ASK_GUI 3
 #define ASK_QUI 4
 #define ASK_DEF 5
+#define ASK_ECH 6
 
 static struct keytab asktab[] = {
     {  "/default", ASK_DEF, CM_ARG },
@@ -754,12 +847,37 @@ static struct keytab asktab[] = {
 };
 static int nasktab = sizeof(asktab)/sizeof(struct keytab)-1;
 
+static struct keytab askqtab[] = {
+    { "/default",  ASK_DEF, CM_ARG },
+    { "/echo",     ASK_ECH, CM_ARG },
+    { "/gui",      ASK_GUI,      
+#ifdef KUI
+           0
+#else /* KUI */
+           CM_INV
+#endif /* KUI */
+    },
+    { "/noecho",   ASK_QUI, CM_INV },
+    { "/popup",    ASK_PUP,   
+#ifdef OS2
+           0
+#else /* OS2 */
+           CM_INV
+#endif /* OS2 */
+    },
+    { "/quiet",    ASK_QUI, 0 },
+    { "/timeout",  ASK_TMO, CM_ARG },
+    { "", 0, 0 }
+};
+static int naskqtab = sizeof(askqtab)/sizeof(struct keytab)-1;
+
 int
 doask(cx) int cx; {
-    extern int cmflgs, asktimer, timelimit;
+    extern int asktimer, timelimit;
 #ifdef CK_RECALL
     extern int on_recall;
 #endif /* CK_RECALL */
+    int echochar = 0;
     int popupflg = 0;
     int guiflg = 0;
     int nomsg = 0;
@@ -784,6 +902,7 @@ doask(cx) int cx; {
 #endif /* CK_APC */
 
     mytimer = asktimer;                 /* Inherit global ASK timer */
+    echostars = 0;                     /* For ASKQ */
 
     if (cx == XXASK || cx == XXASKQ) {
         struct FDB sw, fl;
@@ -796,10 +915,10 @@ doask(cx) int cx; {
                "Variable name or switch",
                "",                      /* default */
                "",                      /* addtl string data */
-               nasktab,                 /* addtl numeric data 1: tbl size */
+              ((cx == XXASK) ? nasktab : naskqtab), /* Table size */
                4,                       /* addtl numeric data 2: 4 = cmswi */
                xxstring,                /* Processing function */
-               asktab,                  /* Keyword table */
+              ((cx == XXASK) ? asktab : askqtab), /* Keyword table */
                &fl                      /* Pointer to next FDB */
                );
         cmfdbi(&fl,                     /* Anything that doesn't match */
@@ -831,6 +950,8 @@ doask(cx) int cx; {
             switch (cmresult.nresult) {
              case ASK_QUI:
                nomsg = 1;
+               if (cx == XXASKQ)
+                 echostars = 0;
                break;
               case ASK_PUP:
                 popupflg = 1;
@@ -846,6 +967,12 @@ doask(cx) int cx; {
                   mytimer = x;
                   break;
               }
+              case ASK_ECH: {
+                  if ((y = cmfld("Character to echo","*",&s,xxstring)) < 0)
+                    return(y);
+                 echochar = *s;
+                  break;
+              }
               case ASK_DEF: {
                   if ((y = cmfld("Text to supply if reply is empty",
                                 "",&s,xxstring)) < 0)
@@ -866,7 +993,7 @@ doask(cx) int cx; {
         y = 0;
         if (*vnp == '%' || *vnp == '&') {
             if ((y = parsevar(vnp,&x,&z)) < 0)
-              return(y);
+             return(y);
         }
     } else if (cx != XXGOK && cx != XXRDBL) { /* Get variable name */
         if ((y = cmfld("Variable name","",&s,NULL)) < 0) {
@@ -1056,11 +1183,15 @@ doask(cx) int cx; {
     concb((char)escape);                /* Enter CBREAK mode */
     cmsavp(psave,PROMPTL);              /* Save old prompt */
     cmsetp(brstrip(p));                 /* Make new prompt */
+
 reprompt:
     if (cx == XXASKQ) {                 /* For ASKQ, */
         cmini(0);                       /* no-echo mode. */
+       if (echochar)
+         echostars = echochar;
     } else {                            /* For others, regular echoing. */
         cmini(ckxech);
+       echostars = 0;
     }
     askflag = 1;
     x = -1;                             /* This means to reparse. */
@@ -1162,8 +1293,9 @@ reparse:
         return(success = ((y < 0 ? 0 : 1) && (asktimedout == 0)));
     } else {                            /* ASK or ASKQ */
 #ifdef CK_RECALL
-        on_recall = 0;
+        on_recall = 0;                 /* Don't put response in recall buf */
 #endif /* CK_RECALL */
+       askflag = 1;                    /* ASK[Q] always goes to terminal */
         y = cmdgquo();                  /* Get current quoting */
         cmdsquo(0);                     /* Turn off quoting */
         while (x == -1) {               /* Prompt till they answer */
@@ -1225,6 +1357,7 @@ int
 doincr(cx) int cx; {                    /* INCREMENT, DECREMENT */
     char vnambuf[VNAML+1];              /* Buffer for variable names */
     int eval = 0;
+    CK_OFF_T x;
     eval = (cx == XX_DECR || cx == XX_INCR);
 
     if ((y = cmfld("Variable name","",&s, eval ? xxstring : NULL)) < 0) {
@@ -1234,7 +1367,7 @@ doincr(cx) int cx; {                    /* INCREMENT, DECREMENT */
         } else return(y);
     }
     ckstrncpy(vnambuf,s,VNAML);
-    if ((y = cmnum("by amount","1",10,&x,xxstring)) < 0)
+    if ((y = cmnumw("by amount","1",10,&x,xxstring)) < 0)
       return(y);
     if ((y = cmcfm()) < 0)
       return(y);
@@ -1691,12 +1824,16 @@ char pdsfx[64] = { NUL, NUL };
 static char *
 xdial(s) char *s; {                     /* Run dial string thru macro */
     int x, m;
+    char * s2;
+    s2 = NULL;
+    makestr(&s2,s);                    /* Copy the argument */
     if (!dialmac)                       /* Dial macro name given? */
       return(NULL);
     if ((x = mxlook(mactab,dialmac,nmac)) < 0) /* Is the macro defined? */
       return(NULL);
     m = maclvl;
-    x = dodo(x,s,0);                    /* Set up the macro */
+    x = dodo(x,s2,0);                  /* Set up the macro */
+    if (s2) free(s2);
     if (x > 0) {
         while (maclvl > m)              /* Execute the parser */
           parser(1);
@@ -2600,8 +2737,10 @@ dodial(cx) int cx; {                    /* DIAL or REDIAL */
     int j = 0, t = 0, n = 0;
     int xretries, xlcc;
 
+#ifdef COMMENT
     debug(F101,"dodial cx","",cx);
     debug(F111,"dodial diallcc",diallcc,diallcc);
+#endif /* COMMENT */
 
     xretries = dialrtr;                 /* If retries not set, */
     if (diallcc) {                      /* choose default based on */
@@ -3025,7 +3164,7 @@ Disabling flow control temporarily %s...\n",
 #ifndef NOSPL
             sav = s;
             p = xdial(s);               /* Apply DIAL macro now */
-            if (p) s = p;
+            if (p) if (*p) s = p;
 #endif /* NOSPL */
 
            /* Dial confirmation */
@@ -3624,7 +3763,7 @@ dotype(file, paging, first, head, pat, width, prefix, incs, outcs, outfile, z)
     char * file, * pat, * prefix; int paging, first, head, width, incs, outcs;
     char * outfile; int z;
 /* dotype */ {
-    extern long ffc;
+    extern CK_OFF_T ffc;
     char buf[TYPBUFL+2];
     char * s = NULL;
     int rc = 1, lines = 0, ucs2 = 0;
@@ -3771,7 +3910,7 @@ dotype(file, paging, first, head, pat, width, prefix, incs, outcs, outfile, z)
 #ifndef MAC
     errno = 0;
     oldsig = signal(SIGINT, tytrap);    /* Save current interrupt trap. */
-    debug(F111,"type SIGINT trap set",ckitoa(errno),oldsig);
+    /* debug(F111,"type SIGINT trap set",ckitoa(errno),oldsig); */
 #endif /* MAC */
 #endif /* AMIGA */
 
@@ -3807,7 +3946,7 @@ dotype(file, paging, first, head, pat, width, prefix, incs, outcs, outfile, z)
 
 #ifdef UNICODE
     if (outcs > -1 && (incs != outcs || incs == FC_UCS2)) { /* Translating? */
-        ffc = 0L;
+        ffc = (CK_OFF_T)0;
         initxlate(incs,outcs);          /* Set up translation functions */
     } else
 #endif /* UNICODE */
@@ -4084,10 +4223,12 @@ dotype(file, paging, first, head, pat, width, prefix, incs, outcs, outfile, z)
 #define GREP_RECU 11                    /* /RECURSIVE */
 #define GREP_TYPE 12                    /* /TYPE: */
 #define GREP_OUTP 13                    /* /OUTPUTFILE: */
+#define GREP_EXCP 14                   /* /EXCEPT: */
 
 static struct keytab greptab[] = {
     { "/count",        GREP_COUN, CM_ARG },
     { "/dotfiles",     GREP_DOTF, 0 },
+    { "/except",       GREP_EXCP, CM_ARG },
     { "/linenumbers",  GREP_NUMS, 0 },
     { "/nameonly",     GREP_NAME, 0 },
     { "/nobackupfiles",GREP_NOBK, 0 },
@@ -4107,6 +4248,8 @@ static struct keytab greptab[] = {
 };
 static int ngreptab =  sizeof(greptab)/sizeof(struct keytab)-1;
 
+static char * grep_except = NULL;
+
 int
 dogrep() {
     int match, x, y, fc, getval, mc = 0, count = 0, bigcount = 0;
@@ -4123,12 +4266,14 @@ dogrep() {
       gr_noli = 0,
       gr_noma = 0,
       gr_nums = 0,
+      gr_excp = 0,
       gr_page = xaskmore;
 
     struct FDB sw, fl;
 
     g_matchdot = matchdot;              /* Save global matchdot setting */
     outfile[0] = NUL;
+    makestr(&grep_except,NULL);
 
     if (ofp != stdout) {                /* In case of previous interruption */
         if (ofp) fclose(ofp);
@@ -4218,6 +4363,17 @@ dogrep() {
               return(x);
             ckstrncpy(outfile,s,CKMAXPATH);
             break;
+         case GREP_EXCP:               /* Exception pattern */
+           if (getval) {
+               if ((x = cmfld("Exception pattern",
+                              "",
+                              &s,
+                              xxstring
+                              )) < 0)
+                 return(x);
+               gr_excp++;
+               makestr(&grep_except,s);
+           }
         }
     }
     if (outfile[0]) {
@@ -4334,6 +4490,10 @@ dogrep() {
             while (len > 0 && (line[len-1] == '\n' || line[len-1] == '\r'))
               line[--len] = NUL;        /* Chop off terminators */
             match = ckmatch(p,line,gr_case,1+4); /* Match against pattern */
+           if (match && gr_excp) {
+               if (ckmatch(grep_except,line,gr_case,1+4))
+                   match = 0;
+           }
             if (gr_noma)                /* Invert match sense if requested */
               match = !match;
             if (match) {                /* Have a matching line */
@@ -4424,6 +4584,7 @@ static struct keytab dirswtab[] = {     /* DIRECTORY command switches */
     { "/backup",      DIR_BUP, 0 },
     { "/before",      DIR_BEF, CM_ARG },
     { "/brief",       DIR_BRF, 0 },
+    { "/count",       DIR_COU, CM_ARG },
     { "/descending",  DIR_DSC, CM_INV },
     { "/directories", DIR_DIR, 0 },
     { "/dotfiles",    DIR_DOT, 0 },
@@ -4443,6 +4604,9 @@ static struct keytab dirswtab[] = {     /* DIRECTORY command switches */
     { "/nofollowlinks",DIR_NLK, 0 },
 #endif /* CKSYMLINK */
     { "/noheading",   DIR_NOH, 0 },
+#ifdef CKSYMLINK
+    { "/nolinks",     DIR_NOL, 0 },
+#endif /* CKSYMLINK */
     { "/nomessage",   DIR_NOM, 0 },
 #ifdef CK_TTGWSIZ
     { "/nopage",      DIR_NOP, 0 },
@@ -4483,6 +4647,7 @@ static struct keytab dirswtab[] = {     /* DIRECTORY command switches */
     { "/smaller-than",DIR_SMA, CM_ARG },
     { "/sort",        DIR_SRT, CM_ARG },
     { "/summary",     DIR_SUM, 0 },
+    { "/top",         DIR_TOP, CM_ARG },
     { "/type",        DIR_BIN, CM_ARG },
     { "/xfermode",    DIR_TYP, 0 },
     { "/verbose",     DIR_VRB, 0 },
@@ -4689,7 +4854,7 @@ setdiropts() {                          /* Set DIRECTORY option defaults */
 }
 
 int
-domydir() {                             /* Internal DIRECTORY command */
+domydir(cx) int cx; {                  /* Internal DIRECTORY command */
     extern char *months[];
 #ifdef VMS
     _PROTOTYP( char * zrelname, (char *,char *) );
@@ -4698,16 +4863,22 @@ domydir() {                             /* Internal DIRECTORY command */
 
     char name[CKMAXPATH+1], outfile[CKMAXPATH+1], *p = NULL, c = NUL;
     char linebuf[CKMAXPATH+256];
-    char * mstr = NULL, * dstr = NULL, * s2 = NULL;
-    long len = 0, ndirs = 0, nfiles = 0, nbytes = 0, nmatches = 0;
+    char * mstr = NULL, * dstr = NULL, * s2 = NULL, * cv = NULL;
+    CK_OFF_T len = (CK_OFF_T)0, nbytes = (CK_OFF_T)0;
+    CK_OFF_T minsize = (CK_OFF_T)-1, maxsize = (CK_OFF_T)-1;
+    long ndirs = 0, nfiles = 0, nmatches = 0;
     int verbose = 0, wild = 0, page = 0, n = 0, engdate = 0, summary = 0;
     int heading = 0, xsort = 0, reverse = 0, sortby = 0, msg = 0;
     int k, i = 0, x = 0, nx = 0, skey = 0, dlen = 0, itsadir = 0;
     int show = 3, xfermod = 0, backup = 1, rc = 0, getval = 0;
+    int touch = 0;
     int fs = 0;
     int multiple = 0;
     int cmifn1 = 1, cmifn2 = 0;
-    long minsize = -1L, maxsize = -1L;
+    int dir_top = 0, dir_cou = 0;
+    int dontshowlinks = 0;
+    int dontfollowlinks = 0;
+    int arrayindex = -1;
     struct FDB sw, fi, fl;
     char dbuf[32], xbuf[32];
 
@@ -4723,8 +4894,12 @@ domydir() {                             /* Internal DIRECTORY command */
       * dir_exc = NULL;
     char * xlist[16];
 
+    debug(F101,"domydir cx","",cx);
+
     g_matchdot = matchdot;              /* Save global matchdot setting */
+#ifdef COMMENT
     nolinks = 2;                        /* (it should already be 2) */
+#endif /* COMMENT */
     outfile[0] = NUL;                   /* No output file yet */
 
     if (ofp != stdout) {                /* In case of previous interruption */
@@ -4733,6 +4908,7 @@ domydir() {                             /* Internal DIRECTORY command */
     }
     for (i = 0; i < 16; i++) xlist[i] = NULL;
 
+    dir_top = 0;
     name[0] = NUL;
     freedirlist();                      /* In case not freed last time */
     page      = dir_page > -1 ? dir_page : xaskmore; /* Set option defaults */
@@ -4753,6 +4929,21 @@ domydir() {                             /* Internal DIRECTORY command */
 #endif /* RECURSIVE */
     show      = dir_show > -1 ? dir_show : 3;
 
+    if (cx == XXWDIR) {                        /* WDIRECTORY */
+       debug(F100,"domydir WDIRECTORY","",0);
+       reverse = 1;                    /* Reverse chronological order */
+       xsort = 1;
+       sortby = DIRS_DT;
+    } else if (cx == XXHDIR) {         /* HDIRECTORY */
+       debug(F100,"domydir HDIRECTORY","",0);
+       reverse = 1;                    /* Reverse order by size */
+       xsort = 1;
+       sortby = DIRS_SZ;
+    } else if (cx == XXTOUC) {
+       touch = 1;
+       verbose = 0;
+    }  
+
 #ifdef CK_TTGWSIZ
 #ifdef OS2
     ttgcwsz();                          /* Screen length for more-prompting */
@@ -4819,7 +5010,7 @@ domydir() {                             /* Internal DIRECTORY command */
         x = cmfdb(&sw);                 /* Parse something */
         debug(F101,"domydir cmfdb","",x);
         if (x < 0)
-          return(x);
+          return(x); 
         if (cmresult.fcode != _CMKEY)   /* Break out if not a switch */
           break;
         c = cmgbrk();
@@ -4827,11 +5018,22 @@ domydir() {                             /* Internal DIRECTORY command */
             printf("?This switch does not take an argument\n");
             return(-9);
         }
-        if (!getval && (cmgkwflgs() & CM_ARG)) {
+       k = cmresult.nresult;
+        if (!getval &&
+           (cmgkwflgs() & CM_ARG) && k != DIR_TOP && k != DIR_COU) {
             printf("?This switch requires an argument\n");
             return(-9);
         }
-        switch (k = cmresult.nresult) {
+        switch (k) {
+          case DIR_COU: {
+              dir_cou++;
+              if (getval) {
+                  if ((x = cmfld("Variable for result","",&s,NULL)) < 0)
+                    return(x);
+                  makestr(&cv,s);
+              }
+              break;
+          }
           case DIR_BRF: verbose = 0; break;
           case DIR_VRB: verbose = 1; break;
 #ifdef CK_TTGWSIZ
@@ -4885,13 +5087,23 @@ domydir() {                             /* Internal DIRECTORY command */
 
 #ifdef CKSYMLINK
           case DIR_LNK:                 /* Follow links */
+#ifdef COMMENT
+           /* A command switch shouldn't be setting a global value! */
             nolinks = 0;
+#endif /* COMMENT */
             cmifn1 &= ~(2);
+           dontfollowlinks = 0;
             goto again;
           case DIR_NLK:                 /* Don't follow links */
+#ifdef COMMENT
             nolinks = 2;
+#endif /* COMMENT */
             cmifn1 &= ~(2);
+           dontfollowlinks = 1;
             goto again;
+         case DIR_NOL:                 /* Don't show links at all */
+           dontshowlinks = 1;
+           goto again;
 #endif /* CKSYMLINK */
 
           case DIR_NOM: msg     = 0;   break;
@@ -4908,17 +5120,26 @@ domydir() {                             /* Internal DIRECTORY command */
             break;
 
           case DIR_SMA:
-          case DIR_LAR:
-            if (!getval) break;
-            if ((x = cmnum("File size in bytes","0",10,&y,xxstring)) < 0)
-              return(x);
-            fs++;
-            show = 1;
-            switch (cmresult.nresult) {
-              case DIR_SMA: minsize = y; break;
-              case DIR_LAR: maxsize = y; break;
-            }
-            break;
+          case DIR_LAR: {
+             CK_OFF_T y;
+             if (!getval) break;
+             if ((x = cmnumw("File size in bytes","0",10,&y,xxstring)) < 0)
+               return(x);
+             fs++;
+             show = 1;
+             switch (cmresult.nresult) {
+               case DIR_SMA: minsize = y; break;
+               case DIR_LAR: maxsize = y; break;
+             }
+             break;
+         }
+         case DIR_TOP:
+           dir_top = 10;
+           if (!getval) break;
+             if ((x = cmnum("How many lines to show","10",10,&y,xxstring))< 0)
+               return(x);
+             dir_top = y;
+             break;
 
 #ifndef NOSPL
           case DIR_ARR:
@@ -5025,7 +5246,7 @@ domydir() {                             /* Internal DIRECTORY command */
 
 /* ^^^ START MULTIPLE */
     
-    while (1) {
+    while (!touch) {
        x = cmfld("Another filespec or Enter","",&s,xxstring);
        if (x == -3)
          break;
@@ -5046,29 +5267,64 @@ domydir() {                             /* Internal DIRECTORY command */
 
     if ((x = cmcfm()) < 0)              /* Get confirmation */
       return(x);
+
+/*
+  Command is TOUCH and file doesn't exist.
+*/
+    if (touch) {                       /* TOUCH */
+       if ((cmresult.fcode == _CMIFI && zchki(s) == (CK_OFF_T)-1)) {
+           FILE * fp;
+           s = brstrip(s);
+           if (!iswild(s)) {
+#ifdef UNIX
+               if (s[0] == '~')
+                 s = tilde_expand(s);
+#endif /* UNIX */
+               fp = fopen(s,"w");      /* Create file */
+               if (!fp) {
+                   printf("?TOUCH %s: %s\n",s,ck_errstr());
+                   rc = -9;
+                   goto xdomydir;
+               }
+               fclose(fp);
+               cx = XXDIR;             /* Now maybe list it. */
+               multiple++;             /* Force new directory scan */
+           }
+       }
+    } else
+
     if (cmresult.fcode != _CMIFI) {     /* Nothing matched */
+       /*
+         Note - this never gets executed because after the "begin
+         multiple" hack above, the result is always _CMIFI).
+       */
         char * m;
-        if (*s == '/')
+       if (*s == '/')
 #ifdef UNIXOROSK
-          m = "does not match switch or name of accessible file";
+         m = "does not match switch or name of accessible file";
 #else
 #ifdef OS2
-          m = "does not match switch or name of accessible file";
+       m = "does not match switch or name of accessible file";
 #else
-          m = "no switches match";
+       m = "no switches match";
 #endif /* OS2 */
 #endif /* UNIXOROSX */
-        else
-          m = "not found or not accessible";
-        printf("\"%s\" - %s\n",s,m);
-        rc = -9;
-        goto xdomydir;
+       else
+         m = "not found or not accessible";
+       printf("\"%s\" - %s\n",s,m);
+       rc = -9;
+       goto xdomydir;
     }
+#ifdef COMMENT
+    /* This can't be right because it's based on _CMCFM */
     wild = cmresult.nresult;            /* Wildcard was given? */
     debug(F111,"domydir cmifi2",s,wild);
+#else
+    wild = 0;
+#endif /* COMMENT */
 
-    if (outfile[0]) {
-        ofp = fopen(outfile,"w");       /* Open output file */
+    if (outfile[0]) {                  /* If an output file was specified */
+        ofp = fopen(outfile,"w");       /* open it */
         if (!ofp) {
             printf("?Can't open output file %s: %s\n",outfile,ck_errstr());
             ofp = stdout;
@@ -5133,6 +5389,15 @@ domydir() {                             /* Internal DIRECTORY command */
        debug(F111,"domydir zxrewind",s,x);
     } else {
 #endif /* ZXREWIND */
+/*
+  In case we gave multiple filespecs they are now in {a,b,c} list format.
+  Which is a valid wildcard.  We pass it to nzxpand() to get back the list
+  of files that match.  This is fine for DIRECTORY but it's not find for
+  TOUCH because we want TOUCH to see those names so it can create the files.
+  So for now at least, if TOUCH is to be used to create files -- as opposed
+  to changing the timestamps of existing files -- it can only do one file
+  at a time.
+*/
        nzxopts = (show == ZX_DIRONLY) ? ZX_DIRONLY :
          (show == ZX_FILONLY ? ZX_FILONLY : 0);
        if (matchdot)  nzxopts |= ZX_MATCHDOT;
@@ -5152,15 +5417,17 @@ domydir() {                             /* Internal DIRECTORY command */
             rc = -9;
             goto xdomydir;
         }
-        array = xx;
-        ap = a_ptr[array];
-        if (n < 1) {
+       arrayindex = xx;
+        ap = a_ptr[xx];                        /* Pointer to list of elements */
+        if (ap)                                /* Set element 0 to dimension */
+          makestr(&(ap[0]),"0");       /* which so far is zero */
+        if (n < 1) {                   /* No files matched, done. */
             rc = 0;
             goto xdomydir;
         }
     } else
 #endif /* NOSPL */
-      if (x < 1) {
+      if (!touch && x < 1) {
 #ifdef CKROOT
           extern int ckrooterr;
           if (ckrooterr)
@@ -5173,12 +5440,13 @@ domydir() {                             /* Internal DIRECTORY command */
               printf("?%s %s match - \"%s\"\n",
                      (x == 0) ? "No" : "Too many",
                      (show == 2) ? "directories" : "files",
-                     s
+                     brstrip(s)
                      );
           rc = -9;
           goto xdomydir;
     }
     nx = x;                             /* Remember how many files */
+    if (nx < 2) xsort = 0;             /* Skip sorting if none or one */
 
     if (msg) {
         makestr(&dirmsg,tmpbuf);
@@ -5216,7 +5484,7 @@ domydir() {                             /* Internal DIRECTORY command */
     if (page > -1)                      /* Paging */
       xaskmore = page;
 
-    if (!verbose) {                     /* /BRIEF */
+    if (!verbose && !touch) {          /* /BRIEF */
         if (outfile[0]) {               /* To file  */
             int k = 0;
             znext(name);
@@ -5236,7 +5504,9 @@ domydir() {                             /* Internal DIRECTORY command */
             rc = 1;
             goto xdomydir;
         } else {
-            rc = filhelp(x,"","",n,0);
+            rc = xfilhelp(x,"","",n,0,1,
+                         dir_aft,dir_bef,dir_naf,dir_nbf,
+                         minsize,maxsize,!backup,16,xlist);
             if (rc < 0)
               goto xdomydir;
             if (heading && rc > 0)
@@ -5245,7 +5515,8 @@ domydir() {                             /* Internal DIRECTORY command */
             goto xdomydir;
         }
     }
-    ndirs = nfiles = nbytes = 0L;       /* Initialize counters */
+    ndirs = nfiles = 0L;               /* Initialize counters */
+    nbytes = (CK_OFF_T)0;
 
     if (dir_exc)                        /* Have exception list? */
       makelist(dir_exc,xlist,16);      /* Yes, convert to array */
@@ -5264,7 +5535,7 @@ domydir() {                             /* Internal DIRECTORY command */
 #ifdef VMSORUNIX
         itsadir = zgfs_dir;             /* See if it's a directory */
 #else
-        itsadir = (len == -2 || isdir(name));
+        itsadir = (len == (CK_OFF_T)-2 || isdir(name));
 #endif /* VMSOUNIX */
         debug(F111,"domydir itsadir",name,itsadir);
         if ((itsadir && (show == 1)) || (!itsadir && (show == 2))) {
@@ -5273,17 +5544,38 @@ domydir() {                             /* Internal DIRECTORY command */
         }
         /* Get here when we know we have selected this file */
 
-        nmatches ++;
+        nmatches++;
         if (itsadir) {                  /* Accumulate totals for summary */
             ndirs++;
         } else {
             nfiles++;
             nbytes += len;
         }
-        if (summary) {                  /* Summary only, no detail */
+       dstr = NULL;
+       if (cx == XXTOUC) {             /* Command was TOUCH, not DIRECTORY */
+           char * filename;
+           struct zattr xx;
+           dstr = ckcvtdate("",0);
+           xx.date.val = dstr;
+           xx.date.len = (int)strlen(xx.date.val);
+           xx.lprotect.len = 0;
+           debug(F110,"domydir touch",name,0);
+           debug(F110,"domydir touch",dstr,0);
+           if (zstime(name,&xx,0) < 0) {
+               printf("?TOUCH %s: %s\n",name,ck_errstr());
+               rc = -9;
+               goto xdomydir;
+           }
+           if (!verbose) {             /* No listing so skip detail */
+               znext(name);
+               continue;
+           }
+       }
+        if (summary) {                 /* Summary only, no detail */
             znext(name);
             continue;
         }
+
 #ifndef NOSPL
         if (array) {
             debug(F111,"domydir array",name,nfiles);
@@ -5299,10 +5591,13 @@ domydir() {                             /* Internal DIRECTORY command */
   permission strings, date/time strings, and filenames, all of which have
   known maximum lengths; none of these items is input from users.  The
   destination buffers are large enough to hold maximum sizes for any and
-  all items.
+  all items.  NOTE 2: If command was TOUCH, dstr was already set just
+  above.
 */
-        dstr = zfcdat(name);            /* Get modification date/time */
-        debug(F111,"domydir zcfdat",dstr,0);
+       if (!dstr) {                    /* Get file's modification date/time */
+           dstr = zfcdat(name);
+           debug(F111,"domydir zcfdat",dstr,0);
+       }
         if (!dstr) dstr = "";
         {
 /*
@@ -5368,7 +5663,7 @@ domydir() {                             /* Internal DIRECTORY command */
         ckstrncpy(name,zrelname(name,cdp),CKMAXPATH);
 #endif /* VMS */
 
-        if (itsadir && len < 0) {       /* Directory */
+        if (itsadir && len < (CK_OFF_T)0) { /* Directory */
 #ifdef VMS
             sprintf(linebuf,"%-22s%-10s  %s  %s",p,"<DIR>",dstr,name);
 #else
@@ -5379,18 +5674,24 @@ domydir() {                             /* Internal DIRECTORY command */
 #endif /* VMS */
         } else {                        /* Regular file */
 #ifdef VMS
-            sprintf(linebuf,"%-22s%10ld  %s  %s", p, len, dstr, name);
+            sprintf(linebuf,"%-22s%10s  %s  %s", p, ckfstoa(len), dstr, name);
 #else
             if (p)
-              sprintf(linebuf,"%10s%10ld  %s  %s", p, len, dstr, name);
+              sprintf(linebuf,"%10s%10s  %s  %s", p, ckfstoa(len), dstr, name);
             else
-              sprintf(linebuf,"%10ld  %s  %s", len, dstr, name);
+              sprintf(linebuf,"%10s  %s  %s", ckfstoa(len), dstr, name);
 #endif /* VMS */
         }
 #ifdef UNIX
 #ifdef CKSYMLINK
-        if (zgfs_link) {
-            int n, m;
+        if (zgfs_link) {               /* If it's a symlink */
+           if (dontshowlinks) {        /* If /NOLINKS don't show it */
+               znext(name);
+               continue;
+           }
+       }
+        if (zgfs_link && !dontfollowlinks) { /* Symlink and following links */
+            int n, m;                  /* Show what the link points to */
             extern char linkname[];
             n = strlen(linebuf);
             m = strlen(linkname) + n;
@@ -5434,7 +5735,7 @@ domydir() {                             /* Internal DIRECTORY command */
             if (n + dirmsglen + 2 < CKMAXPATH)
               sprintf((char *)(linebuf+n)," %s", dirmsg); /* SAFE */
         }
-        if (xsort) {                    /* Sorting - save line */
+        if (xsort) {                   /* Sorting - save line */
             i = strlen(linebuf);
             if ((ndirlist >= nx) ||
                 !(dirlist[ndirlist] = (char *)malloc(i+1))) {
@@ -5446,9 +5747,9 @@ domydir() {                             /* Internal DIRECTORY command */
             ndirlist++;
         }
         znext(name);                    /* Peek ahead to next file */
-
         if (!xsort) {
-            fprintf(ofp,"%s\n",linebuf);
+           if (!touch || (touch && verbose))
+             fprintf(ofp,"%s\n",linebuf);
             if (page && (name[0] || heading)) { /* If /PAGE */
                 if (cmd_cols > 0) {
                     int x = strlen(linebuf);
@@ -5479,29 +5780,35 @@ domydir() {                             /* Internal DIRECTORY command */
     }
 #endif /* NOSPL */
     if (xsort) {
+       int namepos;
         skey = 0;
 #ifdef VMS
+       namepos = dlen + 35;
         switch (sortby) {
-          case DIRS_NM: skey = dlen + 35; break;
+          case DIRS_NM: skey = namepos; break;
           case DIRS_DT: skey = 33; break;
           case DIRS_SZ: skey = 21;
         }
 #else
         if (p) {
+           namepos = dlen + 24;
             switch (sortby) {
-              case DIRS_NM: skey = dlen + 24; break;
+              case DIRS_NM: skey = namepos; break;
               case DIRS_DT: skey = 22; break;
               case DIRS_SZ: skey = 10;
             }
         } else {
+           namepos = dlen + 14;
             switch (sortby) {
-              case DIRS_NM: skey = dlen + 14; break;
+              case DIRS_NM: skey = namepos; break;
               case DIRS_DT: skey = 12; break;
               case DIRS_SZ: skey = 0;
             }
         }
 #endif /* VMS */
         sh_sort(dirlist,NULL,ndirlist,skey,reverse,filecase);
+       if (dir_top > 0 && dir_top < ndirlist)
+         ndirlist = dir_top;
         for (i = 0; i < ndirlist; i++) {
             fprintf(ofp,"%s\n",dirlist[i]);
             if (page && (i < ndirlist -1 || heading)) { /* If /PAGE */
@@ -5530,12 +5837,12 @@ domydir() {                             /* Internal DIRECTORY command */
 #ifdef CKFLOAT
         CKFLOAT gm;
 #endif /* CKFLOAT */
-        fprintf(ofp,"\n%ld director%s, %ld file%s, %ld byte%s",
+        fprintf(ofp,"\n%ld director%s, %ld file%s, %s byte%s",
                ndirs,
                (ndirs == 1) ? "y" : "ies",
                nfiles,
                (nfiles == 1) ? "" : "s",
-               nbytes,
+              ckfstoa(nbytes),
                (nbytes == 1) ? "" : "s"
                );
 #ifdef CKFLOAT
@@ -5546,8 +5853,20 @@ domydir() {                             /* Internal DIRECTORY command */
           fprintf(ofp," (%0.2fMB)",gm);
 #endif /* CKFLOAD */
         fprintf(ofp,"\n\n");
+    } else if (dir_cou && !cv) {
+       fprintf(ofp,"\n Files: %ld\n\n",nfiles);
     }
   xdomydir:
+#ifndef NOSPL
+    if (dir_cou && cv) {                /* /COUNT:var */
+        addmac(cv,ckitoa(nfiles));     /* set the variable */
+        makestr(&cv,NULL);              /* free this */
+    }
+    if (ap) {                          /* If we have a result array */
+       if (a_dim[arrayindex] > nmatches) /* but it was not filled */
+         a_dim[arrayindex] = nmatches;   /* adjust dimension */
+    }
+#endif /* NOSPL */
     if (g_matchdot > -1) {
         matchdot = g_matchdot;          /* Restore these... */
         g_matchdot = -1;
@@ -5567,14 +5886,15 @@ dodir(cx) int cx; {                     /* Do the DIRECTORY command */
     char *dc , *msg;
 
 #ifdef OS2
-    return(domydir());
+    return(domydir(cx));
 #else /* OS2 */
     if (nopush
 #ifdef DOMYDIR                          /* Builds that domydir() by default */
-        || (cx == XXDIR || cx == XXLDIR)
+        || (cx == XXDIR  || cx == XXLDIR || cx == XXWDIR ||
+           cx == XXHDIR || cx == XXTOUC)
 #endif /* DOMYDIR */
         )
-      return(domydir());                /* Built-in directory command */
+      return(domydir(cx));             /* Built-in directory command */
 
     /* Use the system's directory command. */
 
@@ -5876,7 +6196,7 @@ dodel() {                               /* DELETE */
     int bad = 0;
     int getval = 0, asking = 0;
     int simulate = 0, rc = 0;
-    long minsize = -1L, maxsize = -1L;
+    CK_OFF_T minsize = -1L, maxsize = -1L;
     int havename = 0, confirmed = 0;
     int qflag = 0;
     int summary = 0;
@@ -6121,9 +6441,9 @@ dodel() {                               /* DELETE */
         if (*atmbuf) {
            int x;
             if (iswild(atmbuf) && nzxpand(atmbuf,nzxopts) == 0)
-              printf("?No files match: %s\n",atmbuf);
+              printf("?No files match: %s\n",brstrip(atmbuf));
             else if ((x = zchki(atmbuf)) == -1)
-             printf("?File not found: %s\n",atmbuf);
+             printf("?File not found: %s\n",brstrip(atmbuf));
            else if (x == -2)
              printf("?Not a regular file: %s\n",atmbuf);
            else
@@ -6607,7 +6927,7 @@ doelse() {
     if (!iftest[cmdlvl]) {              /* If IF was false do ELSE part */
         if (maclvl > -1 || tlevel > -1) { /* In macro or command file */
             debug(F100,"doelse pushing","",0);
-#ifdef COMMENT
+#ifndef COMMENT
             pushcmd(NULL);              /* save rest of command. */
 #else
             /* This fixes certain obscure problems */
@@ -6918,92 +7238,6 @@ badfor:
 }
 #endif /* NOSPL */
 
-#ifndef NOFRILLS
-/* Do the BUG command */
-
-int
-dobug() {
-    int n;
-    char * s = "";
-    extern char * k_info_dir;
-
-    if (k_info_dir)
-      s = k_info_dir;
-
-#ifdef COMMENT
-    printf("\n%s,%s\n Numeric: %ld",versio,ckxsys,vernum);
-#endif /* COMMENT */
-    printf(
-"\nBefore requesting technical support from Columbia U., please consult:\n\n"
-           );
-    n = 7;
-#ifdef OS2
-    printf(" . Your \"Kermit 95\" user manual (use the MANUAL command).\n");
-    printf(" . The technical reference manual, \"Using C-Kermit\".\n");
-    n += 2;
-#else
-    printf(" . The book \"Using C-Kermit\" (type HELP for more info).\n");
-    n += 1;
-#endif /* OS2 */
-
-    printf(" . Your own organization's support staff, if any.\n");
-    printf(
-" . The comp.protocols.kermit.misc newsgroup.\n");
-    printf(
-" . The Kermit support website, http://www.columbia.edu/kermit/support.html \n"
-           );
-    printf(
-
-" . The Kermit FAQ, http://www.columbia.edu/kermit/newfaq.html \n");
-#ifdef OS2
-    printf(
-" . The Kermit 95 FAQ, http://www.columbia.edu/kermit/k95faq.html \n");
-    n++;
-#endif /* OS2 */
-
-    printf(
-" . The C-Kermit FAQ, http://www.columbia.edu/kermit/ckfaq.html \n");
-    n += 4;
-    if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
-    printf("\n\
-If you still need help or have a bug to report after consulting these sources,"
-           );
-    printf("\nsend e-mail to:\n\n");
-    n += 2;
-    if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
-    printf("  mailto:kermit-support@columbia.edu\n\n");
-    n += 1;
-    if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
-    printf("Or contact us by post:\n\n");
-    printf(
-"  Kermit, Columbia University, 612 W 115 Street, New York NY  10025, USA\n\n"
-           );
-    n += 1;
-    if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
-    printf("Or by fax at +1 (212) 662-6442.\n\n");
-    n += 1;
-    if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
-#ifdef COMMENT
-    printf("Telephone support is available too:\n\n");
-    n += 1;
-    if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
-    printf(
-    "  +1 (212) 854-5126, from anywhere, $25.00 USD per call, MC/Visa\n\n");
-    n += 1;
-    if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
-#endif /* COMMENT */
-#ifndef NOSHOW
-#ifndef NOFRILLS
-    printf(
-"Before reporting problems, please use the SHOW FEATURES command\n");
-    if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
-    printf(
-"to get detailed program version and configuration information.\n\n");
-#endif /* NOFRILLS */
-#endif /* NOSHOW */
-    return(1);
-}
-#endif /* NOFRILLS */
 
 #ifndef NOSPL
 
@@ -7574,18 +7808,24 @@ dolink() {
 #ifdef ZCOPY
 int
 docopy() {
-    int i, x, listing = 0, nolist = 0, havename = 0;
+    int i, x, listing = 0, nolist = 0, havename = 0, getval;
+    char c;
     struct FDB sw, fi;
+    int overwrite = OVW_ALWAYS;
     int targetisdir = 0;
     int targetlen = 0;
-    int swapping = 0;
     int appending = 0;
+    int preserve = 0;
+    int swapping = 0;
     int fromb64 = 0;
     int tob64 = 0;
     int wild = 0;
     int rc = 1;
 
-    cmfdbi(&sw,                         /* 2nd FDB - optional /PAGE switch */
+    char newname[CKMAXPATH], * nm;
+    nm = newname;
+
+    cmfdbi(&sw,                         /* 1st FDB - switches */
            _CMKEY,                      /* fcode */
            "Filename or switch",        /* hlpmsg */
            "",                          /* default */
@@ -7596,7 +7836,7 @@ docopy() {
            copytab,                     /* Keyword table */
            &fi                          /* Pointer to next FDB */
            );
-    cmfdbi(&fi,                         /* 1st FDB - file to type */
+    cmfdbi(&fi,                         /* 2nd FDB - file to copy */
            _CMIFI,                      /* fcode */
            "",                          /* hlpmsg */
            "",                          /* default */
@@ -7614,6 +7854,17 @@ docopy() {
           return(x);
         switch (cmresult.fcode) {
           case _CMKEY:
+           c = cmgbrk();                   /* Get break character */
+           if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
+               printf("?This switch does not take an argument\n");
+               rc = -9;
+               return(rc);
+           }
+           if (!getval && (cmgkwflgs() & CM_ARG)) {
+               printf("?This switch requires an argument\n");
+               rc = -9;
+               return(rc);
+           }
             switch (cmresult.nresult) {
               case DEL_LIS:
               case DEL_VRB:
@@ -7631,6 +7882,16 @@ docopy() {
               case 998:
                 appending = 1;
                 break;
+             case 995:
+               preserve = 1;
+                break;
+             case 994:
+               if ((x = cmkey(ovwtab,novwtab,
+                              "When to overwrite existing destination file",
+                              "",xxstring)) < 0)
+                 return(x);
+               overwrite = x;
+                break;
 #ifndef NOSPL
               case 997:
                 fromb64 = 1;
@@ -7675,7 +7936,7 @@ docopy() {
     }
 #ifdef COMMENT
 /*
-  This unreasonably prevented "COPY /APPEND *.* bifile" from concatenating
+  This unreasonably prevented "COPY /APPEND *.* bigfile" from concatenating
   a bunch of files into one big file.
 */
     if (appending && wild) {
@@ -7734,6 +7995,7 @@ docopy() {
 #endif /* VMS */
     debug(F110,"docopy line",line,0);
     debug(F110,"docopy p",p,0);
+    debug(F110,"docopy nm",nm,0);
 
 #ifdef ZXREWIND
     z = zxrewind();                     /* Rewind file list */
@@ -7773,13 +8035,62 @@ docopy() {
 
         errno = 0;                      /* Reset errno */
 
-        if (listing) printf("%s => %s ",line,p);
+       if (targetisdir) {
+           zstrip(line,&nm);
+           ckmakmsg(newname,CKMAXPATH,p,nm,NULL,NULL);
+           nm = newname;
+       } else {
+           nm = p;
+       }
+       if (overwrite) {                /* Overwrite checking? */
+           if (zchki(nm) >= (CK_OFF_T)0) { /* Destination file exists? */
+
+               char d1[20], * d2;
+               char * n1, * n2;
+               int i, skip = 0;
+
+               i = strlen(line);       /* Isolate source filename */
+               for (; i >= 0; i--) {
+                   if (ISDIRSEP(line[i])) {
+                       n1 = &line[i+1];
+                       break;
+                   }
+               }
+               debug(F110,"COPY n1", n1, 0);
+               i = strlen(nm);         /* And destination filename */
+               for (; i >= 0; i--) {
+                   if (ISDIRSEP(nm[i])) {
+                       n2 = &nm[i+1];
+                       break;
+                   }
+               }
+               debug(F110,"COPY n2", n2, 0);
+               if (!strcmp(n1,n2)) {             /* Same name? */
+                   if (overwrite == OVW_NEVER) { /* Never overwrite? */
+                       if (listing)              /* Skip */
+                         if (listing) printf("%s => %s (SKIPPED)\n",line,nm);
+                       continue;
+                   }
+                   ckstrncpy(d1,zfcdat(line),20); /* Source file timestamp */
+                   d2 = zfcdat(nm);           /* Timestamp of dest file */
+                   x = strcmp(d1,d2);         /* Compare them */
+                   if (((overwrite == OVW_NEWER) && (x < 0)) ||
+                       ((overwrite == OVW_OLDER) && (x > 0))) {
+                       if (listing)
+                         if (listing) printf("%s => %s (SKIPPED)\n",line,nm);
+                       continue;
+                   }
+               }
+           }
+       }
+        if (listing) printf("%s => %s ",line,nm);
 
         /* Straight copy */
         if (!swapping && !appending && !fromb64 && !tob64) {
             debug(F110,"COPY zcopy",line,0);
 
             if ((x = zcopy(line,p)) < 0) { /* Let zcopy() do it. */
+               debug(F111,"COPY not OK",line,x);
                 switch (x) {
                   case -2:
                    if (listing)
@@ -7832,8 +8143,33 @@ docopy() {
                      printf("?%s\n",ck_errstr());
                     rc = 0;
                 }
-            } else {
-                if (listing) printf("(OK)\n");
+            } else {                   /* Regular copy succeeded */
+               debug(F110,"COPY OK..",newname,0);
+#ifndef NOXFER
+               if (preserve) {         /* Handle /PRESERVE */
+                   char * pstr = "";   /* File permissions string */
+                   struct zattr xx;    /* File attribute structure */
+                   extern char * cksysid;
+
+                   initattr(&xx);      /* Initialize the struct */
+
+                   xx.systemid.val = cksysid; /* Set our system ID */
+                   xx.systemid.len = (int)strlen(cksysid);
+#ifdef CK_PERMS
+                   pstr = zgperm(line); /* Get source file's permissions */
+#endif /* CK_PERMS */
+                   xx.lprotect.val = pstr;
+                   xx.lprotect.len = (int)strlen(pstr);
+                   xx.date.val = zfcdat(line); /* Source file's timestamp */
+                   xx.date.len = (int)strlen(xx.date.val);
+                   if (zstime(nm,&xx,0) < 0) {
+                       printf("?COPY /PRESERVE %s: %s\n",nm,ck_errstr());
+                       rc = -9;
+                   }
+               }
+#endif /* NOXFER */
+               if (listing && rc > -1)
+                 printf("(OK)\n");
             }
 
         } else {                        /* Special options */
@@ -8045,102 +8381,804 @@ docopy() {
 #endif /* ZCOPY */
 #endif /* NOFRILLS */
 
+#ifndef NOCSETS
+#ifndef NOUNICODE
+static struct keytab * xfcstab = NULL; /* For RENAME /CONVERT: */
+static char cvtbufin[CKMAXPATH+8] = { NUL, NUL };
+static char cvtbufout[CKMAXPATH+8] = { NUL, NUL };
+static char * pcvtbufin = NULL;
+static char * pcvtbufout = NULL;
+
+static int                             /* Input function xgnbyte() */
+cvtfnin() {
+    CHAR c;
+    c = *pcvtbufin++;
+    return(c ? c : -1);
+}
+
+_PROTOTYP(int cvtfnout,(char));                /* Output function for xpnbyte() */
+int
+#ifdef CK_ANSIC
+cvtfnout(char c)
+#else
+cvtfnout(c) char c;
+#endif /* CK_ANSIC */
+{
+    if (pcvtbufout - cvtbufout >= CKMAXPATH)
+      return(-1);
+    *pcvtbufout++ = c;
+    *pcvtbufout = NUL;
+    return(1);
+}
+
+/* Convert a string from any charset to any other charset */
+
+char *
+cvtstring(s,csin,csout) char * s; int csin, csout; {
+    int c;
+    extern CK_OFF_T ffc;
+
+    ckstrncpy(cvtbufin,s,CKMAXPATH);   /* Put it in a public place */
+    pcvtbufin = cvtbufin;              /* with public pointers */
+    pcvtbufout = cvtbufout;
+    *pcvtbufout = NUL;
+
+    if (csin == csout)                 /* If the two sets are the same */
+      return((char *)cvtbufin);                /* don't bother converting */
+
+    initxlate(csin,csout);             /* Initialize the translator */
+
+    while ((c = xgnbyte(FC_UCS2,csin,cvtfnin)) > -1) { /* Loop thru string */
+       if (xpnbyte(c,TC_UCS2,csout,cvtfnout) < 0) {
+           ffc = (CK_OFF_T)0;
+           return("");
+       }
+    }
+    /* ffc is touched by xgnbyte() but this is not file transfer */
+    /* so we have to undo it */
+    ffc = (CK_OFF_T)0;
+    return((char *)cvtbufout);
+}
+#endif /* NOUNICODE */
+#endif /* NOCSETS */
+
 #ifndef NORENAME
 #ifndef NOFRILLS
 #ifdef ZRENAME
+
+/* The RENAME command - expanded and improved in 8.0.212 April 2006 */
+
+static char * ren_sub[4] = { NULL,NULL,NULL,NULL }; /* For RENAME /REPLACE */
+
+int ren_list = 0;                      /* Default listing action for RENAME */
+int ren_coll = RENX_OVWR;              /* Default collision action */
+
+int
+shorename() {
+    char * s;
+    switch (ren_coll) {
+      case RENX_FAIL: s = "fail"; break;
+      case RENX_OVWR: s = "overwrite"; break;
+      case RENX_SKIP: s = "proceed"; break;
+    }
+    printf(" rename collision: %s\n",s);
+    printf(" rename list:      %s\n",showoff(ren_list));
+    return(1);
+}
+
+int
+setrename() {                          /* Parse SET RENAME options */
+    int x, y;
+    if ((x = cmkey(renamset,nrenamset,"","", xxstring)) < 0)
+      return(x);
+    switch (x) {
+      case REN_OVW:                    /* COLLISION */
+       if ((x = cmkey(r_collision,nr_collision,"","", xxstring)) < 0)
+         return(x);
+       if ((y = cmcfm()) < 0)
+         return(y);
+       ren_coll = x;
+       break;
+      case DEL_LIS:                    /* LIST */
+       return(seton(&ren_list));
+    }
+    return(success = 1);
+}
+
+/* Reverse a string - Assumes a single-byte character set */
+
+int
+gnirts(s1, s2, len) char * s1, * s2; int len; {
+    int n, m = 0;
+    if (!s1)                           /* Null source pointer, fail */
+      return(0);
+    n = (int) strlen(s1);
+    if (n > len-1)                     /* Source longer than dest, fail */
+      return(0);
+    s2[n--] = NUL;                     /* Deposit null byte at end of dest */
+    for (; n >= 0; n--) {              /* Copy the rest backwards */
+       *s2++ = s1[n];
+       m++;
+    }
+    return(m);
+}
+
+/*
+  r e n a m e o n e
+
+  Worker function to rename one file for dorenam() (below).
+    old        = name of file or directory to be renamed
+    new        = new name (not required for /UPPER, /LOWER, and /REPLACE)
+    replacing  = 1 if doing string replacement on the name  
+    casing     = 1 if converting name to lowercase, 2 if to uppercase
+    all        = if doing case conversion on all names, not just monocase ones
+    converting = 1 if converting character sets
+    cset1      = character set to convert from (File Character Set index)
+    cset2      = character set to convert to (ditto, see ck?xla.h)
+    listing    = 1 to show results of rename
+    nolist     = 1 to be completely silent (don't even print error messages)
+    op         = 1 means simulate, 2 means check for collision, 0 means rename
+    size       = length of result buffer.
+    collision  = action to take if destination file already exists:
+                 0 = fail
+                 1 = overwrite and succeed
+                 2 = skip and succeed
+  Returns:
+     0: on failure to rename or when a forbidden collision would have occurred.
+     1: on success (file was renamed or did not need to be renamed).
+  Note:
+     If this code is ever built on any platform that is not Unix, Windows,
+     VMS, or OS/2, this routine might need some adjustment.
+*/
+
+/* Opcodes for op... */
+#define REN_OP_SIM 1                   /* Simulate */
+#define REN_OP_CHK 2                   /* Check for collisions */
+
+static int
+renameone(old,new,
+         replacing,casing,all,converting,cset1,cset2,
+         listing,nolist,op,size,collision)
+    char * old, * new;
+    int replacing,casing,all,converting,cset1,cset2,
+    listing,nolist,op,size,collision;
+{
+    char buf[CKMAXPATH];               /* Temporary filename buffer */
+    char out[CKMAXPATH];               /* Buffer for new name */
+    char dir[CKMAXPATH];               /* Destination directory */
+    char pat[CKMAXPATH];               /* Path segment on old filename */
+
+    char * destdir;                    /* Destination directory, if any */
+    char * srcpath;                    /* Source path, if any */
+    int rc = 1, flag = 0, skip = 0;    /* Control */
+    int honorcase = 0, replaced = 0;
+    int anchor = 0;                    /* 1 = beginning, 2 = end */
+    int occur = 0;                     /* Occurrence */
+    int minus = 0;                     /* Occurrence is negative */
+    int allbut = 0;                    /* Occurrence is "all but" */
+    int arg2isfile = 0;                        /* Arg2 ("new") is a filename */
+    
+    debug(F110,"RENAMEONE old",old,0);
+    debug(F110,"RENAMEONE new",new,0);
+    debug(F110,"RENAMEONE ren_sub[0]",ren_sub[0],0);
+    debug(F110,"RENAMEONE ren_sub[1]",ren_sub[1],0);
+    debug(F110,"RENAMEONE ren_sub[2]",ren_sub[2],0);
+
+    if (op == REN_OP_SIM && !nolist)   /* For convenience */
+      listing = 1;
+#ifndef NOSPL
+    honorcase = inpcas[cmdlvl];                /* Inherit SET CASE value */
+#else
+#ifdef UNIX
+    honorcase = 1;
+#else
+    honorcase = 0;
+#endif /* UNIX */
+#endif /* NOSPL */
+
+    if (!old) old = "";                        /* In case of bad args */
+    if (!new) new = "";
+    if (!*old) return(success = 0);
+    ckstrncpy(out,new,CKMAXPATH);      /* So we don't write into */
+    new = out;                         /* our argument... */
+    size = CKMAXPATH;
+
+    pat[0] = NUL;                      /* Assume no path in source file.. */
+    srcpath = pat;
+    {
+       int n;                          /* If the old name includes a path */
+       n = (int)strlen(old) - 1;       /* put it in a separate place.     */
+       for (; n >= 0; n--) {           /* We are renaming the file only.  */
+           if (ISDIRSEP(old[n])) {
+               ckstrncpy(pat,old,CKMAXPATH);
+               pat[n+1] = NUL;
+               old = old+n+1;
+               break;
+           }
+       }
+    }
+    debug(F110,"RENAMEONE old 2",old,0);
+    debug(F110,"RENAMEONE pat 2",pat,0);
+
+    dir[0] = NUL;                      /* Assume no destination directory */
+    destdir = dir;
+    if (*new) {                                /* If Arg2 given */
+       if (isdir(new)) {               /* If it's a directory */
+           ckstrncpy(dir,new,CKMAXPATH); /* put it here */
+       } else {                        /* otherwise */
+           arg2isfile++;               /* flag that it's a filename */
+       }    
+    }
+    if (!casing && !replacing && !converting) {
+       if (!*new)
+         return(success = 0);
+       if (!arg2isfile) {              /* Destination is a directory? */
+           if (!isdir(old)) {          /* and source is not? */
+#ifndef VMS
+               int n, x = 0;           /* Concatenate them */
+               if ((n = strlen(new)) > 0) /* so we can check for */
+                 if (ISDIRSEP(new[n-1]))  /* collisions. */
+                   x++;
+               ckmakmsg(buf,size,new,x ? "" : "/", old, "");
+#else
+               ckmakmsg(buf,size,new, old, NULL, NULL);
+#endif /* VMS */
+               debug(F110,"RENAMEONE new new",new,0);          
+               new = buf;
+               size = CKMAXPATH;
+           }
+       }
+    } else if (*new) {                 /* Directory to move file to */
+       int n, x = 0;                   /* after changing its name */
+       if (!isdir(new))
+         return(success = 0);
+#ifndef VMS
+       if ((n = strlen(new)) > 0)
+         if (ISDIRSEP(new[n-1]))
+           x++;
+       ckmakmsg(dir,CKMAXPATH,new,x ? "" : "/", "", "");
+#else
+       ckstrncpy(dir,new,CKMAXPATH);
+#endif /* VMS */
+    }
+
+#ifndef NOCSETS
+#ifndef NOUNICODE
+    if (converting) {
+       new = cvtstring(old,cset1,cset2);
+    }
+#endif /* NOUNICODE */
+#endif /* NOCSETS */
+
+    if (replacing) {                   /* Replacing strings */
+       int todo = 0;
+       int len0, len1, len2;
+       char c, *p, *s, *bp[3];
+
+       bp[0] = old;                    /* Original name */
+       bp[1] = ren_sub[0];             /* String to be replaced */
+       bp[2] = ren_sub[1];             /* What to replace it with */
+       if (!bp[2]) bp[2] = "";
+
+       len0 = (int)strlen(bp[0]);      /* length of original filename */
+       len1 = (int)strlen(bp[1]);      /* length of target substring */
+       len2 = (int)strlen(bp[2]);      /* Length of replacement string */
+
+       if (ren_sub[2]) {               /* Optional options */
+           p = ren_sub[2];
+           while ((c = *p++)) {
+               switch (c) {
+                 case '^':
+                   anchor = 1; occur = 0; minus = 0; allbut = 0; break;
+                 case '$':
+                   anchor = 2; occur = 0; minus = 0; allbut = 0; break;
+                 case 'A': honorcase = 1; minus = 0; allbut = 0; break;
+                 case 'a': honorcase = 0; minus = 0; allbut = 0; break;
+                 case '-': minus = 1; break;
+                 case '~': allbut = 1; break;
+                 default:
+                   if (isdigit(c)) {
+                       occur = c - '0';
+                       if (minus) occur = 0 - occur;
+                       anchor = 0;
+                   }
+                   minus = 0;
+               }
+           }
+       }
+       if (anchor) {                   /* Anchored replacement... */
+           y = len0 - len1;
+           if (y > 0) {
+               int x;
+               switch (anchor) {
+                 case 1:               /* Anchored at beginning */
+                   if (!ckstrcmp(bp[1],bp[0],len1,honorcase)) {
+                       x = ckstrncpy(new,bp[2],size);
+                       (VOID) ckstrncpy(new+x,bp[0]+len1,size-x);
+                       replaced = 1;
+                   }
+                   break;
+                 case 2:               /* Anchored at end */
+                   if (!ckstrcmp(bp[1],bp[0]+y,len1,honorcase)) {
+                       x = ckstrncpy(new,bp[0],y+1);
+                       (VOID) ckstrncpy(new+y,bp[2],size-x);
+                       replaced = 1;
+                   }
+                   break;
+               }
+           }
+           if (!replaced) {
+               ckstrncpy(new,old,size); /* Keep old name */
+               replaced = 1;
+           }
+       } else {                        /* Replace all occurrences */
+           int j, n = 0;               /* or a particular occurrence */
+           char c;
+           int x = 0;
+           char * s0 = NULL, * s1 = NULL, * s2 = NULL;
+           p = new;                    /* Pointer to new name */
+
+           if (occur < 0) {            /* nth occurrence from the right */
+               occur = 0 - occur;
+               s0 = (char *)malloc(len0+1); /* Reverse original string */
+               if (s0) {
+                   (VOID) gnirts(bp[0],s0,len0+1);
+                   bp[0] = s0;
+               } else return(0); 
+               s1 = (char *)malloc(len1+1); /* Reverse target string */
+               if (s1) {
+                   (VOID) gnirts(bp[1],s1,len1+1);
+                   bp[1] = s1;
+               } else return(0); 
+               s2 = (char *)malloc(len2+1); /* Reverse replacement string */
+               if (s2) {
+                   (VOID) gnirts(bp[2],s2,len2+1);
+                   bp[2] = s2;
+               } else return(0); 
+               debug(F111,"RENAMEONE s0",s0,len0);
+               debug(F111,"RENAMEONE s1",s1,len1);
+               debug(F111,"RENAMEONE s2",s2,len2);
+           }
+           s = bp[0];                  /* Pointer to old name */
+           p = new;                    /* Pointer to new name */
+           j = len0 - len1 + 1;        /* How much to scan */
+           while (j-- > 0) {           /* For each character... */
+               if (!ckstrcmp(bp[1],s,len1,honorcase)) { /* Match? */
+                   n++;                /* Occurrence counter */
+                   todo = (occur == 0) ||
+                       (!allbut && n == occur) ||
+                       (allbut && n != occur);
+                   if (!todo) {        /* Desired occurrence? */
+                       size -= ckstrncpy(p,bp[1],size); /* No... */
+                       p += len1;      /* Copy target string */
+                       s += len1;      /* instead of replacement string */
+                       continue;
+                   }
+                   if (len2) {         /* If replacement string not empty */
+                       size -= ckstrncpy(p,bp[2],size); /* Copy it */
+                       p += len2;
+                   }
+                   s += len1;          /* Advance source position */
+               } else {                /* No match */
+                   *p++ = *s++;        /* just copy this character */
+                   size--;
+               }
+           }
+           while ((*p++ = *s++));      /* Done copy the rest */
+           replaced = 1;               /* Remember we changed the name */
+           if (s0) {                   /* Were we doing "all but"? */
+               debug(F110,"RENAMEONE new1",new,0);
+               x = (int)strlen(new);   /* Unreverse the result */
+               if ((p = (char *)malloc(x+2))) {
+                   (VOID) gnirts(new,p,x+2);
+                   debug(F110,"RENAMEONE new2",new,0);
+                   ckstrncpy(new,p,x+2);
+                   free(p);
+               }
+               if (s0) free(s0);       /* Free the temporary strings */
+               if (s1) free(s1);
+               if (s2) free(s2);
+               debug(F110,"RENAMEONE new3",new,0);
+           }
+       }
+    }
+    if (casing) {                      /* Changing case? */
+       char c, * t;                    /* See if mixed case. */
+       if (!replaced)
+         ckstrncpy(new,old,size);      /* Copy old name to new name */
+       t = new;
+       while ((c = *t++)) {
+           if (islower(c)) flag |= 1; /* Have a lowercase letter */
+           else if (isupper(c)) flag |= 2; /* Have an uppercase letter */
+           if (flag == 3) break;       /* Have a mixed-case name */
+       }
+       if (all || flag < 3) {  /* Not skipping or not mixed case */
+           if (casing == 1 && flag != 1) /* Change case to lower */
+             (VOID) cklower(new);
+           else if (casing == 2 && flag != 2) /* Change case to upper */
+             (VOID) ckupper(new);
+       }
+    }
+    debug(F110,"XXX 1 new",new,0);
+    debug(F110,"XXX 1 old",old,0);
+    debug(F110,"XXX 1 srcpath",srcpath,0);
+    debug(F110,"XXX 1 destdir",destdir,0);
+
+    if (*destdir && !arg2isfile) {     /* Moving without renaming */
+       ckstrncat(srcpath,old,CKMAXPATH);
+       old = srcpath;
+       new = destdir;
+    } else if (*destdir || *srcpath) { /* Were there any pathnames? */
+       char tmp[CKMAXPATH];
+       ckmakmsg(tmp,CKMAXPATH,srcpath,old,NULL,NULL);
+       ckstrncpy(old,tmp,CKMAXPATH);
+       if (*destdir) {                 /* Directory-to-move-to given? */
+           ckstrncat(destdir,new,CKMAXPATH);
+           new = destdir;
+       } else if (*srcpath && !arg2isfile) { /* Or was there a source path? */
+           ckstrncat(srcpath,new,CKMAXPATH);
+           new = srcpath;
+       }
+    }
+    debug(F110,"XXX 2",new,0);
+
+    skip = 0;                          /* Can we skip this one? */
+#ifdef COMMENT
+    if (casing && !replaced) {
+       skip = (((all == 0) && (flag == 3)) || (flag == casing)) ? 1 : 0;
+       if (!skip && destdir) skip = 0;
+    }
+#endif /* COMMENT */
+    if (!skip) {
+       if (!ckstrcmp(old,new,-1,1))
+         skip = 1;
+    }
+    if (op == 0 && !skip && (collision != RENX_OVWR)) {
+       if (zchki(new) > (CK_OFF_T)-1) { /* New file already exists?  */
+           switch (collision) {        /* Yes, take specified action */
+             case RENX_SKIP:           /* Skip this one and proceed  */
+               skip = 2;
+               break;
+             case RENX_FAIL:           /* Or fail. */
+               skip = 3;
+               if (!listing && !nolist)
+                 printf("?File already exists: %s\n",new);
+           }
+       }
+    }
+    debug(F110,"RENAMEONE new",new,0);
+    debug(F101,"RENAMEONE flag","",flag);      
+    debug(F101,"RENAMEONE skip","",skip);      
+    debug(F100,"RENAMEONE ----------------","",0);
+
+    if (skip == 3) {
+       if (listing) printf("%s => %s (SKIPPED: %s already exists)\n",
+                           old,new,new);
+       rc = 0;
+    } else if (skip) {                 /* Skipping this one */
+       if (listing) printf("%s => %s (%s)\n",
+                           old,new,
+                           (skip == 2) ? "COLLISION: SKIPPED" : "SKIPPED");
+    } else {                           /* Have to rename this one */
+       if (op == REN_OP_CHK) {         /* Checking for collisions */
+           return((zchki(new) > (CK_OFF_T)-1) ? 0 : 1 );
+       } else if (op == REN_OP_SIM) {  /* Simulating */
+           if (listing) printf("%s => %s (SIMULATED)\n",old,new);
+       } else {                        /* Really renaming */
+           if (listing) printf("%s => %s ",old,new);
+           if (zrename(old,new) < 0) {
+               rc = 0;
+               if (listing)
+                 printf("(FAILED: %s)\n",ck_errstr());
+               else if (!nolist)
+                 printf("?%s\n",ck_errstr());
+           } else {
+               if (listing) printf("(OK)\n");
+           }
+       }
+    }
+    return(success = rc);  /* Succeeds also if nothing needed to be renamed */
+}
+
 int
 dorenam() {
-    /* Parse a file or a directory name */
-    int i, x, z, listing = 0, havename = 0, wild = 0, rc = 1;
-    int nolist = 0;
+#ifndef NOCSETS
+#ifndef NOUNICODE
+    extern int nfilc;
+    extern struct keytab fcstab[];
+    extern struct csinfo fcsinfo[];
+#endif /* NOUNICODE */
+#endif /* NOCSETS */
+    int cset1 = 0, cset2 = 0;
+
+    int i, x, z, fn, listing = 0, havename = 0, wild = 0, rc = 1, noarg = 0;
+    int nolist = 0, all = 0, casing = 0, replacing = 0, getval = 0, sim = 0;
+    int converting = 0, collision = 0;
+
+    char c;
     struct FDB sw, fi;
 
-    cmfdbi(&sw,                         /* 2nd FDB - optional /PAGE switch */
+    collision = ren_coll;              /* Inherit SET RENAME COLLISION */
+    listing = ren_list;                        /* Inhereit SET RENAME LIST */
+
+    if (ren_sub[0]) makestr(&(ren_sub[0]),NULL);
+    if (ren_sub[1]) makestr(&(ren_sub[1]),NULL);
+    if (ren_sub[2]) makestr(&(ren_sub[2]),NULL);
+    line[0] = NUL;
+    tmpbuf[0] = NUL;
+
+    cmfdbi(&sw,                         /* 1st FDB - switches */
            _CMKEY,                      /* fcode */
            "Filename or switch",        /* hlpmsg */
            "",                          /* default */
            "",                          /* addtl string data */
-           nqvswtab,                    /* addtl numeric data 1: tbl size */
+           nrenamsw,                   /* addtl numeric data 1: tbl size */
            4,                           /* addtl numeric data 2: 4 = cmswi */
            xxstring,                    /* Processing function */
-           qvswtab,                     /* Keyword table */
+           renamsw,                     /* Keyword table */
            &fi                          /* Pointer to next FDB */
            );
 
-    cmfdbi(&fi,                         /* 1st FDB - file to type */
+    cmfdbi(&fi,                         /* 2nd FDB - file or directory name */
            _CMIFI,                      /* fcode */
            "",                          /* hlpmsg */
            "",                          /* default */
            "",                          /* addtl string data */
-           3,                           /* addtl numeric data 1 */
-           0,                           /* addtl numeric data 2 */
+           3,                           /* Flags */
+           0,                           /* 0 = Parse file or directory names */
            xxstring,
            NULL,
            NULL
            );
 
+    if (cmflgs == 1) {
+       printf("?File or directory name required\n");
+       return(-9);
+    }
     while (!havename) {
+       noarg = 0;
         x = cmfdb(&sw);                 /* Parse something */
-        if (x < 0)                      /* Error */
-          return(x);
-        switch (cmresult.fcode) {
-          case _CMKEY:
-            switch (cmresult.nresult) {
-              case DEL_LIS:
-              case DEL_VRB:
+       if (x == -3) {                  /* They hit Enter prematurely */
+           printf("?Command incomplete\n");
+           return(-9);
+       } else if (x < 0) {             /* Other error */
+           if (x == -1)
+             return(x);
+            if (iswild(atmbuf) && nzxpand(atmbuf,nzxopts) == 0)
+              printf("?No files match: %s\n",brstrip(atmbuf));
+            else if (zchki(atmbuf) == -1)
+             printf("?File not found: %s\n",brstrip(atmbuf));
+           else
+             printf("?Error with switch or filename: %s\n",brstrip(atmbuf));
+           return(-9);
+       }
+       fn = cmresult.nresult;          /* For brevity */
+        switch (cmresult.fcode) {      /* Handle each kind of field */
+          case _CMKEY:                 /* Keyword (switch) */
+            c = cmgbrk();
+            if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
+                printf("?This switch does not take an argument\n");
+                return(-9);
+            }
+            if (!getval && (cmgkwflgs() & CM_ARG))
+             noarg = 1;                /* Remember arg is missing */
+            switch (cmresult.nresult) {        /* Handle the switch */
+              case DEL_LIS:            /* /LIST */
+              case DEL_VRB:            /* /VERBOSE */
                 listing = 1;
                 break;
-              case DEL_NOL:
-              case DEL_QUI:
+              case DEL_NOL:            /* /NOLIST */
+              case DEL_QUI:            /* /QUIET */
                nolist = 1;
                 listing = 0;
                 break;
+              case DEL_SIM:            /* /SIMULATE */
+                sim = 1;
+                break;
+             case REN_UPP:             /* /UPPER: */
+             case REN_LOW:             /* /LOWER */
+               all = 1;
+               if (!noarg) {
+                   if ((x = cmkey((fn == REN_UPP) ? r_upper : r_lower,
+                                  2, "","all",xxstring)) < 0) {
+                       if (x == -3)
+                         x = 1;
+                       else
+                         return(x);
+                   }
+                   all = x;
+               }
+               /* 0 = don't convert; 1 = convert to lower; 2 = to upper */
+               casing = (fn == REN_UPP) ? 2 : 1;
+               converting = 0;
+               break;
+             case REN_OVW:             /* /COLLISION */
+               if (!noarg) {
+                   if ((x = cmkey(r_collision,
+                                  nr_collision,"","overwrite",xxstring))<0) {
+                       if (x == -3)
+                         x = RENX_OVWR;
+                       else
+                         return(x);
+                   }
+                   collision = x;
+               }
+               break;
+             case REN_RPL:             /* /REPLACE: */
+               if (noarg) {
+                   printf("?This switch requires an argument\n");
+                   return(-9);
+               }
+               if ((x = cmfld("String to remove, or {{String1}{String2}}",
+                              "",&s,xxstring)) < 0) {
+                   if (x == -3) {
+                       printf("?Target string required\n");
+                       x = -9;
+                   }
+                   return(x);
+               }
+               if (s[0]) {
+                   if (s[0] == '{' && s[1] == '{') /* Get the list */
+                     makelist(s,ren_sub,3);
+                   else
+                     makestr(&(ren_sub[0]),s);
+               }
+               converting = 0;
+               break;
+
+             case REN_SPA:             /* /FIXSPACES: */
+               if (!noarg)
+                 if ((x = cmfld("Character or string to replace spaces with",
+                                "_",&s,xxstring)) < 0)
+                   if (x == -3)
+                     s = "_";
+                   else
+                     return(x);
+               makestr(&(ren_sub[0])," ");
+               makestr(&(ren_sub[1]),noarg ? "_" : brstrip(s));
+               makestr(&(ren_sub[3]),NULL);
+               converting = 0;
+               break;
+
+#ifndef NOCSETS
+#ifndef NOUNICODE
+             case REN_XLA:             /* /CONVERT:cset1:cset2 */
+               if (!xfcstab) {         /* Make a copy of the file charset */
+                   int i, x;           /* table with CM_ARG set for each */
+                   x = (nfilc + 1) * sizeof(struct keytab);
+                   xfcstab = (struct keytab *)malloc(x);
+                   if (!xfcstab) {
+                       printf("?Memory allocation failure\n");
+                       return(-9);
+                   }
+                   for (i = 0; i < nfilc; i++) {
+                       xfcstab[i].kwd = fcstab[i].kwd;
+                       xfcstab[i].kwval = fcstab[i].kwval;
+                       xfcstab[i].flgs = fcstab[i].flgs | CM_ARG;
+                   }
+               }
+               if ((x = cmswi(xfcstab,nfilc,
+                              "Character-set of old name","",xxstring)) < 0) {
+                   if (x == -3) {
+                       printf("?Pair of character-set names required\n");
+                       return(-9);
+                   } else
+                     return(x);
+               }
+               cset1 = x;
+               c = cmgbrk();
+               if (!getval) {
+                   printf("?Secondcharacter-set name required\n");
+                   return(-9);
+               }
+               if ((x = cmkey(fcstab,nfilc,
+                              "Character-set of new name","",xxstring)) < 0) {
+                   if (x == -3) {
+                       printf("?Second character-set name required\n");
+                       return(-9);
+                   } else
+                     return(x);
+               }
+               cset2 = x;
+               if (casing)
+                 casing = 0;
+               if (ren_sub[0])
+                 makestr(&(ren_sub[0]),NULL);
+               if (ren_sub[1])
+                 makestr(&(ren_sub[1]),NULL);
+               if (ren_sub[2])
+                 makestr(&(ren_sub[2]),NULL);
+               converting = 1;
+               break;
+#endif /* NOUNICODE */
+#endif /* NOCSETS */
             }
             break;
-          case _CMIFI:
+          case _CMIFI:                 /* File or directory name */
             s = cmresult.sresult;
             havename = 1;
             break;
           default:
-            return(-2);
+           printf("?File or directory name required\n");
+           return(-9);
         }
     }
+    if (havename) {
+       ckstrncpy(line,s,LINBUFSIZ);    /* Make a safe copy of source name */
+    } else {
+       printf("?Internal error\n");
+       return(-9);                     /* Shouldn't happen */
+    }
     wild = cmresult.nresult;            /* Source specification wild? */
-
-    ckstrncpy(line,s,LINBUFSIZ);        /* Make a safe copy of source name */
-    s = line;
-
     if (!wild)
       wild = iswild(line);
 
+    debug(F111,"RENAME WILD",line,wild);
+
     p = tmpbuf;                         /* Place for new name */
+    p[0] = NUL;
+    replacing = ren_sub[0] ? 1 : 0;
+
+#ifdef COMMENT
+    if (!(casing || replacing || converting)) {
+       if ((x = cmofi(wild ? "Target directory" : "New name",
+                      "",&s,xxstring)) < 0) { /* Get new name */
+           if (x == -3) {
+               printf("?%s required\n",
+                      wild ? "Target directory" : "New name");
+               return(-9);
+           } else return(x);
+       }
+       ckstrncpy(p,s,TMPBUFSIZ);       /* Make a safe copy of the new name */
+    }
+#else
     if ((x = cmofi(wild ? "Target directory" : "New name",
-                   "",&s,xxstring)) < 0) { /* Get new name */
-        if (x == -3) {
-            printf("?%s required\n", wild ? "Target directory" : "New name");
-            return(-9);
-        } else return(x);
+                  "",&s,xxstring)) < 0) { /* Get new name */
+       if (x == -3) {
+           if (casing || replacing || converting) {
+               s = "";
+           } else {
+               printf("?%s required\n",
+                      wild ? "Target directory" : "New name");
+               return(-9);
+           }
+       } else return(x);
     }
-    ckstrncpy(p,s,TMPBUFSIZ);           /* Make a safe copy of the new name */
-    if ((y = cmcfm()) < 0) return(y);
+    ckstrncpy(p,s,TMPBUFSIZ);          /* Make a safe copy of the new name */
+#endif /* COMMENT */
 
-    if (!wild) {                        /* Just one */
-        if (listing) printf("%s => %s ",line,p);
-        if (zrename(line,p) < 0) {
-            if (listing)
-             printf("(FAILED: %s)\n",ck_errstr());
-           else if (!nolist)
-             printf("?%s\n",ck_errstr());
-            rc = 0;
-        } else {
-            if (listing) printf("(OK)\n");
-        }
-        return(success = rc);
+    if ((y = cmcfm()) < 0) return(y);  /* Confirm the command */
+
+#ifdef COMMENT
+#ifndef NOUNICODE
+    if (converting) {
+       printf(" From: %s\n",fcsinfo[cset1].keyword);
+       printf(" To:   %s\n",fcsinfo[cset2].keyword);
     }
-    if (!isdir(p)) {                    /* Multiple */
-        printf(                         /* if target is not a directory */
+#endif /* NOUNICODE */
+    if (casing) {
+       printf("CASING: %s\n", (casing == 1) ? "LOWER" : "UPPER");
+    }
+    if (replacing) {
+       printf("REPLACING: '%s' with '%s'\n",
+              ren_sub[0],
+              ren_sub[1] ? ren_sub[1] : "");
+    }
+#endif /* COMMENT */
+
+    s = line;
+    if (!wild)                         /* Just one */
+      return(success =
+            renameone(s,p,
+                      replacing,casing,all,converting,cset1,cset2,
+                      listing,nolist,sim,TMPBUFSIZ,collision));
+
+    if (!casing && !replacing && !converting) {        /* Multiple files */
+       if (!isdir(p)) {
+           printf(                     /* if target is not a directory */
 "?Multiple source files not allowed if target is not a directory.\n");
-        return(-9);
+           return(-9);
+       }
     }
 #ifdef COMMENT
     else {                              /* Show full path of target */
@@ -8167,26 +9205,45 @@ dorenam() {
       sh_sort(mtchs,NULL,z,0,0,filecase); /* Alphabetize the filename list */
 #endif /* UNIX */
 
-/*
-  Note: COPY, RENAME, DELETE and similar commands should have options to
-  stop or proceed when they are operating on multiple files and the operation
-  fails.
-*/
-    while (z-- > 0) {
+    /* For /COLLISION:FAIL make a silent pass to see if there would be any */
+
+    if (collision == RENX_FAIL) {
+       int n = 0;
+       char line[CKMAXPATH+2];
+       while (z-- > 0) {
+           if (!(z == 0 && !wild))
+             znext(line);
+           if (!line[0])
+             break;
+           if (!renameone((char *)line,p,
+                          replacing,casing,all,converting,cset1,cset2,
+                          0,1,REN_OP_CHK,TMPBUFSIZ,RENX_FAIL))
+             n++;
+       }
+       if (n > 0) {
+           printf("?Failed: %d file%s would be overwritten\n",
+                  n, (n != 1) ? "s" : "");
+#ifdef VMS
+           concb((char)escape);
+#endif /* VMS */
+           return(success = 0);
+       }
+       /* Get the file list back. */
+#ifdef ZXREWIND
+       z = zxrewind();
+#else
+       z = nzxpand(s,0);
+#endif /* ZXREWIND */
+    }
+    while (z-- > 0 && rc > 0) {
+       char line[CKMAXPATH+2];
         if (!(z == 0 && !wild))
           znext(line);
         if (!line[0])
           break;
-        if (listing) printf("%s => %s ",line,p);
-        if (zrename(line,p) < 0) {
-            if (listing)
-             printf("(FAILED: %s)\n",ck_errstr());
-           else if (!nolist)
-             printf("?%s - %s\n",ck_errstr(),line);
-            rc = 0;
-        } else {
-            if (listing) printf("(OK)\n");
-        }
+       rc = renameone((char *)line,p, 
+                      replacing,casing,all,converting,cset1,cset2,
+                      listing,nolist,sim,TMPBUFSIZ,collision);
     }
 #ifdef VMS
     concb((char)escape);
@@ -8428,17 +9485,14 @@ doxget(cx) int cx; {
 #endif /* PIPESEND */
     extern struct keytab rpathtab[];
     extern int nrpathtab;
-    extern long calibrate;
+    extern CK_OFF_T calibrate;
     int asname = 0;                     /* Flag for have as-name */
     int konly = 0;                      /* Kermit-only function */
     int c, i, n, confirmed = 0;         /* Workers */
     int getval = 0;                     /* Whether to get switch value */
     int rcvcmd = 0;                     /* Whether it is the RECEIVE command */
     int mget = 0;                       /* Whether it is the MGET command */
-    struct stringint {                  /* Temporary array for switch values */
-        char * sval;
-        int ival;
-    } pv[SND_MAX+1];
+    struct stringint pv[SND_MAX+1];    /* Temporary array for switch values */
     struct FDB sw, fl, cm;              /* FDBs for each parse function */
     char * cmdstr = "this command";
 
@@ -8446,8 +9500,15 @@ doxget(cx) int cx; {
     if (cx == XXGET || cx == XXREGET || cx == XXMGET || cx == XXRETR) {
         extern int ftpget;
         extern int ftpisopen();
-        if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
-          return(doftpget(cx,0));
+        if ((ftpget == 1) || ((ftpget == 2) && ftpisopen())) {
+           int x;
+           x = doftpget(cx,0);
+           debug(F101,"doftpget return","",x);
+           if (x > -1)
+             success = x;
+           debug(F101,"doftpget success","",success);
+           return(x);
+       }
     }
 #endif /* NEWFTP */
 
@@ -8459,6 +9520,7 @@ doxget(cx) int cx; {
     for (i = 0; i <= SND_MAX; i++) {    /* Initialize switch values */
         pv[i].sval = NULL;
         pv[i].ival = -1;
+        pv[i].wval = (CK_OFF_T)-1;
     }
     /* Preset switch values based on top-level command that called us */
 
@@ -8534,6 +9596,7 @@ doxget(cx) int cx; {
            "",                          /* addtl string data */
            0,                           /* addtl numeric data 1 */
            0,                           /* addtl numeric data 2 */
+#ifdef COMMENT
 #ifdef CK_XYZ
            (protocol == PROTO_X || protocol == PROTO_XC) ?
              xxstring :
@@ -8541,6 +9604,9 @@ doxget(cx) int cx; {
 #else
            rcvcmd ? (xx_strp)0  : xxstring /* Processing function */
 #endif /* CK_XYZ */
+#else  /* COMMENT */
+          xxstring                     /* Always evaluate - fdc 2006/02/01 */
+#endif /* COMMENT */
              ,
            NULL,
            &cm
@@ -8728,7 +9794,13 @@ doxget(cx) int cx; {
                 x = -9;
                 goto xgetx;
             }
-            if ((x = cmfld("Name to store it under","",&s,NULL)) < 0)
+            if (
+#ifdef COMMENT
+               (x = cmfld("Name to store it under","",&s,NULL))
+#else
+               (x = cmfld("Name to store it under","",&s,xxstring))
+#endif /* COMMENT */
+               < 0)
               goto xgetx;
             s = brstrip(s);
             if ((y = strlen(s)) > 0) {
@@ -9143,7 +10215,7 @@ doxget(cx) int cx; {
 
 #ifdef CALIBRATE
     if (pv[SND_CAL].ival > 0)
-      calibrate = 1L;
+      calibrate = (CK_OFF_T)1;
 #endif /* CALIBRATE */
     g_displa = fdispla;
     if (pv[SND_SHH].ival > 0)
@@ -9197,7 +10269,8 @@ doxget(cx) int cx; {
     if (local) {
         if (pv[SND_SHH].ival != 0)
           displa = 1;
-        ttflui();
+       if (protocol == PROTO_K)        /* fdc 20070108 */
+         ttflui();
     }
     x = 0;
 #ifdef PIPESEND
@@ -9356,6 +10429,7 @@ dogta(cx) int cx; {
             takerr[cmdlvl - 2] = takerr[cmdlvl];
             merror[cmdlvl - 2] = merror[cmdlvl];
             xquiet[cmdlvl - 2] = xquiet[cmdlvl];
+            xvarev[cmdlvl - 2] = xvarev[cmdlvl];
         } else return(success = 0);     /* Bad call to this routine */
     }
     if (cx == XXPTA) {                  /* Restore interrupts if we */
@@ -9400,20 +10474,15 @@ dogta(cx) int cx; {
   Do the GOTO and [_]FORWARD commands.
   s = Label to search for, cx = function code: XXGOTO, XXFWD, or XXXFWD.
 */
-#ifdef BIGBUFOK
-#define LBLMAXLEN 255                   /* Max label length */
-#else
-#define LBLMAXLEN 63
-#endif /* BIGBUFOK */
 
 int
 dogoto(s, cx) char *s; int cx; {
     int i, j, x, y, z, bc;
     int empty = 0, stopflg = 0;
     char * cmd;                         /* Name of this command */
-    char tmplbl[LBLMAXLEN+1], *lp;      /* Current label from command stream */
-    char tmp2[LBLMAXLEN+1];             /* SWITCH label conversion buffer */
-    char tmp3[LBLMAXLEN+1];             /* Target label */
+    char tmplbl[LBLSIZ+1], *lp;                /* Current label from command stream */
+    char tmp2[LBLSIZ+1];               /* SWITCH label conversion buffer */
+    char tmp3[LBLSIZ+1];               /* Target label */
 
     stopflg = (cx == XXXFWD);           /* _FORWARD (used in SWITCH) */
     bc = 0;                             /* Brace counter */
@@ -9432,7 +10501,15 @@ dogoto(s, cx) char *s; int cx; {
     }
 #endif /* DEBUG */
     debug(F110,cmd,s,0);
-    ckstrncpy(tmp3+1,s,LBLMAXLEN-1);
+    x = ckstrncpy(tmp3+1,s,LBLSIZ);
+    debug(F101,"GOTO target len","",x);
+    debug(F101,"GOTO target at x","",s[x]);
+    if (s[x]) {
+       debug(F100,"GOTO target overflow","",0);
+       printf("?GOTO target or SWITCH case label too long\n");
+       if (stopflg) dostop();          /* If in SWITCH return to prompt */
+       return(success = 0);
+    }
     s = tmp3+1;
     if (*s != ':') {                    /* Make copy of label */
         tmp3[0] = ':';                  /* guaranteed to start with ":" */
@@ -9441,6 +10518,7 @@ dogoto(s, cx) char *s; int cx; {
     if (!stopflg && !empty) {
         if (s[1] == '.' || s[1] == SP || s[1] == NUL) {
             printf("?Bad label syntax - '%s'\n",s);
+           if (stopflg) dostop();      /* If in SWITCH return to prompt */
             return(success = 0);
         }
     }
@@ -9459,8 +10537,8 @@ dogoto(s, cx) char *s; int cx; {
             /* GOTO: rewind the macro; FORWARD: start at current position */
 
             lp = (cx == XXGOTO) ? macx[maclvl] : macp[maclvl];
-            m = (int)strlen(lp) - y + 1;
-            debug(F010,"GOTO in macro",lp,0);
+            m = (int)strlen(lp);
+            debug(F111,"GOTO in macro",lp,m);
 
             flag = 1;                   /* flag for valid label position */
             for (i = 0; i < m; i++,lp++) { /* search for label in macro body */
@@ -9487,13 +10565,12 @@ dogoto(s, cx) char *s; int cx; {
                 xp = lp; tp = tmplbl;   /* Copy the label from the macro */
                 j = 0;                  /* to make it null-terminated */
                 while ((*tp = *xp)) {
-                    if (j++ > LBLMAXLEN) /* j = length of word from macro */
-                      break;
-#ifdef COMMENT
-                    if (*tp < 33 || *tp == ',') /* Look for end of word */
-#else
-                    if (!*tp || *tp == ',')     /* Look for end of word */
-#endif /* COMMENT */
+                    if (j++ > LBLSIZ-1) { /* j = length of word from macro */
+                       printf("?GOTO target or SWITCH case label too long\n");
+                       if (stopflg) dostop(); /* Return to prompt */
+                       return(success = 0);
+                   }
+                    if (!*tp || *tp == ',') /* Look for end of word */
                       break;
                     else tp++, xp++;    /* Next character */
                 }
@@ -9502,15 +10579,19 @@ dogoto(s, cx) char *s; int cx; {
                 debug(F111,"macro GOTO label",s,y);
                 debug(F111,"macro target label",tmplbl,j);
                 if (stopflg) {          /* Allow variables as SWITCH labels */
-                    int n = LBLMAXLEN - 1;
+                    int n = LBLSIZ - 1;
                     char * p = tmp2;
                     zzstring(tmplbl,&p,&n);
-                    ckstrncpy(tmplbl,tmp2,LBLMAXLEN);
-                    tmp2[49] = NUL;
+                   if (n < 0) {
+                       printf("?GOTO target or SWITCH case label too long\n");
+                       if (stopflg) dostop(); /* Return to prompt */
+                       return(0);
+                   }
+                    ckstrncpy(tmplbl,tmp2,LBLSIZ);
                 }
                 debug(F111,"GOTO s",s,y);
                 debug(F111,"GOTO tmplbl",tmplbl,j);
-                debug(F101,"GOTO empty",ckitoa(stopflg),empty);
+                debug(F111,"GOTO empty",ckitoa(stopflg),empty);
 
                 if (empty) {              /* Empty target */
                    z = (!strcmp(s,":") && /* String is empty */
@@ -9791,15 +10872,43 @@ boolexp(cx) int cx; {
     }
     debug(F111,"boolval switch","",cmresult.fcode);
     switch (cmresult.fcode) {           /* What did we get? */
+      case _CMFLD: {                   /* A "field" */
+         int i;
+         char * s;
+         s = cmresult.sresult;
+/*
+  C-Kermit 9.0: This allows a macro name to serve as an
+  IF condition without having to enclose it in \m(...).
+*/
+         if (
+#ifdef FNFLOAT   
+             !isfloat(cmresult.sresult,0) /* Not a number */
+#else
+             !chknum(cmresult.sresult) /* Not a number */
+#endif /* FNFLOAT */
+             ) {
+             i = mlook(mactab,cmresult.sresult,nmac); /* Look it up */
+             if (i > -1)               /* in the macro table */
+               s = mactab[x].mval;     /* and get its value */
+             else                      /* Otherwise if no such macro */
+               s = "0";                /* evaluate as FALSE. */
+         }
 #ifdef FNFLOAT
-      case _CMFLD:                      /* A "field" */
-        if (isfloat(cmresult.sresult,0)) { /* A floating-point number? */
+        if (isfloat(s,0)) {            /* A floating-point number? */
             f1 = floatval;              /* Yes, get its value */
             f1flag = 1;                 /* remember we did this */
             ifc = 9999;                 /* Set special "if-code" */
-        } else
-          return(-2);
+        }
+#else
+       if (chknum(s)) {
+           cmresult.nresult = atoi(s);
+           ifc = 9999;
+           break;
+       }
 #endif /* FNFLOAT */
+       else
+         return(-2);
+      }
       case _CMNUM:                      /* A number... */
         ifc = 9999;                     /* Set special "if-code" */
         break;
@@ -9993,6 +11102,7 @@ boolexp(cx) int cx; {
       case XXIFDI:                      /* IF DIRECTORY */
 #endif /* CK_TMPDIR */
       case XXIFAB:                      /* IF ABSOLUTE */
+      case XXIFLN:                     /* IF LINK */
         if ((x = cmfld(
                        ((ifc == XXIFDI) ? "Directory name" : "File"),
                        "",&s,
@@ -10011,6 +11121,11 @@ boolexp(cx) int cx; {
             } else return(x);
         }
         s = brstrip(s);
+#ifdef UNIX
+       if (ifc == XXIFLN) {
+           z = isalink(s);
+       } else
+#endif /* UNIX */
         if (ifc == XXIFAB) {
             z = isabsolute(s);
         } else if (ifc == XXIFEX) {
@@ -10114,11 +11229,12 @@ boolexp(cx) int cx; {
       case XXIFGE:                      /* IF >= */
       case XXIFGT: {                    /* IF >  */
 
-        /* Really should use longs here... */
-        /* But cmnum parses ints. */
-        int xx, n1 = 0, n2 = 0;
+         /* July 2006 - converted to use CK_OFF_T rather than int to */
+          /* allow long integers on platforms that have ck_off_t > 32 bits */
+         int xx;
+         CK_OFF_T n1 = (CK_OFF_T)0, n2 = (CK_OFF_T)0;
         if (ifc == XXIFVE) {
-            n1 = (int) vernum;
+            n1 = (CK_OFF_T) vernum;
         } else {
             x = cmfld("first number or variable name","",&s,xxstring);
             if (x == -3) {
@@ -10134,11 +11250,11 @@ boolexp(cx) int cx; {
 /* The following bit is for compatibility with old versions of MS-DOS Kermit */
 
             if (!ckstrcmp(lp,"count",5,0)) {
-                n1 = count[cmdlvl];
+                n1 = (CK_OFF_T)count[cmdlvl];
             } else if (!ckstrcmp(lp,"version",7,0)) {
-                n1 = (int) vernum;
+                n1 = (CK_OFF_T) vernum;
             } else if (!ckstrcmp(lp,"argc",4,0)) {
-                n1 = (int) macargc[maclvl];
+                n1 = (CK_OFF_T) macargc[maclvl];
             } else {
 
 /* End of compatibility bit */
@@ -10150,13 +11266,15 @@ boolexp(cx) int cx; {
                 } else
 #endif /* FNFLOAT */
                   if (chknum(lp)) {
-                      n1 = atoi(lp);
+                      n1 = ckatofs(lp);
                   } else {              /* Check for arithmetic expression */
                       q = evala(lp);    /* cmnum() does this but ... */
-                      if (chknum(q))    /* we're not using cmnum(). */
-                        n1 = atoi(q);
-                      else
-                        return(-2);
+                      if (chknum(q)) { /* we're not using cmnum(). */
+                         n1 = ckatofs(q);
+                     } else {
+                         printf("?Value not numeric - %s", lp);
+                         return(-9);
+                     }
                   }
             }
         }
@@ -10177,11 +11295,11 @@ boolexp(cx) int cx; {
         ckstrncpy(tp,s,LINBUFSIZ-x-2);
         debug(F110,"xxifgt exp2",tp,0);
         if (!ckstrcmp(tp,"count",5,0)) {
-            n2 = count[cmdlvl];
+            n2 = (CK_OFF_T) count[cmdlvl];
         } else if (!ckstrcmp(tp,"version",7,0)) {
-            n2 = (int) vernum;
+            n2 = (CK_OFF_T) vernum;
         } else if (!ckstrcmp(tp,"argc",4,0)) {
-            n2 = (int) macargc[maclvl];
+            n2 = (CK_OFF_T) macargc[maclvl];
         } else {
 #ifdef FNFLOAT
             if (isfloat(tp,0) > 1) {
@@ -10190,13 +11308,15 @@ boolexp(cx) int cx; {
             } else
 #endif /* FNFLOAT */
             if (chknum(tp)) {
-                n2 = atoi(tp);
+                n2 = ckatofs(tp);
             } else {
                 q = evala(tp);
-                if (chknum(q))
-                  n2 = atoi(q);
-                else
-                  return(-2);
+               if (chknum(q)) {        /* we're not using cmnum(). */
+                   n2 = ckatofs(q);
+               } else {
+                   printf("?Value not numeric - %s", tp);
+                   return(-9);
+               }
             }
         }
         xx = (ifc == XXIFVE) ? XXIFGE : ifc;
@@ -10568,10 +11688,20 @@ boolexp(cx) int cx; {
 
       case XXIFKG: {                    /* KERBANG */
           extern int cfilef;
-          z = (xcmdsrc == 0) ? 0 : cfilef;
+#ifdef COMMENT
+          z = (xcmdsrc == 0) ? 0 : (cfilef && cmdlvl == 1);
+#else
+          z = (xcmdsrc == 0) ? 0 : (cfilef && tlevel == 0);
+#endif /* COMMENT */
           break;
       }
 
+      case XXIFDB: {                   /* IF DEBUG - 2010/03/16 */
+          extern int debmsg;
+          z = debmsg;
+         break;
+      }
+
       default:                          /* Shouldn't happen */
         return(-2);
     } /* end of switch */
@@ -10856,6 +11986,7 @@ dotake(s) char *s; {
         takerr[cmdlvl] = takerr[cmdlvl-1]; /* Inherit this */
         merror[cmdlvl] = merror[cmdlvl-1]; /* Inherit this */
         xquiet[cmdlvl] = quiet;
+        xvarev[cmdlvl] = vareval;
         xcmdsrc = CMD_TF;
         cmdstk[cmdlvl].src = CMD_TF;    /* Say we're in a TAKE file */
         cmdstk[cmdlvl].lvl = tlevel;    /* nested at this level */
index 4268ef1..1e74ab6 100644 (file)
--- a/ckuus7.c
+++ b/ckuus7.c
@@ -9,7 +9,7 @@
     Jeffrey E Altman <jaltman@secure-endpoints.com>
       Secure Endpoints Inc., New York City
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2011,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -66,6 +66,7 @@
 #endif /* putchar */
 #define putchar(x) conoc(x)
 extern int mskkeys;
+extern int mskrename;
 #endif /* OS2 */
 
 #ifdef CK_AUTHENTICATION
@@ -98,6 +99,12 @@ extern int g_matchdot, hints, xcmdsrc, rcdactive;
 
 extern char * k_info_dir;
 
+#ifdef CK_LOGIN
+#ifdef CK_PAM
+int gotemptypasswd = 0;   /* distinguish empty passwd from none given */
+#endif /* CK_PAM */
+#endif /* CK_LOGIN */
+
 #ifndef NOSPL
 extern int nmac;
 extern struct mtab *mactab;
@@ -528,11 +535,13 @@ static struct keytab tcprawtab[] = {    /* SET HOST options */
 #endif /* RLOGCODE */
 #ifdef CK_SSL
     { "/ssl",        NP_SSL,    0 },
+    { "/ssl-raw",    NP_SSL_RAW, 0 },
     { "/ssl-telnet", NP_SSL_TELNET, 0 },
 #endif /* CK_SSL */
     { "/telnet",     NP_TELNET, 0 },
 #ifdef CK_SSL
     { "/tls",        NP_TLS,    0 },
+    { "/tls-raw",    NP_TLS_RAW, 0 },
     { "/tls-telnet", NP_TLS_TELNET, 0 },
 #endif /* CK_SSL */
     { "", 0, 0 }
@@ -859,10 +868,11 @@ struct keytab colxtab[] = { /* SET FILE COLLISION options */
     { "backup",    XYFX_B, 0 },         /* rename old file */
 #ifndef MAC
     /* This crashes Mac Kermit. */
-    { "discard",   XYFX_D, 0 },         /* don't accept new file */
+    { "discard",   XYFX_D, CM_INV },   /* don't accept new file */
     { "no-supersede", XYFX_D, CM_INV }, /* ditto (MSK compatibility) */
 #endif /* MAC */
     { "overwrite", XYFX_X, 0 },         /* overwrite the old file */
+    { "reject",    XYFX_D, 0 },                /* (better word than discard) */
     { "rename",    XYFX_R, 0 },         /* rename the incoming file */
 #ifndef MAC                             /* This crashes Mac Kermit. */
     { "update",    XYFX_U, 0 },         /* replace if newer */
@@ -971,6 +981,7 @@ static struct keytab trmtab[] = {
     { "keyboard-mode", XYTKBMOD,  0 },
     { "keypad-mode",   XYTKPD,    0 },
 #endif /* OS2 */
+    { "lf-display",    XYTLFD,    0 },
 #ifndef NOCSETS
 #ifdef OS2
 #ifndef KUI
@@ -1205,6 +1216,7 @@ struct keytab crdtab[] = {              /* Carriage-return display */
     { "normal",      0, 0 }
 };
 extern int tt_crd;                      /* Carriage-return display variable */
+extern int tt_lfd;                     /* Linefeed display variable */
 
 #ifdef CK_APC
 extern int apcstatus, apcactive;
@@ -1329,8 +1341,8 @@ int tt_arrow = TTK_NORM;                /* Arrow key mode: normal (cursor) */
 int tt_keypad = TTK_NORM;               /* Keypad mode: normal (numeric) */
 int tt_shift_keypad = 0;                /* Keypad Shift mode: Off */
 int tt_wrap = 1;                        /* Terminal wrap, 1 = On */
-int tt_type = TT_VT320;                 /* Terminal type, initially VT320 */
-int tt_type_mode = TT_VT320;            /* Terminal type set by host command */
+int tt_type = TT_VT220;                 /* Terminal type, initially VT220 */
+int tt_type_mode = TT_VT220;            /* Terminal type set by host command */
 int tt_cursor = 0;                      /* Terminal cursor, 0 = Underline */
 int tt_cursor_usr = 0;                  /* Users Terminal cursor type */
 int tt_cursorena_usr = 1;               /* Users Terminal cursor enabled */
@@ -2002,6 +2014,7 @@ struct keytab msktab[] = { /* SET MS-DOS KERMIT compatibilities */
 #ifdef COMMENT
     { "color",    MSK_COLOR,  0 },
 #endif /* COMMENT */
+    { "file-renaming", MSK_REN, 0 },
     { "keycodes", MSK_KEYS,   0 }
 };
 int nmsk = (sizeof(msktab) / sizeof(struct keytab));
@@ -2690,7 +2703,7 @@ dopurge() {                             /* Do the PURGE command */
     int xx[MAXKEEP+1];                  /* Array of numbers to keep */
     int min = -1;
     int x_hdg = 0, fs = 0, rc = 0;
-    long minsize = -1L, maxsize = -1L;
+    CK_OFF_T minsize = -1L, maxsize = -1L;
     char namebuf[CKMAXPATH+4];
     char basebuf[CKMAXPATH+4];
     char
@@ -2981,7 +2994,7 @@ dopurge() {                             /* Do the PURGE command */
     if (n < tokeep) {                   /* Not deleting any */
         count = 0;
         if (listing)
-          printf(" Matches = %d: Not enough to purge.\n");
+          printf(" Matches = %d: Not enough to purge.\n",n);
         goto xpurge;
     }
 
@@ -3141,7 +3154,7 @@ doxdis(which) int which; {                /* 1 = Kermit, 2 = FTP */
     if (which == 1)                    /* It's OK. */
       fdispla = x;
 #ifdef NEWFTP
-    else
+    else if (which == 2)
       ftp_dis = x;
 #endif /* NEWFTP */
     return(success = 1);
@@ -3797,26 +3810,71 @@ setfil(rmsflg) int rmsflg; {
     }
 }
 
-#ifndef NOLOCAL
-#ifdef OS2
-/* MS-DOS KERMIT compatibility modes */
+#ifdef UNIX
+#ifndef NOPUTENV
+#ifdef BIGBUFOK
+#define NPUTENVS 4096
+#else
+#define NPUTENVS 128
+#endif /* BIGBUFOK */
+/* environment variables must be static, not automatic */
+
+static char * putenvs[NPUTENVS];       /* Array of environment var strings */
+static int nputenvs = -1;              /* Pointer into array */
+/*
+  If anyone ever notices the limitation on the number of PUTENVs, the list
+  can be made dynamic, we can recycle entries with the same name, etc.
+*/
 int
-setmsk() {
-    if ((y = cmkey(msktab,nmsk,"MS-DOS Kermit compatibility mode",
-                    "keycodes",xxstring)) < 0) return(y);
+doputenv(s1, s2) char * s1; char * s2; {
+    char * s, * t = tmpbuf;            /* Create or alter environment var */
+
+    if (nputenvs == -1) {              /* Table not used yet */
+       int i;                          /* Initialize the pointers */
+       for (i = 0; i < NPUTENVS; i++)
+         putenvs[i] = NULL;
+       nputenvs = 0;
+    }
+    if (!s1) return(1);                        /* Nothing to do */
+    if (!*s1) return(1);               /* ditto */
+
+    if (ckindex("=",s1,0,0,0)) {       /* Does the name contain an '='? */
+       printf(                         /* putenv() does not allow this. */
+        /* This also catches the 'putenv name=value' case */
+         "?PUTENV - Equal sign in variable name - 'help putenv' for info.\n");
+        return(-9);
+    }
+    nputenvs++;                                /* Point to next free string */
 
-    switch ( y ) {
-#ifdef COMMENT
-      case MSK_COLOR:
-        return(seton(&mskcolors));
-#endif /* COMMENT */
-      case MSK_KEYS:
-        return(seton(&mskkeys));
-      default:                          /* Shouldn't get here. */
-        return(-2);
+    debug(F111,"doputenv s1",s1,nputenvs);
+    debug(F111,"doputenv s2",s2,nputenvs);
+
+    if (nputenvs > NPUTENVS - 1) {     /* Notice the end */
+       printf("?PUTENV - static buffer space exhausted\n");
+       return(-9);
+    }
+    /* Quotes are not needed but we allow them for familiarity */
+    /* but then we strip them, so syntax is same as for Unix shell */
+
+    if (s2) {
+       s2 = brstrip(s2);
+    } else {
+       s2 = (char *)"";
     }
+    ckmakmsg(t,TMPBUFSIZ,s1,"=",s2,NULL);
+    debug(F111,"doputenv",t,nputenvs);
+    (VOID) makestr(&(putenvs[nputenvs]),t); /* Make a safe permananent copy */
+    if (!putenvs[nputenvs]) {
+       printf("?PUTENV - memory allocation failure\n");
+       return(-9);
+    }
+    if (putenv(putenvs[nputenvs])) {
+       printf("?PUTENV - %s\n",ck_errstr());
+       return(-9);
+    } else return(success = 1);
 }
-#endif /* OS2 */
+#endif /* NOPUTENV */
+#endif /* UNIX */
 
 int
 settrmtyp() {
@@ -3825,7 +3883,7 @@ settrmtyp() {
     extern int ttnum;                    /* Last Telnet Terminal Type sent */
     extern int ttnumend;                 /* Has end of list been found */
 #endif /* TNCODE */
-    if ((x = cmkey(ttyptab,nttyp,"","vt320",xxstring)) < 0)
+    if ((x = cmkey(ttyptab,nttyp,"","vt220",xxstring)) < 0)
       return(x);
     if ((y = cmcfm()) < 0)
       return(y);
@@ -3837,13 +3895,52 @@ settrmtyp() {
 #endif /* TNCODE */
     return(success = 1);
 #else  /* Not OS2 */
+#ifdef UNIX
+    extern int fxd_inited;
+    x = cmtxt("Terminal type name, case sensitive","",&s,NULL);
+#ifdef NOPUTENV
+    success = 1;
+#else
+    success = doputenv("TERM",s);      /* Set the TERM variable */
+#ifdef CK_CURSES
+    fxd_inited = 0;           /* Force reinitialization of curses database */
+    (void)doxdis(0);                /* Re-initialize file transfer display */
+    concb((char)escape);               /* Fix command terminal */
+#endif /* CK_CURSES */
+#endif /* NOPUTENV */
+    return(success);
+#else
     printf(
 "\n Sorry, this version of C-Kermit does not support the SET TERMINAL TYPE\n");
     printf(
 " command.  Type \"help set terminal\" for further information.\n");
-#endif /* OS2 */
     return(success = 0);
+#endif /* UNIX */
+#endif /* OS2 */
+}
+
+#ifndef NOLOCAL
+#ifdef OS2
+/* MS-DOS KERMIT compatibility modes */
+int
+setmsk() {
+    if ((y = cmkey(msktab,nmsk,"MS-DOS Kermit compatibility mode",
+                    "keycodes",xxstring)) < 0) return(y);
+
+    switch ( y ) {
+#ifdef COMMENT
+      case MSK_COLOR:
+        return(seton(&mskcolors));
+#endif /* COMMENT */
+      case MSK_KEYS:
+        return(seton(&mskkeys));
+      case MSK_REN:
+        return(seton(&mskrename));
+      default:                          /* Shouldn't get here. */
+        return(-2);
+    }
 }
+#endif /* OS2 */
 
 #ifdef CKTIDLE
 static char iactbuf[132];
@@ -3867,7 +3964,7 @@ getiact() {
           q = &iactbuf[k];
           p = tt_idlestr;
           if (!p) p = "";
-          if (!*p) return("output (nothing)");
+          if (!*p) return("output NUL");
           while ((c = *p++) && n < 131) {
               c &= 0xff;
               if (c == '\\') {
@@ -3876,7 +3973,7 @@ getiact() {
                   *q++ = '\\';
                   *q = NUL;
                   n += 2;
-              } else if ((c > 31 && c < 127) || c > 159) {
+              } else if ((c > 32 && c < 127) || c > 159) {
                   *q++ = c;
                   *q = NUL;
                   n++;
@@ -4522,6 +4619,12 @@ settrm() {
         tt_crd = x;
         return(success = 1);
 
+      case XYTLFD:                      /* SET TERMINAL LF-DISPLAY */
+        if ((x = cmkey(crdtab,2,"", "normal", xxstring)) < 0) return(x);
+        if ((y = cmcfm()) < 0) return(y);
+        tt_lfd = x;
+        return(success = 1);
+
 #ifdef OS2
       case XYTANS: {                    /* SET TERMINAL ANSWERBACK */
 /*
@@ -4721,7 +4824,7 @@ settrm() {
             return(y);
           if (y == IDLE_OUT) {
               if ((x = cmtxt("string to send, may contain kverbs and variables"
-                             , "\\v(newline)",&s,xxstring)) < 0)
+                             , "",&s,xxstring)) < 0)
                 return(x);
               makestr(&tt_idlestr,brstrip(s)); /* (new) */
               tt_idlesnd_str = tt_idlestr; /* (old) */
@@ -5829,7 +5932,7 @@ settrm() {
     return(-2);
 #endif /* COMMENT */
 #ifdef OS2
-return(-2);
+    return(-2);
 #endif /* OS2 */
 }
 
@@ -7071,7 +7174,22 @@ or type carriage return to confirm the command",
     debug(F101,"remcfm local","",local);
     debug(F110,"remcfm s",s,0);
     debug(F101,"remcfm cmd","",xzcmd);
-
+/* 
+  This check was added in C-Kermit 6.0 or 7.0 but it turns out to be
+  unhelpful in the situation where the remote is running a script that sends
+  REMOTE commands to the local workstation.  What happens is, the local
+  server executes the command and sends the result back as screen text, which
+  is indicated by using an X packet instead of an F packet as the file
+  header.  There are two parts to this: executing the command under control
+  of the remote Kermit, which is desirable (and in fact some big applications
+  depend on it, and therefore never installed any new C-Kermit versions after
+  5A), and displaying the result.  Commenting out the check allows the
+  command to be executed, but the result is still sent back to the remote in
+  a file transfer, where it vanishes into the ether.  Actually it's on the
+  communication connection, mixed in with the packets.  Pretty amazing that
+  the file transfer still works, right?
+*/
+#ifdef COMMENT
     if (!*s) {                          /* No redirection indicator */
         if (!local &&
             (xzcmd == XZDIR || xzcmd == XZTYP ||
@@ -7084,6 +7202,7 @@ or type carriage return to confirm the command",
         } else
           return(1);
     }
+#endif /* COMMENT */
     c = *s;                             /* We have something */
     if (c != '>' && c != '|') {         /* Is it > or | ? */
         printf("?Not confirmed\n");     /* No */
@@ -7171,6 +7290,7 @@ remtxt(p) char ** p; {
     s = *p;
     if (!s)                             /* No redirection indicator */
       s = "";
+#ifdef COMMENT
     if (!*s) {                          /* Ditto */
         if (!local &&
             (xzcmd == XZDIR || xzcmd == XZTYP ||
@@ -7186,6 +7306,7 @@ remtxt(p) char ** p; {
         } else
           return(1);
     }
+#endif /* COMMENT */
     bpos = -1;                          /* Position of > (bracket) */
     ppos = -1;                          /* Position of | (pipe) */
     x = strlen(s);                      /* Length of cmtxt() string */
@@ -7200,6 +7321,7 @@ remtxt(p) char ** p; {
           ppos = i;
     }
     if (bpos < 0 && ppos < 0) {         /* No redirectors. */
+#ifdef COMMENT
         if (!local &&
             (xzcmd == XZDIR || xzcmd == XZTYP ||
              xzcmd == XZXIT || xzcmd == XZSPA ||
@@ -7212,6 +7334,7 @@ remtxt(p) char ** p; {
             }
             return(-9);
         }
+#endif /* COMMENT */
         s = brstrip(s);                 /* Remove outer braces if any. */
         *p = s;                         /* Point to result */
         return(1);                      /* and return. */
@@ -7646,6 +7769,14 @@ dormt(xx) int xx;
         retcode = sstate = setgen('U',s,"","");
         break;
 
+      case XZMSG:                       /* Message */
+        if ((x = cmtxt("Short text message for server","",&s,xxstring)) < 0)
+          return(x);
+        if ((x = remtxt(&s)) < 0)
+          return(x);
+        retcode = sstate = setgen('M',s,"","");
+        break;
+
 #ifndef NOFRILLS
       case XZTYP:                       /* Type */
         if ((x = cmtxt("Remote file specification","",&s,xxstring)) < 0)
@@ -8515,7 +8646,7 @@ int
 clsconnx(ask) int ask; {
     int x, rc = 0;
 #ifdef NEWFTP
-    extern int ftpget, ftpisopen(), ftpbye();
+    extern int ftpget, ftpisopen();
     if ((ftpget == 1) || ((ftpget == 2) && !local && ftpisopen()))
       return(success = ftpbye());
 #endif /* NEWFTP */
@@ -9048,30 +9179,96 @@ cx_net(net, protocol, xhost, svc,
          if (net == NET_TCPB) {
             switch (protocol) {
 #ifdef CK_SSL
+#ifdef COMMENT
+/*
+  Jeff's version from 30 Dec 2006 - doesn't work - SSL/TLS_RAW still
+  start Telnet negotions if a 0xff byte comes in.
+*/
+             case NP_SSL_RAW:
+                ttnproto = NP_SSL_RAW;
+               debug(F101,"NP_SSL_RAW ttnproto","",ttnproto);
+                ssl_only_flag = 1;
+                tls_only_flag = 0;
+                break;
+
+             case NP_TLS_RAW:
+                 ttnproto = NP_TLS_RAW;
+                 debug(F101,"NP_TLS_RAW ttnproto","",ttnproto);
+                 ssl_only_flag = 0;
+                 tls_only_flag = 1;
+                 break;
+
+             case NP_SSL:
+                ttnproto = NP_SSL;
+               debug(F101,"NP_SSL ttnproto","",ttnproto);
+                ssl_only_flag = 1;
+                tls_only_flag = 0;
+                break;
+
+             case NP_TLS:
+                ttnproto = NP_TLS;
+               debug(F101,"NP_TLS ttnproto","",ttnproto);
+                ssl_only_flag = 0;
+                tls_only_flag = 1;
+                break;
+
+             case NP_SSL_TELNET:
+                ttnproto = NP_TELNET;
+               debug(F101,"NP_SSL_TELNET ttnproto","",ttnproto);
+                ssl_only_flag = 1;
+                tls_only_flag = 0;
+                break;
+
+             case NP_TLS_TELNET:
+                ttnproto = NP_TELNET;
+               debug(F101,"NP_TLS_TELNET ttnproto","",ttnproto);
+                ssl_only_flag = 0;
+                tls_only_flag = 1;
+                break;
+#else
+/* fdc version of 4 Dec 2006 works OK */
+             case NP_SSL_RAW:
              case NP_SSL:
+               ssl_raw_flag = (protocol == NP_SSL_RAW) ? 1 : 0;
                 ttnproto = protocol;
+               debug(F101,protocol==NP_SSL ?
+                     "NP_SSL ttnproto" :
+                     "NP_SSL_RAW ttnproto",
+                     "",ttnproto);
                 ssl_only_flag = 1;
                 tls_only_flag = 0;
                 break;
 
              case NP_TLS:
+             case NP_TLS_RAW:
+               tls_raw_flag = (protocol == NP_SSL_RAW) ? 1 : 0;
                 ttnproto = protocol;
+               debug(F101,protocol==NP_TLS ?
+                     "NP_TLS ttnproto" :
+                     "NP_TLS_RAW ttnproto",
+                     "",ttnproto);
                 ssl_only_flag = 0;
                 tls_only_flag = 1;
                 break;
 
              case NP_SSL_TELNET:
+               ssl_raw_flag = 0;
                 ttnproto = NP_TELNET;
+               debug(F101,"NP_SSL_TELNET ttnproto","",ttnproto);
                 ssl_only_flag = 1;
                 tls_only_flag = 0;
                 break;
 
              case NP_TLS_TELNET:
+               tls_raw_flag = 0;
                 ttnproto = NP_TELNET;
+               debug(F101,"NP_TLS_TELNET ttnproto","",ttnproto);
                 ssl_only_flag = 0;
                 tls_only_flag = 1;
                 break;
+#endif /* COMMENT */
 #endif /* CK_SSL */
+
              case NP_NONE:
              case NP_TCPRAW:
              case NP_RLOGIN:
@@ -9084,8 +9281,17 @@ cx_net(net, protocol, xhost, svc,
              default:
                 ttnproto = protocol;
 #ifdef CK_SSL
+#ifdef COMMENT
+               /* Jeff version from 30 Dec 2006 */
                 ssl_only_flag = 0;
                 tls_only_flag = 0;
+#else
+               /* fdc version from 4 Dec 2006 */
+               ssl_raw_flag = 0;
+               tls_raw_flag = 0;
+                ssl_only_flag = 0;
+                tls_only_flag = 0;
+#endif /* COMMENT */
 #endif /* CK_SSL */
                 break;
             }
@@ -10055,7 +10261,11 @@ setlin(xx, zz, fc)
     if (xx == XXSSH) {                  /* SSH becomes PTY SSH ... */
         dossh = 1;
         xx = XYHOST;
+    } else if (!ckstrcmp("ssh ",line,4,0)) { /* 2010/03/01 */
+        dossh = 1;
+        xx = XYHOST;
     }
+    debug(F101,"setlin dossh","",dossh);
 #endif /* SSHCMD */
 
 #ifdef TNCODE
@@ -10114,25 +10324,32 @@ setlin(xx, zz, fc)
 #ifdef SSHCMD
         if (dossh) {                    /* SSH connection via pty */
             int k;
+           extern int ttyfd;           /* 2010/03/01 */
             k = ckstrncpy(line, sshcmd ? sshcmd : defsshcmd, LINBUFSIZ);
             debug(F111,"setlin sshcmd 1",line,k);
             if ((x = cmtxt("Optional switches and hostname","",&s,xxstring))<0)
               return(x);
-            if (!*s) {
-                printf("?SSH to where?\n");
-                return(-9);
-            }
-            if (k < LINBUFSIZ) {
-                line[k++] = SP;
-                line[k] = NUL;
-                debug(F111,"setlin sshcmd 2",line,k);
-            } if (k < LINBUFSIZ) {
-                ckstrncpy(&line[k],s,LINBUFSIZ-k);
-                debug(F111,"setlin sshcmd 3",line,k);
-            } else {
-                printf("?Too long\n");
-                return(-9);
-            }
+
+            /* 2010-03-30 */
+           if (!*s && ttyfd < 0 && !ckstrcmp("ssh ",ttname,4,0)) { 
+               x = ckstrncpy(line,ttname,LINBUFSIZ);
+           } else {
+               if (!*s) {
+                   printf("?SSH to where?\n");
+                   return(-9);
+               }
+               if (k < LINBUFSIZ) {
+                   line[k++] = SP;
+                   line[k] = NUL;
+                   debug(F111,"setlin sshcmd 2",line,k);
+               } if (k < LINBUFSIZ) {
+                   ckstrncpy(&line[k],s,LINBUFSIZ-k);
+                   debug(F111,"setlin sshcmd 3",line,k);
+               } else {
+                   printf("?Too long\n");
+                   return(-9);
+               }
+           }
            x = cx_net( NET_PTY,                /* network type */
                         0,                      /* protocol (not used) */
                         line,                   /* host */
@@ -10446,8 +10663,8 @@ setlin(xx, zz, fc)
                 if ((x = cmtxt("Rest of command","",&s,xxstring)) < 0)
                   return(x);
                 if (*s) {
-                    strncat(line," ",LINBUFSIZ);
-                    strncat(line,s,LINBUFSIZ);
+                    ckstrncat(line," ",LINBUFSIZ);
+                    ckstrncat(line,s,LINBUFSIZ);
                 }
                 s = line;
             }
@@ -11203,19 +11420,13 @@ setlin(xx, zz, fc)
   <#>ifdef'ing out this code and adding the equivalent replacement routines
   to the ck?fio.c module, e.g. for RMS-based file i/o in ckvfio.c.
 */
-
-/* Define NOSTAT if the <#>include causes trouble. */
-
 #ifndef NOSTAT
 #ifdef VMS
-#ifdef VAXC                             /* As it does in VAX C */
-#define NOSTAT
-#endif /* VAXC */
-#endif /* VMS */
-#endif /* NOSTAT */
-
-#ifndef NOSTAT
+/* 2010-03-09 SMS.  VAX C needs help to find "sys".  It's easier not to try. */
+#include <stat.h>
+#else /* def VMS */
 #include <sys/stat.h>
+#endif /* def VMS [else] */
 #endif /* NOSTAT */
 
 #ifdef NLCHAR
@@ -11227,10 +11438,10 @@ static int z_lt = 2;
 struct ckz_file {                       /* C-Kermit file struct */
     FILE * z_fp;                        /* Includes the C-Lib file struct */
     unsigned int z_flags;               /* Plus C-Kermit mode flags, */
-    long z_nline;                       /* current line number if known, */
+    CK_OFF_T z_nline;                  /* current line number if known, */
     char z_name[CKMAXPATH+2];           /* and the file's name. */
 };
-static struct ckz_file * z_file = NULL; /* Array of C-Kermit file structs */
+static struct ckz_file ** z_file = NULL; /* Array of C-Kermit file structs */
 static int z_inited = 0;                /* Flag for array initialized */
 int z_maxchan = Z_MAXCHAN;              /* Max number of C-Kermit channels */
 int z_openmax = CKMAXOPEN;              /* Max number of open files overall */
@@ -11350,6 +11561,8 @@ z_open(name, flags) char * name; int flags; {
         /* Note: This could be a pretty big chunk of memory */
         /* if z_maxchan is a big number.  If this becomes a problem */
         /* we'll need to malloc and free each element at open/close time */
+#ifdef COMMENT
+       /* May 2006 - it's time - in current Linux this about 3MB */
         if (!(z_file = (struct ckz_file *)
               malloc(sizeof(struct ckz_file) * (z_maxchan + 1))))
           return(z_error = FX_NMF);
@@ -11359,19 +11572,42 @@ z_open(name, flags) char * name; int flags; {
             z_file[i].z_nline = 0;
             *(z_file[i].z_name) = '\0';
         }
-        z_inited = 1;                   /* Remember we did */
+#else
+       /* New economical way, allocate storage for each channel as needed */
+       if (!z_file) {
+           z_file = (struct ckz_file **)malloc((z_maxchan + 1) *
+                                               sizeof(struct ckz_file *));
+           if (!z_file)
+             return(z_error = FX_NMF);
+           for (i = 0; i < z_maxchan; i++)
+             z_file[i] = NULL;
+       }
+#endif /* COMMENT */
+        z_inited = 1;                   /* Remember we initialized */
     }
-    for (n = -1, i = 0; i < z_maxchan; i++) {
+    for (n = -1, i = 0; i < z_maxchan; i++) { /* Find a free channel */
+#ifdef COMMENT
         if (!z_file[i].z_fp) {
             n = i;
             break;
         }
+#else
+        if (!z_file[i]) {
+           z_file[i] = (struct ckz_file *) malloc(sizeof(struct ckz_file));
+           if (!z_file[i])
+             return(z_error = FX_NMF);
+            n = i;
+            break;
+        }
+#endif /* COMMENT */
+
     }
     if (n < 0 || n >= z_maxchan)        /* Any free channels? */
       return(z_error = FX_NMF);         /* No, fail. */
     errno = 0;
 
-    z_file[n].z_flags = 0;              /* In case of failure... */
+    z_file[n]->z_flags = 0;            /* In case of failure... */
+    z_file[n]->z_fp = NULL;            /* Set file pointer to NULL */
 
     t = fopen(name, mode);              /* Try to open the file. */
     if (!t) {                           /* Failed... */
@@ -11380,6 +11616,8 @@ z_open(name, flags) char * name; int flags; {
         if (errno == EMFILE)
           return(z_error = FX_NMF);
 #endif /* EMFILE */
+       free(z_file[n]);
+       z_file[n] = NULL;
         return(z_error = (errno ?  FX_SYS : FX_UNK)); /* Return error code */
     }
 #ifdef NT
@@ -11389,10 +11627,11 @@ z_open(name, flags) char * name; int flags; {
 #endif /* O_SEQUENTIAL */
 #endif /* NT */
     z_nopen++;                          /* Open, count it. */
-    z_file[n].z_fp = t;                 /* Stash the file pointer */
-    z_file[n].z_flags = flags;          /* and the flags */
+    z_file[n]->z_fp = t;               /* Stash the file pointer */
+    z_file[n]->z_flags = flags;                /* and the flags */
+    z_file[n]->z_nline = 0;            /* Current line number is 0 */
     z_error = 0;
-    zfnqfp(name,CKMAXPATH,z_file[n].z_name); /* and the file's full name */
+    zfnqfp(name,CKMAXPATH,z_file[n]->z_name); /* and the file's full name */
     return(n);                          /* Return the channel number */
 }
 
@@ -11404,17 +11643,21 @@ z_close(channel) int channel; {         /* Close file on given channel */
       return(z_error = FX_NOP);
     if (channel >= z_maxchan)           /* Channel out of range? */
       return(z_error = FX_CHN);
-    if (!(t = z_file[channel].z_fp))    /* Channel wasn't open? */
+    if (!z_file[channel])
+      return(z_error = FX_NOP);
+    if (!(t = z_file[channel]->z_fp))    /* Channel wasn't open? */
       return(z_error = FX_NOP);
     errno = 0;                          /* Set errno 0 to get a good reading */
     x = fclose(t);                      /* Try to close */
     if (x == EOF)                       /* On failure */
       return(z_error = FX_SYS);         /* indicate system error. */
     z_nopen--;                          /* Closed OK, decrement open count */
-    z_file[channel].z_fp = NULL;        /* Set file pointer to NULL */
-    z_file[channel].z_nline = 0;        /* Current line number is 0 */
-    z_file[channel].z_flags = 0;        /* Set flags to 0 */
-    *(z_file[channel].z_name) = '\0';   /* Clear name */
+    z_file[channel]->z_fp = NULL;      /* Set file pointer to NULL */
+    z_file[channel]->z_nline = 0;      /* Current line number is 0 */
+    z_file[channel]->z_flags = 0;      /* Set flags to 0 */
+    *(z_file[channel]->z_name) = '\0'; /* Clear name */
+    free(z_file[channel]);
+    z_file[channel] = NULL;
     return(z_error = 0);
 }
 
@@ -11453,9 +11696,11 @@ z_out(channel,s,length,flags) int channel, flags, length; char * s; {
       return(z_error = FX_NOP);
     if (channel >= z_maxchan)           /* Channel in range? */
       return(z_error = FX_CHN);
-    if (!(t = z_file[channel].z_fp))    /* File open? */
+    if (!z_file[channel])
       return(z_error = FX_NOP);
-    if (!((z_file[channel].z_flags) & (FM_WRI|FM_APP))) /* In write mode? */
+    if (!(t = z_file[channel]->z_fp))    /* File open? */
+      return(z_error = FX_NOP);
+    if (!((z_file[channel]->z_flags) & (FM_WRI|FM_APP))) /* In write mode? */
       return(z_error = FX_FOP);
     n = length;                         /* Length of string to write */
     if (n < 0) {                        /* Negative means get it ourselves */
@@ -11472,7 +11717,7 @@ z_out(channel,s,length,flags) int channel, flags, length; char * s; {
             if (x < 1)
               return(z_error = (errno ? FX_SYS : FX_UNK));
         }
-        z_file[channel].z_nline = -1;   /* Current line no longer known */
+        z_file[channel]->z_nline = -1;   /* Current line no longer known */
         z_error = 0;
         return(i);
     } else {                            /* Writing string arg */
@@ -11486,10 +11731,10 @@ z_out(channel,s,length,flags) int channel, flags, length; char * s; {
         if (flags == 0) {               /* If supplying line termination */
             if (fwrite("\n",1,1,t))     /* do that  */
               x += z_lt;                /* count the terminator */
-            if (z_file[channel].z_nline > -1) /* count this line */
-              z_file[channel].z_nline++;
+            if (z_file[channel]->z_nline > -1) /* count this line */
+              z_file[channel]->z_nline++;
         } else {
-            z_file[channel].z_nline = -1; /* Current line no longer known */
+            z_file[channel]->z_nline = -1; /* Current line no longer known */
         }
     }
     z_error = 0;
@@ -11523,9 +11768,11 @@ z_in(channel,s,buflen,length,flags)
       return(z_error = FX_NOP);
     if (channel >= z_maxchan)
       return(z_error = FX_CHN);
-    if (!(t = z_file[channel].z_fp))
+    if (!z_file[channel])
+      return(z_error = FX_NOP);
+    if (!(t = z_file[channel]->z_fp))
       return(z_error = FX_NOP);
-    if (!((z_file[channel].z_flags) & FM_REA))
+    if (!((z_file[channel]->z_flags) & FM_REA))
       return(z_error = FX_FOP);
     if (!s)                             /* Check destination */
      return(z_error = FX_RNG);
@@ -11542,24 +11789,33 @@ z_in(channel,s,buflen,length,flags)
       return(z_error = FX_RNG);
     errno = 0;                          /* Reset errno */
     if (flags) {                        /* Read block or byte */
-        i = fread(s,1,length,t);
+       int n;                          /* 20050912 */
+       n = length;                     /* 20050912 */
+       i = 0;                          /* 20050912 */
+       while (n > 0) {                 /* 20050912 */
+           i = fread(s,1,n,t);         /* 20050912 */
 #ifdef DEBUG
-        if (deblog) {
-            debug(F111,"z_in block",s,i);
-            debug(F101,"z_in block errno","",errno);
-            debug(F101,"z_in block ferror","",ferror(t));
-            debug(F101,"z_in block feof","",feof(t));
-        }
+           if (deblog) {
+               debug(F111,"z_in block",s,i);
+               debug(F101,"z_in block errno","",errno);
+               debug(F101,"z_in block ferror","",ferror(t));
+               debug(F101,"z_in block feof","",feof(t));
+           }
 #endif /* DEBUG */
-        z_file[channel].z_nline = -1;   /* Current line no longer known */
+           if (i == 0) break;          /* 20050912 */
+           s += i;                     /* 20050912 */
+           n -= i;                     /* 20050912 */
+       }
+       /* Current line no longer known */
+        z_file[channel]->z_nline = (CK_OFF_T)-1;
     } else {                            /* Read line */
 #ifndef COMMENT
         /* This method is used because it's simpler than the others */
         /* and also marginally faster. */
-        debug(F101,"z_in getc loop","",ftell(t));
+        debug(F101,"z_in getc loop","",CKFTELL(t));
         for (i = 0; i < length; i++) {
             if ((x = getc(t)) == EOF) {
-                debug(F101,"z_in getc error","",ftell(t));
+                debug(F101,"z_in getc error","",CKFTELL(t));
                 s[i] = '\0';
                 break;
             }
@@ -11570,9 +11826,9 @@ z_in(channel,s,buflen,length,flags)
             }
         }
         debug(F111,"z_in line byte loop",ckitoa(errno),i);
-        debug(F111,"z_in line got",s,z_file[channel].z_nline);
-        if (z_file[channel].z_nline > -1)
-          z_file[channel].z_nline++;
+        debug(F111,"z_in line got",s,z_file[channel]->z_nline);
+        if (z_file[channel]->z_nline > -1)
+          z_file[channel]->z_nline++;
 #else
 #ifdef COMMENT2
         /* Straightforward but strlen() slows it down. */
@@ -11583,15 +11839,15 @@ z_in(channel,s,buflen,length,flags)
             if (i > 0 && s[i-1] == '\n') i--;
         }
         debug(F111,"z_in line fgets",ckitoa(errno),i);
-        if (z_file[channel].z_nline > -1)
-          z_file[channel].z_nline++;
+        if (z_file[channel]->z_nline > -1)
+          z_file[channel]->z_nline++;
 #else
         /* This is a do-it-yourself fgets() with its own readahead and */
         /* putback.  It's a bit faster than real fgets() but not enough */
         /* to justify the added complexity or the risk of the ftell() and */
         /* fseek() calls failing. */
         int k, flag = 0;
-        long pos;
+        CK_OFF_T pos;
         for (i = 0; !flag && i <= (length - Z_INBUFLEN); i += Z_INBUFLEN) {
             k = ((length - i) < Z_INBUFLEN) ? length - i : Z_INBUFLEN;
             if ((x = fread(s+i,1,k,t)) < 1)
@@ -11601,10 +11857,10 @@ z_in(channel,s,buflen,length,flags)
                 if (s[i+j] == '\n') {
                     s[i+j] = '\0';
                     flag ++;
-                    pos = ftell(t);
+                    pos = CKFTELL(t);
                     if (pos > -1) {
                         pos -= (x - j - 1);
-                        x = fseek(t, pos, 0);
+                        x = CKFSEEK(t, pos, 0);
                         i += j;
                         break;
                     } else
@@ -11612,8 +11868,8 @@ z_in(channel,s,buflen,length,flags)
                 }
             }
         }
-        if (z_file[channel].z_nline > -1)
-          z_file[channel].z_nline++;
+        if (z_file[channel]->z_nline > -1)
+          z_file[channel]->z_nline++;
         debug(F111,"z_in line chunk loop",ckitoa(errno),i);
 #endif /* COMMENT2 */
 #endif /* COMMENT */
@@ -11638,9 +11894,11 @@ z_flush(channel) int channel; {         /* Flush output channel */
       return(z_error = FX_NOP);
     if (channel >= z_maxchan)
       return(z_error = FX_CHN);
-    if (!(t = z_file[channel].z_fp))
+    if (!z_file[channel])
+      return(z_error = FX_NOP);
+    if (!(t = z_file[channel]->z_fp))
       return(z_error = FX_NOP);
-    if (!((z_file[channel].z_flags) & (FM_WRI|FM_APP))) /* Write access? */
+    if (!((z_file[channel]->z_flags) & (FM_WRI|FM_APP))) /* Write access? */
       return(z_error = FX_FOP);
     errno = 0;                          /* Reset errno */
     x = fflush(t);                      /* Try to flush */
@@ -11649,9 +11907,9 @@ z_flush(channel) int channel; {         /* Flush output channel */
 
 int
 #ifdef CK_ANSIC
-z_seek(int channel, long pos)           /* Move file pointer to byte */
+z_seek(int channel, CK_OFF_T pos)      /* Move file pointer to byte */
 #else
-z_seek(channel,pos) int channel; long pos; /* (seek to given position) */
+z_seek(channel,pos) int channel; CK_OFF_T pos; /* (seek to given position) */
 #endif /* CK_ANSIC */
 {
     int i, x = 0, rc;
@@ -11660,42 +11918,46 @@ z_seek(channel,pos) int channel; long pos; /* (seek to given position) */
       return(z_error = FX_NOP);
     if (channel >= z_maxchan)
       return(z_error = FX_CHN);
-    if (!(t = z_file[channel].z_fp))
+    if (!z_file[channel])
+      return(z_error = FX_NOP);
+    if (!(t = z_file[channel]->z_fp))
       return(z_error = FX_NOP);
     if (pos < 0L) {
         x = 2;
         pos = (pos == -2) ? -1L : 0L;
     }
     errno = 0;
-    rc = fseek(t,pos,x);                /* Try to seek */
+    rc = CKFSEEK(t,pos,x);             /* Try to seek */
     debug(F111,"z_seek",ckitoa(errno),rc);
     if (rc < 0)                         /* OK? */
       return(z_error = FX_SYS); /* No. */
-    z_file[channel].z_nline = ((pos || x) ? -1 : 0);
+    z_file[channel]->z_nline = ((pos || x) ? -1 : 0);
     return(z_error = 0);
 }
 
 int
 #ifdef CK_ANSIC
-z_line(int channel, long pos)           /* Move file pointer to line */
+z_line(int channel, CK_OFF_T pos)           /* Move file pointer to line */
 #else
-z_line(channel,pos) int channel; long pos; /* (seek to given position) */
+z_line(channel,pos) int channel; CK_OFF_T pos; /* (seek to given position) */
 #endif /* CK_ANSIC */
 {
     int i, len, x = 0;
-    long current = 0L, prev = -1L, old = -1L;
+    CK_OFF_T current = (CK_OFF_T)0, prev = (CK_OFF_T)-1, old = (CK_OFF_T)-1;
     FILE * t;
     char tmpbuf[256];
     if (!z_inited)                      /* Check... */
       return(z_error = FX_NOP);
     if (channel >= z_maxchan)
       return(z_error = FX_CHN);
-    if (!(t = z_file[channel].z_fp))
+    if (!z_file[channel])
+      return(z_error = FX_NOP);
+    if (!(t = z_file[channel]->z_fp))
       return(z_error = FX_NOP);
     debug(F101,"z_line pos","",pos);
     if (pos < 0L) {                     /* EOF wanted */
-        long n;
-        n = z_file[channel].z_nline;
+        CK_OFF_T n;
+        n = z_file[channel]->z_nline;
         debug(F101,"z_line n","",n);
         if (n < 0 || pos < 0) {
             rewind(t);
@@ -11708,7 +11970,7 @@ z_line(channel,pos) int channel; long pos; /* (seek to given position) */
                 n++;
                 if (pos == -2) {
                     old = prev;
-                    prev = ftell(t);
+                    prev = CKFTELL(t);
                 }
             }
         }
@@ -11720,17 +11982,17 @@ z_line(channel,pos) int channel; long pos; /* (seek to given position) */
             else
               n--;
         }
-        z_file[channel].z_nline = n;
+        z_file[channel]->z_nline = n;
         return(z_error = 0);
     }
     if (pos == 0L) {                    /* Rewind wanted */
-        z_file[channel].z_nline = 0L;
+        z_file[channel]->z_nline = 0L;
         rewind(t);
         debug(F100,"z_line rewind","",0);
         return(0L);
     }
     tmpbuf[255] = NUL;                  /* Make sure buf is NUL terminated */
-    current = z_file[channel].z_nline;  /* Current line */
+    current = z_file[channel]->z_nline;  /* Current line */
     /*
       If necessary the following could be optimized, e.g. for positioning
       to a previous line in a large file without starting over.
@@ -11753,12 +12015,12 @@ z_line(channel,pos) int channel; long pos; /* (seek to given position) */
                 return(z_error = FX_UNK);
             }
         } else {
-            z_file[channel].z_nline = -1L;
+            z_file[channel]->z_nline = -1L;
             debug(F101,"z_line premature EOF","",current);
             return(z_error = FX_EOF);
         }
     }
-    z_file[channel].z_nline = current;
+    z_file[channel]->z_nline = current;
     debug(F101,"z_line result","",current);
     z_error = 0;
     return(current);
@@ -11775,11 +12037,15 @@ z_getname(channel) int channel; {       /* Return name of file on channel */
         z_error = FX_CHN;
         return(NULL);
     }
-    if (!(t = z_file[channel].z_fp)) {
+    if (!z_file[channel]) {
         z_error = FX_NOP;
         return(NULL);
     }
-    return((char *)(z_file[channel].z_name));
+    if (!(t = z_file[channel]->z_fp)) {
+        z_error = FX_NOP;
+        return(NULL);
+    }
+    return((char *)(z_file[channel]->z_name));
 }
 
 int
@@ -11797,47 +12063,53 @@ z_getmode(channel) int channel; {       /* Return OPEN modes of channel */
       return(0);
     if (channel >= z_maxchan)
       return(z_error = FX_CHN);
-    if (!(t = z_file[channel].z_fp))
+    if (!z_file[channel])
+      return(0);
+    if (!(t = z_file[channel]->z_fp))
       return(0);
-    x = z_file[channel].z_flags;
+    x = z_file[channel]->z_flags;
     if (feof(t)) {                      /* This might not work for */
         x |= FM_EOF;                    /* output files */
 #ifndef NOSTAT
     /* But this does if we can use it. */
-    } else if (stat(z_file[channel].z_name,&statbuf) > -1) {
-        if (ftell(t) == statbuf.st_size)
+    } else if (stat(z_file[channel]->z_name,&statbuf) > -1) {
+        if (CKFTELL(t) == statbuf.st_size)
           x |= FM_EOF;
 #endif /* NOSTAT */
     }
     return(x);
 }
 
-long
+CK_OFF_T
 z_getpos(channel) int channel; {        /* Get file pointer position */
     FILE * t;                           /* on this channel */
-    long x;
+    CK_OFF_T x;
     if (!z_inited)
       return(z_error = FX_NOP);
     if (channel >= z_maxchan)
       return(z_error = FX_CHN);
-    if (!(t = z_file[channel].z_fp))
+    if (!z_file[channel])
       return(z_error = FX_NOP);
-    x = ftell(t);
+    if (!(t = z_file[channel]->z_fp))
+      return(z_error = FX_NOP);
+    x = CKFTELL(t);
     return((x < 0L) ? (z_error = FX_SYS) : x);
 }
 
-long
+CK_OFF_T
 z_getline(channel) int channel; {       /* Get current line number */
     FILE * t;                           /* in file on this channel */
-    long rc;
+    CK_OFF_T rc;
     if (!z_inited)
       return(z_error = FX_NOP);
     if (channel >= z_maxchan)
       return(z_error = FX_CHN);
-    if (!(t = z_file[channel].z_fp))
+    if (!z_file[channel])
+      return(z_error = FX_NOP);
+    if (!(t = z_file[channel]->z_fp))
       return(z_error = FX_NOP);
-    debug(F101,"z_getline","",z_file[channel].z_nline);
-    rc = z_file[channel].z_nline;
+    debug(F101,"z_getline","",z_file[channel]->z_nline);
+    rc = z_file[channel]->z_nline;
     return((rc < 0) ? (z_error = FX_LNU) : rc);
 }
 
@@ -11848,7 +12120,9 @@ z_getfnum(channel) int channel; {       /* Get file number / handle */
       return(z_error = FX_NOP);
     if (channel >= z_maxchan)
       return(z_error = FX_CHN);
-    if (!(t = z_file[channel].z_fp))
+    if (!z_file[channel])
+      return(z_error = FX_NOP);
+    if (!(t = z_file[channel]->z_fp))
       return(z_error = FX_NOP);
     z_error = 0;
     return(fileno(t));
@@ -11858,27 +12132,31 @@ z_getfnum(channel) int channel; {       /* Get file number / handle */
   Line-oriented counts and seeks are as dumb as they can be at the moment.
   Later we can speed them up by building little indexes.
 */
-long
+CK_OFF_T
 z_count(channel, what) int channel, what; { /* Count bytes or lines in file */
     FILE * t;
     int i, x;
-    long pos, count = 0L;
+    CK_OFF_T pos, count = (CK_OFF_T)0;
     if (!z_inited)                      /* Check stuff... */
       return(z_error = FX_NOP);
     if (channel >= z_maxchan)
       return(z_error = FX_CHN);
-    if (!(t = z_file[channel].z_fp))
+    if (!z_file[channel])
+      return(z_error = FX_NOP);
+    if (!(t = z_file[channel]->z_fp))
       return(z_error = FX_NOP);
-    pos = ftell(t);                     /* Save current file pointer */
+    pos = CKFTELL(t);                  /* Save current file pointer */
     errno = 0;
     z_error = 0;
     if (what == RD_CHAR) {              /* Size in bytes requested */
-        if (!fseek(t,0L,2)) {           /* Seek to end */
-            count = ftell(t);           /* Get file pointer */
-            fseek(t,pos,0);             /* Restore file file pointer */
+#ifdef COMMENT
+        if (!CKFSEEK(t,0L,2)) {                /* Seek to end */
+            count = CKFTELL(t);                /* Get file pointer */
+            CKFSEEK(t,pos,0);          /* Restore file file pointer */
             return(count);
         } else                          /* Fallback in case seek fails */
-          return(zgetfs(z_file[channel].z_name));
+#endif /* COMMENT */
+          return(zgetfs(z_file[channel]->z_name));
     }
     rewind(t);                          /* Line count requested - rewind. */
     while (1) {                         /* Count lines. */
@@ -11887,7 +12165,7 @@ z_count(channel, what) int channel, what; { /* Count bytes or lines in file */
         if (x == '\n')                  /* else... */
           count++;
     }
-    x = fseek(t,pos,0);                 /* Restore file pointer */
+    x = CKFSEEK(t,pos,0);              /* Restore file pointer */
     return(count);
 }
 
@@ -11932,11 +12210,13 @@ static int nfsekwtab = (sizeof (fsekwtab) / sizeof (struct keytab));
 #define SEE_CHAR  RD_CHAR
 #define SEE_REL   3
 #define SEE_ABS   4
+#define SEE_FIND  5
 
 static struct keytab fskswtab[] = {
     { "/absolute",  SEE_ABS,  0 },
     { "/byte",      SEE_CHAR, 0 },
     { "/character", SEE_CHAR, CM_INV },
+    { "/find",      SEE_FIND, CM_ARG },
     { "/line",      SEE_LINE, 0 },
     { "/relative",  SEE_REL,  0 }
 };
@@ -11981,20 +12261,23 @@ static struct keytab fwrtab[] = {       /* WRITE types */
 static int nfwrtab = (sizeof (fwrtab) / sizeof (struct keytab));
 
 static char blanks[] = "\040\040\040\040"; /* Some blanks for formatting */
+static char * seek_target = NULL;
 
 int
 dofile(op) int op; {                    /* Do the FILE command */
     char vnambuf[VNAML];                /* Buffer for variable names */
     char *vnp = NULL;                   /* Pointer to same */
     char zfilnam[CKMAXPATH+2];
-    char * p;
+    char * p, * m;
     struct FDB fl, sw, nu;
-    long z;
+    CK_OFF_T z;
     int rsize, filmode = 0, relative = -1, eofflg = 0;
     int rc, x, y, cx, n, getval, dummy, confirmed, listing = -1;
     int charflag = 0, sizeflag = 0;
     int pad = 32, wr_lpad = 0, wr_rpad = 0, rd_trim = 0, rd_untab = 0;
 
+    makestr(&seek_target,NULL);
+
     if (op == XXFILE) {                 /* FILE command was given */
         /* Get subcommand */
         if ((cx = cmkey(fctab,nfctab,"Operation","",xxstring)) < 0) {
@@ -12063,7 +12346,7 @@ dofile(op) int op; {                    /* Do the FILE command */
                     return(-9);
                 }
 #ifdef COMMENT
-                /* Uncomment if we add any switches ere that take args */
+                /* Uncomment if we add any switches here that take args */
                 if (!getval && (cmgkwflgs() & CM_ARG)) {
                     printf("?This switch requires an argument\n");
                     return(-9);         /* (none do...) */
@@ -12090,24 +12373,22 @@ dofile(op) int op; {                    /* Do the FILE command */
                 return(-9);
             }
         }
+       /* Assign a negative channel number in case we fail */
+       addmac(vnambuf,"-1");
+
         if (!(filmode & FM_RWA))        /* If no access mode specified */
           filmode |= FM_REA;            /* default to /READ. */
 
         y = 0;                          /* Now parse the filename */
-        if ((filmode & FM_RWA) == FM_WRI)
-          x = cmofi("Name of new file","",&s,xxstring);
-        else if ((filmode & FM_RWA) == FM_REA)
-          x = cmifi("Name of existing file","",&s,&y,xxstring);
-        else {
+        if ((filmode & FM_RWA) == FM_WRI) {
+           x = cmofi("Name of new file","",&s,xxstring);
+       } else if ((filmode & FM_RWA) == FM_REA) {
+           x = cmifi("Name of existing file","",&s,&y,xxstring);
+       } else {
             x = cmiofi("Filename","",&s,&y,xxstring);
-            debug(F101,"fopen /append x","",x);
-        }
-        if (x == -9) {
-            if (zchko(s) < 0) {
-                printf("Can't create \"%s\"\n",s);
-                return(x);
-            }
-        } else if (x < 0) {
+            debug(F111,"fopen /append x",s,x);
+       }
+        if (x < 0) {
             if (x == -3) {
                 printf("?Filename required\n");
                 x = -9;
@@ -12147,6 +12428,9 @@ dofile(op) int op; {                    /* Do the FILE command */
         }
         if ((x = cmcfm()) < 0)
           return(x);
+       if (n == -9) return(success = 0);
+       if (n == -8) return(success = 1);
+
         if ((rc = z_seek(n,0L)) < 0) {
             printf("?REWIND failed - Channel %d: %s\n",n,ckferror(rc));
             return(-9);
@@ -12154,29 +12438,41 @@ dofile(op) int op; {                    /* Do the FILE command */
         return(success = 1);
 
       case FIL_CLS:                     /* CLOSE */
-          cmfdbi(&sw,                   /* Second FDB - switches */
-                 _CMKEY,                /* fcode */
-                 "Channel number; or keyword",
-                 "",
-                 "",                    /* addtl string data */
-                 1,                     /* addtl numeric data 1: tbl size */
-                 0,                     /* addtl numeric data 2: 4 = cmswi */
-                 xxstring,              /* Processing function */
-                 fclkwtab,              /* Keyword table */
-                 &nu                    /* Pointer to next FDB */
-                 );
-          cmfdbi(&nu,                   /* First FDB - command switches */
+#ifdef COMMENT                         /* fdc 20100804 - bad idea */
+         {
+           int i, j, k;                /* Supply default if only one open */
+           s = "";
+           for (k = 0, j = 0, i = 0; i < z_maxchan; i++) {
+               if (z_file)
+                 if (z_file[i])
+                   if (z_file[i]->z_fp) { k++; j = i; }
+           }
+           if (k == 1) s = ckitoa(j);
+        }
+#endif /* COMMENT */
+          cmfdbi(&nu,                   /* Second FDB - channel number */
                  _CMNUM,                /* fcode */
-                 "",
-                 "",                    /* default */
+                 "Channel number or ALL", /* Help message */
+                 s,                    /* default */
                  "",                    /* addtl string data */
                  10,                    /* addtl numeric data 1: radix */
                  0,                     /* addtl numeric data 2: 0 */
                  xxstring,              /* Processing function */
                  NULL,                  /* Keyword table */
-                 NULL                   /* Pointer to next FDB */
-                 );                     /*  */
-        x = cmfdb(&sw);                 /* Parse something */
+                 &sw                   /* Pointer to next FDB */
+                 );                     /* Pointer to next FDB */
+        cmfdbi(&sw,                    /* First FDB - command switches */
+                 _CMKEY,                /* fcode */
+                 "",                   /* help message */
+                "",                    /* Default */
+                "",                    /* No addtl string data */
+                 1,                     /* addtl numeric data 1: tbl size */
+                 0,                     /* addtl numeric data 2: 4 = cmswi */
+                 xxstring,              /* Processing function */
+                 fclkwtab,              /* Keyword table */
+                NULL                   /* Last in chain */
+                 );
+        x = cmfdb(&nu);                 /* Parse something */
         if (x < 0) {
             if (x == -3) {
                 printf("?Channel number or ALL required\n");
@@ -12190,6 +12486,9 @@ dofile(op) int op; {                    /* Do the FILE command */
           n = -1;
         if ((x = cmcfm()) < 0)
           return(x);
+       if (n == -9) return(success = 0);
+       if (n == -8) return(success = 1);
+
         rc = 1;
         if (n < 0) {
             int count = 0;
@@ -12276,6 +12575,11 @@ dofile(op) int op; {                    /* Do the FILE command */
                         }
                         return(x);
                     }
+                   if (rsize > LINBUFSIZ) {
+                       printf("?Maximum FREAD/FWRITE size is %d\n",LINBUFSIZ);
+                       rsize = 0;
+                       return(-9);
+                   }
                     charflag = 0;
                     sizeflag = 1;
                     break;
@@ -12314,6 +12618,9 @@ dofile(op) int op; {                    /* Do the FILE command */
             int len = 0;
             if ((x = cmtxt("Text","",&s,xxstring)) < 0)
               return(x);
+           if (n == -9) return(success = 0);
+           if (n == -8) return(success = 1);
+
             ckstrncpy(line,s,LINBUFSIZ); /* Make a safe copy */
             s = line;
             s = brstrip(s);             /* Strip braces */
@@ -12392,9 +12699,14 @@ dofile(op) int op; {                    /* Do the FILE command */
               if ((x = cmcfm()) < 0)
                 return(x);
 
+           if (n == -9) return(success = 0);
+           if (n == -8) return(success = 1);
+
             line[0] = NUL;              /* Clear destination buffer */
+#ifdef COMMENT
             if (rsize >= LINBUFSIZ)     /* Don't overrun it */
               rsize = LINBUFSIZ - 1;
+#endif /* COMMENT */
 
             if (rsize == 0) {          /* Read a line */
                rc = z_in(n,line,LINBUFSIZ,LINBUFSIZ-1,0);
@@ -12485,6 +12797,15 @@ dofile(op) int op; {                    /* Do the FILE command */
                     switch (cmresult.nresult) {
                       case SEE_REL: relative = 1; break;
                       case SEE_ABS: relative = 0; break;
+                     case SEE_FIND: {
+                         if (getval) {
+                             y = cmfld("string or pattern","",&s,xxstring);
+                             if (y < 0)
+                               return(y);
+                             makestr(&seek_target,brstrip(s));
+                             break;
+                         }
+                     }
                       default: rsize = cmresult.nresult;
                     }
                 } else if (cx == FIL_COU) {
@@ -12503,6 +12824,9 @@ dofile(op) int op; {                    /* Do the FILE command */
         if (cx == FIL_COU) {
             if ((x = cmcfm()) < 0)
               return(x);
+           if (n == -9) return(success = 0);
+           if (n == -8) return(success = 1);
+
             z_filcount = z_count(n,rsize);
             if (z_filcount < 0) {
                 rc = z_filcount;
@@ -12519,9 +12843,12 @@ dofile(op) int op; {                    /* Do the FILE command */
                      );
             return(success = (z_filcount > -1) ? 1 : 0);
         }
+       m = (rsize == RD_CHAR) ?
+           "Number of bytes;\n or keyword" :
+           "Number of lines;\n or keyword";
         cmfdbi(&sw,                     /* SEEK symbolic targets (EOF) */
                _CMKEY,                  /* fcode */
-               "Channel number;\n or keyword",
+               m,
                "",
                "",                      /* addtl string data */
                nfsekwtab,               /* addtl numeric data 1: table size */
@@ -12530,8 +12857,8 @@ dofile(op) int op; {                    /* Do the FILE command */
                fsekwtab,                /* Keyword table */
                &nu                      /* Pointer to next FDB */
                );
-        cmfdbi(&nu,                     /* Channel number */
-               _CMNUM,                  /* fcode */
+        cmfdbi(&nu,                     /* Byte or line number */
+               _CMNUW,                  /* fcode */
                "",
                "",                      /* default */
                "",                      /* addtl string data */
@@ -12549,8 +12876,8 @@ dofile(op) int op; {                    /* Do the FILE command */
             }
             return(x);
         }
-        if (cmresult.fcode == _CMNUM) {
-            y = cmresult.nresult;
+        if (cmresult.fcode == _CMNUW) {
+            z = cmresult.wresult;
             debug(F110,"FILE SEEK atmbuf",atmbuf,0);
             if (relative < 0) {
                 if (cx == FIL_SEE && (atmbuf[0] == '+' || atmbuf[0] == '-'))
@@ -12565,7 +12892,8 @@ dofile(op) int op; {                    /* Do the FILE command */
         }
         if ((x = cmcfm()) < 0)
           return(x);
-        z = y;                          /* Convert to long */
+       if (n == -9) return(success = 0);
+       if (n == -8) return(success = 1);
         y = 1;                          /* Recycle this */
         z_flush(n);
         debug(F101,"FILE SEEK relative","",relative);
@@ -12573,9 +12901,9 @@ dofile(op) int op; {                    /* Do the FILE command */
 
         if (rsize == RD_CHAR) {         /* Seek to byte position */
             if (relative > 0) {
-                long pos;
+                CK_OFF_T pos;
                 pos = z_getpos(n);
-                if (pos < 0L) {
+                if (pos < (CK_OFF_T)0) {
                     rc = pos;
                     printf("?Relative SEEK failed: %s\n",ckferror(rc));
                     return(-9);
@@ -12599,10 +12927,10 @@ dofile(op) int op; {                    /* Do the FILE command */
             }
         } else {                        /* Seek to line */
             if (relative > 0) {
-                long pos;
+                CK_OFF_T pos;
                 pos = z_getline(n);
                 debug(F101,"FILE SEEK /LINE pos","",pos);
-                if (pos < 0L) {
+                if (pos < 0) {
                     rc = pos;
                     printf("?Relative SEEK failed: %s\n",ckferror(rc));
                     return(-9);
@@ -12621,7 +12949,42 @@ dofile(op) int op; {                    /* Do the FILE command */
                 return(-9);
             }
         }
-        return(success = y);
+       /*
+         Now, having sought to the desired starting spot, if a /FIND:
+         target was specified, look for it now.
+       */
+       if (seek_target) {
+           int flag = 0, ispat = 0, matchresult = 0;
+           while (!flag) {
+               y = z_in(n,line,LINBUFSIZ,LINBUFSIZ-1,0);
+               if (y < 0) {
+                   y = 0;
+                   break;
+               }
+               if (ispattern(seek_target)) {
+                   matchresult = ckmatch(seek_target,line,inpcas[cmdlvl],1+4);
+               } else {
+                   /* This is faster */
+                   matchresult = ckindex(seek_target,line,0,0,inpcas[cmdlvl]);
+               }
+               if (matchresult) {
+                   flag = 1;
+                   break;
+               }
+           }
+           if (flag) {
+               debug(F111,"FSEEK HAVE MATCH",seek_target,z_getline(n));
+               /* Back up to beginning of line where target found */
+               if ((y = z_line(n,z_getline(n)-1)) < 0) {
+                   if (rc == FX_EOF) return(success = 0);
+                   printf("?SEEK /LINE failed - Channel %d: %s\n",
+                          n,ckferror(rc));
+                   return(-9);
+               }
+               debug(F101,"FSEEK LINE","",y);
+           }
+       }
+        return(success = (y < 0) ? 0 : 1);
 
       case FIL_LIS: {                   /* LIST open files */
 #ifdef CK_TTGWSIZ
@@ -12639,9 +13002,9 @@ dofile(op) int op; {                    /* Do the FILE command */
 #endif /* CK_TTGWSIZ */
             paging = xaskmore;
 
-          printf("System open file limit: %4d\n", z_openmax);
-          printf("Maximum for FILE OPEN:  %4d\n", z_maxchan);
-          printf("Files currently open:   %4d\n\n", z_nopen);
+          printf("System open file limit:%5d\n", z_openmax);
+          printf("Maximum for FILE OPEN: %5d\n", z_maxchan);
+          printf("Files currently open:  %5d\n\n", z_nopen);
           n = 4;
           for (i = 0; i < z_maxchan; i++) {
               s = z_getname(i);         /* Got one? */
@@ -12651,7 +13014,7 @@ dofile(op) int op; {                    /* Do the FILE command */
                   printf("%2d. %s",i,s); /* Print name */
                   n++;                   /* Count it */
                   x = z_getmode(i);      /* Get modes & print them */
-                  if (x > -1) {
+                  if (x > 0) {
                       if (x & FM_REA) ckstrncat(m,"R",8);
                       if (x & FM_WRI) ckstrncat(m,"W",8);
                       if (x & FM_APP) ckstrncat(m,"A",8);
@@ -12660,8 +13023,8 @@ dofile(op) int op; {                    /* Do the FILE command */
                         printf(" (%s)",m);
                       if (x & FM_EOF)
                         printf(" [EOF]");
-                      else
-                        printf(" %ld",z_getpos(i)); /* And file position too */
+                      else             /* And file position too */
+                        printf(" %s",ckfstoa(z_getpos(i)));
                   }
                   printf("\n");
 #ifdef CK_TTGWSIZ
@@ -12689,6 +13052,8 @@ dofile(op) int op; {                    /* Do the FILE command */
         }
         if ((x = cmcfm()) < 0)
           return(x);
+       if (n == -9) return(success = 0);
+       if (n == -8) return(success = 1);
         if ((rc = z_flush(n)) < 0) {
             printf("?FLUSH failed - Channel %d: %s\n",n,ckferror(rc));
             return(-9);
@@ -12696,15 +13061,32 @@ dofile(op) int op; {                    /* Do the FILE command */
         return(success = 1);
 
       case FIL_STA:                     /* STATUS */
-        if ((x = cmnum("Channel number","",10,&n, xxstring)) < 0) {
+       {
+           int i, j, k;                /* Supply default if only one open */
+           s = "";
+           for (k = 0, j = 0, i = 0; i < z_maxchan; i++) {
+               if (z_file)
+                 if (z_file[i])
+                   if (z_file[i]->z_fp) { k++; j = i; }
+           }
+           if (k == 1) s = ckitoa(j);
+       }
+        if ((x = cmnum("Channel number",s,10,&n, xxstring)) < 0) {
             if (x == -3) {
-                printf("?Channel number required\n");
-                x = -9;
-            }
-            return(x);
+               if (z_nopen > 1) {
+                   printf("?%d files open - please supply channel number\n",
+                          z_nopen);
+                   return(-9);
+               }
+            } else
+             return(x);
         }
-        if ((x = cmcfm()) < 0)
-          return(x);
+        if ((y = cmcfm()) < 0)
+          return(y);
+       if ((!z_file || z_nopen == 0) && x == -3) {
+           printf("No files open\n");
+           return(success = 1);
+       }
         p = blanks + 3;                 /* Tricky formatting... */
         if (n < 1000) p--;
         if (n < 100) p--;
@@ -12716,7 +13098,7 @@ dofile(op) int op; {                    /* Do the FILE command */
             printf("Channel %d:%sNot open\n",n,p);
             return(success = 0);
         } else {
-            long xx;
+            CK_OFF_T xx;
             s = z_getname(n);
             if (!s) s = "(name unknown)";
             printf("Channel %d:%sOpen\n",n,p);
@@ -12727,11 +13109,11 @@ dofile(op) int op; {                    /* Do the FILE command */
             if (rc & FM_BIN) printf(" /BINARY");
             if (rc & FM_CMD) printf(" /COMMAND");
             if (rc & FM_EOF) printf(" [EOF]");
-            printf("\n Size:        %ld\n",z_count(n,RD_CHAR));
-            printf(" At byte:     %ld\n",z_getpos(n));
+            printf("\n Size:        %s\n",ckfstoa(z_count(n,RD_CHAR)));
+            printf(" At byte:     %s\n",ckfstoa(z_getpos(n)));
             xx = z_getline(n);
-            if (xx > -1)
-              printf(" At line:     %ld\n",xx);
+            if (xx > (CK_OFF_T)-1)
+              printf(" At line:     %s\n",ckfstoa(xx));
             return(success = 1);
         }
       default:
@@ -13269,8 +13651,8 @@ dosave(xx) int xx; {
 #ifndef NORECALL
         if (y == SV_HIST)               /* .. HISTORY */
           return(success = savhistory(s,disp));
-        break;
 #endif /* NORECALL */
+        break;
 
 #ifdef OS2
 #ifndef NOLOCAL
@@ -13904,6 +14286,7 @@ sho_auth(cx) int cx; {
             printf("\n");
             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
             break;
+#ifdef CK_SSL
           case AUTHTYPE_SSL:
             kv = all ? AUTHTYPE_SRP : 0;
             if (ck_ssleay_is_installed()) {
@@ -13915,8 +14298,6 @@ sho_auth(cx) int cx; {
                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
                 continue;
             }
-
-#ifdef CK_SSL
             printf(" RSA Certs file: %s\n",ssl_rsa_cert_file?
                   ssl_rsa_cert_file:"(none)");
             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
@@ -14057,10 +14438,7 @@ cp_auth() {                             /* Command_Parse AUTHENTICATE */
 #ifdef CK_RECALL
     extern int on_recall;               /* around Password prompting */
 #endif /* CK_RECALL */
-    struct stringint {                  /* Temporary array for switch values */
-        char * sval;                    /* String value */
-        int ival;                       /* Integer value */
-    } pv[KRB_I_MAX+1];                  /* This many */
+    struct stringint pv[KRB_I_MAX+1];   /* Temporary array for switch values */
     struct FDB kw, sw, fl;              /* FDBs for each parse function */
 
     krb_action = -1;                    /* Initialize Kerberos action. */
@@ -14104,12 +14482,11 @@ cp_auth() {                             /* Command_Parse AUTHENTICATE */
         if (krb5_d_instance)
           makestr(&tmpinst,krb5_d_instance);
     }
-
     for (i = 0; i <= KRB_I_MAX; i++) {  /* Initialize switch values */
         pv[i].sval = NULL;              /* to null pointers */
         pv[i].ival = 0;                 /* and 0 int values */
+        pv[i].wval = (CK_OFF_T)-1;     /* and -1 wide values */
     }
-
     if (kv == 4) {                      /* Kerberos 4 */
         pv[KRB_I_LF].ival = krb4_d_lifetime;
         pv[KRB_I_PA].ival = krb4_d_preauth;
@@ -14656,9 +15033,9 @@ ckxlogin(userid, passwd, acct, promptok)
 #ifdef CK_RECALL
     extern int on_recall;               /* around Password prompting */
 #endif /* CK_RECALL */
-#ifdef CK_PAM
+#ifdef COMMENT
     extern int guest;
-#endif /* CK_PAM */
+#endif /* COMMENT */
     int rprompt = 0;                    /* Restore prompt */
 #ifdef CKSYSLOG
     int savlog;
@@ -14774,9 +15151,9 @@ ckxlogin(userid, passwd, acct, promptok)
     debug(F111,"ckxlogin zvuser",userid,ok);
 
     if (!*passwd && promptok
-#ifdef CK_PAM
+#ifdef COMMENT
         && guest
-#endif /* CK_PAM */
+#endif /* COMMENT */
         ) {
         char prmpt[80];
 
@@ -14852,6 +15229,9 @@ ckxlogin(userid, passwd, acct, promptok)
         if (pflag) prompt(xxstring);    /* Issue prompt if at top level */
         cmres();                        /* Reset the parser */
         for (x = -1; x < 0;) {          /* Prompt till they answer */
+#ifdef CK_PAM
+           gotemptypasswd=0;
+#endif /* CK_PAM */
             x = cmtxt("","",&s,NULL);   /* Get a literal line of text */
             if (x == -4 || x == -10) {
                 printf("\r\n%sLogin cancelled\n",
@@ -14861,6 +15241,10 @@ ckxlogin(userid, passwd, acct, promptok)
 #endif /* CKSYSLOG */
                 doexit(GOOD_EXIT,0);
             }
+#ifdef CK_PAM
+           if (!*s)
+             gotemptypasswd = 1;
+#endif /* CK_PAM */
             if (sstate)                 /* In case of a Kermit packet */
               goto XCKXLOG;
             cmres();                    /* Reset the parser again */
@@ -14895,6 +15279,12 @@ ckxlogin(userid, passwd, acct, promptok)
     if (ok) {
         ok = zvpass((char *)passwd);    /* Check password */
         debug(F101,"ckxlogin zvpass","",ok);
+#ifdef CK_PAM
+    } else {
+       /* Fake pam password failure for nonexistent users */
+       sleep(1);
+       printf("Authentication failure\n");
+#endif /* CK_PAM */
     }
 
     if (ok > 0 && isguest) {
index 8545f89..3b77fe6 100644 (file)
--- a/ckuusr.c
+++ b/ckuusr.c
@@ -3,7 +3,7 @@
 #endif /* SSHTEST */
 
 #include "ckcsym.h"
-char *userv = "User Interface 8.0.278, 12 Mar 2004";
+char *userv = "User Interface 9.0.299, 9 Jun 2011";
 
 /*  C K U U S R --  "User Interface" for C-Kermit (Part 1)  */
 
@@ -14,7 +14,7 @@ char *userv = "User Interface 8.0.278, 12 Mar 2004";
     Jeffrey E Altman <jaltman@secure-endpoints.com>
       Secure Endpoints Inc., New York City
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2011,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -42,7 +42,7 @@ char *userv = "User Interface 8.0.278, 12 Mar 2004";
   parser are these:
 
   . Set parameters via global variables like duplex, speed, ttname, etc.  See
-    ckmain.c for the declarations and descriptions of these variables.
+    ckcmai.c for the declarations and descriptions of these variables.
 
   . If a command can be executed without the use of Kermit protocol, then
     execute the command directly and set the variable sstate to 0. Examples
@@ -149,6 +149,7 @@ int didsetlin = 0;
 #ifdef NEWFTP
 extern int ftpget, ftpisopen(), doftpres();
 _PROTOTYP(int doftptyp,(int));
+_PROTOTYP(VOID doftpglobaltype,(int));
 #endif /* NEWFTP */
 
 #ifdef VMS
@@ -210,7 +211,7 @@ extern int iksdcf;
 extern int isguest;
 #endif /* CK_LOGIN */
 
-extern long sendstart;
+extern CK_OFF_T sendstart;
 
 extern char *cmarg, *cmarg2, **cmlist, *dftty;
 
@@ -491,16 +492,17 @@ extern char * prstring[];
 char *lp;                              /* Pointer to line buffer */
 
 #ifndef NOSPL
+int vareval = 1;                       /* Evaluation method */
 int unkmacro = 0;                      /* Flag for in ON_UNKNOWN_COMMAND */
 int oldeval = 0;
 char evalbuf[33];                      /* EVALUATE result */
 extern char * inpbuf;                  /* Buffer for INPUT and REINPUT */
 char *inpbp;                           /* And pointer to same */
-extern char lblbuf[];                  /* Buffer for labels */
 int m_found;                           /* MINPUT result */
 int i_active = 0;                      /* INPUT command is active */
 char *ms[MINPMAX];                     /* Pointers to MINPUT strings */
-static int mp[MINPMAX];                        /* and flags */
+static int mpinited = 0;               /* Flag they have been initialized */
+static int mp[MINPMAX];                        /* and MINPUT flags */
 extern int fndiags, fnerror, fnsuccess;        /* Function diagnostics */
 #ifndef NOSEXP
 char * lastsexp = NULL;                        /* S-Expressions */
@@ -522,7 +524,6 @@ int                                 /* SET INPUT parameters. */
   inecho = 1,                          /* 1 = echo on */
   inautodl = 0,                                /* INPUT autodownload */
   inintr = 1,                          /* INPUT interrupion allowed */
-  innomatch = 0,                       /* INPUT /NOMATCH */
   insilence = 0;                       /* 0 = no silence constraint */
 
 #ifdef CKFLOAT
@@ -554,12 +555,35 @@ long ck_alarm = 0;                        /* SET ALARM value */
 char alrm_date[24] = { ' ',' ',' ',' ',' ',' ',' ',' ',' ' };
 char alrm_time[24] = { ' ',' ',' ',' ',' ',' ',' ' };
 
-#define INPSW_NOM 1
 struct keytab inputsw[] = {
-    { "/nomatch", INPSW_NOM, 0 }
+    { "/clear",   INPSW_CLR, 0 },
+    { "/count",   INPSW_COU, CM_ARG },
+    { "/nomatch", INPSW_NOM, 0 },
+    { "/nowrap",  INPSW_NOW, 0 }
 };
 static int ninputsw = sizeof(inputsw)/sizeof(struct keytab);
 
+/* The following should be reconciled with the above */
+
+#ifdef COMMENT                         /* INPUT switches not used yet... */
+static struct keytab inswtab[] = {
+#ifdef COMMENT
+    { "/assign",       IN_ASG, CM_ARG },
+#endif /* COMMENT */
+    { "/autodownload", IN_ADL, CM_ARG },
+    { "/case",         IN_CAS, CM_ARG },
+    { "/echo",         IN_ECH, CM_ARG },
+    { "/interrupts",   IN_NOI, CM_ARG },
+    { "/silence",      IN_SIL, CM_ARG },
+#ifdef COMMENT
+    { "/pattern",      IN_PAT, CM_ARG },
+#endif /* COMMENT */
+    { "", 0, 0 }
+};
+static int ninswtab = (sizeof(inswtab) / sizeof(struct keytab)) - 1;
+#endif /* COMMENT */
+
+
 #endif /* NOSPL */
 
 static int x, y, z = 0;                        /* Local workers */
@@ -768,10 +792,10 @@ struct keytab cmdtab[] = {
 #ifndef NOSPL
     { "date",        XXDATE,  0 },     /* DATE */
     { "dcl",         XXDCL,   CM_INV },        /* DECLARE an array (see ARRAY) */
-    { "debug",       XXDEBUG, CM_INV },
+    { "debug",       XXDEBUG, 0 },     /* Print a debugging msg [9.0]  */
     { "declare",     XXDCL,   CM_INV },        /* DECLARE an array (see ARRAY) */
     { "decrement",   XXDEC,   0 },     /* DECREMENT a numeric variable */
-    { "define",      XXDEF,   0 },     /* DEFINE a macro or variable */
+    { "define",      XXDEF,   0 },     /* DEFINE a macro or variable   */
 #else
     { "date",        XXNOTAV, CM_INV },
     { "dcl",         XXNOTAV, CM_INV },
@@ -996,6 +1020,7 @@ struct keytab cmdtab[] = {
 #ifndef NOLOCAL
     { "hangup",      XXHAN, CM_LOC },  /* HANGUP the connection */
 #endif /* NOLOCAL */
+    { "hdirectory",  XXHDIR,  CM_INV },        /* DIR sorted by size biggest first */
     { "HELP",        XXHLP, 0 },       /* Display HELP text */
 #ifndef NOHTTP
 #ifdef TCPSOCKET
@@ -1069,6 +1094,7 @@ struct keytab cmdtab[] = {
 #endif /* NT */
 
     { "lmkdir",      XXLMKD, CM_INV },
+    { "lmv",         XXLREN, CM_INV },
 
 #ifndef NOFRILLS
     { "lo",          XXLOG,  CM_INV|CM_ABR }, /* Invisible synonym for log */
@@ -1080,6 +1106,8 @@ struct keytab cmdtab[] = {
     { "local",       XXNOTAV, CM_INV },
 #endif /* NOSPL */
 
+    { "locus",       XXLOCU, CM_INV|CM_HLP }, /* "help locus" */
+
     { "log",        XXLOG, 0 },        /* Open a log file */
 
     { "login",       XXLOGIN,  0 },    /* (REMOTE) LOGIN to server or IKSD */
@@ -1113,6 +1141,7 @@ struct keytab cmdtab[] = {
 #ifdef CK_MKDIR
     { "md",          XXMKDIR, CM_INV },        /* Synonym for MKDIR */
 #endif /* CK_MKDIR */
+    { "message",     XXMSG, 0 },       /* Print debugging message */
 #ifdef CK_MINPUT
     { "minput",      XXMINP, 0 },      /* MINPUT */
 #else
@@ -1161,6 +1190,7 @@ struct keytab cmdtab[] = {
     { "msend",       XXNOTAV, CM_INV },
 #endif /* NOMSEND */
 #endif /* NOXFER */
+    { "msg",         XXMSG, CM_INV },  /* Print debugging message */
 #ifndef NOSPL
     { "msleep",      XXMSL, 0 },       /* Millisecond sleep */
 #else
@@ -1280,6 +1310,12 @@ struct keytab cmdtab[] = {
     { "put",         XXSEN, CM_INV },  /* PUT = SEND */
 #endif /* NOXFER */
 
+#ifdef UNIX
+#ifndef NOPUTENV
+    { "putenv",      XXPUTE, CM_INV }, /* PUTENV */
+#endif /* NOPUTENV */
+#endif /* UNIX */
+
     { "pwd",         XXPWD, 0 },       /* Print Working Directory */
     { "q",           XXQUI, CM_INV|CM_ABR }, /* Invisible synonym for QUIT */
 
@@ -1385,10 +1421,13 @@ struct keytab cmdtab[] = {
 
 #ifndef NOXFER
 #ifdef CK_RESEND
+    { "rep",         XXTYP, CM_INV|CM_ABR },  /* REPLAY abbreviation */
+    { "reput",       XXRSEN, CM_INV },       /* REPUT = RESEND */
     { "res",         XXRSEN, CM_INV|CM_ABR }, /* RESEND */
     { "rese",        XXRSEN, CM_INV|CM_ABR }, /* RESEND */
     { "resend",      XXRSEN, 0 },      /* RESEND */
 #else
+    { "reput",       XXNOTAV, CM_INV },
     { "res",         XXNOTAV, CM_INV },
     { "rese",        XXNOTAV, CM_INV },
     { "resend",      XXNOTAV, CM_INV },
@@ -1448,7 +1487,9 @@ struct keytab cmdtab[] = {
 #endif /* CK_MKDIR */
 
 #ifndef NOXFER
+    { "rmessage",    XXRMSG, CM_INV }, /* REMOTE MESSAGE */
     { "rmkdir",      XXRMKD, CM_INV }, /* REMOTE MKDIR */
+    { "rmsg",        XXRMSG, CM_INV }, /* REMOTE MESSAGE */
 #ifndef NOSPL
     { "robust",      XXROB,  CM_INV },
 #else
@@ -1648,7 +1689,7 @@ struct keytab cmdtab[] = {
 #ifndef NOXFER
     { "text",        XXASC, CM_INV },  /* == SET FILE TYPE TEXT */
 #endif /* NOXFER */
-
+    { "touch",       XXTOUC, 0 },      /* TOUCH */
 #ifndef NOSPL
     { "trace",       XXTRACE, 0 },     /* TRACE */
 #else
@@ -1699,6 +1740,7 @@ struct keytab cmdtab[] = {
     { "wait",        XXNOTAV, CM_INV },
 #endif /* NOSPL */
 
+    { "wdirectory",  XXWDIR,  CM_INV },        /* Like TOPS-20, reverse chron order */
     { "wermit",      XXKERMI, CM_INV },
 
 #ifndef NOXFER
@@ -1756,6 +1798,14 @@ struct keytab cmdtab[] = {
 #endif /* NOCSETS */
 
 #ifndef NOXMIT
+    { "xm",          XXTRA, CM_INV|CM_ABR }, /* Avoid conflict with XMESSAGE */
+#else
+    { "xm",          XXNOTAV, CM_INV|CM_ABR }, /* Synonym for TRANSMIT */
+#endif /* NOXMIT */
+
+    { "xmessage",    XXXMSG, 0 },      /* Print debugging message */
+
+#ifndef NOXMIT
     { "xmit",        XXTRA, CM_INV },  /* Synonym for TRANSMIT */
 #else
     { "xmit",        XXNOTAV, CM_INV },
@@ -1959,6 +2009,13 @@ struct keytab prmtab[] = {
 #endif /* NOSPL */
     { "exit",            XYEXIT,  0 },
 #ifndef NOXFER
+#ifdef CK_XYZ
+#ifndef NOPUSH
+#ifndef XYZ_INTERNAL
+    { "external-protocol",XYEXTRN, 0 },
+#endif /* XYZ_INTERNAL */
+#endif /* NOPUSH */
+#endif /* CK_XYZ */
     { "f-ack-bug",        XYFACKB, CM_INV },
     { "f-ack-path",       XYFACKP, CM_INV },
 #endif /* NOXFER */
@@ -2100,6 +2157,7 @@ struct keytab prmtab[] = {
     { "recv",             XYRECV,  CM_INV },
 #endif /* NOXFER */
     { "reliable",         XYRELY,  0 },
+    { "rename",           XY_REN,  0 },
 #ifndef NOXFER
     { "repeat",           XYREPT,  0 },
     { "retry-limit",      XYRETR,  0 },
@@ -2217,6 +2275,9 @@ struct keytab prmtab[] = {
 #ifndef NOCSETS
     { "unknown-char-set", XYUNCS,  0 },
 #endif /* NOCSETS */
+#ifndef NOSPL
+    { "variable-evaluation", XYVAREV, CM_INV },
+#endif /* NOSPL */
 #endif /* NOXFER */
     { "wait",             XYSLEEP, CM_INV },
 #ifndef NOPUSH
@@ -2631,6 +2692,7 @@ struct keytab remcmd[] = {
     { "log",       XZLGI, CM_ABR|CM_INV },
     { "login",     XZLGI, 0 },
     { "logout",    XZLGO, 0 },
+    { "message",   XZMSG, 0 },
     { "mkdir",     XZMKD, 0 },
     { "print",     XZPRI, 0 },
 #endif /* NOFRILLS */
@@ -2701,24 +2763,6 @@ struct keytab writab[] = {
 };
 int nwri = (sizeof(writab) / sizeof(struct keytab));
 
-#ifdef COMMENT                         /* INPUT switches not used yet... */
-static struct keytab inswtab[] = {
-#ifdef COMMENT
-    { "/assign",       IN_ASG, CM_ARG },
-#endif /* COMMENT */
-    { "/autodownload", IN_ADL, CM_ARG },
-    { "/case",         IN_CAS, CM_ARG },
-    { "/echo",         IN_ECH, CM_ARG },
-    { "/interrupts",   IN_NOI, CM_ARG },
-    { "/silence",      IN_SIL, CM_ARG },
-#ifdef COMMENT
-    { "/pattern",      IN_PAT, CM_ARG },
-#endif /* COMMENT */
-    { "", 0, 0 }
-};
-static int ninswtab = (sizeof(inswtab) / sizeof(struct keytab)) - 1;
-#endif /* COMMENT */
-
 static struct keytab clrtab[] = {      /* Keywords for CLEAR command */
 #ifndef NOSPL
     { "alarm",            CLR_ALR,         0 },
@@ -2964,6 +3008,7 @@ struct keytab shotab[] = {
 #ifndef NOXFER
     { "protocol",     SHPRO,  0 },
 #endif /* NOXFER */
+    { "rename",       SHOREN, 0 },
 #ifndef NOSPL
     { "scripts",      SHSCR,  CM_LOC },
 #endif /* NOSPL */
@@ -3486,8 +3531,9 @@ setlocus(x, isauto) int x, isauto; {
     } else {
 #endif /* OS2 */
         if (isauto && msgflg && !quitting)
-          printf("Switching LOCUS for file-management commands to %s.\n",
-                x ? "LOCAL" : "REMOTE"
+          printf("Switching LOCUS for file-management commands to %s %s.\n",
+                x ? "LOCAL" : "REMOTE",
+                "(HELP LOCUS for info)"
                 );
        locus = x;
 #ifdef OS2
@@ -3559,7 +3605,6 @@ _PROTOTYP (int doask,    ( int  ) );
 _PROTOTYP (int dodef,    ( int  ) );
 _PROTOTYP (int doelse,   ( void ) );
 _PROTOTYP (int dofor,    ( void ) );
-_PROTOTYP (int doincr,   ( int  ) );
 #endif /* NOSPL  */
 #ifndef NODIAL
 _PROTOTYP (int dodial,   ( int  ) );
@@ -3894,10 +3939,7 @@ doxsend(cx) int cx; {
     extern int rprintf;                        /* REMOTE PRINT flag */
     extern int fdispla;                        /* TRANSFER DISPLAY setting */
     extern int skipbup;                        /* Skip backup files when sending */
-    struct stringint {                 /* Temporary array for switch values */
-       char * sval;
-       int ival;
-    } pv[SND_MAX+1];
+    struct stringint pv[SND_MAX+1];    /* Temporary array for switch values */
     struct FDB sf, sw, fl, cm;         /* FDBs for each parse function */
     int mlist = 0;                     /* Flag for MSEND or MMOVE */
     char * m;                          /* For making help messages */
@@ -3905,7 +3947,7 @@ doxsend(cx) int cx; {
     extern int xfrxla, g_xfrxla, nprotos;
     extern char sndbefore[], sndafter[], *sndexcept[]; /* Selection criteria */
     extern char sndnbefore[], sndnafter[];
-    extern long sndsmaller, sndlarger, calibrate;
+    extern CK_OFF_T sndsmaller, sndlarger, calibrate;
 #ifndef NOSPL
     int range[2];                      /* Array range */
     char ** ap = NULL;                 /* Array pointer */
@@ -3925,6 +3967,7 @@ doxsend(cx) int cx; {
     for (i = 0; i <= SND_MAX; i++) {   /* Initialize switch values */
        pv[i].sval = NULL;              /* to null pointers */
        pv[i].ival = -1;                /* and -1 int values */
+       pv[i].wval = (CK_OFF_T)-1;      /* and -1 wide values */
     }
 #ifndef NOSPL
     range[0] = -1;
@@ -4171,13 +4214,14 @@ doxsend(cx) int cx; {
            break;
 
          case SND_SMA:                 /* Smaller / larger than */
-         case SND_LAR:
-           if (!getval) break;
-           if ((x = cmnum("Size in bytes","0",10,&y,xxstring)) < 0)
-             goto xsendx;
-           pv[n].ival = y;
-           break;
-
+         case SND_LAR: {
+             CK_OFF_T w;
+             if (!getval) break;
+             if ((x = cmnumw("Size in bytes","0",10,&w,xxstring)) < 0)
+               goto xsendx;
+             pv[n].wval = w;
+             break;
+         }
          case SND_AFT:                 /* Send /AFTER:date-time */
          case SND_BEF:                 /* Send /BEFORE:date-time */
          case SND_NAF:                 /* Send /NOT-AFTER:date-time */
@@ -4260,13 +4304,14 @@ doxsend(cx) int cx; {
            }
            break;
 
-         case SND_STA:                 /* Starting position (= PSEND) */
-           if (!getval) break;
-           if ((x = cmnum("0-based position","0",10,&y,xxstring)) < 0)
-             goto xsendx;
-           pv[n].ival = y;
-           break;
-
+         case SND_STA: {               /* Starting position (= PSEND) */
+             CK_OFF_T w;
+             if (!getval) break;
+             if ((x = cmnumw("0-based position","0",10,&w,xxstring)) < 0)
+               goto xsendx;
+             pv[n].wval = w;
+             break;
+         }
          case SND_PRO:                 /* Protocol to use */
            if (!getval) break;
            if ((x = cmkey(protos,nprotos,"File-transfer protocol","",
@@ -4334,16 +4379,18 @@ doxsend(cx) int cx; {
            break;
 
 #ifdef CALIBRATE
-          case SND_CAL:                        /* /CALIBRATE */
-           if (getval) {
-               if ((x = cmnum("number of Kbytes to send",
-                          "1024",10,&y,xxstring)) < 0)
-                 goto xsendx;
-           } else
-             y = 1024;
-           pv[n].ival = y;
-           pv[SND_ARR].ival = 0;
-           break;
+          case SND_CAL: {              /* /CALIBRATE */
+             CK_OFF_T w;
+             if (getval) {
+                 if ((x = cmnumw("number of Kbytes to send",
+                                 "1024",10,&w,xxstring)) < 0)
+                   goto xsendx;
+             } else
+               w = (CK_OFF_T)1024;
+             pv[n].wval = w;
+             pv[SND_ARR].ival = 0;
+             break;
+         }
 #endif /* CALIBRATE */
 
          case SND_FIL:                 /* Name of file containing filnames */
@@ -4439,7 +4486,7 @@ doxsend(cx) int cx; {
        goto xsendx;
     }
     if (pv[SND_RES].ival > 0 ||        /* /RECOVER */
-       pv[SND_STA].ival > 0) { /* or /STARTING */
+       pv[SND_STA].wval > 0) { /* or /STARTING */
        if (sndfilter || pv[SND_FLT].ival > 0) {
            printf("?Sorry, no /RECOVER or /START if SEND FILTER selected\n");
            x = -9;
@@ -4704,14 +4751,14 @@ doxsend(cx) int cx; {
        x = -9;
        goto xsendx;
     }
-    if (pv[SND_STA].ival > 0) {                /* /START */
+    if (pv[SND_STA].wval > 0) {                /* /START */
        if (wild) {
            printf("?Sorry, wildcards not permitted with /START\n");
            x = -9;
            goto xsendx;
        }
        if (sizeof(int) < 4) {
-           printf("?Sorry, this command needs 32-bit integers\n");
+           printf("?Sorry, this command needs at least 32-bit integers\n");
            x = -9;
            goto xsendx;
        }
@@ -4909,9 +4956,9 @@ like \\v(filename)";
 #endif /* NOFRILLS */
 
 #ifdef CALIBRATE
-    if (pv[SND_CAL].ival > 0) {                /* Handle /CALIBRATE */
+    if (pv[SND_CAL].wval > 0) {                /* Handle /CALIBRATE */
        if (confirmed) {
-           calibrate = pv[SND_CAL].ival * 1024L;
+           calibrate = pv[SND_CAL].wval * (CK_OFF_T)1024;
            sndsrc = -9;
            nfils = 1;
            wild = 0;
@@ -4923,8 +4970,9 @@ like \\v(filename)";
            if (!cmarg2) cmarg2 = "";
            debug(F110,"doxsend cmarg2 calibrate",cmarg2,0);
        } else if (line[0]) {
-           calibrate = 0L;
-           pv[SND_CAL].ival = 0L;
+           calibrate = 0;
+           pv[SND_CAL].ival = 0;
+           pv[SND_CAL].wval = 0;
        }
     }
 #endif /* CALIBRATE */
@@ -4983,7 +5031,7 @@ like \\v(filename)";
        cmlist = msfiles;               /* List of files to send */
        sndsrc = nfils;
        cmarg2 = "";
-       sendstart = 0L;
+       sendstart = (CK_OFF_T)0;
 #endif /* NOMSEND */
 #ifdef PIPESEND
        pipesend = 0;
@@ -5007,10 +5055,10 @@ like \\v(filename)";
            1
 #endif /* NOFRILLS */
            ) {
-           int y = 1;
+           CK_OFF_T y = (CK_OFF_T)1;
            if (!wild)
              y = zchki(s);
-           if (y < 0) {
+           if (y < (CK_OFF_T)0) {
                printf("?Read access denied - \"%s\"\n", s);
                x = -9;
                goto xsendx;
@@ -5074,15 +5122,15 @@ like \\v(filename)";
 
 #ifdef CK_RESEND
        debug(F111,"xsend pv[SND_STA].ival","",pv[SND_STA].ival);
-       if (pv[SND_STA].ival > -1) {    /* /START position */
+       if (pv[SND_STA].wval > (CK_OFF_T)-1) { /* /START position */
            if (wild) {
                printf("?/STARTING-AT may not be used with multiple files.\n");
                x = -9;
                goto xsendx;
            } else
-             sendstart = pv[SND_STA].ival;
+             sendstart = pv[SND_STA].wval;
        } else
-         sendstart = 0L;
+         sendstart = (CK_OFF_T)0;
        debug(F101,"xsend /STARTING","",sendstart);
 #endif /* CK_RESEND */
     }
@@ -5144,10 +5192,10 @@ sendend:                                /* Common successful exit */
          ckstrncpy(sndnbefore,pv[SND_NBE].sval,19);
        if (pv[SND_EXC].ival > 0)
          makelist(pv[SND_EXC].sval,sndexcept,NSNDEXCEPT);
-       if (pv[SND_SMA].ival > -1)
-         sndsmaller = pv[SND_SMA].ival;
-       if (pv[SND_LAR].ival > -1)
-         sndlarger = pv[SND_LAR].ival;
+       if (pv[SND_SMA].wval > (CK_OFF_T)-1)
+         sndsmaller = pv[SND_SMA].wval;
+       if (pv[SND_LAR].wval > (CK_OFF_T)-1)
+         sndlarger = pv[SND_LAR].wval;
        if (pv[SND_NAM].ival > -1) {
            g_fncnv = fncnv;            /* Save global value */
            fncnv = pv[SND_NAM].ival;
@@ -5270,10 +5318,7 @@ static int g_tt_idlelimit, g_tt_saved = 0;
 static char * g_tt_idlesnd_str;                /* global settings */
 #endif /* OS2 */
 
-static struct stringint {              /* Temporary array for switch values */
-    char * sval;
-    int ival;
-} pv[CONN_MAX+1];
+static struct stringint pv[CONN_MAX+1];
 
 VOID
 resconn() {
@@ -5335,6 +5380,7 @@ doxconn(cx) int cx; {
     for (i = 0; i <= CONN_MAX; i++) {  /* Initialize switch values */
        pv[i].sval = NULL;              /* to null pointers */
        pv[i].ival = -1;                /* and -1 int values */
+       pv[i].wval = (CK_OFF_T)-1;
     }
     if (cx == XXCQ)                    /* CQ == CONNECT /QUIETLY */
       pv[CONN_NV].ival = 1;
@@ -5483,6 +5529,25 @@ doxconn(cx) int cx; {
     }
 #endif /* CK_TRIGGER */
 
+#ifdef SSHCMD
+/*
+  2010/03/01...
+  The previous connection was through the external ssh client and now, with
+  that connection closed, the user says "connect" and expects a new connection
+  to be made to the same host, because that's how all the other connection
+  methods work, so (and this is quite a hack)...
+*/
+    if (!ckstrcmp("ssh ",ttname,4,0)) {        /* Previous "host" was "ssh blah" */
+       _PROTOTYP (int redossh, ( void ) );
+       extern int ttyfd;
+       if (ttyfd < 0) {                /* And connection is no longer open */
+           int xx;
+           xx = redossh();             /* So redo the SSH connection */
+           if (xx < 0) return(xx);
+           goto xconnx;
+       }
+    }
+#endif /* SSHCMD */
     x = doconect((pv[CONN_NV].ival > 0) ? 1 : 0, async);
     {
        int xx;
@@ -6015,11 +6080,17 @@ dodcl(cx) int cx; {
                      "]",
                      NULL,NULL,NULL,NULL,NULL,NULL,NULL
                      );
-           if ((rc = cmfld((char *)tmp,"",&s,xxstring)) < 0) { /* Get field */
-               if (rc == -3)           /* If answer is empty, we're done */
-                 break;
-               else                    /* Parse error, free temp pointers */
-                 goto dclx;
+           
+           rc = cmfld((char *)tmp,"",&s,xxstring); /* Get field */
+           if (rc < 0) {               /* Error... */
+               if (rc == -3) {         /* Empty element */
+                   if (cmflgs == 1)    /* because end of line? */
+                     break;            /* Yes, done initializing */
+                   else                /* No, it's just empty */
+                     continue;         /* Go on to next one. */
+               } else {                /* Other parse error */
+                   goto dclx;          /* Go free temp pointers */
+               }
            }
            rc = 1;
            if (v == 0 && !strcmp(s,"=")) /* Skip the = sign. */
@@ -6219,7 +6290,7 @@ unarray() {
            printf("?Sorry, \\&@[] is read-only\n");
            return(-9);
        }
-       rc = dclarray(c,0);             /* Undeclare the array */
+       rc = dclarray(c,-1);            /* Undeclare the array */
     } else                             /* It wasn't declared */
       rc = 1;
     if (rc > -1) {                     /* Set return code and success */
@@ -6782,25 +6853,19 @@ doedit() {
   a nonexistent file to be created.
 */
     x = cmiofi("File to edit", (char *)tmpbuf, &s, &y, xxstring);
-    if (x < 0) {
-       if (x == -9) {
-           if (zchko(s) < 0) {
-               printf("Can't create \"%s\"\n",s);
-               return(x);
-           }
-       } else if (x != -3)
-         return(x);
-    }
-    if (x == -3)
-      tmpbuf[0] = NUL;
-    else {
+    debug(F111,"edit",s,x);
+    if (x < 0 && x != -3)
+      return(x);
+    if (x == -3) {
+       tmpbuf[0] = NUL;
+    } else {
        ckstrncpy(tmpbuf,s,TMPBUFSIZ);
-       if (iswild((char *)tmpbuf)) {
-           printf("?A single file please\n");
-           return(-9);
-       }
     }
     if ((z = cmcfm()) < 0) return(z);
+    if (y) {
+       printf("?A single file please\n");
+       return(-9);
+    }
     if (nopush) {
        printf("?Sorry, editing not allowed\n");
        return(success = 0);
@@ -6818,6 +6883,12 @@ doedit() {
 #endif /* OS2 */
     } else
       editfile[0] = NUL;
+    if (editfile[0]) {
+       if (zchki(editfile) < (CK_OFF_T)0 && zchko(editfile) < 0) {
+           printf("?Access denied: %s\n",editfile);
+           return(-9);
+       }
+    }
     x = 0;
     if (editopts[0]) {
 #ifdef OS2
@@ -7369,6 +7440,8 @@ dohttp() {                                /* HTTP */
       }
       case HTTP_GET:                   /* GET */
       case HTTP_IDX: {                 /* INDEX */
+         extern int wildena;
+         int tmp;
          char * lfile = "";
          if ((x = cmfld("URL or remote source file","",&s,xxstring)) < 0) {
              if (x == -3) {
@@ -7380,9 +7453,16 @@ dohttp() {                               /* HTTP */
          makestr(&http_rfile,s);
          if (http_action == HTTP_GET && !http_type)
            zstrip(http_rfile,&lfile);
-         if ((x = cmofi("Local filename",lfile,&s,xxstring)) < 0)
-           if (x != -3)
-             goto xhttp;
+         /* URLs often contain question marks or other metacharacters */
+         /* cmofi() doesn't like them */
+         tmp = wildena;
+         wildena = 0;
+         if ((x = cmofi("Local filename",lfile,&s,xxstring)) < 0) {
+             wildena = tmp;
+             if (x != -3)
+               goto xhttp;
+         }
+         wildena = tmp;
          makestr(&http_lfile,s);
          break;
       }
@@ -7736,6 +7816,85 @@ learncmd(s) char *s; {                   /* Record commands in learned script */
 #endif /* CKLEARN */
 
 
+#ifdef SSHCMD
+/*
+  2010/03/01...
+  Reopen a connection that was made with an external ssh client
+  after it has been closed.
+ */
+int
+redossh() {
+    int x, netsave;
+    x = nettype;
+    debug(F111,"redossh nettype",ttname,nettype);
+    if ((y = setlin(XXSSH,0,1)) < 0) {
+       if (errno)
+         printf("?%s\n",ck_errstr());
+       else
+         return(y);
+       nettype = x;                    /* Failed, restore net type. */
+       success = 0;
+       return(y);
+    }
+    netsave = x;
+    return(y);
+}
+#endif /* SSHCMD */
+
+/*
+  Like hmsga() in ckuus2.c but takes a single substitution parameter, s2,
+  which replaces every occurrence of "%s" in the first argument.
+  Added to print text containing the copyright year, so the year doesn't 
+  have to be hardwired into lots of scattered text strings.
+*/
+int                                     /* Print an array of lines, */
+#ifdef CK_ANSIC
+hmsgaa(char *s[], char *s2)            /* pausing at end of each screen. */
+#else
+hmsgaa(s,s2) char *s[]; char *s2;
+#endif /* CK_ANSIC */
+{
+    extern int hmtopline;
+#ifdef OS2
+    extern int tt_rows[], tt_cols[];
+#else /* OS2 */
+    extern int tt_rows, tt_cols;
+#endif /* OS2 */
+    int x, y, i, j, k, n;
+    if ((x = cmcfm()) < 0) return(x);
+
+#ifdef CK_TTGWSIZ
+#ifdef OS2
+    ttgcwsz();
+#else /* OS2 */
+    /* Check whether window size changed */
+    if (ttgwsiz() > 0) {
+        if (tt_rows > 0 && tt_cols > 0) {
+            cmd_rows = tt_rows;
+            cmd_cols = tt_cols;
+        }
+    }
+#endif /* OS2 */
+#endif /* CK_TTGWSIZ */
+
+    printf("\n");                       /* Start off with a blank line */
+    n = (hmtopline > 0) ? hmtopline : 1; /* Line counter */
+    for (i = 0; *s[i]; i++) {
+        printf((char *)s[i],s2);       /* Print a line. */
+       printf("\n");
+        y = (int)strlen(s[i]);
+        k = 1;
+        for (j = 0; j < y; j++)         /* See how many newlines were */
+          if (s[i][j] == '\n') k++;     /* in the string... */
+        n += k;
+        if (n > (cmd_rows - 3) && *s[i+1]) /* After a screenful, give them */
+          if (!askmore()) return(0);    /* a "more?" prompt. */
+          else n = 0;
+    }
+    printf("\n");
+    return(0);
+}
+
 /*  D O C M D  --  Do a command  */
 
 /*
@@ -7884,7 +8043,7 @@ docmd(cx) int cx; {
            } else
              return(y);
        }
-       ckstrncpy(lblbuf,s,LBLSIZ);
+       ckstrncpy(tmpbuf,s,TMPBUFSIZ);
        if ((x = cmcfm()) < 0) return(x);
 #else
        if ((y = cmtxt("label","",&s,xxstring)) < 0) {
@@ -7898,9 +8057,9 @@ docmd(cx) int cx; {
            } else
              return(y);
        }
-       ckstrncpy(lblbuf,brstrip(s),LBLSIZ);
+       ckstrncpy(tmpbuf,brstrip(s),TMPBUFSIZ);
 #endif /* COMMENT */
-       s = lblbuf;
+       s = tmpbuf;
        debug(F111,"GOTO target",s,cx);
        return(dogoto(s,cx));
     }
@@ -7983,8 +8142,7 @@ docmd(cx) int cx; {
            line[k++] = SP;
            line[k] = NUL;
            debug(F111,"XXMACRO A",line,k);
-           /* Defer evaluation of variables until the commands are exec'd */
-           if ((y = cmtxt("Braced list of commands","",&s,NULL)) < 0)
+           if ((y = cmtxt("Braced list of commands","",&s,xxstring)) < 0)
              return(y);
            k = ckstrncpy(line+k,s,LINBUFSIZ-k);
            debug(F111,"XXMACRO B",line,k);
@@ -8071,7 +8229,7 @@ docmd(cx) int cx; {
            if (x < 0)
              return(x);
            if (!*s)                    /* Needed for (=) and (:) */
-             s = atmbuf;
+             s = cmdbuf+1;             /* I can't explain why. */
            k = ckmakmsg(tmp, size, contd ? " " : "(", s, NULL, NULL);
            if (k < 1) {
                printf("?SEXP too long - %d max\n",TMPBUFSIZ);
@@ -8150,7 +8308,7 @@ docmd(cx) int cx; {
          return(x);
        if (!s) s = "";
 #ifdef COMMENT
-/* This is to preserver the pre-8.0 behavior but it's too confusing */
+/* This is to preserve the pre-8.0 behavior but it's too confusing */
        x = strlen(s);
        x = (x > 1) ? ((s[0] == '"' && s[x-1] == '"') ? 1 : 0) : 0;
 #endif /* COMMENT */
@@ -8244,11 +8402,13 @@ docmd(cx) int cx; {
 #endif /* NOSPL */
 
 #ifndef NOFRILLS
+#ifndef NOHELP
     if (cx == XXBUG) {                 /* BUG */
        if ((x = cmcfm()) < 0) return(x);
        return(dobug());
     }
-#endif /* NOFRILLS */
+#endif /* NOHELP */
+#endif /* NOFRILLS */
 
 #ifndef NOXFER
     if (cx == XXBYE) {                 /* BYE */
@@ -8516,7 +8676,13 @@ docmd(cx) int cx; {
     }
 #endif /* NOFRILLS */
 
-    if (cx == XXDIR || cx == XXLS || cx == XXLDIR) { /* DIRECTORY or LS */
+    if (cx == XXTOUC)                  /* TOUCH */
+      return(dodir(cx));
+
+    /* DIRECTORY commands */
+
+    if (cx == XXDIR  || cx == XXLS || cx == XXLDIR ||
+       cx == XXWDIR || cx == XXHDIR) {
 #ifdef LOCUS
        if (!locus && cx != XXLDIR) {
 #ifdef NOXFER
@@ -8929,15 +9095,18 @@ docmd(cx) int cx; {
 #ifdef NOHELP
        return(dohlp(XXHLP));
 #else
-       x = cmkey2(cmdtab,ncmd,"\nCommand or topic","help",toktab,xxstring,3);
-       debug(F101,"HELP command x","",x);
+       x = cmkey2(cmdtab,
+                  ncmd,"\nCommand or topic","help",toktab,xxstring,1+2+8);
+       debug(F111,"HELP command x",cmdbuf,x);
        if (x == -5) {
            y = chktok(toktab);
            debug(F101,"HELP cmkey token","",y);
            /* ungword(); */
            switch (y) {
 #ifndef NOPUSH
-             case '!': x = XXSHE; break;
+             case '!':
+             case '@': x = XXSHE; break;
+             case '<': x = XXFUN; break;
 #endif /* NOPUSH */
              case '#': x = XXCOM; break;
              case ';': x = XXCOM; break;
@@ -8948,7 +9117,10 @@ docmd(cx) int cx; {
              case '(': x = XXSEXP; break;
 #endif /* NOSEXP */
 #endif /* NOSPL */
-             case '&': x = XXECH; break;
+#ifdef CK_RECALL
+             case '^': x = XXREDO; break;
+#endif /* CK_RECALL */
+             case '&': x = XXECH; break; /* (what is this?) */
              default:
                printf("\n?Invalid - %s\n",cmdbuf);
                x = -2;
@@ -9041,7 +9213,9 @@ docmd(cx) int cx; {
 
     if (cx == XXINP || cx == XXREI || cx == XXMINP) {
        long zz;
-       extern int ispattern, isjoin;
+       int flags = 0, incount = 0;
+       extern int itsapattern, isjoin, isinbuflen;
+       int c, getval;
 
        struct FDB sw, nu, fl;
        int fc, havetime = 0;
@@ -9050,11 +9224,9 @@ docmd(cx) int cx; {
        if (cx == XXREI) {
            m = "Timeout in seconds (ignored)";
        } else {
-           m = "Seconds to wait for input,\n or time of day hh:mm:ss, \
+           m = "Seconds to wait for input,\n or time of day hh:mm:ss,\
  or switch";
        }
-       innomatch = 0;                  /* Initialize switch value(s) */
-
        cmfdbi(&sw,                     /* First FDB - command switches */
               _CMKEY,                  /* fcode */
               m,                       /* helpmsg */
@@ -9090,6 +9262,17 @@ docmd(cx) int cx; {
               );
        fc = (cx == XXREI) ? cmfdb(&nu) : cmfdb(&sw); /* Parse something */
 
+       for (y = 0; y < MINPMAX; y++) { /* Initialize search strings */
+           mp[y] = 0;                  /* Assume it's not a pattern */
+           if (!mpinited) {
+               ms[y] = NULL;
+           }
+           if (ms[y]) {
+               free(ms[y]);            /* Free old strings, if any */
+               ms[y] = NULL;
+           }
+       }
+       mpinited = 1;
        while (!havetime) {
            if (fc < 0) {               /* Error */
                if (fc == -3) {
@@ -9100,12 +9283,20 @@ docmd(cx) int cx; {
            }
            switch (cmresult.fcode) {
              case _CMKEY:              /* Switch */
-               if (cmresult.nresult == INPSW_NOM) /* /NOMATCH */
-                 innomatch = 1;
-               m = "Seconds to wait for input,\n or time of day hh:mm:ss";
-               cmfdbi(&nu,_CMNUM,m,"","",10,0,xxstring,NULL,&fl);
-               cmfdbi(&fl,_CMFLD,"","","",0,0,xxstring,NULL,NULL);
-               fc = cmfdb(&nu);        /* Parse something */
+               c = cmgbrk();
+               if ((getval = (c == ':' || c == '=')) &&
+                   !(cmgkwflgs() & CM_ARG)) {
+                   printf("?This switch does not take an argument\n");
+                   return(-9);
+               }
+               if (getval && cmresult.nresult == INPSW_COU) {
+                   if ((y = cmnum("Number of bytes to read",
+                                  "",10,&x,xxstring)) < 0)
+                     return(y);
+                   incount = x;
+               }
+               flags |= cmresult.nresult;
+               fc = cmfdb(&sw);        /* Maybe parse more switches */
                continue;
 
              case _CMNUM:              /* Seconds to time out */
@@ -9152,13 +9343,6 @@ docmd(cx) int cx; {
        /* Now parse the search text */
 
 #ifdef CK_MINPUT
-       for (y = 0; y < MINPMAX; y++) { /* Initialize strings */
-           mp[y] = 0;                  /* Assume it's not a pattern */
-           if (ms[y]) {
-               free(ms[y]);            /* Free old strings, if any */
-               ms[y] = NULL;
-           }
-       }
        if (cx == XXMINP) {             /* MINPUT */
            int i, k = 0, n = 0;
            struct stringarray * q;
@@ -9192,8 +9376,8 @@ docmd(cx) int cx; {
                } else {
                    if (s) if (*s) {
                        makestr(&(ms[k]),brstrip(s));
-                       if (ispattern) mp[k] = 1;
-                       debug(F111,"MINPUT",ms[k],ispattern);
+                       if (itsapattern) mp[k] = 1;
+                       debug(F111,"MINPUT",ms[k],itsapattern);
                        k++;
                    }
                }
@@ -9204,9 +9388,14 @@ docmd(cx) int cx; {
 
            /* INPUT or REINPUT */
 
-           if ((y = cmtxt("Material to be input","",&s,xxstring)) < 0)
-             return(y);
-           mp[0] = ispattern ? 1 : 0;
+           if (flags & INPSW_COU) {
+               if ((y = cmcfm()) < 0)
+                 return(y);
+           } else {
+               if ((y = cmtxt("Material to be input","",&s,xxstring)) < 0)
+                 return(y);
+           }
+           mp[0] = itsapattern ? 1 : 0;
            makestr(&(ms[0]),brstrip(s));
            ms[1] = NULL;
 
@@ -9214,19 +9403,16 @@ docmd(cx) int cx; {
        }
 #endif /* CK_MINPUT */
 
-#ifdef COMMENT
-       printf("/NOMATCH=%d\n",innomatch);
-       printf("Timeout=%d\n",x);
-       return(1);
-#endif /* COMMENT */
+       if (incount > 0)                /* No searching if /COUNT: given */
+         makestr(&(ms[0]),NULL);
 
        if (cx == XXINP || cx == XXMINP) { /* Not REINPUT... */
            i_active = 1;
            /* Go try to input the search string */
-           success = doinput(x,ms,mp,innomatch);
+           success = doinput(x,ms,mp,flags,incount);
            i_active = 0;
        } else {                        /* REINPUT */
-           success = doreinp(x,ms[0],ispattern);
+           success = doreinp(x,ms[0],itsapattern);
        }
        if (intime[cmdlvl] && !success) { /* TIMEOUT-ACTION = QUIT? */
            popclvl();                  /* If so, pop command level. */
@@ -9439,7 +9625,7 @@ docmd(cx) int cx; {
 
 #ifdef CK_RESEND
     if (cx == XXPSEN) {                        /* PSEND */
-       int seekto = 0;
+       int seekto = 0;                 /* FIX THIS */
 
        cmarg = cmarg2 = "";
        x = cmifi("File to partially send", "", &s, &y, xxstring);
@@ -10481,6 +10667,7 @@ necessary DLLs did not load.  Use SHOW NETWORK to check network status.\n");
 #endif /* NOSPL */
 
            /* Line parameter to ttopen() is ignored */
+           debug(F110,"SSH line",line,0);
            k = ttopen(line,&x,mdmtyp, 0);
            if (k < 0) {
                printf("?Unable to connect to %s\n",ssh_hst);
@@ -12243,7 +12430,11 @@ necessary DLLs did not load.  Use SHOW NETWORK to check network status.\n"
        if ((y = cmcfm()) < 0)
           return(y);
 
+#ifdef CK_64BIT
+       printf("\n%s, for%s (64-bit)\n Numeric: %ld",versio,ckxsys,vernum);
+#else
        printf("\n%s, for%s\n Numeric: %ld",versio,ckxsys,vernum);
+#endif /* CK_64BIT */
        printf("\n\n");
         printf("Authors:\n");
        printf(" Frank da Cruz, Columbia University\n");
@@ -12274,15 +12465,11 @@ necessary DLLs did not load.  Use SHOW NETWORK to check network status.\n"
     }
 
     if (cx == XXCPR) {                 /* COPYRIGHT or LICENSE */
+        _PROTOTYP( int hmsgaa, (char * [], char *) );
+        extern char * ck_cryear;
        if ((y = cmcfm()) < 0)
           return(y);
-#ifdef OS2
-       if (inserver) {                 /* Free WIKSD */
-           extern char * wiksdcpr[];
-           hmsga(wiksdcpr);
-       } else
-#endif /* OS2 */
-         hmsga(copyright);
+       hmsgaa(copyright,ck_cryear);
        return(success = 1);
     }
 
@@ -12358,11 +12545,15 @@ necessary DLLs did not load.  Use SHOW NETWORK to check network status.\n"
        }
        if (chkfn(y) > 0) {
            x = (cx == XXWRI) ? zsout(y,s) : zsoutl(y,s);
+           debug(F111,"WRITE",
+                 (cx == XXWRI) ? "zsout" : "zsoutl",
+                 x);
            if (x < 0) printf("?Write error\n");
        } else {
            x = -1;
            printf("?File or log not open\n");
        }
+       debug(F101,"WRITE x","",x);
        return(success = (x == 0) ? 1 : 0);
     }
 #endif /* NOFRILLS */
@@ -12371,9 +12562,18 @@ necessary DLLs did not load.  Use SHOW NETWORK to check network status.\n"
     if (cx == XXASC || cx == XXBIN) {
        if ((x = cmcfm()) < 0) return(x);
 #ifdef NEWFTP
-       if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
-         return(success = doftptyp((cx == XXASC) ? 0 : 1));
+/*
+  Make C-Kermit work like other ftp clients, where
+  the ASCII (TEXT) and BINARY commands are global settings.
+*/
+       if (ftpisopen()) {
+           doftpglobaltype((cx == XXASC) ? XYFT_T : XYFT_B);
+           /* Fall thru--the command it should apply to both FTP and Kermit */
+           /* return(success = 1); */
+       }
 #endif /* NEWFTP */
+
+       xfermode = XMODE_M;             /* Set manual Kermit transfer mode */
        binary = (cx == XXASC) ? XYFT_T : XYFT_B;
        return(success = 1);
     }
@@ -12666,6 +12866,8 @@ necessary DLLs did not load.  Use SHOW NETWORK to check network status.\n"
       return(dormt(XZREN));
     if (cx == XXRMKD)
       return(dormt(XZMKD));
+    if (cx == XXRMSG)
+      return(dormt(XZMSG));
     if (cx == XXRRMD)
       return(dormt(XZRMD));
     if (cx == XXRSET)
@@ -12685,6 +12887,7 @@ necessary DLLs did not load.  Use SHOW NETWORK to check network status.\n"
     if (cx == XXRESET) {               /* RESET */
        if ((x = cmcfm()) < 0)
          return(x);
+       concb((char)escape);            /* Make command echoing to normal */
        doclean(0);                     /* Close all files */
        return(success = 1);
     }
@@ -12852,7 +13055,7 @@ necessary DLLs did not load.  Use SHOW NETWORK to check network status.\n"
            return(-9);
        }
     }
-    if (cx == XXTRACE)
+    if (cx == XXTRACE)                 /* TRACE */
       return(dotrace());
 #endif /* NOSPL */
 
@@ -12877,6 +13080,29 @@ necessary DLLs did not load.  Use SHOW NETWORK to check network status.\n"
        return(seton(&deblog));
 #endif /* DEBUG */
     }
+    if (cx == XXMSG || cx == XXXMSG) { /* MESSAGE */
+       extern int debmsg;              /* Script debugging messages */
+       if ((x = cmtxt("Message to print if SET DEBUG MESSAGE is ON or STDERR",
+                "",&s,xxstring)) < 0)
+         return(x);
+       if (!s)                         /* Watch out for null result */
+         s = "";                       /* Make it an empty string */
+       else                            /* Not null */
+         s = brstrip(s);               /* Strip braces and doublequotes */
+       switch (debmsg) {               /* Not debugging - don't print */
+         case 0:
+           break;
+         case 1:
+           printf("%s",s);             /* Print to stdout */
+           if (cx == XXMSG) printf("\n");
+           break;
+         case 2:
+           fprintf(stderr,"%s",s);     /* Ditto but print to stderr */
+           if (cx == XXMSG) fprintf(stderr,"\n");
+           break;
+       }
+       return(0);                      /* Return without affecting SUCCESS */
+    }
 
 #ifdef CKLEARN
     if (cx == XXLEARN) {               /* LEARN */
@@ -13105,6 +13331,35 @@ necessary DLLs did not load.  Use SHOW NETWORK to check network status.\n"
 #endif /* NOSPL */
        }
     }
+#ifdef UNIX
+#ifndef NOPUTENV
+/*
+  NOTE: Syntax is PUTENV name value, not PUTENV name=value.
+  I could check for this but it would be too much magic.
+*/
+    if (cx == XXPUTE) {                        /* PUTENV */
+        char * t = tmpbuf;             /* Create or alter environment var */
+       char * s1 = NULL, * s2 = NULL;
+       if ((x = cmfld("Variable name","",&s,xxstring)) < 0)
+          return(x);
+       if (s) if (s == "") s = NULL;
+       (VOID) makestr(&s1,s);
+       if (s && !s1) {
+           printf("?PUTENV - memory allocation failure\n");
+           return(-9);
+       }
+       if ((x = cmtxt("Value","",&s,xxstring)) < 0)
+         return(x);
+       if (s) if (s == "") s = NULL;
+       (VOID) makestr(&s2,s);
+       success = doputenv(s1,s2);
+       (VOID) makestr(&s1,NULL);
+       (VOID) makestr(&s2,NULL);
+       return(success);
+    }
+#endif /* NOPUTENV */
+#endif /* UNIX */
+
     if (cx == XXNOTAV) {               /* Command in table not available */
        ckstrncpy(tmpbuf,atmbuf,TMPBUFSIZ);
        if ((x = cmtxt("Rest of command","",&s,NULL)) < 0)
index eecb78c..83891fb 100644 (file)
--- a/ckuusr.h
+++ b/ckuusr.h
@@ -4,7 +4,7 @@
   Author: Frank da Cruz <fdc@columbia.edu>,
   Columbia University Academic Information Systems, New York City.
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2010,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
 #define LOCUS
 #endif /* NOLOCUS */
 
-/* Sizes of things */
+/* Sizes of things - FNVALL and MAXARGLEN increased from 8K 20050912 */
 
 #ifdef BIGBUFOK
-#define FNVALL 10238                   /* Function return value length */
-#define MAXARGLEN 8191                 /* Max func arg length after eval */
+#define FNVALL CMDBL                   /* Function return value length */
+#define MAXARGLEN CMDBL                        /* Max func arg length after eval */
 #define MAXARGLIST 1024                        /* Max number of args for a macro */
 #define FSPECL CMDBL                   /* Max length for MSEND/GET string */
 #define MSENDMAX 1024                  /* Number of filespecs for MSEND */
@@ -59,6 +59,7 @@
 #define MACLEVEL 128                   /* Maximum nesting for macros */
 #define INPBUFSIZ 4096                 /* Size of INPUT buffer */
 #define PROMPTL 1024                   /* Max length for prompt */
+#define LBLSIZ 8192                    /* Maximum length for a GOTO label */
 #else
 #define VNAML 256                      /* Max length for variable name */
 #define ARRAYREFLEN 128                        /* Max length for array reference */
 #define MACLEVEL 64                    /* Maximum nesting for macros */
 #define INPBUFSIZ 256
 #define PROMPTL 256                    /* Max length for prompt */
+#define LBLSIZ 128                     /* Maximum length for a GOTO label */
 #endif /* BIGBUFOK */
 #define NARGS 10                       /* Max number of macro arguments */
 #define LINBUFSIZ (CMDBL + 10)         /* Size of line[] buffer */
 #define TMPBUFSIZ (CMDBL + 10)         /* Size of temporary buffer */
-#define LBLSIZ 50                      /* Maximum length for a GOTO label */
+
 #define CMDSTKL ( MACLEVEL + MAXTAKE + 2) /* Command stack depth */
 
 #ifndef NOPURGE                                /* PURGE command */
@@ -133,6 +135,12 @@ struct stringlist {                        /* General purpose string list */
     struct stringlist * sl_next;
 };
 
+struct stringint {                     /* String and (wide) integer */
+    char * sval;                       /* used mainly with command switches */
+    int ival;
+    CK_OFF_T wval;
+};
+
 #ifndef NOICP
 /*
   C-Kermit Initialization file...
@@ -357,7 +365,9 @@ struct stringlist {                 /* General purpose string list */
 #define XA_WMIN  45
 #define XA_SCALE 46                     /* GUI Scale Font */
 #define XA_CHGD  47                     /* GUI Change Dimensions */
-#define XA_MAX  47                     /* Highest extended option number */
+#define XA_NOCLOSE 48                   /* GUI Disable Close Window */
+#define XA_UNBUF 49                    /* UNIX unbuffered console */
+#define XA_MAX  49                     /* Highest extended option number */
 #endif /* NOCMDL */
 
 #ifndef NOICP
@@ -415,6 +425,9 @@ struct stringlist {                 /* General purpose string list */
 #define DIR_LNK 38     /* follow symlinks */
 #define DIR_NLK 39     /* don't follow symlinks */
 #define DIR_OUT 40     /* Output file for listing */
+#define DIR_TOP 41     /* Top n lines */
+#define DIR_COU 42     /* COUNT:var */
+#define DIR_NOL 43     /* NOLINKS (don't show symlinks at at all) */
 
 #define DIRS_NM 0       /* Sort directory by NAME */
 #define DIRS_DT 1       /* Sort directory by DATE */
@@ -748,6 +761,12 @@ struct stringlist {                        /* General purpose string list */
 #define XXNSCR  261    /* NOSCROLL */
 #define XXSFTP  262    /* SFTP */
 #define XXSKRM  263    /* SKERMIT */
+#define XXWDIR  264    /* WDIRECTORY */
+#define XXHDIR  265    /* HDIRECTORY */
+#define XXTOUC  266    /* TOUCH */
+#define XXLOCU  267    /* LOCUS (for HELP) */
+#define XXPUTE  268     /* PUTENV */
+#define XXXMSG  269     /* XMESSAGE */
 
 /* End of Top-Level Commands */
 
@@ -833,6 +852,15 @@ struct stringlist {                        /* General purpose string list */
 #define DEL_LNK 25                     /* /FOLLOWLINKS */
 #define DEL_NLK 26                     /* /NOFOLLOWLINKS */
 
+/* RENAME switches that can be used in the same table as the DEL switches */
+
+#define REN_LOW 100                    /* Convert to lowercase */
+#define REN_UPP 101                    /* Converto to uppercase */
+#define REN_RPL 102                    /* String replacement */
+#define REN_OVW 103                    /* Overwrite file with same name */
+#define REN_XLA 104                    /* Translate character sets */
+#define REN_SPA 105                    /* Fix spaces */
+
 /* FILE operations */
 
 #define FIL_OPN  0                     /* OPEN */
@@ -1254,6 +1282,7 @@ struct stringlist {                       /* General purpose string list */
 #define   XYTITMO   62  /* SET TERM IDLE-TIMEOUT */
 #define   XYTIACT   63  /* SET TERM IDLE-ACTION  */
 #define   XYTLSP    64  /* SET TERM LINE-SPACING */
+#define   XYTLFD    65 /* SET TERM LF-DISPLAY   */
 
 #define XYATTR 34       /* Attribute packets  */
 #define XYSERV 35      /* Server parameters  */
@@ -1432,12 +1461,18 @@ struct stringlist {                     /* General purpose string list */
 #define XYX25  57       /* X.25 parameter (ANYX25) */
 #define XYPAD  58       /* X.3 PAD parameter (ANYX25) */
 #define XYWILD 59       /* Wildcard expansion method */
+
+#define WILD_OFF  0    /* Wildcard expansion off */
+#define WILD_ON   1    /* Wildcard expansion on  */
+#define WILD_KER  2    /* Wildcard expansion by Kermit */
+#define WILD_SHE  3    /* Wildcard expansion by Shell */
+
 #define XYSUSP 60       /* Suspend */
 #define XYMAIL 61      /* Mail-Command */
 #define XYPRIN 62      /* Print-Command */
 #define XYQUIE 63      /* Quiet */
 #define XYLCLE 64      /* Local-echo */
-#define XYSCRI 65      /* SCRIPT command paramaters */
+#define XYSCRI 65      /* SCRIPT command parameters */
 #define XYMSGS 66       /* MESSAGEs ON/OFF */
 #ifdef TNCODE
 #define XYTEL  67      /* SET TELNET parameters */
@@ -1585,6 +1620,7 @@ struct stringlist {                       /* General purpose string list */
 #define XYMSK  83       /* MS-DOS Kermit compatibility options */
 #define  MSK_COLOR 0    /*  Terminal color handling   */
 #define  MSK_KEYS  1    /*  SET KEY uses MSK keycodes */
+#define  MSK_REN   2    /*  File renaming uses 8.3 notation always */
 #endif /* OS2 */
 
 #define XYDEST  84     /* SET DESTINATION as in MS-DOS Kermit */
@@ -1710,6 +1746,9 @@ struct stringlist {                       /* General purpose string list */
 #define XYANSWER 131    /* SET ANSWER */
 #define XYMATCH  132    /* SET MATCHDOT */
 #define XYSFTP   133    /* SET SFTP */
+#define XY_REN   134    /* SET RENAME */
+#define XYEXTRN  135    /* SET EXTERNAL-PROTOCOL */
+#define XYVAREV  136    /* SET VARIABLE-EVALUATION */
 
 /* End of SET commands */
 
@@ -1957,7 +1996,8 @@ struct stringlist {                       /* General purpose string list */
 #define SHSEXP    68                   /* SHOW SEXPRESSIONS */
 #define SHOSSH    69                   /* SHOW SSH */
 #define SHOIKS    70                    /* SHOW IKS */
-#define SHOGUI    71                   /* SHOW RGB */
+#define SHOGUI    71                   /* SHOW GUI (K95) */
+#define SHOREN    72                   /* SHOW RENAME */
 
 /* REMOTE command symbols */
 
@@ -2350,6 +2390,14 @@ struct stringlist {                      /* General purpose string list */
 #define VN_LOG_CON  245                 /* Connection Log Filename */
 
 #define VN_ISCALE   246                        /* INPUT scale factor */
+#define VN_BITS     247                        /* Bits of this build (16, 32, 64) */
+#define VN_LASTFIL  248                        /* Last input filespec */
+#define VN_LASTKWV  249                        /* Last \fkeywordvalue() keyword */
+#define VN_DMSG     250                        /* Msg corresponding to dialstatus */
+#define VN_HOSTIP   251                        /* IP address of remote host */
+#define VN_INPMSG   252                        /* Msg corresponding to instatus */
+#define VN_VAREVAL  253                        /* SET VARIABLE-EVALUATION setting */
+#define VN_PREVCMD  254                        /* Previous command */
 #endif /* NOSPL */
 
 /* INPUT status values */
@@ -2360,6 +2408,14 @@ struct stringlist {                      /* General purpose string list */
 #define INP_IE  3                      /* Internal error */
 #define INP_IO  4                      /* I/O error or connection lost */
 #define INP_IKS 5                       /* Kermit Server Active */
+#define INP_BF  6                      /* Buffer full */
+
+/* INPUT switch values */
+
+#define INPSW_NOM 1                    /* /NOMATCH */
+#define INPSW_CLR 2                    /* /CLEAR */
+#define INPSW_NOW 4                    /* /NOWRAP */
+#define INPSW_COU 8                    /* /COUNT */
 
 #ifndef NOSPL
 /* Symbols for builtin functions */
@@ -2530,6 +2586,17 @@ struct stringlist {                      /* General purpose string list */
 #define FN_LNAME   154                 /* \fLongPathName() (Windows) */
 #define FN_SNAME   155                 /* \fShortPathName() (Windows) */
 #define FN_UNTAB   156                 /* \funtabify() */
+#define FN_LOPX    157                 /* \flopx() */
+#define FN_EMAIL   158                 /* \femailaddress() */
+#define FN_PICTURE 159                 /* \fpictureinfo() */
+#define FN_PID     160                 /* \fpidinfo() */
+#define FN_COUNT   161                 /* \fcount() */
+#define FN_FUNC    162                 /* \ffunction() */
+#define FN_RECURSE 163                 /* \frecurse() */
+#define FN_SQUEEZE 164                 /* \fsqueeze() */
+#define FN_UNPCT   165                 /* \fdecodehex() */
+#define FN_STRINGT 166                 /* \fstringtype() */
+#define FN_STRCMP  167                 /* \fstrcmp() */
 
 #endif /* NOSPL */
 
@@ -2682,6 +2749,12 @@ struct stringlist {                      /* General purpose string list */
 
 /* ANSI-C prototypes for user interface functions */
 
+#ifdef UNIX
+_PROTOTYP( int doputenv, ( char *, char * ) );
+#endif /* UNIX */
+
+_PROTOTYP( int chkaes, ( char, int ) );
+
 #ifndef NOICP
 _PROTOTYP( int matchname, ( char *, int, int ) );
 _PROTOTYP( int ck_cls, ( void ) );
@@ -2702,6 +2775,7 @@ _PROTOTYP( char * nvlook, (char *) );
 _PROTOTYP( int xarray, (char *) );
 _PROTOTYP( int arraynam, (char *, int *, int *) );
 _PROTOTYP( int arraybounds, (char *, int *, int *) );
+_PROTOTYP( int boundspair, (char *, char *, int *, int *, char *) );
 _PROTOTYP( int arrayitoa, (int) );
 _PROTOTYP( int arrayatoi, (int) );
 _PROTOTYP( char * bldlen, (char *, char *) );
@@ -2725,9 +2799,10 @@ _PROTOTYP( int doenable, (int, int) );
 _PROTOTYP( int dogoto, (char *, int) );
 _PROTOTYP( int dogta, (int) );
 _PROTOTYP( int dohlp, (int) );
+_PROTOTYP (int doincr, (int) );
 _PROTOTYP( int dohrmt, (int) );
 _PROTOTYP( int doif, (int) );
-_PROTOTYP( int doinput, (int, char *[], int[], int) );
+_PROTOTYP( int doinput, (int, char *[], int[], int, int) );
 _PROTOTYP( int doreinp, (int, char *, int) );
 _PROTOTYP( int dolog, (int) );
 _PROTOTYP( int dologin, (char *) );
@@ -2743,7 +2818,7 @@ _PROTOTYP( int dotype, (char *, int, int, int, char *, int, char *, int, int,
 _PROTOTYP( int transmit, (char *, char, int, int, int) );
 _PROTOTYP( int xlate, (char *, char *, int, int) );
 _PROTOTYP( int litcmd, (char **, char **, int) );
-_PROTOTYP( int incvar, (char *, int, int) );
+_PROTOTYP( int incvar, (char *, CK_OFF_T, int) );
 _PROTOTYP( int ckdial, (char *, int, int, int, int) );
 _PROTOTYP( int hmsg, (char *) );
 _PROTOTYP( int hmsga, (char * []) );
@@ -2768,7 +2843,7 @@ _PROTOTYP( int debopn, (char *,int) );
 _PROTOTYP( int diaopn, (char *,int,int) );
 _PROTOTYP( int prepop, (void) );
 _PROTOTYP( int popclvl, (void) );
-_PROTOTYP( int varval, (char *, int *) );
+_PROTOTYP( int varval, (char *, CK_OFF_T *) );
 _PROTOTYP( char * evala, (char *) );
 _PROTOTYP( char * evalx, (char *) );
 _PROTOTYP( int setalarm, (long) );
index e2c89c6..14f19cc 100644 (file)
--- a/ckuusx.c
+++ b/ckuusx.c
@@ -9,7 +9,7 @@
     Jeffrey E Altman <jaltman@secure-endpoints.com>
       Secure Endpoints Inc., New York City
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2010,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -17,7 +17,8 @@
 
 /*
   This module contains user interface functions needed by both the interactive
-  user interface and the command-line-only user interface.
+  user interface and the command-line-only user interface, as well as the
+  screen-control routines (curses and equivalent).
 */
 
 /* Includes */
@@ -76,6 +77,7 @@ extern xx_strp xxstring;
 #ifdef OS2
 #include "ckcnet.h"
 #else /* OS2 */
+_PROTOTYP( char * ckgetpeer, (VOID));
 _PROTOTYP(int getlocalipaddr, (void));
 _PROTOTYP(int istncomport, (void));
 #ifndef NOCKGETFQHOST
@@ -207,8 +209,9 @@ _PROTOTYP( FILE * popen, (char *, char *) );
 #endif /* DCLPOPEN */
 
 int tt_crd = 0;                         /* Carriage return display */
+int tt_lfd = 0;                         /* Linefeed display */
 int interrupted = 0;                    /* Interrupted from keyboard flag */
-static int fxd_inited = 0;              /* Fullscreen stuff initialized */
+int fxd_inited = 0;                    /* Fullscreen stuff initialized */
 
 #ifdef DEBUG
 char debfil[CKMAXPATH+1];               /* Debugging log file name */
@@ -258,6 +261,7 @@ int success = 1,                        /* Command success/failure flag */
     cmdlvl = 0,                         /* Command level */
     action = 0,                                /* Action selected on command line */
     slogts = 0,                                /* Session-log timestamps on/off */
+    slognul = 0,                       /* Session-log null-terminated lines */
 #ifdef UNIX
     sessft = XYFT_T,                    /* Session log file type */
 #else
@@ -327,8 +331,11 @@ extern int streaming, streamok;
 
 /* Used internally */
 
-_PROTOTYP( VOID screenc, (int, char, long, char *) );
+#ifdef KUI
 _PROTOTYP( VOID screeng, (int, char, long, char *) );
+#endif /* KUI */
+_PROTOTYP( VOID screenc, (int, char, CK_OFF_T, char *) );
+
 
 #ifdef CK_CURSES
 #ifndef DYNAMIC
@@ -338,8 +345,8 @@ char * trmbuf = xtrmbuf;
 char * trmbuf = NULL;
 #endif /* DYNAMIC */
 _PROTOTYP( static VOID dpyinit, (void) );
-_PROTOTYP( static long shocps, (int, long, long) );
-_PROTOTYP( static long shoetl, (long, long, long, long) );
+_PROTOTYP( static long shocps, (int, CK_OFF_T, CK_OFF_T) );
+_PROTOTYP( static CK_OFF_T shoetl, (CK_OFF_T, long, CK_OFF_T, CK_OFF_T) );
 #endif /* CK_CURSES */
 
 static int ft_win = 0;  /* Fullscreen file transfer display window is active */
@@ -384,7 +391,7 @@ extern int rcvtimo;
 
 #ifdef CK_RESEND
 extern int sendmode;
-extern long sendstart, rs_len;
+extern CK_OFF_T sendstart, rs_len;
 #endif /* CK_RESEND */
 
 #ifdef CK_PCT_BAR                       /* File transfer thermometer */
@@ -407,7 +414,8 @@ extern int server, bctu, rptflg, ebqflg, spsiz, urpsiz, wmax, czseen, cxseen,
   retrans, wcur, numerrs, fsecs, whatru, crunched, timeouts,
   rpackets, fncnv, bye_active, discard, inserver, diractive, cdactive;
 
-extern long filcnt, filrej, ffc, tfc, rptn, fsize, filcps, tfcps, cps, peakcps;
+extern long filcnt, filrej, rptn, filcps, tfcps, cps, peakcps;
+extern CK_OFF_T ffc, tfc, fsize; 
 
 long oldcps = 0L;
 
@@ -538,8 +546,8 @@ extern char * g_pswd, pwbuf[];
 extern int spsizf, spsizr, spmax, prefixing, fncact, fnspath, fnrpath;
 extern int moving;                      /* SEND criteria */
 extern char sndafter[], sndbefore[], *sndexcept[], *rcvexcept[];
-extern long sndlarger, sndsmaller, calibrate, skipbup;
-extern int rmailf, rprintf;
+extern CK_OFF_T sndlarger, sndsmaller, calibrate;
+extern int rmailf, rprintf, skipbup;
 extern char optbuf[];
 
 #ifdef PIPESEND
@@ -799,8 +807,9 @@ ftreset() {
           free(rcvexcept[i]);
         rcvexcept[i] = NULL;
     }
-    sndlarger =  -1L;
-    sndsmaller = -1L;
+    sndlarger =  (CK_OFF_T)-1;
+    sndsmaller = (CK_OFF_T)-1;
+    debug(F101,"present sndsmaller","",sndsmaller);
 #ifdef GFTIMER
     gtv = -1.0;
     oldgtv = -1.0;
@@ -1382,7 +1391,8 @@ matchname(filename, local, os) char * filename; int local; int os; {
      1 = UTF-8 text (flag = -1)
      2 = UCS-2 text (flag =  0: big-endian; flag = 1: little-endian)
      3 = 8-bit text (flag =  0: no C1 bytes; flag = 1: includes C1 bytes)
-     4 = binary     (flag = -1)
+     4 = Text       (type unknown)
+     5 = binary     (flag = -1)
 
   If UNICODE is defined:
 
@@ -1966,24 +1976,270 @@ scanfile(name,flag,nscanfile) char * name; int * flag, nscanfile; {
     return(rc);
 }
 
+/*
+  scanstring - like scan file but for a string.
+  This is just a quick butchery of scanfile without thinking too much.
+*/
+int
+scanstring(s) char * s; {
+    int x, val = -1, count = 0;                /* Workers */
+    int rc = -1;                       /* Return code */
+    int pv = -1;                       /* Pattern-match value */
+    int bytes = 0;                     /* Total byte count */
+#ifdef UNICODE
+    unsigned int c0, c1;               /* First 2 file bytes (for BOM) */
+#endif /* UNICODE */
+    extern int pipesend, filepeek;
+
+    register int i;                    /* Loop control */
+    int readsize = 0;                  /* How much to read */
+    int eightbit = 0;                  /* Number of bytes with 8th bit on */
+    int c0controls = 0;                        /* C0 non-text control-char counter */
+    int c0noniso = 0;                  /* C0 non-ISO control-char counter */
+    int c1controls = 0;                        /* C1 control-character counter */
+    unsigned int c;                    /* Current character */
+    int runmax = 0;                    /* Longest run of 0 bytes */
+    int runzero = 0;                   /* Run of 0 bytes */
+    int pctzero = 0;                   /* Percentage of 0 bytes */
+    int txtcz = 0;
+
+#ifdef UNICODE
+    int notutf8 = 0;                   /* Nonzero if definitely not UTF-8 */
+    int utf8state = 0;                 /* UTF-8 recognizer state */
+    int oddzero = 0;                   /* Number of 0 bytes in odd postions */
+    int evenzero = 0;                  /* and in even positions */
+    int lfnul = 0;                     /* Number of <LF><NUL> sequences */
+    int crlf = 0;                      /* Number of <CRLF> sequences */
+#else
+    int notutf8 = 1;
+#endif /* UNICODE */
+
+    char * buf = s;
+    if (!s) s = "";
+    count = strlen(s);
+
+#ifdef UNICODE
+    if (bytes == 0 && count > 1) {
+       int incl_cnt = 0;
+
+       /* First look for BOM */
+
+       c0 = (unsigned)((unsigned)buf[0]&0xFF); /* First file byte */
+       c1 = (unsigned)((unsigned)buf[1]&0xFF); /* Second byte */
+
+       if (c0 == 0xFE && c1 == 0xFF) { /* UCS-2 BE */
+           rc = FT_UCS2;
+           val = 0;
+           debug(F111,"scanstring UCS2 BOM BE",ckitoa(val),rc);
+           incl_cnt++;
+       } else if (c0 == 0xFF && c1 == 0xFE) { /* UCS-2 LE */
+           rc = FT_UCS2;
+           val = 1;
+           debug(F111,"scanstring UCS2 BOM LE",ckitoa(val),rc);
+           incl_cnt++;
+       } else if (count > 2) if (c0 == 0xEF && c1 == 0xBB &&
+                  (unsigned)((unsigned)buf[2]&0xFF) == 0xBF) {
+           rc = FT_UTF8;
+           debug(F111,"scanstring UTF8 BOM",ckitoa(val),rc);
+           incl_cnt++;
+       }
+       if (incl_cnt) {         /* Have BOM */
+           bytes += count;
+           goto xscanstring;
+       }
+    }
+#endif /* UNICODE */
+
+    bytes += count;                    /* Count bytes read */
+
+    for (i = 0; i < count; i++) {      /* For each byte... */
+       c = (unsigned)buf[i];   /* For ease of reference */
+       if (!c) {                       /* Zero byte? */
+           goto xscanstring;   /* Null terminated string */
+       }
+       if ((c & 0x80) == 0) {  /* We have a 7-bit byte */
+#ifdef UNICODE
+           if (i > 0 && c == 10) { /* Linefeed */
+               if (buf[i-1] == 0) lfnul++; /* Preceded by NUL */
+               else if (buf[i-1] == 13) crlf++; /* or by CR... */
+           }
+#endif /* UNICODE */
+           if (c < ' ') {              /* Check for CO controls */
+               if (c != LF && c != CR && c != HT && c != FF) {
+                   c0controls++;
+                   if (c != ESC && c != SO && c != SI)
+                     c0noniso++;
+               }
+               if ((c == '\032')       /* Ctrl-Z */
+                   ) {
+                   c0controls--;
+                   c0noniso--;
+               }
+           }
+#ifdef UNICODE
+           if (!notutf8 && utf8state) { /* In UTF-8 sequence? */
+               utf8state = 0;
+               debug(F000,"scanstring","7-bit byte in UTF8 sequence",c);
+               notutf8++;              /* Then it's not UTF-8 */
+               continue;
+           }
+#endif /* UNICODE */
+       } else {                        /* We have an 8-bit byte */
+           eightbit++;         /* Count it */
+           if (c >= 0x80 && c < 0xA0) /* Check for C1 controls */
+             c1controls++;
+#ifdef UNICODE
+           if (!notutf8) {             /* If it might still be UTF8... */
+               switch (utf8state) { /* Enter the UTF-8 state machine */
+                 case 0:                /* First byte... */
+                   if ((c & 0xE0) == 0xC0) { /* Tells number of */
+                       utf8state = 1;        /* subsequent bytes */
+                   } else if ((c & 0xF0) == 0xE0) {
+                       utf8state = 2;
+                   } else if ((c & 0xF8) == 0xF0) {
+                       utf8state = 3;
+                   } else {
+                       notutf8++;
+                   }
+                   break;
+                 case 1:               /* Subsequent byte */
+                 case 2:
+                 case 3:
+                   if ((c & 0xC0) != 0x80) { /* Must start with 10 */
+                       debug(F000,"scanstring",
+                             "bad byte in UTF8 sequence",c);
+                       notutf8++;
+                       break;
+                   }
+                   utf8state--;        /* Good, one less in this sequence */
+                   break;
+                 default:              /* Shouldn't happen */
+                   debug(F111,"scanstring","bad UTF8 state",utf8state);
+                   notutf8++;
+               }
+           }
+#endif /* UNICODE */
+       }
+    }
+    if (bytes == 0)                    /* If nothing was read */
+      return(-1);                      /* we're done. */
+
+#ifdef UNICODE
+    if (bytes > 100)                   /* Bytes is not 0 */
+      pctzero = (evenzero + oddzero) / (bytes / 100);
+    else
+      pctzero = ((evenzero + oddzero) * 100) / bytes;
+#endif /* UNICODE */
+
+#ifdef UNICODE
+    x = eightbit ? bytes / 20 : bytes / 4; /* For UCS-2... */
+
+    if (runmax > 2) {                  /* File has run of more than 2 NULs */
+       debug(F100,"scanstring BIN runmax","",0);
+       rc = FT_BIN;                    /* so it can't be any kind of text. */
+       goto xscanstring;
+
+    } else if (rc == FT_UCS2 || (rc == FT_UTF8 && runmax == 0)) {
+       goto xscanstring;                       /* File starts with a BOM */
+
+    } else if (eightbit > 0 && !notutf8) { /* File has 8-bit data */
+       if (runmax > 0) {                  /* and runs of NULs */
+           debug(F100,"scanstring BIN (nnUTF8) runmax","",0);
+           rc = FT_BIN;                   /* UTF-8 doesn't have NULs */
+       } else {                           /* No NULs */
+           debug(F100,"scanstring UTF8 (nnUTF8 + runmax == 0)","",0);
+           rc = FT_UTF8;                  /* and not not UTF-8, so is UTF-8 */
+       }
+       goto xscanstring;
+    }
+/*
+  It seems to be UCS-2 but let's be more certain since there is no BOM...
+  If the number of 7- and 8-bit characters is approximately equal, it might
+  be a compressed file.  In this case we decide based on the name.
+*/
+    if (rc == FT_UCS2) {
+       if (bytes < 100) {
+           if (oddzero != 0 && evenzero != 0) {
+               debug(F100,"scanstring small UCS2 doubtful","",0);
+               rc = FT_BIN;
+               goto xscanstring;
+           } else if (oddzero == 0 && evenzero == 0) {
+               rc = eightbit ? FT_8BIT : FT_7BIT;
+           }
+       }
+       goto xscanstring;                       /* Seems to be UCS-2 */
+    }
+
+/* If none of the above, it's probably not Unicode.  */
+
+    if (!eightbit) {                   /* It's 7-bit */
+       if (c0controls) {               /* This would be strange */
+           if ((c0noniso > 0) && (txtcz == 0)) {
+               debug(F100,"scanstring 7-bit BIN (c0coniso)","",0);
+               rc = FT_BIN;
+           } else {
+               debug(F100,"scanstring 7-bit ISO2022 TEXT (no c0noniso)","",0);
+               rc = FT_7BIT;
+           }
+       } else {                        /* 7-bit text */
+           debug(F100,"scanstring 7-bit TEXT (no c0controls)","",0);
+           rc = FT_7BIT;
+       }
+    } else if (!c0noniso || txtcz) {   /* 8-bit text */
+       debug(F100,"scanstring 8-bit TEXT (no c0noniso)","",0);
+       rc = FT_8BIT;
+       val = c1controls ? 1 : 0;
+    } else {                           /* 8-bit binary */
+       debug(F100,"scanstring 8-bit BIN (c0noniso)","",0);
+       rc = FT_BIN;
+    }
+
+#else  /* !UNICODE */
+
+    if (c0noniso) {
+       debug(F100,"scanstring 8-bit BIN (c0noniso)","",0);
+       rc = FT_BIN;
+    } else if (eightbit) {
+       debug(F100,"scanstring 8-bit TEXT (no c0noniso)","",0);
+       rc = FT_8BIT;
+       val = c1controls ? 1 : 0;
+    } else {
+       debug(F100,"scanstring 7-bit TEXT (no c0noniso)","",0);
+       rc = FT_7BIT;
+    }
+
+#endif /* UNICODE */
+
+  xscanstring:
+    debug(F101,"scanstring result     ","",rc);
+    return(rc);
+}
+
+
+
 /*  F I L E S E L E C T  --  Select this file for sending  */
 
 int
 #ifdef CK_ANSIC
 fileselect(
     char *f, char *sa, char *sb, char *sna, char *snb,
-    long minsiz, long maxsiz,
+    CK_OFF_T minsiz, CK_OFF_T maxsiz,
     int nbu, int nxlist,
     char ** xlist
 )
 #else
 fileselect(f,sa,sb,sna,snb,minsiz,maxsiz,nbu,nxlist,xlist)
- char *f,*sa,*sb,*sna,*snb; long minsiz,maxsiz; int nbu,nxlist; char ** xlist;
+ char *f,*sa,*sb,*sna,*snb; CK_OFF_T minsiz,maxsiz;
+ int nbu,nxlist; char ** xlist;
 #endif /* CK_ANSIC */
 /* fileselect */ {
     char *fdate;
     int n;
-    long z;
+    CK_OFF_T z;
+
+    debug(F111,"fileselect minsiz",ckfstoa(minsiz),minsiz);
+    debug(F111,"fileselect maxsiz",ckfstoa(maxsiz),maxsiz);
+    debug(F111,"fileselect (CK_OFF_T)-1",ckfstoa((CK_OFF_T)-1),(CK_OFF_T)-1);
 
     if (!sa) sa = "";
     if (!sb) sb = "";
@@ -1994,10 +2250,10 @@ fileselect(f,sa,sb,sna,snb,minsiz,maxsiz,nbu,nxlist,xlist)
 #ifndef NOICP
 #ifndef NOXFER
     if (nolinks) {
-       long zz;
+       CK_OFF_T zz;
        zz = zgetfs(f);
        debug(F111,"fileselect NOLINKS zgetfs",f,zz);
-       if (zz < 0L)
+       if (zz < (CK_OFF_T)0)
          return(0);
        debug(F111,"fileselect NOLINKS zgfs_link",f,zgfs_link);
        if (zgfs_link)
@@ -2040,17 +2296,18 @@ fileselect(f,sa,sb,sna,snb,minsiz,maxsiz,nbu,nxlist,xlist)
            return(0);
        }
     }
-    if (minsiz > -1L || maxsiz > -1L) { /* Smaller or larger */
+    /* Smaller or larger */
+    if (minsiz > (CK_OFF_T)-1 || maxsiz > (CK_OFF_T)-1) {
        z = zchki(f);                   /* Get size */
        debug(F101,"fileselect filesize","",z);
-       if (z < 0)
+       if (z < (CK_OFF_T)0)
          return(1);
-       if ((minsiz > -1L) && (z >= minsiz)) {
+       if ((minsiz > (CK_OFF_T)-1) && (z >= minsiz)) {
            debug(F111,"fileselect minsiz skipping",f,minsiz);
            /* tlog(F111,"Skipping (too big)",f,z); */
            return(0);
        }
-       if ((maxsiz > -1L) && (z <= maxsiz)) {
+       if ((maxsiz > (CK_OFF_T)-1) && (z <= maxsiz)) {
            debug(F111,"fileselect maxsiz skipping",f,maxsiz);
            /* tlog(F110,"Skipping (too small)",f,0); */
            return(0);
@@ -2888,10 +3145,12 @@ trap(sig) int sig;
 
 #ifdef DEBUG
     if (deblog) {
+       debug(F100,"*********************","",0);
        if (sig == SIGINT)
          debug(F101,"trap caught SIGINT","",sig);
-       else
+       else 
          debug(F101,"trap caught signal","",sig);
+       debug(F100,"*********************","",0);
     }
 #endif /* DEBUG */
 
@@ -3039,6 +3298,52 @@ trap(sig) int sig;
 #endif /* OSK */
 #endif /* UNIX */
 
+#ifdef NETPTY
+    /* Clean up Ctrl-C out of REDIRECT or external protocol */
+    {
+       extern PID_T pty_fork_pid;
+       extern int pty_master_fd, pty_slave_fd;
+       int x;
+
+       signal(SIGCHLD,SIG_IGN);        /* We don't want this any more */
+
+       debug(F101,"trap pty_master_fd","",pty_master_fd);
+       if (pty_master_fd > 2) {
+           x = close(pty_master_fd);
+           debug(F101,"trap pty_master_fd close","",x);
+       }
+       pty_master_fd = -1;
+       debug(F101,"trap pty_slave_fd","",pty_slave_fd);
+       if (pty_slave_fd > 2) {
+           x = close(pty_slave_fd);
+           debug(F101,"trap pty_slave_fd close","",x);
+       }
+       pty_slave_fd = -1;
+       debug(F101,"trap pty_fork_pid","",pty_fork_pid);
+       if (pty_fork_pid > 0) {
+           x = kill(pty_fork_pid,0);   /* See if the fork is really there */
+           debug(F111,"trap pty_fork_pid kill 0 errno",ckitoa(x),errno);
+           if (x == 0) {               /* Seems to be active */
+               x = kill(pty_fork_pid,SIGHUP); /* Ask it to clean up & exit */
+               debug(F101,"trap pty_fork_pid kill SIGHUP","",x);
+               msleep(100);
+               errno = 0;
+               x = kill(pty_fork_pid,0); /* Is it still there? */
+               if (x == 0
+#ifdef ESRCH
+                   /* This module is not always exposed to <errno.h> */
+                   || errno != ESRCH
+#endif /* ESRCH */
+                   ) {
+                   x = kill(pty_fork_pid,SIGKILL);
+                   debug(F101,"trap pty_fork_pid kill SIGKILL","",x);
+               }
+           }
+           pty_fork_pid = -1;
+       }
+    }
+#endif /* NETPTY */
+
 #ifdef OSK
     sigmask(-1);
 /*
@@ -3174,9 +3479,9 @@ stptrap(sig) int sig;
 */
 VOID
 #ifdef CK_ANSIC
-dotlog(int f, char *s1, char *s2, long n)
+dotlog(int f, char *s1, char *s2, CK_OFF_T n)
 #else
-dotlog(f,s1,s2,n) int f; long n; char *s1, *s2;
+dotlog(f,s1,s2,n) int f; CK_OFF_T n; char *s1, *s2;
 #endif /* CK_ANSIC */
 /* dotlog */ {
     static char s[TBUFL];
@@ -3192,11 +3497,11 @@ dotlog(f,s1,s2,n) int f; long n; char *s1, *s2;
         if ((int)strlen(s1) + (int)strlen(s2) + 15 > TBUFL)
           sprintf(sp,"?T-Log string too long");
         else
-         sprintf(sp,"%s %ld %s",s1,n,s2);
+         sprintf(sp,"%s %s %s",s1,ckfstoa(n),s2);
         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
         break;
       case F001:                        /* 1, " n" */
-        sprintf(sp," %ld",n);
+        sprintf(sp," %s",ckfstoa(n));
         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
         break;
       case F010:                        /* 2, "[s2]" */
@@ -3212,7 +3517,7 @@ dotlog(f,s1,s2,n) int f; long n; char *s1, *s2;
         if (s2[x] == '\n') s2[x] = '\0';
         if (x + 6 > TBUFL)
           sprintf(sp,"?String too long");
-        else sprintf(sp,"[%s] %ld",s2,n);
+        else sprintf(sp,"[%s] %s",s2,ckfstoa(n));
         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
         break;
       case F100:                        /* 4, "s1" */
@@ -3221,7 +3526,7 @@ dotlog(f,s1,s2,n) int f; long n; char *s1, *s2;
       case F101:                        /* 5, "s1: n" */
         if ((int)strlen(s1) + 15 > TBUFL)
           sprintf(sp,"?String too long");
-        else sprintf(sp,"%s: %ld",s1,n);
+        else sprintf(sp,"%s: %s",s1,ckfstoa(n));
         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
         break;
       case F110:                        /* 6, "s1 s2" */
@@ -3239,11 +3544,11 @@ dotlog(f,s1,s2,n) int f; long n; char *s1, *s2;
         if ((int)strlen(s1) + x + 15 > TBUFL)
           sprintf(sp,"?String too long");
         else
-         sprintf(sp,"%s%s%s: %ld",s1,((*s2 == ':') ? "" : " "),s2,n);
+         sprintf(sp,"%s%s%s: %s",s1,((*s2 == ':') ? "" : " "),s2,ckfstoa(n));
         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
         break;
       default:
-        sprintf(sp,"?Invalid format for tlog() - %ld",n);
+        sprintf(sp,"?Invalid format for tlog() - %d",f);
         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
     }
 }
@@ -3267,10 +3572,10 @@ dotlog(f,s1,s2,n) int f; long n; char *s1, *s2;
 */
 VOID
 #ifdef CK_ANSIC
-doxlog(int x, char * fn, long fs, int fm, int status, char * msg)
+doxlog(int x, char * fn, CK_OFF_T fs, int fm, int status, char * msg)
 #else
 doxlog(x, fn, fs, fm, status, msg)
-    int x; char * fn; long fs; int fm; int status; char * msg;
+    int x; char * fn; CK_OFF_T fs; int fm; int status; char * msg;
 #endif /* CK_ANSIC */
 /* doxlog */ {
     extern int tlogsep;
@@ -3325,7 +3630,7 @@ doxlog(x, fn, fs, fm, status, msg)
     if (ckstrchr(fn,sep[0]))           /* Filename */
       s = "\"";
     ckmakmsg(bufp,left,s,fn,s,sep);
-    sprintf(tmpbuf,"%ld",fs);           /* Size */
+    sprintf(tmpbuf,"%s",ckfstoa(fs));  /* Size */
     ckstrncat(buf,tmpbuf,CKMAXPATH);
     ckstrncat(buf,sep,CKMAXPATH);
     debug(F110,"doxlog 4",buf,0);
@@ -3355,15 +3660,13 @@ doxlog(x, fn, fs, fm, status, msg)
     debug(F110,"doxlog buf 1", buf, len);
     s = buf + len;
     if (status == 0 && left > 32) {
-        long cps;
-
+        long cps = 0L;
 #ifdef GFTIMER
        debug(F101,"DOXLOG fpxfsecs","",(long)(fpxfsecs * 1000));
-
-        cps = (long)((CKFLOAT) fs / fpxfsecs);
+        if (fpxfsecs) cps = (long)((CKFLOAT) fs / fpxfsecs);
         sprintf(s,"%s\"%0.3fsec %ldcps\"",sep,fpxfsecs,cps);
 #else
-        cps = fs / xfsecs;
+        if (xfsecs) cps = fs / xfsecs;
         sprintf(s,"%s\"%ldsec %ldcps\"",sep,xfsecs,cps);
 #endif /* GFTIMER */
     } else if ((int)strlen(msg) + 4 < left) {
@@ -3500,10 +3803,10 @@ chkint() {
           xxscreen(SCR_QE,0, speed, " speed");
         if (what & W_SEND)
 
-          xxscreen(SCR_QE,0,(long)spsiz, " packet length");
+          xxscreen(SCR_QE,0,spsiz, " packet length");
         else if (what & W_RECV || what & W_REMO)
-          xxscreen(SCR_QE,0,(long)urpsiz," packet length");
-        xxscreen(SCR_QE,0,(long)wslots,  " window slots");
+          xxscreen(SCR_QE,0,urpsiz," packet length");
+        xxscreen(SCR_QE,0,wslots,  " window slots");
         fdispla = ofd; /* [MF] Restore file display type */
         return(0);
 
@@ -3675,8 +3978,8 @@ static int newdpy = 0;                  /* New display flag */
 static char fbuf[80];                   /* Filename buffer */
 static char abuf[80];                   /* As-name buffer */
 static char a2buf[80];                  /* Second As-name buffer */
-static long oldffc = 0L;
-static long dots = 0L;
+static CK_OFF_T oldffc = 0L;
+static CK_OFF_T dots = 0L;
 static int hpos = 0;
 
 static VOID                             /* Initialize Serial or CRT display */
@@ -3685,8 +3988,8 @@ dpyinit() {
     char * s = "";
 
     newdpy = 0;                         /*  Don't do this again */
-    oldffc = 0L;                        /*  Reset this */
-    dots = 0L;                          /*  and this.. */
+    oldffc = (CK_OFF_T)0;              /*  Reset this */
+    dots = (CK_OFF_T)0;                        /*  and this.. */
     oldcps = cps = 0L;
 
     conoll("");                                /* New line */
@@ -3716,8 +4019,8 @@ dpyinit() {
     }
     *fbuf = NUL; *abuf = NUL; *a2buf = NUL;
     conoll("");
-    if (fsize > -1L) {                 /* Size */
-        sprintf(fbuf,"Size: %ld, Type: ",fsize); /* SAFE (80) */
+    if (fsize > (CK_OFF_T)-1) {                /* Size */
+        sprintf(fbuf,"Size: %s, Type: ",ckfstoa(fsize)); /* SAFE (80) */
         conol(fbuf); *fbuf = NUL;
     } else conol("Size: unknown, Type: ");
     if (binary) {                      /* Type */
@@ -3791,11 +4094,11 @@ showpkt(c) char c;
 #ifndef GFTIMER
     long et;                            /* Elapsed time, entire batch  */
 #endif /* GFTIMER */
-    long howfar;                        /* How far into file */
+    CK_OFF_T howfar;                   /* How far into file */
     long pd;                            /* Percent done, this file     */
     long tp;                            /* Transfer rate, entire batch */
     long ps;                            /* Packet size, current packet */
-    long mytfc;                         /* Local copy of byte counter  */
+    CK_OFF_T mytfc;                    /* Local copy of byte counter  */
 
 #ifdef GFTIMER
     CKFLOAT tnow;
@@ -3820,8 +4123,8 @@ showpkt(c) char c;
 #endif /* CK_RESEND */
     pd = -1;                            /* Percent done. */
     if (c == NUL) {                     /* Still going, figure % done */
-        if (fsize == 0L) return;        /* Empty file, don't bother */
-        pd = (fsize > 99L) ? (howfar / (fsize / 100L)) : 0L;
+        if (!fsize) return;            /* Empty file, don't bother */
+        pd = (fsize > 99) ? (howfar / (fsize / (CK_OFF_T)100)) : 0;
         if (pd > 100) pd = 100;         /* Expansion */
     }
     if (c != NUL)
@@ -3853,7 +4156,7 @@ showpkt(c) char c;
     pd = -1;                            /* Percent done. */
     if (c == NUL) {                     /* Still going, figure % done */
         if (fsize == 0L) return;        /* Empty file, don't bother */
-        pd = (fsize > 99L) ? (howfar / (fsize / 100L)) : 0L;
+        pd = (fsize > 99) ? (howfar / (fsize / (CK_OFF_T)100)) : 0;
         if (pd > 100) pd = 100;         /* Expansion */
     }
     if (c != NUL)
@@ -3867,7 +4170,7 @@ showpkt(c) char c;
   Rate so far is ffc / (et - fsecs),  estimated time for remaining bytes
   is (fsize - ffc) / (ffc / (et - fsecs)).
 */
-    tp = (howfar > 0L) ? (fsize - howfar) * (et - fsecs) / howfar : 0L;
+    tp = (howfar > 0) ? (fsize - howfar) * (et - fsecs) / howfar : 0;
 #endif /* CK_CPS */
 
 #ifdef CK_CPS
@@ -3891,9 +4194,9 @@ showpkt(c) char c;
        /* These sprintfs should be safe until we have 32-digit numbers */
 
         if (pd > -1L)
-          sprintf(buffer, "%c%9ld%5ld%%%8ld%8ld ", CR, howfar, pd, tp, ps);
+          sprintf(buffer, "%c%9s%5ld%%%8ld%8ld ", CR,ckfstoa(howfar),pd,tp,ps);
         else
-          sprintf(buffer, "%c%9ld      %8ld%8ld ", CR, howfar, tp, ps);
+          sprintf(buffer, "%c%9s      %8ld%8ld ", CR,ckfstoa(howfar),tp,ps);
         conol(buffer);
         hpos = 31;
     } else if (fdispla == XYFD_R) {     /* SERIAL */
@@ -3934,9 +4237,9 @@ showpkt(c) char c;
 */
 VOID
 #ifdef CK_ANSIC
-ckscreen(int f, char c,long n,char *s)
+ckscreen(int f, char c,CK_OFF_T n,char *s)
 #else
-ckscreen(f,c,n,s) int f; char c; long n; char *s;
+ckscreen(f,c,n,s) int f; char c; CK_OFF_T n; char *s;
 #endif /* CK_ANSIC */
 /* screen */ {
     char buf[80];
@@ -4046,20 +4349,20 @@ _PROTOTYP( VOID conbgt, (int) );
 
       case SCR_FS:                      /* File-size */
         if (fdispla == XYFD_B) {
-            printf(" (%s) (%ld byte%s)",
+            printf(" (%s) (%s byte%s)",
 #ifdef NOICP
                    (binary ? "binary" : "text")
 #else
                    gfmode(binary,0)
 #endif /* NOICP */
-                   , n, n == 1L ? "" : "s");
+                   , ckfstoa(n), n == 1 ? "" : "s");
 #ifdef UNIX
             fflush(stdout);
 #endif /* UNIX */
             return;
         }
 #ifdef MAC
-        sprintf(buf,", Size: %ld",n);  conoll(buf);  hpos = 0;
+        sprintf(buf,", Size: %s",ckfstoa(n));  conoll(buf);  hpos = 0;
 #endif /* MAC */
         return;
 
@@ -4080,11 +4383,14 @@ _PROTOTYP( VOID conbgt, (int) );
             showpkt('Z');               /* Update numbers one last time */
             if (fdispla == XYFD_B) {
 #ifdef GFTIMER
-                printf(": OK (%0.3f sec, %ld cps)\n",fpxfsecs,
-                       (long)((CKFLOAT)ffc / fpxfsecs));
+               if (fpxfsecs)
+                 printf(": OK (%0.3f sec, %ld cps)",fpxfsecs,
+                        (long)((CKFLOAT)ffc / fpxfsecs));
 #else
-                printf(": OK (%d sec, %ld cps)\n",xfsecs,ffc/xfsecs);
+               if (xfsecs)
+                 printf(": OK (%d sec, %ld cps)",xfsecs,ffc/xfsecs);
 #endif /* GFTIMER */
+               printf("\n");
                 return;
             }
             if ((hpos += 5) > 78) conoll(""); /* Wrap screen line. */
@@ -4272,8 +4578,8 @@ _PROTOTYP( VOID conbgt, (int) );
             if (filcnt > 1) {
                 long fx;
                 fx = filcnt - filrej;
-                printf(" SUMMARY: %ld file%s", fx, ((fx == 1L) ? "" : "s"));
-                printf(", %ld byte%s", tfc, ((tfc == 1L) ? "" : "s"));
+                printf(" SUMMARY: %ld file%s", fx, ((fx == 1) ? "" : "s"));
+                printf(", %s byte%s", ckfstoa(tfc), ((tfc == 1) ? "" : "s"));
 #ifdef GFTIMER
                 printf(", %0.3f sec, %ld cps", fptsecs, tfcps);
 #else
@@ -4303,6 +4609,13 @@ _PROTOTYP( VOID conbgt, (int) );
         }
         conoll(""); conoll(s); hpos = 0; return;
 
+      case SCR_MS:                      /* Message from other Kermit */
+        if (fdispla == XYFD_B) {
+            printf(" MESSAGE: %s\n",s);
+            return;
+        }
+        conoll(""); conoll(s); hpos = 0; return;
+
       case SCR_TU:                      /* Undelimited text */
         if (fdispla == XYFD_B)
           return;
@@ -4862,9 +5175,9 @@ static char *dbptr = (char *)0;
 
 int
 #ifdef CK_ANSIC
-dodebug(int f, char *s1, char *s2, long n)
+dodebug(int f, char *s1, char *s2, CK_OFF_T n)
 #else
-dodebug(f,s1,s2,n) int f; char *s1, *s2; long n;
+dodebug(f,s1,s2,n) int f; char *s1, *s2; CK_OFF_T n;
 #endif /* CK_ANSIC */
 /* dodebug */ {
     char *sp;
@@ -4993,7 +5306,7 @@ dodebug(f,s1,s2,n) int f; char *s1, *s2; long n;
               sprintf(sp,"%s[%s]=^%c\n",s1,s2,(CHAR) ((n+64) & 0x7F));
             else if (n > 127 && n < 160)
               sprintf(sp,"%s[%s]=~^%c\n",s1,s2,(CHAR)((n-64) & 0x7F));
-            else sprintf(sp,"%s[%s]=0x%lX\n",s1,s2,n);
+            else sprintf(sp,"%s[%s]=0x%lX\n",s1,s2,(long)n);
         } else {
             if ((n > 31 && n < 127) || (n > 159 && n < 256))
               sprintf(sp,"%s=%c\n",s1,(CHAR) n);
@@ -5001,7 +5314,7 @@ dodebug(f,s1,s2,n) int f; char *s1, *s2; long n;
               sprintf(sp,"%s=^%c\n",s1,(CHAR) ((n+64) & 0x7F));
             else if (n > 127 && n < 160)
               sprintf(sp,"%s=~^%c\n",s1,(CHAR)((n-64) & 0x7F));
-            else sprintf(sp,"%s=0x%lX\n",s1,n);
+            else sprintf(sp,"%s=0x%lX\n",s1,(long)n);
         }
         if (zsout(ZDFILE,dbptr) < 0) {
             deblog = 0;
@@ -5017,7 +5330,7 @@ dodebug(f,s1,s2,n) int f; char *s1, *s2; long n;
       case F001:                        /* 1, "=n" */
 #ifdef COMMENT
         /* This was never used */
-        sprintf(sp,"=%ld\n",n);
+        sprintf(sp,"=%s\n",ckfstoa(n));
 #else
         /* Like F111, but shows number n in hex */
        ckmakxmsg(sp,DBUFL,
@@ -5153,7 +5466,7 @@ dodebug(f,s1,s2,n) int f; char *s1, *s2; long n;
 #endif /* CKSYSLOG */
         break;
       case F101:                        /* 5, "s1=n" */
-        sprintf(sp,"%s=%ld\n",s1,n);
+        sprintf(sp,"%s=%s\n",s1,ckfstoa(n));
         if (zsout(ZDFILE,dbptr) < 0) {
             deblog = 0;
             zclose(ZDFILE);
@@ -5177,7 +5490,7 @@ dodebug(f,s1,s2,n) int f; char *s1, *s2; long n;
 #endif /* CKSYSLOG */
         break;
       case F111:                        /* 7, "s1[s2]=n" */
-        sprintf(sp,"%s[%s]=%ld\n",s1,s2,n);
+        sprintf(sp,"%s[%s]=%s\n",s1,s2,ckfstoa(n));
         if (zsout(ZDFILE,dbptr) < 0) {
             deblog = 0;
             zclose(ZDFILE);
@@ -5321,7 +5634,6 @@ dohexdump(msg,st,cnt) CHAR *msg; CHAR *st; int cnt;
 
 /*  Session Log... */
 
-extern int slogts;                     /* Session Log timestamps */
 int tsstate = 0;
 
 VOID
@@ -5335,13 +5647,13 @@ logchar(c) char c;
 #endif /* CK_ANSIC */
 #endif /* OS2 */
 /* logchar */ {                         /* Log character c to session log */
+    extern int slognul;
     int oktolog = 0;
 #ifndef NOLOCAL
     if (!seslog)
       return;
 
-    if ((sessft != XYFT_T) ||
-       (c != '\0' &&
+    if ((sessft != XYFT_T) || (
 #ifdef UNIX
         c != '\r' &&
 #else
@@ -5371,6 +5683,8 @@ logchar(c) char c;
         c != XON &&
         c != XOFF))
       oktolog = 1;
+    if (c == '\0' && !sessft)          /* NUL in text mode */
+      if (slognul) oktolog = 1;                /* only if padding (2009/10/22) */
     if (!oktolog)
       return;
     if (slogts) {                      /* Log is timestamped */
@@ -5388,14 +5702,18 @@ logchar(c) char c;
            }
            if (zsout(ZSFILE,&ts[11]) < 0)
              goto xlogchar;
-           if (c != '\n')              /* If this is not eol */
-             tsstate = 1;              /* go to in-a-line state. */
-       } else if (c == '\n') {         /* In a line */
-           tsstate = 0;                /* If eol go to between-lines state. */
        }
     }
+    if (c == '\n')                     /* At end of line? */
+      tsstate = 0;                     /* yes */
+    else
+      tsstate = 1;                     /* no */
     if (zchout(ZSFILE,(CHAR)(c & 0xFF)) < 0) /* Log the character */
       goto xlogchar;
+    if (tsstate == 0 && slognul != 0) {        /* Null-terminating lines? */
+       if (zchout(ZSFILE,(CHAR)0) < 0) /* Add a NUL */
+         goto xlogchar;
+    }
     return;
 
   xlogchar:
@@ -5499,7 +5817,9 @@ _PROTOTYP(int tgetent,(char *, char *));
 #undef CR
 #undef NL
 #undef SO
+#ifdef US
 #undef US
+#endif /* US */
 #undef SP                               /* Used in ncurses */
 #define CHR_SP 32                       /* Use this instead */
 
@@ -5557,6 +5877,13 @@ extern int isvt52;                      /* From CKVTIO.C */
 #endif /* MYCURSES */
 #endif /* VMS */
 
+#ifdef BUG999
+_PROTOTYP(int tgetent,(char *, char *));
+_PROTOTYP(char *tgetstr,(char *, char **));
+_PROTOTYP(int tputs,(char *, int, int (*)()));
+_PROTOTYP(char *tgoto,(const char *, int, int));
+#endif /* BUG999 */
+
 #endif /* CK_CURSES */
 
 /*  F X D I N I T  --  File Xfer Display Initialization  */
@@ -5583,13 +5910,7 @@ static int notermcap = 0;
 #endif /* NOTERMCAP */
 
 #ifndef NODISPLAY
-#ifdef OSK
-VOID
-#else
-#ifdef CK_ANSIC
-void
-#endif /* CKANSIC */
-#endif /* OSK */
+CKVOID
 fxdinit(xdispla) int xdispla; {
 #ifndef COHERENT
 #ifndef OS2
@@ -5641,9 +5962,9 @@ fxdinit(xdispla) int xdispla; {
                 fdispla = XYFD_S;
                 return;
             }
+#ifdef COMMENT
             debug(F111,"fxdinit malloc trmbuf","OK",TRMBUFL);
             debug(F001,"fxdinit trmbuf","",trmbuf);
-#ifdef COMMENT
             memset(trmbuf,'\0',(size_t)TRMBUFL);
             debug(F100,"fxdinit memset OK","",0);
 #endif /* COMMENT */
@@ -6420,29 +6741,29 @@ updpct(old, new) long old, new;
 #endif /* COMMENT */
 }
 
-static long old_tr = -1L;               /* Time remaining previously */
+static CK_OFF_T old_tr = (CK_OFF_T)-1; /* Time remaining previously */
 
-static long
+static CK_OFF_T
 #ifdef CK_ANSIC
-shoetl(long old_tr, long cps, long fsiz, long howfar)
+shoetl(CK_OFF_T old_tr, long cps, CK_OFF_T fsiz, CK_OFF_T howfar)
 #else
-shoetl(old_tr, cps, fsiz, howfar) long old_tr, cps, fsiz, howfar;
+    shoetl(old_tr, cps, fsiz, howfar) long cps; CK_OFF_T old_tr, fsiz, howfar;
 #endif /* CK_ANSIC */
 /* shoetl */ {                          /* Estimated time left in transfer */
-    long tr;                            /* Time remaining, seconds */
+    CK_OFF_T tr;                       /* Time remaining, seconds */
 
 #ifdef GFTIMER
     if (fsiz > 0L && cps > 0L)
-      tr = (long)((CKFLOAT)(fsiz - howfar) / (CKFLOAT)cps);
+      tr = (CK_OFF_T)((CKFLOAT)(fsiz - howfar) / (CKFLOAT)cps);
     else
-      tr = -1L;
+      tr = (CK_OFF_T)-1;
 #else
     tr = (fsiz > 0L && cps > 0L) ?
       ((fsiz - howfar) / cps) :
-        -1L;
+        (CK_OFF_T)-1;
 #endif /* GFTIMER */
     move(CW_TR,22);
-    if (tr > -1L) {
+    if (tr > (CK_OFF_T)-1) {
         if (tr != old_tr) {
             printw("%s",hhmmss(tr));
 #ifdef KUI
@@ -6466,18 +6787,18 @@ shoetl(old_tr, cps, fsiz, howfar) long old_tr, cps, fsiz, howfar;
 
 static long
 #ifdef CK_ANSIC
-shocps(int pct, long fsiz, long howfar)
+shocps(int pct, CK_OFF_T fsiz, CK_OFF_T howfar)
 #else
-shocps(pct, fsiz, howfar) int pct; long fsiz, howfar;
+shocps(pct, fsiz, howfar) int pct; CK_OFF_T fsiz, howfar;
 #endif /* CK_ANSIC */
 /* shocps */ {
 #ifdef CPS_WEIGHTED
-    static long oldffc = 0L;
+    static CK_OFF_T oldffc = 0L;
 #endif /* CPS_WEIGHTED */
 #ifdef GFTIMER
     CKFLOAT secs, xx;
 #else
-    long secs, xx;
+    CK_OFF_T secs, xx;
 #endif /* GFTIMER */
 
 #ifdef GFTIMER
@@ -6635,6 +6956,7 @@ int
 scrft() {                               /* Display file type */
     char xferstr[256];
     xferstr[0] = NUL;
+    debug(F101,"scrft binary","",binary);
     if (binary) {
         switch(binary) {
           case XYFT_L:
@@ -6756,17 +7078,13 @@ static int nnetname = (sizeof(netname) / sizeof(char *));
 
 #ifdef CK_ANSIC
 void
-screenc(int f, char c,long n,char *s)
+screenc(int f, char c,CK_OFF_T n,char *s)
 #else
-#ifdef MYCURSES
-VOID
-#else
-int
-#endif /* MYCURSES */
+CKVOID
 screenc(f,c,n,s)
 int f;          /* argument descriptor */
 char c;         /* a character or small integer */
-long n;         /* a long integer */
+CK_OFF_T n;     /* a long integer */
 char *s;        /* a string */
 #endif /* CK_ANSIC */
 /* screenc() */ {
@@ -6777,10 +7095,10 @@ char *s;        /* a string */
     extern int ttnproto;
 #endif /* RLOGCODE */
     static int q = 0;
-    static long fsiz = -1L;   /* Copy of file size */
-    static long fcnt = 0L;    /* Number of files transferred */
-    static long fbyt = 0L;    /* Total file bytes of all files transferred */
-    static long howfar = 0L;  /* How much of current file has been xfer'd. */
+    static long fcnt = 0L;             /* Number of files transferred */
+    static CK_OFF_T fsiz = (CK_OFF_T)-1; /* Copy of file size */
+    static CK_OFF_T fbyt = 0L; /* Total file bytes of all files transferred */
+    static CK_OFF_T howfar = 0L; /* How much of current file has been xfer'd */
     static int  pctlbl = 0L;  /* Percent done vs Bytes so far */
     long cps = 0L;
 
@@ -7259,7 +7577,7 @@ char *s;        /* a string */
         /* oldgtv = -1L; */
 #endif /* GFTIMER */
         oldwin = -1;
-        fsiz = -1L;                     /* Invalidate previous file size */
+        fsiz = (CK_OFF_T)-1;           /* Invalidate previous file size */
         move(CW_PCD,22);                /* Erase percent done from last time */
 #ifdef KUI
 #ifndef K95G
@@ -7389,18 +7707,21 @@ char *s;        /* a string */
       case SCR_FS:                      /* File size */
         fsiz = n;
         move(CW_SIZ,22);
-        if (fsiz > -1L) {
+        if (fsiz > (CK_OFF_T)-1) {
 #ifdef KUI
 #ifndef K95G
             KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_SIZ, (long) n );
 #endif /* K95G */
 #endif /* KUI */
-            printw("%ld",n);
+            printw("%s",ckfstoa(n));
         }
+       if (fsiz == -2L) {
+           printw("POSSIBLY EXCEEDS LOCAL FILE SIZE LIMIT");
+       }
         clrtoeol();
 #ifdef COMMENT
         move(CW_PCD, 8);
-        if (fsiz > -1L) {               /* Put up percent label */
+        if (fsiz > (CK_OFF_T)-1) {     /* Put up percent label */
             pctlbl = 1;
            clrtoeol();
             printw("Percent Done:");
@@ -7408,7 +7729,7 @@ char *s;        /* a string */
 #else
        move(CW_PCD, 8);
        clrtoeol();
-        if (fsiz > -1L) {               /* Put up percent label */
+        if (fsiz > (CK_OFF_T)-1) {     /* Put up percent label */
             pctlbl = 1;
             printw("Percent Done:");
         } else {
@@ -7626,7 +7947,7 @@ char *s;        /* a string */
                   updpct(oldpct, pct);
             } else {
                 move(CW_PCD,22);
-                printw("%ld", ffc);
+                printw("%s", ckfstoa(ffc));
             }
 #ifdef KUI
 #ifndef K95G
@@ -7759,7 +8080,7 @@ char *s;        /* a string */
             if (pctlbl)
               updpct(oldpct,100);
             else
-              printw("%ld", ffc);
+              printw("%s", ckfstoa(ffc));
 #ifdef KUI
 #ifndef K95G
             KuiSetProperty(KUI_FILE_TRANSFER, (long) CW_FFC, (long) ffc);
@@ -7783,7 +8104,7 @@ char *s;        /* a string */
                  clrtoeol();           /* to "percent done"... */
                updpct(oldpct,100);
            } else
-              printw("%ld", ffc);
+              printw("%s", ckfstoa(ffc));
 #ifdef KUI
 #ifndef K95G
             KuiSetProperty(KUI_FILE_TRANSFER, (long) CW_FFC, (long) ffc);
@@ -7979,7 +8300,7 @@ char *s;        /* a string */
           KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_CP, tfcps);
 #endif /* K95G */
 #endif /* KUI */
-          printw("%ld", tfcps);
+          printw("%s", ckfstoa(tfcps));
           clrtoeol();
           if (success) {
               move(CW_MSG,22);          /* Print statistics in message line */
@@ -7987,9 +8308,9 @@ char *s;        /* a string */
           }
           if (success) {
               sprintf(msgbuf,
-                      "SUCCESS.  Files: %ld, Bytes: %ld, %ld CPS",
+                      "SUCCESS.  Files: %ld, Bytes: %s, %ld CPS",
                       filcnt - filrej,
-                      fbyt,
+                      ckfstoa(fbyt),
                       tfcps
                       );
               printw("%s", msgbuf);
@@ -8083,6 +8404,11 @@ char *s;        /* a string */
       case SCR_TZ:                      /* Text delimited at end */
         return;                         /* (ignored in fullscreen display) */
 
+      case SCR_MS:                     /* Message from Kermit partner */
+        move(CW_MSG,22);
+       printw("%s",s);
+        clrtoeol(); refresh(); return;
+
       case SCR_XD:                      /* X-packet data */
         pct = oldpct = 0;
         move(CW_NAM,22);
@@ -8146,7 +8472,7 @@ char *s;        /* a string */
 void
 screeng(int f, char c,long n,char *s)
 #else
-VOID
+CKVOID
 screeng(f,c,n,s)
 int f;          /* argument descriptor */
 char c;         /* a character or small integer */
@@ -8161,10 +8487,10 @@ char *s;        /* a string */
     extern int ttnproto;
 #endif /* RLOGCODE */
     static int q = 0;
-    static long fsiz = -1L;   /* Copy of file size */
+    static CK_OFF_T fsiz = (CK_OFF_T)-1; /* Copy of file size */
     static long fcnt = 0L;    /* Number of files transferred */
     static long fbyt = 0L;    /* Total file bytes of all files transferred */
-    static long howfar = 0L;  /* How much of current file has been xfer'd. */
+    static CK_OFF_T howfar = (CK_OFF_T)0; /* How much of file xfer'd so far */
     static int  pctlbl = 0L;  /* Percent done vs Bytes so far */
     long cps = 0L;
 
@@ -8336,7 +8662,7 @@ char *s;        /* a string */
         /* oldgtv = -1L; */
 #endif /* GFTIMER */
         oldwin = -1;
-        fsiz = -1L;                     /* Invalidate previous file size */
+        fsiz = (CK_OFF_T)-1L;          /* Invalidate previous file size */
         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_PCD, (long) 0 );
         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_FFC, (long) 0 );
         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_SIZ, (long) 0 );
@@ -8359,10 +8685,10 @@ char *s;        /* a string */
 
       case SCR_FS:                      /* File size */
         fsiz = n;
-        if (fsiz > -1L) {
+        if (fsiz > (CK_OFF_T)-1) {
             KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_SIZ, (long) n );
         }
-        if (fsiz > -1L) {               /* Put up percent label */
+        if (fsiz > (CK_OFF_T)-1) {     /* Put up percent label */
             pctlbl = 1;
         } else {
             pctlbl = 0;
@@ -8730,9 +9056,9 @@ char *s;        /* a string */
           KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_CP, tfcps);
           if (success) {
               sprintf(msgbuf,
-                      "SUCCESS.  Files: %ld, Bytes: %ld, %ld CPS",
+                      "SUCCESS.  Files: %s, Bytes: %ld, %ld CPS",
                       filcnt - filrej,
-                      fbyt,
+                      ckfstoa(fbyt),
                       tfcps
                       );
               KuiSetProperty(KUI_FILE_TRANSFER,
@@ -8975,7 +9301,7 @@ dbinit() {
 int
 updslot(n) int n; {                     /* Update our slot */
     int rc = 0;
-    long position;
+    CK_OFF_T position;
 
     debug(F111,"updslot","ikdbopen",ikdbopen);
     if (!ikdbopen)                      /* Not if not ok */
@@ -8988,9 +9314,9 @@ updslot(n) int n; {                     /* Update our slot */
             return(-1);
         }
     }
-    debug(F111,"updslot dbfile",dbfile,dbfp);
+    /* debug(F111,"updslot dbfile",dbfile,dbfp); */
     position = n * DB_RECL;
-    if (fseek(dbfp,position,0) < 0) {   /* Seek to desired slot */
+    if (CKFSEEK(dbfp,position,0) < 0) {        /* Seek to desired slot */
         debug(F111,"updslot fseek failed",dbfile,mydbseek);
         ikdbopen = 0;
         rc = -1;
@@ -9165,6 +9491,10 @@ freeslot(n) int n; {
 
 /*  G E T S L O T  --  Find a free database slot; returns slot number  */
 
+#ifdef UNIX
+#include <fcntl.h>                     /* For creat() */
+#endif /* UNIX */
+
 int
 getslot() {                             /* Find a free slot for us */
     FILE * rfp = NULL;                  /* Returns slot number (0, 1, ...) */
@@ -9172,7 +9502,8 @@ getslot() {                             /* Find a free slot for us */
     char pidbuf[64], * s;
     int j, k, n, x, rc = -1;
     int lockfd, tries, haveslot = 0;
-    long lockpid, i;
+    long lockpid;
+    CK_OFF_T i;
     /* char ipbuf[17]; */
 
     if (!myhexip[0])                    /* Set my hex IP address if not set */
@@ -9189,7 +9520,7 @@ getslot() {                             /* Find a free slot for us */
 
     /* Make a temporary file */
 
-    lockfd = creat(tmplck, 0600);
+    lockfd = creat(tmplck, 0600);      /* BUT THIS ISN'T PORTABLE */
     if (lockfd < 0) {
         debug(F111,"getslock temp lockfile create failure", tmplck, errno);
         return(-1);
@@ -9290,10 +9621,10 @@ getslot() {                             /* Find a free slot for us */
 #ifdef COHERENT
             chsize(fileno(dbfp),i);
 #else
-            ftruncate(fileno(dbfp),i);
+            ftruncate(fileno(dbfp),(CK_OFF_T)i);
 #endif /* COHERENT */
             x = 0;
-            fseek(dbfp,i,0);
+            CKFSEEK(dbfp,i,0);
             break;
         }
 #endif /* NOFTRUNCATE */
@@ -9359,7 +9690,7 @@ getslot() {                             /* Find a free slot for us */
 #ifdef COHERENT
         x = chsize(fileno(dbfp),dblastused+DB_RECL);
 #else
-        x = ftruncate(fileno(dbfp),dblastused+DB_RECL);
+        x = ftruncate(fileno(dbfp),(CK_OFF_T)(dblastused+DB_RECL));
 #endif /* COHERENT */
         if (x < 0)                      /* (Not fatal) */
           debug(F101,"getslot ftruncate failed", "", errno);
index 479ee36..1802b05 100644 (file)
--- a/ckuusy.c
+++ b/ckuusy.c
@@ -1,7 +1,7 @@
 #include "ckcsym.h"
 #define XFATAL fatal
 
-/*  C K U U S Y --  "User Interface" for Unix Kermit, part Y  */
+/*  C K U U S Y --  "User Interface" for C-Kermit Kermit, part Y  */
 
 /*  Command-Line Argument Parser */
 
@@ -12,7 +12,7 @@
     Jeffrey E Altman <jaltman@secure-endpoints.com>
       Secure Endpoints Inc., New York City
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2009,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -156,6 +156,8 @@ _PROTOTYP(static int dossharg, (char x) );
 int haveftpuid = 0;                    /* Have FTP user ID */
 static int have_cx = 0;                        /* Have connection */
 
+static char * failmsg = NULL;          /* Failure message */
+
 #ifdef NEWFTP
 extern char * ftp_host;
 #endif /* NEWFTP */
@@ -219,7 +221,8 @@ struct urldata g_url = {NULL,NULL,NULL,NULL,NULL,NULL,NULL};
 /*
   Returns 0 if the candidate does not seem to be a URL.
   Returns 1 if it might be a URL, with the above pointers set to its pieces:
-    service : [ // ] [ user [ : password ] @ ] host [ : service ] [ / path ]
+    service : [ // ] [ user [ : password ] @ ] host [ : service ] [ / path ] -
+              [ ? name [ = value ]]
 
   Example: ftp://ds.internic.net:21/rfc/rfc1234.txt
     url.svc = [ftp]
@@ -282,6 +285,20 @@ urlparse(s,url) char *s; struct urldata * url; {
         free(url->pth);
         url->pth = NULL;
     }
+    if (url->nopts) {
+        int i;
+        for (i = 0; i < url->nopts && i < MAX_URL_OPTS; i++ ) {
+            if (url->opt[i].nam) {
+                free(url->opt[i].nam);
+                url->opt[i].nam = NULL;
+            }
+            if (url->opt[i].val) {
+                free(url->opt[i].val);
+                url->opt[i].val = NULL;
+            }
+        }
+        url->nopts = 0;
+    }
     p = urlbuf;                                /* Was a service requested? */
     while (*p && *p != ':')            /* Look for colon */
       p++;
@@ -317,9 +334,11 @@ urlparse(s,url) char *s; struct urldata * url; {
                 p = q;
                url->hos = p;
             }
+#ifdef COMMENT
            debug(F111,"urlparse url->usr",url->usr,url->usr);
            debug(F111,"urlparse url->psw",url->usr,url->psw);
            debug(F111,"urlparse url->hos",url->usr,url->hos);
+#endif /* COMMENT */
 
             while (*p != NUL && *p != ':' && *p != '/')        /* Port? */
               p++;
@@ -447,7 +466,19 @@ static
 char *hlp4[] = {        /* ssh */
 "  [option-list] host[:port] [port]\n",
 "  The option-list consists of zero, one, or more of:\n",
+#ifdef OS2
+"  -# flags          Kermit 95 Startup Flags\n",
+"       1              turn off Win95 special fixes\n",
+"       2              do not load optional network dlls\n",
+"       4              do not load optional tapi dlls\n",
+"       8              do not load optional kerberos dlls\n",
+"      16              do not load optional zmodem dlls\n",
+"      32              use stdin for input instead of the console\n",
+"      64              use stdout for output instead of the console\n",
+"     128              do not terminate process in response to Session Logoff\n",
+#endif /* OS2 */
 "  -d                Turn on debug mode\n",
+"  -Y                Disable init file processing\n",
 "  -l user           Set username\n",
 ""
 };
@@ -508,7 +539,7 @@ xx_ftp(host, port) char * host, * port; {
       ftp_cmdlin++;                    /* 2 = same plus file transfer */
 
 #ifndef NOURL
-    debug(F111,"ftp xx_ftp g_url.usr",g_url.usr,g_url.usr);
+    /* debug(F111,"ftp xx_ftp g_url.usr",g_url.usr,g_url.usr); */
     if (haveurl && g_url.usr) {                /* Wed Oct  9 15:15:22 2002 */
        if (!*(g_url.usr)) {            /* Force username prompt if */
            haveftpuid = 0;             /* "ftp://:@host" given. */
@@ -1660,6 +1691,7 @@ struct keytab xargtab[] = {
     { "maximize",    XA_WMAX,  CM_PRE },
     { "minimize",    XA_WMIN,  CM_PRE },
     { "nobars",      XA_NOBAR, CM_PRE },
+    { "noclose" ,    XA_NOCLOSE, CM_PRE },
 #endif /* KUI */
     { "noescape",    XA_NOESCAPE, CM_PRE },
 #endif /* OS2 */
@@ -1727,6 +1759,9 @@ struct keytab xargtab[] = {
 #ifdef OS2
     { "title",       XA_TITL, CM_ARG },
 #endif /* OS2 */
+#ifdef UNIX
+    { "unbuffered",  XA_UNBUF, 0 },
+#endif /* UNIX */
 #ifndef NOSPL
     { "user",        XA_USER, CM_ARG },
 #endif /* NOSPL */
@@ -1889,6 +1924,12 @@ inixopthlp() {
             xopthlp[j] = "--nointerrupts";
             xarghlp[j] = "Disable keyboard interrupts.";
             break;
+#ifdef UNIX
+          case XA_UNBUF:
+            xopthlp[j] = "--unbuffered";
+            xarghlp[j] = "Force unbuffered console i/o.";
+            break;
+#endif /* UNIX */
 #ifdef IKSDB
           case XA_DBAS:
             xopthlp[j] = "--database:{on,off}";
@@ -1964,6 +2005,10 @@ inixopthlp() {
            xopthlp[j] = "--lockdown";
            xarghlp[j] = "Enable all lockdown options.";
            break;
+          case XA_NOCLOSE:
+            xopthlp[j] = "--noclose";
+            xarghlp[j] = "Disable Close Window and Menu Exit.";
+            break;
           case XA_NOSCROLL:
            xopthlp[j] = "--noscroll";
            xarghlp[j] = "Disable scrollback operations.";
@@ -2076,7 +2121,7 @@ iniopthlp() {
             break;
 #ifdef TCPSOCKET
           case 'F':
-            opthlp[i] = "Make a TCP connection";
+            opthlp[i] = "Use an existing TCP connection";
             arghlp[i] = "Numeric file descriptor of open TCP connection";
             break;
 #endif /* TCPSOCKET */
@@ -2559,6 +2604,11 @@ doxarg(s,pre) char ** s; int pre; {
        xsuspend = 0;
         break;
 
+#ifdef UNIX
+      case XA_UNBUF:                   /* Unbuffered console i/o*/
+       break;                          /* This one is handled in ckcmai.c */
+#endif /* UNIX */
+
 #ifdef IKSDB
       case XA_DBFI: {
           extern char * dbdir, * dbfile;
@@ -2724,10 +2774,15 @@ doxarg(s,pre) char ** s; int pre; {
         kui_init.nostatusbar = 1;
 #endif
         break;
-    case XA_NOSCROLL:
+#ifdef KUI
+      case XA_NOCLOSE:
+        kui_init.noclose = 1;
+        break;
+#endif /* KUI */
+      case XA_NOSCROLL:
         tt_scroll = 0;
         break;
-    case XA_NOESCAPE:
+      case XA_NOESCAPE:
         tt_escape = 0;
         break;
 #endif /* OS2 */
@@ -2806,9 +2861,12 @@ doxarg(s,pre) char ** s; int pre; {
          break;
       }
 #ifdef OS2
-    case XA_TITL:
-        os2settitle(p,1);
+    case XA_TITL: {
+        extern char usertitle[];
+        ckstrncpy(usertitle,p,64);
+        os2settitle("",1);
         break;
+    }
 #endif /* OS2 */
 
 #ifdef COMMENT                         /* TO BE FILLED IN ... */
@@ -3523,18 +3581,37 @@ extern char *line, *tmpbuf;             /* Character buffers for anything */
                      /* or contains wildcard characters matching real files */
                          fil2snd = 1;
                          nfils++;
+                     } else {
+                         if (!failmsg)
+                           failmsg = (char *)malloc(2000);
+                         if (failmsg) {
+                             ckmakmsg(failmsg,2000,
+#ifdef VMS
+                                      "%CKERMIT-E-SEARCHFAIL "
+#else
+                                      "kermit -s "
+#endif /* VMS */
+                                      ,
+                                      *xargv,
+                                      ": ",
+                                      ck_errstr()
+                                      );
+                         }
                      }
              }
              xargc++, xargv--;         /* Adjust argv/argc */
              if (!fil2snd && z == 0) {
+                 if (!failmsg) {
 #ifdef VMS
-                 XFATAL("%CKERMIT-E-SEARCHFAIL, no files for -s");
+                     failmsg = "%CKERMIT-E-SEARCHFAIL, no files for -s";
 #else
-                 XFATAL("No files for -s");
+                     failmsg = "No files for -s";
 #endif /* VMS */
+                 }
+                 XFATAL(failmsg);
              }
              if (z > 1) {
-                 XFATAL("-s: too many -'s");
+                 XFATAL("kermit -s: too many -'s");
              }
              if (z == 1 && fil2snd) {
                  XFATAL("invalid mixture of filenames and '-' in -s");
@@ -4293,14 +4370,18 @@ dotnarg(x) char x;
 #endif /* COMMENT */
 
 /*
+ * -#                Kermit 95 Startup Flags
  * -8                Negotiate Telnet Binary in both directions
  * -a                Require use of Telnet authentication
  * -c                Do not read the .telnetrc file
  * -d                Turn on debug mode
  * -E                No escape character
+ * -f                Forward credentials to host
  * -K                Refuse use of authentication; do not send username
+ * -k realm          Set default realm
  * -l user           Set username and request Telnet authentication
  * -L                Negotiate Telnet Binary Output only
+ * -q                Quiet mode (suppress messages)
  * -S tos            Use the IP type-of-service tos
  * -x                Require Encryption
  * -D                Disable forward-X
@@ -4310,8 +4391,7 @@ dotnarg(x) char x;
  * -T crldir=dir     Use CRLs in directory
  * -T cipher=string  Use only ciphers in string
  * -X atype          Disable use of atype authentication
- * -f                Forward credentials to host
- * -k realm          Set default realm
+ * -Y                Disable init file processing
  *
  */
          case 'h':                     /* help */
@@ -4331,6 +4411,20 @@ dotnarg(x) char x;
            TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
            break;
 
+         case 'Y':
+           xargv++, xargc--;           /* Skip past argument */
+           break;                      /* Action done in prescan */
+
+#ifdef OS2
+          case '#':                    /* K95 stdio threads */
+           xargv++, xargc--;           /* Skip past argument */
+           break;                      /* Action done in prescan */
+#endif /* OS2 */
+
+          case 'q':                    /* Quiet */
+           quiet = 1;
+           break;
+
          case 'd':
 #ifdef DEBUG
            if (deblog) {
@@ -4496,6 +4590,18 @@ dorlgarg(x) char x;
            doexit(GOOD_EXIT,-1);
            break;
 
+          case 'Y':
+           xargv++, xargc--;           /* Skip past argument */
+           break;                      /* Action done in prescan */
+#ifdef OS2
+          case '#':                    /* K95 stdio threads */
+           xargv++, xargc--;           /* Skip past argument */
+           break;                      /* Action done in prescan */
+#endif /* OS2 */
+          case 'q':                    /* Quiet */
+           quiet = 1;
+           break;
+
          case 'd':
 #ifdef DEBUG
            if (deblog) {
@@ -4567,6 +4673,8 @@ dossharg(x) char x;
 
 /*
  * -d                Debug
+ * -# args           Init
+ * -Y                no init file
  * -l user           Set username
  *
  */
@@ -4575,6 +4683,18 @@ dossharg(x) char x;
            doexit(GOOD_EXIT,-1);
            break;
 
+          case 'Y':
+           xargv++, xargc--;           /* Skip past argument */
+           break;                      /* Action done in prescan */
+#ifdef OS2
+          case '#':                    /* K95 stdio threads */
+           xargv++, xargc--;           /* Skip past argument */
+           break;                      /* Action done in prescan */
+#endif /* OS2 */
+          case 'q':                    /* Quiet */
+           quiet = 1;
+           break;
+
          case 'd':
 #ifdef DEBUG
               if (deblog) {
@@ -4601,7 +4721,7 @@ dossharg(x) char x;
 
          default:
            fatal2(*xargv,
-                  "invalid command-line option, type \"rlogin -h\" for help"
+                  "invalid command-line option, type \"ssh -h\" for help"
                   );
         }
 
@@ -4614,9 +4734,9 @@ dossharg(x) char x;
 
 #else /* No command-line interface... */
 
-extern int xargc;
 int
 cmdlin() {
+    extern int xargc;
     if (xargc > 1) {
         XFATAL("Sorry, command-line options disabled.");
     }
index 2d01207..7a111fb 100644 (file)
--- a/ckuver.h
+++ b/ckuver.h
@@ -3,7 +3,7 @@
   Author: Frank da Cruz <fdc@columbia.edu>,
   Columbia University Academic Information Systems, New York City.
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2010,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
 
 #ifdef BSD44
 #ifdef MACOSX
-#ifdef MACOSX103
-#define HERALD " Mac OS X 10.3"
-#else
 #define HERALD " Mac OS X"
-#endif /* MACOSX103 */
 #else
 #ifdef __OpenBSD__
 #define HERALD " OpenBSD"
 #endif /* BSDI4 */
 #else  /* __bsdi__ */
 #ifdef __NetBSD__
+#ifndef HERALD
 #ifdef NETBSD16
 #define HERALD " NetBSD 1.6"
 #else
 #define HERALD " NetBSD"
 #endif /* NETBSD15 */
 #endif /* NETBSD16 */
+#endif /* HERALD */
 #else  /* __NetBSD__ */
 #ifdef __FreeBSD__
 #ifdef FREEBSD51
 #endif /* HPUX5  */
 #endif /* HPUX   */
 
+#ifndef MINIX
+#ifdef MINIX315
+#define MINIX
+#endif /* MINIX315 */
+#endif /* MINIX */
+
+#ifndef MINIX
+#ifdef MINIX3
+#define MINIX
+#endif /* MINIX3 */
+#endif /* MINIX */
+
 #ifdef MINIX
+#ifdef MINIX315
+#define HERALD " Minix 3.1.5"
+#ifndef MINIX3
+#define MINIX3
+#endif /* MINIX3 */
+#endif /* MINIX315 */
+#ifdef MINIX3
+#ifndef MINIX2
+#define MINIX2
+#endif /* MINIX2 */
+#ifndef HERALD
+#define HERALD " Minix 3.0"
+#endif /* HERALD */
+#else
 #ifdef MINIX2
 #define HERALD " Minix 2.0"
 #else
-#define HERALD " Minix 1.x"
+#define HERALD " Minix 1.0"
+#endif /* MINIX3 */
 #endif /* MINIX2 */
 #endif /* MINIX */
 
 #ifdef Plan9
 #define HERALD " Plan 9 from Bell Labs"
 #else
+#ifdef SOLARIS11
+#define HERALD " Solaris 11"
+#else
+#ifdef SOLARIS10
+#define HERALD " Solaris 10"
+#else
 #ifdef SOLARIS9
 #define HERALD " Solaris 9"
 #else
 #endif /* SOLARIS7 */
 #endif /* SOLARIS8 */
 #endif /* SOLARIS9 */
+#endif /* SOLARIS10 */
+#endif /* SOLARIS11 */
 #endif /* Plan9 */
 #endif /* LYNXOS */
 #endif /* _386BSD */
index eaf7976..d5566fa 100644 (file)
--- a/ckuxla.c
+++ b/ckuxla.c
@@ -10,7 +10,7 @@
 #endif /* NOXFER */
 
 #ifndef NOCSETS
-char *xlav = "Character Set Translation 8.0.042, 3 Jul 2000";
+char *xlav = "Character Set Translation 9.0.044, 2 Jun 2011";
 
 /*  C K U X L A  */
 
@@ -19,7 +19,7 @@ char *xlav = "Character Set Translation 8.0.042, 3 Jul 2000";
   Author: Frank da Cruz <fdc@columbia.edu>,
   Columbia University Academic Information Systems, New York City.
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2011,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
@@ -202,6 +202,23 @@ struct keytab tcstab[] = {         /* Keyword table for */
 #ifdef HEBREW
     "hebrew-iso",    TC_HEBREW,  0,
 #endif /* HEBREW */
+
+#ifdef UNICODE
+    "iso-10646-ucs-2", TC_UCS2,    CM_INV, /* ISO 10646 / Unicode UCS-2 */
+#endif /* UNICODE */
+    "iso-8859-1",    TC_1LATIN,  CM_INV, /* ISO Latin Alphabet 1 */
+    "iso-8859-15",   TC_9LATIN,  CM_INV, /* ISO Latin Alphabet 9 (yes) */
+    "iso-8859-2",    TC_2LATIN,  CM_INV, /* ISO Latin Alphabet 2 */
+#ifdef CYRILLIC
+    "iso-8859-5",    TC_CYRILL,  CM_INV, /* ISO Latin/Cyrillic Alphabet */
+#endif /* CYRILLIC */
+#ifdef GREEK
+    "iso-8859-7",    TC_GREEK,   CM_INV, /* ISO 8859-7 Latin/Greek */
+#endif /* GREEK */
+#ifdef HEBREW
+    "iso-8859-8",    TC_HEBREW,  CM_INV, /* ISO Latin/Hebrew */
+#endif /* HEBREW */
+
 #ifdef KANJI
     "japanese-euc",  TC_JEUC,    CM_INV,
 #endif /* KANJI */
@@ -218,6 +235,11 @@ struct keytab tcstab[] = {         /* Keyword table for */
     "transparent",   TC_TRANSP,  0,
 #ifdef UNICODE
     "ucs2",          TC_UCS2,    0,
+#endif /* UNICODE */
+    "us-ascii",      TC_USASCII, CM_INV,
+    "usascii",       TC_USASCII, CM_INV,
+#ifdef UNICODE
+    "utf-8",         TC_UTF8,    CM_INV,
     "utf8",          TC_UTF8,    0,
 #endif /* UNICODE */
     "", 0, 0
@@ -287,16 +309,18 @@ struct csinfo fcsinfo[] = { /* File character set information... */
 /* Includes 7-bit National Replacement Character Sets of ISO 646 */
 /* Plus ISO Latin-1, DEC Multinational Character Set (MCS), NeXT char set, */
 /* Various PC and Windows code pages, etc. */
+/* As of C-Kermit 9.0 MIME names are included as invisible synomyms for */
+/* those character sets that have MIME names. */
 
 struct keytab fcstab[] = { /* Keyword table for 'set file character-set' */
 /*
   IMPORTANT: This table is replicated below as ttcstab (terminal character
   set table).  The only differences are the addition of TRANSPARENT
-  and the removal of the Kanji sets, which are not supported yet.
-  If you make changes to this table, also change ttcstab.
+  and the removal of the Kanji sets, which are not supported for terminal
+  emulation.  If you make changes to this table, also change ttcstab.
 */
 
-/* Keyword             Value       Flags */
+/* Keyword               Value       Flags */
     "apple-quickdraw",    FC_APPQD,   CM_INV, /* Apple Quickdraw */
     "ascii",              FC_USASCII, 0, /* ASCII */
     "british",            FC_UKASCII, 0, /* British NRC */
@@ -334,6 +358,7 @@ struct keytab fcstab[] = { /* Keyword table for 'set file character-set' */
 #ifdef KANJI
     "dec-kanji",          FC_JDEC,    0, /* Japanese DEC Kanji */
 #endif /* KANJI */
+    "dec-mcs",            FC_DECMCS,  CM_INV, /* DEC multinational char set */
     "dec-multinational",  FC_DECMCS,  0, /* DEC multinational character set */
     "dg-international",   FC_DGMCS,   0, /* Data General multinational */
     "dutch",              FC_DUASCII, 0, /* Dutch NRC */
@@ -362,10 +387,59 @@ struct keytab fcstab[] = { /* Keyword table for 'set file character-set' */
 #endif /* HEBREW */
     "hp-roman8",          FC_HPR8,    0, /* Hewlett Packard Roman8 */
     "hungarian",          FC_HUASCII, 0, /* Hungarian NRC */
+
+    "ibm437",             FC_CP437,   CM_INV, /* PC CP437 */
+    "ibm850",             FC_CP850,   CM_INV, /* PC CP850 (not in MIME) */
+#ifdef LATIN2
+    "ibm852",             FC_CP852,   CM_INV, /* PC CP852 */
+#endif /* LATIN2 */
+#ifdef CYRILLIC
+    "ibm855",             FC_CP855,   CM_INV, /* PC CP855 */
+#endif /* CYRILLIC */
+    "ibm858",             FC_CP858,   CM_INV, /* PC CP858 (not in MIME) */
+#ifdef HEBREW
+    "ibm862",             FC_CP862,   CM_INV, /* PC CP862 (not in MIME) */
+#endif /* HEBREW */
+#ifdef CYRILLIC
+    "ibm866",             FC_CP866,   CM_INV, /* CP866 Cyrillic */
+#endif /* CYRILLIC */
+#ifdef GREEK
+    "ibm869",             FC_CP869,   CM_INV, /* CP869 Greek */
+#endif /* GREEK */
+
+#ifdef UNICODE
+    "iso-10646-ucs-2",    FC_UCS2,    CM_INV, /* ISO 10646 / Unicode UCS-2 */
+#endif /* UNICODE */
+    "iso-8859-1",         FC_1LATIN,  CM_INV, /* ISO Latin Alphabet 1 */
+    "iso-8859-15",        FC_9LATIN,  CM_INV, /* ISO Latin Alphabet 9 (yes) */
+    "iso-8859-2",         FC_2LATIN,  CM_INV, /* ISO Latin Alphabet 2 */
+#ifdef CYRILLIC
+    "iso-8859-5",         FC_CYRILL,  CM_INV, /* ISO Latin/Cyrillic Alphabet */
+#endif /* CYRILLIC */
+#ifdef GREEK
+    "iso-8859-7",         FC_GREEK,   CM_INV, /* ISO 8859-7 Latin/Greek */
+#endif /* GREEK */
+#ifdef HEBREW
+    "iso-8859-8",         FC_HEBREW,  CM_INV, /* ISO Latin/Hebrew */
+#endif /* HEBREW */
 #ifdef KANJI
-    "iso2022jp-kanji",    FC_JIS7,    0, /* Synonym for JIS-7 */
+    "iso2022jp-kanji",    FC_JIS7,    CM_INV, /* Synonym for JIS-7 */
 #endif /* KANJI */
-    "italian",            FC_ITASCII, 0, /* Italian NRC */
+
+    "iso646-gb",          FC_UKASCII, CM_INV, /* British NRC */
+    "iso646-ca",          FC_FCASCII, CM_INV, /* French Canadian NRC */
+    "iso646-de",          FC_GEASCII, CM_INV, /* German NRC */
+    "iso646-dk",          FC_NOASCII, CM_INV, /* Norwegian and Danish NRC */
+    "iso646-es",          FC_SPASCII, CM_INV, /* Spanish NRC */
+    "iso646-fi",          FC_FIASCII, CM_INV, /* Finnish NRC */
+    "iso646-fr",          FC_FRASCII, CM_INV, /* French NRC */
+    "iso646-hu",          FC_HUASCII, CM_INV, /* Hungarian NRC */
+    "iso646-it",          FC_ITASCII, CM_INV, /* Italian NRC */
+    "iso646-no",          FC_NOASCII, CM_INV, /* Norwegian and Danish NRC */
+    "iso646-po",          FC_POASCII, CM_INV, /* Portuguese NRC */
+    "iso646-se",          FC_SWASCII, CM_INV, /* Swedish NRC */
+
+    "italian",            FC_ITASCII, CM_INV, /* Italian NRC */
 #ifdef KANJI
     "japanese-euc",       FC_JEUC,    CM_INV, /* Japanese EUC */
     "jis7-kanji",         FC_JIS7,    0, /* Japanese JIS7 7bit code */
@@ -374,8 +448,12 @@ struct keytab fcstab[] = { /* Keyword table for 'set file character-set' */
     "k",                  FC_KOI8,    CM_ABR|CM_INV,
     "ko",                 FC_KOI8,    CM_ABR|CM_INV,
     "koi",                FC_KOI8,    CM_ABR|CM_INV,
+    "koi7",               FC_KOI7,    0, /* Short KOI Cyrillic */
     "koi8",               FC_KOI8,    0, /* Old KOI-8 Cyrillic */
+    "koi8-e",             FC_KOI8,    CM_INV, /* Old KOI-8 Cyrillic */
     "koi8-cyrillic",      FC_KOI8,    CM_INV,
+    "koi8-r",             FC_KOI8R,   CM_INV, /* KOI8-R RFC1489 */
+    "koi8-u",             FC_KOI8U,   CM_INV, /* KOI8-U RFC2319 */
     "koi8r",              FC_KOI8R,   0, /* KOI8-R RFC1489 */
     "koi8u",              FC_KOI8U,   0, /* KOI8-U RFC2319 */
 #endif /* CYRILLIC */
@@ -398,6 +476,7 @@ struct keytab fcstab[] = { /* Keyword table for 'set file character-set' */
     "portuguese",         FC_POASCII, 0, /* Portuguese NRC */
 #ifdef KANJI
     "shift-jis-kanji",    FC_SHJIS,   0, /* Japanese Kanji Shift-JIS */
+    "shift_jis",          FC_SHJIS,   CM_INV, /* Japanese Kanji Shift-JIS */
 #endif /* KANJI */
 #ifdef CYRILLIC
     "short-koi",          FC_KOI7,    0, /* Short KOI Cyrillic */
@@ -407,8 +486,20 @@ struct keytab fcstab[] = { /* Keyword table for 'set file character-set' */
     "swiss",              FC_CHASCII, 0, /* Swiss NRC */
 #ifdef UNICODE
     "ucs2",               FC_UCS2,    0, /* ISO 10646 / Unicode UCS-2 */
+#endif /* UNICODE */
+    "us-ascii",           FC_USASCII, CM_INV, /* MIME */
+    "usascii",            FC_USASCII, CM_INV,
+#ifdef UNICODE
+    "utf-8",              FC_UTF8,    CM_INV, /* ISO 10646 / Unicode UTF-8 */
     "utf8",               FC_UTF8,    0, /* ISO 10646 / Unicode UTF-8 */
 #endif /* UNICODE */
+#ifdef LATIN2
+    "windows-1250",       FC_CP1250,  CM_INV, /* Windows CP 1250 */
+#endif /* LATIN2 */
+#ifdef CYRILLIC
+    "windows-1251",       FC_CP1251,  CM_INV, /* Windows CP 1251 */
+#endif /* CYRILLIC */
+    "windows-1252",       FC_CP1252,  CM_INV, /* Windows CP 1252 */
     "", 0, 0
 };
 int nfilc = (sizeof(fcstab) / sizeof(struct keytab)) - 1;
@@ -419,7 +510,7 @@ struct keytab ttcstab[] = { /* Keyword table for SET TERMINAL CHARACTER-SET */
   addition of TRANSPARENT and deletion of the Japanese sets.  If you make
   changes to this table, make the corresponding changes to fcstab.
 */
-/* Keyword               Value       Flags */
+/* Keyword             Value       Flags */
     "apple-quickdraw",    FC_APPQD,   CM_INV, /* Apple Quickdraw */
     "ascii",              FC_USASCII, 0, /* ASCII */
     "british",            FC_UKASCII, 0, /* British NRC */
@@ -432,10 +523,10 @@ struct keytab ttcstab[] = { /* Keyword table for SET TERMINAL CHARACTER-SET */
     "cp1251-cyrillic",    FC_CP1251,  0, /* Windows CP 1251 */
 #endif /* CYRILLIC */
     "cp1252",             FC_CP1252,  0, /* Windows CP 1252 */
-    "cp437",              FC_CP437,   0, /* IBM CP437 */
-    "cp850",              FC_CP850,   0, /* IBM CP850 */
+    "cp437",              FC_CP437,   0, /* PC CP437 */
+    "cp850",              FC_CP850,   0, /* PC CP850 */
 #ifdef LATIN2
-    "cp852",              FC_CP852,   0, /* IBM CP852 */
+    "cp852",              FC_CP852,   0, /* PC CP852 */
 #endif /* LATIN2 */
 #ifdef CYRILLIC
     "cp855-cyrillic",     FC_CP855,   0, /* PC CP855 */
@@ -454,11 +545,7 @@ struct keytab ttcstab[] = { /* Keyword table for SET TERMINAL CHARACTER-SET */
     "cyrillic-iso",       FC_CYRILL,  0, /* ISO Latin/Cyrillic Alphabet */
 #endif /* CYRILLIC */
     "danish",             FC_NOASCII, 0, /* Norwegian and Danish NRC */
-#ifdef COMMENT
-#ifdef KANJI
-    "dec-kanji",          FC_JDEC,    0, /* Japanese DEC Kanji */
-#endif /* KANJI */
-#endif /* COMMENT */
+    "dec-mcs",            FC_DECMCS,  CM_INV, /* DEC multinational char set */
     "dec-multinational",  FC_DECMCS,  0, /* DEC multinational character set */
     "dg-international",   FC_DGMCS,   0, /* Data General multinational */
     "dutch",              FC_DUASCII, 0, /* Dutch NRC */
@@ -484,20 +571,67 @@ struct keytab ttcstab[] = { /* Keyword table for SET TERMINAL CHARACTER-SET */
 #endif /* HEBREW */
     "hp-roman8",          FC_HPR8,    0, /* Hewlett Packard Roman8 */
     "hungarian",          FC_HUASCII, 0, /* Hungarian NRC */
-    "italian",            FC_ITASCII, 0, /* Italian NRC */
-#ifdef COMMENT
-/* Kanji terminal character sets not implemented yet */
-#ifdef KANJI
-    "japanese-euc",       FC_JEUC,    0, /* Japanese EUC */
-    "jis7-kanji",         FC_JIS7,    0, /* Japanese JIS7 7bit code */
-#endif /* KANJI */
-#endif /* COMMENT */
+
+    "ibm437",             FC_CP437,   CM_INV, /* PC CP437 */
+    "ibm850",             FC_CP850,   CM_INV, /* PC CP850 (not in MIME) */
+#ifdef LATIN2
+    "ibm852",             FC_CP852,   CM_INV, /* PC CP852 */
+#endif /* LATIN2 */
+#ifdef CYRILLIC
+    "ibm855",             FC_CP855,   CM_INV, /* PC CP855 */
+#endif /* CYRILLIC */
+    "ibm858",             FC_CP858,   CM_INV, /* PC CP858 (not in MIME) */
+#ifdef HEBREW
+    "ibm862",             FC_CP862,   CM_INV, /* PC CP862 (not in MIME) */
+#endif /* HEBREW */
+#ifdef CYRILLIC
+    "ibm866",             FC_CP866,   CM_INV, /* CP866 Cyrillic */
+#endif /* CYRILLIC */
+#ifdef GREEK
+    "ibm869",             FC_CP869,   CM_INV, /* CP869 Greek */
+#endif /* GREEK */
+
+#ifdef UNICODE
+    "iso-10646-ucs-2",    FC_UCS2,    CM_INV, /* ISO 10646 / Unicode UCS-2 */
+#endif /* UNICODE */
+    "iso-8859-1",         FC_1LATIN,  CM_INV, /* ISO Latin Alphabet 1 */
+    "iso-8859-15",        FC_9LATIN,  CM_INV, /* ISO Latin Alphabet 9 (yes) */
+    "iso-8859-2",         FC_2LATIN,  CM_INV, /* ISO Latin Alphabet 2 */
+#ifdef CYRILLIC
+    "iso-8859-5",         FC_CYRILL,  CM_INV, /* ISO Latin/Cyrillic Alphabet */
+#endif /* CYRILLIC */
+#ifdef GREEK
+    "iso-8859-7",         FC_GREEK,   CM_INV, /* ISO 8859-7 Latin/Greek */
+#endif /* GREEK */
+#ifdef HEBREW
+    "iso-8859-8",         FC_HEBREW,  CM_INV, /* ISO Latin/Hebrew */
+#endif /* HEBREW */
+
+    "iso646-gb",          FC_UKASCII, CM_INV, /* British NRC */
+    "iso646-ca",          FC_FCASCII, CM_INV, /* French Canadian NRC */
+    "iso646-de",          FC_GEASCII, CM_INV, /* German NRC */
+    "iso646-dk",          FC_NOASCII, CM_INV, /* Norwegian and Danish NRC */
+    "iso646-es",          FC_SPASCII, CM_INV, /* Spanish NRC */
+    "iso646-fi",          FC_FIASCII, CM_INV, /* Finnish NRC */
+    "iso646-fr",          FC_FRASCII, CM_INV, /* French NRC */
+    "iso646-hu",          FC_HUASCII, CM_INV, /* Hungarian NRC */
+    "iso646-it",          FC_ITASCII, CM_INV, /* Italian NRC */
+    "iso646-no",          FC_NOASCII, CM_INV, /* Norwegian and Danish NRC */
+    "iso646-po",          FC_POASCII, CM_INV, /* Portuguese NRC */
+    "iso646-se",          FC_SWASCII, CM_INV, /* Swedish NRC */
+
+    "italian",            FC_ITASCII, CM_INV, /* Italian NRC */
+
 #ifdef CYRILLIC
     "k",                  FC_KOI8,    CM_ABR|CM_INV,
     "ko",                 FC_KOI8,    CM_ABR|CM_INV,
     "koi",                FC_KOI8,    CM_ABR|CM_INV,
+    "koi7",               FC_KOI7,    0, /* Short KOI Cyrillic */
     "koi8",               FC_KOI8,    0, /* Old KOI-8 Cyrillic */
+    "koi8-e",             FC_KOI8,    CM_INV, /* Old KOI-8 Cyrillic */
     "koi8-cyrillic",      FC_KOI8,    CM_INV,
+    "koi8-r",             FC_KOI8R,   CM_INV, /* KOI8-R RFC1489 */
+    "koi8-u",             FC_KOI8U,   CM_INV, /* KOI8-U RFC2319 */
     "koi8r",              FC_KOI8R,   0, /* KOI8-R RFC1489 */
     "koi8u",              FC_KOI8U,   0, /* KOI8-U RFC2319 */
 #endif /* CYRILLIC */
@@ -511,19 +645,14 @@ struct keytab ttcstab[] = { /* Keyword table for SET TERMINAL CHARACTER-SET */
     "latin2-iso",         FC_2LATIN,  0, /* ISO Latin Alphabet 2 */
 #endif /* LATIN2 */
     "latin9-iso",         FC_9LATIN,  0, /* ISO Latin Alphabet 9 */
-    "macintosh-latin",    FC_APPQD,   0, /* "Extended Mac Latin */
+    "macintosh-latin",    FC_APPQD,   0, /* "Extended Mac Latin" */
 #ifdef LATIN2
     "mazovia-pc",         FC_MAZOVIA, 0, /* Polish Mazovia PC code page */
 #endif /* LATIN2 */
     "next-multinational", FC_NEXT,    0, /* NeXT workstation */
     "norwegian",          FC_NOASCII, 0, /* Norwegian and Danish NRC */
     "portuguese",         FC_POASCII, 0, /* Portuguese NRC */
-#ifdef COMMENT
-/* Kanji terminal character sets not implemented yet. */
-#ifdef KANJI
-    "shift-jis-kanji",    FC_SHJIS,   0, /* Japanese Kanji Shift-JIS */
-#endif /* KANJI */
-#endif /* COMMENT */
+
 #ifdef CYRILLIC
     "short-koi",          FC_KOI7,    0, /* Short KOI Cyrillic */
 #endif /* CYRILLIC */
@@ -532,8 +661,21 @@ struct keytab ttcstab[] = { /* Keyword table for SET TERMINAL CHARACTER-SET */
     "swiss",              FC_CHASCII, 0, /* Swiss NRC */
     "transparent",        FC_TRANSP,  0, /* Transparent */
 #ifdef UNICODE
+    "ucs2",               FC_UCS2,    0, /* ISO 10646 / Unicode UCS-2 */
+#endif /* UNICODE */
+    "us-ascii",           FC_USASCII, CM_INV, /* MIME */
+    "usascii",            FC_USASCII, CM_INV,
+#ifdef UNICODE
+    "utf-8",              FC_UTF8,    CM_INV, /* ISO 10646 / Unicode UTF-8 */
     "utf8",               FC_UTF8,    0, /* ISO 10646 / Unicode UTF-8 */
 #endif /* UNICODE */
+#ifdef LATIN2
+    "windows-1250",       FC_CP1250,  CM_INV, /* Windows CP 1250 */
+#endif /* LATIN2 */
+#ifdef CYRILLIC
+    "windows-1251",       FC_CP1251,  CM_INV, /* Windows CP 1251 */
+#endif /* CYRILLIC */
+    "windows-1252",       FC_CP1252,  CM_INV, /* Windows CP 1252 */
     "", 0, 0
 };
 int ntermc = (sizeof(ttcstab) / sizeof(struct keytab)) - 1;
index 6dd3171..a3cd1a5 100644 (file)
--- a/ckuxla.h
+++ b/ckuxla.h
@@ -11,7 +11,7 @@
   Author: Frank da Cruz <fdc@columbia.edu>,
   Columbia University Academic Information Systems, New York City.
 
-  Copyright (C) 1985, 2004,
+  Copyright (C) 1985, 2009,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
index 4ac88bf..2f3bb75 100644 (file)
--- a/ckwart.c
+++ b/ckwart.c
@@ -31,7 +31,7 @@ char *wartv = "Wart Version 2.14, 10 Nov 1999";
   Authors: Jeff Damens, Frank da Cruz
   Columbia University Center for Computing Activites.
   First released November 1984.
-  Copyright (C) 1984, 2004,
+  Copyright (C) 1984, 2009,
     Trustees of Columbia University in the City of New York.
     All rights reserved.  See the C-Kermit COPYING.TXT file or the
     copyright text in the ckcmai.c module for disclaimer and permissions.
index c2380eb..b89778d 100644 (file)
--- a/makefile
+++ b/makefile
@@ -1,63 +1,83 @@
 # makefile / Makefile / ckuker.mak / CKUKER.MAK
 #
-# Sat Apr 17 14:49:18 2004
-BUILDID=20040417
-#
-CKVER= "8.0.211"
+# Thu Jun 16 17:36:23 2011
+# Note: sources haven't changed since 20110615, only this file.
+BUILDID=20110615
+CKVER= "9.0.299"
+TESTID= "Beta.01"
 #
 # -- Makefile to build C-Kermit for UNIX and UNIX-like platforms --
 #
-# Copyright (C) 1985, 2004,
+# Copyright (C) 1985, 2011,
 #   Trustees of Columbia University in the City of New York.
 #   All rights reserved.  See the C-Kermit COPYING.TXT file or the
 #   copyright text in the ckcmai.c module for disclaimer and permissions.
+#   In case you can't find the COPYING.TXT file, it contains the 
+#   Simplified 3-Clause BSD License, which is an Open Source license.
 #
 # Author: Frank da Cruz, Columbia University
 # 612 West 115th Street, New York NY 10025-7799, USA
 # E-mail: fdc@columbia.edu
-# Fax:    +1 212 662-6442
 # Web:    http://www.columbia.edu/kermit/
+# FTP:    ftp://kermit.columbia.edu/kermit/
+#
+# Note: Author is no longer at Columbia University or at the 115th Street
+# address effective 1 July 2011.  The email address should still work,
+# and the website and FTP addresses, for the foreseeable future.
 #
 # Contributions from many others.  Special thanks to Jeff Altman for the
-# secure-target entries, Peter Eichhorn, assyst GmbH, for the consolidated
-# HP-UX entries and the "uninstall" target, to Robert Lipe for the updated
-# and consolidated SCO UNIX / ODT / OSR5 entries, to Ric Anderson for the
-# IRIX 6.x entries.
+# secure-build targets, Peter Eichhorn, assyst GmbH, for the consolidated
+# HP-UX targets and the "uninstall" target, to Robert Lipe for the updated
+# and consolidated SCO UNIX / ODT / OSR5 targets, to Ric Anderson for the
+# IRIX 6.x targets, to Seth Theriault for major improvements to the
+# Mac OS X targets.
+#
+# C-Kermit is written and produced by hand without any automated procedures
+# such as autoconf / automake / configure, although some of the targets below
+# (especially the linux target) inspect the environment and make some
+# decisions in the most portable way possible. The automated tools are not
+# used because (a) C-Kermit predates them, and (b) they are not portable to
+# all the platforms where C-Kermit must be (or once was) built, and (c) to
+# keep C-Kermit as independent as possible from external tools over which
+# we have no control.
 #
 # Most entries use the "xermit" target, which uses the select()-based CONNECT
-# module, ckucns.c.  The "wermit" target uses the older fork()-base CONNECT
-# module, ckucon.c, which has some drawbacks (but is more portable).  If your
-# entry still uses the "wermit" target, please try substituting the "xermit"
-# one and if it works, let us know (mailto:kermit-support@columbia.edu).
-# When changing a target over from wermit to xermit, also remove -DNOLOEARN.
+# module, ckucns.c.  The "wermit" target uses the original fork()-based CONNECT
+# module, ckucon.c, which has some drawbacks but was portable to every Unix
+# variant whether it had TCP/IP or not (select() is part of the TCP/IP
+# library, which was not standard on older Unixes).  If your target still uses
+# the "wermit" target, please try substituting the "xermit" one and if it
+# works, let us know (mailto:kermit-support@columbia.edu).  When changing a
+# target over from wermit to xermit, also remove -DNOLOEARN.
 #
 # CAREFUL: Don't put the lowercase word "if", "define", or "end" as the first
 # word after the "#" comment introducer in the makefile, even if it is
 # separated by whitespace.  Some versions of "make" understand these as
 # directives.  Uppercase letters remove the danger, e.g. "# If you have..."
-#
-# WARNING: This is a huge makefile and it contains nested makes.  Some "make"
-# programs might run out of memory.  If this happens to you, edit away the
-# parts that do not apply to your platform and try again.
+# 
+# WARNING: This is a huge makefile and it contains nested makes.  Although
+# this is less likely since the turn of the century, some "make" programs
+# might run out of memory.  If this happens to you, edit away the parts that
+# do not apply to your platform and try again.
 #
 # Certain UNIX variations have their own separate makefiles:
 #  . For 2.10 or 2.11 BSD on DEC PDP-11s, use ckubs2.mak.
 #  . For Plan 9, use ckpker.mk.
 #
 # Separate build procedures are provided non-UNIX platforms: VMS, VOS,
-# AOS/VS, etc.  See the ckaaaa.txt file for details.
+# AOS/VS, etc.  See the ckaaaa.txt file or the Kermit website for details.
 #
 #
-# DIRECTIONS
+# DIRECTIONS FOR UNIX
 #
 # Rename this file to "makefile" or "Makefile" if necessary.  Pick out the
 # entry most appropriate for your UNIX version from the list below and then
-# give the appropriate "make" command, for example "make aix43", "make sys5r4",
+# give the appropriate "make" command, for example "make aix", "make macosx",
 # "make linux".  If you experience any difficulties with the build procedure,
 # then please also read any comments that accompany the make entry itself
 # (search for the make entry name on the left margin).
 #
-# Other entries:
+# Other targets:
 #  'make install' is an installation script (read accompanying comments!).
 #  'make clean' removes intermediate and object files.
 #
@@ -72,7 +92,7 @@ CKVER= "8.0.211"
 #   http://www.columbia.edu/kermit/ckcbwr.html
 #   http://www.columbia.edu/kermit/ckubwr.html
 #
-# Most entries build C-Kermit with its symbol table included.  To reduce the
+# Most targets build C-Kermit with its symbol table included.  To reduce the
 # size of the executable program, add "LNKFLAGS=-s" to the end of your 'make'
 # command or to the makefile entry, or 'strip' the executable after
 # building.  To further reduce the size after building, use 'mcs -d' if your
@@ -82,26 +102,14 @@ CKVER= "8.0.211"
 # TCP/IP networking support: If your C-Kermit version does not include TCP/IP
 # networking, but your UNIX system does, try adding -DTCPSOCKET to the CFLAGS
 # of your makefile entry.  If that doesn't work, look at some of the other
-# entries that include this flag for ideas about what libraries might need to
+# targets that include this flag for ideas about what libraries might need to
 # be included (typically -lsocket and/or -lBSD and/or -lnsl and/or -linet).
 # NOTE: In some cases (old versions of SCO or HP-UX), you might need not only
 # a C compiler, but also a "TCP/IP developers kit" for the required object
 # libraries and header files.
 #
-# Fullscreen file transfer display support: If you are going to use C-Kermit
-# for establishing connections (dialed, network, etc), you can configure it to
-# produce a formatted file transfer display by including the curses library
-# and adding -DCK_CURSES to the CFLAGS for your option, and linking with the
-# appropriate libraries.  There are many examples below, usually ending in
-# "c", like sunos41c.  Also add -DCK_WREFRESH if your curses library includes
-# clearok() and wrefresh() functions (or remove -DNOWREFRESH if the linker
-# complains that it can't find these functions).
-#
 # Please report modifications, failures (preferably with fixes) or successes
-# to the author.
-#
-# SECURE TARGETS
-#  These are described after the next section.  Search for ******* below.
+# to the author, fdc@columbia.edu.
 #
 # TARGETS FOR DIFFERENT UNIX PLATFORMS AND VERSIONS:
 #
@@ -109,6 +117,45 @@ CKVER= "8.0.211"
 # - Those that once built OK but no longer do (e.g. too big).
 # ? Those that worked in a previous version but have not been tested recently.
 # --------------------------
+# Some commonly used targets:
+#
+# + "make linux" should work for any version of Linux on any hardware.
+# + "make linux+ssl" ditto, with OpenSSL security added.
+# + "make linux+krb5" ditto, with Kerberos 5 security added.
+# + "make linux+krb5+ssl" Linux with OpenSSL and Kerberos 5.
+# + "make netbsd", NetBSD, any version.
+# + "make netbsd+ssl", NetBSD with OpenSSL 0.9.7 or later.
+# + "make netbsd+krb5", NetBSD with Kerberos 5.
+# + "make netbsd+krb5+ssl", NetBSD with Kerberos 5 and OpenSSL 0.9.7 or later.
+# + "make freebsd", FreeBSD 4.1 or later.
+# + "make freebsd+ssl", FreeBSD 5.0 or later with OpenSSL 0.9.7 or later.
+# + "make openbsd", OpenBSD 2.3 or later.
+# + "make openbsd+ssl", OpenBSD 2.3 or later with OpenSSL 0.9.7 or later.
+# + "make mirbsd", MirBSD.
+# + "make mirbsd+ssl", MirBSD with OpenSSL 0.9.7 or later.
+# + "make macosx" should work for any Mac OS X version 10.3.9 or later.
+# + "make macosx+krb5+openssl" Mac OS X 10.3.9 or later + Kerberos V + OpenSSL.
+# + "make aix" should work for any version of AIX 4.2 or later.
+# + "make aixg" should work for any version of AIX 4.2 or later, using gcc.
+# + "make aix+ssl" ditto, with OpenSSL (specifying SSLLIB and SSLINC)
+# + "make aix+ibmssl" ditto, with IBM OpenSSL
+# + "make solaris9", "make solaris10" for Solaris 9 or 10 with Sun cc.
+# + "make solaris9g", "make solaris10g" for Solaris 9 or 10 with gcc.
+# + "make solaris11" for Solaris 11 with Sun CC
+# + "make solaris11g" for Solaris 11 with gcc
+# + "make sco_osr600" for SCO OpenServer 6.0.0.
+#
+# For other current OSs such as Solaris, HP-UX, and SCO there are separate
+# targets for different combinations of OS version and compiler; see the
+# complete list.  For older OS's see the complete list.  If an old target
+# doesn't work in this release of C-Kermit you can get a previous release from
+# the Kermit FTP site: ftp://kermit.columbia.edu/kermit/
+#
+# SECURE TARGETS (versions that support authentication and encryption)
+#  are described after the following list.  Search for ******* below.
+#
+# --------------------------
+# Complete list (alphabetical):
 # ? for 386BSD (Jolix) 0.0, 0.1, "make 386bsd" (see comments in entry),
 #     or (preferably, if it works) "make bsd44" or "make bsd44c".
 # ? for Acorn RISCiX, "make riscix" or "make riscix-gcc"
@@ -127,35 +174,36 @@ CKVER= "8.0.211"
 # ? for Apple Macintosh II with A/UX pre-3.0, "make aux", "auxgcc" or "auxufs"
 # ? for Apple Macintosh with A/UX 3.0 and gcc, "make aux3gcc" or aux3gccc
 # ? for Apple PowerMac with MkLinux, "make mklinux" (read Linux entry first)
-# + for Apple PowerMac with LinuxPPC, "make linuxppc"
+# ? for Apple PowerMac with LinuxPPC, "make linuxppc"
 # ? for Apple Macintosh with Minix 1.5.10, "make minix68k" or "make minixc68"
-# + for Apple Macintosh with Mac OS X 1.0 (Rhapsody), "make macosx10"
+# ? for Apple Macintosh with Mac OS X 1.0 (Rhapsody), "make macosx10"
 #     (no curses), "make macosx10c" (curses), or "make macosx10nc" (ncurses).
 #     Or "make macosx10ncx" (ncurses but "make macosx10nc" doesn't work).
-# + for Apple Macintosh with Mac OS X 10.2, "make macosx102nc" (ncurses).
-# + for Apple Macintosh with Mac OS X 10.3, "make macosx103"
+# ? for Apple Macintosh with Mac OS X 10.2, "make macosx102nc" (ncurses).
+# ? for Apple Macintosh with Mac OS X 10.3, "make macosx103"
+# ? for Apple Macintosh with Mac OS X 10.3.9 or later, "make macosx"
 # ? for Arix System 90 with AT&T SVR3, "make sys5r3na"
 # - for AT&T 6300 with IN/ix, "make sys5"
 # - for AT&T 6300 PLUS, "make att6300" or (with no debugging) "make att6300nd"
 # ? for AT&T 6386 WGS UNIX PC, "make sys5r3"
-# + for AT&T 3B2, 3B20 systems, "make att3b2".
+# ? for AT&T 3B2, 3B20 systems, "make att3b2".
 #   for AT&T 3B1, 7300 UNIX PC (see notes with the entries):
 #     In C-Kermit 7.0, only the gcc entries work:
-# +   "make sys3upcg", "make sys3upcgc", "make att351gm"
+# ?   "make sys3upcg", "make sys3upcgc", "make att351gm"
 #    The others fail with "too many defines" (usually in ckuusr.h):
 # -   "make sys3upc", "make sys3upcold", "make sys3upcc", "make sys3upcx",
 #       "make sys3upcm", "make att351m"
 # ? for AT&T System III/System V R2 or earlier, "make sys3" or "make sys3nid"
 # ? for AT&T System III/System V with Honey DanBer UUCP, "make sys3hdb"
 # ? for AT&T System V on DEC VAX, "make sys3" or "make sys5r3"
-# + for AT&T System V R3, use "make sys5r3" or "make sys5r3c"
-# + for AT&T System V/386 R3.2 built on Interactive 4.1.1, "make sys5r32is".
+# ? for AT&T System V R3, use "make sys5r3" or "make sys5r3c"
+# ? for AT&T System V/386 R3.2 built on Interactive 4.1.1, "make sys5r32is".
 # ? for AT&T System V/386 R320.0 Versyss Systems, use "make sys5r3"
 #     or "make sys5r3c".
-# + for AT&T System V R4, "make sys5r4", "make sys5r4sx", or "make sys5r4nx",
+# ? for AT&T System V R4, "make sys5r4", "make sys5r4sx", or "make sys5r4nx",
 #     or if the ANSI C function prototyping makes trouble, add -DNOANSI,
 #     as in "sys5r4sxna" entry
-# + for AT&T (USL) System V R4.2 use the sys5r4* entries.
+# ? for AT&T (USL) System V R4.2 use the sys5r4* entries.
 # ? for Atari Falcon with MiNT, "make posix"
 # ? for Atari ST with Minix ST 1.5.10.3, "make minix68k" or "make minixc68"
 # ? for BBN C/70 with IOS 2.0, "make c70"
@@ -173,11 +221,11 @@ CKVER= "8.0.211"
 #    (last built successfully in C-Kermit 6.0)
 # ? for Bell Labs / Lucent Plan 9, use separate makefile ckpker.mk:
 #    can be built for Intel, MIPS, 680x0, and PowerPC (last built C-Kermit 7.0)
-# + for BSDI BSD/386 1.x, "make bsdi"
-# + for BSDI BSD/OS 2.x, "make bsdi2"
-# + for BSDI BSD/OS 3.0 or 3.1, "make bsdi3"
-# + for BSDI BSD/OS 4.x, "make bsdi4"
-# + for BSDI BSD/OS 4.x, to build a binary that also works on FreeBSD,
+# ? for BSDI BSD/386 1.x, "make bsdi"
+# ? for BSDI BSD/OS 2.x, "make bsdi2"
+# ? for BSDI BSD/OS 3.0 or 3.1, "make bsdi3"
+# ? for BSDI BSD/OS 4.x, "make bsdi4"
+# ? for BSDI BSD/OS 4.x, to build a binary that also works on FreeBSD,
 #     "make bsdix".
 # ? for Berkeley Unix 2.4, "make v7" (but read v7 material below)
 # ? for Berkeley Unix 2.9 (DEC PDP-11 or Pro-3xx), "make bsd29"
@@ -186,23 +234,23 @@ CKVER= "8.0.211"
 #     This makefile is too big.  Read the instructions in ckubs2.mak.
 #     "make -f ckubs2.mak bsd210" or "make -f ckubs2.mak bsd211".
 #     (last built successfully in C-Kermit 6.0 - later versions too big)
-# + for Berkeley Unix 2.11 "make -f ckubs2.mak bsd210noicp" (no command parser)
+# ? for Berkeley Unix 2.11 "make -f ckubs2.mak bsd210noicp" (no command parser)
 # ? for Berkeley Unix 4.1, "make bsd41"
-# + for Berkeley Unix 4.2 on VAX, "make bsd42" or "make bsd42c"
+# ? for Berkeley Unix 4.2 on VAX, "make bsd42" or "make bsd42c"
 # ? for Berkeley Unix 4.2 or 4.3 with HoneyDanBer UUCP, "make bsdhdb"
-# + for Berkeley Unix 4.3 on VAX, "make bsd43", "make bsd43nc".
-# + for Berkeley Unix 4.3 on VAX, no networking "make bsd43nonet.
-# + for Berkeley Unix 4.3 without acucntrl program, "make bsd42" or "bsd42c"
+# ? for Berkeley Unix 4.3 on VAX, "make bsd43", "make bsd43nc".
+# ? for Berkeley Unix 4.3 on VAX, no networking "make bsd43nonet.
+# ? for Berkeley Unix 4.3 without acucntrl program, "make bsd42" or "bsd42c"
 #     NOTE: all the C-Kermit 7.0 full builds for old BSDs fail with
 #     "too many defines" in CPP, even on big architectures like VAX.  This
 #     can be worked around with a clever ruse.  See comments at target.
-# + for Berkeley Unix 4.3, command-line only, "make bsdm".
-# + for Berkeley Unix 4.3-Tahoe, same as 4.3 BSD
-# + for Berkeley Unix 4.3-Reno, "make bsd43" or "make bsd44" or "make bsd44c"
-# + for Berkeley Unix 4.3-Carson City, "make bsd44" or "make bsd44c"
-# + for Berkeley Unix 4.4-Networking/2 or -Alpha, "make bsd44" or "make bsd44c"
-# + for Berkeley Unix 4.4, "make bsd44" or "make bsd44c"
-# + for Berkeley Unix 4.4-Lite, "make bsd44" or "make bsd44c"
+# ? for Berkeley Unix 4.3, command-line only, "make bsdm".
+# ? for Berkeley Unix 4.3-Tahoe, same as 4.3 BSD
+# ? for Berkeley Unix 4.3-Reno, "make bsd43" or "make bsd44" or "make bsd44c"
+# ? for Berkeley Unix 4.3-Carson City, "make bsd44" or "make bsd44c"
+# ? for Berkeley Unix 4.4-Networking/2 or -Alpha, "make bsd44" or "make bsd44c"
+# ? for Berkeley Unix 4.4, "make bsd44" or "make bsd44c"
+# ? for Berkeley Unix 4.4-Lite, "make bsd44" or "make bsd44c"
 # ? for Bull DPX/2 with BOS/X, "make bulldpx2"
 # ? for Cadmus, "make sys3"
 #   for Caldera, see SCO, Linux.
@@ -211,8 +259,8 @@ CKVER= "8.0.211"
 # ? for Charles River Data Systems Universe 680x0 with UNOS 9.2, maybe
 #     also other UNOS versions, "make crds"
 # ? for CIE Systems 680/20 with Regulus, "make cie"
-# + for Commodore Amiga 3000UX Sys V R4, "make sys5r4sx"
-# + for Commodore Amiga 3000UX Sys V R4 and TCP/IP, "make svr4amiganet"
+# ? for Commodore Amiga 3000UX Sys V R4, "make sys5r4sx"
+# ? for Commodore Amiga 3000UX Sys V R4 and TCP/IP, "make svr4amiganet"
 # ? for Commodore Amiga with Minix 1.5.10, "make minix68k" of "make minixc68"
 # ? for Concurrent/Masscomp with RTU 4.0 or later, BSD environment, "make
 #     rtubsd", "make rtubsd2", "make rtubsd3" (depending on where ndir.h
@@ -220,7 +268,7 @@ CKVER= "8.0.211"
 # ? for Concurrent/Masscomp with RTU 4.0 or later, System V R2, "make rtus5"
 # ? for Concurrent (Perkin-Elmer) 3200 series, "make sys5".
 # ? for Concurrent (Perkin-Elmer) 3200 series with <dirent.h>, "make ccop1"
-# + for Concurrent PowerMAX OS SVR4, "make powermax"
+# ? for Concurrent PowerMAX OS SVR4, "make powermax"
 # ? for Consensys UNIX SV/386 R4V3, "make sys5r4sxtcpc" or "make sys5r4sx"
 # ? for Convergent with CTIX Sys V R2, "make sys5"
 # ? for Convergent with CTIX 6.4.1, "make ctix"
@@ -238,10 +286,10 @@ CKVER= "8.0.211"
 # ? for Cyber 910 (Silicon-Graphics Iris) with Irix 3.3, "irix33"
 # ? for Data General AViiON with DG/UX 5.4 before R3.00, "make dgux540"
 #     or "make dgux540c" (compile ckwart separately if necessary)
-# + for DG/UX 5.4 on AViiON Intel models, "make dgux540i" or dgux540ic.
+# ? for DG/UX 5.4 on AViiON Intel models, "make dgux540i" or dgux540ic.
 # ? for DG/UX 5.4R4.11 on AViiON, all models, "make dgux54411"
-# + for DG/UX 5.4R4.20 on AViiON, all models, "make dgux54420"
-# + for Data General AViiON with DG/UX 4.3x using Sys V-isms, "make dgux430"
+# ? for DG/UX 5.4R4.20 on AViiON, all models, "make dgux54420"
+# ? for Data General AViiON with DG/UX 4.3x using Sys V-isms, "make dgux430"
 # ? for Data General AViiON with DG/UX 4.3x using BSD-isms, "make dgux430bsd"
 # ? for Data General AViiON, earlier UNIX versions,
 #     "make sys5r3" (maybe compile ckwart separately, or "touch ckcpro.c")
@@ -258,8 +306,8 @@ CKVER= "8.0.211"
 # ? for DECstation or VAX with Ultrix 4.0 or 4.1, "make ultrix40"
 # ? for DECstation or VAX with Ultrix 4.2, "make ultrix42" or "make ultrix42c"
 # ? for DECstation or VAX with Ultrix 4.x, POSIX world, "make posix"
-# + for DECstation or VAX with Ultrix 4.3, "make ultrix43".
-# + for DECstation or VAX with Ultrix 4.4, "make ultrix44".
+# ? for DECstation or VAX with Ultrix 4.3, "make ultrix43".
+# ? for DECstation or VAX with Ultrix 4.4, "make ultrix44".
 # ? for DECstation 5000/50, /150 or /260 (R4x00 MIPS CPU), Ultrix 4.3A or later
 #     "make ultrix43-mips3" or "make ultrix43c-mips3"
 # ? for DECstation (MIPS) with Berkeley Sprite, "make bsd44"?
@@ -267,10 +315,10 @@ CKVER= "8.0.211"
 # ? for DEC Alpha with OSF/1 1.0 to 1.3, "make dec-osf"
 # ? for DEC PC 486 with OSF/1, "make dec-osf"
 # ? for DEC Alpha with OSF/1 2.x, "make dec-osf20"
-# + for DEC Alpha with OSF/1 3.0, "make dec-osf30"
-# + for DEC Alpha with Digital UNIX 3.2, "make du32"
-# + for DEC Alpha with Digital UNIX 4.0-4.0D, "make du40" or "make du40gcc"
-# + for DEC Alpha with Digital UNIX 4.0E or higher, see Tru64.
+# ? for DEC Alpha with OSF/1 3.0, "make dec-osf30"
+# ? for DEC Alpha with Digital UNIX 3.2, "make du32"
+# ? for DEC Alpha with Digital UNIX 4.0-4.0D, "make du40" or "make du40gcc"
+# ? for DEC Alpha with Digital UNIX 4.0E or higher, see Tru64.
 # - for DEC Pro-350 with Pro/Venix V1.x, "make provx1" (version 5A is too big)
 # ? for DEC Pro-380 with Pro/Venix V2.0 (Sys V), "make sys3" or "make sys3nid"
 # ? for DEC Pro-380 with 2.9, 2.10, or 2.11 BSD, "make bsd29" or "make bsd210"
@@ -303,66 +351,56 @@ CKVER= "8.0.211"
 # ? for Fortune 32:16, For:Pro 1.8, "make ft18"
 # ? for Fortune 32:16, For:Pro 2.1, "make ft21"
 # ? for FPS 500 with FPX 4.1, "made bsd"
-# + for FreeBSD 1.0, "make freebsd1"
-# + for FreeBSD 2.x, "make freebsd2" (ncurses) or "make freebsd2c" (curses)
-# + for FreeBSD 3.x, "make freebsd3" (ncurses) or "make freebsd3c" (curses)
-# + for FreeBSD 4.0, "make freebsd4"
-# + for FreeBSD 4.1, "make freebsd41"
-# + for FreeBSD 4.2, "make freebsd42"
-# + for FreeBSD 4.3, "make freebsd43"
-# + for FreeBSD 4.4, "make freebsd44"
-# + for FreeBSD 4.5, "make freebsd45"
-# + for FreeBSD 4.6, "make freebsd46"
-# + for FreeBSD 4.7, "make freebsd47"
-# + for FreeBSD 4.8, "make freebsd48"
-# + for FreeBSD 4.9, "make freebsd49"
-# ? for FreeBSD 5.0, "make freebsd50"
-# ? for FreeBSD 5.1, "make freebsd51"
+# ? for FreeBSD 1.0, "make freebsd1"
+# ? for FreeBSD 2.x, "make freebsd2" (ncurses) or "make freebsd2c" (curses)
+# ? for FreeBSD 3.x, "make freebsd3" (ncurses) or "make freebsd3c" (curses)
+# ? for FreeBSD 4.0, "make freebsd40"
+# ? for FreeBSD 4.1 or later, "make freebsd"
 # ? for Harris HCX-2900, "make sys5r3"
 # ? for Harris Night Hawk 88K or 68K with CX/UX pre-6.1, "make sys5r3"
 # ? for Harris Night Hawk 88K or 68K with CX/UX 6.1 or later, "make cx_ux"
 # ? for Heurikon, "make sys3"
 # ? for HP-3000, MPE/ix, "make posix"?
-# + for HP-9000 Series 300 with 4.4BSD, "make bsd44"
-# + for HP-9000 Series 500, HP-UX 5.21 and no networking "make hpux0500"
-# + for HP-9000 Series 500, HP-UX 5.21 with WIN/TCP 1.2 "make hpux0500wintcp"
-# + for HP-9000 Series, HP-UX 6.5, without long filenames,
-#     "make hpux0650" or "make hpux0650c"
-# + for HP-9000 Series, HP-UX 7.0 or later no long filenames, "make hpux0700sf"
+# ? for HP-9000 Series 300 with 4.4BSD, "make bsd44"
+# ? for HP-9000 Series 500, HP-UX 5.21 and no networking "make hpux0500"
+# ? for HP-9000 Series 500, HP-UX 5.21 with WIN/TCP 1.2 "make hpux0500wintcp"
+# ? for HP-9000 Series, HP-UX 6.5, without long filenames,
+#     "make hpux0650", "make hpux0650c" or "make hpux0650tcpc"
+# ? for HP-9000 Series, HP-UX 7.0 or later no long filenames, "make hpux0700sf"
 #     or (to include tcp/ip, curses, etc) "make hpux0700sftcpc"
-# + for HP-9000 Series with HP-UX 7.0, TCP/IP,long filenames,"make hpux0700lfn"
-# + for HP-9000 300/400 Series (680x0) with HP-UX 8.0, TCP/IP, "make hpux0800"
+# ? for HP-9000 Series with HP-UX 7.0, TCP/IP,long filenames,"make hpux0700lfn"
+# ? for HP-9000 300/400 Series (680x0) with HP-UX 8.0, TCP/IP, "make hpux0800"
 #      or "make hpux0800c"
-# + for HP-9000 700/800 Series (PA-RISC), HP-UX 8.0, TCP/IP, "make hpux0800pa"
+# ? for HP-9000 700/800 Series (PA-RISC), HP-UX 8.0, TCP/IP, "make hpux0800pa"
 #      or "make hpux0800pac"
-# + for HP-9000 Series with HP-UX 8.0, no TCP/IP, long filenames,
+# ? for HP-9000 Series with HP-UX 8.0, no TCP/IP, long filenames,
 #      "make hpux0800notcp"
-# + for HP-9000 Series, HP-UX 9.0 - 9.10, TCP/IP, curses, restricted compiler
+# ? for HP-9000 Series, HP-UX 9.0 - 9.10, TCP/IP, curses, restricted compiler
 #     (no optimization, no ANSI), all models, "make hpux0900".  Read the
 #     hpux0900 entry below for more info.
-# + for HP-9000 700 and 800 Series, HP-UX 9.x, TCP/IP, curses,
+# ? for HP-9000 700 and 800 Series, HP-UX 9.x, TCP/IP, curses,
 #     HP optimizing ANSI C compiler, "make hpux0900o700".
-# + for HP-9000 with Motorola CPUs, HP-UX 9.x, TCP/IP, curses,
+# ? for HP-9000 with Motorola CPUs, HP-UX 9.x, TCP/IP, curses,
 #     HP optimizing ANSI C compiler, "make hpux0900mot".
-# + for HP-9000 on other CPUs, HP-UX 9.x, TCP/IP, curses,
+# ? for HP-9000 on other CPUs, HP-UX 9.x, TCP/IP, curses,
 #     HP optimizing ANSI C compiler, "make hpux0900o".
-# + for HP-9000 series, HP-UX 9.x, TCP/IP, curses, gcc, all models,
+# ? for HP-9000 series, HP-UX 9.x, TCP/IP, curses, gcc, all models,
 #     "make hpux0900gcc"
-# + for HP-9000 700/800 Series, HP-UX 10.00,10.01,10.10,10.20,10.30, TCP/IP,
+# ? for HP-9000 700/800 Series, HP-UX 10.00,10.01,10.10,10.20,10.30, TCP/IP,
 #     curses, restricted compiler (no optimization, no ANSI) "make hpux1000".
-# + for HP-9000 700/800 Series, HP-UX 10.00,10.01,10.10,10.20,10.30, TCP/IP,
+# ? for HP-9000 700/800 Series, HP-UX 10.00,10.01,10.10,10.20,10.30, TCP/IP,
 #     curses, HP ANSI/optimizing compiler "make hpux1000o" or "make hpux1000o+"
-# + for HP-9000 HP-UX 10.00 or later with gcc, "make hpux1000gcc"
-# + for Trusted HP-UX 10.xx "make hpux1000t", "make hpux1000to",
+# ? for HP-9000 HP-UX 10.00 or later with gcc, "make hpux1000gcc"
+# ? for Trusted HP-UX 10.xx "make hpux1000t", "make hpux1000to",
 #     or make hpux1000to+"
-# + for HP-9000 700/800 Series, HP-UX 11.00,TCP/IP,curses, restricted compiler
+# ? for HP-9000 700/800 Series, HP-UX 11.00,TCP/IP,curses, restricted compiler
 #     (no optimization, no ANSI) "make hpux1100".
-# + for HP-9000 700/800 Series, HP-UX 11.00,TCP/IP,curses, restricted compiler
+# ? for HP-9000 700/800 Series, HP-UX 11.00,TCP/IP,curses, restricted compiler
 #     HP ANSI/optimizing compiler "make hpux1100o" or "make hpux1100o+"
-# + for Trusted HP-UX 11.xx "make hpux1100t", "make hpux1100to",
+# ? for Trusted HP-UX 11.xx "make hpux1100t", "make hpux1100to",
 #     make hpux1100to+"
-# + for HP-9000 PA-RISC models with NeXTSTEP 3.3, "make nextquadfat".
-# + for HP-9000 PA-RISC models with OPENSTEP/Mach 4.1, "make nextquadfat".
+# ? for HP-9000 PA-RISC models with NeXTSTEP 3.3, "make nextquadfat".
+# ? for HP-9000 PA-RISC models with OPENSTEP/Mach 4.1, "make nextquadfat".
 # ? for IBM 370 Series with IX/370, "make ix370"
 # ? for IBM 370 Series with AIX/370 1.2, "make aix370"
 # ? for IBM 370 Series with AIX/370 3.0, "make aix370"
@@ -373,39 +411,43 @@ CKVER= "8.0.211"
 #     minimum interactive version, "make coherentmi"
 # ? for IBM PC 386 & compatibles with Mark Williams Coherent OS,
 #     full interactive version, prior to v4.2, "make coherentmax"
-# + for IBM PC 386 & compatibles with Mark Williams Coherent OS 4.2,
+# ? for IBM PC 386 & compatibles with Mark Williams Coherent OS 4.2,
 #     "make coherent42"
 # ? for IBM PC 386 & compatibles with LynxOS 2.0 or 2.1, "make lynx21"
 # ? for IBM PC 386 & compatibles with LynxOS 2.2, "make lynx"
 # - for IBM PC/AT & compatibles with original MINIX, "make minix" (too big)
 # ? for IBM PC family, 386-based, with MINIX/386 1.5, "make minix386"
 #     or if you have GNU CC, "make minix386gcc"
-# + for IBM PC family, 386-based, with MINIX 2.0, "make minix20"
-# + for IBM PS/2 with PS/2 AIX 1.0, 1.1, or 1.2, "make ps2aix" or ps2aixnetc.
+# ? for IBM PC family, 386-based, with MINIX 2.0, "make minix20"
+# ? for IBM PC family, 386-based, with MINIX 3.0, "make minix3"
+# ? for IBM PS/2 with PS/2 AIX 1.0, 1.1, or 1.2, "make ps2aix" or ps2aixnetc.
 # ? for IBM PS/2 with PS/2 AIX 1.3, "make ps2aix3"
 # ? for IBM RISC System/6000 with AIX 3.0, "make aix30"
 # ? for IBM RISC System/6000 with AIX 3.1.x, "make aix31"
-# + for IBM RISC System/6000 with AIX 3.2.0 thru 3.2.5, "make aix32"
-# + for IBM RS/6000 or Power Series with AIX 4.1.x, "make aix41"
-# + for IBM RS/6000 or Power Series with AIX 4.1.x with gcc, "make aix41g"
-# + for IBM RS/6000 or Power Series with AIX 4.1 with X.25, "make aix41x25"
-# + for IBM RS/6000 or Power Series with AIX 4.2, "make aix42"
-# + for IBM RS/6000 or Power Series with AIX 4.3, "make aix43" (or aix43gcc)
-# + for IBM RS/6000 or Power Series with AIX 4.4, "make aix44" (or aix44gcc)
-# + for IBM RS/6000 or Power Series with AIX 4.5, "make aix45" (or aix45gcc)
-# + for IBM RS/6000 or Power Series with AIX 5.0, "make aix50" (or aix50gcc)
-# + for IBM RS/6000 or Power Series with AIX 5.1, "make aix51" (or aix51gcc)
+# ? for IBM RISC System/6000 with AIX 3.2.0 thru 3.2.5, "make aix32"
+# ? for IBM RS/6000 or Power Series with AIX 4.1.x, "make aix41"
+# ? for IBM RS/6000 or Power Series with AIX 4.1.x with gcc, "make aix41g"
+# ? for IBM RS/6000 or Power Series with AIX 4.1 with X.25, "make aix41x25"
+# ? for IBM RS/6000 or Power Series with AIX 4.2 or later: "make aix"
+#  (the following "make aixnn" targets are no longer necessary except for gcc)
+# ? for IBM RS/6000 or Power Series with AIX 4.2, "make aix42"
+# ? for IBM RS/6000 or Power Series with AIX 4.3, "make aix43" (or aix43gcc)
+# ? for IBM RS/6000 or Power Series with AIX 4.4, "make aix44" (or aix44gcc)
+# ? for IBM RS/6000 or Power Series with AIX 4.5, "make aix45" (or aix45gcc)
+# ? for IBM RS/6000 or Power Series with AIX 5.0, "make aix50" (or aix50gcc)
+# ? for IBM RS/6000 or Power Series with AIX 5.1, "make aix51" (or aix51gcc)
 # ? for IBM RS/6000 or Power Series with AIX 5.2, "make aix52" (or aix52gcc)
 # ? for IBM RS/6000 or Power Series with AIX 5.3, "make aix53" (or aix53gcc)
+# ? for IBM RS/6000 or Power Series with AIX 6.1, "make aix61" (or aix53gcc)
 # ? for IBM RT PC with AIX 2.1, "make sys3"
-# + for IBM RT PC with AIX 2.2.1, "make rtaix" or "make rtaixc"
+# ? for IBM RT PC with AIX 2.2.1, "make rtaix" or "make rtaixc"
 # ? for IBM RT PC with ACIS 4.2, "make bsd"
 # ? for IBM RT PC with ACIS 4.3, "make rtacis" or "make bsd KFLAGS=-DNOANSI"
 # ? for IBM RT PC with 4.3BSD/Reno, "make bsd44" or "make bsd44c"
 # ? for ICL DRS400 or 400E, "make iclsys5r3"
 # ? for ICL DRS3000 (80486) with DRS/NX, "make iclsys5r4_486"
 # ? for ICL DRS6000 (SPARC) with DRS/NX, "make iclsys5r4"
-# + for ICL DRS6000 (SPARC) with DRS/NX 4.2MP 7MPlus, "make iclsys5r4m+"
+# ? for ICL DRS6000 (SPARC) with DRS/NX 4.2MP 7MPlus, "make iclsys5r4m+"
 # ?     Ditto but with IKSD support included, "make iclsys5r4m+iksd"
 # ? for Integrated Solutions Inc V8S VME 68020, "make isi"
 # ? for Intel 302 with Bell Tech Sys V/386 R3.2, "make sys5r3"
@@ -418,35 +460,36 @@ CKVER= "8.0.211"
 #     or "make is5r3net2"
 # ? for Interactive 386/ix 2.2.1, job control, curses, no net, gcc,
 #     "make is5r3gcc"
-# + for Interactive UNIX Sys V R3.2 V2.2 - 4.0 without TCP/IP, "make is5r3jc"
-# + for Interactive UNIX Sys V R3.2 V2.2 - 4.0 with TCP/IP, "make is5r3netjc"
-# + for Intergraph Clipper, "make clix" or "make clixnet"
+# ? for Interactive UNIX Sys V R3.2 V2.2 - 4.0 without TCP/IP, "make is5r3jc"
+# ? for Interactive UNIX Sys V R3.2 V2.2 - 4.0 with TCP/IP, "make is5r3netjc"
+# ? for Intergraph Clipper, "make clix" or "make clixnet"
 # ? for Jolix (see 386BSD)
-# + for Red Hat Linux 7.1 (and higher) fully configured (krb5, SSL, etc):
-#     "make redhat71", "make redhat72", "make redhat73", "make redhat80"
-#     "make redhat9"
-#     NOTE: You must use this target for Red Hat 7.1 since it
-#     also includes a workaround for its broken curses library.
-#     WARNING: These targets create binaries that include code for
-#     strong encryption and are therefore not exportable. DO NOT PUT
-#     THESE BINARIES ON US OR CANADIAN WEB OR FTP SITES.
 # + for Linux 1.2 and later, "make linux".  Uses ncurses.  This version
 #     handles serial speeds up to 460800 bps, Linux FSSTD 1.2, TCP/IP, and
 #     should work on both libc and glibc systems.  For static linking, use
 #     "make linux LNKFLAGS=-static".  Please read the comments that accompany
-#     the linux entry.
+#     the linux entry.  As of 8.0.212 Dev.10, this also includes Large File
+#     Support (LFS).
 # + for Linux builds that fail with "sys/select.h: No such file or directory",
 #     "make linuxns"
 # + for Linux 1.2 and later but with curses.h and libcurses (rather than
 #     ncurses.h and libncurses), use "make linuxc".
 # + for Linux 1.2 and later with no curses support at all, "make linuxnc".
-# + for Linux on PowerMac (Mklinux DR3), "make mklinux".
-# + for Linux 1.2 and later, to build with egcs, "make linuxegcs".
 # + for Linux with no TCP/IP, "make linuxnotcp"
-# + for Linux with lcc compiler, no TCP/IP, "make linuxnotcp-lcc"
-# ? for Linux 1.0 or earlier, "make linux10", or (to remove TCP/IP)
-#     "make linuxnotcp".
-#     IMPORTANT: Read the comments that accompany the "linux:" entry.
+# (The following Linux targets are historic and might not work...)
+# ? for Red Hat Linux 7.1 through RH9, fully configured (krb5, SSL, etc):
+#     "make redhat71", "make redhat72", "make redhat73", "make redhat80"
+#     "make redhat9"
+#     NOTE: You must use this target for Red Hat 7.1 since it
+#     also includes a workaround for its broken curses library.
+#     WARNING: These targets create binaries that include code for
+#     strong encryption and are therefore not exportable. DO NOT PUT
+#     THESE BINARIES ON US OR CANADIAN WEB OR FTP SITES.
+# ? for Linux on PowerMac (Mklinux DR3), "make mklinux".
+# ? for Linux 1.2 and later, to build with egcs, "make linuxegcs".
+# ? for Linux with lcc compiler, no TCP/IP, "make linuxnotcp-lcc"
+# ? for Linux 1.0 or earlier, "make linux10".
+# (End old linux targets)
 # ? for Mach 2.6 on (anything, e.g. DECstation), "make bsd42" or "make bsd43".
 # ? for MachTen (Tenon) 2.1.1.D on (e.g.) Apple Powerbook, "make machten".
 # ? for Masscomp RTU AT&T System III, "make rtu"
@@ -456,16 +499,16 @@ CKVER= "8.0.211"
 # ? for Microsoft,IBM Xenix (/286, PC/AT, etc), "make xenix" or "make sco286"
 # ? for MIPS System with RISC/os (UMIPS) 4.52 = AT&T SVR3, "make mips"
 #     or "make mipstcpc"
-# + for MkLinux on Power Macintosh, "make mklinux"
+# ? for MkLinux on Power Macintosh, "make mklinux"
 # ? for Modcomp 9730, Real/IX, "make sys5r3" (or modify to use gcc = GLS cc)
 # ? for Modcomp Realstar 1000 with REAL/IX D.1, "make sv88r32"
 # ? for Motorola Four Phase, "make sys3" or "make sys3nid"
-# + for Motorola Delta System V/68 R3, "make sv68r3"
-# + for Motorola Delta System V/68 R3V5, "make sv68r3v5"
-# + for Motorola Delta System V/68 R3V5.1, "make sv68r3v51"
-# + for Motorola Delta System V/68 R3V6 with NSE TCP/IP, "make sv68r3v6"
-# + for Motorola Delta System V/88 R32, "make sv88r32"
-# + for Motorola Delta System V/88 R40, "make sv88r40"
+# ? for Motorola Delta System V/68 R3, "make sv68r3"
+# ? for Motorola Delta System V/68 R3V5, "make sv68r3v5"
+# ? for Motorola Delta System V/68 R3V5.1, "make sv68r3v51"
+# ? for Motorola Delta System V/68 R3V6 with NSE TCP/IP, "make sv68r3v6"
+# ? for Motorola Delta System V/88 R32, "make sv88r32"
+# ? for Motorola Delta System V/88 R40, "make sv88r40"
 # ? for Mt Xinu Mach386 on 386/486-based PCs, "make bsd43"
 # ? for NCR Tower 1632, OS 1.02, "make tower1"
 # ? for NCR Tower 1632 or Minitower with System V R2, "make sys3"
@@ -482,13 +525,15 @@ CKVER= "8.0.211"
 #       ln /usr/include/arpa/inet.h /usr/include/sys/inet.h
 #       ln /usr/include/sys/termiox.h /usr/include/termiox.h
 # ? for NCR System 3000, NCR UNIX 02.02.01, same as above.
-# + for NCR MP-RAS System V R4 V2.03 or 3.02, "make mpras" or "make mprastcpc"
-# + for NetBSD through 1.4.x on any architecture, "make netbsd"
-# + for NetBSD 1.5.0 and later, "make netbsd15"
-# + for NeXT with NeXTSTEP 1.0 through 3.2, "make next" (on a NeXT)
-# + for NeXT with NeXTSTEP 3.3, "make next33"
+# ? for NCR MP-RAS System V R4 V2.03 or 3.02, "make mpras" or "make mprastcpc"
+# ? for NetBSD any version on any architecture, "make netbsd"
+# ? for NetBSD with SSL/TLS, SRP, and ZLIB, "make netbsd+ssl+srp+zlib"
+# ? for NetBSD with ncurses specified instead of curses, "make netbsdn"
+# ? for NetBSD with all curses support omitted, "make netbsdnc"
+# ? for NeXT with NeXTSTEP 1.0 through 3.2, "make next" (on a NeXT)
+# ? for NeXT with NeXTSTEP 3.3, "make next33"
 # ? for NeXT with OPENSTEP/Mach 4.1, "make nextquadfat".
-# + for NeXT with OPENSTEP/Mach 4.2, "make openstep42".
+# ? for NeXT with OPENSTEP/Mach 4.2, "make openstep42".
 # ? for NeXTSTEP/486, "make next" (on a PC)
 # ? for NeXTSTEP portable binary (runs on Intel or Motorola), "make nextfat"
 # ? for NeXTSTEP portable binary (Intel, Motorola, HP PA-RISC, or SPARC),
@@ -501,26 +546,27 @@ CKVER= "8.0.211"
 # ? for Olivetti LSX-3020 with X/OS R.2.3, "make xos23" or "make xos23c"
 # + for OpenBSD, "make openbsd" (also see secure targets listed below).
 # ? for OPENSTEP/Mach 4.1, "make nextquadfat" (NeXT, Intel, PA-RISC, SPARC)
-# + for OPENSTEP/Mach 4.2, "make openstep42" (tested on NeXT)
+# ? for OPENSTEP/Mach 4.2, "make openstep42" (tested on NeXT)
 # ? for Perkin-Elmer (Concurrent) 3200 series, "make sys5".
 # ? for Perkin-Elmer (Concurrent) 3200 series with <dirent.h>, "make ccop1"
 # ? for Perkin-Elmer/Concurrent 3200 with Xelos R02, "make ccop1"
 # ? for PFU Compact A Series SX/A TISP V10/E50 (Japan), "make sxae50"
 # ? for Plexus, "make sys3"
-# + for Pyramid 9XXX (e.g. 9845) or MIServer T series, OSx 4.4b thru 5.1,
+# ? for Pyramid 9XXX (e.g. 9845) or MIServer T series, OSx 4.4b thru 5.1,
 #     "ucb make pyramid" or for HDB UUCP, "ucb make pyramid-hdb" or:
-# + for Pyramid MIServer S or ES Series, DataCenter/OSx, "make pyrdcosx"
-# + for Pyramid MIS-S MIPS R3000, DataCenter OSx System V R4, "make pyrdcosx"
-# + for POSIX on anything, "make posix" (but adjustments might be necessary).
+# ? for Pyramid MIServer S or ES Series, DataCenter/OSx, "make pyrdcosx"
+# ? for Pyramid MIS-S MIPS R3000, DataCenter OSx System V R4, "make pyrdcosx"
+# ? for POSIX on anything, "make posix" (but adjustments might be necessary).
+#      NOTE: this target is not very useful - many features are missing.
 # ? for Prime 8000 MIPS, SVR3, "make mips" or "make mipstcpc"
 # - for QNX 2.x (sorry we don't have a version of C-Kermit for QNX 2.x)
 # ? for QNX 4.0 or 4.1, 16-bit, on 286 PC, Watcom C 8.5, "make qnx16_41"
-# + for QNX 4.21 - 4.22A (286+), and 4.23 (386+), or higher, 16-bit,
+# ? for QNX 4.21 - 4.22A (286+), and 4.23 (386+), or higher, 16-bit,
 #     Watcom C 9.5x or higher, "make qnx16"
 # + for QNX 4.21-4.25, 32-bit, 386 or above, Watcom C 10.6, "make qnx32"
 #     NOTE: ("make qnx" == "make qnx32")
 # ? for QNX Neutrino 2+, "make qnx_nto2+" (crosscompiled on QNX4 with Watcom C)
-# + for QNX 6 = Neutrino 2.xx, "make qnx6"
+# ? for QNX 6 = Neutrino 2.xx, "make qnx6"
 # ? for Ridge 32 (ROS3.2), "make ridge32"
 # ? for Samsung MagicStation, "make sys5r4"
 # ? for SCO Xenix 2.2.1 with development system 2.2 on 8086/8 "make sco86"
@@ -534,7 +580,7 @@ CKVER= "8.0.211"
 # ? for SCO Xenix/386 or UNIX/386 with Excelan TCP/IP, "make sco3r2net"
 #     or (to add curses support) "make sco3r2netc" or "sco386netc"
 # + for SCO XENIX 2.3.4, "make sco234" or "make sco234c" to add curses.
-# + for SCO XENIX 2.3.4 with SCO TCP/IP & curses, "make sco234netc".
+# ? for SCO XENIX 2.3.4 with SCO TCP/IP & curses, "make sco234netc".
 # ? for SCO Xenix 2.3.x with Racal-InterLan TCP/IP, "make sco3r2netri"
 #   for other UNIX varieties with Racal Interlan TCP/IP, read sco3r2netri entry
 # ? for SCO Xenix 2.3.x with SCO (Lachman) TCP/IP, "make sco3r2lai"
@@ -546,62 +592,63 @@ CKVER= "8.0.211"
 # ? for SCO UNIX/386 3.2.2 with SCO TCP/IP, "make sco3r22net"
 #     or "make sco3r22netc" (curses)
 # ? for SCO ODT 1.1, "make sco3r22net" or "make sco3r22netc" (curses)
-# + for SCO UNIX/386 3.2 V4.x, no network support, "make sco32v4"
-# +   or "make sco32v4ns" (this one uses no select() or sockets library)
-# + for SCO UNIX/386 3.2 V4.x with TCP/IP, "make sco32v4net"
+# ? for SCO UNIX/386 3.2 V4.x, no network support, "make sco32v4"
+# ?   or "make sco32v4ns" (this one uses no select() or sockets library)
+# ? for SCO UNIX/386 3.2 V4.x with TCP/IP, "make sco32v4net"
 #     (also sco32v4gcc, sco32v4netgcc)
-# + for SCO UNIX/386 3.2 V5.0 - see SCO OpenServer.
-# + for SCO UNIX 3.2v4.x with TCP/IP, <dirent.h> for Extended Acer File
+# ? for SCO UNIX/386 3.2 V5.0 - see SCO OpenServer.
+# ? for SCO UNIX 3.2v4.x with TCP/IP, <dirent.h> for Extended Acer File
 #     System (EAFS), curses, ANSI C compilation, "make sco32v4net"
-# +   or (to use select()-based CONNECT module) "make sco32v4netx".
-# + for SCO UNIX 3.2v4.2, "make sco-odt30" (includes TCP/IP).
-# + for SCO MPX 3.0 - The SCO UNIX binary runs on the corresponding MPX system.
+# ?   or (to use select()-based CONNECT module) "make sco32v4netx".
+# ? for SCO UNIX 3.2v4.2, "make sco-odt30" (includes TCP/IP).
+# ? for SCO MPX 3.0 - The SCO UNIX binary runs on the corresponding MPX system.
 #
 # NOTE: Also see below for other entries that are variations on these.
 # Also be sure to read the comments accompanying each SCO entry.
 # Also see Unixware section.
 #
-# + for SCO ODT 2.0, "make sco32v4net"
-# + for SCO ODT 3.0, "make sco-odt30"
-# + for SCO OpenServer 5.0 (OSR5), "make sco32v500"
-# + for SCO OpenServer 5.0 (OSR5) with networking, "make sco32v500net"
-# + for SCO OpenServer 5.0 (OSR5), gcc, "make sco32v500gcc"
-# + for SCO OpenServer 5.0 (OSR5), gcc, with networking, "make sco32v500netgcc"
-# + for SCO OpenServer 5.0 (OSR5), as above, ELF, "make sco32v500netgccelf"
-# + for SCO OpenServer 5.0.2, use "make sco32v502xxx" entries as above.
-# + for SCO OpenServer 5.0.4, use "make sco32v504xxx" entries as above.
-# + for SCO OpenServer 5.0.5, use "make sco32v505xxx" entries as above.
+# ? for SCO ODT 2.0, "make sco32v4net"
+# ? for SCO ODT 3.0, "make sco-odt30"
+# ? for SCO OpenServer 5.0 (OSR5), "make sco32v500"
+# ? for SCO OpenServer 5.0 (OSR5) with networking, "make sco32v500net"
+# ? for SCO OpenServer 5.0 (OSR5), gcc, "make sco32v500gcc"
+# ? for SCO OpenServer 5.0 (OSR5), gcc, with networking, "make sco32v500netgcc"
+# ? for SCO OpenServer 5.0 (OSR5), as above, ELF, "make sco32v500netgccelf"
+# ? for SCO OpenServer 5.0.2, use "make sco32v502xxx" entries as above.
+# ? for SCO OpenServer 5.0.4, use "make sco32v504xxx" entries as above.
+# ? for SCO OpenServer 5.0.5, use "make sco32v505xxx" entries as above.
 #     Use the sco32v505udkxxx entries if you have the UDK rather than /bin/cc.
-# + for SCO OpenServer 5.0.6, use "make sco32v506xxx" entries as above.
-# + for SCO OpenServer 5.0.6a,use "make sco32v506axxx" entries as above.
-# + for SCO OpenServer 5.0.7, use "make sco32v507", "make sco32v507net"
+# ? for SCO OpenServer 5.0.6, use "make sco32v506xxx" entries as above.
+# ? for SCO OpenServer 5.0.6a,use "make sco32v506axxx" entries as above.
+# ? for SCO OpenServer 5.0.7, use "make sco32v507", "make sco32v507net"
 # ? for SCO (Univel) UnixWare 1.x, "make unixware" or "make unixwarenetc".
 #     If there are problems with this in C-K 7+ see notes at unixware entry.
-# + for SCO UnixWare 2.0.x, "make uw20"
-# + for SCO UnixWare 2.1.0, "make uw21"
-# + for SCO UnixWare 2.1.3, "make uw213"
-# + for SCO UnixWare 7, "make uw7"
-# + for SCO UnixWare 7 with IKSD support, "make uw7iksd" or "make uw7iksdudk"
-# + for SCO UnixWare 7 with OpenSSL, "make uw7ssl"
-# + for SCO (Caldera) Open UNIX 8, "make ou8"
-# + for Sharp Zaurus SL5500 PDA, "make zsl5500".
+# + for SCO OpenServer 6.0.0, "make sco_osr600"
+# ? for SCO UnixWare 2.0.x, "make uw20"
+# ? for SCO UnixWare 2.1.0, "make uw21"
+# ? for SCO UnixWare 2.1.3, "make uw213"
+# + for SCO UnixWare 7, "make uw7" (includes large file support)
+# ? for SCO UnixWare 7 with IKSD support, "make uw7iksd" or "make uw7iksdudk"
+# ? for SCO UnixWare 7 with OpenSSL, "make uw7ssl"
+# ? for SCO (Caldera) Open UNIX 8, "make ou8"
+# ? for Sharp Zaurus SL5500 PDA, "make zsl5500".
 # ? for Sequent with DYNIX/ptx 1.2.1, "make dynixptx12"
 # ? for Sequent with DYNIX/ptx 1.3 or 1.4 with TCP/IP, "make dynixptx13"
 # ? for Sequent with DYNIX/ptx 2.0 or 2.1 with TCP/IP, "make dynixptx20"
 #     or "dynixptx20c"
-# + for Sequent with DYNIX/ptx 2.1.6 on i486, "dynixptx216c"
+# ? for Sequent with DYNIX/ptx 2.1.6 on i486, "dynixptx216c"
 # ? for Sequent with DYNIX/ptx V4.1.3 with TCP/IP, "make dynixptx41c"
-# + for Sequent with DYNIX/ptx V4.4.2 with TCP/IP, "make dynixptx44"
+# ? for Sequent with DYNIX/ptx V4.4.2 with TCP/IP, "make dynixptx44"
 # ? for Sequent Balance 8000 or B8 with DYNIX 3.0.xx, "make dynix3"
 #    or "make dynix3noacu"
 # ? for Sequent Symmetry S81 with DYNIX 3.0.xx, "make dynix3"
 # ? for Sequent DYNIX 3.1.xx, "make dynix31" or "make dynix31c"
-# + for Siemens/Nixdorf SINIX-L Intel V5.41, "make sinix541i"
-# + for Siemens/Nixdorf SINIX-N MIPS V5.42, "make sinix542"
-# + for Siemens/Nixdorf SINIX-P MIPS V5.42 with gcc, "make sinix542g"
-# + for Siemens/Nixdorf SINIX-Z Intel V5.42, "make sinix542i"
-# + for Siemens/Nixdorf Reliant UNIX V5.43, "make sni543"
-# + for Siemens/Nixdorf Reliant UNIX V5.44, "make sni544"
+# ? for Siemens/Nixdorf SINIX-L Intel V5.41, "make sinix541i"
+# ? for Siemens/Nixdorf SINIX-N MIPS V5.42, "make sinix542"
+# ? for Siemens/Nixdorf SINIX-P MIPS V5.42 with gcc, "make sinix542g"
+# ? for Siemens/Nixdorf SINIX-Z Intel V5.42, "make sinix542i"
+# ? for Siemens/Nixdorf Reliant UNIX V5.43, "make sni543"
+# ? for Siemens/Nixdorf Reliant UNIX V5.44, "make sni544"
 # ? for Silicon Graphics Iris System V IRIX 3.2 or earlier, "make iris"
 # ? for Silicon Graphics Sys V R3 with IRIX 3.3 or later, "make sys5r3"
 # ? for Silicon Graphics Iris Indigo with IRIX 4.0 or 5.0, "make irix40" or
@@ -609,32 +656,40 @@ CKVER= "8.0.211"
 # ? for Silicon Graphics Iris Indigo or Elan with IRIX 4.0.x with microcode
 #     optimization and -O4, "make irix40u" or "irix40uc" (and read notes
 #     accompanying these entries).
-# + for Silicon Graphics IRIX 5.1, "make irix51" or "irix51x" (no optimize)
-# + for Silicon Graphics IRIX 5.2, "make irix52"
-# + for Silicon Graphics IRIX 5.3, "make irix53" or "irix53x" (no optimize)
-# + for Silicon Graphics IRIX 6.0, "make irix60".
-# + for Silicon Graphics IRIX 6.2, "make irix62".
-# + for Silicon Graphics IRIX 6.3, "make irix63".
-# + for Silicon Graphics IRIX 6.4, "make irix64" or "make irix64gcc".
+# ? for Silicon Graphics IRIX 5.1, "make irix51" or "irix51x" (no optimize)
+# ? for Silicon Graphics IRIX 5.2, "make irix52"
+# ? for Silicon Graphics IRIX 5.3, "make irix53" or "irix53x" (no optimize)
+# ? for Silicon Graphics IRIX 6.0, "make irix60".
+# ? for Silicon Graphics IRIX 6.2, "make irix62".
+# ? for Silicon Graphics IRIX 6.3, "make irix63".
+# ? for Silicon Graphics IRIX 6.4, "make irix64" or "make irix64gcc".
+# + for Silicon Graphics (SGI) IRIX 6.5, "make irix65"
+# +   or "make irix65mips2" to force MIPS2, or "make irix65gcc" for GCC.
 # + for Silicon Graphics (SGI) IRIX 6.5, "make irix65" or "make irix65mips2"
+# ? for SGI IRIX 6.5 with SSL/TLS, SRP, and ZLIB "make irix65+ssl+srp+zlib"
 # ? for Solaris 2.0-2.3 on SPARC or Intel, SunPro CC, "make solaris2x",
 # ?   or to add SunLink X.25 8.0x support, "make solaris2x25".
-# + for Solaris 2.4 built with gcc, "make solaris24g".
-# + for Solaris 2.0-2.3 on SPARC or Intel, GNU CC, "make solaris2xg".
-# + for Solaris 2.4 with X.25, "make solaris24x25".
-# + for Solaris 2.5 on SPARC or Intel, SunPro CC, "make solaris25".
-# +   or to add SunLink X.25 8.0x support, "make solaris25x25".
-# + for Solaris 2.5 on SPARC or Intel, GNU CC, "make solaris25g".
-# + for Solaris 2.6 on SPARC or Intel, "make solaris26".
-# + for Solaris 7 on SPARC or Intel, SunPro CC, "make solaris7".
-# + for Solaris 7 on SPARC or Intel, GNU CC, "make solaris7g".
-# + for Solaris 8 on SPARC or Intel, SunPro CC, "make solaris8".
-# + for Solaris 8 on SPARC or Intel, GNU CC, "make solaris8g".
+# ? for Solaris 2.4 built with gcc, "make solaris24g".
+# ? for Solaris 2.0-2.3 on SPARC or Intel, GNU CC, "make solaris2xg".
+# ? for Solaris 2.4 with X.25, "make solaris24x25".
+# ? for Solaris 2.5 on SPARC or Intel, SunPro CC, "make solaris25".
+# ?   or to add SunLink X.25 8.0x support, "make solaris25x25".
+# ? for Solaris 2.5 on SPARC or Intel, GNU CC, "make solaris25g".
+# ? for Solaris 2.6 on SPARC or Intel, "make solaris26".
+# ? for Solaris 7 on SPARC or Intel, SunPro CC, "make solaris7".
+# ? for Solaris 7 on SPARC or Intel, GNU CC, "make solaris7g".
+# ? for Solaris 8 on SPARC or Intel, SunPro CC, "make solaris8".
+# ? for Solaris 8 on SPARC or Intel, GNU CC, "make solaris8g".
 # + for Solaris 9 on SPARC (or Intel?), 32-bit, SunPro CC, "make solaris9".
 # + for Solaris 9 on SPARC (or Intel?), 32-bit, GNU CC, "make solaris9g".
+# + for Solaris 9 on SPARC 100% 64-bit, SunPro CC, "make solaris9_64".
 # + for Solaris 9 on SPARC (or Intel?), 64-bit, GNU CC, "make solaris9g64".
-# + for Solbourne 4/500 with OS/MP 4 "make sunos4"
-# + for Solbourne 4/500 with OS/MP 4.1 "make sunos41" or "make sunos41c"
+# + for Solaris 10 on SPARC (or Intel?), 32-bit, SunPro CC, "make solaris10".
+# + for Solaris 10 on SPARC 64-bit, SunPro CC, "make solaris10_64".
+# + for Solaris 10 on SPARC (or Intel?), 32-bit, GNU CC, "make solaris10g".
+# ? for Solaris 10 on SPARC (or Intel?), 64-bit, GNU CC, "make solaris10g64".
+# ? for Solbourne 4/500 with OS/MP 4 "make sunos4"
+# ? for Solbourne 4/500 with OS/MP 4.1 "make sunos41" or "make sunos41c"
 # ? for SONY NEWS with NEWS-OS 4.0.1C, "make sonynews"
 # ? for SONY NEWS with NEWS-OS 4.1.2C, "make sonynews"
 # ? for Sperry/UNISYS 5000/20, UTS V 5.2 3R1, "make sys5"
@@ -644,17 +699,17 @@ CKVER= "8.0.211"
 #     For UNISYS SVR3 it might be necessary to "make sys5r3 KFLAGS=-UDYNAMIC"
 # ? for Stardent 1520, "make sys5r3"
 # ? for Stratus FTX 2.x, try "make ftx" or else "make sys5r4" or "sys5r4sx"
-# + for Stratus FTX 3.x, PA-RISC 1.0 or 2.0, "make ftx" or "make ftxtcp"
+# ? for Stratus FTX 3.x, PA-RISC 1.0 or 2.0, "make ftx" or "make ftxtcp"
 # ? for Sun with Sun UNIX 3.5 and gcc, "make sunos3gcc"
 # ? for Sun with pre-4.0 SunOS versions, "make bsd" (or appropriate variant)
 # ? for Sun with SunOS 4.0, BSD environment, "make sunos4"
 # ? for Sun with SunOS 4.0, BSD, with SunLink X.25, make sunos4x25
-# + for Sun with SunOS 4.1 or 4.1.1, BSD environment, "make sunos41"
+# ? for Sun with SunOS 4.1 or 4.1.1, BSD environment, "make sunos41"
 #     or "make sunos41c" (curses) or "make sunos41gcc" (compile with gcc)
-# + for Sun with SunOS 4.1.x, BSD, with SunLink X.25 7.00 or earlier,
+# ? for Sun with SunOS 4.1.x, BSD, with SunLink X.25 7.00 or earlier,
 #     "make sunos41x25" or "make sunos41x25c" (curses)
-# + for Sun with SunOS 4.1, 4.1.1, AT&T Sys V R3 environment, "make sunos41s5"
-# + for Sun with SunOS 4.1.2, "make sunos41" or any of its variations.
+# ? for Sun with SunOS 4.1, 4.1.1, AT&T Sys V R3 environment, "make sunos41s5"
+# ? for Sun with SunOS 4.1.2, "make sunos41" or any of its variations.
 #     NOTE:  All SunOS 4.x systems -- Shared libraries are used by default.
 #       If this causes problems, add -Bstatic to CFLAGS.
 #     NOTE2: When building C-Kermit under SunOS for the BSD universe,
@@ -672,11 +727,12 @@ CKVER= "8.0.211"
 #     or (for models without hardware flow control), "make uteknohwfc"
 # ? for Tektronix XD88 series with UTekV OS, "make utekvr3"
 # ? for Tri Star Flash Cache with Esix SVR3.2, "make sys5r3"
-# + for Tru-64 UNIX 4.0E, "make tru64-40e"
-# + for Tru-64 UNIX 4.0F, "make tru64-40f"
-# + for Tru-64 UNIX 4.0G, "make tru64-40g"
-# + for Tru-64 UNIX 5.0A, "make tru64-50a"
-# + for Tru-64 UNIX 5.1A, "make tru64-51a"
+# + for Tru64 UNIX 4.0E, "make tru64-40e"
+# + for Tru64 UNIX 4.0F, "make tru64-40f"
+# + for Tru64 UNIX 4.0G, "make tru64-40g"
+# + for Tru64 UNIX 5.0A, "make tru64-50a"
+# + for Tru64 UNIX 5.1A, "make tru64-51a"
+# + for Tru64 UNIX 5.1B, "make tru64-51b"
 # ? for Unistar, "make sys5"
 # ? for Unisys S/4040 68040 CTIX SVR3.2 6.4.1, "make ctix" or "make sys5r3"
 # ? for Unisys U5000 UNIX SVR3 6.x, "make sys5r3" or "make sys5r3c"
@@ -690,7 +746,8 @@ CKVER= "8.0.211"
 #
 # The result should be a runnable program called "wermit" in the current
 # directory.  After satisfactory testing, you can rename wermit to "kermit"
-# and put it where users can find it.
+# and put it in some directory that's in everybody's PATH, such as
+# /usr/local or /opt/local.
 #
 # To remove intermediate and object files, "make clean".
 # If your C compiler produces files with an extension other than "o",
@@ -721,19 +778,26 @@ CKVER= "8.0.211"
 # for specific details regarding supported versions.
 #
 # NOTE: OpenSSL 0.9.6 and earlier are not compatible with 0.9.7 and later.
-# C-Kermit code is designed for 0.9.6.  To build with 0.9.7 you must add
-# -DOPENSSL_097 to avoid missing symbols in the DES library and to use the
-# entry points that were renamed to avoid conflict with Kerberos 4.
-#
+# C-Kermit code was originally designed for 0.9.6.  To build with 0.9.7 you
+# must add -DOPENSSL_097 to avoid missing symbols in the DES library and to
+# use the entry points that were renamed to avoid conflict with Kerberos 4.
+# If you have OpenSSL 0.9.8, add -DOPENSSL_098, which is a synonym for
+# -DOPENSSL_097.  If you have 1.0.0 or later, add -DOPENSSL_100, which is
+# another synonym.
+
 # In OpenSSL builds add -ldl if you get unresolved references for
 # dlopen, dlclose, dlsym, and/or dlerror.
 #
-# The following symbols are used to specify library and header file locations
-# Redefine them to the values used on your system by:
-# . editing this file
-# . defining the values on the command line
-# . defining the values in the environment and use the -e option
+# In order to build a secure version of Kermit, you need to know the location
+# of the header (include) files and libraries for the desired form of
+# security.  Unless you specify a location, this makefile looks in /usr/local
+# and if the required files are not found, the build fails.
 #
+# If the secure headers and libraries are not on your computer, you have
+# to download and install them, for example from http://www.openssl.org .
+#
+# The following symbols are used to specify library and header file locations:
+# 
 prefix  = /usr/local
 srproot = $(prefix)
 sslroot = $(prefix)
@@ -747,11 +811,19 @@ SRPLIB=-L$(srproot)/lib
 SRPINC=-I$(srproot)/include
 SSLLIB=-L$(sslroot)/ssl/lib
 SSLINC=-I$(sslroot)/ssl/include
+
+# To override these assignments; for example, if your OpenSSL files are
+# not in /usr/local/ssl, invoke the desired target like this:
+# 
+#  make solaris9+openssl "SSLINC=-I/opt/openssl-0.9.8k/include" \
+#   "SSLLIB=-L/opt/openssl-0.9.8k/lib"
+#
+# (don't set the variables and then do "make -e" because that breaks 
+# chaining of makefile targets.)
+#
+# Here are some up-to-date secure targets as of Sep 2009: 
 #
-# aix41+krb5+krb4:                    IBM AIX 4.1 with Kerberos IV and V
-# aix43gcc+krb5+krb4:                 IBM AIX 4.3 built with gcc, ditto
-# aix43gcc+krb5+krb4+openssl:         Ditto, plus OpenSSL (SSL/TLS)
-# aix43gcc+openssl:                   IBM AIX 4.3 with OpenSSL
+# aix+openssl:                        IBM AIX 4.2 or later with OpenSSL
 # freebsd44+srp+openssl               FreeBSD 4.4 with SRP and OpenSSL
 # freebsd50+openssl                   FreeBSD 5.0 with OpenSSL
 # hpux1100o+openssl:                  HP-UX 11.xx with OpenSSL
@@ -759,7 +831,13 @@ SSLINC=-I$(sslroot)/ssl/include
 # hpux1100gcc+openssl:                HP-UX 11.xx with OpenSSL (build with gcc)
 # irix6x+krb5:                        IRIX 6.x with Kerberos V
 # irix65+krb5:                        etc etc...
-# linux+krb5:
+# solaris9+openssl                    Solaris 9,10, or 11 with Openssl (Sun cc)
+# solaris9g+openssl                   Solaris 9,10, or 11 with Openssl (gcc)
+# linux+ssl                           OpenSSL only
+# linux+krb5+ssl                      Linux with Kerberos 5 and OpenSSL
+# linux+krb5:                         Kerberos 5 only
+# 
+# The following secure Linux targets have not been updated or tested recently.
 # linux+krb5+krb4:
 # linux+srp:
 # linux+srp+pam:
@@ -784,9 +862,15 @@ SSLINC=-I$(sslroot)/ssl/include
 # linux+krb5+krb4+srp+openssl+zlib+pam:
 # linux+krb5+krb4+openssl+shadow+pam:
 # linux+krb5+openssl+zlib+shadow+pam:
-# openbsd30+ssl (includes OpenSSL):
-# redhat71, redhat72, redhat73, redhat80, redhat9
-#  (Krb5, OpenSSL, Showdow, PAM, Zlib)
+# 
+# The following have not been tested recently either and might
+# need adjustment.
+#
+# macosx+krb5+ssl:     Mac OS X 10.3.9 or later + OpenSSL and Kerberos 5
+# macosx103+secure:    This one is probably redundant
+# netbsd+openssl:      NetBSD with OpenSSL
+# openbsd30+ssl:       OpenBSD 3.0 with OpenSSL
+# redhat71,redhat72,redhat73,redhat80,redhat9 (Krb5,OpenSSL,Showdow,PAM,Zlib)
 # sco32v500net+ssl:
 # sco32v505net+ssl:
 # solaris2x+krb4:
@@ -807,59 +891,8 @@ SSLINC=-I$(sslroot)/ssl/include
 # sunos41gcc+krb4+openssl+zlib:       ditto, plus ZLIB compression
 # sunos41gcc+krb4+srp+openssl+zlib:   ditto, plus SRP
 # sunos41gcc+srp+openssl+zlib:
-# uw7ssl
-#
-##############################################################################
-#
-# NOTES FOR V7 AND 2.X BSD (BASED ON VERSION 4E OF C-KERMIT, 1987):
-#
-# For Unix Version 7, several variables must be defined to the values
-# associated with your system.  BOOTNAME=/edition7 is the kernel image on
-# okstate's Perkin-Elmer 3230.  Others will probably be /unix.  PROCNAME=proc
-# is the name of the structure assigned to each process on okstate's system.
-# This may be "_proc" or some other variation.  See <sys/proc.h> for more
-# info on your systems name conventions.  NPROCNAME=nproc is the name of a
-# kernel variable that tells how many "proc" structures there are.  Again
-# this may be different on your system, but nproc will probably be somewhere.
-# The variable NPTYPE is the type of the nproc variable -- int, short, etc.
-# which can probably be gleaned from <sys/param.h>.  The definition of DIRECT
-# is a little more complicated.  If nlist() returns, for "proc" only, the
-# address of the array, then you should define DIRECT as it is below.  If
-# however, nlist() returns the address of a pointer to the array, then you
-# should give DIRECT a null definition (DIRECT= ).  The extern declaration in
-# <sys/proc.h> should clarify this for you.  If it is "extern struct proc
-# *proc", then you should NOT define DIRECT.  If it is "extern struct proc
-# proc[]", then you should probably define DIRECT as it is below.  See
-# ckuv7.hlp for further information.
-#
-# For 2.9 BSD, the makefile may use pcc rather than cc for compiles; that's
-# what the CC and CC2 definitions are for (the current version of the
-# makefile uses cc for both; this was tested in version 4E of C-Kermit and
-# worked OK on the DEC Pro 380, but all bets are off for version 5A).  2.9
-# support basically follows the 4.1 path.  Some 2.9 systems use "dir.h" for
-# the directory header file, others will need to change this to "ndir.h".
-#
-# The v7 and 2.9bsd versions assume I&D space on a PDP-11.  When building
-# C-Kermit for v7 on a PDP-11, you should probably add the -i option to the
-# link flags.  Without I&D space, overlays will be necessary (if available),
-# or code segment mapping (a`la Pro/Venix) if that's available.
-#
-# C-Kermit 5A (and 6.0?) can be built for 2.10 and 2.11BSD, using overlays,
-# but a separate makefile is used because this one is too big.
-#
-##############################################################################
-#
-# V7-specific variables.
-# These are set up for Perkin-Elmer 3230 V7 Unix:
-#
-PROC=proc
-DIRECT=
-NPROC=nproc
-NPTYPE=int
-BOOTFILE=/edition7
-#
-# ( For old Tandy TRS-80 Model 16A or 6000 V7-based Xenix, use PROC=_proc,
-#   DIRECT=-DDIRECT, NPROC=_Nproc, NPTYPE=short, BOOTFILE=/xenix )
+# tru64-51b-openssl:                  Tru64 (Digital) Unix 5.1B with OpenSSL
+# uw7ssl                              Unixware 7 with SSL
 #
 ###########################################################################
 #
@@ -877,6 +910,20 @@ MAKE= make
 SHELL=/bin/sh
 
 ###########################################################################
+# (Ancient) UNIX V7-specific variables.
+# These are set up for Perkin-Elmer 3230 V7 Unix:
+#
+PROC=proc
+DIRECT=
+NPROC=nproc
+NPTYPE=int
+BOOTFILE=/edition7
+#
+# ( For old Tandy TRS-80 Model 16A or 6000 V7-based Xenix, use PROC=_proc,
+#   DIRECT=-DDIRECT, NPROC=_Nproc, NPTYPE=short, BOOTFILE=/xenix )
+#
+
+###########################################################################
 # SAMPLE INSTALLATION SCRIPT
 #
 # Modify to suit your own computer's file organization and permissions.  If
@@ -893,7 +940,7 @@ SHELL=/bin/sh
 #
 # You can also build and install in one step, e.g.:
 #
-#   make solaris8 install
+#   make linux install
 #
 # If you use the 'install' target to install C-Kermit, it creates an
 # UNINSTALL script that can be used to uninstall it.
@@ -930,6 +977,20 @@ ckucns.$(EXT) ckcmdb.$(EXT) ckuath.$(EXT) ckctel.$(EXT) ckclib.$(EXT) \
 ckcuni.$(EXT) ck_crp.$(EXT) ck_ssl.$(EXT) ckupty.$(EXT) ckcftp.$(EXT) \
 ckcpro.c wart
 
+show:
+       @echo prefix=$(prefix)
+       @echo srproot=$(srproot)
+       @echo sslroot=$(sslroot)
+       @echo manroot=$(manroot)
+       @echo K4LIB=$(K4LIB)
+       @echo K4INC=$(K4INC)
+       @echo K5LIB=$(K5LIB)
+       @echo K5INC=$(K5INC)
+       @echo SRPLIB=$(SRPLIB)
+       @echo SRPINC=$(SRPINC)
+       @echo SSLLIB=$(SSLLIB)
+       @echo SSLINC=$(SSLINC)
+       
 # Install C-Kermit after building -- IMPORTANT: Read the instructions above
 # (SAMPLE INSTALLATION SCRIPT).  For SSL/TLS versions, ca_certs.pem file
 # should be installed in the appropriate place for your OpenSSL library, e.g.:
@@ -998,7 +1059,7 @@ install:
        echo "RmF $(DESTDIR)$(BINDIR)/kermit-sshsub" >&3;\
        echo "RmF $(DESTDIR)$(BINDIR)/kermit" >&3;\
        if test -f ckermit.ini; then\
-               echo "#!$(DESTDIR)$(BINDIR)/kermit" >\
+               echo "#!$(BINDIR)/kermit" >\
                        $(DESTDIR)$(BINDIR)/_tmp.ini;\
                cat ckermit.ini >> $(DESTDIR)$(BINDIR)/_tmp.ini;\
                mv $(DESTDIR)$(BINDIR)/_tmp.ini\
@@ -1019,20 +1080,19 @@ install:
        echo " for details.";\
        echo;\
        echo MANDIR=$(MANDIR);\
-       if test -n "$(MANDIR)"; then\
-               if test -d $(MANDIR); then\
-                       echo  "$(MANDIR) exists...";\
+       if test -n "$(DESTDIR)$(MANDIR)"; then\
+               if test -d $(DESTDIR)$(MANDIR); then\
+                       echo  "$(DESTDIR)$(MANDIR) exists...";\
                else\
                        echo "Creating $(MANDIR)...";\
                        mkdir $(MANDIR) || exit 1;\
                        chmod 755 $(MANDIR) || exit 1;\
                fi;\
-               echo "Installing man page...";\
-               rm -f $(MANDIR)/kermit.$(MANEXT);\
-               cp    ckuker.nr $(MANDIR)/kermit.$(MANEXT) || exit 1;\
-               chmod 644       $(MANDIR)/kermit.$(MANEXT) || exit 1;\
+               rm -f $(DESTDIR)$(MANDIR)/kermit.$(MANEXT);\
+               cp ckuker.nr $(DESTDIR)$(MANDIR)/kermit.$(MANEXT) || exit 1;\
+               chmod 644 $(DESTDIR)$(MANDIR)/kermit.$(MANEXT) || exit 1;\
                echo 'set flag=f\nPrC Removing man pages' >&3;\
-               echo "RmF $(MANDIR)/kermit.$(MANEXT)" >&3;\
+               echo "RmF $(DESTDIR)$(MANDIR)/kermit.$(MANEXT)" >&3;\
                echo 'EfM' >&3;\
                echo;\
        else\
@@ -1163,15 +1223,13 @@ uninstall:
 
 makewhat:
        @echo 'make what?  You must tell which platform to make C-Kermit for.'
-       @echo Examples: make linux, make hpux1100, make aix43, make solaris8.
+       @echo Examples: make linux, make aix, make solaris10, make hpux1100.
        @echo Please read the comments at the beginning of the makefile.
 
 ###########################################################################
 #
 # Dependencies Section:
 
-# Normal version
-
 wermit:        ckcmai.$(EXT) ckclib.$(EXT) ckucmd.$(EXT) ckuusr.$(EXT) ckuus2.$(EXT) \
                ckuus3.$(EXT) ckuus4.$(EXT) ckuus5.$(EXT) ckuus6.$(EXT) \
                ckuus7.$(EXT) ckuusx.$(EXT) ckuusy.$(EXT) ckcpro.$(EXT) \
@@ -1189,7 +1247,7 @@ wermit:   ckcmai.$(EXT) ckclib.$(EXT) ckucmd.$(EXT) ckuusr.$(EXT) ckuus2.$(EXT) \
                ckusig.$(EXT) ckcuni.$(EXT) ckupty.$(EXT) ckcftp.$(EXT) \
                $(LIBS)
 
-# Version with CONNECT module that uses select() instead of fork()
+# Preferred configuration with select()-based CONNECT
 
 xermit:        ckcmai.$(EXT) ckclib.$(EXT) ckucmd.$(EXT) ckuusr.$(EXT) ckuus2.$(EXT) \
                ckuus3.$(EXT) ckuus4.$(EXT) ckuus5.$(EXT) ckuus6.$(EXT) \
@@ -1406,6 +1464,9 @@ ckcnet.$(EXT): ckcnet.c ckcdeb.h ckcker.h ckcnet.h ckcsym.h ckcsig.h ckctel.h \
 
 ckctel.$(EXT): ckcsym.h ckcdeb.h ckcker.h ckcnet.h ckctel.h ckclib.h
 
+# ck_off_t: ck_off_t.$(EXT)
+#      $(CC) -o ck_off_t ck_off_t.$(EXT)
+
 wart: ckwart.$(EXT)
        $(CC) $(LNKFLAGS) -o wart ckwart.$(EXT) $(LIBS)
 
@@ -1650,7 +1711,7 @@ freebsd3c:
 
 #FreeBSD 4.0 with ncurses and uu_lock().  Note - there is no curses in 4.0.
 #ncurses 5.0 is broken requiring us to work around with setbuf().
-freebsd4:
+freebsd40:
        @echo 'Making C-Kermit $(CKVER) for FreeBSD 4.x with ncurses...'
        $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
        "CFLAGS= -DBSD44 -DCK_NCURSES -DTCPSOCKET -DNOCOTFMC -DFNFLOAT \
@@ -1658,150 +1719,21 @@ freebsd4:
        -DNONOSETBUF -DUSE_UU_LOCK $(KFLAGS) -O -pipe" \
        "LIBS= -lncurses -lcrypt -lutil -lm $(LIBS)"
 
-#FreeBSD 4.1, as above but without the NONOSETBUF hack and with CK_NEWTERM.
-#This works with ncurses 5.1.
-freebsd41:
-       @echo 'Making C-Kermit $(CKVER) for FreeBSD 4.1 with ncurses...'
-       $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
-       "CFLAGS= -DBSD44 -DCK_NCURSES -DCK_NEWTERM -DTCPSOCKET -DNOCOTFMC \
-       -DFREEBSD4 -DFREEBSD41 -DUSE_UU_LOCK -DFNFLOAT \
-       -funsigned-char -DTPUTSARGTYPE=int -DUSE_STRERROR $(KFLAGS) -O -pipe" \
-       "LIBS= -lncurses -lcrypt -lutil -lm $(LIBS)"
-
-#Default FreeBSD make for C-Kermit 8.0...
-freebsd:
-       $(MAKE) "MAKE=$(MAKE)" CC=$(CC) CC2=$(CC2) \
-       KTARGET=$${KTARGET-$(@)} freebsd45
-
-#FreeBSD 4.2, like 4.1.
-freebsd42:
-       @echo 'Making C-Kermit $(CKVER) for FreeBSD 4.2...'
+#FreeBSD 4.1 and above
+#Like FreeBSD 4.0 but without the NONOSETBUF hack and with CK_NEWTERM.
+#OK 2009/11/17 FreeBSD 7.2-RELEASE
+freebsd freebsd41 freebsd72:
+       @echo 'Making C-Kermit $(CKVER) for FreeBSD 4.1 or later...'
        $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
        "CFLAGS= -DBSD44 -DCK_NCURSES -DCK_NEWTERM -DTCPSOCKET -DNOCOTFMC \
-       -DFREEBSD4 -DFREEBSD41 -DFREEBSD42 -DUSE_UU_LOCK -DFNFLOAT \
+       -DFREEBSD4 -DUSE_UU_LOCK -DFNFLOAT \
+       -DHERALD=\"\\\" `uname` `uname -r`\\\"\" \
        -funsigned-char -DTPUTSARGTYPE=int -DUSE_STRERROR $(KFLAGS) -O -pipe" \
        "LIBS= -lncurses -lcrypt -lutil -lm $(LIBS)"
 
-#FreeBSD 4.3, like 4.2.
-freebsd43:
-       @echo 'Making C-Kermit $(CKVER) for FreeBSD 4.3...'
-       $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
-       "CFLAGS= -DBSD44 -DCK_NCURSES -DCK_NEWTERM -DTCPSOCKET -DNOCOTFMC \
-       -DFREEBSD4 -DFREEBSD41 -DFREEBSD42 -DFREEBSD43 -DUSE_UU_LOCK \
-       -DFNFLOAT -funsigned-char -DTPUTSARGTYPE=int -DUSE_STRERROR $(KFLAGS) \
-       -O -pipe" "LIBS= -lncurses -lcrypt -lutil -lm $(LIBS)"
-
-#FreeBSD 4.4, like 4.3.
-freebsd44:
-       @echo 'Making C-Kermit $(CKVER) for FreeBSD 4.4...'
-       $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
-       "CFLAGS= -DBSD44 -DCK_NCURSES -DCK_NEWTERM -DTCPSOCKET -DNOCOTFMC \
-       -DFREEBSD4 -DFREEBSD41 -DFREEBSD42 -DFREEBSD43 -DFREEBSD44 \
-       -DUSE_UU_LOCK -DFNFLOAT -funsigned-char -DTPUTSARGTYPE=int \
-       -DUSE_STRERROR $(KFLAGS) -O -pipe" \
-       "LIBS= -lncurses -lcrypt -lutil -lm $(LIBS)"
-
-#FreeBSD 4.5, like 4.3 and 4.4.
-freebsd45:
-       @echo 'Making C-Kermit $(CKVER) for FreeBSD 4.5...'
-       $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
-       "CFLAGS= -DBSD44 -DCK_NCURSES -DCK_NEWTERM -DTCPSOCKET -DNOCOTFMC \
-       -DFREEBSD4 -DUSE_UU_LOCK -DFNFLOAT -funsigned-char -DTPUTSARGTYPE=int \
-       -DFREEBSD41 -DFREEBSD42 -DFREEBSD43 -DFREEBSD44 -DFREEBSD45 \
-       -DUSE_STRERROR $(KFLAGS) -O -pipe" \
-       "LIBS= -lncurses -lcrypt -lutil -lm $(LIBS)"
-
-#FreeBSD 4.6, like 4.5
-freebsd46:
-       @echo 'Making C-Kermit $(CKVER) for FreeBSD 4.6...'
-       $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
-       "CFLAGS= -DBSD44 -DCK_NCURSES -DCK_NEWTERM -DTCPSOCKET -DNOCOTFMC \
-       -DFREEBSD4 -DUSE_UU_LOCK -DFNFLOAT -funsigned-char -DTPUTSARGTYPE=int \
-       -DFREEBSD41 -DFREEBSD42 -DFREEBSD43 -DFREEBSD44 -DFREEBSD45 \
-       -DFREEBSD46 -DUSE_STRERROR $(KFLAGS) -O -pipe" \
-       "LIBS= -lncurses -lcrypt -lutil -lm $(LIBS)"
-
-#FreeBSD 4.7, like 4.6
-freebsd47:
-       @echo 'Making C-Kermit $(CKVER) for FreeBSD 4.7...'
-       $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
-       "CFLAGS= -DBSD44 -DCK_NCURSES -DCK_NEWTERM -DTCPSOCKET -DNOCOTFMC \
-       -DFREEBSD4 -DUSE_UU_LOCK -DFNFLOAT -funsigned-char -DTPUTSARGTYPE=int \
-       -DFREEBSD41 -DFREEBSD42 -DFREEBSD43 -DFREEBSD44 -DFREEBSD45 \
-       -DFREEBSD46 -DFREEBSD47 -DUSE_STRERROR $(KFLAGS) -O -pipe" \
-       "LIBS= -lncurses -lcrypt -lutil -lm $(LIBS)"
-
-#FreeBSD 4.8, like 4.7
-freebsd48:
-       @echo 'Making C-Kermit $(CKVER) for FreeBSD 4.7...'
-       $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
-       "CFLAGS= -DBSD44 -DCK_NCURSES -DCK_NEWTERM -DTCPSOCKET -DNOCOTFMC \
-       -DFREEBSD4 -DUSE_UU_LOCK -DFNFLOAT -funsigned-char -DTPUTSARGTYPE=int \
-       -DFREEBSD41 -DFREEBSD42 -DFREEBSD43 -DFREEBSD44 -DFREEBSD45 \
-       -DFREEBSD46 -DFREEBSD47 -DFREEBSD48 \
-       -DUSE_STRERROR $(KFLAGS) -O -pipe" \
-       "LIBS= -lncurses -lcrypt -lutil -lm $(LIBS)"
-
-#FreeBSD 4.9
-freebsd49:
-       @echo 'Making C-Kermit $(CKVER) for FreeBSD 4.7...'
-       $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
-       "CFLAGS= -DBSD44 -DCK_NCURSES -DCK_NEWTERM -DTCPSOCKET -DNOCOTFMC \
-       -DFREEBSD4 -DUSE_UU_LOCK -DFNFLOAT -funsigned-char -DTPUTSARGTYPE=int \
-       -DFREEBSD41 -DFREEBSD42 -DFREEBSD43 -DFREEBSD44 -DFREEBSD45 \
-       -DFREEBSD46 -DFREEBSD47 -DFREEBSD48 -DFREEBSD49 \
-       -DUSE_STRERROR $(KFLAGS) -O -pipe" \
-       "LIBS= -lncurses -lcrypt -lutil -lm $(LIBS)"
-
-#FreeBSD 5.0, like 4.6
-freebsd50:
-       @echo 'Making C-Kermit $(CKVER) for FreeBSD 5.0 with ncurses...'
-       $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
-       "CFLAGS= -DBSD44 -DCK_NCURSES -DCK_NEWTERM -DTCPSOCKET -DNOCOTFMC \
-       -DFREEBSD4 -DUSE_UU_LOCK -DFNFLOAT -funsigned-char -DTPUTSARGTYPE=int \
-       -DFREEBSD41 -DFREEBSD42 -DFREEBSD43 -DFREEBSD44 -DFREEBSD45 \
-       -DFREEBSD46 -DFREEBSD50 -DUSE_STRERROR $(KFLAGS) -O -pipe" \
-       "LIBS= -lncurses -lcrypt -lutil -lm $(LIBS)"
-
-#FreeBSD 5.1
-freebsd51:
-       @echo 'Making C-Kermit $(CKVER) for FreeBSD 5.0 with ncurses...'
-       $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
-       "CFLAGS= -DBSD44 -DCK_NCURSES -DCK_NEWTERM -DTCPSOCKET -DNOCOTFMC \
-       -DFREEBSD4 -DUSE_UU_LOCK -DFNFLOAT -funsigned-char -DTPUTSARGTYPE=int \
-       -DFREEBSD41 -DFREEBSD42 -DFREEBSD43 -DFREEBSD44 -DFREEBSD45 \
-       -DFREEBSD46 -DFREEBSD50 -DFREEBSD51 \
-       -DUSE_STRERROR $(KFLAGS) -O -pipe" \
-       "LIBS= -lncurses -lcrypt -lutil -lm $(LIBS)"
-
-#Secure builds for FreeBSD...  gcc required.
-
-freebsd44+srp+openssl:
-       @echo 'Making C-Kermit $(CKVER) for FreeBSD 4.3 with SRP,SSL...'
-       $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} "CC = gcc" "CC2 = gcc" \
-       "CFLAGS= -DBSD44 -DCK_NCURSES -DCK_NEWTERM -DTCPSOCKET -DNOCOTFMC \
-       -DFREEBSD4 -DFREEBSD41 -DFREEBSD42 -DFREEBSD43 -DFREEBSD44 \
-       -DCK_AUTHENTICATION -DCK_SRP \
-       -DCK_ENCRYPTION -DCK_CAST -DCK_DES -DLIBDES -DCK_SSL \
-       -DCK_CURSES -DTCPSOCKET  \
-       $(SRPINC) $(SSLINC) $(KFLAGS)" "LNKFLAGS = $(LNKFLAGS)" \
-       "LIBS = $(SRPLIB) $(SSLLIB) \
-       -lncurses -ltermcap -lsrp -lssl -lkrypto -lcrypto \
-       -lcrypt "
-
-# The following fragmentary FreeBSD+SLL target was suggested, but it's not
-# clear which version of FreeBSD it applies to.
-#
-# ALL_TARGET=  xermit
-# MAKE_ARGS=   KTARGET=freebsd \
-#              CFLAGS="${CFLAGS} -DBSD44 -DCK_NCURSES -DCK_NEWTERM \
-#              -DTCPSOCKET -DNOCOTFMC -DFREEBSD4 -DUSE_UU_LOCK -DFNFLOAT \
-#              -funsigned-char -DTPUTSARGTYPE=int -DUSE_STRERROR -DCKHTTP \
-#              -DCK_SSL -DCK_AUTHENTICATION -DCK_ENCRYPTION -DCK_DES" \
-#              LIBS="-lssl -lcrypto -ldes -lncurses -lcrypt -lutil -lm"
-
-#FreeBSD 5.0 with OpenSSL 0.9.7.
-freebsd50+openssl:
+#FreeBSD 5.0 or later with OpenSSL 0.9.7 or later.
+#OK 2009/11/17 FreeBSD 7.2-RELEASE
+freebsd+ssl freebsd+openssl freebsd50+openssl:
        @echo 'Making C-Kermit $(CKVER) for FreeBSD 5.0, ncurses, openssl'
        $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
        "CFLAGS= -DBSD44 -DCK_NCURSES -DCK_NEWTERM -DTCPSOCKET -DNOCOTFMC \
@@ -1811,43 +1743,137 @@ freebsd50+openssl:
        -DFREEBSD46 -DFREEBSD50 -DUSE_STRERROR $(KFLAGS) -O -pipe" \
        "LIBS= -lncurses -lcrypt -lssl -lcrypto -lutil -lm $(SSLLIB) $(LIBS)"
 
-#NetBSD - all versions - with curses, not ncurses.
-#Some builds seem to need KFLAGS=-DTPUTSFNTYPE=int, others don't.
-#(Only to get rid of a warning -- the binaries are identical.)
-netbsd:
+#NetBSD 1.4.1 or later with vanity banner automated with uname
+#and automatic inclusion of large file support if it is available.
+#This target tested successfully on NetBSD 1.4.1, 1.5.2, and 2.0.3 (Jan 2006).
+#Fails on NetBSD 2.0 on Sun/3 mc68030 with gcc 3.3.3 unless optimization is
+#disabled on ckcfn2.c ("KFLAGS=-O0") (Letter O Digit Zero).
+#(This could be automated by testing `uname -m` for "sun3".)
+#OK: 2011/06/15 on NetBSD 1.5.2 and 5.1.
+netbsd netbsd2 netbsd15 netbsd16 old-netbsd:
        @echo Making C-Kermit $(CKVER) for NetBSD with curses...
        $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
-       "CFLAGS= -DBSD44 -DCK_CURSES -DTCPSOCKET -DUSE_STRERROR -DTPUTSISVOID \
+       "CFLAGS=`grep fseeko /usr/include/stdio.h > /dev/null && \
+       echo '-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'` \
+       -DBSD44 -DCK_CURSES -DTCPSOCKET -DUSE_STRERROR -DHAVE_OPENPTY \
+       -funsigned-char -DHERALD=\"\\\" NetBSD `uname -r`\\\"\" \
        -DCK_DTRCD -DCK_DTRCTS -DTPUTSARGTYPE=int -DFNFLOAT $(KFLAGS) -O" \
-       "LIBS= -lcurses -lcrypt -lm $(LIBS)"
-
-#NetBSD 1.5.x in which the return type of the function pointer that is the
-#third argument of tputs() was changed from void to int...  The regular NetBSD
-#target builds OK here but this one eliminates the (harmless) warning.
-netbsd15:
+       "LIBS= -lcurses -lcrypt -lm -lutil $(LIBS)"
+
+#NetBSD 1.4.1 or later with OpenSSL
+#OK: 2011/06/15 on NetBSD 5.1 (but not 1.5.2 with OpenSSL 0.9.5a)
+netbsd+ssl netbsd+openssl:
+       @echo 'Making C-Kermit $(CKVER) for NetBSD+OpenSSL SSLLIB=$(SSLLIB)'
+       @case `openssl version` in \
+         *0.9.7*) OPENSSLOPTION="-DOPENSSL_097" ;; \
+         *0.9.8*) OPENSSLOPTION="-DOPENSSL_098" ;; \
+         *1.[0-9].[0-9]*) OPENSSLOPTION="-DOPENSSL_100" ;; \
+         *) OPENSSLOPTION="" ;; \
+       esac; \
+       HAVE_DES=''; \
+       DES_LIB=''; \
+       if ls /usr/lib/libdes* > /dev/null 2> /dev/null || \
+          ls $(SSLLIB)/libdes* > /dev/null 2> /dev/null; then \
+             DES_LIB='-ldes'; \
+             HAVE_DES='-DCK_DES -DLIBDES'; \
+              echo "HAVE DES"; \
+           else echo "NO DES"; \
+       fi; \
+       $(MAKE) netbsd KTARGET=$${KTARGET:-$(@)} "CC = gcc" "CC2 = gcc" \
+       "KFLAGS= -DCK_AUTHENTICATION -DCK_ENCRYPTION -DCK_CAST $$HAVE_DES \
+       -DCK_SSL -DCK_PAM -DZLIB -DNO_DCL_INET_ATON $$OPENSSLOPTION \
+       $(KFLAGS)" "LNKFLAGS = $(LNKFLAGS)" \
+       "LIBS= -L/usr/pkg/lib -R/usr/pkg/lib -lssl $$DES_LIB -lcurses \
+       -lcrypto -lcrypt -lz -lm -lpam -lutil $(LIBS)"
+
+#NetBSD with MIT Kerberos 5:
+# OK 2011/06/15 (once K5INC and K5LIB were set right).
+# NOT OK for Heimdal - Heimdal Kerberos support in C-Kermit needs work.
+netbsd+krb5:
+       @echo 'Making C-Kermit $(CKVER) for NetBSD with Kerberos 5...'
+       @echo 'Making C-Kermit $(CKVER) for NetBSD+OpenSSL+Kerberos5...'
+       @case `openssl version` in \
+         *0.9.7*) OPENSSLOPTION="-DOPENSSL_097" ;; \
+         *0.9.8*) OPENSSLOPTION="-DOPENSSL_098" ;; \
+         *1.[0-9].[0-9]*) OPENSSLOPTION="-DOPENSSL_100" ;; \
+         *) OPENSSLOPTION="" ;; \
+       esac; \
+       HAVE_DES=''; \
+       DES_LIB=''; \
+       if ls /usr/lib/libdes* > /dev/null 2> /dev/null || \
+          ls $(SSLLIB)/libdes* > /dev/null 2> /dev/null; then \
+             DES_LIB='-ldes'; \
+             HAVE_DES='-DCK_DES -DLIBDES'; \
+              echo "HAVE DES"; \
+           else echo "NO DES"; \
+       fi; \
+       $(MAKE) netbsd KTARGET=$${KTARGET:-$(@)} "CC = gcc" "CC2 = gcc" \
+       "KFLAGS= -DCK_AUTHENTICATION -DCK_ENCRYPTION -DCK_KERBEROS -DKRB5 \
+       -DCK_CAST $$HAVE_DES -DNOFTP_GSSAPI $(K5INC) $(K5INC)/krb5 \
+       $(KFLAGS)" \
+       "LIBS= $(K5LIB) -L/usr/pkg/lib -R/usr/pkg/lib -lcurses $$DES_LIB \
+       -lcrypto -lgssapi -lkrb5 -lm -lutil $(LIBS)"
+
+# NetBSD - With Kerberos 5 and SSL and Zlib.
+# OK 2011/06/15
+netbsd+krb5+ssl netbsd+krb5+openssl+zlib:
+       @echo 'Making C-Kermit $(CKVER) for NetBSD+OpenSSL+Kerberos5...'
+       @case `openssl version` in \
+         *0.9.7*) OPENSSLOPTION="-DOPENSSL_097" ;; \
+         *0.9.8*) OPENSSLOPTION="-DOPENSSL_098" ;; \
+         *1.[0-9].[0-9]*) OPENSSLOPTION="-DOPENSSL_100" ;; \
+         *) OPENSSLOPTION="" ;; \
+       esac; \
+       HAVE_DES=''; \
+       DES_LIB=''; \
+       if ls /usr/lib/libdes* > /dev/null 2> /dev/null || \
+          ls $(SSLLIB)/libdes* > /dev/null 2> /dev/null; then \
+             DES_LIB='-ldes'; \
+             HAVE_DES='-DCK_DES -DLIBDES'; \
+              echo "HAVE DES"; \
+           else echo "NO DES"; \
+       fi; \
+       $(MAKE) netbsd KTARGET=$${KTARGET:-$(@)} "CC = gcc" "CC2 = gcc" \
+       "KFLAGS= -DCK_AUTHENTICATION -DCK_ENCRYPTION -DCK_CAST $$HAVE_DES \
+       -DCK_KERBEROS -DKRB5 -DNOFTP_GSSAPI $(K5INC) $(K5INC)/krb5 \
+       -DCK_SSL -DCK_PAM -DZLIB -DNO_DCL_INET_ATON $$OPENSSLOPTION \
+       $(KFLAGS)" "LNKFLAGS = $(LNKFLAGS)" \
+       "LIBS= $(K5LIB) -L/usr/pkg/lib -R/usr/pkg/lib -lssl $$DES_LIB \
+       -lcrypto -lcrypt -lgssapi -lkrb5 -lz -lm -lpam -lutil -lcurses $(LIBS)"
+
+#Special Security Enhanced NetBSD target with SRP, SSL, and zlib support.
+#To build this, you need to BUILD the pkgsrc srp_client package.  After
+#you build it, you must go into work/srp-x.y.z/libkrypto and "bmake install"
+#then go to work/srp-x.y.z/libsrp and "bmake install".  As of 2005Q3, the
+#pkgsrc install only installed the statically linked client applications.  You
+#need to manually install the libraries to build your own applications.
+netbsd+ssl+srp+zlib:
        @echo Making C-Kermit $(CKVER) for NetBSD with curses...
        $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
        "CFLAGS= -DBSD44 -DCK_CURSES -DTCPSOCKET -DUSE_STRERROR -DNETBSD15 \
-       -DCK_DTRCD -DCK_DTRCTS -DTPUTSARGTYPE=int -DFNFLOAT $(KFLAGS) -O" \
-       "LIBS= -lcurses -lcrypt -lm $(LIBS)"
-
-#NetBSD 1.6 - like 1.5.x but with vanity banner saying 1.6.
-netbsd16:
-       @echo Making C-Kermit $(CKVER) for NetBSD with curses...
-       $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
-       "CFLAGS= -DBSD44 -DCK_CURSES -DTCPSOCKET -DUSE_STRERROR \
-       -DNETBSD15 -DNETBSD16 \
-       -DCK_DTRCD -DCK_DTRCTS -DTPUTSARGTYPE=int -DFNFLOAT $(KFLAGS) -O" \
-       "LIBS= -lcurses -lcrypt -lm $(LIBS)"
+       -DCK_DTRCD -DCK_DTRCTS -DTPUTSARGTYPE=int -DHAVE_OPENPTY \
+       -I/usr/include/openssl -I/usr/pkg/include \
+       -DCK_AUTHENTICATION -DCK_SRP -DPRE_SRP_1_4_5 -DCK_ENCRYPTION \
+       -DCK_CAST -DCK_DES -DLIBDES -DCK_SSL -DZLIB -DFNFLOAT $(KFLAGS) -O" \
+       "LIBS= -L/usr/pkg/lib -R/usr/pkg/lib -lcurses -lsrp -lgmp -ldes \
+       -lssl -lkrypto -lcrypto -lcrypt -lz -lm -lutil $(LIBS)"
+
+#NetBSD with curses left out (e.g. for use as IKSD).
+netbsdnc:
+       @echo Making C-Kermit $(CKVER) for NetBSD with no curses...
+       $(MAKE) CC=$(CC) CC2=$(CC2) netbsd KTARGET=$${KTARGET:-$(@)} \
+       "KFLAGS=-DNOCURSES"
 
 #NetBSD with ncurses requested explicitly rather than curses-which-is-ncurses
 netbsdn:
-       @echo Making C-Kermit $(CKVER) for NetBSD with ncurses...
+       @echo Making C-Kermit $(CKVER) for NetBSD with curses...
        $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
-       "CFLAGS= -DBSD44 -DCK_CURSES -DTCPSOCKET -DNOCOTFMC -DCK_DTRCD \
-       -DCK_DTRCTS -DFNFLOAT -DUSE_STRERROR -DTPUTSISVOID -DTPUTSARGTYPE=int \
-       $(KFLAGS) -O" \
-       "LIBS= -L/usr/pkg/lib -lncurses -lcrypt -lm $(LIBS)"
+       "CFLAGS=`grep fseeko /usr/include/stdio.h > /dev/null && \
+       echo '-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'` \
+       -DBSD44 -DCK_CURSES -DTCPSOCKET -DUSE_STRERROR -DHAVE_OPENPTY \
+       -DHERALD=\"\\\" NetBSD `uname -r`\\\"\" \
+       -DCK_DTRCD -DCK_DTRCTS -DTPUTSARGTYPE=int -DFNFLOAT $(KFLAGS) -O" \
+       "LIBS= -L/usr/pkg/lib -lncurses -lcrypt -lm -lutil $(LIBS)"
 
 #OpenBSD - All versions.
 #Uses ncurses as its curses so use -ltermlib, not -ltermcap
@@ -1871,6 +1897,16 @@ openbsd:
        @echo Making C-Kermit $(CKVER) for OpenBSD 2.3 or later...
        $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
        "CFLAGS= -DBSD44 -DCK_CURSES -DCK_NEWTERM -DTCPSOCKET -DOPENBSD \
+       -DHERALD=\"\\\" OpenBSD `uname -r`\\\"\" \
+       -DUSE_UU_LOCK -DFNFLOAT -DUSE_STRERROR $(KFLAGS) -O" \
+       "LIBS= -lcurses -lutil -lm"
+
+#Better to chain to the openbsd target but...
+mirbsd:
+       @echo Making C-Kermit $(CKVER) for OpenBSD 2.3 or later...
+       $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
+       "CFLAGS= -DBSD44 -DCK_CURSES -DCK_NEWTERM -DTCPSOCKET -DOPENBSD \
+       -DHERALD=\"\\\" MirBSD `uname -r`\\\"\" \
        -DUSE_UU_LOCK -DFNFLOAT -DUSE_STRERROR $(KFLAGS) -O" \
        "LIBS= -lcurses -lutil -lm"
 
@@ -1881,14 +1917,24 @@ openbsd:
 # -DUSE_UU_LOCK and -lutil added for uu_lock()
 # -DNDSYSERRLIST changed to -DUSE_STRERROR
 #If this gives you trouble use the previous entry.
-openbsd30+ssl:
+openbsd+ssl:
        @echo Making C-Kermit $(CKVER) for OpenBSD 3.0 or later...
        $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
        "CFLAGS= -DBSD44 -DCK_CURSES -DCK_NEWTERM -DTCPSOCKET -DOPENBSD \
+       -DHERALD=\"\\\" OpenBSD `uname -r`\\\"\" \
        -DUSE_UU_LOCK -DFNFLOAT -DUSE_STRERROR -DCK_AUTHENTICATION \
        -DCK_SSL $(KFLAGS) -O" \
        "LIBS= -lcurses -lutil -lm -lssl -lcrypto"
 
+mirbsd+ssl:
+       @echo Making C-Kermit $(CKVER) for OpenBSD 3.0 or later...
+       $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
+       "CFLAGS= -DBSD44 -DCK_CURSES -DCK_NEWTERM -DTCPSOCKET -DOPENBSD \
+       -DHERALD=\"\\\" MirBSD `uname -r`\\\"\" \
+       -DUSE_UU_LOCK -DFNFLOAT -DUSE_STRERROR -DCK_AUTHENTICATION \
+       -DCK_SSL -DNO_DCL_INET_ATON $(KFLAGS) -O" \
+       "LIBS= -lcurses -lutil -lm -lssl -lcrypto"
+
 # make 386bsd 0.0new, posix
 # for  386bsd 0.1.24, change /usr/include/termios.h to #define NCCS if
 #  _POSIX_SOURCE is #defined. (source: lewine, posix prgmrs guide, o`reilly)
@@ -1902,8 +1948,11 @@ openbsd30+ssl:
        -DLOCK_DIR=\\\"/var/spool/lock\\\" \
        $(KFLAGS) -O" "LNKFLAGS = -s" "LIBS = -lcurses -ltermcap"
 
+# Mac OS X 10 early versions.
+# For 10.3.9 and later, use the macosx target below.
+
 #Mac OS X 1.0 (Rhapsody, Darwin) -- TCP/IP but no curses.
-macosx10:
+oldmacosx10:
        @echo Making C-Kermit $(CKVER) for `uname -s`...
        $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
        "CFLAGS= -DMACOSX10 -DTCPSOCKET -DUSE_STRERROR -O $(KFLAGS)"
@@ -1911,7 +1960,7 @@ macosx10:
 #Mac OS X 1.0 (Rhapsody, Darwin) -- TCP/IP and curses.
 #Note: curses must be obtained separately.  See next entry for ncurses.
 #Add "LIBS = -lcurses -ltermcap" if necessary (but reportedly it is not).
-macosx10c:
+oldmacosx10c:
        @echo Making C-Kermit $(CKVER) for `uname -s` + curses...
        $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
        "CFLAGS= -DMACOSX10 -DCK_CURSES -DTPUTSFNTYPE=void -DTPUTSISVOID \
@@ -1920,14 +1969,14 @@ macosx10c:
 #Mac OS X 1.0 (Rhapsody, Darwin) -- TCP/IP and ncurses.
 #Note: ncurses must be obtained separately.
 #In the event of trouble with this one try the next one.
-macosx10nc:
+oldmacosx10nc:
        @echo Making C-Kermit $(CKVER) for `uname -s` + ncurses...
        $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
        "CFLAGS= -DMACOSX10 -DCK_NCURSES -DTCPSOCKET -DUSE_STRERROR -O \
        $(KFLAGS)" "LIBS= -lncurses $(LIBS)"
 
 #Mac OS X 10.2 (Jaguar) ncurses.
-macosx102nc:
+oldmacosx102nc:
        @echo Making C-Kermit $(CKVER) for `uname -s` + ncurses...
        $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
        "CFLAGS= -DMACOSX10 -DCK_NCURSES -DTCPSOCKET -DUSE_STRERROR -O \
@@ -1935,8 +1984,8 @@ macosx102nc:
 
 #The problem here is that if curses.h also exists, it conflicts with
 #ncurses.h and and we have fatal errors.  If this happens to you, then
-#try this entry.
-macosx10ncx:
+#try this target.
+oldmacosx10ncx:
        @echo Making C-Kermit $(CKVER) for `uname -s` + ncurses...
        @rm -f ./curses.h; touch ./curses.h
        $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
@@ -1946,15 +1995,89 @@ macosx10ncx:
        @rm -f ./curses.h
 
 #Mac OS X 10.3 (Panther) - Assumes ncurses is installed.
-macosx103: 
+oldmacosx103: 
        @echo Making C-Kermit $(CKVER) for `uname -s` + ncurses...
        $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
-       "CFLAGS= -DMACOSX10 -DMACOSX103 -DCK_NCURSES -DTCPSOCKET \
+       "CFLAGS= -DMACOSX10 -DMACOSX103 -DCK_NCURSES -DTCPSOCKET -DCKHTTP \
        -DUSE_STRERROR -DUSE_NAMESER_COMPAT -O \
        $(KFLAGS) " "LIBS= -lncurses -lresolv $(LIBS)"
 
-macosx103nc:
-       $(MAKE) MAKE=$(MAKE) CC=$(CC) CC2=$(CC2) macosx103
+#Mac OS X 10.3 (Panther) with Kerberos 5 and SSL, assumes ncurses is installed.
+oldmacosx103+secure:
+       @echo Making Secure C-Kermit $(CKVER) for `uname -s` + ncurses...
+       $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
+       "CFLAGS= -DMACOSX10 -DMACOSX103 -DCK_NCURSES -DTCPSOCKET \
+       -DUSE_STRERROR -DUSE_NAMESER_COMPAT -O -DCK_PAM \
+       -DCK_AUTHENTICATION -DCK_KERBEROS -DKRB5 -DZLIB \
+       -DCK_ENCRYPTION -DCK_CAST -DCK_DES -DLIBDES -DCK_SSL \
+       $(KFLAGS) " "LIBS= -lssl -lcrypto -lkrb5 -lcom_err \
+       -lk5crypto -lgssapi_krb5 -lpam -lncurses -lresolv $(LIBS)"
+
+# THIS IS THE MAIN MAC OS X TARGET (the next one is for Kerberos/SSL builds).
+# Use this target for 10.3.9 (or maybe earlier) through 10.6 (maybe later)
+# on both Power and Intel architectures.  This one uses utmp.h on 10.4 and
+# earlier and utmpx.h on 10.5 onwards.
+# Note: Mac OS X 10.5 and earlier are 32-bit; 10.6 and later 64-bit.
+# Note 2: As of C-Kermit 9.0 -NOUUCP is included by default because
+# Mac OS X doesn't support UUCP.  To undo this, use KFLAGS=-UNOUUCP.
+#OK: 2009/11/16 (for 10.3.9, 10.4.11, 10.5.8, 10.6.1)
+macosx macosx10 macosx10.3.9 macosx10.4 macosx10.5 macosx10.6:
+       @MACOSNAME=`/usr/bin/sw_vers -productName`; \
+       MACOSV=`/usr/bin/sw_vers -productVersion`; \
+       echo Making C-Kermit $(CKVER) for $$MACOSNAME $$MACOSV... ; \
+       MACCPU=$$HOSTTYPE; \
+       if test `uname -r | cut -d . -f 1` -gt 8; \
+       then if test -f /usr/include/utmpx.h ; \
+       then HAVE_UTMPX='-DHAVEUTMPX -D_UTMPX_COMPAT' ; \
+       else HAVE_UTMPX='' ; fi ; fi; \
+       $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
+       "CFLAGS= -DMACOSX10 -DMACOSX103 -DCK_NCURSES -DTCPSOCKET -DCKHTTP \
+       -DUSE_STRERROR -DUSE_NAMESER_COMPAT -DNOCHECKOVERFLOW -DFNFLOAT \
+       -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 $$HAVE_UTMPX \
+       -funsigned-char -DNODCLINITGROUPS \
+       -DNOUUCP -O -DHERALD=\"\\\" $${MACOSNAME} $${MACOSV}\\\"\" \
+       -DCKCPU=\"\\\"$${MACCPU}\\\"\" \
+       $(KFLAGS)" "LIBS= -lncurses -lresolv $(LIBS)"
+
+# Mac OS X 10.3.9 or later with Kerberos 5 and OpenSSL...
+# NOTE: Apple has removed all support for DES in OpenSSL and Kerberos
+#   in Mac OS X 10.6 and later.  The DES flags are included or left out
+#   automatically based on the Mac OS X version number.
+# See note about UUCP in previous target.
+#OK: 2009/11/16 (for 10.3.9, 10.4.11, 10.5.8, 10.6.1)
+macosx+krb5+ssl macosx10.5+krb5+ssl macosx10.6+krb5+ssl \
+macosx+krb5+openssl macosx10.5+krb5+openssl macosx10.6+krb5+openssl:
+       @MACOSNAME=`/usr/bin/sw_vers -productName`; \
+       MACOSV=`/usr/bin/sw_vers -productVersion`; \
+       echo Making C-Kermit $(CKVER) for $$MACOSNAME $$MACOSV... ; \
+       MACCPU=$$HOSTTYPE; \
+       if test `uname -r | cut -d . -f 1` -gt 8; \
+       then if test -f /usr/include/utmpx.h ; \
+       then HAVE_UTMPX='-DHAVEUTMPX -D_UTMPX_COMPAT' ; \
+       else HAVE_UTMPX='' ; fi ; fi; \
+       if test `uname -r | cut -d . -f 1` -eq 7; \
+       then IS_MACOSX103='-DMACOSX103' ; \
+       else IS_MACOSX103='' ; fi; \
+       case $$MACOSV in \
+         10.[012345].*) HAVE_DES='-DCK_DES -DLIBDES' ;; \
+         *.*) HAVE_DES='' ;; \
+       esac ; \
+       if test -x /usr/bin/krb5-config ; \
+       then HAVE_KRB5CONFIG=`/usr/bin/krb5-config --libs krb5 gssapi` ; \
+       else HAVE_KRB5CONFIG='-lgssapi_krb5 -lkrb5 -lk5crypto \
+       -lcom_err -lresolv' ; fi; \
+       $(MAKE) CC=$(CC) CC2=$(CC2) xermit KTARGET=$${KTARGET:-$(@)} \
+       "CFLAGS= -DMACOSX10 $$IS_MACOSX103 -DCK_NCURSES -DTCPSOCKET \
+       -DUSE_STRERROR -DUSE_NAMESER_COMPAT -DNOCHECKOVERFLOW -DFNFLOAT \
+       -DCKHTTP -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 $$HAVE_UTMPX \
+       -DNODCLINITGROUPS -DCK_AUTHENTICATION -DCK_KERBEROS -DKRB5 -DZLIB \
+       -DCK_ENCRYPTION -DCK_CAST -DCK_SSL -DOPENSSL_098 $$HAVE_DES \
+       -DNOUUCP -DHERALD=\"\\\" $${MACOSNAME} $${MACOSV}\\\"\" \
+       -DCKCPU=\"\\\"$${MACCPU}\\\"\" \
+       -funsigned-char -O $(KFLAGS)" \
+       "LIBS= $$HAVE_KRB5CONFIG -lssl -lcrypto -lpam -lncurses $(LIBS)"
+
+# End of Mac OS X Section
 
 #Acorn RISCiX, based on ...
 #Berkeley Unix 4.2 or 4.3 with lock directory /usr/spool/uucp/LCK/LCK..ttyxx,
@@ -1989,7 +2112,7 @@ ctix:
        @echo 'Making C-Kermit $(CKVER) for Convergent CTIX 6.4.1'
        $(MAKE) wermit KTARGET=$${KTARGET:-$(@)} \
        "CFLAGS= -DSVR3 -DDIRENT -DTCPSOCKET -DHDBUUCP -DCK_CURSES \
-       -DNONAWS -DNOLEARN $(KFLAGS) -XO" \
+       -DNONAWS -DNOLEARN -DNOLONGLONG $(KFLAGS) -XO" \
        "LNKFLAGS=-s" "LIBS=-lsocket -lcurses -lc_s"
        mcs -d wermit
 
@@ -2003,8 +2126,8 @@ cx_ux:
        @echo Making C-Kermit $(CKVER) for Harris Night Hawk CX/UX 6.1 or later
        $(MAKE) wermit KTARGET=$${KTARGET:-$(@)} \
        "CFLAGS=-DPOSIX -DTCPSOCKET -DHDBUUCP -DPID_T=pid_t -DWAIT_T=int \
-       -Dd_ino=d_fileno -DUID_T=uid_t -DGID_T=gid_t $(KFLAGS) -Xa \
-       -O3 -g" "LNKFLAGS=-O3"
+       -Dd_ino=d_fileno -DUID_T=uid_t -DGID_T=gid_t -DNOLONGLONG \
+       $(KFLAGS) -Xa -O3 -g" "LNKFLAGS=-O3"
 
 #Intergraph Clipper, CLIX, job control, HDB UUCP.
 clix:
@@ -2183,14 +2306,14 @@ ultrix42s5r4:
        -DTCPSOCKET $(KFLAGS)" "LNKFLAGS = -s"
 
 #OSF/1
-osf:
+osf osf1:
        $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} \
        "CFLAGS= -DBSD4 -DOSF -D_BSD -DTCPSOCKET -DCK_ANSIC -DSIG_V \
        -DCK_CURSES -DCK_RTSCTS -DFNFLOAT $(KFLAGS)" \
-       "LNKFLAGS = -s" "LIBS = -lbsd -lcurses -ltermcap -lm"
+       "LNKFLAGS = -s" "LIBS = $(LIBS) -lbsd -lcurses -ltermcap -lm"
 
 #DEC OSF/1 V1.0-1.3 on DECstation, VAX, Alpha, or PC.
-dec-osf:
+dec-osf dec-osf1:
        $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} \
        "CFLAGS= -DBSD4 -DOSF -DOSF13 -D_BSD -DTCPSOCKET -DCK_ANSIC -DSIG_V \
        -DNOREALPATH -DNOIKSD -DCK_CURSES -DCK_RTSCTS -DFNFLOAT -DNODEBUG \
@@ -2283,11 +2406,21 @@ tru64-51a:
        -unsigned -std1 -O3 -Olimit 2400 $(KFLAGS)"
 
 tru64-51b:
-       @echo Making C-Kermit $(CKVER) for Tru64 UNIX 5.1A...
+       @echo Making C-Kermit $(CKVER) for Tru64 UNIX 5.1B...
        $(MAKE) CC=$(CC) CC2=$(CC2) osf KTARGET=$${KTARGET:-$(@)} \
        "KFLAGS= -DTRU64 -DOSF50 -DOSF51A -DOSF51B -DHDBUUCP \
        -unsigned -std1 -O3 -Olimit 2400 $(KFLAGS)"
 
+# Added 5.1b version with OpenSSL - CDW 6-13-2005...
+tru64-51b+openssl:
+       @echo Making C-Kermit $(CKVER) for Tru64 UNIX 5.1b
+       @echo  including OpenSSL...
+       $(MAKE) CC=$(CC) CC2=$(CC2) osf KTARGET=$${KTARGET:-$(@)} \
+       "KFLAGS= -DTRU64 -DOSF50 -DOSF51A -DOSF51B -DHDBUUCP \
+       -unsigned -std1 -O3 -Olimit 2400 \
+       -DCK_AUTHENTICATION -DCK_SSL $(SSLINC) $(KFLAGS)" \
+       "LIBS= $(SSLLIB) -rpath $(sslroot)/ssl/lib -lssl -lcrypto"
+
 du50:
        $(MAKE) CC=$(CC) CC2=$(CC2) tru64-50a KTARGET=$${KTARGET:-$(@)}
 
@@ -2498,6 +2631,9 @@ nextgc:
 
 #NeXTSTEP 3.3.
 #Includes fullscreen file transfer display and TCP/IP.
+# You might have to add 1 line to 1 NeXT header file <ip.h>
+# to declare n_long as u_long by adding #include <bsd/netinet/in_systm.h>
+
 next33:
        @echo Making C-Kermit $(CKVER) for NeXTSTEP 3.3...
        $(MAKE) xermit CC=$(CC) CC2=$(CC2) KTARGET=$${KTARGET:-$(@)} \
@@ -2623,7 +2759,7 @@ bsdi4:
        $(MAKE) "MAKE=$(MAKE)" CC=$(CC) CC2=$(CC2) bsdi \
        KTARGET=$${KTARGET:-$(@)} \
        "KFLAGS=-DBSDI2 -DBSDI3 -DBSDI4 -DTPUTSFNTYPE=void -DTPUTSISVOID \
-       -m486 $(KFLAGS)"
+       -DCKHTTP -m486 $(KFLAGS)"
 
 # (old name for the above)
 bsdiposix:
@@ -2714,6 +2850,8 @@ rtaix:
        -DUSE_LSTAT -DFNFLOAT -Nn2500 -Np1000 -Wq,-SJ2 -a -w $(KFLAGS)" \
        "LIBS = -lm $(LIBS)" "LNKFLAGS = -s"
 
+#### IBM RT PC - these targets were last verified in C-Kermit 8.0.211.
+
 #IBM RT PC with AIX 2.2.1 + curses
 rtaixc:
        $(MAKE) rtaix CC=$(CC) CC2=$(CC2) "KFLAGS=-DCK_CURSES" "LIBS=-lcurses"
@@ -2726,6 +2864,77 @@ rtacis:
        "CFLAGS= -DBSD4 -DTCPSOCKET -DNOREALPATH -DNOIKSD -DNOPUTENV \
        $(KFLAGS) -U__STDC__" "LNKFLAGS = -s"
 
+#### IBM AIX.  The first two targets should work for any version of AIX
+#### from 4.2 onwards.  The ones after that are for older versions or
+#### specific configurations, and/or with gcc.
+
+# This one should work for any AIX 4.2 or later: "make aix".
+# Other tags are for compatibility with old makefile targets.
+#OK: 2009/11/16
+aix aix42 aix43 aix44 aix45 aix50 aix51 aix52 aix53 aix54 aix61:
+       @echo Making C-Kermit $(CKVER) for IBM AIX...
+       $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} \
+       "CFLAGS= -DAIXRS -DAIX41 -DAIX42 -DSVR4 -DSTERMIOX -DTCPSOCKET \
+       -DDIRENT -DCK_ANSIC -DCLSOPN -DCK_CURSES -DCK_NEWTERM -DFNFLOAT \
+       -DSELECT -DSELECT_H -DNOGETUSERSHELL -qmaxmem=16000 -O \
+       -DCKCPU=\\\"`uname -p`\\\" \
+       -DHERALD=\"\\\" IBM AIX `uname -v`.`uname -r`\\\"\" \
+       -D_LARGE_FILES $(KFLAGS)" "LNKFLAGS = -s" "LIBS=-lcurses -lm"
+
+# Same but using gcc instead of cc
+# This works but we get "gcc: unrecognized option '-qmaxmem-..'" each module.
+aixg:
+       @echo "Using gcc..."
+       $(MAKE) aix KTARGET=$${KTARGET:-$(@)} \
+       CC=gcc CC2=gcc "KFLAGS=-pipe -funsigned-char"
+
+# AIX 4.2 or later with OpenSSL 0.9.7 or later: "make aix+ssl"
+# For earlier OpenSSL remove -DOPENSSL_097 or add "KFLAGS=-UOPENSSL_097".
+# Synonym target names added to cover old redundant targets that were removed.
+# If SSL is not installed in the /usr/local tree (see SSLINC and SSLLIB
+# definitions near the top), you can specify the locations in your make
+# command as in this example:
+#
+#  SSLINC=-I/opt/ssl/include SSLLIB=-L/opt/ssl/lib make -e aix+ssl
+#
+# To build with gcc use "make aix CC=gcc CC2=gcc", or "make aixg"
+#
+#OK: 2009/11/16
+aix+ssl aix51+openssl aix52+openssl aix53+openssl:
+       @echo "Making C-Kermit $(CKVER) for IBM AIX with OpenSSL..."
+       @echo "SSLINC=$(SSLINC) SSLLIB=$(SSLLIB)"
+       $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} \
+       CC=$(CC) CC2=$(CC2) \
+       "CFLAGS=-DAIXRS -DAIX41 -DAIX42 -DSVR4 -DSTERMIOX -DTCPSOCKET \
+       -DDIRENT -DCK_ANSIC -DCLSOPN -DCK_CURSES -DCK_NEWTERM -DFNFLOAT \
+       -D_LARGE_FILES -DSELECT -DSELECT_H -DNOGETUSERSHELL \
+       -DCKCPU=\\\"`uname -p`\\\" \
+       -DHERALD=\"\\\" IBM AIX `uname -v`.`uname -r`\\\"\" \
+       -DCK_AUTHENTICATION -DCK_SSL -DOPENSSL_097 $(SSLINC) $(KFLAGS)" \
+       "LNKFLAGS=-s" "LIBS=$(SSLLIB) -lssl -lcrypto -lcurses -lm -lcrypt"
+
+# AIX 5.3 or 6.1 or later with IBM OpenSSL, which is always in the directories
+# shown below so you don't have to set SSLINC and SSLLIB.  If for some reason
+# the SSL include files and libraries are not in the places assumed, then use
+# "make aix+ssl" (just above) and set SSLINC and SSLLIB to indicate where the
+# SSL files are.  To build with gcc use "make aix+ibmssl CC=gcc CC2=gcc".
+aix+ibmssl:
+       @echo "Making C-Kermit $(CKVER) for IBM AIX 6.1 with OpenSSL..."
+       @echo "If this fails use 'make aix+ss' and specify SSLINC and SSLLIB"
+       $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} \
+       CC=$(CC) CC2=$(CC2) \
+       "CFLAGS=-DAIXRS -DAIX41 -DAIX42 -DSVR4 -DSTERMIOX -DTCPSOCKET \
+       -DDIRENT -DCK_ANSIC -DCLSOPN -DCK_CURSES -DCK_NEWTERM -DFNFLOAT \
+       -D_LARGE_FILES -DSELECT -DSELECT_H -DNOGETUSERSHELL \
+       -DCKCPU=\\\"`uname -p`\\\" \
+       -DHERALD=\"\\\" IBM AIX `uname -v`.`uname -r`\\\"\" \
+       -DCK_AUTHENTICATION -DCK_SSL -DOPENSSL_098 \
+       -I/usr/include/openssl $(KFLAGS)" \
+       "LNKFLAGS=-s" \
+       "LIBS=-L/usr/lib/openssl -lssl -lcrypto -lcurses -lm -lcrypt"
+
+# Old AIX versions...
+
 #IBM AIX 3.0, 3.1, or 3.2 for RISC System/6000.
 rs6000:
        @echo Making C-Kermit $(CKVER) for IBM AIX 3.0 or 3.1, RS/6000...
@@ -2834,20 +3043,25 @@ aix41x25o:
        "LNKFLAGS = -bI:/lib/pse.exp" "LIBS=-lcurses -lodm -lcfg"
        -@echo "\e]0;kermit done\a\c"
 
-#AIX 4.2 -- Must have CK_NEWTERM or echoing is lost after curses.
-# Add -bbigtoc in case ld fails with TOC overflow.
-aix42:
+#AIX 4.2 -- Use this target if the regular "make aix" doesn't work.
+# Must have CK_NEWTERM or echoing is lost after curses.
+# Add -bbigtoc in case ld fails with TOC overflow.  As of C-Kermit 8.0.212,
+# all AIX builds 4.2 and later include large file support.
+oldaix42:
        @echo Making C-Kermit $(CKVER) for IBM AIX 4.2 or higher...
        $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} \
        "CFLAGS= -DAIXRS -DAIX41 -DAIX42 -DSVR4 -DSTERMIOX -DTCPSOCKET \
        -DDIRENT -DCK_ANSIC -DCLSOPN -DCK_CURSES -DCK_NEWTERM -DFNFLOAT \
-       -DSELECT -DSELECT_H -DNOGETUSERSHELL -qmaxmem=16000 -O $(KFLAGS)" \
-       "LNKFLAGS = -s" "LIBS=-lcurses -lm"
+       -DSELECT -DSELECT_H -DNOGETUSERSHELL -qmaxmem=16000 -O \
+       -DCKCPU=\\\"`uname -p`\\\" \
+       -DHERALD=\\\"\ IBM\ AIX\ `uname -v`.`uname -r`\\\" \
+       -D_LARGE_FILES $(KFLAGS)" "LNKFLAGS = -s" "LIBS=-lcurses -lm"
 
-#AIX 4.3 -- Must NOT have CK_NEWTERM or else C-Kermit hangs after curses.
+#AIX 4.3 - Use this target if the regular "make aix" doesn't work.
+# Must NOT have CK_NEWTERM or else C-Kermit hangs after curses.
 # -bbigtoc needed on some systems but not others to avoid TOC overflow.
 # "man ld" says -bbigtoc makes program run slower.
-aix43:
+oldaix43:
        @echo Making C-Kermit $(CKVER) for IBM AIX 4.3 or higher...
        $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} \
        "CFLAGS= -DAIXRS -DAIX41 -DAIX43 -DSVR4 -DSTERMIOX -DTCPSOCKET \
@@ -2911,7 +3125,6 @@ aix43gccz:
        -DSTERMIOX -DTCPSOCKET -DFNFLOAT -DNOGETUSERSHELL $(KFLAGS)" \
        "LIBS= -L. -lcurses -bloadmap -bnoquiet"
 
-
 #AIX 4.3 with MIT Kerberos 5 and Kerberos 4 compatibility mode
 # Must NOT have CK_NEWTERM or else C-Kermit hangs after curses.
 # -mminimal-toc needed on some systems but not others to avoid TOC overflow.
@@ -2954,30 +3167,6 @@ aix43gcc+openssl:
        -DCK_AUTHENTICATION -DCK_SSL -funsigned-char $(SSLINC) $(KFLAGS)" \
        "LIBS=$(SSLLIB) -lssl -lcrypto -lcurses -lm -lcrypt"
 
-aix44:
-       $(MAKE) aix42 "KFLAGS=-DAIX44 -qmaxmem=20000 $(KFLAGS)" \
-       KTARGET=$${KTARGET:-$(@)}
-
-aix45:
-       $(MAKE) aix42 "KFLAGS=-DAIX45 -qmaxmem=20000 $(KFLAGS)" \
-       KTARGET=$${KTARGET:-$(@)}
-
-aix50:
-       $(MAKE) aix42 "KFLAGS=-DAIX50 -qmaxmem=20000 $(KFLAGS)" \
-       KTARGET=$${KTARGET:-$(@)}
-
-aix51:
-       $(MAKE) aix42 "KFLAGS=-DAIX51 -qmaxmem=20000 $(KFLAGS)" \
-       KTARGET=$${KTARGET:-$(@)}
-
-aix52:
-       $(MAKE) aix42 "KFLAGS=-DAIX52 -qmaxmem=20000 $(KFLAGS)" \
-       KTARGET=$${KTARGET:-$(@)}
-
-aix53:
-       $(MAKE) aix42 "KFLAGS=-DAIX53 -qmaxmem=20000 $(KFLAGS)" \
-       KTARGET=$${KTARGET:-$(@)}
-
 aix44gcc:
        $(MAKE) aix43g "KFLAGS=-DAIX44 $(KFLAGS)" \
        KTARGET=$${KTARGET:-$(@)}
@@ -3037,6 +3226,10 @@ sunos4x25:
 # /var/spool/ should be a symbolic link to  /usr/spool/.
 # ... or 'make xermit "CC= /usr/ucb/cc " \'
 # Note: "xermit" means use the select() version of the CONNECT module.
+# Note for C-Kermit 9.0: Reportedly 'you need to modify the sys/ioctl.h
+# include file, i.e. comment out the "struct winsize" and "struct
+# ttysize". Otherwise there will be a conflict with sys/ttycom.h (included by
+# termios.h) which also declares these structs. But you need both includes.'
 sunos41:
        @echo Making C-Kermit $(CKVER) for SunOS 4.1 / BSD...
        $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} \
@@ -3045,7 +3238,7 @@ sunos41:
 
 #As above, but compiled with gcc.  Gives 24-32K size reduction
 #with gcc 2.1 or 2.2.2.  CAUTION: make sure "fixincludes" has been run on
-#the include files, so gcc's are in sync with the regular Sun ones!
+#the include files, so gcc's are in sync with the regular Sun ones.
 #This includes the curses library for fullscreen file transfer display.
 #NDGPWNAM needed for GCC 2.5.6, not needed for 2.4.0, but it's uncertain
 #whether it will do any harm for 2.4.0 compilation -- if so, remove it.
@@ -3213,6 +3406,33 @@ solaris21:
        "CFLAGS = -O -Usun -DSVR4 -DSOLARIS -DDIRENT -DHDBUUCP -DFNFLOAT \
        -DSELECT -DNODEBUG -DSTERMIOX $(KFLAGS)" "LIBS = -lm" "LNKFLAGS = -s"
 
+#Solaris 2.0 - 2.4, SunPro compiler, includes curses and TCP/IP.
+#When using SUNWspro CC 2.0.1 under Solaris 2.3, be sure all cc patches
+#are applied, otherwise corrupt or truncated object files can result.
+#To build, set your PATH as follows:
+#  /usr/local/bin:/usr/bin:/opt/SUNWspro/bin:/usr/ccs/bin:\
+#  /usr/ucb:/usr/sbin:/sbin:.
+# or (depending on where the compiler has been installed):
+#  /usr/openwin/bin:/export/home/SUNWspro/bin:/usr/ccs/bin:/usr/sbin:/usr/bin.
+#For additional optimization try using "-fast -xO4 -xdepend".
+solaris2x:
+       @echo 'Making C-Kermit $(CKVER) for Solaris 2.x with SunPro cc...'
+       $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} \
+       "CFLAGS = -O -Usun -i -DSVR4 -DDIRENT -DSOLARIS -DHDBUUCP -DFNFLOAT \
+       -DSELECT -DCK_CURSES -DCK_NEWTERM -DSTERMIOX -DTCPSOCKET $(KFLAGS)" \
+       "LNKFLAGS = -s" "LIBS= -ltermlib -lsocket -lnsl -lm -lresolv"
+
+#as above but configured for Kerberos IV
+solaris2x+krb4:
+       @echo 'Making C-Kermit $(CKVER) for Solaris 2.x, SunPro cc, krb4...'
+       $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} \
+       "CFLAGS = -O -Usun -i -DSVR4 -DDIRENT -DSOLARIS -DHDBUUCP -DFNFLOAT \
+       -DSELECT -DCK_CURSES -DCK_NEWTERM -DSTERMIOX -DTCPSOCKET  \
+       -DCK_AUTHENTICATION -DCK_KERBEROS  -DKRB4 \
+       -DCK_ENCRYPTION -DCK_DES -DCK_CAST $(K4INC) $(KFLAGS)" \
+       "LNKFLAGS = -s" \
+       "LIBS= $(K4LIB) -ltermlib -lsocket -lnsl -lm -lresolv -lkrb -ldes"
+
 #C-Kermit for Solaris 2.0-2.4 compiled with gcc, includes curses and TCP/IP.
 #Change -O2 to -O if -O2 gives trouble.
 #Remove -Usun if it causes trouble.
@@ -3267,7 +3487,7 @@ solaris2xg+openssl+zlib+pam+shadow:
 
 #Ditto but with GCC 3.1 in which you have to specify 32-bit with -m32.
 #In Solaris 9 (and maybe 8) you'll also need specifiy the Library path.
-#Reportedly this can't be done here, but only with:
+#Reportedly this can be done here, but only with:
 # crle -l /usr/lib:/usr/local/ssl/lib
 #prior to building.  Note: 64-bit not tested with SSL.
 #For no-crypto 64-bit builds see the solaris9g64 target.
@@ -3332,21 +3552,114 @@ solaris24g:
        $(MAKE) "MAKE=$(MAKE)" KTARGET=$${KTARGET:-$(@)} \
        solaris2xg "KFLAGS=-DSOLARIS24 -DPOSIX_CRTSCTS $(KFLAGS)"
 
-#Solaris 2.5 built with gcc
-solaris25g:
-       $(MAKE) "MAKE=$(MAKE)" solaris2xg KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS=-funsigned-char -DSOLARIS25 $(KFLAGS)"
+#Solaris 2.0-2.3, SunPro compiler, with SunLink X.25 support.
+#This will only run if user has /opt/SUNWconn/lib/libsockx25.so.1
+#exists and can be dynamically linked.
+#NOTE: Do not change target to xermit -- it doesn't support X.25.
+solaris2x25:
+       @echo 'Making C-Kermit $(CKVER) for Solaris 2.x+X.25 with SunPro cc...'
+       $(MAKE) wermit KTARGET=$${KTARGET:-$(@)} \
+       "CFLAGS = -O -i -Usun -DSVR4 -DSOLARIS -DDIRENT \
+       -DSUNX25 -DTCPSOCKET -DHDBUUCP -DFNFLOAT -DNOLEARN \
+       -DSELECT -DCK_CURSES -DCK_NEWTERM -DSTERMIOX $(KFLAGS)" \
+       "LNKFLAGS = -s" \
+       "LIBS= -ltermlib -L/opt/SUNWconn/lib -R/opt/SUNWconn/lib \
+       -lsockx25 -lsocket -lnsl -lm -lresolv"
 
-#Solaris 2.5 built with gcc and Kerberos IV
-solaris25g+krb4:
-       $(MAKE) "MAKE=$(MAKE)" solaris2xg+krb4 KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS=-funsigned-char -DSOLARIS25 $(KFLAGS)"
+#Solaris 2.0-2.4, gcc, SunLink X.25 added.
+#NOTE: Can't use xermit target with X.25.
+solaris2xgx25:
+       @echo 'Making C-Kermit $(CKVER) for Solaris 2.x + X.25 with GNU cc...'
+       @echo 'Please read the comments that accompany the solaris2xg entry.'
+       $(MAKE) wermit CC=gcc CC2=gcc KTARGET=$${KTARGET:-$(@)} \
+       "CFLAGS = -g -O -Usun -DSVR4 -DSOLARIS -DSTERMIOX -DSELECT -DSUNX25 \
+       -DCK_CURSES -DCK_NEWTERM -DDIRENT -DHDBUUCP -DTCPSOCKET -DFNFLOAT \
+       -DNOLEARN $(KFLAGS)" \
+       "LIBS= -ltermlib -lm -L/opt/SUNWconn/lib -R/opt/SUNWconn/lib \
+       -lsockx25 -lsocket -lnsl"
 
-#Solaris 2.5 built with gcc and Kerberos V/IV, SSL, ...
-solaris25g+krb5+krb4+openssl+shadow:
-       $(MAKE) "MAKE=$(MAKE)" solaris2xg+krb5+krb4+openssl+shadow \
-       KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS=-funsigned-char -DSOLARIS25 $(KFLAGS)"
+#Solaris 2.4, SunPro compiler, with SunLink X.25 support.
+#This will only run if user has /opt/SUNWconn/lib/libsockx25.so.1
+#exists and can be dynamically linked.
+solaris24x25:
+       @echo 'Making C-Kermit $(CKVER) for Solaris 2.4+X.25 with SunPro cc...'
+       $(MAKE) wermit KTARGET=$${KTARGET:-$(@)} \
+       "CFLAGS = -O -i -Usun -DSVR4 -DSOLARIS -DSOLARIS24 -DDIRENT -DNOLEARN \
+       -DSUNX25 -DTCPSOCKET -DHDBUUCP -DFNFLOAT -DPOSIX_CRTSCTS \
+       -DSELECT -DCK_CURSES -DCK_NEWTERM -DSTERMIOX $(KFLAGS)" \
+       "LNKFLAGS = -s" \
+       "LIBS= -ltermlib -L/opt/SUNWconn/lib -R/opt/SUNWconn/lib \
+       -lsockx25 -lsocket -lnsl -lm -lresolv"
+
+#Solaris 2.5, SunPro compiler, with SunLink X.25 support.
+solaris25x25:
+       @echo 'Making C-Kermit $(CKVER) for Solaris 2.5+X.25 with SunPro cc...'
+       $(MAKE) wermit KTARGET=$${KTARGET:-$(@)} \
+       "CFLAGS = -O -i -Usun -DSVR4 -DSOLARIS25 -DDIRENT -DSUNX25 \
+       -DTCPSOCKET -DHDBUUCP -DSELECT -DCK_CURSES \
+       -DCK_NEWTERM -DSTERMIOX -DFNFLOAT -DPOSIX_CRTSCTS -DNOLEARN \
+       -I/opt/SUNWconn/include $(KFLAGS)" \
+       "LIBS= -ltermlib -L/opt/SUNWconn/lib -R/opt/SUNWconn/lib \
+       -lsockx25 -lsocket -lnsl -lm -lresolv"
+
+solaris23:
+       $(MAKE) "MAKE=$(MAKE)" solaris2x KTARGET=$${KTARGET:-$(@)} \
+       "KFLAGS=$(KFLAGS)"
+
+solaris24:
+       $(MAKE) "MAKE=$(MAKE)" solaris2x KTARGET=$${KTARGET:-$(@)} \
+       "KFLAGS=-DSOLARIS24 -DPOSIX_CRTSCTS $(KFLAGS)"
+
+# template for Solaris 2.5 and above.
+solaris25x:
+       @echo 'Making C-Kermit $(CKVER) for Solaris 2.x with SunPro cc...'
+       $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} \
+       "CFLAGS = -DFNFLOAT -O -Usun -i $(KFLAGS)" \
+       "LNKFLAGS = -s" \
+       "LIBS= -ltermlib -lsocket -lnsl -lm -lresolv $(LIBS)"
+
+#Solaris 2.5, SunPro compiler, curses, TCP/IP
+solaris25:
+       $(MAKE) "MAKE=$(MAKE)" solaris25x KTARGET=$${KTARGET:-$(@)} \
+       "KFLAGS=-DSOLARIS25 $(KFLAGS)"
+
+#Solaris 2.5, SunPro compiler, curses, TCP/IP, Kerberos IV
+solaris25+krb4:
+       $(MAKE) "MAKE=$(MAKE)" solaris25x+krb4 KTARGET=$${KTARGET:-$(@)} \
+       "KFLAGS=-DSOLARIS25 $(KFLAGS)"
+
+#Solaris 2.5 built with gcc
+solaris25g:
+       $(MAKE) "MAKE=$(MAKE)" solaris2xg KTARGET=$${KTARGET:-$(@)} \
+       "KFLAGS=-funsigned-char -DSOLARIS25 $(KFLAGS)"
+
+#Solaris 2.5 built with gcc and Kerberos IV
+solaris25g+krb4:
+       $(MAKE) "MAKE=$(MAKE)" solaris2xg+krb4 KTARGET=$${KTARGET:-$(@)} \
+       "KFLAGS=-funsigned-char -DSOLARIS25 $(KFLAGS)"
+
+#Solaris 2.5 built with gcc and Kerberos V/IV, SSL, ...
+solaris25g+krb5+krb4+openssl+shadow:
+       $(MAKE) "MAKE=$(MAKE)" solaris2xg+krb5+krb4+openssl+shadow \
+       KTARGET=$${KTARGET:-$(@)} \
+       "KFLAGS=-funsigned-char -DSOLARIS25 $(KFLAGS)"
+
+#Solaris 2.5, gcc, SunLink X.25 added.
+solaris25gx25:
+       $(MAKE) "MAKE=$(MAKE)" KTARGET=$${KTARGET:-$(@)} solaris2xgx25 \
+       "KFLAGS=-DSOLARIS25 $(KFLAGS)"
+
+#Solaris 2.6, gcc, SunLink X.25 added.
+solaris26gx25:
+       $(MAKE) "MAKE=$(MAKE)" KTARGET=$${KTARGET:-$(@)} solaris2xgx25 \
+       "KFLAGS=-DSOLARIS26 -DCK_PAM -DCK_SHADOW $(KFLAGS)" \
+       "LIBS= -lpam"
+
+#Solaris 2.6, SunPro compiler, curses, TCP/IP
+solaris26:
+       $(MAKE) "MAKE=$(MAKE)" solaris25x KTARGET=$${KTARGET:-$(@)} \
+       "KFLAGS=-DSOLARIS26 -DCK_PAM -DCK_SHADOW $(KFLAGS)" \
+       "LIBS= -lpam"
 
 #Solaris 2.6 with gcc
 solaris26g:
@@ -3365,6 +3678,23 @@ solaris26gnc:
        "KFLAGS= -DSOLARIS26 -DCK_PAM -DCK_SHADOW $(KFLAGS)" \
        "LIBS= -lpam"
 
+#Solaris 2.6, SunPro compiler, with SunLink X.25 support.
+solaris26x25:
+       @echo 'Making C-Kermit $(CKVER) for Solaris 2.6+X.25 with SunPro cc...'
+       $(MAKE) wermit KTARGET=$${KTARGET:-$(@)} \
+       "CFLAGS = -O -i -Usun -DSVR4 -DSOLARIS26 -DDIRENT -DSUNX25 \
+       -DTCPSOCKET -DHDBUUCP -DSELECT -DCK_CURSES -DCK_PAM -DCK_SHADOW \
+       -DCK_NEWTERM -DSTERMIOX -DFNFLOAT -DPOSIX_CRTSCTS -DNOLEARN \
+       -I/opt/SUNWconn/include $(KFLAGS)" \
+       "LIBS= -ltermlib -L/opt/SUNWconn/lib -R/opt/SUNWconn/lib \
+       -lsockx25 -lsocket -lnsl -lm -lresolv -lpam"
+
+#Solaris 7 (2.7) with Sun CC
+solaris7:
+       $(MAKE) "MAKE=$(MAKE)" solaris25x KTARGET=$${KTARGET:-$(@)} \
+       "KFLAGS=-DSOLARIS7 -DCK_PAM -DCK_SHADOW $(KFLAGS)" \
+       "LIBS= -lpam"
+
 #Solaris 7 with gcc (32-bit)
 solaris7g:
        $(MAKE) "MAKE=$(MAKE)" solaris2xg KTARGET=$${KTARGET:-$(@)} \
@@ -3388,47 +3718,18 @@ solaris7g+openssl+zlib+srp+pam+shadow:
        KTARGET=$${KTARGET:-$(@)} \
        "KFLAGS=-DSOLARIS7 -DCK_PAM -DCK_SHADOW $(KFLAGS)"
 
+#Solaris 8
+solaris8:
+       $(MAKE) "MAKE=$(MAKE)" solaris25x KTARGET=$${KTARGET:-$(@)} \
+       "KFLAGS=-DSOLARIS8 -DCK_PAM -DCK_SHADOW $(KFLAGS)" \
+       "LIBS= -lpam"
+
 #Solaris 8 with gcc (32-bit)
 solaris8g:
        $(MAKE) "MAKE=$(MAKE)" solaris2xg KTARGET=$${KTARGET:-$(@)} \
        "KFLAGS=-DSOLARIS8 -DCK_PAM -DCK_SHADOW $(KFLAGS)" \
        "LIBS= -lpam"
 
-#Solaris 9 with gcc + OpenSSL + Shadow (32-bit)
-solaris9g+openssl+shadow+pam+zlib:
-       $(MAKE) "MAKE=$(MAKE)" solaris2xg+openssl+zlib+pam+shadow \
-       KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS=-DSOLARIS9 -DHDBUUCP -DDIRENT -DZLIB -DCK_PAM -DCK_SHADOW \
-       -DLIBDES $(KFLAGS)" "LIBS= -lpam -ldes425 -lz $(LIBS)"
-
-#Solaris 9 with gcc + OpenSSL + Kerberos 5 + Krb4 + Shadow (32-bit)
-solaris9g+krb5+krb4+openssl+shadow+pam+zlib:
-       $(MAKE) "MAKE=$(MAKE)" solaris2xg+krb5+krb4+openssl+shadow \
-       KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS=-DSOLARIS9 -DHDBUUCP -DDIRENT -DZLIB -DCK_PAM -DCK_SHADOW \
-       -DLIBDES $(KFLAGS)" "LIBS= -lpam -ldes425 -lz $(LIBS)"
-
-#Solaris 9 with gcc 3.1 (32-bit)
-solaris9g:
-       @echo 'Making C-Kermit $(CKVER) for Solaris 9 with gcc'
-       $(MAKE) "MAKE=$(MAKE)" CC="gcc -m32" CC2="gcc -m32" xermit \
-       KTARGET=$${KTARGET:-$(@)} \
-       "CFLAGS = -g -O -Usun -DSVR4 -DSOLARIS -DSOLARIS9 -DUSE_STRERROR \
-       -DSTERMIOX -DSELECT -DFNFLOAT -DCK_PAM -DCK_SHADOW -funsigned-char \
-       -DCK_CURSES -DCK_NEWTERM -DDIRENT -DHDBUUCP -DTCPSOCKET $(KFLAGS)" \
-       "LIBS= -ltermlib -lsocket -lnsl -lm -lresolv -lpam"
-
-#Solaris 9 with gcc 3.1 (64-bit)
-#Peeking inside struct FILE at its members ist strengst verboten.
-solaris9g64:
-       @echo 'Making C-Kermit $(CKVER) for Solaris 9 with gcc'
-       $(MAKE) "MAKE=$(MAKE)" CC="gcc -m64" CC2="gcc -m64" xermit \
-       KTARGET=$${KTARGET:-$(@)} \
-       "CFLAGS = -g -O -Usun -DSVR4 -DSOLARIS  -DSOLARIS9 -DNOARROWKEYS \
-       -DSTERMIOX -DSELECT -DFNFLOAT -DUSE_STRERROR -DCK_PAM -DCK_SHADOW \
-       -DCK_CURSES -DCK_NEWTERM -DDIRENT -DHDBUUCP -DTCPSOCKET $(KFLAGS)" \
-       "LIBS= -ltermlib -lsocket -lnsl -lm -lresolv -lpam"
-
 # In OpenSSL builds add -ldl if you get unresolved references for
 # dlclose, dlsym, dlopen, dlerror.
 
@@ -3437,114 +3738,13 @@ solaris8g+openssl+zlib+pam+shadow:
        $(MAKE) "MAKE=$(MAKE)" solaris2xg+openssl+zlib+pam+shadow \
        KTARGET=$${KTARGET:-$(@)} "KFLAGS=-DSOLARIS8 $(KFLAGS)"
 
-#Solaris 9 with gcc 3.1 + OpenSSL (32-bit)
-solaris9g+openssl+zlib+pam+shadow:
-       $(MAKE) "MAKE=$(MAKE)" solaris2xg32+openssl+zlib+pam+shadow \
-       KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS=-DSOLARIS9 -DUSE_STRERROR $(KFLAGS)"
-
 #Solaris 8 with gcc + Kerberos IV (32-bit)
 solaris8g+krb4:
        $(MAKE) "MAKE=$(MAKE)" solaris2xg+krb4 KTARGET=$${KTARGET:-$(@)} \
        "KFLAGS=-DSOLARIS8 -DCK_PAM -DCK_SHADOW $(KFLAGS)" \
        "LIBS= -lpam"
 
-#Solaris 2.0-2.4, gcc, SunLink X.25 added.
-#NOTE: Can't use xermit target with X.25.
-solaris2xgx25:
-       @echo 'Making C-Kermit $(CKVER) for Solaris 2.x + X.25 with GNU cc...'
-       @echo 'Please read the comments that accompany the solaris2xg entry.'
-       $(MAKE) wermit CC=gcc CC2=gcc KTARGET=$${KTARGET:-$(@)} \
-       "CFLAGS = -g -O -Usun -DSVR4 -DSOLARIS -DSTERMIOX -DSELECT -DSUNX25 \
-       -DCK_CURSES -DCK_NEWTERM -DDIRENT -DHDBUUCP -DTCPSOCKET -DFNFLOAT \
-       -DNOLEARN $(KFLAGS)" \
-       "LIBS= -ltermlib -lm -L/opt/SUNWconn/lib -R/opt/SUNWconn/lib \
-       -lsockx25 -lsocket -lnsl"
-
-#Solaris 2.5, gcc, SunLink X.25 added.
-solaris25gx25:
-       $(MAKE) "MAKE=$(MAKE)" KTARGET=$${KTARGET:-$(@)} solaris2xgx25 \
-       "KFLAGS=-DSOLARIS25 $(KFLAGS)"
-
-#Solaris 2.6, gcc, SunLink X.25 added.
-solaris26gx25:
-       $(MAKE) "MAKE=$(MAKE)" KTARGET=$${KTARGET:-$(@)} solaris2xgx25 \
-       "KFLAGS=-DSOLARIS26 -DCK_PAM -DCK_SHADOW $(KFLAGS)" \
-       "LIBS= -lpam"
-
-#Solaris 2.0 - 2.4, SunPro compiler, includes curses and TCP/IP.
-#When using SUNWspro CC 2.0.1 under Solaris 2.3, be sure all cc patches
-#are applied, otherwise corrupt or truncated object files can result.
-#To build, set your PATH as follows:
-#  /usr/local/bin:/usr/bin:/opt/SUNWspro/bin:/usr/ccs/bin:\
-#  /usr/ucb:/usr/sbin:/sbin:.
-# or (depending on where the compiler has been installed):
-#  /usr/openwin/bin:/export/home/SUNWspro/bin:/usr/ccs/bin:/usr/sbin:/usr/bin.
-#For additional optimization try using "-fast -xO4 -xdepend".
-solaris2x:
-       @echo 'Making C-Kermit $(CKVER) for Solaris 2.x with SunPro cc...'
-       $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} \
-       "CFLAGS = -O -Usun -i -DSVR4 -DDIRENT -DSOLARIS -DHDBUUCP -DFNFLOAT \
-       -DSELECT -DCK_CURSES -DCK_NEWTERM -DSTERMIOX -DTCPSOCKET $(KFLAGS)" \
-       "LNKFLAGS = -s" "LIBS= -ltermlib -lsocket -lnsl -lm -lresolv"
-
-#as above but configured for Kerberos IV
-solaris2x+krb4:
-       @echo 'Making C-Kermit $(CKVER) for Solaris 2.x, SunPro cc, krb4...'
-       $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} \
-       "CFLAGS = -O -Usun -i -DSVR4 -DDIRENT -DSOLARIS -DHDBUUCP -DFNFLOAT \
-       -DSELECT -DCK_CURSES -DCK_NEWTERM -DSTERMIOX -DTCPSOCKET  \
-       -DCK_AUTHENTICATION -DCK_KERBEROS  -DKRB4 \
-       -DCK_ENCRYPTION -DCK_DES -DCK_CAST $(K4INC) $(KFLAGS)" \
-       "LNKFLAGS = -s" \
-       "LIBS= $(K4LIB) -ltermlib -lsocket -lnsl -lm -lresolv -lkrb -ldes"
-
-solaris23:
-       $(MAKE) "MAKE=$(MAKE)" solaris2x KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS=$(KFLAGS)"
-
-solaris24:
-       $(MAKE) "MAKE=$(MAKE)" solaris2x KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS=-DSOLARIS24 -DPOSIX_CRTSCTS $(KFLAGS)"
-
-# template for Solaris 2.5 and above.
-solaris25x:
-       @echo 'Making C-Kermit $(CKVER) for Solaris 2.x with SunPro cc...'
-       $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} \
-       "CFLAGS = -DFNFLOAT -O -Usun -i $(KFLAGS)" \
-       "LNKFLAGS = -s" \
-       "LIBS= -ltermlib -lsocket -lnsl -lm -lresolv $(LIBS)"
-
-#Solaris 2.5, SunPro compiler, curses, TCP/IP
-solaris25:
-       $(MAKE) "MAKE=$(MAKE)" solaris25x KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS=-DSOLARIS25 $(KFLAGS)"
-
-#Solaris 2.5, SunPro compiler, curses, TCP/IP, Kerberos IV
-solaris25+krb4:
-       $(MAKE) "MAKE=$(MAKE)" solaris25x+krb4 KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS=-DSOLARIS25 $(KFLAGS)"
-
-#Solaris 2.6, SunPro compiler, curses, TCP/IP
-solaris26:
-       $(MAKE) "MAKE=$(MAKE)" solaris25x KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS=-DSOLARIS26 -DCK_PAM -DCK_SHADOW $(KFLAGS)" \
-       "LIBS= -lpam"
-
-#Solaris 7 (aka 2.7)
-solaris7:
-       $(MAKE) "MAKE=$(MAKE)" solaris25x KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS=-DSOLARIS7 -DCK_PAM -DCK_SHADOW $(KFLAGS)" \
-       "LIBS= -lpam"
-
-#Solaris 8
-solaris8:
-       $(MAKE) "MAKE=$(MAKE)" solaris25x KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS=-DSOLARIS8 -DCK_PAM -DCK_SHADOW $(KFLAGS)" \
-       "LIBS= -lpam"
-
-#Solaris 9
-solaris9:
+solaris9nolfs:
        $(MAKE) "MAKE=$(MAKE)" solaris25x KTARGET=$${KTARGET:-$(@)} \
        "KFLAGS=-DSOLARIS9 -DCK_PAM -DCK_SHADOW -DUSE_STRERROR $(KFLAGS)" \
        "LIBS= -lpam"
@@ -3552,61 +3752,270 @@ solaris9:
 #Solaris 9 with malloc debugging
 solaris9md:
        $(MAKE) mermit KTARGET=$${KTARGET:-$(@)} \
-       "CFLAGS = -DFNFLOAT -O -Usun -i \
+       "CFLAGS = -DFNFLOAT -O -Usun -i -D_FILE_OFFSET_BITS=64 \
        -DSOLARIS9 -Dmalloc=dmalloc -Dfree=dfree -DMDEBUG \
        -DCK_PAM -DCK_SHADOW -DUSE_STRERROR $(KFLAGS)" \
        "LIBS= -lpam -ltermlib -lsocket -lnsl -lm -lresolv"
 
-#Solaris 2.0-2.3, SunPro compiler, with SunLink X.25 support.
-#This will only run if user has /opt/SUNWconn/lib/libsockx25.so.1
-#exists and can be dynamically linked.
-#NOTE: Do not change target to xermit -- it doesn't support X.25.
-solaris2x25:
-       @echo 'Making C-Kermit $(CKVER) for Solaris 2.x+X.25 with SunPro cc...'
-       $(MAKE) wermit KTARGET=$${KTARGET:-$(@)} \
-       "CFLAGS = -O -i -Usun -DSVR4 -DSOLARIS -DDIRENT \
-       -DSUNX25 -DTCPSOCKET -DHDBUUCP -DFNFLOAT -DNOLEARN \
-       -DSELECT -DCK_CURSES -DCK_NEWTERM -DSTERMIOX $(KFLAGS)" \
-       "LNKFLAGS = -s" \
-       "LIBS= -ltermlib -L/opt/SUNWconn/lib -R/opt/SUNWconn/lib \
-       -lsockx25 -lsocket -lnsl -lm -lresolv"
+#Solaris 9 with gcc + OpenSSL + Shadow (32-bit)
+#Add -DOPENSSL_097 for OpenSSL 0.9.7 or later.
+solaris9g+openssl+shadow+pam+zlib:
+       $(MAKE) "MAKE=$(MAKE)" solaris2xg+openssl+zlib+pam+shadow \
+       KTARGET=$${KTARGET:-$(@)} \
+       "KFLAGS=-DSOLARIS9 -DHDBUUCP -DDIRENT -D_FILE_OFFSET_BITS=64 \
+       -DNO_DCL_INET_ATON -DZLIB -DCK_PAM -DCK_SHADOW -DLIBDES $(KFLAGS)" \
+       "LIBS= -lpam -ldes425 -lz $(LIBS)"
+
+#Solaris 9 with gcc + OpenSSL + Kerberos 5 + Krb4 + Shadow (32-bit)
+#Add -DOPENSSL_097 for OpenSSL 0.9.7 or later.
+solaris9g+krb5+krb4+openssl+shadow+pam+zlib:
+       $(MAKE) "MAKE=$(MAKE)" solaris2xg+krb5+krb4+openssl+shadow \
+       KTARGET=$${KTARGET:-$(@)} \
+       "KFLAGS=-DSOLARIS9 -DHDBUUCP -DDIRENT -D_FILE_OFFSET_BITS=64 \
+       -DNO_DCL_INET_ATON -DZLIB -DCK_PAM -DCK_SHADOW -DLIBDES $(KFLAGS)" \
+       "LIBS= -lpam -ldes -lz $(LIBS)"
+
+#Solaris 9 with gcc + Kerberos 4 and 5:
+solaris9g+krb5+krb4:
+       $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} CC=gcc CC2=gcc \
+       "CFLAGS = -O -Usun -DSVR4 -DSOLARIS9 -DSTERMIOX -DSELECT -DFNFLOAT \
+       -DCK_CURSES -DCK_NEWTERM -DDIRENT -DHDBUUCP -DTCPSOCKET \
+       -DCK_AUTHENTICATION -DCK_KERBEROS -DKRB5 -DKRB4 -DKRB524 \
+       -D_FILE_OFFSET_BITS=64 \
+       -DCK_ENCRYPTION -DCK_DES -DCK_CAST -DBIGBUFOK \
+       $(K5INC) $(K5INC)/krb5 $(KFLAGS)" \
+       "LIBS= $(K5LIB) -ltermlib -lsocket -lnsl -lm -lresolv \
+       -lkrb4 -lcrypto -lgssapi_krb5 -lkrb5 -lcom_err -lk5crypto \
+       -ldes $(LIBS)"
+
+#Solaris 9 with gcc + Kerberos 5.
+#Columbia Only - libdes has a version number in its name.
+#In the general case, change -ldes425 to -des.
+#If you have Kerberos 1.4 or later and and krb5_init_ets can't be found
+#at link time, add -DNO_KRB5_INIT_ETS.
+cu-solaris9g+krb5:
+       @case `openssl version` in \
+         *0.9.7*) OPENSSLOPTION="-DOPENSSL_097" ;; \
+         *0.9.8*) OPENSSLOPTION="-DOPENSSL_098" ;; \
+         *1.[0-9].[0-9]*) OPENSSLOPTION="-DOPENSSL_100" ;; \
+         *) OPENSSLOPTION="" ;; \
+       esac ; \
+       HAVE_DES=''; \
+       DES_LIB=''; \
+       if ls $(SSLLIB)/libdes* > /dev/null 2> /dev/null; then \
+             DES_LIB='-ldes425'; \
+             HAVE_DES='-DCK_DES -DLIBDES'; \
+              echo "HAVE DES"; \
+           else echo "NO DES"; \
+       fi; \
+       GSSAPILIB=''; \
+       K5DIR=`echo $(K5LIB) | sed 's|-L||'`; \
+       echo K5DIR=$$K5DIR; \
+       if ls $$K5DIR/libgssapi_krb5* > /dev/null 2> /dev/null; then \
+              GSSAPILIB='-lgssapi_krb5'; \
+          else GSSAPILIB='-lgssapi'; \
+        fi; \
+       $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} CC=gcc CC2=gcc \
+       "CFLAGS = -O -Usun -DSVR4 -DSOLARIS9 -DSTERMIOX -DSELECT -DFNFLOAT \
+       -DCK_CURSES -DCK_NEWTERM -DDIRENT -DHDBUUCP -DTCPSOCKET  -DBIGBUFOK \
+       -DCK_AUTHENTICATION -DCK_KERBEROS -DKRB5 -DCK_ENCRYPTION -DCK_CAST \
+       $$OPENSSLOPTION $$HAVE_DES $(K5INC) $(K5INC)/krb5 $(KFLAGS)" \
+       "LIBS= $(K5LIB) -ltermlib -lsocket -lnsl -lm -lresolv -lcrypto \
+       $$GSSAPILIB -lkrb5 -lcom_err -lk5crypto $$DES_LIB $(LIBS)"
+
+#Solaris 9 with gcc + OpenSSL + Kerberos 5 + Krb4 + Shadow + Long files
+#Columbia Only, mainly because of the -R clause.
+# (I tried adding -DCK_SRP and -lsrp but got a lot of symbol referencing
+#  errors at link time.)
+cu-solaris9g+krb5+krb4+openssl+shadow+pam+zlib:
+       $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} CC=gcc CC2=gcc \
+       "CFLAGS = -O -Usun -DSVR4 -DSOLARIS -DSTERMIOX -DSELECT -DFNFLOAT \
+       -DSOLARIS9 -D_FILE_OFFSET_BITS=64 -DBIGBUFOK \
+       -DCK_CURSES -DCK_NEWTERM -DDIRENT -DHDBUUCP -DTCPSOCKET \
+       -DCK_AUTHENTICATION -DCK_KERBEROS -DKRB5 -DKRB4 -DKRB524 \
+       -DCK_ENCRYPTION -DCK_SSL -DCK_DES -DCK_CAST -DNO_KRB5_INIT_ETS \
+       -DZLIB -DCK_PAM -DCK_SHADOW -DLIBDES -DOPENSSL_097 -DCK_FORWARD_X \
+       $(K5INC) $(K5INC)/krb5 $(SSLINC) $(KFLAGS)" \
+       "LIBS= $(K5LIB) $(SSLLIB) -R/opt/local/lib -ltermlib -lsocket -lnsl \
+       -lm -lresolv -lkrb4 -lssl -lcrypto -lgssapi_krb5 -lkrb5 \
+       -lcom_err -lk5crypto -lpam -ldes425 -lz $(LIBS)"
+
+#Solaris 9, 10, or 11 with gcc...  
+#Uses streams PTYs rather than BSD ptys as in C-Kermit 8.0 and earlier.
+#This target is chained to be the secure solaris9g+xxx targets below.
+solaris9g solaris10g solaris11g:
+       @echo 'Making C-Kermit $(CKVER) for Solaris 9 or later with gcc'
+       @case `uname -r` in \
+         5.9) SOLARISVERSION="-DSOLARIS9" ;; \
+         5.10) SOLARISVERSION="-DSOLARIS10" ;; \
+         5.11) SOLARISVERSION="-DSOLARIS11" ;; \
+         *) SOLARISVERSION="-DSOLARIS" ;; \
+       esac ; \
+       $(MAKE) "MAKE=$(MAKE)" CC="gcc -m32" CC2="gcc -m32" xermit \
+       KTARGET=$${KTARGET:-$(@)} \
+       "CFLAGS = -g -O -Usun -DSVR4 $$SOLARISVERSION -DUSE_STRERROR \
+       -DSTERMIOX -DSELECT -DFNFLOAT -DCK_PAM -DCK_SHADOW -funsigned-char \
+       -DHAVE_STREAMS -DHAVE_GRANTPT -DHAVE_PTSNAME -DPUSH_PTEM \
+       -DPUSH_LDTERM -DPUSH_TTCOMPAT \
+       -DCK_CURSES -DCK_NEWTERM -DDIRENT -DHDBUUCP -DTCPSOCKET \
+       -D_FILE_OFFSET_BITS=64 $(KFLAGS)" \
+       "LIBS= -ltermlib -lsocket -lnsl -lm -lresolv -lpam $(LIBS)"
+
+#Solaris 9, 10, or 11 with Sun CC, 64 bit build.
+#DON'T USE THIS ONE ON PC ARCHITECTURE - It compiles and links but won't run.
+#OK: 2009/11/16 (but not tested on Solaris 11)
+solaris9_64 solaris10_64 solaris11_64:
+       @echo 'Making C-Kermit $(CKVER) for Solaris 9/10/11 64-bit Sun CC'
+       $(MAKE) "MAKE=$(MAKE)" solaris9 KTARGET=$${KTARGET:-$(@)} \
+       "KFLAGS=-xarch=generic64 -U_FILE_OFFSET_BITS -DNOARROWKEYS" \
+       "LNKFLAGS= -xarch=generic64"
+
+#Solaris 9, 10, or 11 with gcc, 64 bit build.
+#Peeking inside FILE struct not allowed in 64-bit world.
+#DON'T USE THIS ONE ON PC ARCHITECTURE - It compiles and links but won't run.
+#OK: 2009/09/25 (but not tested on Solaris 11)
+solaris9g64 solaris10g64 solaris11g64:
+       @echo 'Making C-Kermit $(CKVER) for Solaris 9++ with gcc 64-bit'
+       @case `uname -r` in \
+         5.9) SOLARISVERSION="-DSOLARIS9" ;; \
+         5.10) SOLARISVERSION="-DSOLARIS10" ;; \
+         5.11) SOLARISVERSION="-DSOLARIS11" ;; \
+         *) SOLARISVERSION="-DSOLARIS" ;; \
+       esac ; \
+       $(MAKE) "MAKE=$(MAKE)" CC="gcc -m64" CC2="gcc -m64" xermit \
+       KTARGET=$${KTARGET:-$(@)} \
+       "CFLAGS = -g -O -Usun -funsigned-char \
+       -DSVR4 $$SOLARISVERSION -DNOARROWKEYS \
+       -DSTERMIOX -DSELECT -DFNFLOAT -DUSE_STRERROR -DCK_PAM -DCK_SHADOW \
+       -DHAVE_STREAMS -DHAVE_GRANTPT -DHAVE_PTSNAME -DPUSH_PTEM \
+       -DPUSH_LDTERM -DPUSH_TTCOMPAT \
+       -DCK_CURSES -DCK_NEWTERM -DDIRENT -DHDBUUCP -DTCPSOCKET $(KFLAGS)" \
+       "LIBS= -ltermlib -lsocket -lnsl -lm -lresolv -lpam $(LIBS)"
+
+#Solaris 9, 10, or 11 with SunPro CC
+#Uses streams PTYs rather than BSD ptys as in C-Kermit 8.0 and earlier.
+#This target is chained to by the secure targets below.
+solaris9 solaris10 solaris11:
+       @echo 'Making C-Kermit $(CKVER) for Solaris 9 or later with Sun CC'
+       @case `uname -r` in \
+         5.9) SOLARISVERSION="-DSOLARIS9" ;; \
+         5.10) SOLARISVERSION="-DSOLARIS10" ;; \
+         5.11) SOLARISVERSION="-DSOLARIS11" ;; \
+         *) SOLARISVERSION="-DSOLARIS" ;; \
+       esac ; \
+       $(MAKE) "MAKE=$(MAKE)" xermit KTARGET=$${KTARGET:-$(@)} \
+       "CFLAGS = -O -Usun -DSVR4 $$SOLARISVERSION -DUSE_STRERROR \
+       -DSTERMIOX -DSELECT -DFNFLOAT -DCK_PAM -DCK_SHADOW \
+       -DHAVE_STREAMS -DHAVE_GRANTPT -DHAVE_PTSNAME -DPUSH_PTEM \
+       -DPUSH_LDTERM -DPUSH_TTCOMPAT \
+       -DCK_CURSES -DCK_NEWTERM -DDIRENT -DHDBUUCP -DTCPSOCKET \
+       -D_FILE_OFFSET_BITS=64 $(KFLAGS)" \
+       "LIBS= $(LIBS) -ltermlib -lsocket -lnsl -lm -lresolv -lpam"
+
+# Solaris 9, 10, or 11 with OpenSSL built with Sun CC.
+# Here's an example of how to invoke this target in case your OpenSSL
+# headers and libraries are not in /usr/local:
+#
+# make solaris9+openssl "SSLINC=" "SSLLIB=" \
+#  "KFLAGS= -I/opt/openssl-0.9.8k/include -L/opt/openssl-0.9.8k/lib"
+#
+# Don't use 'make -e' because that inhibits passing of KFLAGS to
+# the base (solaris9) target.
+#
+#OK: 2011/06/14
+solaris9+ssl solaris10+ssl solaris11+ssl \
+solaris9+openssl solaris10+openssl solaris11+openssl:
+       @echo 'Making C-Kermit $(CKVER) for Solaris 9/10/11 with OpenSSL: cc'
+       @case `openssl version` in \
+         *0.9.7*) OPENSSLOPTION="-DOPENSSL_097" ;; \
+         *0.9.8*) OPENSSLOPTION="-DOPENSSL_098" ;; \
+         *1.[0-9].[0-9]*) OPENSSLOPTION="-DOPENSSL_100" ;; \
+         *) OPENSSLOPTION="" ;; \
+       esac ; \
+       HAVE_DES=''; \
+       DES_LIB=''; \
+       if ls $(SSLLIB)/libdes* > /dev/null 2> /dev/null; then \
+             DES_LIB='-ldes425'; \
+             HAVE_DES='-DCK_DES -DLIBDES'; \
+              echo "HAVE DES"; \
+           else echo "NO DES"; \
+       fi; \
+       $(MAKE) "MAKE=$(MAKE)" solaris9 KTARGET=$${KTARGET:-$(@)} \
+       "KFLAGS=-DCK_AUTHENTICATION -DCK_SSL -DZLIB $$HAVE_DES \
+       -DNO_DCL_INET_ATON $$OPENSSLOPTION $(SSLINC) $(KFLAGS)" \
+       "LIBS= $(SSLLIB) -lz -lssl $$DES_LIB -lcrypto  $(LIBS)"
+
+# Solaris 9 or later with OpenSSL, built with gcc.
+# Remove -DNO_DCL_INET_ATON if inet_aton comes up missing.  This target nicely
+# chains to the solaris{9,10,11}g target but for some reason it doesn't work if
+# you add the -DFORWARD_X option, thus the solaris9g+openssl+forward_x target.
+#
+#OK: 2009/09/25 (but not tested on Solaris 11)
+solaris9g+ssl solaris10g+ssl solaris11g+ssl \
+solaris9g+openssl solaris10g+openssl solaris11g+openssl:
+       @echo 'Making C-Kermit $(CKVER) for Solaris 9/10/11 with OpenSSL: gcc'
+       @case `openssl version` in \
+         *0.9.7*) OPENSSLOPTION="-DOPENSSL_097" ;; \
+         *0.9.8*) OPENSSLOPTION="-DOPENSSL_098" ;; \
+         *1.[0-9].[0-9]*) OPENSSLOPTION="-DOPENSSL_100" ;; \
+         *) OPENSSLOPTION="" ;; \
+       esac ; \
+       HAVE_DES=''; \
+       DES_LIB=''; \
+       if ls $(SSLLIB)/libdes* > /dev/null 2> /dev/null; then \
+             DES_LIB='-ldes425'; \
+             HAVE_DES='-DCK_DES -DLIBDES'; \
+              echo "HAVE DES"; \
+           else echo "NO DES"; \
+       fi; \
+       $(MAKE) "MAKE=$(MAKE)" solaris9g KTARGET=$${KTARGET:-$(@)} \
+       "KFLAGS=-DCK_AUTHENTICATION -DCK_SSL -DZLIB $$HAVE_DES \
+       -DNO_DCL_INET_ATON $$OPENSSLOPTION $(SSLINC) $(KFLAGS)" \
+       "LIBS= $(SSLLIB) -lz -lssl $$DES_LIB -lcrypto  $(LIBS)"
+
+# Solaris 9 or later with gcc + OpenSSL + Shadow (32-bit).
+# Remove -DNO_DCL_INET_ATON if inet_aton comes up missing.
+# Includes long file support - not sure if this was available before Solaris 9.
+# Detects Solaris version automatically.
+#
+solaris9g+openssl+forward_x:
+       @echo 'Making C-Kermit $(CKVER) for Solaris 9 or later with OpenSSL...'
+       @case `openssl version` in \
+         *0.9.7*) OPENSSLOPTION="-DOPENSSL_097" ;; \
+         *0.9.8*) OPENSSLOPTION="-DOPENSSL_098" ;; \
+         *1.[0-9].[0-9]*) OPENSSLOPTION="-DOPENSSL_100" ;; \
+         *) OPENSSLOPTION="" ;; \
+       esac ; case `uname -r` in \
+         5.9) SOLARISVERSION="-DSOLARIS9" ;; \
+         5.10) SOLARISVERSION="-DSOLARIS10" ;; \
+         5.11) SOLARISVERSION="-DSOLARIS11" ;; \
+         *) SOLARISVERSION="-DSOLARIS" ;; \
+       esac ; \
+       $(MAKE) xermit  KTARGET=$${KTARGET:-$(@)} CC=gcc CC2=gcc \
+       "CFLAGS = -g -O -Usun -DSVR4 $$SOLARISVERSION \
+       -DHAVE_STREAMS -DHAVE_GRANTPT -DHAVE_PTSNAME -DPUSH_PTEM \
+       -DPUSH_LDTERM -DPUSH_TTCOMPAT \
+       -DSTERMIOX -DSELECT -DFNFLOAT -DBIGBUFOK -D_FILE_OFFSET_BITS=64 \
+       -DCK_AUTHENTICATION -DCK_SSL -DCK_PAM -DCK_SHADOW -DZLIB -DLIBDES \
+       -DFORWARD_X $$OPENSSLOPTION $(SSLINC) $(KFLAGS)" \
+       "LIBS= $(SSLLIB) -lpam -ldes425 -lz -ltermlib \
+       -lsocket -lnsl -lm -lresolv -lssl -lcrypto -lpam -lz $(LIBS)"
 
-#Solaris 2.4, SunPro compiler, with SunLink X.25 support.
-#This will only run if user has /opt/SUNWconn/lib/libsockx25.so.1
-#exists and can be dynamically linked.
-solaris24x25:
-       @echo 'Making C-Kermit $(CKVER) for Solaris 2.4+X.25 with SunPro cc...'
-       $(MAKE) wermit KTARGET=$${KTARGET:-$(@)} \
-       "CFLAGS = -O -i -Usun -DSVR4 -DSOLARIS -DSOLARIS24 -DDIRENT -DNOLEARN \
-       -DSUNX25 -DTCPSOCKET -DHDBUUCP -DFNFLOAT -DPOSIX_CRTSCTS \
-       -DSELECT -DCK_CURSES -DCK_NEWTERM -DSTERMIOX $(KFLAGS)" \
-       "LNKFLAGS = -s" \
-       "LIBS= -ltermlib -L/opt/SUNWconn/lib -R/opt/SUNWconn/lib \
-       -lsockx25 -lsocket -lnsl -lm -lresolv"
+# These two should be folded in with the ones just above.
 
-#Solaris 2.5, SunPro compiler, with SunLink X.25 support.
-solaris25x25:
-       @echo 'Making C-Kermit $(CKVER) for Solaris 2.5+X.25 with SunPro cc...'
-       $(MAKE) wermit KTARGET=$${KTARGET:-$(@)} \
-       "CFLAGS = -O -i -Usun -DSVR4 -DSOLARIS25 -DDIRENT -DSUNX25 \
-       -DTCPSOCKET -DHDBUUCP -DSELECT -DCK_CURSES \
-       -DCK_NEWTERM -DSTERMIOX -DFNFLOAT -DPOSIX_CRTSCTS -DNOLEARN \
-       -I/opt/SUNWconn/include $(KFLAGS)" \
-       "LIBS= -ltermlib -L/opt/SUNWconn/lib -R/opt/SUNWconn/lib \
-       -lsockx25 -lsocket -lnsl -lm -lresolv"
+#Solaris 9 with gcc 3.1 + OpenSSL (32-bit)
+solaris9g+openssl+zlib+pam+shadow:
+       $(MAKE) "MAKE=$(MAKE)" solaris2xg32+openssl+zlib+pam+shadow \
+       KTARGET=$${KTARGET:-$(@)} \
+       "KFLAGS=-DSOLARIS9 -DUSE_STRERROR $(KFLAGS)"
 
-#Solaris 2.6, SunPro compiler, with SunLink X.25 support.
-solaris26x25:
-       @echo 'Making C-Kermit $(CKVER) for Solaris 2.6+X.25 with SunPro cc...'
-       $(MAKE) wermit KTARGET=$${KTARGET:-$(@)} \
-       "CFLAGS = -O -i -Usun -DSVR4 -DSOLARIS26 -DDIRENT -DSUNX25 \
-       -DTCPSOCKET -DHDBUUCP -DSELECT -DCK_CURSES -DCK_PAM -DCK_SHADOW \
-       -DCK_NEWTERM -DSTERMIOX -DFNFLOAT -DPOSIX_CRTSCTS -DNOLEARN \
-       -I/opt/SUNWconn/include $(KFLAGS)" \
-       "LIBS= -ltermlib -L/opt/SUNWconn/lib -R/opt/SUNWconn/lib \
-       -lsockx25 -lsocket -lnsl -lm -lresolv -lpam"
+#Solaris 10 with gcc 3.1 + OpenSSL (32-bit)
+solaris10g+openssl+zlib+pam+shadow:
+       $(MAKE) "MAKE=$(MAKE)" solaris2xg32+openssl+zlib+pam+shadow \
+       KTARGET=$${KTARGET:-$(@)} \
+       "KFLAGS=-DSOLARIS10 -DUSE_STRERROR $(KFLAGS)"
 
-#The following sunosxxx entries are for debugging and testing only.
+#The following (old, old) sunosxxx entries are for debugging and testing only.
 
 sunos41x:
        $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} \
@@ -4156,6 +4565,7 @@ uw21iksd:
        "KFLAGS=-DCK_SHADOW $(KFLAGS)" "LIBS= -lgen"
 
 #UnixWare 7 with tc[gs]etspeed() high serial speeds & select()-based CONNECT
+#and as of C-Kermit 8.0.212, large file support (LFS).
 #NOTE: This is the one we use.
 unixware7t:
        @echo 'Making C-Kermit $(CKVER) for UnixWare 7 with POSIX i/o...'
@@ -4163,7 +4573,7 @@ unixware7t:
        "CFLAGS = -O -DUNIXWARE -DSELECT -DSVR4 -DDIRENT -DHDBUUCP -DBIGBUFOK \
        -DFNFLOAT -DNOGETUSERSHELL -DSTERMIOX -DCK_CURSES -DTCPSOCKET -DPOSIX \
        -DUW7 -DUSETCSETSPEED -DCK_NEWTERM -DNOLSTAT -DDCLTIMEVAL \
-       -DNEEDMDMDEFS $(KFLAGS)" \
+       -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -DNEEDMDMDEFS $(KFLAGS)" \
        "LIBS=-lsocket -lnsl -lcurses -ltermcap -lcrypt -lm -lresolv $(LIBS)" \
        "LNKFLAGS = -s"
 
@@ -4216,7 +4626,7 @@ ou8:
        KTARGET=$${KTARGET:-$(@)}
 
 #UnixWare 7 with OpenSSL
-uw7ssl:
+uw7ssl uw7+ssl:
        @echo 'Making C-Kermit $(CKVER) for UnixWare 7 and OpenSSL...'
        $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} \
        "CFLAGS = -O -DCK_AUTHENTICATION -DCK_SSL -DCK_SHADOW \
@@ -4500,7 +4910,7 @@ irix53x:
 #Silicon Graphics IRIX 6.[024] common stuff.
 #Yellow Pages and Curses support included.
 #IRIX version 6.0 and later runs only ELF binaries.
-#Depends on code changes in ckudeb.h that make -DIRIX6x define all
+#Depends on code changes in ckcdeb.h that make -DIRIX6x define all
 #lower IRIX6x values and IRIX51.
 irix6x:
        @echo 'Includes fullscreen file display and Yellow Pages...'
@@ -4550,15 +4960,46 @@ irix64:
 irix64gcc:
        @echo 'Making C-Kermit $(CKVER) for Silicon Graphics IRIX 6.4 gcc'
        $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} "CC = gcc" "CC2 = gcc" \
-       "CFLAGS= -DSVR4 -DIRIX64 -DCK_CURSES -DTCPSOCKET -DNOCOTFMC \
+       "CFLAGS= -DSVR4 -DIRIX64 -DDIRENT -DHDBUUCP -DNOGETUSERSHELL \
+       -DSELECT -DPWID_T=uid_t -DTCPSOCKET -DNOCOTFMC \
+       -DCK_ANSIC -DCK_RTSCTS -DCK_NEWTERM -DCK_CURSES \
        $(KFLAGS) -O" "LIBS= -lcurses -ltermcap -lcrypt"
 
 #Note the new Optimization option syntax for MIPSpro CC 7.2.1.2m.
+#See note on irix65gcc target about Large File Support (LFS).
 irix65:
        @echo 'Making C-Kermit $(CKVER) for SGI IRIX 6.5'
        @$(MAKE) "MAKE=$(MAKE)" LNKFLAGS="-Wl,-woff,84" \
-       "KFLAGS=-DIRIX65 -DCK_RTSCTS -OPT:Olimit=0 -woff 1110,1552,1174 \
-       $(KFLAGS)" \
+       "KFLAGS=-DIRIX65 -D_LARGEFILE_SOURCE -DCK_RTSCTS -OPT:Olimit=0 \
+       -woff 1110,1552,1174 $(KFLAGS)" \
+       irix6x KTARGET=$${KTARGET:-$(@)}
+
+#Build for those that have GCC instead of MIPSpro.
+#
+# Large File Support note: use the define _LARGEFILE_SOURCE to enable support
+# for files larger than 2GB.  This may work on releases of Irix prior to
+# 6.5.xx.  To verify, check the man page for fstat and verify that off_t is a
+# 64 bit value for an -n32 build.  Also check the manpage for fseek and ftell
+# to verify that the fseek64 and ftell64 functions are provided.  If so, then
+# LFS support should work and you can try adding -D_LARGEFILE_SOURCE to CFLAGS
+# for your selected Irix target.
+#
+irix65gcc:
+       @echo 'Making C-Kermit $(CKVER) for SGI IRIX 6.5 with gcc'
+       $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} \
+       "CC = gcc" "CC2 = gcc" \
+       "CFLAGS= -DSVR4 -DIRIX65 -D_LARGEFILE_SOURCE -DDIRENT -DHDBUUCP \
+       -DNOGETUSERSHELL -DSELECT -DPWID_T=uid_t -DTCPSOCKET -DNOCOTFMC \
+       -DCK_ANSIC -DCK_RTSCTS -DCK_NEWTERM -DCK_CURSES \
+       $(KFLAGS) -O" "LIBS= -lcurses"
+
+# The 64-bit IRIX target works but presumably is no longer needed given the
+# large file support in the more portable and compact 32-bit version.
+irix65_64:
+       @echo 'Making C-Kermit $(CKVER) 64-bit for SGI IRIX 6.5'
+       @$(MAKE) "MAKE=$(MAKE)" LNKFLAGS="-Wl,-woff,84" \
+       "KFLAGS=-DIRIX65 -64 -DCK_RTSCTS -OPT:Olimit=0 -woff 1110,1552,1174 \
+       -DCK_64BIT $(KFLAGS)" \
        irix6x KTARGET=$${KTARGET:-$(@)}
 
 #Dumb down to MIPS-2 if building on R5000 or higher...
@@ -4569,6 +5010,23 @@ irix65mips2:
        -woff 1110,1552,1174 $(KFLAGS)" \
        irix6x KTARGET=$${KTARGET:-$(@)}
 
+#Special target that adds srp, ssl, and zlib support.  This requires
+#that you have pkgsrc installed instead of Irix Freeware.  See
+#NetBSD.org for pkgsrc for Irix.  You will need to BUILD the srp_client
+#package yourself.  Install it manually using the directions found
+#in the netbsds+ssl+srp+zlib target comments.
+irix65+ssl+srp+zlib:
+       @echo 'Making C-Kermit $(CKVER) for IRIX 6.5 with gcc and SSL SRP ZLIB'
+       $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} \
+       "CC = gcc" "CC2 = gcc" \
+       "CFLAGS= -DIRIX65 -DSVR4 -DDIRENT -DHDBUUCP -DNOGETUSERSHELL -DSELECT \
+       -DTCPSOCKET -DNOCOTFMC -DCK_NEWTERM -DPWID_T=uid_t -DCK_ANSIC \
+       -I/usr/pkg/include -DCK_AUTHENTICATION -DCK_SRP -DPRE_SRP_1_4_5 \
+       -DCK_RTSCTS -DCK_NCURSES -DCK_ENCRYPTION -DCK_CAST -DCK_DES -DCK_SSL \
+       -DLIBDES -DZLIB -DFNFLOAT -I/usr/pkg/include/openssl $(KFLAGS) -O" \
+       "LIBS= -L/usr/pkg/lib -rpath /usr/pkg/lib -lncurses -lsrp -lgmp -ldes \
+       -lssl -lkrypto -lcrypto -lcrypt -lz -lm"
+
 irix6x+krb5:
        @echo 'Includes fullscreen file display and Yellow Pages...'
        @echo 'Add -mips<n> to specify a particular hardware target.'
@@ -4850,10 +5308,10 @@ unisys5r2:
 sys5hdb:
        $(MAKE) "MAKE=$(MAKE)" sys3hdb
 
-#Create the common header line for all hpux[5-10]* entries. This extra entry is
-#here because our header message length may differ for each C-Kermit version.
-#Don't use 'fold -s' for HP-UX 5.x - 7.x! This option is there only since
-#HP-UX 8.0!
+#Create the common header line for all hpux[5-11]* entries and above. This 
+#extra entry is here because our header message length may differ for each 
+#C-Kermit version. Don't use 'fold -s' for HP-UX 5.x - 7.x! This option is 
+#available only for HP-UX 8.0 and above!
 hpux-header:
        @HPUX=`uname -r | sed -e 's/^[^1-9]*//' -e 's/\.00$$/.0/'` ; \
        [ "$(MESSAGE0)" ] && MESSAGE1="$(MESSAGE0)" ; \
@@ -4868,6 +5326,7 @@ hpux-header:
 # Peter E's updated HP-UX 5.xx entries Oct 2001.
 
 #HP-9000 500 HP-UX 5.xx, no TCP/IP.
+# Last known successful build: C-Kermit 8.0.206 2002/20/27.
 hpux0500:
        @MESSAGE0="no TCP/IP and no compiler optimization";\
        MESSAGE0=$${MESSAGE1:-$$MESSAGE0} \
@@ -4875,72 +5334,90 @@ hpux0500:
        $(MAKE) wermit KTARGET=$${KTARGET:-$(@)} \
        "CFLAGS = -DHPUX -DHPUX5 -DHPUXPRE65 -DNOREDIRECT -DDCLGETCWD \
        -DNOGETUSERSHELL -DNOGFTIMER -DNOSYSLOG -DNOTOMACROS -DNOLSTAT \
-       -DNOSYMLINK -DNOINITGROUPS -DNOUNICODE -DNOLEARN $(KFLAGS)" \
-       "LIBS = $(LIBS)" "LNKFLAGS = "
+       -DNOSYMLINK -DNOINITGROUPS -DNOUNICODE -DNOLEARN -DNOLONGLONG \
+       $(KFLAGS)" "LIBS = $(LIBS)" "LNKFLAGS = "
 
 #HP-9000 500 HP-UX 5.21 with Wollongong WIN/TCP 1.2 TCP/IP.
 #Requires /usr/wins/usr/include and /usr/lib/libnet.a from Wollongong.
 #Optimization skipped - takes forever. Really.
 # WARNING: this doesn't work if a file called "hpux0500" is on the disk.
+# Last known successful build: C-Kermit 8.0.206 2002/20/27.
 hpux0500wintcp:
        @MESSAGE1="with WIN/TCP but without any extra compiler optimization" \
        $(MAKE) hpux0500 KTARGET=$${KTARGET:-$(@)} \
        "KFLAGS = -DTCPSOCKET -DHPUX5WINTCP -DINADDRX -DNO_DNS_SRV -DNOMHHOST \
-       -DNOHADDRLIST -I/usr/wins/usr/include $(KFLAGS)" \
+       -DNOHADDRLIST -DNOLONGLONG -I/usr/wins/usr/include $(KFLAGS)" \
        "LIBS = /usr/lib/libnet.a"
 
 #HP-UX 6.5, short filenames, no network and no curses support.
 #ckcpro, ckuusr, ckuus3 and others are broken out because they make the
-#optimizer run away.  Note that xermit target does not work with this one!
-#If you get compiler warnings like 'Switch table overflow' increase the '...'
-#value in '-Wc,-Nw...'!
+#optimizer run away.  Note that the XERMIT target does not work with HP-UX 6.5!
+#
+#If you get compiler warnings like:
+#'Switch table overflow. Try the -Wc,-Nw option.' (for ckcuni.c, or
+#other files) increase the '...' value in '-Wc,-Nw...'! The default maximum
+#switch table stack (-Nw) is 250 table entries. ckcuni.c from Oct 16 2009
+#needs 257 table entries (C-Kermit Version "9.0.299").
+#OK: 2010/03/26
 hpux0650:
        @$(MAKE) hpux-header
-       @echo 'supporting: NO long filenames, NO network${MESSAGE2}.'
+       @MESSAGE2=$${MESSAGE2:-'and NO network'}; \
+       echo "supporting: NO long filenames $$MESSAGE2."
 
        $(MAKE) KTARGET=$${KTARGET:-$(@)} \
-               ckuusr.$(EXT) ckuus3.$(EXT) ckuus4.$(EXT) ckuus5.$(EXT) \
-               ckuus6.$(EXT) ckuxla.$(EXT) ckcpro.$(EXT) \
+               ckuus3.$(EXT) ckuus4.$(EXT) ckuus5.$(EXT) ckuus6.$(EXT) \
+               ckuusr.$(EXT) ckuxla.$(EXT) ckcftp.$(EXT) ckcpro.$(EXT) \
        "CFLAGS = -DHPUX -DHPUX6 -DSIG_V -DNOSYSLOG -DNOSELECT -DFNFLOAT \
-       -DDCLGETCWD -DNOGETUSERSHELL -DNO_DNS_SRV -DNOLEARN $(KFLAGS) \
-       -Wc,-Nw260"
+       -DDCLGETCWD -DNOGETUSERSHELL -DNO_DNS_SRV -DNOLEARN -DNOLONGLONG \
+       $(KFLAGS)"
 
        $(MAKE) wermit KTARGET=$${KTARGET:-$(@)} \
        "CFLAGS = -DHPUX -DHPUX6 -DSIG_V -DNOSYSLOG -DNOSELECT -DFNFLOAT \
-       -DDCLGETCWD -DNOGETUSERSHELL -DNO_DNS_SRV -DNOLEARN $(KFLAGS) \
-       -Wc,-Nw260 $(OFLAGS)" "LNKFLAGS = -s" "LIBS = -lm $(LIBS)"
+       -DDCLGETCWD -DNOGETUSERSHELL -DNO_DNS_SRV -DNOLEARN -DNOLONGLONG \
+       $(KFLAGS) -Wc,-Nw260 $(OFLAGS)" "LNKFLAGS = -s" "LIBS = -lm $(LIBS)"
 
 #Exactly as above, plus curses:
+#OK: 2009/10/06
 hpux0650c:
-       @MESSAGE2=", but with curses" \
+       @MESSAGE2="and NO network but with curses" \
        $(MAKE) hpux0650 KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS= -DCK_CURSES $(KFLAGS)" \
-       "LIBS= -lcurses"
+       "KFLAGS = -DCK_CURSES $(KFLAGS)" \
+       "LIBS = -lcurses"
 
 #Exactly as above, plus curses + network:
-#(doesn't work -- HP-UX 6 lacks the FD_SET macros -- this can be addressed
-
+#OK: 2009/10/02
 hpux0650tcpc:
-       @MESSAGE2=", but with curses and with tcp/ip" \
+       @MESSAGE2="but with curses and with TCP/IP" \
        $(MAKE) hpux0650 KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS= -DCK_CURSES -DTCPSOCKET -DNOHADDRLIST $(KFLAGS)" \
-       "LIBS= -lcurses"
+       "KFLAGS=-DCK_CURSES -DTCPSOCKET -DNOHADDRLIST \
+       -DINTSELECT -DNOCKGETFQHOST $(KFLAGS)" \
+       "LIBS=-lcurses"
 
 #Exactly as hpux0650 but with compiler optimization:
+#OK: 2009/10/06
 hpux0650o:
        @MESSAGE1="with compiler optimization" \
        $(MAKE) hpux0650 KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS= $(KFLAGS)" "OFLAGS = -O"
+       "KFLAGS = $(KFLAGS)" "OFLAGS = -O"
 
 #Exactly as hpux0650c but with compiler optimization:
+#OK: 2009/10/06
 hpux0650oc:
        @MESSAGE1="with compiler optimization" \
        $(MAKE) hpux0650c KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS= $(KFLAGS)" "OFLAGS = -O"
+       "KFLAGS = $(KFLAGS)" "OFLAGS = -O"
+
+#Exactly as hpux0650tcpc but with compiler optimization:
+#OK: 2009/10/06
+hpux0650otcpc:
+       @MESSAGE1="with compiler optimization" \
+       $(MAKE) hpux0650tcpc KTARGET=$${KTARGET:-$(@)} \
+       "KFLAGS = $(KFLAGS)" "OFLAGS = -O"
 
-#Take this as startup entry for all 'nonoptimized' files under HP-UX 7.x!
-#Make sure we doesn't call it with the '-O' option because this will blow up
+#Take this as startup entry for all 'non-optimized' files under HP-UX 7.x!
+#Make sure we don't call it with the '-O' option because this will blow up
 #the compiler!
+#OK: 2009/09/30
 hpux0700noopt:
        @case "$(CFLAGS)" in \
        *-O*) echo "Don't use CFLAGS= -O here!" ;; \
@@ -4952,8 +5429,12 @@ hpux0700noopt:
        esac
 
 #HP-UX 7.0, no long filenames, no network support, no curses.
-#If you get compiler warnings like 'Switch table overflow' increase the '...'
-#value in '-Wc,-Nw...'!
+#If you get compiler warnings like:
+#'Switch table overflow. Try the -Wc,-Nw option.' (for ckcuni.c, or
+#other files) increase the '...' value in '-Wc,-Nw...'! The default maximum
+#switch table stack (-Nw) is 250 table entries. ckcuni.c from Oct 16 2009
+#needs 257 table entries (C-Kermit Version "9.0.299").
+#OK: 2010/10/26
 hpux0700sf:
        @$(MAKE) hpux-header
        @echo 'supporting: NO long filenames, NO network, NO curses.'
@@ -4967,14 +5448,22 @@ hpux0700sf:
        "LNKFLAGS = -s" "LIBS = -lm $(LIBS)"
 
 #Exactly as hpux0700sf but with compiler optimization:
+#OK: 2009/09/30
 hpux0700osf:
        @MESSAGE1="with compiler optimization" \
        $(MAKE) hpux0700sf KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS= $(KFLAGS)" "OFLAGS = -O"
+       "KFLAGS = $(KFLAGS)" "OFLAGS = -O"
 
 #HP-UX 7.0, short filenames, but with tcp/ip and curses.
 #To use this, you must have bought the ARPA Services Product from HP, and you
 #must have /usr/lib/libBSD.a.
+#
+#If you get compiler warnings like:
+#'Symbol table overflow. Try the -Wc,-Ns option.' (as for ckuus4.c or
+#other files) increase the '...' value in '-Wc,-Ns...'! The default maximum
+#symbol table size (-Ns) is 2000 table entries. ckuus4.c from Mar 12 2010
+#needs 2031 table entries (C-Kermit Version "9.0.299").
+#OK: 2020/03/24
 hpux0700sftcpc:
        @$(MAKE) hpux-header
        @echo 'supporting: NO long filenames, \c'
@@ -4982,23 +5471,32 @@ hpux0700sftcpc:
        $(MAKE) hpux0700noopt KTARGET=$${KTARGET:-$(@)} \
        "CFLAGS =  -DHPUXDEBUG -DHPUX -DHPUX7 -DTCPSOCKET -DSIG_V \
        -DCK_REDIR -DCK_RTSCTS -DCK_CURSES -DNOGETUSERSHELL -DFNFLOAT \
-       -DNO_DNS_SRV -DHDBUUCP -DLOCK_DIR=\\\"/usr/spool/uucp\\\" $(KFLAGS) \
-       -Wc,-Nw260"
+       -DNO_DNS_SRV -DHDBUUCP -DLOCK_DIR=\\\"/usr/spool/uucp\\\" \
+       -DNOLONGLONG $(KFLAGS) -Wc,-Nw260,-Ns2040"
 
        $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} \
        "CFLAGS =  -DHPUXDEBUG -DHPUX -DHPUX7 -DTCPSOCKET -DSIG_V \
        -DCK_REDIR -DCK_RTSCTS -DCK_CURSES -DNOGETUSERSHELL -DFNFLOAT \
-       -DNO_DNS_SRV -DHDBUUCP  -DLOCK_DIR=\\\"/usr/spool/uucp\\\" $(KFLAGS) \
-       -Wc,-Nw260 $(OFLAGS)" "LNKFLAGS = -s" "LIBS= -lm -lBSD -lcurses"
+       -DNO_DNS_SRV -DHDBUUCP -DLOCK_DIR=\\\"/usr/spool/uucp\\\" \
+       -DNOLONGLONG $(KFLAGS) -Wc,-Nw260,-Ns2040 $(OFLAGS)" \
+       "LNKFLAGS = -s" "LIBS = -lm -lBSD -lcurses"
 
 #Exactly as above but with compiler optimization:
+#OK: 2009/09/30
 hpux0700osftcpc:
        @MESSAGE1="with compiler optimization" \
        $(MAKE) hpux0700sftcpc KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS= $(KFLAGS)" "OFLAGS = -O"
+       "KFLAGS = $(KFLAGS)" "OFLAGS = -O"
 
 #HP 9000 series 300/800 HP-UX 7.0, long filenames, network support, HDB uucp,
 #but NO curses. See comments in hpux0700sftcpc about TCP/IP support.
+#
+#If you get compiler warnings like:
+#'Symbol table overflow. Try the -Wc,-Ns option.' (as for ckuus4.c or
+#other files) increase the '...' value in '-Wc,-Ns...'! The default maximum
+#symbol table size (-Ns) is 2000 table entries. ckuus4.c from Mar 12 2010
+#needs 2031 table entries (C-Kermit Version "9.0.299").
+#OK: 2010/03/24
 hpux0700lfn:
        @$(MAKE) hpux-header
        @echo 'supporting: long filenames, networking, HDB uucp$(MESSAGE2)...'
@@ -5006,33 +5504,36 @@ hpux0700lfn:
        "CFLAGS =  -DHPUXDEBUG -DHPUX -DHPUX7 -DTCPSOCKET -DSIG_V -DFNFLOAT \
        -DNOGETUSERSHELL -DNOSETBUF -DCK_REDIR -DCK_RTSCTS -DLONGFN \
        -DNO_DNS_SRV -DDIRENT -DHDBUUCP -DLOCK_DIR=\\\"/usr/spool/uucp\\\" \
-       $(KFLAGS) -Wc,-Nw260"
+       -DNOLONGLONG $(KFLAGS) -Wc,-Nw260,-Ns2040"
 
        $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} \
        "CFLAGS =  -DHPUXDEBUG -DHPUX -DHPUX7 -DTCPSOCKET -DSIG_V -DFNFLOAT \
        -DNOGETUSERSHELL -DNOSETBUF -DCK_REDIR -DCK_RTSCTS -DLONGFN \
        -DNO_DNS_SRV -DDIRENT -DHDBUUCP -DLOCK_DIR=\\\"/usr/spool/uucp\\\" \
-       $(KFLAGS) -Wc,-Nw260 \
-       $(OFLAGS)" "LNKFLAGS = -s" "LIBS = -lm -lBSD $(LIBS)"
+       -DNOLONGLONG $(KFLAGS) -Wc,-Nw260,-Ns2040 $(OFLAGS)" \
+       "LNKFLAGS = -s" "LIBS = -lm -lBSD $(LIBS)"
 
 #Exactly as above + curses.
+#OK: 2009/09/30
 hpux0700lfnc:
        @MESSAGE2=', curses' \
        $(MAKE) hpux0700lfn KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS= -DCK_CURSES $(KFLAGS)" \
-       "LIBS= -lcurses"
+       "KFLAGS = -DCK_CURSES $(KFLAGS)" \
+       "LIBS = -lcurses"
 
 #Exactly as above hpux0700lfn but with compiler optimization:
+#OK: 2009/09/30
 hpux0700olfn:
        @MESSAGE1="with compiler optimization" \
        $(MAKE) hpux0700lfn KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS= $(KFLAGS)" "OFLAGS = -O"
+       "KFLAGS = $(KFLAGS)" "OFLAGS = -O"
 
 #Exactly as above hpux0700lfnc but with compiler optimization:
+#OK: 2009/09/30
 hpux0700olfnc:
        @MESSAGE1="with compiler optimization" \
        $(MAKE) hpux0700lfnc KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS= $(KFLAGS)" "OFLAGS = -O"
+       "KFLAGS = $(KFLAGS)" "OFLAGS = -O"
 
 #HP 9000 Series 300 or 400, HP-UX 8.0, long filenames and TCP/IP support.
 #This one should also work on 700/800, but without PA-specific optimization.
@@ -5042,6 +5543,7 @@ hpux0700olfnc:
 #For HP-UX 8.0 on Motorola CPUs, you might have to reinstall your kernel with
 #maxdsiz >= 0x03000000.  But if physical memory is small, that still will not
 #help much.
+#OK: 2009/10/01
 hpux0800:
        @$(MAKE) hpux-header
        @MESSAGE3=$${MESSAGE3:='TCP/IP'}; \
@@ -5051,15 +5553,17 @@ hpux0800:
        "CFLAGS =  -DCK_REDIR -DHPUXDEBUG -DHPUX -DHPUX8 -DRENAME -DSIG_V \
        -DNOSETBUF -DDIRENT -DCK_RTSCTS -DSTERMIOX -DLONGFN -DTCPSOCKET \
        -DHDBUUCP  -DNO_DNS_SRV -DLOCK_DIR=\\\"/usr/spool/uucp\\\" -DFNFLOAT \
-       $(KFLAGS)"
+       -DNOLONGLONG $(KFLAGS)"
 
        $(MAKE) -B "CC=$(CC)" "CC2=$(CC2)" xermit KTARGET=$${KTARGET:-$(@)} \
        "CFLAGS =  -DCK_REDIR -DHPUXDEBUG -DHPUX -DHPUX8 -DRENAME -DSIG_V \
        -DNOSETBUF -DDIRENT -DCK_RTSCTS -DSTERMIOX -DLONGFN -DTCPSOCKET \
        -DHDBUUCP  -DNO_DNS_SRV -DLOCK_DIR=\\\"/usr/spool/uucp\\\" -DFNFLOAT \
-       $(KFLAGS) $(OFLAGS)" "LNKFLAGS = -s" "LIBS = -lm -lBSD $(LIBS)"
+       -DNOLONGLONG -DNODCLENDUSERSHELL $(KFLAGS) $(OFLAGS)" \
+       "LNKFLAGS = -s" "LIBS = -lm -lBSD $(LIBS)"
 
 #Exactly as above hpux0800 + curses.
+#OK: 2009/10/01
 hpux0800c:
        @MESSAGE2=', curses' \
        $(MAKE) hpux0800  KTARGET=$${KTARGET:-$(@)} \
@@ -5067,24 +5571,28 @@ hpux0800c:
 
 #HP 9000 HP-UX 8.0, no TCP/IP because /usr/lib/libBSD.a can't be found,
 #or TCP/IP header files missing.
+#OK: 2009/10/01
 hpux0800notcp:
        @MESSAGE3='NO network, NO curses' \
        $(MAKE) "MAKE=$(MAKE)" hpux0800 KTARGET=$${KTARGET:-$(@)} \
        "KFLAGS = $(KFLAGS) -UTCPSOCKET"
 
 #Now the same as above hpux0800 but with compiler optimization
+#OK: 2009/10/01
 hpux0800o:
        @MESSAGE1="with compiler optimization" \
        $(MAKE) hpux0800 KTARGET=$${KTARGET:-$(@)} \
        "KFLAGS = $(KFLAGS)" "OFLAGS = -O"
 
 #Exactly as above hpux0800 + curses and with compiler optimization.
+#OK: 2009/10/01
 hpux0800oc:
        @MESSAGE1="with compiler optimization" \
        $(MAKE) hpux0800c KTARGET=$${KTARGET:-$(@)} \
        "KFLAGS = $(KFLAGS)" "OFLAGS = -O" "LIBS = -lcurses"
 
 #Exactly as above hpux0800notcp but with compiler optimization
+#OK: 2009/10/01
 hpux0800onotcp:
        @MESSAGE1="with compiler optimization" \
        $(MAKE) "MAKE=$(MAKE)" hpux0800notcp KTARGET=$${KTARGET:-$(@)} \
@@ -5092,41 +5600,62 @@ hpux0800onotcp:
 
 #HP 9000 Series 700 or 800, HP-UX 8.0, long filenames and TCP/IP support.
 # Like the previous entries, but with PA-RISC-specific optimization.
+#OK: 2009/10/01
 hpux0800pa:
        @MESSAGE1="with PA-RISC-specific optimization" \
        $(MAKE) hpux0800 KTARGET=$${KTARGET:-$(@)} \
        "KFLAGS = $(KFLAGS) +Obb1100"
 
 #As above, but with curses.
+#OK: 2009/10/01
 hpux0800pac:
        @MESSAGE1="with PA-RISC-specific optimization" \
        $(MAKE) hpux0800c KTARGET=$${KTARGET:-$(@)} \
        "KFLAGS = $(KFLAGS) +Obb1100"
 
 #As above, but compiled with GCC 2.3.3.
+#OK: 2009/10/01
 hpux0800pagcc:
        @MESSAGE1='using the gcc compiler' \
        $(MAKE) hpux0800 KTARGET=$${KTARGET:-$(@)} \
-       "CC=gcc" "CC2=gcc" "KFLAGS= -funsigned-char $(KFLAGS)"
+       "CC=gcc" "CC2=gcc" "KFLAGS = -funsigned-char $(KFLAGS)"
 
 #HP-UX 9.0, 9.01, 9.03, 9.04, 9.05, 9.07, 9.10 ..., + TCP/IP + curses, fully
 #configured.  Use this entry with the restricted compiler: no optimization, no
 #ANSI support.  If you get unresolved sockets library references at link time,
 #then try adding -lBSD to LIBS, or else remove -DTCPSOCKET to build a version
 #without TCP/IP support.
+#
+#Please note that we have to add the compiler option +DA1.0/+DA1.1 to avoid
+#core-dumps for large arguments in IF MATCH. The man page says these options
+#are default but C-Kermit dumps core without them! Therefore keep them
+#untouched. If you want to overwrite or disable the +DA1.0/+DA1.1 option use
+#'make hpux0900 OFLAGS=...'. An other possibility would be to create a new
+#kernel with maxssiz >= 0x01185000 (default maxssiz=0x00800000).
+#OK: 2009/09/24
 hpux0900:
        @MESSAGE1A='. Read hpux0900 entry comments if you have trouble.' \
        $(MAKE) hpux-header
+       @case `uname -m` in \
+         */[34]*) KFLAGS='-DNOLONGLONG $(KFLAGS)' ;; \
+         */7*)    AFLAGS='+DA1.1' ;; \
+         */8*)    AFLAGS='+DA1.0' ;; \
+       esac ; \
+       OFLAGS=$${OFLAGS:-$$AFLAGS} ; \
        $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} \
        "CFLAGS = -DHPUXDEBUG -DHPUX9 -DSTERMIOX -DDIRENT -DUTIMEH \
        -DNOSETBUF -DCK_CURSES -DTCPSOCKET -DRENAME -DCK_REDIR -DLONGFN \
-       -DHDBUUCP -DLOCK_DIR=\\\"/usr/spool/uucp\\\" -DFNFLOAT $(KFLAGS)" \
+       -DHDBUUCP -DLOCK_DIR=\\\"/usr/spool/uucp\\\" -DFNFLOAT \
+       -DNODCLENDUSERSHELL $$KFLAGS $$OFLAGS" \
        "LNKFLAGS = -s" "LIBS = -lm -lcurses" "CC=$(CC)" "CC2=$(CC2)"
 
 #Like hpux0900, but for the "value-added" compiler on all HP 9000 models.
 #Adds optimization and ANSI compilation:
 # +O2 makes smaller executable (= -O = Level-1 and global optimization)
 # +O3 adds interprocedural global optimization, makes bigger executable.
+# Please note: To support long-long we would need compiler switch '-Ae' but
+# this one works only on Risc systems. But the equivalant compiler flags
+# '-Aa -D_HPUX_SOURCE +e' works for Motorola and Risc.
 # If optimization fails on some modules, you can add:
 #  +Obb<n>, +Olimit <n>, or +Onolimit, depending on your cc version,
 # where <n> is a number, e.g. +Obb1200.  In other words, if you get optimizer
@@ -5137,10 +5666,11 @@ hpux0900:
 # depending on the amount of main memory, this entry might fail no matter what
 # you do ("Out of Memory", "cc: Fatal error in /lib/c.c1", etc).  In that case
 # use "make hpux0900" (no "o").
+#OK: 2009/09/24
 hpux0900o:
        @MESSAGE1=$${MESSAGE1:-"with compiler optimization"} \
        $(MAKE) hpux0900 KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS = $(KFLAGS) -Aa -DCK_ANSIC -D_HPUX_SOURCE +O2"
+       "KFLAGS = $(KFLAGS) -Aa -DCK_ANSIC -D_HPUX_SOURCE +O2 +e"
 
 # For HP-UX 9.0 on Motorola CPUs, optimization of ckcpro.c tends to blow up
 # the compiler.  You might have to reinstall your kernel with maxdsiz >=
@@ -5148,17 +5678,21 @@ hpux0900o:
 # In that case, use this entry to skip optimization of ckcpro.c.  But for
 # C-Kermit 8.0.208 you need a kernel with maxdsiz >= 0x02000000 to compile an
 # optimized ckcftp.c.
+# Please note: To support long-long we would need compiler switch '-Ae' but
+# this one works only on Risc systems. But the equivalant compiler flags
+# '-Aa -D_HPUX_SOURCE +e' works for Motorola and Risc.
 hpux0900m68ko:
        @MESSAGE1='without compiler optimization for ckcpro.$(EXT) ...' \
        $(MAKE) hpux-header
-       $(MAKE) ckuusr.$(EXT) ckuus3.$(EXT) ckcpro.$(EXT) \
+       $(MAKE) ckuusr.$(EXT) ckuus3.$(EXT) ckuus4.$(EXT) \
+       ckcftp.$(EXT) ckcpro.$(EXT) \
        "CFLAGS = -DHPUXDEBUG -DHPUX9 -DSTERMIOX -DDIRENT \
        -DNOSETBUF -DCK_CURSES -DTCPSOCKET -DRENAME  -DCK_REDIR -DLONGFN \
        -DHDBUUCP -DLOCK_DIR=\\\"/usr/spool/uucp\\\" -DFNFLOAT $(KFLAGS)"
        @echo
        @MESSAGE1="with compiler optimization for the rest" \
        $(MAKE) hpux0900 KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS = $(KFLAGS) -Aa -DCK_ANSIC -D_HPUX_SOURCE +O2"
+       "KFLAGS = $(KFLAGS) -Aa -DCK_ANSIC -D_HPUX_SOURCE +O2 +e"
 
 # Old name for hpux0900m68ko.
 hpux0900mot:
@@ -5181,7 +5715,8 @@ hpux0900o700:
 hpux0900gcc:
        @MESSAGE1='using the gcc compiler' \
        $(MAKE) hpux0900 KTARGET=$${KTARGET:-$(@)} CC=gcc CC2=gcc \
-       "KFLAGS = $(KFLAGS) -DCK_ANSIC -funsigned-char -O2"
+       "KFLAGS = -DCK_ANSIC $(KFLAGS)" \
+       "OFLAGS = -funsigned-char -O2 $(OFLAGS)"
 
 #HP-9000 HP-UX 10.0 + TCP/IP + curses, fully configured.
 #Use with restricted (bundled) compiler: no optimization, no ANSI support.
@@ -5191,14 +5726,19 @@ hpux0900gcc:
 #the 10.10 curses problem is supposedly fixed in 10.30.
 # +DA1.0 = Generate PA-RISC 1.0 code that runs on both 700 and 800 models.
 # +DA1.1 = Generate PA-RISC 1.1 code that runs on both 700 and 800 models.
-# Note that HP-UX 10.20 and upwards  not support PA-RISC 1.0 systems.
+# Note that HP-UX 10.20 and upwards do not support PA-RISC 1.0 systems.
 # And that as of Dec 2001, 11.00 and 11.11 are PA-only and 11.20 is IA64-only.
 # Later 11.2x releases are expected to be for both.  Architecture can be
 # determined with the model command, at least in 10.20 and later...
 #For future releases, we need to include +DA1.1 for PA builds, so that a
 #binary built on PA 2.0 will still work on PA 1.1 machines, whereas +DA1.1
 #must NOT be included for IA64 builds.
-#
+#4 Jan 2006 - Added Large File Support (LFS).  Large files (>2GB) are
+#possible in HP-UX 10.20 and later.  The only change is to add:
+# -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
+#to KFLAGS.  These should be harmless in 10.00 and 10.10, if any of examples
+#of those still exist, but I have no way to test this hypothesis.
+#OK: 2009/11/16
 hpux1000:
        @$(MAKE) hpux-header
        @LIBS='-lHcurses' ; \
@@ -5226,6 +5766,7 @@ hpux1000:
        "CC=$(CC)" "CC2=$(CC2)" \
        "CFLAGS = -DHPUX10 -DDIRENT -DSTERMIOX -DCK_DSYSINI -DHDBUUCP \
        -DCK_CURSES -DCK_WREFRESH -DTCPSOCKET -DCK_REDIR -DRENAME -DFNFLOAT \
+       -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 \
        $$KFLAGS $$OFLAGS" \
        "LNKFLAGS=-s $(LNKFLAGS)" "LIBS = -lm $$LIBS $(KLIBS)"
 
@@ -5233,16 +5774,17 @@ hpux1000:
 # (add CC and CC2, drop the A1.[0||1])
 # Builds w/ no compiler warnings but minimally tested.
 #
+#OK: 2009/09/21
 hpux1000gcc:
        @MESSAGE1="using the gcc compiler $(MESSAGE1)" \
        $(MAKE) hpux1000 KTARGET=$${KTARGET:-$(@)} CC=gcc CC2=gcc \
-       "KFLAGS = $(KFLAGS)" OFLAGS=" -DCK_ANSIC -funsigned-char -O2"
+       "KFLAGS = $(KFLAGS)" "OFLAGS = -DCK_ANSIC -funsigned-char -O2"
 
 # Trusted HP-UX 10
 # echo KFLAGS=$(KFLAGS) YTARGET YTARGET=$(YTARGET) $(XTARGET) ;
 hpux1000t:
        @case "$(KTARGET)" in \
-          *+openssl) \
+          *+openssl | *+ssl) \
                KENTRY=hpux1000o+openssl ;; \
           *gcc) \
                KENTRY=hpux1000gcc ;; \
@@ -5252,7 +5794,7 @@ hpux1000t:
        esac ; \
        MESSAGE1="and support for 'Trusted HP-UX'" \
        $(MAKE) $$KENTRY KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS= $(KFLAGS) -DHPUX10_TRUSTED" "KLIBS=-lsec"
+       "KFLAGS = $(KFLAGS) -DHPUX10_TRUSTED" "KLIBS=-lsec"
 
 hpux1000to:
        $(MAKE) hpux1000t KTARGET=$${KTARGET:-$(@)}
@@ -5263,10 +5805,10 @@ hpux1000to+:
 hpux1000tgcc:
        $(MAKE) hpux1000t KTARGET=$${KTARGET:-$(@)}
 
-hpux1000to+openssl:
+hpux1000to+ssl hpux1000to+openssl:
        $(MAKE) hpux1000t KTARGET=$${KTARGET:-$(@)}
 
-hpux1000tgcc+openssl:
+hpux1000tgcc+ssl hpux1000tgcc+openssl:
        $(MAKE) hpux1000t KTARGET=$${KTARGET:-$(@)}
 
 #HP-9000 HP-UX 10.00 and higher with ANSI prototyping and optimization.
@@ -5290,6 +5832,7 @@ hpux1000tgcc+openssl:
 # +DA1.1 is PA-only.  If this is included in in HP-UX 11.00 or later,
 # then +DS2.0 should be included too (but don't use +DS2.0 without +DA1.1,
 # or else the binary won't run on older PA hardware).
+#OK: 2009/09/21
 hpux1000o:
        @case `uname -m` in \
          ia64) ;; \
@@ -5298,7 +5841,7 @@ hpux1000o:
        MESSAGE1="with PA-RISC-specific optimizations $(MESSAGE1)" \
        $(MAKE) "SHELL=/usr/bin/sh" "PATH=/opt/ansic/bin:$$PATH" hpux1000 \
        KTARGET=$${KTARGET:-$(@)} "KFLAGS = $(KFLAGS) \
-       -Aa -D_HPUX_SOURCE -DCK_ANSIC -DUTIMEH \
+       -Ae -D_HPUX_SOURCE -DCK_ANSIC -DUTIMEH \
        +O2 -Wl,-Fw $$MFLAGS"
 
 #Like hpux1000o but with "+Onolimit".
@@ -5311,8 +5854,8 @@ hpux1000o+:
 
 #HP-UX 10.xx + 11.xx with optimizing ANSI compiler and OpenSSL.
 #Define SSLLIB and SSLINC appropriately for your OpenSSL installation.
-#Do overwrite the default SSLLIB and SSLINC settings you can also use the
-#command-line variable KSSLLIB and KSSLINC like: 
+#To overwrite the default SSLLIB and SSLINC settings you can also use the
+#command-line variable KSSLLIB and KSSLINC like:
 #make hpux1000o+openssl KSSLLIB=-L/opt/openssl/lib KSSLINC=-I/...
 #Ditto for the Zlib location.
 #This entry works for C-Kermit 8.0.206 on HP-UX 10.20 + 11.11
@@ -5320,21 +5863,32 @@ hpux1000o+:
 #NOTE: an ANSI C compiler is required for the SSL interface.  If you don't
 #have the HP Optimizing ANSI compiler, see the hpux1000gcc+openssl target
 #below.
-hpux1000o+openssl:
+hpux1000o+ssl hpux1000o+openssl:
        @case "$(KTARGET)" in \
-          *gcc+*) KENTRY=hpux1000gcc ;; \
-          *)      KENTRY=hpux1000o ;; \
+          *gcc+*) \
+               KENTRY=hpux1000gcc ;; \
+          *)   KENTRY=hpux1000o ;; \
+       esac ; \
+       case "$(KTARGET)" in \
+          *-zlib*) \
+               DZLIB= LZLIB= ;; \
+          *)   DZLIB=-DZLIB LZLIB='-L/opt/zlib/lib -lz' ;; \
        esac ; \
        SSLINC=$${KSSLINC:-$(SSLINC)}; \
        SSLLIB=$${KSSLLIB:-$(SSLLIB)}; \
        MESSAGE1="and with OpenSSL $(MESSAGE1)" \
        $(MAKE) $$KENTRY KTARGET=$${KTARGET:-$(@)} \
-       KFLAGS="-DCK_AUTHENTICATION -DCK_SSL -DOPENSSL_097 -DZLIB \
+       KFLAGS="-DCK_AUTHENTICATION -DCK_SSL -DOPENSSL_097 $$DZLIB \
        $$SSLINC $(KFLAGS)" \
        KLIBS="$(KLIBS) \
        $$SSLLIB -lssl -lcrypto \
-       -L/opt/zlib/lib -lz \
-       " 
+       $$LZLIB \
+       "
+
+# Ditto but without Zlib:
+hpux1000o+ssl-zlib hpux1000o+openssl-zlib:
+       @MESSAGE1="but without Zlib $(MESSAGE1)" \
+       $(MAKE) hpux1000o+ssl KTARGET=$${KTARGET:-$(@)}
 
 #HP-UX 10.00 or higher with OpenSSL 0.9.7.  Compiled with gcc.
 #From Chris Chaney, NEC America Inc.  His instructions:
@@ -5350,26 +5904,43 @@ hpux1000o+openssl:
 # (5) Install gmp version 3.1.1 from http://hpux.cs.utah.edu/
 #
 #Note from Peter Eichhorn, assyst Munich. It works also without gcc make!
-hpux1000gcc+openssl:
+hpux1000gcc+ssl hpux1000gcc+openssl:
        $(MAKE) hpux1000o+openssl KTARGET=$${KTARGET:-$(@)}
 
+# Ditto but without Zlib:
+hpux1000gcc+ssl-zlib hpux1000gcc+openssl-zlib:
+       $(MAKE) hpux1000o+openssl-zlib KTARGET=$${KTARGET:-$(@)}
+
 # Same for HP-UX 11
-hpux1100o+openssl:
+hpux1100o+ssl hpux1100o+openssl:
        $(MAKE) hpux1000o+openssl KTARGET=$${KTARGET:-$(@)}
 
-hpux1100gcc+openssl:
+#OK: 2009/09/26
+hpux1100gcc+ssl hpux1100gcc+openssl:
        $(MAKE) hpux1000gcc+openssl KTARGET=$${KTARGET:-$(@)}
 
+hpux1100o+ssl-zlib hpux1100o+openssl-zlib:
+       $(MAKE) hpux1000o+openssl-zlib KTARGET=$${KTARGET:-$(@)}
+
+hpux1100gcc+ssl-zlib hpux1100gcc+openssl-zlib:
+       $(MAKE) hpux1000gcc+openssl-zlib KTARGET=$${KTARGET:-$(@)}
+
 # HP-UX 11
+# Note: these are 32-bit builds even on IA64.
+# Adding +DD64 to CFLAGS produces 64-bit object files,
+# but the linker fails to find the needed 64-bit libs.
+#OK: 2009/09/26
 hpux1100:
        $(MAKE) hpux1000 KTARGET=$${KTARGET:-$(@)}
 
+#OK: 2009/09/26
 hpux1100o:
        $(MAKE) hpux1000o KTARGET=$${KTARGET:-$(@)}
 
 hpux1100o+:
        $(MAKE) hpux1000o+ KTARGET=$${KTARGET:-$(@)}
 
+#OK: 2009/09/26
 hpux1100gcc:
        $(MAKE) hpux1000gcc KTARGET=$${KTARGET:-$(@)}
 
@@ -5386,10 +5957,10 @@ hpux1100to+:
 hpux1100tgcc:
        $(MAKE) hpux1000tgcc KTARGET=$${KTARGET:-$(@)}
 
-hpux1100to+openssl:
+hpux1100to+ssl hpux1100to+openssl:
        $(MAKE) hpux1000to+openssl KTARGET=$${KTARGET:-$(@)}
 
-hpux1100tgcc+openssl:
+hpux1100tgcc+ssl hpux1100tgcc+openssl:
        $(MAKE) hpux1000tgcc+openssl KTARGET=$${KTARGET:-$(@)}
 
 #Regulus on CIE Systems 680/20
@@ -5432,13 +6003,13 @@ cie:
 #
 # Add -DCK_DSYSINI if you want a shared system-wide init file.
 #
-# See ckubwr.txt about -DNOCOTFMC.  In fact, you really should read the
-# entire Linux section of ckubwr.txt.
+# See http://www.columbia.edu/kermit/ckubwr.html about -DNOCOTFMC.
+# Better still, should read the entire Linux section of that document.
 #
 # The "linuxa" entry can be referenced directly on LIBC systems, but not
 # GLIBC, where -lcrypt is required.  The "make linux" entry should normally
 # be used for all builds on all Linux distributions unless you have special
-# requirements, in which case keep reading.  CK_NEWTERM added after 7.0B04
+# requirements, in which case keep reading.  CK_NEWTERM added after 7.0b04
 # due to new complaints about ncurses changing buffering of tty.
 
 linuxa:
@@ -5448,85 +6019,263 @@ linuxa:
        $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} "CC = gcc" "CC2 = gcc" \
        "CFLAGS = -O -DLINUX -pipe -funsigned-char -DFNFLOAT -DCK_POSIX_SIG \
        -DCK_NEWTERM -DTCPSOCKET -DLINUXFSSTND -DNOCOTFMC -DPOSIX \
-       -DUSE_STRERROR $(KFLAGS)" "LNKFLAGS = $(LNKFLAGS)" "LIBS = $(LIBS) -lm"
+       -DUSE_STRERROR $(KFLAGS)" "LNKFLAGS = $(LNKFLAGS)" \
+       "LIBS = $(LIBS) -lm"
 
 # As above but with profiling
 linuxp:
        $(MAKE) linuxa KTARGET=$${KTARGET:-$(@)} "KFLAGS=$(KFLAGS) -pg" \
        "LIBS=-pg -lcrypt -lresolv"
 
-#New primary Linux entry for C-Kermit 8.0, replacing big nested
-#if-then-else construction full of repeated clauses with a simpler scheme
-#for automatically detecting:
+#Linux.  This entry should work for any Linux distribution on any platform,
+#32-bit or 64-bit, except for extremely ancient ones.  Automatically detects:
+# . curses, ncurses, or no curses
 # . Old versus new pty handling (new == glibc 2.1++)
-# . Presence or absence of librypt.a and <crypt.h>
+# . Presence or absence of libcrypt.a and <crypt.h>
 # . Presence or absence of libresolv.a
-#Unlike the previous scheme, this one is easily extended to include more tests.
+# . Transitional Long File API for 32-bit platforms (SUS V2 UNIX 98 LFS).
 #Note: The HAVE_PTMX test was previously "if test -c /dev/ptmx" but this was
 #not sufficient for Debian 2.1, because although it had /dev/ptmx, it did not
 #have grantpt(), unlockpt(), or ptsname(), so has been changed to look for a
-#grantpt() prototype in the header files.  Warning: uses a temporary file in
-#the current directory.  Modified in 8.0.206 to allow for libraries that
-#contain .so's but no .a's, e.g. Mandrake 9.0.
+#grantpt() prototype in the header files.  Modified in 8.0.206 to allow for
+#libraries that contain .so's but no .a's, e.g. Mandrake 9.0.
 #HAVE_BAUDBOY added in 8.0.210 for Red Hat -- it's like AIX ttylock().
+#Modified 17 Aug 2005 to use openpty() if available because the other stuff
+#dumps core in 64-bit ia64 and x86_64 builds.
+#Long file support for 32-bit builds added in 8.0.212 - if features.h contains
+#__USE_LARGEFILE64 then we set the flags that must be set before reading any
+#header files; on 32-bit platforms such as i386, this produces a 32-bit build
+#capable of accessing, sending, receiving, and managing long (> 2GB) files.
+#On 64-bit platforms, it does no harm.
+#As of 3 March 2009 we detect automatically if we have curses, ncurses,
+#or no curses at all.
+#OK: 2009/11/16
+#Added HAVE_LOCKDEV as openSuSE >= 11.3 uses ttylock directly instead of
+#baudboy 2010/08/23
 linux:
        @if test \
        `grep grantpt /usr/include/*.h /usr/include/sys/*.h | wc -l` -gt 0; \
        then if test -c /dev/ptmx; then HAVE_PTMX='-DHAVE_PTMX'; \
        else HAVE_PTMX=''; fi; fi ; \
+       if test `grep openpty /usr/include/pty.h | wc -l` -gt 0; \
+       then HAVE_OPENPTY='-DHAVE_OPENPTY'; \
+       else HAVE_OPENPTY=''; fi ; \
+       HAVE_LIBCURSES=''; \
+       if test -f /usr/lib64/libncurses.so || \
+          test -f /usr/lib/libncurses.a  || \
+          test -f /usr/lib/libncurses.so; then \
+         HAVE_LIBCURSES='-lncurses'; \
+       else if test -f /usr/lib64/libcurses.so || \
+          test -f /usr/lib/libcurses.a || \
+          test -f /usr/lib/libcurses.so; then \
+            HAVE_LIBCURSES='-lcurses'; fi; fi; \
+       HAVE_CURSES=''; \
+       if test -n '$$HAVE_LIBCURSES'; then \
+         if test -f /usr/include/ncurses.h; then \
+           HAVE_CURSES='-DCK_NCURSES  -I/usr/include/ncurses'; \
+         else if test -f /usr/include/curses.h; then \
+           HAVE_CURSES='-DCK_CURSES'; \
+       fi; fi; fi; \
+       if test -f /usr/include/baudboy.h || test -f /usr/include/ttylock.h; \
+       then HAVE_LOCKDEV='-DHAVE_LOCKDEV' ; \
+       else HAVE_LOCKDEV='' ; fi ; \
        if test -f /usr/include/baudboy.h ; \
        then HAVE_BAUDBOY='-DHAVE_BAUDBOY' ; \
        else HAVE_BAUDBOY='' ; fi ; \
        $(MAKE) KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS=-DCK_NCURSES -I/usr/include/ncurses \
-       $$HAVE_PTMX $$HAVE_BAUDBOY \
+       "KFLAGS=$$HAVE_CURSES $$HAVE_PTMX $$HAVE_LOCKDEV \
+       $$HAVE_BAUDBOY $$HAVE_OPENPTY \
+       `grep __USE_LARGEFILE64 /usr/include/features.h > /dev/null && \
+       echo '-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'` \
        `if test -f /usr/include/crypt.h; then echo -DHAVE_CRYPT_H; fi` \
        $(KFLAGS)" \
-       "LIBS=-lncurses \
-       `if test -f /usr/lib/libresolv.a || test -f /usr/lib/libresolv.so; \
+       "LIBS=$(LIBS) $$HAVE_LIBCURSES \
+       `if test -n '$$HAVE_OPENPTY'; then echo -lutil; fi` \
+       `if test -f /usr/lib64/libresolv.a || test -f /usr/lib64/libresolv.so \
+       || test -f /usr/lib/libresolv.a || test -f /usr/lib/libresolv.so; \
        then echo -lresolv; fi` \
-       `if test -f /usr/lib/libcrypt.a || test -f /usr/lib/libcrypt.so; \
-       then echo -lcrypt; fi`" \
+       `if test -f /usr/lib64/libcrypt.a || test -f /usr/lib64/libcrypt.so \
+       || test -f /usr/lib/libcrypt.a || test -f /usr/lib/libcrypt.so; \
+       then echo -lcrypt; fi` \
+       `if test -f /usr/lib64/liblockdev.a || \
+       test -f /usr/lib64/liblockdev.so || \
+       test -f /usr/lib/liblockdev.a || \
+       test -f /usr/lib/liblockdev.so; \
+       then echo -llockdev; fi`" \
        linuxa
 
+# Secure targets for Linux.  These work on RHAS4, RHEL4, and RHEL5,
+# unlike some of the older targets that follow.  They hook into the main Linux
+# target so we pick up all the other new stuff - large files, baudboy.h, the
+# appropriate pty interface, etc.
+
+# Linux with Kerberos 5 (but not 4) and OpenSSL.
+# Note: -DOPENSSL_097 is necessary.  Without it we use the wrong names
+# for the DES routines and the link step fails.
+# Note 2: In recent Red Hat releases libpam might be in /lib instead of in
+# /usr/lib.  There should be symlinks in place but if not add them yourself.
+#OK: 2010/04/01
+
+# Linux with Kerberos 5.
+# Use "make linux+krb5 KFLAGS=-DNO_KRB5_INIT_ETS" if necessary.
+#OK 2011/06/14 on Fedora 14:
+# make linux+krb5 "LIBS=$LIBS /lib/libk5crypto.so.3 /lib/libcom_err.so.2"
+# On RHEL5: make linux+krb5 -UCK_DES
+linux+krb5:
+       @echo 'Making C-Kermit $(CKVER) for Linux with Kerberos 5...'
+       @case `openssl version` in \
+         *0.9.7*) OPENSSLOPTION="-DOPENSSL_097" ;; \
+         *0.9.8*) OPENSSLOPTION="-DOPENSSL_098" ;; \
+         *1.[0-9].[0-9]*) OPENSSLOPTION="-DOPENSSL_100" ;; \
+         *) OPENSSLOPTION="" ;; \
+       esac; \
+       HAVE_DES=''; \
+       DES_LIB=''; \
+       if ls /usr/lib/libdes* > /dev/null 2> /dev/null || \
+          ls $(SSLLIB)/libdes* > /dev/null 2> /dev/null; then \
+             DES_LIB='-ldes425'; \
+             HAVE_DES='-DCK_DES -DLIBDES'; \
+              echo "HAVE DES"; \
+           else echo "NO DES"; \
+       fi; \
+       K5CRYPTO=''; \
+       if ls /lib/libk5crypto* > /dev/null 2> /dev/null; then \
+               K5CRYPTO='-lk5crypto'; \
+       fi; \
+       COM_ERR=''; \
+       if ls /lib/libcom_err* > /dev/null 2> /dev/null; then \
+               COM_ERR='-lcom_err'; \
+       fi; \
+       GSSAPILIB='-lgssapi'; \
+       K5DIR=`echo $(K5LIB) | sed 's|-L||'`; \
+       if ls $$K5DIR/libgssapi_krb5* > /dev/null 2> /dev/null; then \
+               GSSAPILIB='-lgssapi_krb5'; \
+       fi; \
+       $(MAKE) linux KTARGET=$${KTARGET:-$(@)} "CC = gcc" "CC2 = gcc" \
+       "KFLAGS= -DCK_AUTHENTICATION -DCK_KERBEROS -DKRB5 $$OPENSSLOPTION \
+       -DCK_ENCRYPTION $$HAVE_DES $(K5INC) $(K5INC)/krb5 \
+       -I/usr/include/et $(KFLAGS)" "LNKFLAGS = $(LNKFLAGS)" \
+       "LIBS = $(K5LIB) $$DES_LIB -lcrypto $$GSSAPILIB -lkrb5 \
+       $$K5CRYPTO $$COM_ERR $(LIBS)"
+
+# Linux with OpenSSL 
+# In Linux, SSL libs are often in /lib or /usr/lib and so found by default.
+# This targets takes into account the DES library might or might not
+# exist.  If it does exist, however, the target will require some editing
+# if its basename is not libdes425.  - fdc Tue Sep 21 14:28:00 2010
+# IMPORTANT: Some Linux platforms have DES libraries but they are missing
+# functions used by Kermit.  In that case you will get fatal errors at
+# link time involving routines such as des_ecb3_encrypt, des_random_seed,
+# and des_set_odd_parity.  In that case, "make linux KFLAGS=-UCK_DES"
+# There's a new warning at the end that should come out if this happens,
+# and that should not come out if it didn't.
+#
+linux+ssl linux+openssl:
+       @echo 'Making C-Kermit $(CKVER) for Linux+OpenSSL SSLLIB=$(SSLLIB)'
+       @case `openssl version` in \
+         *0.9.7*) OPENSSLOPTION="-DOPENSSL_097" ;; \
+         *0.9.8*) OPENSSLOPTION="-DOPENSSL_098" ;; \
+         *1.[0-9].[0-9]*) OPENSSLOPTION="-DOPENSSL_100" ;; \
+         *) OPENSSLOPTION="" ;; \
+       esac; \
+       HAVE_DES=''; \
+       DES_LIB=''; \
+       if ls /usr/lib/libdes* > /dev/null 2> /dev/null || \
+          ls $(SSLLIB)/libdes* > /dev/null 2> /dev/null; then \
+             DES_LIB='-ldes425'; \
+             HAVE_DES='-DCK_DES -DLIBDES'; \
+              echo "HAVE DES"; \
+           else echo "NO DES"; \
+       fi; \
+       $(MAKE) linux KTARGET=$${KTARGET:-$(@)} "CC = gcc" "CC2 = gcc" \
+       "KFLAGS= -DCK_AUTHENTICATION -DCK_ENCRYPTION -DCK_CAST $$HAVE_DES \
+       -DCK_SSL -DCK_PAM -DZLIB -DCK_SHADOW $$OPENSSLOPTION $(SSLINC) \
+       $(KFLAGS)" "LNKFLAGS = $(LNKFLAGS)" \
+       "LIBS = $(SSLLIBS) -lssl $$DES_LIB -lcrypto -lpam -ldl -lz $(LIBS)"; \
+       if [ ! -f ./wermit ] || [ ckcmai.o -nt ./wermit ]; then \
+       echo ""; \
+       echo "If build failed try:"; \
+       echo ""; \
+       echo "  make clean ; make linux+ssl KFLAGS=-UCK_DES"; \
+       echo ""; fi
+
+# Linux with Kerberos 5 and OpenSSL
+# OK 2011/05/16
+# Add -UCK_DES if functions like des_ecb3_encrypt, es_random_seed,
+# come up missing at link time.
+linux+krb5+ssl linux+krb5+openssl:
+       @echo 'Making C-Kermit $(CKVER) for Linux with Krb5 and OpenSSL...'
+       @case `openssl version` in \
+         *0.9.7*) OPENSSLOPTION="-DOPENSSL_097" ;; \
+         *0.9.8*) OPENSSLOPTION="-DOPENSSL_098" ;; \
+         *1.[0-9].[0-9]*) OPENSSLOPTION="-DOPENSSL_100" ;; \
+         *) OPENSSLOPTION="" ;; \
+       esac; \
+       HAVE_DES=''; \
+       DES_LIB=''; \
+       if ls /usr/lib/libdes* > /dev/null 2> /dev/null || \
+          ls $(SSLLIB)/libdes* > /dev/null 2> /dev/null; then \
+             DES_LIB='-ldes425'; \
+             HAVE_DES='-DCK_DES -DLIBDES'; \
+             echo "HAVE DES"; \
+          else echo "NO DES"; \
+       fi; \
+       K5CRYPTO=''; \
+       if ls /lib/libk5crypto* > /dev/null 2> /dev/null; then \
+               K5CRYPTO='-lk5crypto'; \
+       fi; \
+       COM_ERR=''; \
+       if ls /lib/libcom_err* > /dev/null 2> /dev/null; then \
+               COM_ERR='-lcom_err'; \
+       fi; \
+       GSSAPILIB='-lgssapi'; \
+       K5DIR=`echo $(K5LIB) | sed 's|-L||'`; \
+       echo K5DIR=$$K5DIR; \
+       if ls $$K5DIR/libgssapi_krb5* > /dev/null 2> /dev/null; then \
+               GSSAPILIB='-lgssapi_krb5'; \
+       fi; \
+       $(MAKE) linux KTARGET=$${KTARGET:-$(@)} "CC = gcc" "CC2 = gcc" \
+       "KFLAGS= -DCK_AUTHENTICATION -DCK_KERBEROS -DKRB5 \
+       -DCK_SSL -DCK_PAM -DZLIB -DCK_SHADOW $$OPENSSLOPTION $(SSLINC) \
+       -DCK_ENCRYPTION $$HAVE_DES $(K5INC) $(K5INC)/krb5 \
+       -I/usr/include/et $(KFLAGS)" "LNKFLAGS = $(LNKFLAGS)" \
+       "LIBS = $(K5LIB) $(SSLLIBS) -lssl $$DES_LIB -lpam -lz \
+       -lcrypto $$GSSAPILIB_krb5 -lkrb5 $$K5CRYPTO $$COM_ERR $(LIBS)" \
+       if [ ! -f ./wermit ] || [ ckcmai.o -nt ./wermit ]; then \
+       echo ""; \
+       echo "If build failed try:"; \
+       echo ""; \
+       echo "  make clean ; make linux+ssl KFLAGS=-UCK_DES"; \
+       echo ""; fi
+
+#Linux configured for SSL/TLS, ZLIB, PAM and Shadow Passwords
+#OK: 2009/11/17
+linux+openssl+zlib+shadow+pam:
+       @echo 'Making C-Kermit $(CKVER) for Linux on i386 with SSL/TLS...'
+       $(MAKE) linux KTARGET=$${KTARGET:-$(@)} "CC = gcc" "CC2 = gcc" \
+       "KFLAGS = -DCK_AUTHENTICATION -DCK_SSL -DCK_PAM -DZLIB -DOPENSSL_097 \
+       -DCK_SHADOW $(SSLINC) $(KFLAGS)" "LNKFLAGS = $(LNKFLAGS)" \
+       "LIBS= $(SSLLIB) -lssl -lcrypto -lz -lpam -ldl $(LIBS)"
+
 # As above but for Linux systems that have no <sys/select.h>.
 linuxns:
        $(MAKE) linux KTARGET=$${KTARGET:-$(@)} KFLAGS=-DNO_SYS_SELECT_H
 
-# As above, but forces use of curses rather than ncurses.
-# Add -ltermcap to LIBS if necessary.
-# Also watch out for libcurses and/or libtermcap having been moved.
-# In that case you might need something like:
-#  "LIBS = -L/usr/lib/curses -lcurses -L/usr/lib/termcap -ltermcap"
-
-linuxc:
-       @if test \
-       `grep grantpt /usr/include/*.h /usr/include/sys/*.h | wc -l` -gt 0; \
-       then if test -c /dev/ptmx; then HAVE_PTMX='-DHAVE_PTMX'; \
-       else HAVE_PTMX=''; fi; fi ; \
-       $(MAKE) KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS=-DCK_CURSES $$HAVE_PTMX \
-       `if test -f /usr/lib/libcrypt.a; then echo -DHAVE_CRYPTH; fi` \
-       $(KFLAGS)" \
-       "LIBS=-lcurses \
-       `if test -f /usr/lib/libresolv.a; then echo -lresolv; fi` \
-       `if test -f /usr/lib/libcrypt.a; then echo -lcrypt; fi`" \
-       linuxa
+# A minimum-size version for Linux that does only scripting and
+# serial communication -- no networks, no file transfer.
+linuxso:
+       $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} "CC = gcc" "CC2 = gcc" \
+       "CFLAGS = -O -DLINUX -pipe -funsigned-char -DPOSIX -DCK_POSIX_SIG \
+       -DLINUXFSSTND -DNOCOTFMC -DNOXFER -DNODEBUG -DNOCSETS -DNOHELP \
+       -DNONET -DMINIDIAL -DNOSCRIPT -DNOIKSD -DNOPUSH $(KFLAGS)" \
+       "LNKFLAGS = $(LNKFLAGS)" "LIBS = "
 
-# As above but with with no curses support, for example because you installed
-# the developer tools but did not install (n)curses.
-linuxnc:
-       @if test \
-       `grep grantpt /usr/include/*.h /usr/include/sys/*.h | wc -l` -gt 0; \
-       then if test -c /dev/ptmx; then HAVE_PTMX='-DHAVE_PTMX'; \
-       else HAVE_PTMX=''; fi; fi ; \
-       $(MAKE) KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS= $$HAVE_PTMX \
-       `if test -f /usr/lib/libcrypt.a; then echo -DHAVE_CRYPTH; fi` \
-       $(KFLAGS)" "LIBS= \
-       `if test -f /usr/lib/libresolv.a; then echo -lresolv; fi` \
-       `if test -f /usr/lib/libcrypt.a; then echo -lcrypt; fi`" \
-       linuxa
+# The remaining Linux entries are for special or customized builds.  They
+# have not been generalized like the ones above.  Ideally, we should allow
+# for every combination of libc vs glibc, gcc vs egcs, curses vs ncurses,
+# Kerberos IV vs Kerberos V vs SRP (in any combination), and so on.  The
+# best way to do this is simply to set KFLAGS and LIBS values and then
+# chain to the main "linux" target, as in the examples just above.
 
 #Sharp Zaurus SL-5500 - Linux based
 zsl5500:
@@ -5536,15 +6285,6 @@ zsl5500:
        $(MAKE) linuxnc KTARGET=$${KTARGET:-$(@)} "KFLAGS=-DZSL5500" \
        "CC = gcc" "CC2 = gcc"
 
-# A minimum-size version for Linux that does only scripting and
-# serial communication -- no networks, no file transfer.
-linuxso:
-       $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} "CC = gcc" "CC2 = gcc" \
-       "CFLAGS = -O -DLINUX -pipe -funsigned-char -DPOSIX -DCK_POSIX_SIG \
-       -DLINUXFSSTND -DNOCOTFMC -DNOXFER -DNODEBUG -DNOCSETS -DNOHELP \
-       -DNONET -DMINIDIAL -DNOSCRIPT -DNOIKSD -DNOPUSH $(KFLAGS)" \
-       "LNKFLAGS = $(LNKFLAGS)" "LIBS = "
-
 #Mklinux DR3 has horrible bug in <utmpbits.h> - see ckufio.c.
 mklinux:
        $(MAKE) KTARGET=$${KTARGET:-$(@)} "KFLAGS=-DUTMPBUG" \
@@ -5580,16 +6320,9 @@ linuxppc:
        fi
 
 
-# The remaining Linux entries are for special or customized builds.  They
-# have not been generalized like the ones above.  Ideally, we should allow
-# for every combination of libc vs glibc, gcc vs egcs, curses vs ncurses,
-# Kerberos IV vs Kerberos V vs SRP (in any combination), and so on --
-# volunteers welcome.
-
+# Like "make linux" but built with egcs rather than gcc.
 # If you get "Internal compiler error xxx, output pipe has been closed",
 # try removing -pipe.
-
-# Like "make linux" but built with egcs rather than gcc.
 linuxegcs:
        @echo 'Making C-Kermit $(CKVER) for Linux 1.2 or later with egcs...'
        $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} "CC = egcs" "CC2 = egcs" \
@@ -5599,7 +6332,7 @@ linuxegcs:
        "LNKFLAGS = $(LNKFLAGS)" "LIBS = -lncurses -lcrypt -lresolv"
 
 #Linux on Intel PC with Cygnus or MIT Kerberos 5 1.2.1 (no K4 compatibility).
-linux+krb5:
+linux+krb5-old:
        @echo 'Making C-Kermit $(CKVER) for Linux on Intel with Kerberos...'
        $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} "CC = gcc" "CC2 = gcc" \
        "CFLAGS = -O -funsigned-char -pipe -DPOSIX -DLINUX -DNOCOTFMC \
@@ -5710,7 +6443,7 @@ linux+shadow+pam:
 #Linux configured for SSL/TLS.
 #Remove -ltermcap if it causes trouble e.g. in Debian 2.2.
 #If you have OpenSSL 0.9.7 or later, add -DOPENSSL_097 to KFLAGS.
-linux+openssl:
+oldlinux+openssl:
        @echo 'Making C-Kermit $(CKVER) for Linux on i386 with SSL/TLS...'
        $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} "CC = gcc" "CC2 = gcc" \
        "CFLAGS = -O -funsigned-char -pipe -DPOSIX -DLINUX -DNOCOTFMC \
@@ -5733,19 +6466,6 @@ linux+openssl+shadow:
        "LIBS= $(SSLLIB) \
        -lncurses -ltermcap -lssl -lcrypto -lm -lresolv -lcrypt"
 
-#Linux configured for SSL/TLS, ZLIB, PAM and Shadow Passwords
-#Remove -ltermcap if it causes trouble e.g. in Debian 2.2.
-#If you have OpenSSL 0.9.7 or later, add -DOPENSSL_097 to KFLAGS.
-linux+openssl+zlib+shadow+pam:
-       @echo 'Making C-Kermit $(CKVER) for Linux on i386 with SSL/TLS...'
-       $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} "CC = gcc" "CC2 = gcc" \
-       "CFLAGS = -O -funsigned-char -pipe -DPOSIX -DLINUX -DNOCOTFMC \
-       -DCK_AUTHENTICATION -DCK_SSL -DCK_PAM -DZLIB \
-       -DCK_CURSES -DCK_POSIX_SIG -DTCPSOCKET -DLINUXFSSTND -DHAVE_CRYPT_H \
-       -DFNFLOAT -DCK_SHADOW $(SSLINC) $(KFLAGS)" "LNKFLAGS = $(LNKFLAGS)" \
-       "LIBS= $(SSLLIB) \
-       -lncurses -ltermcap -lssl -lcrypto -lm -lresolv -lcrypt -lz -lpam -ldl"
-
 #Linux on Intel PC with SRP and SSL/TLS.
 #
 # libsrp.a should be build with OpenSSL
@@ -6018,6 +6738,12 @@ redhat9+srp:
        $(MAKE) linux+krb5+krb4+srp+openssl+zlib+shadow+pam \
        KTARGET=$${KTARGET:-$(@)} "KFLAGS = -DRH90 -DOPENSSL_097 $(KFLAGS)"
 
+#For Red Hat AS 2.1 with OpenSSL
+redhat21+ssl:
+       @echo "Building SECURE Kermit for Red Hat 2.1..."
+       $(MAKE) linux+openssl+zlib+shadow+pam \
+       KTARGET=$${KTARGET:-$(@)} "KFLAGS =  $(KFLAGS)"
+
 #Red Hat Linux 8.0 - full install includes Kerberos 5 (4 compat), PAM, SSL.
 #Also works around bug in curses in which terminal goes dead after
 #returning from file-transfer display.
@@ -6076,7 +6802,7 @@ linux+krb5+openssl+zlib+shadow+pam:
        @echo 'Making C-Kermit $(CKVER) for Linux on i386 with KRB5,SSL...'
        $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} "CC = gcc" "CC2 = gcc" \
        "CFLAGS = -g -O -funsigned-char -pipe -DPOSIX -DLINUX -DNOCOTFMC \
-       -DCK_AUTHENTICATION -DCK_KERBEROS  -DKRB5 -DCK_SHADOW \
+       -DCK_AUTHENTICATION -DCK_KERBEROS  -DKRB5 -DCK_SHADOW -DHAVE_PTMX \
        -DCK_ENCRYPTION -DCK_CAST -DCK_DES -DLIBDES -DCK_SSL -DCK_PAM -DZLIB \
        -DCK_CURSES -DCK_POSIX_SIG -DTCPSOCKET -DLINUXFSSTND -DHAVE_CRYPT_H \
        $(K5INC) $(K5INC)/krb5 $(SSLINC) \
@@ -6746,6 +7472,8 @@ sco32v505net+ssl:
        @echo TCP/IP networking and OpenSSL added...
        $(MAKE) "MAKE=$(MAKE)" sco32v500net+ssl KTARGET=$${KTARGET:-$(@)} \
        "KFLAGS=-DSCO_OSR505 -DNOSHADOW -b elf -DPOSIX $(KFLAGS) " \
+       "LIBS=$(SSLLIB) -lcurses -lsocket -lssl -lcrypto $(LIBS)" \
+       "LNKFLAGS=$(LNKFLAGS)"
 
 #SCO OpenServer 5.0.5 with networking, SCO UDK.
 #See comments with above sco32v505 targets.
@@ -6814,46 +7542,196 @@ sco32v506a:
        "KFLAGS=-DSCO_OSR505 -DSCO_OSR506 -DSCO_OSR506A -DNEEDMDMDEFS \
        -b elf -DPOSIX $(KFLAGS)"
 
-#SCO OpenServer 5.0.6a with networking, SCO development tools.
-# Add -DDCLTIMEVAL when building with UDK.
-sco32v506anet:
-       @echo TCP/IP networking added...
-       $(MAKE) "MAKE=$(MAKE)" sco32v500net KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS=-DSCO_OSR505 -DSCO_OSR506 -DSCO_OSR506A -DNEEDMDMDEFS \
-       -b elf -DPOSIX $(KFLAGS)"
+#SCO OpenServer 5.0.6a with networking, SCO development tools.
+# Add -DDCLTIMEVAL when building with UDK.
+sco32v506anet:
+       @echo TCP/IP networking added...
+       $(MAKE) "MAKE=$(MAKE)" sco32v500net KTARGET=$${KTARGET:-$(@)} \
+       "KFLAGS=-DSCO_OSR505 -DSCO_OSR506 -DSCO_OSR506A -DNEEDMDMDEFS \
+       -b elf -DPOSIX $(KFLAGS)"
+
+#SCO OpenServer 5.0.7, no networking, SCO development tools.
+#Adds flags to make PTY and SSH commands work.  These have been tested
+#only in 5.0.7 but probably they can also be added to earlier OSR5 targets.
+sco32v507:
+       $(MAKE) "MAKE=$(MAKE)" sco32v500 KTARGET=$${KTARGET:-$(@)} \
+       "KFLAGS=-DSCO_OSR505 -DSCO_OSR506 -DSCO_OSR507 -DNEEDMDMDEFS \
+       -DHAVE_PTSNAME -DHAVE_PTMX -DHAVE_GRANTPT \
+       -b elf -DPOSIX $(KFLAGS)"
+
+#SCO OpenServer 5.0.7 as above but with networking.
+sco32v507net:
+       @echo TCP/IP networking added...
+       $(MAKE) "MAKE=$(MAKE)" sco32v500net KTARGET=$${KTARGET:-$(@)} \
+       "KFLAGS=-DSCO_OSR505 -DSCO_OSR506 -DSCO_OSR507 -DNEEDMDMDEFS \
+       -DHAVE_PTSNAME -DHAVE_PTMX -DHAVE_GRANTPT \
+       -b elf -DPOSIX $(KFLAGS)"
+
+#SCO OpenServer 6 (new target 30 Jan 2006)
+sco_osr600:
+       @echo Making C-Kermit $(CKVER) for SCO OpenServer 6.0.0...
+       $(MAKE) xermit KTARGET=$${KTARGET:-$(@)} \
+       "CFLAGS= -O -DDIRENT -DHDBUUCP -DSVR4 -DCK_SCOV5 -DCK_RTSCTS \
+       -DCK_CURSES -DCK_WREFRESH -DCK_NEWTERM -DSELECT -DSELECT_H \
+       -DNOGETUSERSHELL -DNOLSTAT -DNOLINKBITS -DTCPSOCKET \
+       -DNO_DNS_SRV -DSCO_OSR505 -DSCO_OSR506 -DSCO_OSR507 -DNEEDMDMDEFS \
+       -DHAVE_PTSNAME -DHAVE_PTMX -DHAVE_GRANTPT -DDCLTIMEVAL \
+       -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 \
+       -DSOCKOPT_T=socklen_t -DGSOCKNAME_T=size_t -DGPEERNAME_T=size_t \
+       -DHERALD=\"\\\" SCO OpenServer `uname -v`\\\"\" \
+       -b elf -DPOSIX $(KFLAGS)" \
+       "LIBS=-lcurses -lsocket $(LIBS)" "LNKFLAGS=$(LNKFLAGS)"
+
+#Tandy 16/6000 with Xenix 3.0 (16 bits)
+#C-Kermit 7.0 (and later) do not build here; "too many defines".
+#Add more -DNOxxx options to remove features if program won't load.
+#Successful operation is a function of program size, physical memory,
+#available swap space, etc.  The following stripped-down configuration
+#seems to work on most Tandy 6000s.  NOTE: "-+" means allow long variable
+#names, needed for C-Kermit 6.0 because some identifiers are not unique
+#within the first six characters.
+trs16:
+       @echo 'Making C-Kermit $(CKVER) for Tandy 16/6000, Xenix 3.0...'
+       $(MAKE) wermit KTARGET=$${KTARGET:-$(@)} \
+       "CFLAGS = -+ -DATTSV -DTRS16 -DNOMKDIR -DDCLPOPEN -DCK_CURSES \
+       -DNODEBUG -DNOTLOG -DNOHELP -DNOSCRIPT -DNOCSETS -DNOIKSD \
+       -DNOREDIRECT -DNOSYSLOG -DNOPUTENV -DNOREALPATH -DNOLEARN \
+       $(KFLAGS) -O" "LIBS= -lcurses -ltermcap" "LNKFLAGS = -+ -n -s"
+
+# QNX 4.21 and above, 32-bit version, Watcom C32 10.6, fully configured,
+# except no job control because QNX 4.x does not support it.  New NCURSES
+# library used instead of CURSES.
+#
+# -Oatx optimizes to favor speed over size: loop optimization, inline fn's.
+# -Os favors size over speed.  Saves 30-40K out of about 1.75M.
+# -3r = generate 386 code with register-based arg passing.
+# -3s = generate 386 code with stack-based arg passing.
+# -ms = separate code & data 4GB segments (32-bit builds only).
+# -mf = flat memory model code+data in one 4GB segment (ditto).
+# -zc = place literal strings in code segment.
+# -N4M = Big stack (increase the digit upon SIGSEGVs at runtime).
+# chars are unsigned by default (-j makes them signed by default).
+# -NOUUCP is included because QNX doesn't use it.
+# Add these to the end if you like but they dump core on my QNX 4.25 system:
+#
+#      @wermit -h >use.qnx
+#      @usemsg wermit use.qnx
+#      @rm use.qnx
+#
+# If you get warnings about HEADER or C_IN add -DNO_DNS_SRV.
+qnx32:
+       @echo 'Making C-Kermit $(CKVER) for QNX 4.2x, 32-bit...'
+       $(MAKE) xermit \
+       "LNKFLAGS = -N4M -3r" \
+       "CFLAGS = -ms -3r -DQNX -DTCPSOCKET -DCK_CURSES -DNOGETUSERSHELL \
+       -DCK_WREFRESH -DCK_REDIR -DSELECT -DSELECT_H -DCK_RTSCTS -DNOJC \
+       -DNOINITGROUPS -DNOUUCP -DCK_ANSIC -DPID_T=pid_t -Oatx -zc $(KFLAGS)" \
+       "LIBS= -lsocket -lncurses -ltermcap"
+
+# As above but no networking since some QNX systems do not have TCP/IP
+# installed, or the TCP/IP developers kit, which includes all the needed
+# header files.  This entry has not been tested on a QNX system that, in
+# fact, does not have TCP/IP installed; some adjustments might be necessary,
+# in particular regarding the use of select(): is -lsocket needed, can we
+# get the needed definitions from non-TCP/IP header files (FD_SET, etc)?
+qnx32nonet:
+       @echo 'Making C-Kermit $(CKVER) for QNX 4.2x, 32-bit, no net...'
+       $(MAKE) xermit \
+       "LNKFLAGS = -N4M -3r" \
+       "CFLAGS = -3r -ms -DQNX -DNONET -DNOIKSD -DCK_CURSES \
+       -DCK_WREFRESH -DCK_REDIR -DSELECT -DSELECT_H -DCK_RTSCTS -DNOJC \
+       -DNOUUCP -DCK_ANSIC -DPID_T=pid_t -Oatx -zc $(KFLAGS)" \
+       "LIBS= -lsocket -lncurses -ltermcap"
+       @wermit -h >use.qnx
+       @usemsg wermit use.qnx
+       @rm use.qnx
+
+# Synonym for qnx32.
+qnx:
+       $(MAKE) qnx32 "KFLAGS=$(KFLAGS)"
 
-#SCO OpenServer 5.0.7, no networking, SCO development tools.
-#Adds flags to make PTY and SSH commands work.  These have been tested
-#only in 5.0.7 but probably they can also be added to earlier OSR5 targets.
-sco32v507:
-       $(MAKE) "MAKE=$(MAKE)" sco32v500 KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS=-DSCO_OSR505 -DSCO_OSR506 -DSCO_OSR507 -DNEEDMDMDEFS \
-       -DHAVE_PTSNAME -DHAVE_PTMX -DHAVE_GRANTPT \
-       -b elf -DPOSIX $(KFLAGS)"
+# QNX 4.21 and above, 16-bit version, Watcom C 8.5 - and higher on i286 PCs
+# and above.
+#
+#      IMPORTANT: Do not use Watcom C 10.6!!!
+#      If you have it installed, add "-v9.52 to CFLAGS"
+#
+# NOTE: QNX 4.23 onward does not work on 286's anyway.
+# Stacksize 26000, objects larger than 100 bytes in their own segments,
+# string constants to the codesegment, etc.  Fully configured except job ctrl.
+# This entry works for building a 16-bit executable on a 32-bit system, but
+# has not been tested on a 16-bit system.  Uses large memory model, links
+# explicitly with large-model sockets library.  Correct-model curses library
+# is chosen automatically.  See comment in qnx32 entry about -DNOUUCP.
+#
+# WARNING:
+#
+# Watcom C prior to 10.6 never had released curses library. To link against it,
+# you must obtain ported free curses source from ftp://ftp.qnx.com/usr/free,
+# then compile and build library (cursesl.lib) and place it in /usr/lib.  You
+# must also copy curses.h to /usr/include.  Be aware that if you have Watcom
+# 10.6 installed, you should already have curses.h, which is the new ncurses
+# library. You must back it up and use free curses.h instead, since ncurses is
+# only for 32-bit applications and some definitions in these files are
+# different (e.g., clearok()).  For safety, curses is not defined in build.
+#
+# In 7.0 -DNOHELP added to keep ckuus2.c from blowing up; NOCSETS and NOSPL
+# added because ckuus4 was blowing up, and NOFLOAT just because it seemed
+# dangerous (remove -DNOFLOAT if you want to try it), The result works OK
+# except for some mysterious beeps upon termination of the top-level keyword.
+#
+# Things to try next time we get in trouble:
+#  . Change -zt100 to something smaller like -zt25
+#  . Change -Oatx to -Omilerat (enable stack checking)
+#  . Maybe get rid of -v9.52 -- it's only there because we were warned.
+#
+qnx16:
+       @echo 'Making C-Kermit $(CKVER) for QNX 4.21, 16-bit...'
+       $(MAKE) xermit \
+       "LNKFLAGS = -2 -ml -N 26000" \
+       "CFLAGS = -2 -Oatx -zc -zt100 -ml -DQNX -DQNX16 -DNOUUCP -DNOHELP \
+       -DCK_REDIR -DSELECT -DSELECT_H -DNOJC -DNOGETUSERSHELL -DNOCSETS \
+       -v9.52 -DTCPSOCKET -DCK_RTSCTS -DCK_ANSIC -DNOINITGROUPS -DNOKVERBS \
+       -DNORANDOM -DNOCSETS -DNOSPL -DNOFLOAT -DPID_T=pid_t $(KFLAGS)"
 
-#SCO OpenServer 5.0.7 as above but with networking.
-sco32v507net:
-       @echo TCP/IP networking added...
-       $(MAKE) "MAKE=$(MAKE)" sco32v500net KTARGET=$${KTARGET:-$(@)} \
-       "KFLAGS=-DSCO_OSR505 -DSCO_OSR506 -DSCO_OSR507 -DNEEDMDMDEFS \
-       -DHAVE_PTSNAME -DHAVE_PTMX -DHAVE_GRANTPT \
-       -b elf -DPOSIX $(KFLAGS)"
+# QNX 4.1, 16-bit version, with Watcom C 8.5 on i286 PCs and above.
+# stacksize 26000, objects larger than 100 bytes in their own segments,
+# string constants to the codesegment, etc.  Add -DNOUUCP if desired.
+qnx16_41:
+       @echo 'Making C-Kermit $(CKVER) for QNX 4.1, 16-bit...'
+       $(MAKE) xermit \
+       "LNKFLAGS = -mh -N 26000" "CFLAGS = -Wc,-fpc -Wc,-j -DNOGETUSERSHELL \
+       -Wc,-Ols -Wc,-zdf -Wc,-zc -Wc,-zt100 -mh -DPOSIX -DQNX -DDIRENT \
+       -DNOCYRIL -DNODEBUG -DNOMSEND -DMINIDIAL -DNOXMIT -DNOSCRIPT -DNOSPL \
+       -DNOSETKEY -DNOINITGROUPS -DQNX16 -DPID_T=pid_t $(KFLAGS)"
 
-#Tandy 16/6000 with Xenix 3.0
-#Add more -DNOxxx options to remove features if program won't load.
-#Successful operation is a function of program size, physical memory,
-#available swap space, etc.  The following stripped-down configuration
-#seems to work on most Tandy 6000s.  NOTE: "-+" means allow long variable
-#names, needed for C-Kermit 6.0 because some identifiers are not unique
-#within the first six characters.
-#C-Kermit 7.0 does not build here; "too many defines".
-trs16:
-       @echo 'Making C-Kermit $(CKVER) for Tandy 16/6000, Xenix 3.0...'
-       $(MAKE) wermit KTARGET=$${KTARGET:-$(@)} \
-       "CFLAGS = -+ -DATTSV -DTRS16 -DNOMKDIR -DDCLPOPEN -DCK_CURSES \
-       -DNODEBUG -DNOTLOG -DNOHELP -DNOSCRIPT -DNOCSETS -DNOIKSD \
-       -DNOREDIRECT -DNOSYSLOG -DNOPUTENV -DNOREALPATH -DNOLEARN \
-       $(KFLAGS) -O" "LIBS= -lcurses -ltermcap" "LNKFLAGS = -+ -n -s"
+# QNX Neutrino 2 (pwaechtler@qnx.de) crosscompiled on QNX 4.25.
+# Gets lots of compiler warnings.
+qnx_nto2+:
+       @echo 'Making C-Kermit $(CKVER) for QNX Neutrino 2+ '
+       cc -o wart ckwart.c
+       $(MAKE) xermit \
+       "CC = qcc -Vgcc_ntox86" \
+       "CC2 = qcc -Vgcc_ntox86" \
+       "LNKFLAGS = " \
+       "CFLAGS = -DNEUTRINO -DTCPSOCKET -DCK_CURSES -DNOGETUSERSHELL \
+       -DNOUUCP -DCK_WREFRESH -DCK_REDIR -DSELECT -DSELECT_H -DCK_RTSCTS \
+       -DNOJC -DNOINITGROUPS -DCK_ANSIC -DPID_T=pid_t -DUNIX -DDIRENT \
+       -DMYREAD -DBSD44ORPOSIX -DSVORPOSIX -DNDGPWNAM $(KFLAGS)" \
+       "LIBS= -lsocket -lncurses "
+
+# QNX 6 (= Neutrino 2.xx) native build (kirussel@cisco.com).
+qnx6:
+       @echo 'Making C-Kermit $(CKVER) for QNX6'
+       $(MAKE) xermit KTARGET=QNX6 \
+       "CFLAGS = -DPOSIX -DCK_POSIX_SIG -DNETPTY -DNOARROWKEYS \
+       -DUSE_TIOCSDTR -DBIGBUFOK -DCKMAXOPEN=100 -DRLOGCODE -DNOREALPATH \
+       -DMAXNAMLEN=48 -DQNX6 -DUSE_TERMIO -DINIT_SPTY \
+       -DCK_CURSES -DCK_WREFRESH -DCK_NEWTERM -DDYNAMIC \
+       -DTCPSOCKET -DNOGETUSERSHELL -DCK_REDIR -DSELECT -DSELECT_H \
+       -DCK_RTSCTS -DNOJC -DSVORPOSIX -DBSD44ORPOSIX -DNOUUCP -DCK_ANSIC \
+       $(KFLAGS) -O" \
+       "LIBS= -lsocket  -lncurses"
 
 #MINIX/2.0 32 Bit version for intel 386+ running the POSIX-compliant MINIX
 # version 2.0 (The definition of fatal avoids a conflict with a symbol by
@@ -6904,7 +7782,7 @@ minix386gcc:
 # Make sure make(1) has (at least) 100000 chmemory!
 # If you are using the Amsterdam C compiler, you might have to add "-D__ACK__".
 minix68k:
-       @echo 'Making C-Kermit $(CKVER) for MINIX 68k with ACK...
+       @echo 'Making C-Kermit $(CKVER) for MINIX 68k with ACK...'
        $(MAKE) wermit KTARGET=$${KTARGET:-$(@)} \
        "CFLAGS= -DV7 -DMINIX -D_MINIX -D_POSIX_SOURCE -DNOLEARN \
        -DNODIAL -DNOHELP -DNODEBUG -DNOTLOG \
@@ -6919,7 +7797,7 @@ minix68k:
 # call of make fails due to memory shortage.  Try "make -n minixc68 >makeit",
 # followed by ". makeit".  Otherwise, as above.
 minixc68:
-       @echo 'Making C-Kermit $(CKVER) for MINIX 68k with c68...
+       @echo 'Making C-Kermit $(CKVER) for MINIX 68k with c68...'
        $(MAKE) wermit "CC= cc -c68" KTARGET=$${KTARGET:-$(@)} \
        "CFLAGS= -DV7 -DMINIX -D_MINIX -D_POSIX_SOURCE -DNOLEARN \
        -DNODIAL -DNOHELP -DNODEBUG -DNOTLOG \
@@ -6929,7 +7807,7 @@ minixc68:
 #MINIX - 68k version with c68 compiler.
 #A variation on the above that was recently (Sep 95) reported to work.
 minixc68a:
-       @echo 'Making C-Kermit $(CKVER) for MINIX 68k with c68...
+       @echo 'Making C-Kermit $(CKVER) for MINIX 68k with c68...'
        $(MAKE) wermit "CC= cc -c68" KTARGET=$${KTARGET:-$(@)} \
        "CFLAGS= -DV7 -DMINIX -D_MINIX -D_POSIX_SOURCE \
        -DCK_ANSIC -DNODEBUG -DNOTLOG -DMINIDIAL -DEXTEN -DMYCURSES \
@@ -7519,141 +8397,6 @@ dnix5r3ansinet:
        -DTCPSOCKET -DCK_ANSILIBS -DCK_CURSES -DRENAME -O -X7 -X9 $(KFLAGS) \
        -I/usr/include/bsd" "LIBS= -ln -lcurses"
 
-# QNX 4.21 and above, 32-bit version, Watcom C32 10.6, fully configured,
-# except no job control because QNX 4.x does not support it.  New NCURSES
-# library used instead of CURSES.
-#
-# -Oatx optimizes to favor speed over size: loop optimization, inline fn's.
-# -Os favors size over speed.  Saves 30-40K out of about 1.75M.
-# -3r = generate 386 code with register-based arg passing.
-# -3s = generate 386 code with stack-based arg passing.
-# -ms = separate code & data 4GB segments (32-bit builds only).
-# -mf = flat memory model code+data in one 4GB segment (ditto).
-# -zc = place literal strings in code segment.
-# -N4M = Big stack (increase the digit upon SIGSEGVs at runtime).
-# chars are unsigned by default (-j makes them signed by default).
-# -NOUUCP is included because QNX doesn't use it.
-# Add these to the end if you like but they dump core on my QNX 4.25 system:
-#
-#      @wermit -h >use.qnx
-#      @usemsg wermit use.qnx
-#      @rm use.qnx
-#
-# If you get warnings about HEADER or C_IN add -DNO_DNS_SRV.
-qnx32:
-       @echo 'Making C-Kermit $(CKVER) for QNX 4.2x, 32-bit...'
-       $(MAKE) xermit \
-       "LNKFLAGS = -N4M -3r" \
-       "CFLAGS = -ms -3r -DQNX -DTCPSOCKET -DCK_CURSES -DNOGETUSERSHELL \
-       -DCK_WREFRESH -DCK_REDIR -DSELECT -DSELECT_H -DCK_RTSCTS -DNOJC \
-       -DNOINITGROUPS -DNOUUCP -DCK_ANSIC -DPID_T=pid_t -Oatx -zc $(KFLAGS)" \
-       "LIBS= -lsocket -lncurses -ltermcap"
-
-# As above but no networking since some QNX systems do not have TCP/IP
-# installed, or the TCP/IP developers kit, which includes all the needed
-# header files.  This entry has not been tested on a QNX system that, in
-# fact, does not have TCP/IP installed; some adjustments might be necessary,
-# in particular regarding the use of select(): is -lsocket needed, can we
-# get the needed definitions from non-TCP/IP header files (FD_SET, etc)?
-qnx32nonet:
-       @echo 'Making C-Kermit $(CKVER) for QNX 4.2x, 32-bit, no net...'
-       $(MAKE) xermit \
-       "LNKFLAGS = -N4M -3r" \
-       "CFLAGS = -3r -ms -DQNX -DNONET -DNOIKSD -DCK_CURSES \
-       -DCK_WREFRESH -DCK_REDIR -DSELECT -DSELECT_H -DCK_RTSCTS -DNOJC \
-       -DNOUUCP -DCK_ANSIC -DPID_T=pid_t -Oatx -zc $(KFLAGS)" \
-       "LIBS= -lsocket -lncurses -ltermcap"
-       @wermit -h >use.qnx
-       @usemsg wermit use.qnx
-       @rm use.qnx
-
-# Synonym for qnx32.
-qnx:
-       $(MAKE) qnx32 "KFLAGS=$(KFLAGS)"
-
-# QNX 4.21 and above, 16-bit version, Watcom C 8.5 - and higher on i286 PCs
-# and above.
-#
-#      IMPORTANT: Do not use Watcom C 10.6!!!
-#      If you have it installed, add "-v9.52 to CFLAGS"
-#
-# NOTE: QNX 4.23 onward does not work on 286's anyway.
-# Stacksize 26000, objects larger than 100 bytes in their own segments,
-# string constants to the codesegment, etc.  Fully configured except job ctrl.
-# This entry works for building a 16-bit executable on a 32-bit system, but
-# has not been tested on a 16-bit system.  Uses large memory model, links
-# explicitly with large-model sockets library.  Correct-model curses library
-# is chosen automatically.  See comment in qnx32 entry about -DNOUUCP.
-#
-# WARNING:
-#
-# Watcom C prior to 10.6 never had released curses library. To link against it,
-# you must obtain ported free curses source from ftp://ftp.qnx.com/usr/free,
-# then compile and build library (cursesl.lib) and place it in /usr/lib.  You
-# must also copy curses.h to /usr/include.  Be aware that if you have Watcom
-# 10.6 installed, you should already have curses.h, which is the new ncurses
-# library. You must back it up and use free curses.h instead, since ncurses is
-# only for 32-bit applications and some definitions in these files are
-# different (e.g., clearok()).  For safety, curses is not defined in build.
-#
-# In 7.0 -DNOHELP added to keep ckuus2.c from blowing up; NOCSETS and NOSPL
-# added because ckuus4 was blowing up, and NOFLOAT just because it seemed
-# dangerous (remove -DNOFLOAT if you want to try it), The result works OK
-# except for some mysterious beeps upon termination of the top-level keyword.
-#
-# Things to try next time we get in trouble:
-#  . Change -zt100 to something smaller like -zt25
-#  . Change -Oatx to -Omilerat (enable stack checking)
-#  . Maybe get rid of -v9.52 -- it's only there because we were warned.
-#
-qnx16:
-       @echo 'Making C-Kermit $(CKVER) for QNX 4.21, 16-bit...'
-       $(MAKE) xermit \
-       "LNKFLAGS = -2 -ml -N 26000" \
-       "CFLAGS = -2 -Oatx -zc -zt100 -ml -DQNX -DQNX16 -DNOUUCP -DNOHELP \
-       -DCK_REDIR -DSELECT -DSELECT_H -DNOJC -DNOGETUSERSHELL -DNOCSETS \
-       -v9.52 -DTCPSOCKET -DCK_RTSCTS -DCK_ANSIC -DNOINITGROUPS -DNOKVERBS \
-       -DNORANDOM -DNOCSETS -DNOSPL -DNOFLOAT -DPID_T=pid_t $(KFLAGS)"
-
-# QNX 4.1, 16-bit version, with Watcom C 8.5 on i286 PCs and above.
-# stacksize 26000, objects larger than 100 bytes in their own segments,
-# string constants to the codesegment, etc.  Add -DNOUUCP if desired.
-qnx16_41:
-       @echo 'Making C-Kermit $(CKVER) for QNX 4.1, 16-bit...'
-       $(MAKE) xermit \
-       "LNKFLAGS = -mh -N 26000" "CFLAGS = -Wc,-fpc -Wc,-j -DNOGETUSERSHELL \
-       -Wc,-Ols -Wc,-zdf -Wc,-zc -Wc,-zt100 -mh -DPOSIX -DQNX -DDIRENT \
-       -DNOCYRIL -DNODEBUG -DNOMSEND -DMINIDIAL -DNOXMIT -DNOSCRIPT -DNOSPL \
-       -DNOSETKEY -DNOINITGROUPS -DQNX16 -DPID_T=pid_t $(KFLAGS)"
-
-# QNX Neutrino 2 (pwaechtler@qnx.de) crosscompiled on QNX 4.25.
-# Gets lots of compiler warnings.
-qnx_nto2+:
-       @echo 'Making C-Kermit $(CKVER) for QNX Neutrino 2+ '
-       cc -o wart ckwart.c
-       $(MAKE) xermit \
-       "CC = qcc -Vgcc_ntox86" \
-       "CC2 = qcc -Vgcc_ntox86" \
-       "LNKFLAGS = " \
-       "CFLAGS = -DNEUTRINO -DTCPSOCKET -DCK_CURSES -DNOGETUSERSHELL \
-       -DNOUUCP -DCK_WREFRESH -DCK_REDIR -DSELECT -DSELECT_H -DCK_RTSCTS \
-       -DNOJC -DNOINITGROUPS -DCK_ANSIC -DPID_T=pid_t -DUNIX -DDIRENT \
-       -DMYREAD -DBSD44ORPOSIX -DSVORPOSIX -DNDGPWNAM $(KFLAGS)" \
-       "LIBS= -lsocket -lncurses "
-
-# QNX 6 (= Neutrino 2.xx) native build (kirussel@cisco.com).
-qnx6:
-       @echo 'Making C-Kermit $(CKVER) for QNX6'
-       $(MAKE) xermit KTARGET=QNX6 \
-       "CFLAGS = -DPOSIX -DCK_POSIX_SIG -DNETPTY -DNOARROWKEYS \
-       -DUSE_TIOCSDTR -DBIGBUFOK -DCKMAXOPEN=100 -DRLOGCODE -DNOREALPATH \
-       -DMAXNAMLEN=48 -DQNX6 -DUSE_TERMIO -DINIT_SPTY \
-       -DCK_CURSES -DCK_WREFRESH -DCK_NEWTERM -DDYNAMIC \
-       -DTCPSOCKET -DNOGETUSERSHELL -DCK_REDIR -DSELECT -DSELECT_H \
-       -DCK_RTSCTS -DNOJC -DSVORPOSIX -DBSD44ORPOSIX -DNOUUCP -DCK_ANSIC \
-       $(KFLAGS) -O" \
-       "LIBS= -lsocket  -lncurses"
-
 #Ridge 32 with ROS 3.2
 ridge32:
        @echo 'Making C-Kermit $(CKVER) Ridge 32 ROS 3.2'
@@ -7715,7 +8458,7 @@ altos3:
 # -DNOSPL, plus every other -DNOxxx flag there is, except for -DNOICP
 # (see ckccfg.txt).
 minix:
-       @echo 'Making C-Kermit $(CKVER) for MINIX, no command parser...
+       @echo 'Making C-Kermit $(CKVER) for MINIX, no command parser...'
        @echo 'TOTALLY UNTESTED!'
        $(MAKE) wermit EXT=s \
        "CFLAGS= -DV7 -DMINIX -i -D_MINIX -D_POSIX_SOURCE \
@@ -7727,7 +8470,7 @@ minix:
 #MINIX - PC version with 64K+64K limit, new (as yet unreleased) ACK 2.0 beta C
 #compiler, which outputs .o object files, rather than .s.  But 'make' still
 #expects .s files, so must be patched to use .o.  Tested on Minix 1.5.10.
-minixnew:
+minix15:
        @echo 'Making C-Kermit $(CKVER) for MINIX (new ACK 2.0 compiler),'
        @echo 'no command parser...  TOTALLY UNTESTED!'
        $(MAKE) wermit \
@@ -7736,6 +8479,24 @@ minixnew:
        -DNOHELP -DNODEBUG -DNOTLOG -DNOSCRIPT -DNOCSETS -DNOICP $(KFLAGS)" \
        "LNKFLAGS= -i -T"
 
+#MINIX3 - MINIX 3.0 (no VM) - May-Aug 2005 (not sure if this ever worked...)
+minix3:
+       @echo 'Making C-Kermit $(CKVER) for MINIX3...'
+       $(MAKE) wermit KTARGET=$${KTARGET:-$(@)} \
+       "CFLAGS= -DPOSIX -DNOUUCP -DNOLEARN $(KFLAGS) -DMINIX2 \
+       -DMINIX3 -DNO_PARAM_H -DNOSYSLOG -DNOGETUSERSHELL \
+       -DNOINITGROUPS -DNOFTRUNCATE -DNOARROWKEYS -DDNOREALPATH \
+       -DTCPSOCKET -DNOTIMEZONE -DNOFTP -DNO_DNS_SRV -O"
+
+#MINIX315 - MINIX 3 1.5 - January 2010
+minix315:
+       @echo 'Making C-Kermit $(CKVER) for Minix 3 1.5...'
+       $(MAKE) wermit KTARGET=$${KTARGET:-$(@)} \
+       "CFLAGS= -DMINIX315 -DPOSIX -DNOUUCP -DNOJC -DNOLEARN $(KFLAGS) \
+       -DHAVE_OPENPTY -DNO_PARAM_H -DNOSYSLOG -DNOGETUSERSHELL \
+       -DSYSTIMEH -DNOINITGROUPS -DNOFTRUNCATE -DNOARROWKEYS -DNOREALPATH \
+       -DTCPSOCKET -DNOTIMEZONE -DNO_DNS_SRV -DNOFTP -O"
+
 #PFU Compact A Series UNIX System V R3, SX/A TISP V10/L50 (Japan)
 #Maybe the -i link option should be removed?
 sxae50: