home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / ckc197.zip / PATCHES-6.0 < prev    next >
Text File  |  1998-03-10  |  115KB  |  3,584 lines

  1. C-KERMIT 6.0 PATCHES  --  Source-code patches for C-Kermit 6.0.192
  2.  
  3.   Most recent update:   Tue Mar 10 16:50:30 1998
  4.   Highest patch number: 37
  5.  
  6. You can apply these patches if you have source code and the necessary C
  7. compiler and libraries to build a new executable.  There is no need to apply
  8. any patch if it does not apply to your configuration, or if the symptom does
  9. not affect you or your users.
  10.  
  11. Each patch is self-contained and independent from the others, unless
  12. otherwise noted.  Line numbers correspond to the source-code files of
  13. the 6.0.192 release.
  14.  
  15. The patches included in this file are believed to be safe, but come with no
  16. guarantees.  In particular, those submitted by users fall into the "use at
  17. your own risk" category.  The patches appear in chronological order in
  18. email-message format separated by lines of equal signs (=).
  19.  
  20. CONTENTS:
  21.  
  22. Number Domain           Description
  23.  0001   All UNIX         C-Kermit mishandles timestamps on files before 1970
  24.  0002    Solaris 2.5++    Compilation error on Solaris 2.5 with Pro C
  25.  0003    All VMS          CKERMIT.INI Fix for VMS
  26.  0004    VMS/VAX/UCX 2.0  C-Kermit 6.0 can't TELNET on VAX/VMS with UCX 2.0
  27.  0005    All              C-Kermit Might Send Packets Outside Window
  28.  0006    All              MOVE from SEND-LIST does not delete original files
  29.  0007    Solaris 2.5++    Higher serial speeds on Solaris 2.5
  30.  0008   All              C-Kermit application file name can't contain spaces
  31.  0009   AT&T 7300 UNIXPC setuid and hardware flow-control problems
  32.  0010   Linux on Alpha   Patch to make ckutio.c compile on Linux/Alpha
  33.  0011   OS-9/68000 2.4   Patch to make ck9con.c compile on OS-9/68000 2.4
  34.  0012   MW Coherent 4.2  Patches for successful build on Coherent 4.2
  35.  0013   SINIX-Y 5.43     "delay" variable conflicts with <sys/clock.h>
  36.  0014   VMS/VAX/CMU-IP   Subject: Patches for VAX/VMS 5.x + CMU-IP
  37.  0015   All              XECHO doesn't flush its output
  38.  0016   VMS              CD and other directory operations might not work
  39.  0017   Linux 1.2.x++    Use standard POSIX interface for high serial speeds
  40.  0018   UNIX             SET WILDCARD-EXPANSION SHELL dumps core
  41.  0019   All              Hayes V.34 modem init string problem
  42.  0020   All              READ command does not fail if file not open
  43.  0021   All              Problems with long function arguments 
  44.  0022   All              Certain \function()s can misbehave
  45.  0023   All              X MOD 0 crashes program
  46.  0024   All              Internal bulletproofing for lower() function
  47.  0025   OpenBSD          Real OpenBSD support for C-Kermit 6.0
  48.  0026   All              Incorrect checks for macro/command-file nesting depth
  49.  0027   All              ANSWER doesn't automatically CONNECT
  50.  0028   All              Overzealous EXIT warning
  51.  0029   All              OUTPUT doesn't echo when DUPLEX is HALF
  52.  0030   All              Minor problems with REMOTE DIRECTORY/DELETE/etc
  53.  0031   All              CHECK command broken
  54.  0032   All              Problem with SET TRANSMIT ECHO
  55.  0033   UNIX, VMS, etc   HELP SET SERVER says too much
  56.  0034   All              READ and !READ too picky about line terminators
  57.  0035   All              END from inside SWITCH doesn't work
  58.  0036   All              Problem telnetting to multihomed hosts
  59.  0037   All              Redirection failures in REMOTE xxx > file 
  60.  
  61. Legend:
  62.  ++ means "and above"
  63.  
  64. ----------------------------------------------------------------------------
  65. PATCH-LEVEL ANNOUNCEMENT
  66.  
  67. If you install any patches, you should also install an indicator of which
  68. patches were installed.  This is done as follows:
  69.  
  70.  1. In ckcmai.c, after the line:
  71.  
  72.         char *ck_ver = "C-Kermit 6.0.192";    /* C-Kermit Version */
  73.  
  74.     add a new line such as:
  75.  
  76.         char *ck_patch = "1 2 3 4 8 10";      /* Patches */
  77.  
  78.     The string contains the patch number of each patch that has been
  79.     installed, separated by spaces.  A range of patches can be indicated
  80.     in the customary hyphenated notation:
  81.  
  82.         char *ck_patch = "1-4 8 10";         /* Patches */
  83.  
  84.  2. Make the following change to the VERSION command in ckuusr.c:
  85.  
  86. *** /w/pub/ftp/kermit/f/ckuusr.c    Sun Nov 24 19:20:51 1996
  87. --- ./ckuusr.c    Sat Jan 11 11:58:14 1997
  88. ***************
  89. *** 3677,3694 ****
  90.   #endif /* NOCSETS */
  91.   
  92.       if (cx == XXVER) {            /* VERSION */
  93. +     extern char * ck_patch;
  94.      if ((y = cmcfm()) < 0) 
  95.             return(y);
  96.   
  97.      printf("%s, for%s\n Numeric: %ld",versio,ckxsys,vernum);
  98.      if (xvernum)
  99.        printf("C-Kermit %s",ck_ver);
  100.      if (verwho) 
  101.        printf("-%d\n",verwho); 
  102.      else printf("\n");
  103. +     if (*ck_patch)
  104. +       printf(" Patches: %s\n", ck_patch);
  105.      hmsga(copyright);
  106.   #ifdef OS2
  107.      shoreg();
  108.   #endif /* OS2 */
  109.  
  110.       return(success = 1);
  111.       }
  112.  
  113.  3. And make a similar change to the shover() routine in ckuus5.c:
  114.  
  115. *** /w/pub/ftp/kermit/f/ckuus5.c    Sun Nov 24 19:20:50 1996
  116. --- ./ckuus5.c    Sat Jan 11 12:03:41 1997
  117. ***************
  118. *** 2663,2673 ****
  119. --- 2663,2675 ----
  120.   shover() {
  121.       extern long xvernum;
  122.       extern char *ck_ver;
  123. +     extern char *ck_patch;
  124.       printf("\nVersions:\n %s\n Numeric: %ld",versio,vernum);
  125.       if (verwho) printf("-%d",verwho);
  126.       printf("\n");
  127.       if (xvernum)
  128.         printf("C-Kermit %s\n",ck_ver);
  129. +     if (*ck_patch) printf(" Patches: %s\n", ck_patch);
  130.       printf(xxdiff(ckxv,ckxsys) ? " %s for%s\n" : " %s\n",ckxv,ckxsys);
  131.       printf(xxdiff(ckzv,ckzsys) ? " %s for%s\n" : " %s\n",ckzv,ckzsys);
  132.       printf(" %s\n",protv);
  133.       ...
  134.  
  135. Whenever you install a new patch, be sure to update the ck_patch string in
  136. ckcmai.c, and then the VERSION and SHOW VERSION commands will indicate the
  137. patch level.
  138.  
  139. ====================
  140. X-Patch-Number: 0001
  141. Date: Sun, 1 Dec 1996 22:16:56 -0800
  142. From: Paul Eggert <eggert@twinsun.com>
  143. To: kermit-support@columbia.edu
  144. Subject: C-Kermit mishandles timestamps on files before 1970
  145.  
  146. C-Kermit 6.0.192 rejects files whose timestamps are before 1970-01-01
  147. local time.  But every Unix can represent files with timestamps before
  148. that.  It's common, for example, in the US/Pacific time zone to have a
  149. file with timestamp 1969-12-31 16:00:00 local time, since this equals
  150. 1970-01-01 00:00:00 UTC.  And many Unixes can represent times before
  151. the epoch, e.g. on Solaris 2.5.1:
  152.  
  153.   $ uname -a
  154.   SunOS shade 5.5.1 Generic_103640-03 sun4u sparc SUNW,Ultra-1
  155.   $ echo $TZ
  156.   UTC0
  157.   $ ls -l test
  158.   -rw-rw-r--   1 eggert   eggert         0 Dec 13  1901 test
  159.  
  160. It is certainly not a requirement of the ANSI C Library, or of Posix,
  161. that timestamps before 1970 cannot be represented.  Here is a patch:
  162.  
  163. RCS file: RCS/ckufio.c,v
  164. retrieving revision 6.0.192.0
  165. retrieving revision 6.0.192.1
  166. diff -c -r6.0.192.0 -r6.0.192.1
  167. *** ckufio.c    1996/11/23 19:27:13    6.0.192.0
  168. --- ckufio.c    1996/12/02 06:07:54    6.0.192.1
  169. ***************
  170. *** 2659,2666 ****
  171.       yy = time_stamp->tm_year;        /* Year - 1900 */
  172.       yy += 1900;
  173.       debug(F101,"zdatstr year","",yy);
  174. -     if (yy < 1970)            /* By definition of C library */
  175. -       return("");
  176.   
  177.       if (time_stamp->tm_mon  < 0 || time_stamp->tm_mon  > 11)
  178.         return("");
  179. --- 2659,2664 ----
  180. [It is not known if this patch is safe on all UNIX platforms.]
  181.  
  182. ====================
  183. X-Patch-Number: 0002
  184. Date: Mon, 02 Dec 1996 13:47:13 -0500
  185. To: kermit-support@columbia.edu
  186. Subject: Compilation error on Solaris 2.5 with Pro C
  187. From: "David J. Fiander" <davidf@worf.mks.com>
  188.  
  189. I defined CK_ENVIRONMENT and found that the prototype for tn_snenv() in
  190. ckcnet.h conflicted with the function definition in ckcnet.c.  the former
  191. declared the first parameter to be a CHAR * (i.e. an unsigned char *),
  192. while the latter declared to be a char * (i.e. signed char *).  The
  193. Pro C compiler treats this as an error.  I changed the function definition
  194. in ckcnet.c to declare the parameter as a CHAR * and the problem was
  195. resolved.
  196.  
  197. - David
  198.  
  199. [Note: This problem does not occur with standard builds.
  200. Resolution: CK_ENVIRONMENT, which controls the use of TELNET
  201. NEW-ENVIRONMENT protocol, is not supported in the UNIX version of
  202. C-Kermit 6.0.192.  The type mismatch is a mistake, however.]
  203.  
  204. ====================
  205. X-Patch-Number: 0003
  206. Date: Tue, 3 Dec 96 10:56:50 EST
  207. From: Mike Freeman <freeman@WATSUN.CC.COLUMBIA.EDU>
  208. Subject: CKERMIT.INI Fix for VMS
  209.  
  210. A minor fix to CKERMIT.INI from the 6-Sep release is shown below. 
  211. Needed to get C-Kermit 6(192) to run on my Vax/VMS system with VmS
  212. V5.5-2 and VAX C V3.1.
  213.  
  214. *** $ker:ckermit.ini;-1
  215. --- $ker:ckermit.ini;
  216. **************
  217. *** 680,686
  218.   
  219.   ; In VMS and OpenVMS, allow for system-wide site customizations
  220.   
  221. ! if equal "\v(system)" "VMS" {
  222.       xif exist CKERMIT_INI:CKERMIT.SYS {
  223.       echo Executing CKERMIT_INI:CKERMIT.SYS
  224.       take CKERMIT_INI:CKERMIT.SYS
  225. --- 680,686 -----
  226.   
  227.   ; In VMS and OpenVMS, allow for system-wide site customizations
  228.   
  229. ! xif equal "\v(system)" "VMS" {
  230.       xif exist CKERMIT_INI:CKERMIT.SYS {
  231.       echo Executing CKERMIT_INI:CKERMIT.SYS
  232.       take CKERMIT_INI:CKERMIT.SYS
  233.  
  234. MIke Freeman                    | Internet: freeman@watsun.cc.columbia.edu
  235. Amateur Radio Calsign: K7UIJ    | */ PGP Public Key Available */
  236.  
  237. ====================
  238. X-Patch-Number: 0004
  239. Date: Thu, 5 Dec 1996 15:20:00 EST
  240. From: Frank da Cruz <fdc@columbia.edu>
  241. Subject: C-Kermit 6.0 can't TELNET on VAX/VMS with UCX 2.0
  242.  
  243. PROBLEM:
  244.  
  245. On VAX/VMS systems with early versions of DEC TCP/IP (UCX), "set host" and
  246. "telnet" commands might fail with "Connection refused", even though the system
  247. (UCX) TELNET program to the same host works correctly.
  248.  
  249. DIAGNOSIS:
  250.  
  251. If you don't specify a port, Kermit substitutes the service name "telnet" and
  252. then asks UCX to look it up; similary, if you specify a port by name, rather
  253. than number, Kermit asks UCX to look it up.
  254.  
  255. On VAX/VMS with DEC TCP/IP UCX 2.0, 2.0A, 2.0B, or 2.0C, the getservbyname()
  256. function fails to return the port number in network byte order as it should,
  257. and instead returns the number with its bytes swapped (e.g. 5888 instead of
  258. 23).  Then Kermit tries to connect to port 5888 on the host; most hosts will
  259. refuse the connection; if they don't, you probably didn't reach a Telnet port
  260. anyway.
  261.  
  262. This bug was fixed in UCX 2.0D and thereafter.  However, there is no way for
  263. Kermit to know which version of UCX is being used.
  264.  
  265. WORKAROUND:
  266.  
  267. Specify the port number (not name) in your SET HOST or TELNET command, e.g.:
  268.  
  269.   set host xyzcorp.com 23
  270.  
  271. CURE:
  272.  
  273. A new command:
  274.  
  275.   SET TCP UCX-PORT-BUG { ON, OFF }
  276.  
  277. It is OFF by default, so UCX versions of VMS C-Kermit will work with all
  278. latter-day versions of UCX with no special effort.  But if you have an old
  279. UCX system, and you tell C-Kermit to "set host" or "telnet" and it says
  280. "Connection refused", tell it to SET TCP UCX-PORT-BUG ON and try again.  If
  281. this works, then put this command into your (or the system-wide) CKERMIT.INI
  282. file.  The following patch adds this command to VMS versions of C-Kermit that
  283. were built for UCX support.  It has already been applied to the CKVV55-UCX20
  284. binary in the Kermit archive.
  285.  
  286. PATCH:
  287.  
  288. *** /w/pub/ftp/kermit/f/ckcnet.c    Wed Nov 27 19:54:46 1996
  289. --- ./ckcnet.c    Wed Dec  4 17:14:41 1996
  290. ***************
  291. *** 1,4 ****
  292. ! char *cknetv = "Network support, 6.0.078, 6 Sep 1996";
  293.   
  294.   /*  C K C N E T  --  Network support  */
  295.   
  296. --- 1,4 ----
  297. ! char *cknetv = "Network support, 6.0.079, 4 Dec 1996";
  298.   
  299.   /*  C K C N E T  --  Network support  */
  300.   
  301. ***************
  302. *** 960,965 ****
  303. --- 960,967 ----
  304.   extern VOID C$$SOCK_TRANSLATE();
  305.   #endif /* CK_ANSIC */
  306.   
  307. + int ucx_port_bug = 0;            /* Explained below */
  308.   struct servent *
  309.   my_getservbyname (service, proto) char *service, *proto; {
  310.       static struct servent sent;
  311. ***************
  312. *** 1007,1035 ****
  313.       C$$SOCK_TRANSLATE(&s.sb.st[0]);
  314.       return NULL;
  315.       }
  316. -     /* sent.s_port is returned by UCX in network byte order. */
  317. -     /* Calling htons here swaps the bytes, which ruins everything. */
  318. -     /* Oh yeah?  WHICH VERSION of UCX???  Let's try this... */
  319. - #ifndef __alpha /* Maybe it should be __DECC, or some version thereof... */
  320.   /*
  321. !   Hunter says: "In fact, the "#ifndef __alpha" isn't even needed, since
  322. !   my_getservbyname() isn't included if "__DECC" is defined, and that's
  323. !   always defined on Alpha."  But if it doesn't hurt either, better not risk
  324. !   taking it out.
  325.   */
  326. ! #ifndef TCPWARE
  327. ! #define DO_HTONS
  328. ! #endif /* TCPWARE */
  329. ! #endif /* __alpha */
  330. ! #ifdef DO_HTONS
  331.       sent.s_port = htons(sent.s_port);
  332. !     debug(F111,"UCX getservbyname","port",ntohs(sent.s_port));
  333. ! #else
  334. !     debug(F111,"UCX getservbyname","port",sent.s_port);
  335. ! #endif /* DO_HTONS */
  336.       return &sent;
  337.   }
  338.   #endif /* __DECC */
  339. --- 1009,1028 ----
  340.       C$$SOCK_TRANSLATE(&s.sb.st[0]);
  341.       return NULL;
  342.       }
  343.   /*
  344. !   sent.s_port is supposed to be returned by UCX in network byte order.
  345. !   However, UCX 2.0 through 2.0C did not do this; 2.0D and later do it.
  346. !   But there is no way of knowing which UCX version, so we have a user-settable
  347. !   runtime variable.  Note: UCX 2.0 was only for the VAX.
  348.   */
  349. !     debug(F101,"UCX getservbyname port","",sent.s_port);
  350. !     debug(F101,"UCX getservbyname ntohs(port)","",ntohs(sent.s_port));
  351. !     if (ucx_port_bug) {
  352.       sent.s_port = htons(sent.s_port);
  353. !     debug(F100,"UCX-PORT-BUG ON: swapping bytes","",0);
  354. !     debug(F101,"UCX swapped port","",sent.s_port);
  355. !     debug(F101,"UCX swapped ntohs(port)","",ntohs(sent.s_port));
  356. !     }
  357.       return &sent;
  358.   }
  359.   #endif /* __DECC */
  360. *** /w/pub/ftp/kermit/f/ckuus3.c    Sun Nov 24 19:20:50 1996
  361. --- ./ckuus3.c    Wed Dec  4 16:58:49 1996
  362. ***************
  363. *** 3031,3036 ****
  364. --- 3031,3046 ----
  365.         success = recvbuf(z);
  366.         return(success);
  367.   #endif /* SO_RCVBUF */
  368. + #ifdef VMS
  369. + #ifdef DEC_TCPIP
  370. +     case XYTCP_UCX: {            /* UCX 2.0 port swabbing bug */
  371. +     extern int ucx_port_bug;
  372. +     return(success = seton(&ucx_port_bug));
  373. +     }
  374. + #endif /* DEC_TCPIP */
  375. + #endif /* VMS */
  376.      default:
  377.         return(0);
  378.      }
  379. *** /w/pub/ftp/kermit/f/ckuusr.c    Sun Nov 24 19:20:51 1996
  380. --- ./ckuusr.c    Wed Dec  4 17:12:50 1996
  381. ***************
  382. *** 1098,1103 ****
  383. --- 1098,1108 ----
  384.   #ifdef SO_SNDBUF
  385.      "sendbuf", XYTCP_SENDBUF, 0,
  386.   #endif /* SO_SNDBUF */
  387. + #ifdef VMS
  388. + #ifdef DEC_TCPIP
  389. +    "ucx-port-bug", XYTCP_UCX, 0,
  390. + #endif /* DEC_TCPIP */
  391. + #endif /* VMS */
  392.      "",0,0
  393.   };
  394.   int ntcpopt = (sizeof(tcpopt) / sizeof(struct keytab));
  395. *** /w/pub/ftp/kermit/f/ckuusr.h    Sun Nov 24 19:20:52 1996
  396. --- ./ckuusr.h    Wed Dec  4 16:59:18 1996
  397. ***************
  398. *** 803,808 ****
  399. --- 803,809 ----
  400.   #define  XYTCP_LINGER    3  /* Linger */
  401.   #define  XYTCP_RECVBUF   4  /* Receive Buffer Size */
  402.   #define  XYTCP_KEEPALIVE 5  /* Keep Alive packets */
  403. + #define  XYTCP_UCX       6  /* UCX 2.0 port swabbing bug */
  404.   
  405.   #define XYMSK  83       /* MS-DOS Kermit compatibility options */
  406.   #define  MSK_COLOR 0    /*  Terminal color handling   */
  407.  
  408. ====================
  409. X-Patch-Number: 0005
  410. Date: Mon, 9 Dec 1996 17:00:56 EST
  411. From: Frank da Cruz <fdc@columbia.edu>
  412. Subject: C-Kermit Might Send Packets Outside Window
  413.  
  414. PROBLEM:
  415.  
  416. When sending a file with a window size greater than 1 under conditions of
  417. packet loss, C-Kermit might send packets outside the current window.  This
  418. should not cause file corruption, and in many cases (depending on the Kermit
  419. implementation on the receiving end), it won't even cause a noticable problem,
  420. but in other cases it might cause the transfer to stop unnecessarily.
  421.  
  422. CURE:
  423.  
  424. In the ckcfn2.c module, replace the nxtpkt() function with this new one:
  425.  
  426. /*  N X T P K T  --  Next Packet  */
  427. /*
  428.   Get packet number of next packet to send and allocate a buffer for it.
  429.   Returns:
  430.     0 on success, with global pktnum set to the packet number;
  431.    -1 on failure to allocate buffer (fatal);
  432.    -2 if resulting packet number is outside the current window. 
  433. */
  434. int
  435. nxtpkt() {                /* Called by file sender */
  436.     int j, n, x;
  437.  
  438.     debug(F101,"nxtpkt pktnum","",pktnum);
  439.     debug(F101,"nxtpkt winlo ","",winlo);
  440.     n = (pktnum + 1) % 64;        /* Increment packet number mod 64 */
  441.     debug(F101,"nxtpkt n","",n);
  442.     x = chkwin(n,winlo,wslots);        /* Don't exceed window boundary */
  443.     debug(F101,"nxtpkt chkwin","",x);
  444.     if (x)
  445.       return(-2);
  446.  
  447.     j = getsbuf(n);            /* Get a buffer for packet n */
  448.     if (j < 0) {
  449.     debug(F101,"nxtpkt getsbuf failure","",j);
  450.     return(-1);
  451.     }
  452.     pktnum = n;          
  453.     return(0);
  454. }
  455.  
  456. ====================
  457. X-Patch-Number: 0006
  458. Date: Wed, 11 Dec 1996 12:26:00 EST
  459. From: Frank da Cruz <fdc@columbia.edu>
  460. Subject: MOVE from SEND-LIST does not delete original files
  461.  
  462. If you build up a list of files to be sent using ADD SEND-LIST and then
  463. give a SEND command with no operands, it sends the files in the send list.
  464. If you give a MOVE command with no operands, it does the same thing.  But
  465. unlike SEND, MOVE should delete each original after sending it successfully;
  466. in C-Kermit 6.0.192, it does not.
  467.  
  468. Here's the patch:
  469.  
  470. *** /w/pub/ftp/kermit/f/ckuusr.c    Sun Nov 24 19:20:51 1996
  471. --- ckuusr.c    Wed Dec 11 12:39:01 1996
  472. ***************
  473. *** 2863,2868 ****
  474. --- 2863,2870 ----
  475.               sndsrc = nfils;    /* Like MSEND */
  476.               addlist = 1;    /* But using a different list... */
  477.               filenext = filehead;
  478. +             if (cx == XXMOVE)
  479. +               moving = 1;
  480.               sstate = 's';
  481.               goto sendend;
  482.           } else {        /* Oops, no list. */
  483.  
  484. ====================
  485. X-Patch-Number: 0007
  486. Date: Thu, 12 Dec 1996 21:11:47 -0500
  487. From: "Richard L. Hamilton" <rlhamil@mindwarp.smart.net>
  488. Subject: Higher serial speeds on Solaris 2.5
  489.  
  490. Here's how I hacked up C-Kermit 6.0 for more of the speeds that
  491. Solaris >= 2.5 supports.
  492.  
  493. This was with the following make command, to get rid of references
  494. to unsupported speeds as well as to help get some of the additional
  495. speeds.  POSIX is a must, 'cause setting speeds > 38400 without
  496. the cfsetospeed() and similar functions is a pain.  The #ifndef VANILLA
  497. was just so I could turn off all my hacks real easily, and it and the
  498. corresponding #endif should probably be removed.
  499.  
  500. make solaris2xg KFLAGS="-DCK_DSYSINI -DCK_INI_B -DCK_WREFRESH -DPOSIX
  501. -DNOB_3600 -DNOB_7200 -DBPS_134 -DBPS_1800 -DBPS_57K -DBPS_76K
  502. -DBPS_115K -DBPS_230K"
  503.  
  504. diff ckutio.c.orig ckutio.c
  505. 4605c4605,4616
  506. ---
  507. > #ifndef VANILLA
  508. > #ifdef SOLARIS
  509. > #ifdef POSIX
  510. > #ifdef BPS_76K
  511. >       case 7680: s = B76800; break;
  512. > #endif /* BPS_76K */
  513. > #ifdef BPS_230K
  514. >       case 23040: s = B230400; break;
  515. > #endif /* BPS_230K */
  516. > #endif /* POSIX */
  517. > #endif /* SOLARIS */
  518. > #endif /* VANILLA */
  519. 4951a4963,4974
  520. > #ifndef VANILLA
  521. > #ifdef SOLARIS
  522. > #ifdef POSIX
  523. > #ifdef BPS_76K
  524. >       case B76800: ss = 76800L; break;
  525. > #endif /* BPS_76K */
  526. > #ifdef BPS_230K
  527. >       case B230400: ss = 230400L; break;
  528. > #endif /* BPS_230K */
  529. > #endif /* POSIX */
  530. > #endif /* SOLARIS */
  531. > #endif /* VANILLA */
  532. diff ckuus3.c.orig ckuus3.c
  533. 328a329,331
  534. > #ifdef BPS_1800
  535. >   "1800", 180, 0,
  536. > #endif /* BPS_1800 */
  537.  
  538. ====================
  539. X-Patch-Number: 0008
  540. Date: Wed, 18 Dec 1996 11:42:00 EST
  541. From: Frank da Cruz <fdc@columbia.edu>
  542. Subject: C-Kermit application file name can't contain spaces
  543.  
  544. When the first command-line argument to C-Kermit is a filename, C-Kermit 
  545. should execute the commands from the file, e.g.
  546.  
  547.   kermit filename
  548.  
  549. But if the filename contains spaces, this doesn't work in version 6.0, even
  550. if the filename is properly quoted to the shell:
  551.  
  552.   kermit "this is a file name"
  553.  
  554. Here is the patch:
  555.  
  556. *** /w/pub/ftp/kermit/f/ckuus4.c    Sun Nov 24 19:20:50 1996
  557. --- ckuus4.c    Wed Dec 18 11:40:46 1996
  558. ***************
  559. *** 636,642 ****
  560.   */
  561.           cmdini();            /* Allocate command buffers etc */
  562.           cmini(0);            /* Initialize them */
  563. !         strcpy(cmdbuf,yargv[1]);    /* Stuff filename into command buf */
  564.           strcat(cmdbuf,"\r\r");    /* And some carriage returns */
  565.           if ((y = cmifip("","",&s,&x,0,takepath,xxstring)) < 0)
  566.             doexit(BAD_EXIT,xitsta);
  567. --- 636,642 ----
  568.   */
  569.           cmdini();            /* Allocate command buffers etc */
  570.           cmini(0);            /* Initialize them */
  571. !         sprintf(cmdbuf,"{%s}",yargv[1]); /* Put filename in command buf */
  572.           strcat(cmdbuf,"\r\r");    /* And some carriage returns */
  573.           if ((y = cmifip("","",&s,&x,0,takepath,xxstring)) < 0)
  574.             doexit(BAD_EXIT,xitsta);
  575.  
  576. ====================
  577. X-Patch-Number: 0009
  578. Subject: cku192 on an AT&T 3B1/7300
  579. Date: Sun, 5 Jan 97 16:12:40 CST (-0600)
  580. From: "Randolph J. Herber" <rjh@yclept.chi.il.us>
  581.  
  582. I used the sys3upcx entry in the makefile.  It works.
  583.  
  584. I noticed the following problems:
  585.  
  586.     1. kermit needs to run setuid uucp if it is sharing a line with
  587.        HDB uucp.  If you set kermit setuid uucp and attempt to run
  588.        it as user root, it fails because the AT&T 3B1 UNIX operating
  589.        system is System V Release 0 and does not have save uid in
  590.        the kernel.  The following code snippet in priv_ini() of
  591.        ckutio.c shows the change I made to address this situation:
  592.  
  593.     if (realuid == UID_ROOT) {        /* If real id is root, */
  594.       privuid = (UID_T) -1;        /* stay root at all times. */
  595.       err &= ~1;            /* and remove any setuid err */
  596.     }                    /* added RJH 31DEC1996 */
  597.  
  598.     2. AT&T UNIX 3.51m does have hardware flow control which can
  599.        set but not tested for.   I added the following in tthflow()
  600.        of ckutio.c after the #ifdef ATTSV to address this situation:
  601.  
  602. #ifdef ATT7300
  603. #define RTSFLOW CTSCD
  604. #define CTSFLOW CTSCD
  605. #endif
  606.  
  607.        With these present, then cku192 can be generated with CK_RTSCTS.
  608.        I have observed that it can make a 30% difference in performance
  609.        by avoiding hangs while kermit times out when the other system
  610.        is expecting hardware flow control.
  611.  
  612.        Please note that version 3.51m was released as a patch on
  613.        fix disk 2 and not everyone has it.
  614.  
  615.     Randolph J. Herber,
  616.     (Speaking for myself and not US, USDOE, Fermilab or URA.)
  617.     (Trademarks belong to their respective owners.)
  618.  
  619. ====================
  620. X-Patch-Number: 0010
  621. Date: Sat, 11 Jan 1997 00:06:01 -0600 (CST)
  622. From: "Patrick J. Volkerding" <volkerdi@mhd1.moorhead.msus.edu>
  623. To: fdc@watsun.cc.columbia.edu
  624. Subject: C-Kermit for Linux on Alpha
  625.  
  626. ************************************************************************
  627.  
  628. NOTE: This patch (Patch 0010) and Patch 0017 are mutually exclusive.
  629.       Patch 0017 includes same fix for Linux/Alpha as Patch 0010 does.
  630.       If you wish to use the higher serial speeds available with the
  631.       standard POSIX interface, apply Patch 0017 instead of Patch 0010.
  632.       
  633. ************************************************************************      
  634.  
  635. There was one little snag in the compile, but it looks like this patch
  636. fixes it:
  637.  
  638. --- ckutio.c.orig       Fri Jan 10 23:55:38 1997
  639. +++ ckutio.c    Fri Jan 10 23:55:38 1997
  640. @@ -671,6 +671,9 @@
  641.  #ifdef LINUXHISPEED
  642.  #include <linux/serial.h>
  643.  #endif /* LINUXHISPEED */
  644. +#ifdef __alpha__ /* Linux on DEC Alpha */
  645. +#include <asm/termios.h>
  646. +#endif /* __alpha__ */
  647.  #else
  648.  #ifdef AIXRS                           /* IBM AIX */
  649.  #include <sys/time.h>
  650.  
  651. ====================
  652. X-Patch-Number: 0011
  653. Date: Sat, 11 Jan 1997 00:06:01 -0600 (CST)
  654. From: ...
  655. Subject: Patch to make ck9con.c compile on OS-9/68000 2.4
  656.  
  657. *** /w/pub/ftp/kermit/f/ck9con.c    Thu Aug 22 19:50:45 1996
  658. --- ./ck9con.c    Sat Jan 11 12:57:23 1997
  659. ***************
  660. *** 935,941 ****
  661. --- 935,945 ----
  662.               else if (n < 0) {
  663.                   debug(F101, "conect comm errno", NULL, errno);
  664.                   if (!quiet)
  665. + #ifdef OSK
  666. +                   printf("\n\012Communications disconnect ");
  667. + #else             
  668.                     printf("\n\lCommunications disconnect ");
  669. + #endif                  
  670.                   if (network) ttclos(0);
  671.                   dohangup = 1;
  672.                   active = 0;
  673.  
  674. ====================
  675. X-Patch-Number: 0012
  676. Date: Sat, 25 Jan 1997 20:46:22 -0500 (EST)
  677. From: Fred Smith <fredex@fcshome.stoneham.ma.us>
  678. Subject: Patches for Coherent 4.2
  679.  
  680. You've now got TWO new Coherent executables in your /pub/kermit/incoming
  681. directory. Both were compiled using the coherent42 target in the makefile,
  682. without any changes to the target.
  683.  
  684. In both cases, however, I needed to make some changes in the code. I'll
  685. append some patches here with the changes.  NOTE that I'll also embed
  686. some commentary in the patches (I'll add a "FRANK" to my commentary so
  687. you can easily find it) describing WHY I made that change.
  688.  
  689. One of the executables, cku192.coherent42-mw-uucp is compiled with as few
  690. changes as possible, using the default lockfile naming rules that were in
  691. effect in older revs of Coherent.
  692.  
  693. The other, cku192.coherent42-taylor-uucp was slightly modified to use a naming
  694. convention matching that used by the Taylor UUCP in use in Coherent 4.2 (and
  695. as an add-on by some people to the 4.0.x systems).
  696.  
  697. So, in theory, the cku192.coherent42-mw-uucp ought to be usable on older 4.x
  698. releases that do not use Taylor UUCP.  But who knows if it really will work.
  699. It was compiled on 4.2.10. I believe there have been numerous changes in the
  700. system internals and in the libraries across each of the (many) revs between
  701. 4.0.0 and 4.2.10, so each person who tries it has my sincere wishes for good
  702. luck!
  703.  
  704. OTOH, MWC (as far as I know) did not ship Taylor UUCP as an official part of
  705. the distribution prior to 4.2.x (though they had an update available for
  706. earlier revs), and beginning at 4.2.x shipped ONLY Taylor UUCP.  So, I believe
  707. that the cku192.coherent42-taylor-uucp executable is quite likely to work on
  708. any 4.2.x release.
  709.  
  710. Both executables were tested (on my 4.2.10 system) by uploading themselves to
  711. our ISP, so at least to the extent that that exercises the program, they do
  712. appear to work. I noticed that the old bug remains where on Coherent the
  713. full-screen display is drawn twice.
  714.  
  715. OK, here's the patches, with some additional commentary:
  716. -------------------------------------------------------------------------------
  717. *** ../src/ckufio.c    Sat Nov 23 14:27:13 1996
  718. --- ckufio.c    Sat Jan 25 20:28:18 1997
  719. ***************
  720. *** 211,216 ****
  721. --- 211,221 ----
  722.   #endif /* BSD4 */
  723.   #endif /* BSD44 */
  724.   
  725. FRANK
  726. This is needed for cku192 to avoid fatal compiler errors. I didn't track
  727. down the reason, but it must be something that changed since 190.
  728.  
  729. + /* FCS */
  730. + #ifdef COHERENT
  731. + #include <time.h>
  732. + #endif /* COHERENT */
  733.   /* Is `y' a leap year? */
  734.   #define leap(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)
  735.   
  736. *** ../src/ckutio.c    Mon Nov 18 12:10:44 1996
  737. --- ckutio.c    Sat Jan 25 20:28:19 1997
  738. ***************
  739. *** 993,1000 ****
  740. --- 993,1003 ----
  741.   #else
  742.   #ifdef SELECT
  743.   #ifndef BELLV10
  744.  
  745. FRANK
  746. Also needed on 192 but not on 190.
  747.  
  748. + /* FCS */
  749. + #ifndef COHERENT
  750.       static struct timeval tv;
  751.       static struct timezone tz;
  752. + #endif /* COHERENT */
  753.   #endif /* BELLV10 */
  754.   #endif /* SELECT */
  755.   #endif /* OXOS */
  756. ***************
  757. *** 2999,3004 ****
  758. --- 3002,3008 ----
  759.   #endif /* LFDEVNO */            /* ... define it here or on CC */
  760.   #endif /* SVR4 */            /* command line. */
  761.   
  762. FRANK
  763. This, if NOT commented out, builds the cku192.coherent42.MWC-uucp
  764. executable. If commented out you get the cku192.coherent42.TAYLOR-uucp.
  765.  
  766. + /* FCS
  767.   #ifdef COHERENT
  768.   #define LFDEVNO
  769.   #endif /* COHERENT */
  770. ***************
  771. *** 4272,4277 ****
  772. --- 4276,4286 ----
  773.       flow == FLO_DTRC ||
  774.       flow == FLO_DTRT) {
  775.       tthflow(flow, 1, &ttraw);
  776.  
  777. FRANK
  778. This is needed only for cku192.coherent42-taylor-uucp.
  779.  
  780. + /* FCS */
  781. + #ifdef COHERENT
  782. + #define SVORPOSIX
  783. + #endif /* COHERENT */
  784.   #ifndef SVORPOSIX
  785.       ttraw.sg_flags &= ~TANDEM;    /* Turn off software flow control */
  786.   #else
  787. ***************
  788. *** 4317,4322 ****
  789. --- 4326,4336 ----
  790.   #endif /* BSD44ORPOSIX */
  791.   #endif /* SVORPOSIX */
  792.       return(0);
  793.  
  794. FRANK
  795. ditto.
  796.  
  797. + /* FCS */
  798. + #ifdef COHERENT
  799. + #undef SYSVORPOSIX
  800. + #endif /* COHERENT */
  801.   }
  802.   
  803.   /*  T T V T -- Condition communication line for use as virtual terminal  */
  804. *** ../src/ckuus3.c    Sun Nov 24 12:51:52 1996
  805. --- ckuus3.c    Sat Jan 25 20:28:18 1997
  806. ***************
  807. *** 3334,3340 ****
  808.  
  809. FRANK
  810. without this one MWC's C compiler takes a fatal error, complaining 
  811. something like redefining a function to null.??
  812.  
  813.   #ifdef CK_ANSIC
  814.       xxstring = y ? zzstring : (xx_strp) NULL;
  815.   #else
  816. !     xxstring = y ? zzstring : NULL;
  817.   #endif /* CK_ANSIC */
  818.   #endif /* datageneral */
  819.       return(success = 1);
  820. --- 3334,3341 ----
  821.   #ifdef CK_ANSIC
  822.       xxstring = y ? zzstring : (xx_strp) NULL;
  823.   #else
  824. ! /* FCS */
  825. !     xxstring = y ? zzstring : (xx_strp)NULL;
  826.   #endif /* CK_ANSIC */
  827.   #endif /* datageneral */
  828.       return(success = 1);
  829.  
  830. ====================
  831. X-Patch-Number: 0013
  832. From: Stephan Hoffmann-Emden <HEStephan@aol.com>
  833. Date: Tue, 4 Feb 1997 06:00:49 -0500 (EST)
  834. To: fdc@watsun.cc.columbia.edu
  835. Subject: SINIX-RM BINARIES
  836.  
  837. this is the result of our porting-works for a
  838. SINIX-Y rm600 5.43 B0045 RM600 3/512 R4000
  839.  
  840. We've got problems with the declaration of variable 'delay' caused by
  841. include-file /usr/include/sys/clock.h
  842.  
  843. Therefore the variables were renamed in the following modules:
  844.  
  845. ckcfns.c
  846. ckcmai.c
  847. ckuus3.c
  848. ckuus4.c
  849. ckuusy.c
  850.  
  851. Patch:
  852.  
  853. *** /w/pub/ftp/kermit/c-kermit/ckcfns.c    Sun Nov 24 19:20:48 1996
  854. --- ./ckcfns.c    Mon Feb  3 11:46:51 1997
  855. ***************
  856. *** 44,46 ****
  857.   extern int parity, turn, network, what, whatru, fsecs, justone, slostart,
  858. !  delay, displa, xflg, mypadn, remfile, moving;
  859.   extern long filcnt, ffc, flci, flco, tlci, tlco, tfc, fsize, sendstart, rs_len;
  860. --- 44,46 ----
  861.   extern int parity, turn, network, what, whatru, fsecs, justone, slostart,
  862. !  ckdelay, displa, xflg, mypadn, remfile, moving;
  863.   extern long filcnt, ffc, flci, flco, tlci, tlco, tfc, fsize, sendstart, rs_len;
  864. ***************
  865. *** 1305,1308 ****
  866.       }
  867. !     if (!local && !server && delay > 0)    /* OS-9 sleep(0) == infinite */
  868. !       sleep(delay);            /* Delay if requested */
  869.   #ifdef datageneral
  870. --- 1305,1308 ----
  871.       }
  872. !     if (!local && !server && ckdelay > 0)    /* OS-9 sleep(0) == infinite */
  873. !       sleep(ckdelay);            /* Delay if requested */
  874.   #ifdef datageneral
  875. *** /w/pub/ftp/kermit/c-kermit/ckcmai.c    Fri Nov 29 08:52:13 1996
  876. --- ./ckcmai.c    Mon Feb  3 11:35:33 1997
  877. ***************
  878. *** 893,895 ****
  879.       escape = DFESC,            /* Escape character for connect */
  880. !     delay = DDELAY,                     /* Initial delay before sending */
  881.       tnlm = 0,                /* Terminal newline mode */
  882. --- 893,895 ----
  883.       escape = DFESC,            /* Escape character for connect */
  884. !     ckdelay = DDELAY,                     /* Initial delay before sending */
  885.       tnlm = 0,                /* Terminal newline mode */
  886. *** /w/pub/ftp/kermit/c-kermit/ckuus3.c    Sun Nov 24 19:20:50 1996
  887. --- ./ckuus3.c    Mon Feb  3 11:45:18 1997
  888. ***************
  889. *** 75,77 ****
  890.     local, server, success, dest,
  891. !   flow, autoflow, binary, xfermode, delay, parity, escape, what, srvdis,
  892.     turn, duplex, backgrd,
  893. --- 75,77 ----
  894.     local, server, success, dest,
  895. !   flow, autoflow, binary, xfermode, ckdelay, parity, escape, what, srvdis,
  896.     turn, duplex, backgrd,
  897. ***************
  898. *** 3550,3552 ****
  899.       if (x < 0) x = 0;
  900. !     return(success = setnum(&delay,x,y,999));
  901.   
  902. --- 3550,3552 ----
  903.       if (x < 0) x = 0;
  904. !     return(success = setnum(&ckdelay,x,y,999));
  905.   
  906. *** /w/pub/ftp/kermit/c-kermit/ckuus4.c    Sun Nov 24 19:20:50 1996
  907. --- ./ckuus4.c    Mon Feb  3 11:45:24 1997
  908. ***************
  909. *** 234,236 ****
  910.     atcapr, autopar, bctr, bctu, bgset, bigrbsiz, bigsbsiz, binary, carrier,
  911. !   cdtimo, cmask, crunched, delay, duplex, ebq, ebqflg, flow, fmask,
  912.     fncact, fncnv, inecho, keep, local, lscapr, lscapu, xfermode,
  913. --- 234,236 ----
  914.     atcapr, autopar, bctr, bctu, bgset, bigrbsiz, bigsbsiz, binary, carrier,
  915. !   cdtimo, cmask, crunched, ckdelay, duplex, ebq, ebqflg, flow, fmask,
  916.     fncact, fncnv, inecho, keep, local, lscapr, lscapu, xfermode,
  917. ***************
  918. *** 2487,2489 ****
  919.       printf(  " Pad Character:%11d%9d", padch,  mypadc);
  920. !     printf("        Delay:       %6d\n",delay);
  921.       printf(  " Packet Start: %11d%9d", mystch, stchr);
  922. --- 2487,2489 ----
  923.       printf(  " Pad Character:%11d%9d", padch,  mypadc);
  924. !     printf("        Delay:       %6d\n",ckdelay);
  925.       printf(  " Packet Start: %11d%9d", mystch, stchr);
  926. *** /w/pub/ftp/kermit/c-kermit/ckuusy.c    Sun Nov 10 18:37:33 1996
  927. --- ./ckuusy.c    Mon Feb  3 11:45:30 1997
  928. ***************
  929. *** 116,118 ****
  930.     urpsiz, wslotr, swcapr, binary, warn, parity, turn, turnch, duplex, flow,
  931. !   fncact, clfils, noinit, stayflg, nettype, cfilef, delay, noherald,
  932.     cmask, cmdmsk, backgrd, exitonclose;
  933. --- 116,118 ----
  934.     urpsiz, wslotr, swcapr, binary, warn, parity, turn, turnch, duplex, flow,
  935. !   fncact, clfils, noinit, stayflg, nettype, cfilef, ckdelay, noherald,
  936.     cmask, cmdmsk, backgrd, exitonclose;
  937. ***************
  938. *** 321,323 ****
  939.       if (z > -1)                /* If in range */
  940. !       delay = z;            /* set it */
  941.       else {
  942. --- 321,323 ----
  943.       if (z > -1)                /* If in range */
  944. !       ckdelay = z;            /* set it */
  945.       else {
  946.  
  947. ====================
  948. X-Patch-Number: 0014
  949. From: Wolfgang J. Moeller <moeller@decus.decus.de>
  950. Date: Tue 4 Feb 1997 09:10:11 +0100
  951. To: fdc@watsun.cc.columbia.edu
  952. Subject: Patches for VAX/VMS 5.x + CMU-IP
  953.  
  954. Note: The missing argument to ttclos() applies to all builds, not
  955. just this one.
  956.  
  957. *** /w/pub/ftp/kermit/f/ckcnet.c    Wed Nov 27 19:54:46 1996
  958. --- ./ckcnet.c    Thu Jan 23 01:02:52 1997
  959. ***************
  960. *** 2513,2519 ****
  961.       x = read(ttyfd,&dummy,0);    /* Try to read nothing */
  962.       if (x < 0) {            /* "Connection reset by peer" */
  963.           perror("TCP/IP");        /* or somesuch... */
  964. !         ttclos();            /* Close our end too. */
  965.           return(-1);
  966.       }
  967.       }
  968. --- 2513,2519 ----
  969.       x = read(ttyfd,&dummy,0);    /* Try to read nothing */
  970.       if (x < 0) {            /* "Connection reset by peer" */
  971.           perror("TCP/IP");        /* or somesuch... */
  972. !         ttclos(0);            /* Close our end too. */
  973.           return(-1);
  974.       }
  975.       }
  976. ***************
  977. *** 2663,2669 ****
  978.           x = read(ttyfd,&dummy,0);    /* Try to read nothing */
  979.           if (x < 0) {        /* "Connection reset by peer" */
  980.           perror("TCP/IP");    /* or somesuch... */
  981. !         ttclos();        /* Close our end too. */
  982.           return(-1);
  983.           }
  984.       }
  985. --- 2663,2669 ----
  986.           x = read(ttyfd,&dummy,0);    /* Try to read nothing */
  987.           if (x < 0) {        /* "Connection reset by peer" */
  988.           perror("TCP/IP");    /* or somesuch... */
  989. !         ttclos(0);        /* Close our end too. */
  990.           return(-1);
  991.           }
  992.       }
  993. *** /w/pub/ftp/kermit/f/ckvtio.c    Sun Nov 24 19:20:55 1996
  994. --- ./ckvtio.c    Sun Feb  2 15:54:12 1997
  995. ***************
  996. *** 2557,2562 ****
  997. --- 2557,2563 ----
  998.   #ifdef CMU_TCPIP
  999.           mask = 1;
  1000.           exceptfds = mask;
  1001. + #ifdef CMU_TCPIP_BOGUS_SELECT
  1002.           if (select(1, &mask, 0, &exceptfds, &timeout) == 1)
  1003.             if (FD_ISSET(0,&exceptfds))
  1004.               return(*c = -1);
  1005. ***************
  1006. *** 2564,2569 ****
  1007. --- 2565,2589 ----
  1008.           *c   = (unsigned)(concc & 0xff);
  1009.           *src = 0;
  1010.           return(1);
  1011. + #else    /* CMU_TCPIP_BOGUS_SELECT (wjm 02-feb-1997) */
  1012. +         /* non-blocking select() - zero timeout */
  1013. +         switch(select(1, &mask, 0, &exceptfds, &timeout)) {
  1014. +           case 1:    /* console ready */
  1015. +             netcon_queued = 0;            /* QIO completed */
  1016. +             *src = 0;
  1017. +             if (!(FD_ISSET(0,&exceptfds))) {    /* o.k. */
  1018. +             *c = (unsigned)(concc & 0xff);
  1019. +             return(1);
  1020. +             } else                /* I/O error */
  1021. +             return(*c = -1);
  1022. +           case 0:    /* timeout (no console input) */
  1023. +             break;
  1024. +           default:    /* select() error */
  1025. +             return(*c = -1);        /* shouldn't get here */
  1026. +         } 
  1027. + #endif    /* CMU_TCPIP_BOGUS_SELECT (wjm 02-feb-1997) */
  1028.   #else
  1029.                  (void) sys$readef(CON_EFN, &mask);
  1030.               if (mask & (1 << CON_EFN)) {
  1031. ***************
  1032. *** 2887,2892 ****
  1033. --- 2907,2913 ----
  1034.   
  1035.       net_chan = GET_SDC(ttyfd);
  1036.           if (nettty_queued) (void) sys$cancel(net_chan);
  1037. +     nettty_queued = 0;                    /*+wjm*/
  1038.   #else  /* DEC_TCPIP */
  1039.   #ifdef CMU_TCPIP
  1040.       /* not going to do this when CMU is the network transport.
  1041. ***************
  1042. *** 2896,2907 ****
  1043.        */
  1044.   #else  /* !CMU_TCPIP */
  1045.          if (nettty_queued) (void) sys$cancel(ttyfd);
  1046.   #endif /* CMU_TCPIP */
  1047.   #endif /* DEC_TCPIP */
  1048.           if (netcon_queued) (void) sys$cancel(conchn);
  1049.           netcon_queued = 0;
  1050. !         nettty_queued = 0;
  1051.       return(0);
  1052.   #else /* Not TCPIPLIB */
  1053.       return(0);
  1054. --- 2917,2929 ----
  1055.        */
  1056.   #else  /* !CMU_TCPIP */
  1057.       if (nettty_queued) (void) sys$cancel(ttyfd);
  1058. +     nettty_queued = 0;                    /*+wjm*/
  1059.   #endif /* CMU_TCPIP */
  1060.   #endif /* DEC_TCPIP */
  1061.           if (netcon_queued) (void) sys$cancel(conchn);
  1062.           netcon_queued = 0;
  1063. ! /*-wjm    nettty_queued = 0; */
  1064.       return(0);
  1065.   #else /* Not TCPIPLIB */
  1066.       return(0);
  1067.  
  1068. ====================
  1069. X-Patch-Number: 0015
  1070. From: "Melissa O'Neill" <oneill@cs.sfu.ca>
  1071. Subject: XECHO doesn't flush its output...
  1072. To: kermit-support@columbia.edu
  1073. Date: Tue, 4 Feb 1997 18:20:51 -0800 (PST)
  1074.  
  1075. CKermit 6.0.192 has a small problem with the XECHO command, which doesn't
  1076. doesn't flush it's output. This means that a display from an XECHO command may
  1077. not be seen a timely way.  Enclosed is a simple patch to fix the problem.
  1078.  
  1079. --- ckuusr.c.orig    Tue Jan 28 11:55:50 1997
  1080. +++ ckuusr.c    Tue Jan 28 11:56:20 1997
  1081. @@ -2071,6 +2071,7 @@
  1082.          printf("%s\n",s);
  1083.      } else if (cx == XXXECH) {    /* XECHO */
  1084.          printf("%s",s);
  1085. +        fflush(stdout);
  1086.      } else {            /* APC */
  1087.  #ifdef CK_APC
  1088.          if (apcactive == APC_LOCAL || 
  1089.  
  1090. ====================
  1091. X-Patch-Number: 0016
  1092. Date: Mon, 17 Feb 1997 17:16:56 -0800
  1093. From: Frank da Cruz <fdc@columbia.edu>
  1094. Subject: CD and other directory operations might not work
  1095.  
  1096. In the VMS-specific file i/o module, CKVFIO.C, routine isdir(), a struct
  1097. that contained a pointer to a malloc'd buffer was being used after the
  1098. buffer was freed.  In many cases this does not cause a problem because the
  1099. material is still actually there, but in some cases the free() implementation
  1100. actually wipes the buffer clean, causing the operation to fail.  The most
  1101. common symptom was failure of CD / SET DEFAULT in OpenVMS Alpha 6.2 or later
  1102. that has been updated with ALPLIBR04_070, "Fix realloc fragmentation problem,"
  1103. LIBRTL patch (this was discovered by Lucas Hart).  The fix is to postpone the
  1104. free() call till after we are finished using the struct:
  1105.  
  1106. *** /w/pub/ftp/kermit/f/ckvfio.c    Sun Nov 24 19:20:54 1996
  1107. --- ./ckvfio.c    Mon Feb 17 17:23:23 1997
  1108. ***************
  1109. *** 18,22 ****
  1110.   #endif /* __ALPHA */
  1111.   
  1112. ! char *ckzv = "File support, 6.0.130, 6 Sep 96";
  1113.   
  1114.   char *ckzsys = CKVFIO_OS_ARCH_STRING;
  1115. --- 18,22 ----
  1116.   #endif /* __ALPHA */
  1117.   
  1118. ! char *ckzv = "File support, 6.0.131, 17 Feb 1997";
  1119.   
  1120.   char *ckzsys = CKVFIO_OS_ARCH_STRING;
  1121. ***************
  1122. *** 31,35 ****
  1123.     Columbia University Academic Information Systems, New York City.
  1124.   
  1125. !   Copyright (C) 1985, 1996, Trustees of Columbia University in the City of New
  1126.     York.  The C-Kermit software may not be, in whole or in part, licensed or
  1127.     sold for profit as a software product itself, nor may it be included in or
  1128. --- 31,35 ----
  1129.     Columbia University Academic Information Systems, New York City.
  1130.   
  1131. !   Copyright (C) 1985, 1997, Trustees of Columbia University in the City of New
  1132.     York.  The C-Kermit software may not be, in whole or in part, licensed or
  1133.     sold for profit as a software product itself, nor may it be included in or
  1134. ***************
  1135. *** 255,258 ****
  1136. --- 255,259 ----
  1137.    * 129 06-Sep-96 fdc  Fix zchki() to return -2 if blah.DIR;n is a directory.
  1138.    * 130 06-Sep-96 fdc  Fixes to isdir(), zstrip(), zchdir(). 
  1139. +  * 131 17-Feb-97 fdc  Another fix to isdir() (free() was called too early).
  1140.    */
  1141.   
  1142. ***************
  1143. *** 628,633 ****
  1144.   #endif /* COMMENT */
  1145.   
  1146. -     free(full_name);
  1147.       if (new_len == 0) {
  1148.           /* Could still be a device name. */
  1149. --- 629,632 ----
  1150. ***************
  1151. *** 644,647 ****
  1152. --- 643,647 ----
  1153.              i, i, serial_num, new_len);
  1154.   #endif /* COMMENT */
  1155. +         free(full_name);
  1156.           return(((i & 1) == 1 && new_len > 0) ? 1: 0);
  1157.   
  1158. ***************
  1159. *** 657,666 ****
  1160. --- 657,669 ----
  1161.               name_buf[new_len-1] = '\0';
  1162.           }
  1163. +         free(full_name);
  1164.           return( isdir(name_buf) );
  1165.       } else {
  1166.           /* Logical name is just a random string signifying nothing */
  1167. +         free(full_name);
  1168.           return(0);
  1169.       }
  1170.       }
  1171.       return(1);
  1172.   }
  1173.  
  1174. ====================
  1175. X-Patch-Number: 0017
  1176. Date: Wed, 22 Jan 1997 18:57:18 -0500
  1177. To: kermit@columbia.edu
  1178. Subject: Patches to C-Kermit 6.0.192 for better Linux support
  1179. From: tytso@mit.edu
  1180.  
  1181. ************************************************************************
  1182.  
  1183. NOTE: This patch (Patch 0017) and Patch 0010 are mutually exclusive.
  1184.       Patch 0017 includes same fix for Linux/Alpha as Patch 0010 does.
  1185.       If do not wish to use the higher serial speeds available with the
  1186.       standard POSIX interface, apply Patch 0010 instead of Patch 0017.
  1187.  
  1188. ************************************************************************
  1189.  
  1190. I'm the tty and serial driver maintainer for Linux, and I've recently made
  1191. some changes so that kermit can better support Linux serial ports.  The
  1192. current kermit code uses a non-standard Linux specific ioctl to use the
  1193. 57600 and 115200 baud rates.  These ioctl's have not been required for two
  1194. major versions (2.0, 1.2).  Indeed, Linux at this point can support 230K bps
  1195. and 460K bps.
  1196.  
  1197. These patches do allow the use of the old ioctl's, but most Linux systems
  1198. really don't need them anymore.  I've added support for 230 or 460 kbaud,
  1199. using the standard POSIX interface.
  1200.  
  1201. I hope you find this useful, and these patches will find their way into the
  1202. next version of C-kermit.  Please let me know if you have any problems with
  1203. them.
  1204.     Thanks!!
  1205.                         - Ted
  1206.  
  1207. Patch generated: on Wed Jan 22 15:18:08 EST 1997 by tytso@rsts-11.mit.edu
  1208. against Kermit version 6.0.192 
  1209.  
  1210. ----------------------------------------------------------------
  1211. RCS file: RCS/makefile,v
  1212. retrieving revision 1.1
  1213. diff -u -r1.1 makefile
  1214. --- makefile    1996/12/07 17:12:55    1.1
  1215. +++ makefile    1996/12/07 21:49:22
  1216. @@ -2800,13 +2800,35 @@
  1217.      $(MAKE) wermit \
  1218.      "CFLAGS = -DATTSV -DNOFILEH -DCIE $(KFLAGS) -O" "LNKFLAGS ="
  1219.  
  1220. -# Linux 0.99.14 or later with gcc, dynamic libraries, curses, TCP/IP.
  1221. -# 
  1222. -# -DLINUXFSSTND (Linux File System Standard) gives UUCP lockfil /var/lock with
  1223. -# string pid.  Remove this and get /usr/spool/uucp with int pid, which was used
  1224. -# in early Linux versions.
  1225. +# Linux 1.2 and later (1.3, 2.0, 2.1) with gcc, dynamic libraries, TCP/IP
  1226. +#
  1227. +# Most modern Linux systems use ncurses (with curses.h and an ncurses 
  1228. +# shared library.   Modern Linux systems also generally use FSSTND 1.2.
  1229. +# So, you don't need most of the compatibility hair described below.
  1230. +#
  1231. +# If your Linux system does not have ncurses, remove -DCK_CURSES 
  1232. +# and the entire LIBS= clause.
  1233. +#
  1234. +# NOTE: Remove -DBIGBUFOK for small-memory or limited-resource systems.
  1235.  #
  1236. -# If you get compiler errors regarding <linux/serial.h>, add -DNOHISPEED.
  1237. +#
  1238. +# For very old (ancient) Linux systems, mainly systems with pre-1.0 and 
  1239. +# 1.0 kernel versions, and various odd-ball Linux distributions, read on....
  1240. +# 
  1241. +# -DLINUXFSSTND (Linux File System Standard 1.2) gives UUCP lockfil /var/lock
  1242. +# with string pid.  Remove this and get /usr/spool/uucp with int pid, 
  1243. +# which was used in early Linux versions.
  1244. +#
  1245. +# Add -DFSSTND10 to support the version 1.0 of the FSSTND.  In the earlier
  1246. +# version of the FSSTND, the PID string in the UUCP lock file had leading
  1247. +# zeros.  In FSSTND 1.2 this was changed to be be leading spaces instead.
  1248. +# To use the older standard, add define FSSTND10.
  1249. +#
  1250. +# Add -DOLINUXHISPEED (Old Linux High Speed support) to turn on an ugly kludge
  1251. +# which was used in Linux 1.0 systems to support speeds of 57600 and 115200.
  1252. +# Really, really, old Linux systems (pre-0.99pl15) will not support this.
  1253. +# If OLINUXHISPEED is not defined, then only the standard termios methods 
  1254. +# of setting the port speed will be used.
  1255.  #
  1256.  # -DCK_POSIX_SIG (POSIX signal handling) is good for Linux releases back to at
  1257.  # least 0.99.14; if it causes trouble for you, just remove it.
  1258. @@ -2825,23 +2847,14 @@
  1259.  # But wait, there's more.  On most Linux systems, -ltermcap must be included
  1260.  # in LIBS.  But on others, the linker complains that libtermcap can't be
  1261.  # found.  In that case, try removing -ltermcap from LIBS=.
  1262. -#
  1263. -# But wait, there's more.  The format of the PID string in the UUCP lockfile
  1264. -# changed between Linux FSSTND 1.0 and 1.2.  In the earlier standard, it had
  1265. -# leading zeros; in the second, it has leading spaces.  By default this entry
  1266. -# uses the newer standard.  To force the second one, add -DFSSTND10.
  1267. -#
  1268. -# "The nice thing about the Linux standard is there are so many to choose from"
  1269. -#
  1270. -# NOTE: Remove -DBIGBUFOK for small-memory or limited-resource systems.
  1271.  linux:
  1272.      @echo 'Making C-Kermit $(CKVER) for Linux...'
  1273.      @echo 'IMPORTANT: Read the comments in the linux section of the'
  1274.      @echo 'makefile if you get compilation or link errors.'
  1275.      $(MAKE) wermit "CC = gcc" "CC2 = gcc" \
  1276.      "CFLAGS = -O -DPOSIX -DDYNAMIC -DCK_CURSES -DCK_POSIX_SIG \
  1277. -    -DBIGBUFOK -DTCPSOCKET -DLINUXFSSTND $(KFLAGS)" \
  1278. -    "LNKFLAGS = $(LNKFLAGS)" "LIBS = -lcurses -ltermcap"
  1279. +    -DBIGBUFOK -DTCPSOCKET -DLINUXFSSTND -DCK_DSYSINI $(KFLAGS)" \
  1280. +    "LNKFLAGS = $(LNKFLAGS)" "LIBS = -lncurses -ltermcap"
  1281.  
  1282.  #This version was used for Linux prior to C-Kermit 6.0.192.
  1283.  #Now the "Linux File System Standard" is considered standard, ditto TCP/IP.
  1284. ----------------------------------------------------------------
  1285. RCS file: RCS/ckuusr.h,v
  1286. retrieving revision 1.1
  1287. diff -u -r1.1 ckuusr.h
  1288. --- ckuusr.h    1996/12/07 21:31:08    1.1
  1289. +++ ckuusr.h    1996/12/07 21:33:08
  1290. @@ -104,7 +104,11 @@
  1291.  #ifdef CU_ACIS
  1292.  #define CK_SYSINI "/usr/share/lib/kermit/ckermit.ini"
  1293.  #else
  1294. +#ifdef __linux__
  1295. +#define CK_SYSINI "/usr/share/kermit/ckermit.ini"
  1296. +#else
  1297.  #define CK_SYSINI "/usr/local/bin/ckermit.ini"
  1298. +#endif /* linux */
  1299.  #endif /* CU_ACIS */
  1300.  #endif /* HPUX10 */
  1301.  /* Fill in #else..#ifdef's here for VMS, OS/2, etc. */
  1302. ----------------------------------------------------------------
  1303. RCS file: RCS/ckcdeb.h,v
  1304. retrieving revision 1.1
  1305. diff -u -r1.1 ckcdeb.h
  1306. --- ckcdeb.h    1996/12/07 17:12:53    1.1
  1307. +++ ckcdeb.h    1996/12/07 18:33:35
  1308. @@ -1513,18 +1513,6 @@
  1309.  #define BPS_38K                /* 38400 bps */
  1310.  #endif
  1311.  
  1312. -/*
  1313. -  Speeds of 57600 and higher are supported in Linux 0.99.15 and later, but
  1314. -  it seems to do no harm to enable them for earlier releases too, in which
  1315. -  case commands like "set speed 57600" simply fail with an "Unsupported line
  1316. -  speed" message.
  1317. -*/
  1318. -#ifndef NOHISPEED
  1319. -#ifdef __linux__
  1320. -#define LINUXHISPEED
  1321. -#endif /* __linux__ */
  1322. -#endif /* NOHISPEED */
  1323. -
  1324.  #ifndef NOB_57K
  1325.  #ifdef Plan9
  1326.  #define BPS_57K
  1327. @@ -1536,9 +1524,7 @@
  1328.  #define BPS_57K
  1329.  #else
  1330.  #ifdef __linux__
  1331. -#ifdef LINUXHISPEED
  1332.  #define BPS_57K
  1333. -#endif /* LINUXHISPEED */
  1334.  #else
  1335.  #ifdef HPUX
  1336.  #define BPS_57K
  1337. @@ -1607,9 +1593,7 @@
  1338.  #define BPS_115K
  1339.  #else
  1340.  #ifdef __linux__
  1341. -#ifdef LINUXHISPEED
  1342.  #define BPS_115K
  1343. -#endif /* LINUXHISPEED */
  1344.  #else
  1345.  #ifdef __386BSD__
  1346.  #define BPS_115K
  1347. @@ -1643,11 +1627,26 @@
  1348.  #ifdef __32BIT__            
  1349.  #define BPS_230K
  1350.  #endif /* __32BIT__ */
  1351. -#else 
  1352. +#else
  1353. +#ifdef __linux__
  1354. +#define BPS_230K
  1355. +#else
  1356.  #undef BPS_230K
  1357. +#endif /* Linux */
  1358.  #endif /* OS2 */
  1359.  #endif /* NOB_230K */
  1360.  
  1361. +#ifndef NOB_460K            /* 460800 bps */
  1362. +#ifdef __linux__
  1363. +#define BPS_460K
  1364. +#else
  1365. +#undef BPS_460K
  1366. +#endif /* Linux */
  1367. +#endif /* NOB_460K */
  1368. +    
  1369. +#ifdef BPS_460K
  1370. +#define MAX_SPD 460800L            /* Maximum speed defined */
  1371. +#else
  1372.  #ifdef BPS_230K                /* Maximum speed defined */
  1373.  #define MAX_SPD 230400L
  1374.  #else
  1375. @@ -1673,6 +1672,7 @@
  1376.  #define MAX_SPD 14400L
  1377.  #else
  1378.  #define MAX_SPD 9600L
  1379. +#endif
  1380.  #endif
  1381.  #endif
  1382.  #endif
  1383. ----------------------------------------------------------------
  1384. RCS file: RCS/ckutio.c,v
  1385. retrieving revision 1.1
  1386. diff -u -r1.1 ckutio.c
  1387. --- ckutio.c    1996/12/07 17:12:53    1.1
  1388. +++ ckutio.c    1996/12/07 19:32:28
  1389. @@ -668,9 +668,9 @@
  1390.  #include <linux/fs.h>
  1391.  #include <linux/tty.h>
  1392.  #include <sys/time.h>
  1393. -#ifdef LINUXHISPEED
  1394. +#ifdef OLINUXHISPEED
  1395.  #include <linux/serial.h>
  1396. -#endif /* LINUXHISPEED */
  1397. +#endif /* OLINUXHISPEED */
  1398.  #else
  1399.  #ifdef AIXRS                /* IBM AIX */
  1400.  #include <sys/time.h>
  1401. @@ -4167,11 +4167,10 @@
  1402.      ttraw.c_iflag &= ~(IXON|IXOFF);    /* Turn off Xon/Xoff flags */
  1403.      ttraw.c_iflag |= (ttold.c_iflag & (IXON|IXOFF)); /* OR in old ones */
  1404.      /* NOTE: We should also handle hardware flow control here! */
  1405. -#ifdef __linux__
  1406. -/* In Linux case, we do this, which is unlikely to be portable */
  1407. +#ifdef POSIX_CRTSCTS
  1408.          ttraw.c_cflag &= ~CRTSCTS;    /* Turn off RTS/CTS flag */
  1409.          ttraw.c_cflag |= (ttold.c_cflag & CRTSCTS); /* OR in old one */
  1410. -#endif /* __linux__ */
  1411. +#endif /* POSIX_CRTSCTS */
  1412.      } else if (flow == FLO_RTSC ||    /* Hardware */
  1413.             flow == FLO_DTRC ||
  1414.             flow == FLO_DTRT) {
  1415. @@ -4419,10 +4418,10 @@
  1416.      tttvt.c_iflag &= ~(IXON|IXOFF);    /* Turn off Xon/Xoff flags */
  1417.      tttvt.c_iflag |= (ttold.c_iflag & (IXON|IXOFF)); /* OR in old ones */
  1418.      /* NOTE: We should also handle hardware flow control here! */
  1419. -#ifdef __linux__
  1420. +#ifdef POSIX_CRTSCTS
  1421.          tttvt.c_cflag &= ~CRTSCTS;    /* Turn off RTS/CTS flag */
  1422.          tttvt.c_cflag |= (ttold.c_cflag & CRTSCTS); /* OR in old one */
  1423. -#endif /* __linux__ */
  1424. +#endif /* POSIX_CRTSCTS */
  1425.      } else if (flow == FLO_NONE) {    /* NONE */
  1426.      tthflow(flow, 0, &tttvt);    /* Turn off hardware f/c */
  1427.      tttvt.c_iflag &= ~(IXON|IXOFF);    /* Turn off Xon/Xoff */
  1428. @@ -4524,12 +4523,10 @@
  1429.        s, s2;
  1430.      int ok = 1;                /* Speed check result, assume ok */
  1431.  
  1432. -#ifdef __linux__            /* Linux... */
  1433. -#ifdef ASYNC_SPD_MASK
  1434. +#ifdef OLINUXHISPEED            /* Linux... */
  1435.      unsigned int spd_flags = 0;
  1436.      struct serial_struct serinfo;
  1437. -#endif /* ASYNC_SPD_MASK */
  1438. -#endif /* __linux__ */
  1439. +#endif /* OLINUXHISPEED */
  1440.  
  1441.      debug(F101,"ttsspd cps","",cps);
  1442.      debug(F101,"ttsspd ttyfd","",ttyfd);
  1443. @@ -4591,11 +4588,9 @@
  1444.  #endif /* B28800 */
  1445.  #ifdef B38400
  1446.        case 3840: s = B38400;
  1447. -#ifdef __linux__
  1448. -#ifdef ASYNC_SPD_MASK
  1449. +#ifdef OLINUXHISPEED
  1450.          spd_flags = ~ASYNC_SPD_MASK;    /* Nonzero, but zero flags */
  1451. -#endif /* ASYNC_SPD_MASK */
  1452. -#endif /* __linux__ */
  1453. +#endif /* OLINUXHISPEED */
  1454.      break;
  1455.  #else /* B38400 not defined... */
  1456.  #ifdef EXTB
  1457. @@ -4611,8 +4606,7 @@
  1458.        case 11520: s = _B115200; break;
  1459.  #endif /* _B115200 */
  1460.  #else
  1461. -#ifdef __linux__
  1462. -#ifdef ASYNC_SPD_MASK
  1463. +#ifdef OLINUXHISPEED
  1464.  /*
  1465.    This bit from <carlo@sg.tn.tudelft.nl>:
  1466.    "Only note to make is maybe this: When the ASYNC_SPD_CUST flags are set then
  1467. @@ -4623,9 +4617,7 @@
  1468.  */
  1469.        case 5760: s = B38400; spd_flags = ASYNC_SPD_HI; break;
  1470.        case 11520: s = B38400; spd_flags = ASYNC_SPD_VHI; break;
  1471. -#endif /* ASYNC_SPD_MASK */
  1472.  #else
  1473. -#ifdef QNX
  1474.  #ifdef B57600
  1475.        case 5760: s = B57600; break;
  1476.  #endif /* B57600 */
  1477. @@ -4635,15 +4627,13 @@
  1478.  #ifdef B115200
  1479.        case 11520: s = B115200; break;
  1480.  #endif /* B115200 */
  1481. -#else
  1482. -#ifdef B57600
  1483. -      case 5760: s = B57600; break;
  1484. -#endif /* B57600 */
  1485. -#ifdef B115200
  1486. -      case 11520: s = B115200; break;
  1487. -#endif /* B115200 */
  1488. -#endif /* QNX */
  1489. -#endif /* __linux__ */
  1490. +#endif /* OLINUXHISPEED */
  1491. +#ifdef B230400
  1492. +      case 23040: s = B230400; break;
  1493. +#endif /* B230400 */
  1494. +#ifdef B460800
  1495. +      case 46080: s = B460800; break;
  1496. +#endif /* 460800 */           
  1497.  #endif /* HPUX */
  1498.        default:
  1499.      ok = 0;                /* Good speed not found, so not ok */
  1500. @@ -4672,8 +4662,7 @@
  1501.      debug(F101,"ttsspd tcgetattr","",x);
  1502.      if (x < 0)
  1503.        return(-1);
  1504. -#ifdef __linux__
  1505. -#ifdef ASYNC_SPD_MASK
  1506. +#ifdef OLINUXHISPEED
  1507.      debug(F101,"ttsspd spd_flags","",spd_flags);
  1508.      if (spd_flags && spd_flags != ASYNC_SPD_CUST) {
  1509.          if (ioctl(ttyfd, TIOCGSERIAL, &serinfo) < 0) {
  1510. @@ -4685,8 +4674,7 @@
  1511.          if (ioctl(ttyfd, TIOCSSERIAL, &serinfo) < 0)
  1512.            return(-1);
  1513.      }
  1514. -#endif /* ASYNC_SPD_MASK */
  1515. -#endif /* __linux__ */
  1516. +#endif /* OLINUXHISPEED */
  1517.      cfsetospeed(&ttcur,s);
  1518.      cfsetispeed(&ttcur,s2);
  1519.      cfsetospeed(&ttraw,s);
  1520. @@ -4783,12 +4771,10 @@
  1521.  #endif /* POSIX */
  1522.        s;
  1523.      long ss;
  1524. -#ifdef __linux__
  1525. -#ifdef ASYNC_SPD_MASK
  1526. +#ifdef OLINUXHISPEED
  1527.      unsigned int spd_flags = 0;
  1528.      struct serial_struct serinfo;
  1529. -#endif /* ASYNC_SPD_MASK */
  1530. -#endif /* __linux__ */
  1531. +#endif /* OLINUXHISPEED */
  1532.  
  1533.  #ifdef NETCONN
  1534.      if (netconn) return(-1);        /* -1 if network connection */
  1535. @@ -4801,13 +4787,9 @@
  1536.      else
  1537.        ss = ttylastspeed;
  1538.  #else
  1539. -#ifdef __linux__
  1540. -#ifdef ASYNC_SPD_MASK
  1541. -    debug(F100,"ttgspd Linux ASYNC_SPD_MASK defined","",0);
  1542. -#else
  1543. -    debug(F100,"ttgspd Linux ASYNC_SPD_MASK not defined","",0);
  1544. -#endif /* ASYNC_SPD_MASK */
  1545. -#endif /* __linux__ */
  1546. +#ifdef OLINUXHISPEED
  1547. +    debug(F100,"ttgspd Linux OLINUXHISPEED","",0);
  1548. +#endif /* OLINUXHISPEED */
  1549.  
  1550.      if (ttyfd < 0) {
  1551.  #ifdef BSD44ORPOSIX
  1552. @@ -4828,13 +4810,11 @@
  1553.      if (tcgetattr(ttyfd,&ttcur) < 0) return(-1);
  1554.      s = cfgetospeed(&ttcur);
  1555.      debug(F101,"ttgspd cfgetospeed 2 BSDORPOSIX","",s);
  1556. -#ifdef __linux__
  1557. -#ifdef ASYNC_SPD_MASK
  1558. +#ifdef OLINUXHISPEED
  1559.      if (ioctl(ttyfd,TIOCGSERIAL,&serinfo) > -1)
  1560.        spd_flags = serinfo.flags & ASYNC_SPD_MASK;
  1561.      debug(F101,"ttgspd spd_flags","",spd_flags);
  1562. -#endif /* ASYNC_SPD_MASK */
  1563. -#endif /* __linux__ */
  1564. +#endif /* OLINUXHISPEED */
  1565.  #else
  1566.  #ifdef ATTSV
  1567.      if (ioctl(ttyfd,TCGETA,&ttcur) < 0) return(-1);
  1568. @@ -4854,11 +4834,9 @@
  1569.  #endif /* BSD44ORPOSIX */
  1570.      }
  1571.      debug(F101,"ttgspd code","",s);
  1572. -#ifdef __linux__
  1573. -#ifdef ASYNC_SPD_MASK
  1574. +#ifdef OLINUXHISPEED
  1575.      debug(F101,"ttgspd spd_flags","",spd_flags);
  1576. -#endif /* ASYNC_SPD_MASK */
  1577. -#endif /* __linux__ */
  1578. +#endif /* OLINUXHISPEED */
  1579.      switch (s) {
  1580.  #ifdef B0
  1581.        case B0:    ss = 0L; break;
  1582. @@ -4934,14 +4912,12 @@
  1583.  #ifdef B38400
  1584.        case B38400:
  1585.          ss = 38400L;
  1586. -#ifdef __linux__
  1587. -#ifdef ASYNC_SPD_MASK
  1588. +#ifdef OLINUXHISPEED
  1589.          switch(spd_flags) {
  1590.            case ASYNC_SPD_HI:  ss =  57600L; break;
  1591.            case ASYNC_SPD_VHI: ss = 115200L; break;
  1592.      }
  1593. -#endif /* ASYNC_SPD_MASK */
  1594. -#endif /* __linux__ */
  1595. +#endif /* OLINUXHISPEED */
  1596.          break;
  1597.  #else
  1598.  #ifdef EXTB
  1599. @@ -4958,7 +4934,6 @@
  1600.        case _B115200: ss = 115200L; break;
  1601.  #endif /* _B115200 */
  1602.  #else
  1603. -#ifdef QNX
  1604.  #ifdef B57600
  1605.        case B57600: ss = 57600L; break;
  1606.  #endif /* B57600 */
  1607. @@ -4968,14 +4943,12 @@
  1608.  #ifdef B115200
  1609.        case B115200: ss = 115200L; break;
  1610.  #endif /* B115200 */
  1611. -#else
  1612. -#ifdef B57600
  1613. -      case B57600: ss = 57600L; break;
  1614. -#endif /* B57600 */
  1615. -#ifdef B115200
  1616. -      case B115200: ss = 115200L; break;
  1617. -#endif /* B115200 */
  1618. -#endif /* QNX */
  1619. +#ifdef B230400
  1620. +      case B230400: ss = 230400L; break;
  1621. +#endif /* B230400 */
  1622. +#ifdef B460800
  1623. +      case B460800: ss = 460800L; break;
  1624. +#endif /* B460800 */
  1625.  #endif /* HPUX */
  1626.  
  1627.        default:
  1628. ----------------------------------------------------------------
  1629. RCS file: RCS/ckuus3.c,v
  1630. retrieving revision 1.1
  1631. diff -u -r1.1 ckuus3.c
  1632. --- ckuus3.c    1996/12/07 17:12:54    1.1
  1633. +++ ckuus3.c    1996/12/07 18:30:44
  1634. @@ -346,6 +346,9 @@
  1635.  #ifdef BPS_38K
  1636.    "38400", 3840,  0,
  1637.  #endif /* BPS_38K */
  1638. +#ifdef BPS_460K
  1639. +  "460800", 46080,  0,
  1640. +#endif /* BPS_460K */
  1641.    "4800",   480,  0,
  1642.  #ifdef BPS_50
  1643.    "50",       5,  0,
  1644. ----------------------------------------------------------------
  1645. RCS file: RCS/ckuusx.c,v
  1646. retrieving revision 1.1
  1647. diff -u -r1.1 ckuusx.c
  1648. ------------------------------------------------------------------------
  1649. Date: Tue Feb 18 16:28:45 EST 1997
  1650. From: Jim Knoble <jmknoble@pobox.com>
  1651. Subject: linux-posix-hispeed+linux-alpha patch
  1652.  
  1653. Here's the patch that ought to be used to build ckermit for Linux/Alpha
  1654. systems *after* Ted Tso's POSIX-hispeed patch has been applied (his
  1655. patch breaks if patch #10 for Linux/Alpha is applied, and patch #10
  1656. breaks if Ted's patch is applied first).  Seems like the thing to do is
  1657. put Ted's patch in the PATCHES file, then this one right after it (or
  1658. even combine them ... it won't hurt Linux on Intel or SPARC platforms
  1659. to have this in there).
  1660.  
  1661. --- ckutio.c.orig    Wed Jan 29 00:10:16 1997
  1662. +++ ckutio.c    Wed Jan 29 00:12:17 1997
  1663. @@ -671,6 +671,9 @@
  1664.  #ifdef OLINUXHISPEED
  1665.  #include <linux/serial.h>
  1666.  #endif /* OLINUXHISPEED */
  1667. +#ifdef __alpha__ /* Linux on DEC Alpha */
  1668. +#include <asm/termios.h>
  1669. +#endif /* __alpha__ */
  1670.  #else
  1671.  #ifdef AIXRS                /* IBM AIX */
  1672.  #include <sys/time.h>
  1673.  
  1674. ====================
  1675. X-Patch-Number: 0018
  1676. Date: Thu Feb 20 12:25:11 1997
  1677. From: Frank da Cruz <fdc@columbia.edu>
  1678. Subject: SET WILDCARD-EXPANSION SHELL dumps core
  1679.  
  1680. In UNIX, SET WILDCARD-EXPANSION SHELL causes C-Kermit to dump core whenever
  1681. a command was given that had to parse the name of an existing file or file
  1682. group.  Diagnosis: storage wasn't being allocated for the file list.  Here's
  1683. the patch:
  1684.  
  1685. *** /w/pub/ftp/kermit/f/ckufio.c    Sun Nov 24 19:20:49 1996
  1686. --- ./ckufio.c    Thu Feb 20 12:22:58 1997
  1687. ***************
  1688. *** 2259,2265 ****
  1689.   #endif /* DTILDE */
  1690.   #ifndef NOPUSH
  1691.       if (!nopush && wildxpand)        /* Who is expanding wildcards? */
  1692. !       fcount = shxpand(fn,mtchs,MAXWLD); /* Shell */
  1693.       else
  1694.   #endif /* NOPUSH */
  1695.         fcount = (mtchs == NULL &&    /* Kermit */
  1696. --- 2259,2268 ----
  1697.   #endif /* DTILDE */
  1698.   #ifndef NOPUSH
  1699.       if (!nopush && wildxpand)        /* Who is expanding wildcards? */
  1700. !       fcount = (mtchs == NULL &&     /* Shell */
  1701. !         (mtchs = (char **)malloc(MAXWLD * sizeof(*mtchs))) == NULL)
  1702. !     ? 0
  1703. !       :  shxpand(fn,mtchs,MAXWLD);
  1704.       else
  1705.   #endif /* NOPUSH */
  1706.         fcount = (mtchs == NULL &&    /* Kermit */
  1707.  
  1708. ====================
  1709. X-Patch-Number: 0019
  1710. Date: Sat Mar  8 13:02:07 1997
  1711. From: Frank da Cruz <fdc@columbia.edu>
  1712. Subject: Hayes V.34 modem init string problem
  1713.  
  1714. A user writes:
  1715. > I replaced the Accura 144 with and Accura 288 on our 3B2.  I used the same 
  1716. > kermit script to configure the new modem as I had with the old one.  But I 
  1717. > can no longer use the dial command.  I get the message "Error initializing 
  1718. > modem."  What signal is kermit getting from the modem to cause this?
  1719. It seems that Hayes removed an S register (S82) from the new model.  
  1720. Workaround:  In your .mykermrc file, or wherever else you are setting up
  1721. your modem, right after it says:
  1722.  
  1723.   set modem type hayes-high-speed
  1724.  
  1725. Add:
  1726.  
  1727.   set modem command init-string ATQ0X4N1Y0&S0&C1&D2S37=0\13
  1728.  
  1729. Patch:
  1730.  
  1731. *** /w/pub/ftp/kermit/f/ckudia.c    Sun Nov 24 19:20:49 1996
  1732. --- ./ckudia.c    Sat Mar  8 13:04:15 1997
  1733. ***************
  1734. *** 896,904 ****
  1735.       ",",                /* pause_chars */
  1736.       2,                    /* pause_time */
  1737.   #ifdef OS2
  1738. !     "ATQ0X4N1Y0&S0&C1&D2S37=0S82=128\015", /* wake_str */
  1739.   #else
  1740. !     "ATQ0X4N1Y0S37=0S82=128\015",    /* wake_str */
  1741.   #endif /* OS2 */
  1742.       0,                    /* wake_rate */
  1743.       "OK\015",                /* wake_prompt */
  1744. --- 896,904 ----
  1745.       ",",                /* pause_chars */
  1746.       2,                    /* pause_time */
  1747.   #ifdef OS2
  1748. !     "ATQ0X4N1Y0&S0&C1&D2S37=0\015",    /* wake_str */
  1749.   #else
  1750. !     "ATQ0X4N1Y0S37=0\015",        /* wake_str */
  1751.   #endif /* OS2 */
  1752.       0,                    /* wake_rate */
  1753.       "OK\015",                /* wake_prompt */
  1754.  
  1755. ====================
  1756. X-Patch-Number: 0020
  1757. Date: Sun Mar 23 19:25:18 1997
  1758. From: Frank da Cruz <fdc@columbia.edu>
  1759. Subject: READ command does not fail if file not open
  1760.  
  1761. IF FAILURE does not work after a READ command that is executed before
  1762. the READ file is opened.  Here's the patch:
  1763.  
  1764. *** /w/pub/ftp/kermit/f/ckuus6.c    Sun Nov 24 19:20:51 1996
  1765. --- ./ckuus6.c    Sun Mar 23 19:23:24 1997
  1766. ***************
  1767. *** 338,348 ****
  1768.         return(y);
  1769.       if (chkfn(ZRFILE) < 1) {    /* File open? */
  1770.           printf("?Read file not open\n");
  1771. !         return(0);
  1772.       }
  1773.       if (!(s = (char *)readbuf)) {        /* Where to read into. */
  1774.           printf("?Oops, no READ buffer!\n");
  1775. !         return(0);
  1776.       }
  1777.   #ifdef BINREAD
  1778.       if (cx == XXRDBL) {        /* READBLOCK */
  1779. --- 338,348 ----
  1780.         return(y);
  1781.       if (chkfn(ZRFILE) < 1) {    /* File open? */
  1782.           printf("?Read file not open\n");
  1783. !         return(success = 0);
  1784.       }
  1785.       if (!(s = (char *)readbuf)) {        /* Where to read into. */
  1786.           printf("?Oops, no READ buffer!\n");
  1787. !         return(success = 0);
  1788.       }
  1789.   #ifdef BINREAD
  1790.       if (cx == XXRDBL) {        /* READBLOCK */
  1791.  
  1792. ====================
  1793. X-Patch-Number: 0021
  1794. Date: Sun Mar 23 19:25:18 1997
  1795. From: Frank da Cruz <fdc@columbia.edu>
  1796. Subject: Problems with long function arguments 
  1797.  
  1798. The 1023-byte limit on function arguments is overly restrictive on platforms
  1799. where memory is not tight.  Patch:
  1800.  
  1801. *** /w/pub/ftp/kermit/f/ckuusr.h    Sun Nov 24 19:20:52 1996
  1802. --- ckuusr.h    Sun Mar 23 19:48:59 1997
  1803. ***************
  1804. *** 19,24 ****
  1805. --- 19,33 ----
  1806.    
  1807.   /* Sizes of things */
  1808.   
  1809. + #ifdef BIGBUFOK
  1810. + #define FNVALL 10238            /* Function return value */
  1811. + #define MAXARGLEN 8191        /* Function arg length after eval */
  1812. + #else
  1813. + #define FNVALL 1022
  1814. + #define MAXARGLEN 1023
  1815. + #endif /* BIGBUFOK */
  1816.   #define FSPECL 300            /* Max length for MSEND/GET string */
  1817.   #define VNAML 64            /* Max length for variable name */
  1818.   #define ARRAYREFLEN 128        /* Max length for array reference */
  1819.  
  1820. *** /w/pub/ftp/kermit/f/ckuus4.c    Sun Nov 24 19:20:50 1996
  1821. --- ckuus4.c    Sun Mar 23 19:46:01 1997
  1822. ***************
  1823. *** 3138,3144 ****
  1824.   }
  1825.   #endif /* NOFRILLS */
  1826.   
  1827. - #define FNVALL 1024
  1828.   char fnval[FNVALL+2];            /* Return value */
  1829.   
  1830.   static char ipabuf[16] = { NUL };    /* IP address buffer */
  1831.  
  1832. ====================
  1833. X-Patch-Number: 0022
  1834. Date: Sun Mar 23 19:25:18 1997
  1835. From: Frank da Cruz <fdc@columbia.edu>
  1836. Subject: Certain \function()s can misbehave
  1837.  
  1838. Certain \f...() functions return incorrect values, or even cause crashes or
  1839. core dumps, when arguments are missing (especially the first one), or when
  1840. they are too long.  Also:
  1841.  
  1842.  . The \fverify() function did not work right when given a starting position
  1843.    as the third argument. 
  1844.  . \fbreak() did not pay attention to the SET CASE setting
  1845.  . fverify() did not pay attention to the SET CASE setting
  1846.  . fverify() would crash if given a huge number as the 3rd argument
  1847.  . \flpad() and \frpad() erroneously truncated their arguments if they
  1848.    were longer than the padding length
  1849.  . \ftrim() and \fltrim() erroneously returned "0" if given an empty argument
  1850.  . \ttrim() and \fltrim() ignored SET CASE
  1851.  
  1852. Also, some of the string functions were inconsistent as to whether they
  1853. allowed a starting position -- e.g. \fverify() did, but \fbreak() didn't.
  1854. So an optional starting position was added as the 3rd argument to \fbreak()
  1855. and \fspan().  These are not documented in manual.
  1856.  
  1857. There were numerous problems in the code.  The fixes involve a complete
  1858. replacement of the fneval() function in ckuus4.c.  Note: this patch depends
  1859. on Patch 0021.
  1860.  
  1861. static char *                /* Evaluate builtin functions */
  1862. fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
  1863.     int i, j, k, len1, len2, len3, n, x, y;
  1864.     char *bp[FNARGS + 1];        /* Pointers to malloc'd strings */
  1865.     char c;
  1866.     char *p, *s;
  1867.     char *val1, *val2;            /* Pointers to numeric string values */
  1868. /*
  1869.   IMPORTANT: Note that argn is not an accurate count of the number of
  1870.   arguments.  We can't really tell if an argument is null until after we
  1871.   execute the code below.  So argn is really the maximum number of arguments
  1872.   we might have.  In particular note that argn is always at least 1, even
  1873.   if the function is called with empty parentheses (but don't count on it).
  1874. */
  1875.     if (!fn) fn = "";            /* Protect against null pointers */
  1876.     debug(F111,"fneval",fn,argn);
  1877.     debug(F110,"fneval",argp[0],0);
  1878.     if (argn > FNARGS) argn = FNARGS;    /* And too many arguments */
  1879.  
  1880.     y = lookup(fnctab,fn,nfuncs,&x);
  1881.     if (y < 0)                /* bad function name */
  1882.       return("");            /* so value is null */
  1883.  
  1884. #ifdef DEBUG
  1885.     if (deblog) {
  1886.     int j;
  1887.     for (j = 0; j < argn; j++)
  1888.       debug(F111,"fneval function arg",argp[j],j);
  1889.     }
  1890. #endif /* DEBUG */
  1891. /*
  1892.   \fliteral() and \fcontents() are special functions that do not evaluate
  1893.   their arguments, and are treated specially here.  After these come the
  1894.   functions whose arguments are evaluated in the normal way.
  1895. */
  1896.     if (y == FN_LIT) {            /* literal(arg1) */
  1897.     debug(F110,"flit",xp,0);
  1898.     return(xp ? xp : "");        /* return a pointer to arg itself */
  1899.     }
  1900.     if (y == FN_CON) {            /* Contents of variable, unexpanded. */
  1901.     char c;
  1902.     if (!(p = argp[0]) || !*p) return("");
  1903.     p = brstrip(p);
  1904.     if (*p == CMDQ) p++;
  1905.     if ((c = *p) == '%') {        /* Scalar variable. */
  1906.         c = *++p;            /* Get ID character. */
  1907.         p = "";            /* Assume definition is empty */
  1908.         if (!c) return(p);        /* Double paranoia */
  1909.         if (c >= '0' && c <= '9') { /* Digit for macro arg */
  1910.         if (maclvl < 0)        /* Digit variables are global */
  1911.           p = g_var[c];        /* if no macro is active */
  1912.         else            /* otherwise */
  1913.           p = m_arg[maclvl][c - '0']; /* they're on the stack */
  1914.         } else {
  1915.         if (isupper(c)) c -= ('a'-'A');
  1916.         p = g_var[c];        /* Letter for global variable */
  1917.         }
  1918.         return(p ? p : "");
  1919.     }
  1920.     if (c == '&') {            /* Array reference. */
  1921.         int vbi, d;
  1922.         if (arraynam(p,&vbi,&d) < 0) /* Get name and subscript */
  1923.           return("");
  1924.         if (chkarray(vbi,d) > 0) {    /* Array is declared? */
  1925.         vbi -= ARRAYBASE;    /* Convert name to index */
  1926.         if (a_dim[vbi] >= d) {    /* If subscript in range */
  1927.             char **ap;
  1928.             ap = a_ptr[vbi];    /* get data pointer */
  1929.             if (ap) {        /* and if there is one */
  1930.             return(ap[d]);    /* return what it points to */
  1931.             }
  1932.         }
  1933.         } else return("");
  1934.     }
  1935.     }
  1936.  
  1937.     for (i = 0; i < FNARGS; i++)    /* Initialize all argument pointers */
  1938.       bp[i] = NULL;
  1939.  
  1940.     for (i = 0; i < argn; i++) {    /* Loop to expand each argument */
  1941.     n = MAXARGLEN;            /* Allow plenty of space */
  1942.     bp[i] = s = malloc(n+1);    /* Allocate space for this argument */
  1943.     if (bp[i] == NULL) {        /* handle failure to get space */
  1944.         for (k = 0; k < i; k++) if (bp[k]) free(bp[k]);
  1945.         debug(F101,"fneval malloc failure, arg","",i);
  1946.         return("");
  1947.     }
  1948.     p = argp[i] ? argp[i] : "";    /* Point to this argument */
  1949.  
  1950. /*
  1951.   Trim leading and trailing spaces from the original argument, before
  1952.   evaluation.  This code new to edit 184.
  1953. */
  1954.     {
  1955.         int x, j;
  1956.         x = strlen(p);
  1957.         if (*p == '{' && *(p+x-1) == '}') {
  1958.         p[x-1] = NUL;
  1959.         p++;
  1960.         x -= 2;
  1961.         } else {
  1962.         j = x - 1;        /* Trim trailing whitespace */
  1963.         while (j > 0 && (*(p + j) == SP || *(p + j) == HT))
  1964.           *(p + j--) = NUL;
  1965.         while (*p == SP || *p == HT) /* Strip leading whitespace */
  1966.           p++;
  1967.         }
  1968.     }
  1969.  
  1970. /* Now evaluate the argument */
  1971.  
  1972.     if (zzstring(p,&s,&n) < 0) {    /* Expand arg into new space */
  1973.         debug(F101,"fneval xxstring fails, arg","",i);
  1974.         for (k = 0; k <= i; k++)    /* Free up previous space on error */
  1975.           if (bp[k]) free(bp[k]);
  1976.         return("");            /* and return null string. */
  1977.     }
  1978.     debug(F111,"fneval arg",bp[i],i);
  1979.     }
  1980.  
  1981. #ifdef DEBUG
  1982.     if (deblog) {
  1983.     int j;
  1984.     for (j = 0; j < argn; j++) {
  1985.         debug(F111,"fneval arg post eval",argp[j],j);
  1986.         debug(F111,"fneval evaluated arg",bp[j],j);
  1987.     }
  1988.     }
  1989. #endif /* DEBUG */
  1990. /*
  1991.   At this point bp[0..argn-1] are not NULL and all must be freed
  1992.   before returning.
  1993. */
  1994.     switch (y) {            /* Do function on expanded args */
  1995.  
  1996.       case FN_DEF:            /* \fdefinition(arg1) */
  1997.     if (!bp[0]) return("");
  1998.     k = mlook(mactab,bp[0],nmac);
  1999.     p = (k > -1) ? mactab[k].mval : "";
  2000.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2001.     return(p ? p : "");
  2002.  
  2003.       case FN_EVA:            /* \fevaluate(arg1) */
  2004.     p = "";
  2005.     if (argn > 0)
  2006.       p = *(bp[0]) ? evala(bp[0]) : "";
  2007.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2008.     return(p ? p : "");
  2009.  
  2010.       case FN_EXE:            /* \fexecute(arg1) */
  2011.     if (argn < 1) return("");
  2012.     j = (int)strlen(s = bp[0]);    /* Length of macro invocation */
  2013.     p = "";                /* Initialize return value to null */
  2014.     if (j) {            /* If there is a macro to execute */
  2015.         while (*s == SP) s++,j--;    /* strip leading spaces */
  2016.         p = s;            /* remember beginning of macro name */
  2017.         for (i = 0; i < j; i++) {    /* find end of macro name */
  2018.         if (*s == SP)
  2019.           break;
  2020.         s++;
  2021.         }
  2022.         if (*s == SP)     {    /* if there was a space after */
  2023.         *s++ = NUL;        /* terminate the macro name */
  2024.         while (*s == SP) s++;    /* skip past any extra spaces */
  2025.         } else s = "";        /* maybe there are no arguments */
  2026.         if (p && *p)
  2027.           k = mlook(mactab,p,nmac);    /* Look up the macro name */
  2028.         else k = -1;
  2029. /*
  2030.   This is just a WEE bit dangerous because we are copying up to 9 arguments
  2031.   into the space reserved for one.  It won't overrun the buffer, but if there
  2032.   are lots of long arguments we might lose some.  The other problem is that if
  2033.   the macro has more than 3 arguments, the 4th through last are all
  2034.   concatenated onto the third.  (The workaround is to use spaces rather than
  2035.   commas to separate them.)  Leaving it like this to avoid having to allocate
  2036.   tons more buffers.
  2037. */
  2038.         if (argn > 1) {        /* Commas used instead of spaces */
  2039.         int i;
  2040.         char *p = bp[0];    /* Reuse this space */
  2041.         *p = NUL;        /* Make into dodo() arg list */
  2042.         for (i = 1; i < argn; i++) {
  2043.             strncat(p,bp[i],MAXARGLEN);
  2044.             strncat(p," ",MAXARGLEN);
  2045.         }            
  2046.         s = bp[0];        /* Point to new list */
  2047.         }
  2048.         p = "";            /* Initialize return value */
  2049.         if (k >= 0) {        /* If macro found in table */
  2050.         /* Go set it up (like DO cmd) */
  2051.         if ((j = dodo(k,s,cmdstk[cmdlvl].ccflgs)) > 0) {
  2052.             if (cmpush() > -1) { /* Push command parser state */
  2053.             extern int ifc;
  2054.             int ifcsav = ifc; /* Push IF condition on stack */
  2055.             k = parser(1);    /* Call parser to execute the macro */
  2056.             cmpop();    /* Pop command parser */
  2057.             ifc = ifcsav;    /* Restore IF condition */
  2058.             if (k == 0) {    /* No errors, ignore action cmds. */
  2059.                 p = mrval[maclvl+1]; /* If OK, set return value. */
  2060.                 if (p == NULL) p = "";
  2061.             }
  2062.             } else {        /* Can't push any more */
  2063.             debug(F100,"fexec pushed too deep","",0);
  2064.                         printf("\n?\\fexec() too deeply nested\n");
  2065.             while (cmpop() > -1) ;
  2066.             p = "";
  2067.             }
  2068.         }
  2069.         }
  2070.     }
  2071.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2072.     return(p ? p : "");
  2073.  
  2074.       case FN_FC:            /* \ffiles() - File count. */
  2075.     if (argn < 1) return("0");
  2076.     if (*(bp[0])) {
  2077.         k = zxpand(bp[0]);
  2078.         sprintf(fnval,"%d",k);
  2079.         p = fnval;
  2080.     } else p = "0";
  2081.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2082.     return(p);
  2083.  
  2084.       case FN_FIL:            /* \fnextfile() - Next file in list. */
  2085.     p = fnval;            /* (no args) */
  2086.     *p = NUL;
  2087.     znext(p);
  2088.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2089.     return(p ? p : "");
  2090.  
  2091.       case FN_IND:            /* \findex(arg1,arg2,arg3) */
  2092.       case FN_RIX:            /* \frindex(arg1,arg2,arg3) */
  2093.     p = "0";
  2094.     if (argn > 1) {            /* Only works if we have 2 or 3 args */
  2095.         int start;
  2096.         len1 = (int)strlen(bp[0]);    /* length of string to look for */
  2097.         len2 = (int)strlen(s = bp[1]); /* length of string to look in */
  2098.         if (len1 < 1 || len2 < 1)    /* Watch out for empty strings */
  2099.           goto indexfin;
  2100.         j = len2 - len1;        /* length difference */
  2101.         start = (y == FN_IND) ? 0 : j; /* Starting position */
  2102.         if (argn > 2) {
  2103.         val1 = *(bp[2]) ? evala(bp[2]) : "";
  2104.         if (chknum(val1)) {
  2105.             int t;
  2106.             t = atoi(val1) - 1;
  2107.             if (t < 0) t = 0;
  2108.             start = (y == FN_IND) ? t : start - t - 1;
  2109.             if (start < 0) start = 0;
  2110.         }
  2111.         }
  2112.         start = ckindex(bp[0],bp[1],start,(y==FN_IND)?0:1,inpcas[cmdlvl]);
  2113.         sprintf(fnval,"%d",start);
  2114.         p = fnval;
  2115.     }
  2116.       indexfin:
  2117.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2118.     return(p);
  2119.  
  2120.       case FN_RPL:            /* \freplace(s1,s2,s3) */
  2121.       /*
  2122.     s = bp[0] = source string
  2123.         bp[1] = match string
  2124.         bp[2] = replacement string
  2125.     p = fnval = destination (result) string
  2126.       */
  2127.     if (argn < 1) return("");
  2128.     p = fnval;
  2129.     if (argn < 2) {            /* Only works if we have 2 or 3 args */
  2130.         strcpy(p,bp[0]);
  2131.     } else  {            
  2132.         len1 = (int)strlen(bp[0]);    /* length of string to look in */
  2133.         len2 = (int)strlen(bp[1]);    /* length of string to look for */
  2134.         len3 = (argn < 3) ? 0 : (int)strlen(bp[2]); /* Len of replacemnt */
  2135.         j = len1 - len2 + 1;
  2136.         if (j < 1 || len1 == 0 || len2 == 0) { /* Args out of whack */
  2137.         strcpy(p,bp[0]);    /* so just return original string */
  2138.         } else {
  2139.         s = bp[0];        /* Point to beginning of string */
  2140.         while (j--) {        /* For each character */
  2141.             if (inpcas[cmdlvl] ?
  2142.             !strncmp(bp[1],s,len2) :
  2143.             !xxstrcmp(bp[1],s,len2) ) { /* To be replaced? */
  2144.             if (len3) {            /* Yes, */
  2145.                 strncpy(p,bp[2],len3);  /* replace it */
  2146.                 p += len3;
  2147.             }
  2148.             s += len2;                /* and skip past it. */
  2149.             } else {        /* No, */
  2150.             *p++ = *s++;    /* just copy this character */
  2151.             }
  2152.         }
  2153.         *p = NUL;
  2154.         while (*p++ = *s++);
  2155.         }
  2156.     }
  2157.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2158.     return(p = fnval);
  2159.  
  2160.       case FN_CHR:            /* \fcharacter(arg1) */
  2161.     if (argn < 1) return("");
  2162.     val1 = *(bp[0]) ? evala(bp[0]) : "";
  2163.     if (chknum(val1)) {        /* Must be numeric */
  2164.         i = atoi(val1);
  2165.         if (i >= 0 && i < 256) {    /* Must be an 8-bit value */
  2166.         p = fnval;
  2167.         *p++ = (char) i;
  2168.         *p = NUL;
  2169.         p = fnval;
  2170.         } else p = "";        /* Otherwise return empty string */
  2171.     } else p = "";            /* Otherwise return empty string */
  2172.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2173.     return(p);
  2174.  
  2175.       case FN_COD:            /* \fcode(char) */
  2176.     if (argn < 1) return("");
  2177.     if ((int)strlen(bp[0]) > 0) {
  2178.         p = fnval;
  2179.         i = *bp[0];
  2180.         sprintf(p,"%d",(i & 0xff));
  2181.     } else p = "";
  2182.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2183.     return(p);
  2184.  
  2185.       case FN_LEN:            /* \flength(arg1) */
  2186.     if (argn > 0) {
  2187.         p = fnval;
  2188.         sprintf(p,"%d",(int)strlen(bp[0]));
  2189.     } else p = "0";
  2190.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2191.     return(p);
  2192.  
  2193.       case FN_LOW:            /* \flower(arg1) */
  2194.     if (argn < 1) return("");
  2195.     s = bp[0];
  2196.     p = fnval;
  2197.  
  2198.     while (*s) {
  2199.         if (isupper(*s))
  2200.           *p = (char) tolower(*s);
  2201.         else
  2202.           *p = *s;
  2203.         p++; s++;
  2204.     }
  2205.     *p = NUL;
  2206.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2207.     p = fnval;
  2208.     return(p);
  2209.  
  2210.       case FN_MAX:            /* \fmax(arg1,arg2) */
  2211.       case FN_MIN:            /* \fmin(arg1,arg2) */
  2212.       case FN_MOD:            /* \fmod(arg1,arg2) */
  2213.     if (argn < 2) return("");
  2214.     val1 = *(bp[0]) ? evala(bp[0]) : "";
  2215.     free(bp[0]);            /* Copy this because evala() returns */
  2216.     bp[0] = malloc((int)strlen(val1)+1); /* pointer to same */
  2217.     strcpy(bp[0],val1);
  2218.     val1 = bp[0];            /* buffer next time. */
  2219.     val2 = *(bp[1]) ? evala(bp[1]) : "";
  2220.     if (chknum(val1) && chknum(val2)) {
  2221.         i = atoi(val1);
  2222.         j = atoi(val2);
  2223.         switch (y) {
  2224.           case FN_MAX:
  2225.         if (j < i) j = i;
  2226.         break;
  2227.           case FN_MIN:
  2228.         if (j > i) j = i;
  2229.         break;
  2230.           case FN_MOD:
  2231.         if (j == 0) { p = ""; goto modfin; }
  2232.         j = i % j;
  2233.         break;
  2234.         }
  2235.         p = fnval;
  2236.         sprintf(p,"%d",j);
  2237.     } else p = "";
  2238.       modfin:
  2239.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2240.     return(p);
  2241.  
  2242.       case FN_SUB:            /* \fsubstr(arg1,arg2,arg3) */
  2243.       case FN_RIG:            /* \fright(arg1,arg2) */
  2244.     if (argn < 1) return("");
  2245.     val1 = "";
  2246.     if (argn > 1)
  2247.       if (*(bp[1]))
  2248.         val1 =  evala(bp[1]);
  2249.     free(bp[1]);            /* Have to copy this */
  2250.     bp[1] = malloc((int)strlen(val1)+1);
  2251.     strcpy(bp[1],val1);
  2252.     val1 = bp[1];
  2253.     val2 = "";
  2254.     if (argn > 2)
  2255.       if (*(bp[2]))
  2256.         val2 = evala(bp[2]);
  2257.     if (
  2258.         ((argn > 1) && (int)strlen(val1) && !rdigits(val1)) ||
  2259.         ((y == FN_SUB) &&
  2260.           ((argn > 2) && (int)strlen(val2) && !rdigits(val2)))
  2261.         ) {
  2262.         p = "";            /* if either, return null */
  2263.     } else {
  2264.         int lx;
  2265.         p = fnval;            /* pointer to result */
  2266.         lx = strlen(bp[0]);        /* length of arg1 */
  2267.         if (y == FN_SUB) {        /* substring */
  2268.         k = (argn > 2) ? atoi(val2) : MAXARGLEN; /* length */
  2269.         j = (argn > 1) ? atoi(val1) : 1; /* start pos for substr */
  2270.         } else {                 /* right */
  2271.         k = (argn > 1) ? atoi(val1) : lx; /* length */
  2272.         j = lx - k + 1;             /* start pos for right */
  2273.         if (j < 1) j = 1;
  2274.         }
  2275.         if (k > 0 && j <= lx) {          /* if start pos in range */
  2276.         s = bp[0]+j-1;             /* point to source string */
  2277.         for (i = 0; (i < k) && (*p++ = *s++); i++) ;  /* copy */
  2278.         }
  2279.         *p = NUL;            /* terminate the result */
  2280.         p = fnval;            /* and point to it. */
  2281.     }
  2282.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]); /* Free temp mem */
  2283.     return(p);
  2284.  
  2285.       case FN_UPP:            /* \fupper(arg1) */
  2286.     s = bp[0] ? bp[0] : "";
  2287.     p = fnval;
  2288.     while (*s) {
  2289.         if (islower(*s))
  2290.           *p = (char) toupper(*s);
  2291.         else
  2292.           *p = *s;
  2293.         p++; s++;
  2294.     }
  2295.     *p = NUL;
  2296.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2297.     p = fnval;
  2298.     return(p);
  2299.  
  2300.       case FN_REP:            /* \frepeat(text,number) */
  2301.     if (argn < 1) return("");
  2302.     p = fnval;            /* Return value */
  2303.     *p = NUL;
  2304.     val1 = "1";
  2305.     if (argn > 1)
  2306.       if (*(bp[1]))
  2307.         val1 = evala(bp[1]);
  2308.     if (chknum(val1)) {        /* Repeat count */
  2309.         n = atoi(val1);
  2310.         if (n > 0) {        /* Make n copies */
  2311.         p = fnval;
  2312.         *p = '\0';
  2313.         k = (int)strlen(bp[0]);    /* Make sure string has some length */
  2314.         if (k > 0) {
  2315.             for (i = 0; i < n; i++) {
  2316.             s = bp[0];
  2317.             for (j = 0; j < k; j++) {
  2318.                 if ((p - fnval) >= FNVALL) { /* Protect against */
  2319.                 p = "";                 /* core dumps... */
  2320.                 break;
  2321.                 } else *p++ = *s++;
  2322.             }
  2323.             }
  2324.             *p = NUL;
  2325.         }
  2326.         }
  2327.     }
  2328.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2329.     p = fnval;
  2330.     return(p);
  2331.  
  2332. #ifndef NOFRILLS
  2333.       case FN_REV:            /* \freverse() */
  2334.     if (argn < 1) return("");
  2335.     p = fnval;
  2336.     yystring(bp[0],&p);
  2337.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2338.     return(p);
  2339. #endif /* NOFRILLS */
  2340.  
  2341.       case FN_RPA:            /* \frpad() and \flpad() */
  2342.       case FN_LPA:
  2343.     if (argn < 1) return("");
  2344.     *fnval = NUL;            /* Return value */
  2345.     val1 = "";
  2346.     if (argn > 1)
  2347.       if (*(bp[1]))
  2348.         val1 = evala(bp[1]);
  2349.     if (argn == 1 || !*val1) {    /* If a number wasn't given */
  2350.         p = fnval;            /* just return the original string */
  2351.         strncpy(p,bp[0],FNVALL);
  2352.     } else if (chknum(val1)) {    /* Repeat count */
  2353.         char pc;
  2354.         n = atoi(val1);
  2355.         if (n >= 0) {
  2356.         p = fnval;
  2357.         k = (int)strlen(bp[0]);    /* Length of string to be padded */
  2358.         if (k >= n) {        /* It's already long enough */
  2359.             strncpy(p,bp[0],FNVALL);
  2360.         } else {
  2361.             if (n + k <= FNVALL) {
  2362.             pc = (char) ((argn < 3) ? SP : *bp[2]);
  2363.             if (!pc) pc = SP;
  2364.             if (y == FN_RPA) { /* RPAD */
  2365.                 strncpy(p,bp[0],k);
  2366.                 p += k;
  2367.                 for (i = k; i < n; i++)
  2368.                   *p++ = pc;
  2369.             } else {    /* LPAD */
  2370.                 n -= k;
  2371.                 for (i = 0; i < n; i++)
  2372.                   *p++ = pc;
  2373.                 strncpy(p,bp[0],k);
  2374.                 p += k;
  2375.             }
  2376.             }
  2377.             *p = NUL;
  2378.         }
  2379.         }
  2380.     }
  2381.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2382.     p = fnval;
  2383.     return(p);
  2384.  
  2385. #ifdef ZFCDAT
  2386.       case FN_FD:            /* \fdate(filename) */
  2387.     p = fnval;
  2388.     *p = NUL;
  2389.     if (argn > 0)
  2390.       sprintf(fnval,"%s",*(bp[0]) ? zfcdat(bp[0]) : "");
  2391.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2392.     return(p);
  2393. #endif /* ZFCDAT */
  2394.  
  2395.       case FN_FS:            /* \fsize(filename) */
  2396.     p = fnval;
  2397.     *p = NUL;
  2398.     if (argn > 0)
  2399.       sprintf(fnval,"%ld",*(bp[0]) ? zchki(bp[0]) : 0L);
  2400.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2401.     return(p);
  2402.  
  2403.       case FN_VER:            /* \fverify() */
  2404.     p = "0";
  2405.     if (argn > 1) {            /* Only works if we have 2 or 3 args */
  2406.         int start;
  2407.         char *s2, ch1, ch2;
  2408.         start = 0;
  2409.         if (argn > 2) {        /* Starting position specified */
  2410.         val1 = *(bp[2]) ? evala(bp[2]) : "";
  2411.         if (chknum(val1)) {
  2412.             start = atoi(val1) /* - 1 */;
  2413.             if (start < 0) start = 0;
  2414.             if (start > (int)strlen(bp[1]))
  2415.               goto verfin;
  2416.         }
  2417.         }
  2418.         i = start;
  2419.         p = "0";
  2420.         for (s = bp[1] + start; *s; s++,i++) {
  2421.         ch1 = *s;
  2422.         if (!inpcas[cmdlvl]) if (islower(ch1)) ch1 = toupper(ch1);
  2423.         j = 0;
  2424.         for (s2 = bp[0]; *s2; s2++) {
  2425.             ch2 = *s2;
  2426.             if (!inpcas[cmdlvl]) if (islower(ch2)) ch2 = toupper(ch2);
  2427.             if (ch1 == ch2) {
  2428.             j = 1;
  2429.             break;
  2430.             }
  2431.         }
  2432.         if (j == 0) {
  2433.             sprintf(fnval,"%d",i+1);
  2434.             p = fnval;
  2435.             break;
  2436.         }
  2437.         }
  2438.     }
  2439.       verfin:
  2440.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2441.     return(p);
  2442.  
  2443.       case FN_IPA:            /* Find and return IP address */
  2444.     if (argn > 0) {            /* in argument string. */
  2445.         int start;
  2446.         char *s2;
  2447.         start = 0;
  2448.         if (argn > 1) {        /* Starting position specified */
  2449.         if (chknum(bp[1])) {
  2450.             start = atoi(bp[1]) - 1;
  2451.             if (start < 0) start = 0;
  2452.         }
  2453.         }
  2454.         p = getip(bp[0]+start);
  2455.     } else p = "";
  2456.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2457.     return(p);
  2458.  
  2459.       case FN_HEX:            /* \fhexify(arg1) */
  2460.     if (argn < 1) return("");
  2461.     p = "";
  2462.     if ((int)strlen(bp[0]) < (FNVALL / 2)) {
  2463.         s = bp[0];
  2464.         p = fnval;
  2465.         while (*s) {
  2466.         x = (*s >> 4) & 0x0f;
  2467.         *p++ = hexdigits[x];
  2468.         x = *s++ & 0x0f;
  2469.         *p++ = hexdigits[x];        
  2470.         }
  2471.         *p = NUL;
  2472.         p = fnval;
  2473.     }
  2474.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2475.     return(p);
  2476.  
  2477.       case FN_UNH: {            /* \funhex(arg1) */
  2478.       int c[2], i;
  2479.       if (argn < 1) return("");
  2480.       p = "";
  2481.       if ((int)strlen(bp[0]) < (FNVALL * 2)) {
  2482.           s = bp[0];
  2483.           p = fnval;
  2484.           while (*s) {
  2485.           for (i = 0; i < 2; i++) {
  2486.               c[i] = *s++;
  2487.               if (!c[i]) { p = ""; goto unhexfin; }
  2488.               if (islower(c[i])) c[i] = toupper(c[i]);
  2489.               if (c[i] >= '0' && c[i] <= '9')
  2490.             c[i] -= 0x30;
  2491.               else if (c[i] >= 'A' && c[i] <= 'F')
  2492.             c[i] -= 0x37;
  2493.               else { p = ""; goto unhexfin; }
  2494.           }
  2495.           *p++ = ((c[0] << 4) & 0xf0) | (c[1] & 0x0f);
  2496.           }
  2497.           *p = NUL;
  2498.           p = fnval;
  2499.       }
  2500.   unhexfin:
  2501.       for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2502.       return(p);
  2503.       }
  2504.  
  2505.       case FN_BRK: {            /* \fbreak() */
  2506.       char * c;            /* Characters to break on */
  2507.       char c2, s2;
  2508.       int start = 0;
  2509.       int done = 0;
  2510.       if (argn < 1) return("");
  2511.       p = fnval;            /* Destination pointer */
  2512.       *p = NUL;
  2513.       if (argn > 2) {
  2514.           s = bp[2] ? bp[2] : "";
  2515.           if (chknum(s)) {
  2516.           start = atoi(s);
  2517.           if (start < 0) start = 0;
  2518.           if (start > (int)strlen(bp[0]))
  2519.             goto brkfin;
  2520.           }
  2521.       }
  2522.       s = bp[0] + start;        /* Source pointer */
  2523.  
  2524.       while (*s && !done) {
  2525.           s2 = *s;
  2526.           if (!inpcas[cmdlvl] && islower(s2)) s2 = toupper(s2);
  2527.           c = bp[1] ? bp[1] : "";    /* Character to break on */
  2528.           while (*c) {
  2529.           c2 = *c;
  2530.           if (!inpcas[cmdlvl] && islower(c2)) c2 = toupper(c2);
  2531.           if (c2 == s2) {
  2532.               done = 1;
  2533.               break;
  2534.           }
  2535.           c++;
  2536.           }
  2537.           if (done) break;
  2538.           *p++ = *s++;
  2539.       }
  2540.       *p = NUL;            /* terminate the result */
  2541.       p = fnval;            /* and point to it. */
  2542.     brkfin:
  2543.       for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2544.       return(p);
  2545.       }
  2546.  
  2547.       case FN_SPN: {            /* \fspan() */
  2548.       char *q;
  2549.       char c1, c2;
  2550.       int start = 0;
  2551.       if (argn < 1) return("");
  2552.       p = fnval;            /* Result pointer */
  2553.       *p = NUL;
  2554.       if (argn > 2) {        /* Starting position */
  2555.           s = bp[2] ? bp[2] : "";
  2556.           if (chknum(s)) {
  2557.           start = atoi(s);
  2558.           if (start < 0) start = 0;
  2559.           }
  2560.       }
  2561.       s = bp[0] + start;        /* Source pointer */
  2562.       if (argn > 1 &&
  2563.           (int)strlen(bp[1]) > 0 &&
  2564.           start <= (int)strlen(bp[0])) {
  2565.           while (*s) {        /* Loop thru source string */
  2566.           q = bp[1];        /* Span string */
  2567.           c1 = *s;
  2568.           if (!inpcas[cmdlvl])
  2569.             if (islower(c1)) c1 = toupper(c1);
  2570.           x = 0;
  2571.           while (c2 = *q++) {
  2572.               if (!inpcas[cmdlvl])
  2573.             if (islower(c2)) c2 = toupper(c2);
  2574.               if (c1 == c2) { x = 1; break; }
  2575.           }
  2576.           if (!x) break;
  2577.           *p++ = *s++;
  2578.           }
  2579.           *p = NUL;            /* Terminate and return the result */
  2580.           p = fnval;
  2581.       }
  2582.       for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2583.       return(p);
  2584.       }
  2585.  
  2586.       case FN_TRM:            /* \ftrim(s1[,s2]) */
  2587.       case FN_LTR:            /* \fltrim(s1[,s2]) */
  2588.     if (argn < 1) return("");
  2589.     if ((len1 = (int)strlen(bp[0])) > 0) {
  2590.         if (len1 > FNVALL)
  2591.           len1 = FNVALL;
  2592.         s = " \t";
  2593.         if (argn > 1)        /* Trim list given */
  2594.           s = bp[1];
  2595.         len2 = (int)strlen(s);
  2596.         if (len2 < 1) {        /* or not... */
  2597.         s = " \t";        /* Default is to trim whitespace */
  2598.         len2 = 2;
  2599.         }
  2600.         if (y == FN_TRM) {        /* Trim from right */
  2601.         char * q, p2, q2;
  2602.         strncpy(fnval,bp[0],FNVALL); /* Copy string to output */
  2603.         p = fnval + len1 - 1;    /* Point to last character */
  2604.  
  2605.         while (p >= (char *)fnval) { /* Go backwards */
  2606.             q = s;        /* Point to trim list */
  2607.             p2 = *p;
  2608.             if (!inpcas[cmdlvl])
  2609.               if (islower(p2)) p2 = toupper(p2);
  2610.             while (*q) {    /* Is this char in trim list? */
  2611.             q2 = *q;
  2612.             if (!inpcas[cmdlvl])
  2613.               if (islower(q2)) q2 = toupper(q2);
  2614.             if (p2 == q2) {    /* Yes, null it out */
  2615.                 *p = NUL;
  2616.                 break;
  2617.             }
  2618.             q++;
  2619.             }
  2620.             if (!*q)        /* Trim list exhausted */
  2621.               break;        /* So we're done. */
  2622.             p--;        /* Else keep trimming */
  2623.         }
  2624.         } else {            /* Trim from left */
  2625.         char * q, p2, q2;
  2626.         p = bp[0];        /* Source */
  2627.         while (*p) {
  2628.             p2 = *p;
  2629.             if (!inpcas[cmdlvl])
  2630.               if (islower(p2)) p2 = toupper(p2);
  2631.             q = s;
  2632.             while (*q) {    /* Is this char in trim list? */
  2633.             q2 = *q;
  2634.             if (!inpcas[cmdlvl])
  2635.               if (islower(q2)) q2 = toupper(q2);
  2636.             if (p2 == q2) {    /* Yes, point past it */
  2637.                 p++;    /* and try next source character */
  2638.                 break;
  2639.             }
  2640.             q++;        /* No, try next trim character */
  2641.             }
  2642.             if (!*q)        /* Trim list exhausted */
  2643.               break;        /* So we're done. */
  2644.         }
  2645.         strncpy(fnval,p,FNVALL);
  2646.         }
  2647.         p = fnval;
  2648.     } else p = "";
  2649.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2650.     return(p);
  2651.  
  2652.       case FN_CAP:            /* \fcapitalize(arg1) */
  2653.     if (argn < 1) return("");
  2654.     s = bp[0];
  2655.     p = fnval;
  2656.     x = 0;
  2657.     while (c = *s++) {
  2658.         if (isalpha(c)) {
  2659.         if (x == 0) {
  2660.             x = 1;
  2661.             if (islower(c))
  2662.               c = toupper(c);
  2663.         } else if (isupper(c))
  2664.           c = tolower(c);
  2665.         }
  2666.         *p++ = c;
  2667.     }
  2668.     *p = NUL;
  2669.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2670.     p = fnval;
  2671.     return(p);
  2672.  
  2673.       case FN_TOD:            /* Time of day to secs since midnite */
  2674.     if (argn < 1) return("");
  2675.     p = fnval;
  2676.     sprintf(p,"%ld",tod2sec(bp[0]));
  2677.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2678.     return(p);
  2679.  
  2680.       case FN_FFN:            /* Full pathname of file */
  2681.     p = fnval;
  2682.     *p = NUL;
  2683.     if (argn > 0)
  2684. #ifdef ZFNQFP
  2685.       zfnqfp(bp[0],FNVALL,p);
  2686. #else
  2687.       strcpy(p,bp[0]);
  2688. #endif /* ZFNQFP */
  2689.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2690.     return(p ? p : "");
  2691.  
  2692.       case FN_CHK: {            /* \fchecksum() */
  2693.       long chk = 0;
  2694.       p = (argn > 0) ? bp[0] : "";
  2695.       while (*p) chk += *p++;
  2696.       sprintf(fnval,"%lu",chk);
  2697.       for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2698.       return((char *)fnval);
  2699.       }
  2700.       case FN_CRC:            /* \fcrc16() */
  2701.     *fnval = NUL;
  2702.     if (argn > 0)
  2703.       sprintf(fnval,"%u",chk3((CHAR *)bp[0],0));
  2704.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2705.     return((char *)fnval);
  2706.  
  2707.       case FN_BSN:            /* \fbasename() */
  2708.     if (argn > 0)
  2709.       zstrip(bp[0],&p);
  2710.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2711.     return(p);
  2712.  
  2713.       default:
  2714.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  2715.     return("");
  2716.     }
  2717. }
  2718.  
  2719. ====================
  2720. X-Patch-Number: 0023
  2721. Date: Sun Mar 23 19:25:18 1997
  2722. From: Frank da Cruz <fdc@columbia.edu>
  2723. Subject: X MOD 0 crashes program
  2724.  
  2725. "\feval(number%0)", "\fmod(number,0)", or "EVALUATE number % 0" would
  2726. crash C-Kermit.  Also, dividing by zero would return -1 without issuing any
  2727. kind of warning.  Now both return -1 and always print a "?Divide by zero"
  2728. warning.  Patch:
  2729.  
  2730. *** /w/pub/ftp/kermit/f/ckuus5.c    Tue Feb 18 09:31:55 1997
  2731. --- ./ckuus5.c    Thu Mar 27 19:54:55 1997
  2732. ***************
  2733. *** 5532,5540 ****
  2734.       switch(op) {
  2735.         case '*': expval = oldval * expval; break;
  2736.         case '/':
  2737. !         if (expval == 0) expval = -1; /* don't divide by 0 */
  2738. !         else expval = oldval / expval; break;
  2739. !       case '%': expval = oldval % expval; break;
  2740.         case '&': expval = oldval & expval; break;
  2741.       }
  2742.       }
  2743. --- 5532,5545 ----
  2744.       switch(op) {
  2745.         case '*': expval = oldval * expval; break;
  2746.         case '/':
  2747. !       case '%':
  2748. !         if (expval == 0) {
  2749. !         if (!x_ifnum)
  2750. !           printf("?Divide by zero\n");
  2751. !         expval = -1; /* No way to return a null integer */
  2752. !         } else
  2753. !           expval = (op == '/') ? (oldval / expval) : (oldval % expval);
  2754. !         break;
  2755.         case '&': expval = oldval & expval; break;
  2756.       }
  2757.       }
  2758.  
  2759. ====================
  2760. X-Patch-Number: 0024
  2761. Date: Mon Mar 31 19:02:32 1997
  2762. From: Frank da Cruz <fdc@columbia.edu>
  2763. Subject: Internal bulletproofing for lower() function.
  2764.  
  2765. The lower() function did not check if called with a null pointer.  Patch:
  2766.  
  2767. *** /w/pub/ftp/kermit/f/ckucmd.c    Sun Nov 24 19:20:49 1996
  2768. --- ckucmd.c    Mon Mar 31 19:00:40 1997
  2769. ***************
  2770. *** 3875,3880 ****
  2771. --- 3875,3881 ----
  2772.   int
  2773.   lower(s) char *s; {
  2774.       int n = 0;
  2775. +     if (!s) return(0);
  2776.       while (*s) {
  2777.           if (isupper(*s)) *s = (char) tolower(*s);
  2778.           s++, n++;
  2779.       }
  2780.       return(n);
  2781.   }
  2782.  
  2783. ====================
  2784. X-Patch-Number: 0025
  2785. To: kermit@columbia.edu
  2786. Subject: Real OpenBSD support for C-Kermit 6.0
  2787. Date: Tue, 01 Apr 1997 11:56:01 -0700
  2788. From: "Todd C. Miller" <Todd.Miller@courtesan.com>
  2789.  
  2790. Below is a diff to add a real OpenBSD entry.  OpenBSD uses
  2791. ncurses as its curses and has terminfo so must link with
  2792. -ltermlib (-ltermcap is for termcap-compatibility).
  2793.  
  2794. --- makefile.DIST    Wed Dec 18 21:57:53 1996
  2795. +++ makefile    Tue Apr  1 11:51:23 1997
  2796. @@ -402,7 +402,7 @@
  2797.  # + for OSF/1 (vanilla, from OS/F), "make posix"
  2798.  # + for OkiStation 7300 Series, "make sys5r4sxtcp"
  2799.  # + for Olivetti LSX-3020 with X/OS R.2.3, "make xos23" or "make xos23c"
  2800. -# ? for OpenBSD, "make netbsd"?
  2801. +# + for OpenBSD, "make openbsd"
  2802.  # + for Perkin-Elmer (Concurrent) 3200 series, "make sys5".
  2803.  # + for Perkin-Elmer (Concurrent) 3200 series with <dirent.h>, "make ccop1"
  2804.  # + for Perkin-Elmer/Concurrent 3200 with Xelos R02, "make ccop1"
  2805. @@ -888,6 +888,14 @@
  2806.      $(MAKE) wermit \
  2807.      "CFLAGS= -DBSD44 -DCK_CURSES -DDYNAMIC -DTCPSOCKET $(KFLAGS) -O" \
  2808.      "LIBS= -lcurses -ltermcap"
  2809. +
  2810. +#OpenBSD
  2811. +#Note that OpenBSD uses ncurses as its curses so use -ltermlib, not -ltermcap
  2812. +openbsd:
  2813. +    @echo Making C-Kermit $(CKVER) for OpenBSD with curses...
  2814. +    $(MAKE) wermit \
  2815. +    "CFLAGS= -DBSD44 -DCK_CURSES -DDYNAMIC -DTCPSOCKET $(KFLAGS) -O" \
  2816. +    "LIBS= -lcurses -ltermlib"
  2817.  
  2818.  #NetBSD
  2819.  netbsd:
  2820.  
  2821. ====================
  2822. X-Patch-Number: 0026
  2823. Date: Tue Apr  1 18:02:15 1997
  2824. From: Frank da Cruz <fdc@columbia.edu>
  2825. Subject: Incorrect checks for macro/command-file nesting depth
  2826.  
  2827. *** /w/pub/ftp/kermit/f/ckuusr.c    Tue Feb 18 09:31:40 1997
  2828. --- ckuusr.c    Tue Apr  1 18:00:56 1997
  2829. ***************
  2830. *** 3405,3411 ****
  2831.   #endif /* OS2 */
  2832.       char takepath[1024];
  2833.   
  2834. !     if (tlevel > MAXTAKE-1) {
  2835.           printf("?Take files nested too deeply\n");
  2836.           return(-2);
  2837.       }
  2838. --- 3405,3411 ----
  2839.   #endif /* OS2 */
  2840.       char takepath[1024];
  2841.   
  2842. !     if (tlevel >= MAXTAKE-1) {
  2843.           printf("?Take files nested too deeply\n");
  2844.           return(-2);
  2845.       }
  2846.  
  2847. *** /w/pub/ftp/kermit/f/ckuus5.c    Tue Feb 18 09:31:55 1997
  2848. --- ckuus5.c    Tue Apr  1 18:08:25 1997
  2849. ***************
  2850. *** 2526,2534 ****
  2851. --- 2526,2536 ----
  2852.           debug(F111,"popclvl mac 3",macp[maclvl],maclvl);
  2853.           *cmdbuf = '\0';        /* clear the command buffer */
  2854.           debug(F111,"popclvl mac 4",mrval[maclvl+1],maclvl);
  2855. +         if (maclvl+1 < MACLEVEL) {
  2856.           if (mrval[maclvl+1]) {    /* Free any deeper return values. */
  2857.               free(mrval[maclvl+1]);
  2858.               mrval[maclvl+1] = NULL;
  2859. +         }
  2860.           }
  2861.           debug(F111,"popclvl mac 6",mrval[maclvl+1],maclvl);
  2862.           maclvl--;            /* Pop macro level */
  2863.  
  2864. ====================
  2865. X-Patch-Number: 0027
  2866. Date: Tue Apr  1 18:34:55 1997
  2867. From: Frank da Cruz <fdc@columbia.edu>
  2868. Subject: ANSWER doesn't automatically CONNECT
  2869.  
  2870. The DIAL and REDIAL commands, if given from top level with DIAL CONNECT set
  2871. to ON or AUTO, and if they succeed, cause C-Kermit to enter CONNECT mode
  2872. automatically.  ANSWER should behave the same way.  Patch:
  2873.  
  2874. *** /w/pub/ftp/kermit/f/ckuusr.c    Tue Feb 18 09:31:40 1997
  2875. --- ckuusr.c    Tue Apr  1 18:31:48 1997
  2876. ***************
  2877. *** 1928,1934 ****
  2878.       cx == XXANSW || cx == XXLOOK) { /* DIAL, REDIAL etc */
  2879.       x = dodial(cx);
  2880.       debug(F101,"dodial returns","",x);
  2881. !     if ((cx == XXDIAL || cx == XXRED) &&
  2882.           (x > 0) &&            /* If DIAL or REDIAL succeeded */
  2883.           (dialcon > 0)) {
  2884.           if ( dialcon == 1 ||    /* And DIAL CONNECT is ON, */
  2885. --- 1928,1934 ----
  2886.       cx == XXANSW || cx == XXLOOK) { /* DIAL, REDIAL etc */
  2887.       x = dodial(cx);
  2888.       debug(F101,"dodial returns","",x);
  2889. !     if ((cx == XXDIAL || cx == XXRED || cx == XXANSW) &&
  2890.           (x > 0) &&            /* If DIAL or REDIAL succeeded */
  2891.           (dialcon > 0)) {
  2892.           if ( dialcon == 1 ||    /* And DIAL CONNECT is ON, */
  2893.  
  2894. ====================
  2895. X-Patch-Number: 0028
  2896. Date: Tue Apr  1 19:39:51 1997
  2897. From: Frank da Cruz <fdc@columbia.edu>
  2898. Subject: Overzealous EXIT warning
  2899.  
  2900. When SET EXIT WARNING is ON, C-Kermit can sometimes warn you about a
  2901. connection being open when it couldn't possibly be open.  This can happen,
  2902. for example, if you SET LINE to a serial device and then HANGUP, but the
  2903. serial device is still getting the Carrier Detect signal (e.g. because it is
  2904. connected to a modem that never drops CD).  However, if C-Kermit has been
  2905. told to HANGUP, or to close the connection via SET HOST or SET LINE with no
  2906. argument, then it knows the connection is closed and so it should not warn.
  2907. Here's the patch:
  2908.  
  2909. *** /w/pub/ftp/kermit/f/ckcmai.c    Tue Feb 18 09:31:26 1997
  2910. --- ./ckcmai.c    Tue Apr  1 19:35:59 1997
  2911. ***************
  2912. *** 969,974 ****
  2913. --- 969,975 ----
  2914.   extern int ttyfd, tn_exit;
  2915.   #endif /* NETCONN */
  2916.       int exitonclose = 0;        /* Exit on close */
  2917. +     int haveline = 0;            /* SET LINE or SET HOST in effect */
  2918.   
  2919.       int tlevel = -1;            /* Take-file command level */
  2920.   #ifdef NOLOCAL
  2921. *** /w/pub/ftp/kermit/f/ckuus3.c    Sun Nov 24 19:20:50 1996
  2922. --- ./ckuus3.c    Tue Apr  1 19:35:04 1997
  2923. ***************
  2924. *** 85,90 ****
  2925. --- 85,92 ----
  2926.     xfrcan, xfrchr, xfrnum, pacing, xitwarn, xitsta,
  2927.     cmd_cols, cmd_rows, ckxech, xaskmore, xfrbel;
  2928.   
  2929. + extern int haveline;
  2930.   #ifdef TCPSOCKET
  2931.     extern int tn_exit;
  2932.   #endif /* TCPSOCKET */
  2933. ***************
  2934. *** 4428,4433 ****
  2935. --- 4430,4436 ----
  2936.       debug(F101,"hupok x","",x);
  2937.       debug(F101,"hupok xitwarn","",xitwarn);
  2938.       debug(F101,"hupok network","",network);
  2939. +     debug(F101,"hupok haveline","",haveline);
  2940.   #ifdef CK_TTYFD
  2941.       debug(F101,"hupok ttyfd","",ttyfd);
  2942.   #endif /* CK_TTYFD */
  2943. ***************
  2944. *** 4450,4455 ****
  2945. --- 4453,4460 ----
  2946.           ttchk() >= 0
  2947.           )
  2948.             needwarn = 1;
  2949. +         /* A connection seems to be open but it can't possibly be */
  2950. +         if (!haveline) needwarn = 0;
  2951.           if (needwarn) {
  2952.           if (strcmp(ttname,"*"))
  2953.             printf(
  2954. ***************
  2955. *** 4474,4479 ****
  2956. --- 4479,4486 ----
  2957.             1            /* or can't check ttyfd, then warn */
  2958.   #endif /* CK_TTYFD */ 
  2959.               ;
  2960. +         /* A connection seems to be open but it can't possibly be */
  2961. +         if (!haveline) needwarn = 0;
  2962.           if (needwarn)
  2963.             printf(
  2964.                " A serial connection might still be active on %s.\n",
  2965. *** /w/pub/ftp/kermit/f/ckuus7.c    Wed Nov 27 19:54:46 1996
  2966. --- ./ckuus7.c    Tue Apr  1 19:38:36 1997
  2967. ***************
  2968. *** 129,134 ****
  2969. --- 129,135 ----
  2970.   extern int tnlm, sosi, tlevel, lf_opts, backgrd, flow, fdispla, b_save, f_save;
  2971.   extern int fnrpath, fnspath, debses, parity, pktpaus, ttnproto, ckxech;
  2972.   extern int x_ifnum;
  2973. + extern int haveline;
  2974.   extern int
  2975.     atenci, atenco, atdati, atdato, atleni, atleno, atblki, atblko,
  2976.     attypi, attypo, atsidi, atsido, atsysi, atsyso, atdisi, atdiso;
  2977. ***************
  2978. *** 5243,5248 ****
  2979. --- 5244,5250 ----
  2980.       mdmhup();
  2981.   #endif /* NODIAL */
  2982.       ttclos(0);            /* Close old connection, if any */
  2983. +     haveline = 0;
  2984.       if (oldplex > -1)        /* Restore duplex setting. */
  2985.         duplex = oldplex;
  2986.       if (*s) {            /* They gave a hostname */
  2987. ***************
  2988. *** 5273,5278 ****
  2989. --- 5275,5281 ----
  2990.           if (zz) {
  2991.           if (autoflow)        /* Maybe change flow control */
  2992.             setflow();
  2993. +         haveline = 1;
  2994.           return(success = 1);
  2995.           }
  2996.       }
  2997. *** /w/pub/ftp/kermit/f/ckuusr.c    Tue Feb 18 09:31:40 1997
  2998. --- ./ckuusr.c    Tue Apr  1 19:37:07 1997
  2999. ***************
  3000. *** 127,132 ****
  3001. --- 127,133 ----
  3002.   extern int size, local, sndsrc, xitsta, server, displa, binary, msgflg,
  3003.     escape, duplex, nfils, quiet, tlevel, pflag, zincnt, atcapr, atdiso, verwho,
  3004.     ckxech, carrier, deblog, sendmode, epktflg, what, moving, protocol;
  3005. + extern int haveline;
  3006.   extern int bye_active;
  3007.   extern long sendstart;
  3008.   #ifdef CK_TTYFD
  3009. ***************
  3010. *** 2417,2422 ****
  3011. --- 2418,2424 ----
  3012.       if (x)
  3013.         DialerSend(OPT_KERMIT_HANGUP, 0);
  3014.   #endif /* OS2 */
  3015. +     if (x) haveline = 0;
  3016.       return(success = x);
  3017.       }
  3018.  
  3019. ====================
  3020. X-Patch-Number: 0029
  3021. Date: Sat Apr  5 13:50:08 1997
  3022. From: Frank da Cruz <fdc@columbia.edu>
  3023. Subject: OUTPUT doesn't echo when DUPLEX is HALF
  3024.  
  3025. If INPUT ECHO is ON and DUPLEX is HALF, OUTPUT should echo locally.  Patch:
  3026.  
  3027. *** /w/pub/ftp/kermit/f/ckuus5.c    Tue Feb 18 09:31:55 1997
  3028. --- ckuus5.c    Sat Apr  5 13:48:46 1997
  3029. ***************
  3030. *** 1734,1739 ****
  3031. --- 1734,1740 ----
  3032.           msleep(pacing);
  3033.       }
  3034.       }
  3035. +     if (inecho && duplex && local) conxo(obsize,obuf);
  3036.       rc = 0;                /* Success */
  3037.     xxout_x:
  3038.       obn = 0;                /* Reset count */
  3039.  
  3040. ====================
  3041. X-Patch-Number: 0030
  3042. Date: Sat Apr  5 14:33:39 1997
  3043. From: Frank da Cruz <fdc@columbia.edu>
  3044. Subject: Minor problems with REMOTE DIRECTORY/DELETE/etc
  3045.  
  3046. The replies to REMOTE DIRECTORY, REMOTE DELETE, and REMOTE SPACE generated
  3047. by the C-Kermit server in UNIX and AOS/VS contained double carriage returns.
  3048. The responses generated by the OS-9 or Mac server contained double linefeeds.
  3049. Also, the REMOTE DELETE summary report counted files as being deleted when
  3050. they actually were not (e.g. if write-protected).  Patch:
  3051.  
  3052. *** /w/pub/ftp/kermit/f/ckcfns.c    Sun Nov 24 19:20:48 1996
  3053. --- ./ckcfns.c    Sat Apr  5 14:29:25 1997
  3054. ***************
  3055. *** 2631,2640 ****
  3056.   /*
  3057.     The following bunch of routines feed internally generated data to the server
  3058.     to send to the client in response to REMOTE commands like DIRECTORY, DELETE,
  3059. !   and so on.  Note that in writing this data to buffers, we do not use "\n".
  3060. !   Instead we use "\15\12", i.e. LITERAL carriage return and linefeed, because
  3061. !   that it was is required by the Kermit protocol in text mode.
  3062.   */
  3063.   static
  3064.   char funcbuf[512];
  3065.   static int
  3066. --- 2636,2663 ----
  3067.   /*
  3068.     The following bunch of routines feed internally generated data to the server
  3069.     to send to the client in response to REMOTE commands like DIRECTORY, DELETE,
  3070. !   and so on.  We have to write these lines in the format appropriate to our
  3071. !   platform, so they can be converted to generic (CRLF) text format by the
  3072. !   packetizer.
  3073.   */
  3074. + #ifdef UNIX
  3075. + char * endline = "\12";
  3076. + #else
  3077. + #ifdef datageneral
  3078. + char * endline = "\12";
  3079. + #else
  3080. + #ifdef MAC
  3081. + char * endline = "\15";
  3082. + #else
  3083. + #ifdef OSK
  3084. + char * endline = "\15";
  3085. + #else
  3086. + char * endline = "\15\12";
  3087. + #endif /* OSK */
  3088. + #endif /* MAC */
  3089. + #endif /* datageneral */
  3090. + #endif /* UNIX */
  3091.   static
  3092.   char funcbuf[512];
  3093.   static int
  3094. ***************
  3095. *** 2792,2817 ****
  3096.           if (len > -1L) {
  3097.               nfiles++;
  3098.               nbytes += len;
  3099. !             sprintf(funcbuf," %04d-%02d-%02d %02d:%02d %11ld %s\15\12",
  3100. !                     year, month, date, hour, minute, len, p);
  3101.           } else {
  3102.               ndirs++;
  3103.               sprintf(funcbuf,
  3104. !             " %04d-%02d-%02d %02d:%02d %11s %s\15\12", 
  3105. !                     year, month, date, hour, minute, "(directory)", p);
  3106.           }
  3107.           funcnxt = 0;
  3108.           funclen = strlen(funcbuf);
  3109.       } else if (nxpnd == 0) {        /* Done, send summary */
  3110.       char *blankline = "";        /* At beginning of summary */
  3111. -     char *endline = "\15\12";    /* At end of summary */
  3112.   /*
  3113.     The idea is to prevent (a) unnecessary multiple blanklines, and (b)
  3114.     prompt-stomping.  Preventing (b) is practically impossible, because it
  3115.     depends on the client so for now always include that final CRLF.
  3116.   */
  3117.       if (!ndirs || !nbytes || !nfiles)
  3118. !       blankline = "\15\12";
  3119.           sprintf(funcbuf,
  3120.           "%sSummary: %ld director%s, %ld file%s, %ld byte%s%s",
  3121.           blankline,
  3122. --- 2815,2840 ----
  3123.           if (len > -1L) {
  3124.               nfiles++;
  3125.               nbytes += len;
  3126. !             sprintf(funcbuf," %04d-%02d-%02d %02d:%02d %11ld %s%s",
  3127. !                     year, month, date, hour, minute, len, p, endline);
  3128.           } else {
  3129.               ndirs++;
  3130.               sprintf(funcbuf,
  3131. !             " %04d-%02d-%02d %02d:%02d %11s %s%s", 
  3132. !                     year, month, date, hour, minute,
  3133. !             "(directory)", p, endline);
  3134.           }
  3135.           funcnxt = 0;
  3136.           funclen = strlen(funcbuf);
  3137.       } else if (nxpnd == 0) {        /* Done, send summary */
  3138.       char *blankline = "";        /* At beginning of summary */
  3139.   /*
  3140.     The idea is to prevent (a) unnecessary multiple blanklines, and (b)
  3141.     prompt-stomping.  Preventing (b) is practically impossible, because it
  3142.     depends on the client so for now always include that final CRLF.
  3143.   */
  3144.       if (!ndirs || !nbytes || !nfiles)
  3145. !       blankline = endline;
  3146.           sprintf(funcbuf,
  3147.           "%sSummary: %ld director%s, %ld file%s, %ld byte%s%s",
  3148.           blankline,
  3149. ***************
  3150. *** 2887,2893 ****
  3151.       ndirs = 0L;
  3152.       nfiles = 0L;
  3153.       nbytes = 0L;
  3154. !     sprintf(funcbuf,"Listing files: \"%s\"\15\12\15\12",name);
  3155.       funcnxt = 0;
  3156.       funclen = strlen(funcbuf);
  3157.   
  3158. --- 2910,2916 ----
  3159.       ndirs = 0L;
  3160.       nfiles = 0L;
  3161.       nbytes = 0L;
  3162. !     sprintf(funcbuf,"Listing files: \"%s\"%s%s",name,endline,endline);
  3163.       funcnxt = 0;
  3164.       funclen = strlen(funcbuf);
  3165.   
  3166. ***************
  3167. *** 2951,2965 ****
  3168.           if (*p == '/') p++;
  3169.   
  3170.           if (len > -1L) {
  3171.               nfiles++;
  3172.               nbytes += len;
  3173. !             sprintf(funcbuf,
  3174. !             " %10s: %s\15\12",
  3175. !                     zdelet(name) ? "skipping" : "deleted",
  3176. !             p
  3177. !             );
  3178.           } else
  3179. !       sprintf(funcbuf," directory: %s\15\12", p);
  3180.           funcnxt = 0;
  3181.           funclen = strlen(funcbuf);
  3182.       } else 
  3183. --- 2974,2988 ----
  3184.           if (*p == '/') p++;
  3185.   
  3186.           if (len > -1L) {
  3187. +         if (zdelet(name)) {
  3188. +         sprintf(funcbuf," %10s: %s%s","skipping",p,endline);
  3189. +         } else {
  3190.           nfiles++;
  3191.           nbytes += len;
  3192. !         sprintf(funcbuf," %10s: %s%s","deleted",p,endline);
  3193. !         }
  3194.           } else
  3195. !       sprintf(funcbuf," directory: %s%s", p, endline);
  3196.           funcnxt = 0;
  3197.           funclen = strlen(funcbuf);
  3198.       } else 
  3199. ***************
  3200. *** 2968,2978 ****
  3201.   
  3202.         if (nxpnd == 0) {
  3203.         sprintf(funcbuf,
  3204. !           "\15\12%ld file%s deleted, %ld byte%s freed\15\12",
  3205.             nfiles,
  3206.             (nfiles == 1) ? "" : "s",
  3207.             nbytes,
  3208. !           (nbytes == 1) ? "" : "s"
  3209.             );
  3210.         nxpnd--;
  3211.         funcnxt = 0;
  3212. --- 2991,3003 ----
  3213.   
  3214.         if (nxpnd == 0) {
  3215.         sprintf(funcbuf,
  3216. !           "%s%ld file%s deleted, %ld byte%s freed%s",
  3217. !           endline,
  3218.             nfiles,
  3219.             (nfiles == 1) ? "" : "s",
  3220.             nbytes,
  3221. !           (nbytes == 1) ? "" : "s",
  3222. !           endline
  3223.             );
  3224.         nxpnd--;
  3225.         funcnxt = 0;
  3226. ***************
  3227. *** 3018,3024 ****
  3228.   #endif /* OS2 */
  3229.   
  3230.       nfiles = nbytes = 0L;
  3231. !     sprintf(funcbuf,"Deleting \"%s\"\15\12",name);
  3232.       funcnxt = 0;
  3233.       funclen = strlen(funcbuf);
  3234.   
  3235. --- 3043,3049 ----
  3236.   #endif /* OS2 */
  3237.   
  3238.       nfiles = nbytes = 0L;
  3239. !     sprintf(funcbuf,"Deleting \"%s\"%s",name,endline);
  3240.       funcnxt = 0;
  3241.       funclen = strlen(funcbuf);
  3242.   
  3243. ***************
  3244. *** 3044,3053 ****
  3245.       static char spctext[64];
  3246.       if (drive)
  3247.         sprintf(spctext,
  3248. !           " Drive %c: %ldK free\15\12", drive, 
  3249. !           zdskspace(drive - 'A' + 1) / 1024L);
  3250.       else
  3251. !       sprintf(spctext, " Free space: %ldK\15\12", zdskspace(0) / 1024L);
  3252.       nfils = 0;                /* No files, no lists. */
  3253.       xflg = 1;                /* Flag we must send X packet. */
  3254.       strcpy(cmdstr,"free space");    /* Data for X packet. */
  3255. --- 3069,3081 ----
  3256.       static char spctext[64];
  3257.       if (drive)
  3258.         sprintf(spctext,
  3259. !           " Drive %c: %ldK free%s",
  3260. !           drive, 
  3261. !           zdskspace(drive - 'A' + 1) / 1024L,
  3262. !           endline
  3263. !           );
  3264.       else
  3265. !       sprintf(spctext, " Free space: %ldK%s", zdskspace(0) / 1024L, endline);
  3266.       nfils = 0;                /* No files, no lists. */
  3267.       xflg = 1;                /* Flag we must send X packet. */
  3268.       strcpy(cmdstr,"free space");    /* Data for X packet. */
  3269.  
  3270. ====================
  3271. X-Patch-Number: 0031
  3272. Date: Sat Apr  5 15:19:46 1997
  3273. From: Frank da Cruz <fdc@columbia.edu>
  3274. Subject: CHECK command broken
  3275.  
  3276. Patch:
  3277.  
  3278. *** /w/pub/ftp/kermit/f/ckuus3.c    Sun Nov 24 19:20:50 1996
  3279. --- ckuus3.c    Sat Apr  5 15:18:40 1997
  3280. ***************
  3281. *** 1465,1471 ****
  3282.       if ((y = cmcfm()) < 0)
  3283.         return(y);
  3284.   #ifndef NOPUSH
  3285. !     if (!xxstrcmp(atmbuf,"push",(int)strlen(atmbuf))) {
  3286.       if (msgflg)            /* If at top level... */
  3287.         printf(" push%s available\n", nopush ? " not" : "");
  3288.       else if (nopush && !backgrd)
  3289. --- 1465,1471 ----
  3290.       if ((y = cmcfm()) < 0)
  3291.         return(y);
  3292.   #ifndef NOPUSH
  3293. !     if (!xxstrcmp(line,"push",(int)strlen(line))) {
  3294.       if (msgflg)            /* If at top level... */
  3295.         printf(" push%s available\n", nopush ? " not" : "");
  3296.       else if (nopush && !backgrd)
  3297.  
  3298. ====================
  3299. X-Patch-Number: 0032
  3300. Date: Sat Apr  5 16:34:57 1997
  3301. From: Frank da Cruz <fdc@columbia.edu>
  3302. Subject: Problem with SET TRANSMIT ECHO
  3303.  
  3304. SET TRANSMIT ECHO ON didn't work when PARITY was NONE.  Patch:
  3305.  
  3306. *** /w/pub/ftp/kermit/f/ckuus4.c    Sun Nov 24 19:20:50 1996
  3307. --- ckuus4.c    Sat Apr  5 16:33:36 1997
  3308. ***************
  3309. *** 1285,1294 ****
  3310.                   *s &= 0x7f;
  3311.                   s++;
  3312.               }
  3313.               if (conoll(p) < 0) {
  3314.                   z = 0;
  3315.                   goto xmitexit;
  3316. -             }
  3317.               }
  3318.           }
  3319.           if (xmitw)        /* Give receiver time to digest. */
  3320. --- 1285,1294 ----
  3321.                   *s &= 0x7f;
  3322.                   s++;
  3323.               }
  3324. +             }
  3325.               if (conoll(p) < 0) {
  3326.               z = 0;
  3327.               goto xmitexit;
  3328.               }
  3329.           }
  3330.           if (xmitw)        /* Give receiver time to digest. */
  3331.  
  3332. ====================
  3333. X-Patch-Number: 0033
  3334. Date: Sun Apr  6 14:24:24 1997
  3335. From: Frank da Cruz <fdc@columbia.edu>
  3336. Subject: HELP SET SERVER says too much
  3337.  
  3338. SET SERVER IDLE-TIMEOUT is only available in Kermit 95.  Patch:
  3339.  
  3340. *** /w/pub/ftp/kermit/f/ckuus2.c    Wed Nov 27 19:54:46 1996
  3341. --- ckuus2.c    Sun Apr  6 14:23:03 1997
  3342. ***************
  3343. *** 1127,1134 ****
  3344. --- 1127,1136 ----
  3345.   "Tells the C-Kermit server where to search for files whose names it receives",
  3346.   "from client GET commands when the names are not fully specified pathnames.",
  3347.   "Default is no GET-PATH, so C-Kermit looks only in its current directory.\n",
  3348. + #ifdef OS2
  3349.   "SET SERVER IDLE-TIMEOUT seconds",
  3350.   "Idle time limit while in server mode, 0 for no limit.\n",
  3351. + #endif /* OS2 */
  3352.   "SET SERVER LOGIN [ username [ password [ account ] ] ]",
  3353.   "Sets up a username and optional password which must be supplied before",
  3354.   "the server will respond to any commands other than REMOTE LOGIN.  The",
  3355.  
  3356. ====================
  3357. X-Patch-Number: 0034
  3358. Date: Thu May 29 11:50:52 1997
  3359. From: Frank da Cruz <fdc@columbia.edu>
  3360. Subject: READ and !READ too picky about line terminators
  3361.  
  3362. The READ and !READ commands do not return the last or only line of the input
  3363. file (or command) if it does not end with a proper line terminator.  Patch:
  3364.  
  3365. *** /w/pub/ftp/kermit/f/ckuus6.c    Sun Nov 24 19:20:51 1996
  3366. --- ./ckuus6.c    Thu May 29 11:49:41 1997
  3367. ***************
  3368. *** 358,364 ****
  3369.         {
  3370.           y = zsinl(ZRFILE, s, readblock); /* Read a line. */
  3371.           debug(F111,"read zsinl",s,y);
  3372. !         if (y < 0) {        /* On EOF or other error, */
  3373.           zclose(ZRFILE);        /* close the file, */
  3374.           delmac(vnp);        /* delete the variable, */
  3375.           return(success = 0);    /* and return failure. */
  3376. --- 358,364 ----
  3377.         {
  3378.           y = zsinl(ZRFILE, s, readblock); /* Read a line. */
  3379.           debug(F111,"read zsinl",s,y);
  3380. !         if (y < 0 && !*s) {        /* On EOF or other error, */
  3381.           zclose(ZRFILE);        /* close the file, */
  3382.           delmac(vnp);        /* delete the variable, */
  3383.           return(success = 0);    /* and return failure. */
  3384.  
  3385. ====================
  3386. X-Patch-Number: 0035
  3387. Date: Thu Jul  3 13:35:08 1997
  3388. From: Frank da Cruz <fdc@columbia.edu>
  3389. Subject: END from inside SWITCH doesn't work
  3390.  
  3391. Instead of terminating the current macro or command file, the END command,
  3392. when given in a SWITCH statement, just exits from the SWITCH statement.
  3393. Patch:
  3394.  
  3395. *** /w/pub/ftp/kermit/f/ckuusr.c    Tue Feb 18 09:31:40 1997
  3396. --- ./ckuusr.c    Thu Jul  3 13:34:10 1997
  3397. ***************
  3398. *** 3372,3378 ****
  3399.              (cmdstk[cmdlvl].src == CMD_MD) &&
  3400.                (!strncmp(m_arg[maclvl-1][0],"_xif",4) ||
  3401.                 !strncmp(m_arg[maclvl-1][0],"_for",4) ||
  3402. !               !strncmp(m_arg[maclvl-1][0],"_whi",4))) {
  3403.           debug(F110,"END popping",m_arg[maclvl-1][0],0);
  3404.           dogta(XXPTA);        /* Put args back */
  3405.           popclvl();        /* Pop up two levels */
  3406. --- 3372,3379 ----
  3407.              (cmdstk[cmdlvl].src == CMD_MD) &&
  3408.                (!strncmp(m_arg[maclvl-1][0],"_xif",4) ||
  3409.                 !strncmp(m_arg[maclvl-1][0],"_for",4) ||
  3410. !               !strncmp(m_arg[maclvl-1][0],"_whi",4) ||
  3411. !               !strncmp(m_arg[maclvl-1][0],"_swi",4))) {
  3412.           debug(F110,"END popping",m_arg[maclvl-1][0],0);
  3413.           dogta(XXPTA);        /* Put args back */
  3414.           popclvl();        /* Pop up two levels */
  3415.  
  3416. ====================
  3417. X-Patch-Number: 0036
  3418. Date: Sat Sep 20 10:50:49 1997
  3419. From: Frank da Cruz <fdc@columbia.edu>
  3420. Subject: Problem telnetting to multihomed hosts
  3421.  
  3422. Problems can occur telnetting to multihomed hosts by IP number.
  3423. If the address given is an IP address (rather than a hostname),
  3424. the gethostbyname call should be skipped.  This was already done
  3425. for Windows, but it should be done everywhere.  Cure: apply this patch:
  3426.  
  3427. *** /w/pub/ftp/kermit/f/ckcnet.c    Wed Nov 27 19:54:46 1996
  3428. --- ./ckcnet.c    Sat Sep 20 11:38:57 1997
  3429. ***************
  3430. *** 1940,1958 ****
  3431.   
  3432.       bzero((char *)&saddr, sizeof(saddr));
  3433.       debug(F100,"netopen bzero ok","",0);
  3434.       if (
  3435. ! #ifdef NT
  3436. !         /* we found that Win95 tries to call the DNS  */
  3437. !         /* when a numeric IP Address is specified.    */
  3438. !         /* and of course the lookup fails resulting   */
  3439. !         /* in a long delay.  So we test for the IP    */
  3440. !         /* numeric value before calling gethostbyname */
  3441. !         /* but only in Win32 so as not to             */
  3442. !         /* alter current code that works properly     */
  3443. !         /* everywhere else.                           */
  3444. !         inet_addr(namecopy) == INADDR_NONE &&
  3445. ! #endif /* NT */
  3446. !         (host = gethostbyname(namecopy)) != NULL) {
  3447.       debug(F100,"netopen gethostbyname != NULL","",0);
  3448.   #ifdef OS2
  3449.       strncpy(name,host->h_name,80);
  3450. --- 1940,1961 ----
  3451.   
  3452.       bzero((char *)&saddr, sizeof(saddr));
  3453.       debug(F100,"netopen bzero ok","",0);
  3454. + /*
  3455. +   NOTE: Originally the inet_addr() check was #ifdef NT, but is enabled for
  3456. +   all as of 20 Sep 97, to allow people to "set host" to a specific numeric IP
  3457. +   address without going through the multihomed host sequence and winding up
  3458. +   at a different place than the one requested.
  3459. + */
  3460. +     x = inet_addr(namecopy);
  3461. +     debug(F111,"netopen inet_addr",namecopy,x);
  3462.       if (
  3463. ! #ifdef INADDR_NONE
  3464. !     x == INADDR_NONE
  3465. ! #else
  3466. !     x < 0
  3467. ! #endif /* INADDR_NONE */
  3468. !     && (host = gethostbyname(namecopy)) != NULL) {
  3469.       debug(F100,"netopen gethostbyname != NULL","",0);
  3470.   #ifdef OS2
  3471.       strncpy(name,host->h_name,80);
  3472.  
  3473. ====================
  3474. X-Patch-Number: 0037
  3475. Date: Tue Mar 10 16:50:51 1998
  3476. From: Frank da Cruz <fdc@columbia.edu>
  3477. Subject: Redirection failures in REMOTE xxx > file 
  3478.  
  3479. If the server replies to a REMOTE command with a short-form reply (i.e.
  3480. in the data field of an ACK), any redirection specified in the REMOTE command
  3481. fails to take place, but the file is left open.  Fix:
  3482.  
  3483. *** /w/pub/ftp/kermit/f/ckcpro.w    Sun Nov 10 18:37:30 1996
  3484. --- ./ckcpro.w    Tue Mar 10 14:55:14 1998
  3485. ***************
  3486. *** 1018,1033 ****
  3487.       querybuf[0] = NUL;
  3488.       }
  3489.   #endif /* NOSPL */
  3490. !     decode(rdatap,puttrm,0);        /* Text is in ACK Data field */
  3491.       if (rdatap)                /* If we had data */
  3492. !       if (*rdatap)
  3493. !      conoll("");            /* Then add a CRLF */
  3494.       if (bye_active && network) {    /* I sent a BYE command and got */
  3495.       msleep(500);            /* the ACK... */
  3496.       tthang();
  3497.       }
  3498.       success = 1;
  3499.       RESUME;
  3500.   #endif /* NOSERVER */
  3501.   }
  3502.   
  3503. --- 1018,1074 ----
  3504.       querybuf[0] = NUL;
  3505.       }
  3506.   #endif /* NOSPL */
  3507. !     rf_err = "Can't open file";
  3508. !     x = 1;
  3509. !     if (remfile) {            /* Response redirected to file */
  3510. !     if (rempipe)            /* or pipe */
  3511. !       x = zxcmd(ZOFILE,remdest);    /* Pipe: Start command */
  3512. !     else
  3513. !       x = opena(remdest,&iattr);    /* File: Open with attributes */
  3514. !     } else {    
  3515. !     x = opent(&iattr);        /* "open" the screen */
  3516. !     }
  3517. !     if (x) {                /* If file was opened ok */
  3518. !     if (decode(rdatap, 
  3519. ! #ifndef NOSPL
  3520. !            (query || !remfile) ? puttrm : 
  3521. ! #else
  3522. !            !remfile ? puttrm : 
  3523. ! #endif /* NOSPL */
  3524. !            putfil, 1) < 0) {
  3525. !         errpkt((CHAR *)"Error writing data");
  3526. !         RESUME;
  3527. !     } else {
  3528.           if (rdatap)            /* If we had data */
  3529. !           if (*rdatap)        /* add a line terminator */
  3530. !         if (remfile) {        /* Can't use zsout("") for this... */
  3531. !             extern char * zoutptr;
  3532. !             extern int zoutcnt;
  3533. ! #ifndef UNIX
  3534. ! #ifndef datageneral
  3535. !             zmchout('\015');    /* Carriage return */
  3536. ! #endif /* datageneral */
  3537. ! #endif /* UNIX */
  3538. ! #ifndef MAC
  3539. ! #ifndef OSK
  3540. !             zmchout('\012');    /* Linefeed */
  3541. ! #endif /* OSK */
  3542. ! #endif /* MAC */
  3543. !         } else {        /* To screen, easy. */
  3544. !             conoll("");
  3545. !         }
  3546.           if (bye_active && network) { /* I sent a BYE command and got */
  3547.           msleep(500);        /* the ACK... */
  3548.           tthang();
  3549.           }
  3550. +         clsof(0);
  3551.           success = 1;
  3552.           RESUME;
  3553. +     }
  3554. +     } else {                /* otherwise */
  3555. +     errpkt((CHAR *) rf_err);    /* send error message */
  3556. +     RESUME;                /* and quit. */
  3557. +     }
  3558.   #endif /* NOSERVER */
  3559.   }
  3560.   
  3561. ====================
  3562. __________________________________
  3563. (End of C-Kermit 6.0 PATCHES file)
  3564.