fixed "Loggin" spelling error
authorIan Beckwith <ianb@erislabs.net>
Wed, 12 May 2010 00:34:35 +0000 (01:34 +0100)
committerIan Beckwith <ianb@erislabs.net>
Wed, 12 May 2010 00:34:35 +0000 (01:34 +0100)
.pc/060_speeling.patch/ckcpro.w [new file with mode: 0644]
ckcpro.w
debian/patches/060_speeling.patch

diff --git a/.pc/060_speeling.patch/ckcpro.w b/.pc/060_speeling.patch/ckcpro.w
new file mode 100644 (file)
index 0000000..cd9d1fa
--- /dev/null
@@ -0,0 +1,3591 @@
+char *protv =                                                     /* -*-C-*- */
+"C-Kermit Protocol Module 8.0.158, 11 Sep 2002";
+
+int kactive = 0;                       /* Kermit protocol is active */
+
+#define PKTZEROHACK
+
+/* C K C P R O  -- C-Kermit Protocol Module, in Wart preprocessor notation. */
+/*
+  Author: Frank da Cruz <fdc@columbia.edu>,
+  Columbia University Academic Information Systems, New York City.
+
+  Copyright (C) 1985, 2004,
+    Trustees of Columbia University in the City of New York.
+    All rights reserved.  See the C-Kermit COPYING.TXT file or the
+    copyright text in the ckcmai.c module for disclaimer and permissions.
+*/
+#ifndef NOXFER
+#include "ckcsym.h"
+#include "ckcdeb.h"
+#include "ckcasc.h"
+#include "ckcker.h"
+#ifdef OS2
+#ifndef NT
+#define INCL_NOPM
+#define INCL_VIO                       /* Needed for ckocon.h */
+#include <os2.h>
+#undef COMMENT
+#endif /* NT */
+#include "ckocon.h"
+#endif /* OS2 */
+
+/*
+ Note -- This file may also be preprocessed by the UNIX Lex program, but
+ you must indent the above #include statements before using Lex, and then
+ restore them to the left margin in the resulting C program before compilation.
+ Also, the invocation of the "wart()" function below must be replaced by an
+ invocation  of the "yylex()" function.  It might also be necessary to remove
+ comments in the (%)(%)...(%)(%) section.
+*/
+
+/* State definitions for Wart (or Lex) */
+%states ipkt rfile rattr rdpkt ssinit ssfile ssattr ssdata sseof sseot
+%states serve generic get rgen ssopkt ropkt
+
+_PROTOTYP(static VOID xxproto,(void));
+_PROTOTYP(static VOID wheremsg,(void));
+_PROTOTYP(int wart,(void));
+_PROTOTYP(static int sgetinit,(int,int));
+_PROTOTYP(int sndspace,(int));
+
+/* External C-Kermit variable declarations */
+  extern char *versio, *srvtxt, *cmarg, *cmarg2, **cmlist, *rf_err;
+  extern char * rfspec, * sfspec, * srfspec, * rrfspec;
+  extern char * prfspec, * psfspec, * psrfspec, * prrfspec;
+  extern char *cdmsgfile[];
+  extern char * snd_move, * snd_rename, * srimsg;
+  extern char filnam[], ofilnam[], fspec[], ttname[], ofn1[];
+  extern CHAR sstate, *srvptr, *data;
+  extern int timint, rtimo, nfils, hcflg, xflg, flow, mdmtyp, network;
+  extern int oopts, omode, oname, opath, nopush, isguest, xcmdsrc, rcdactive;
+  extern int rejection, moving, fncact, bye_active, urserver, fatalio;
+  extern int protocol, prefixing, filcnt, carrier, fnspath, interrupted;
+  extern int recursive, inserver, nzxopts, idletmo, srvidl, xfrint;
+  extern struct ck_p ptab[];
+  extern int remfile, rempipe, xferstat, filestatus, wearealike, fackpath;
+  extern int patterns, filepeek, gnferror;
+  extern char * remdest;
+
+#ifdef PKTZEROHACK
+#define PKTZEROLEN 32
+static char ipktack[PKTZEROLEN];
+static int ipktlen = 0;
+#endif /* PKTZEROHACK */
+
+static int s_timint = -1;              /* For saving timeout value */
+static int myjob = 0;
+static int havefs = 0;
+#ifdef CK_LOGIN
+static int logtries = 0;
+#endif /* CK_LOGIN */
+
+static int cancel = 0;
+int fackbug = 0;
+
+#ifdef STREAMING
+extern int streaming, streamok;
+
+static VOID
+streamon() {
+    if (streamok) {
+       debug(F100,"streamon","",0);
+       streaming = 1;
+       timint = 0;                     /* No timeouts while streaming. */
+    }
+}
+
+#ifdef COMMENT                         /* (not used) */
+static VOID
+streamoff() {
+    if (streaming) {
+       debug(F100,"streamoff","",0);
+       streaming = 0;
+       timint = s_timint;              /* Restore timeout */
+    }
+}
+#endif /* COMMENT */
+#else /* STREAMING */
+#define streamon()
+#define streamoff()
+#endif /* STREAMING */
+
+#ifndef NOSPL
+_PROTOTYP( int addmac, (char *, char *) );
+_PROTOTYP( int zzstring, (char *, char **, int *) );
+#endif /* NOSPL */
+#ifndef NOICP
+_PROTOTYP( int cmdsrc, (void) );
+#endif /* NOICP */
+
+#ifndef NOSERVER
+  extern char * x_user, * x_passwd, * x_acct;
+  extern int x_login, x_logged;
+#endif /* NOSERVER */
+
+#include "ckcnet.h"
+
+#ifdef TNCODE
+  extern int ttnproto;                 /* Network protocol */
+#endif /* TNCODE */
+
+#ifdef CK_SPEED
+  extern short ctlp[];                 /* Control-character prefix table */
+#endif /* CK_SPEED */
+
+#ifdef TNCODE
+  extern int tn_b_nlm, tn_b_xfer, tn_nlm;
+#ifdef CK_ENCRYPTION
+  extern int tn_no_encrypt_xfer;
+#endif /* CK_ENCRYPTION */
+#endif /* TNCODE */
+
+#ifdef TCPSOCKET
+#ifndef NOLISTEN
+  extern int tcpsrfd;
+#endif /* NOLISTEN */
+#endif /* TCPSOCKET */
+
+  extern int cxseen, czseen, server, srvdis, local, displa, bctu, bctr, bctl;
+  extern int quiet, tsecs, parity, backgrd, nakstate, atcapu, wslotn, winlo;
+  extern int wslots, success, xitsta, rprintf, discard, cdtimo, keep, fdispla;
+  extern int timef, stdinf, rscapu, sendmode, epktflg, epktrcvd, epktsent;
+  extern int binary, fncnv;
+  extern long speed, ffc, crc16, calibrate, dest;
+#ifdef COMMENT
+  extern char *TYPCMD, *DIRCMD, *DIRCM2;
+#endif /* COMMENT */
+#ifndef OS2
+  extern char *SPACMD, *SPACM2, *WHOCMD;
+#endif /* OS2 */
+  extern CHAR *rdatap;
+  extern struct zattr iattr;
+
+#ifdef VMS
+  extern int batch;
+#endif /* VMS */
+
+#ifdef GFTIMER
+  extern CKFLOAT fptsecs;
+#endif /* GFTIMER */
+
+  extern CHAR *srvcmd;
+  extern CHAR *epktmsg;
+
+#ifdef CK_TMPDIR
+extern int f_tmpdir;                   /* Directory changed temporarily */
+extern char savdir[];                  /* For saving current directory */
+extern char * dldir;
+#endif /* CK_TMPDIR */
+
+  extern int query;                    /* Query-active flag */
+#ifndef NOSPL
+  extern int cmdlvl;
+  char querybuf[QBUFL+1] = { NUL, NUL }; /* QUERY response buffer */
+  char *qbufp = querybuf;              /* Pointer to it */
+  int qbufn = 0;                       /* Length of data in it */
+#else
+  extern int tlevel;
+#endif /* NOSPL */
+
+#ifndef NOICP
+  extern int escape;
+#endif /* NOICP */
+/*
+  If the following flag is nonzero when the protocol module is entered,
+  then server mode persists for exactly one transaction, rather than
+  looping until BYE or FINISH is received.
+*/
+extern int justone;
+
+static int r_save = -1;
+static int p_save = -1;
+
+/* Function to let remote-mode user know where their file(s) went */
+
+int whereflg = 1;                      /* Unset with SET XFER REPORT */
+
+static VOID
+wheremsg() {
+    extern int quiet, filrej;
+    int n;
+    n = filcnt - filrej;
+    debug(F101,"wheremsg n","",n);
+
+    debug(F110,"wheremsg prfspec",prfspec,0);
+    debug(F110,"wheremsg rfspec",rfspec,0);
+    debug(F110,"wheremsg psfspec",psfspec,0);
+    debug(F110,"wheremsg sfspec",sfspec,0);
+
+    debug(F110,"wheremsg prrfspec",prrfspec,0);
+    debug(F110,"wheremsg rrfspec",rrfspec,0);
+    debug(F110,"wheremsg psrfspec",psrfspec,0);
+    debug(F110,"wheremsg srfspec",srfspec,0);
+
+    if (!quiet && !local) {
+       if (n == 1) {
+           switch (myjob) {
+             case 's':
+               if (sfspec) {
+                   printf(" SENT: [%s]",sfspec);
+                   if (srfspec)
+                     printf(" To: [%s]",srfspec);
+                   printf(" (%s)\n", success ? "OK" : "FAILED");
+               }
+               break;
+             case 'r':
+             case 'v':
+               if (rrfspec) {
+                   printf(" RCVD: [%s]",rrfspec);
+                   if (rfspec)
+                     printf(" To: [%s]",rfspec);
+                   printf(" (%s)\n", success ? "OK" : "FAILED");
+               }
+           }
+       } else if (n > 1) {
+           switch (myjob) {
+             case 's':
+               if (sfspec) {
+                   printf(" SENT: (%d files)",n);
+                   if (srfspec)
+                     printf(" Last: [%s]",srfspec);
+                   printf(" (%s)\n", success ? "OK" : "FAILED");
+               }
+               break;
+             case 'r':
+             case 'v':
+               if (rrfspec) {
+                   printf(" RCVD: (%d files)",n);
+                   if (rfspec)
+                     printf(" Last: [%s]",rfspec);
+                   printf(" (%s)\n", success ? "OK" : "FAILED");
+               }
+           }
+       } else if (n == 0) {
+           if (myjob == 's')
+             printf(" SENT: (0 files)          \n");
+           else if (myjob == 'r' || myjob == 'v')
+             printf(" RCVD: (0 files)          \n");
+       }
+    }
+}
+
+static VOID
+rdebug() {
+    if (server)
+      debug(F111,"RESUME","server=1",justone);
+    else
+      debug(F111,"RESUME","server=0",justone);
+}
+
+/* Flags for the ENABLE and DISABLE commands */
+extern int
+  en_cpy, en_cwd, en_del, en_dir, en_fin, en_get, en_bye, en_mai, en_pri,
+  en_hos, en_ren, en_sen, en_spa, en_set, en_typ, en_who, en_ret, en_xit,
+  en_mkd, en_rmd;
+#ifndef NOSPL
+extern int en_asg, en_que;
+#endif /* NOSPL */
+extern int what, lastxfer;
+
+/* Global variables declared here */
+
+  int whatru = 0;                      /* What are you. */
+  int whatru2 = 0;                     /* What are you, cont'd. */
+
+/* Local variables */
+
+  static char vstate = 0;              /* Saved State   */
+  static char vcmd = 0;                /* Saved Command */
+  static int reget = 0;                        /* Flag for executing REGET */
+  static int retrieve = 0;             /* Flag for executing RETRIEVE */
+  static int opkt = 0;                 /* Send Extended GET packet */
+
+  static int x;                                /* General-purpose integer */
+  static char *s;                      /* General-purpose string pointer */
+
+/* Macros - Note, BEGIN is predefined by Wart (and Lex) as "state = ", */
+/* BEGIN is NOT a GOTO! */
+#define TINIT if (tinit(1) < 0) return(-9)
+#define SERVE { TINIT; resetc(); nakstate=1; what=W_NOTHING; cmarg2=""; \
+sendmode=SM_SEND; havefs=0; recursive=r_save; fnspath=p_save; BEGIN serve; }
+#define RESUME { rdebug(); if (!server) { wheremsg(); return(0); } else \
+if (justone) { justone=0; wheremsg(); return(0); } else { SERVE; } }
+
+#ifdef GFTIMER
+#define QUIT x=quiet; quiet=1; clsif(); clsof(1); tsecs=gtimer(); \
+ fptsecs=gftimer(); quiet=x; return(success)
+#else
+#define QUIT x=quiet; quiet=1; clsif(); clsof(1); tsecs=gtimer(); quiet=x; \
+ return(success)
+#endif /* GFTIMER */
+
+/*
+  By late 1999, the big switch() statement generated from the following state
+  table began choking even gcc, so here we extract the code from the larger
+  states into static routines to reduce the size of the cases and the
+  switch() overall.  The routines follow the state table; the prototypes are
+  here.  Each of these routines simply contains the text from the
+  corresponding case, but with return(-1) added in appropriate places; see
+  instructions after the state table switcher.
+*/
+static int rc;                         /* Return code for these routines */
+static int rcv_s_pkt();                        /* Received an S packet */
+static int rcv_firstdata();            /* Received first Data packet */
+static int rcv_shortreply();           /* Short reply to a REMOTE command  */
+static int srv_query();                        /* Server answers an query */
+static int srv_copy();                 /* Server executes REMOTE COPY */
+static int srv_rename();               /* Server executes REMOTE RENAME */
+static int srv_login();                        /* Server executes REMOTE LOGIN */
+static int srv_timeout();              /* Server times out */
+
+%%
+
+/*
+  Protocol entry points, one for each start state (sstate).
+  The lowercase letters are internal "inputs" from the user interface.
+  NOTE: The start state letters that appear on the left margin immediately
+  below can NOT be used as packet types OR as G-packet subcodes.
+*/
+
+s { TINIT;                             /* Send file(s) */
+    if (sinit() > 0) BEGIN ssinit;
+       else RESUME; }
+
+v { TINIT; nakstate = 1; BEGIN get; }  /* Receive file(s) */
+
+r {                                    /* Client sends a GET command */
+    TINIT;
+    vstate = get;
+    reget = 0;
+    retrieve = 0;
+    opkt = 0;
+    vcmd = 0;
+#ifdef PKTZEROHACK
+    ipktack[0] = NUL;
+#endif /* PKTZEROHACK */
+    if (sipkt('I') >= 0)
+      BEGIN ipkt;
+    else
+      RESUME;
+}
+
+h {                                    /* Client sends a RETRIEVE command */
+    TINIT;
+    vstate = get;
+    reget = 0;
+    retrieve = 1;
+    opkt = 0;
+    vcmd = 0;
+    if (sipkt('I') >= 0)
+      BEGIN ipkt;
+    else
+      RESUME;
+}
+j {                                    /* Client sends a REGET command */
+    TINIT;
+    vstate = get;
+    reget = 1;
+    retrieve = 0;
+    opkt = 0;
+    vcmd = 0;
+    if (sipkt('I') >= 0)
+      BEGIN ipkt;
+    else
+      RESUME;
+}
+o {                                    /* Client sends Extended GET Packet */
+    TINIT;
+    vstate = get;
+    reget = oopts & GOPT_RES;
+    retrieve = oopts & GOPT_DEL;
+    opkt = 1;
+    vcmd = 0;
+    if (sipkt('I') >= 0)
+      BEGIN ipkt;
+    else
+      RESUME;
+}
+c {                                    /* Client sends a Host command */
+    TINIT;
+    vstate = rgen;
+    vcmd = 'C';
+    if (sipkt('I') >= 0)
+      BEGIN ipkt;
+    else
+      RESUME;
+}
+k { TINIT;                             /* Client sends a Kermit command */
+    vstate = rgen;
+    vcmd = 'K';
+    if (sipkt('I') >= 0)
+      BEGIN ipkt;
+    else
+      RESUME;
+}
+g {                                    /* Client sends a REMOTE command */
+    TINIT;
+    vstate = rgen;
+    vcmd = 'G';
+    if (sipkt('I') >= 0)
+      BEGIN ipkt;
+    else
+      RESUME;
+}
+x {                                    /* Enter server mode */
+    int x;
+    x = justone;
+    if (!ENABLED(en_del)) {            /* If DELETE is disabled */
+       if (fncact == XYFX_B ||         /* undo any file collision action */
+           fncact == XYFX_U ||         /* that could result in deletion or */
+           fncact == XYFX_A ||         /* modification of existing files. */
+           fncact == XYFX_X) {
+#ifndef NOICP
+           extern int g_fncact;
+           g_fncact = fncact;          /* Save current setting */
+#endif /* NOICP */
+           fncact = XYFX_R;            /* Change to RENAME */
+           debug(F101,"server DELETE disabled so fncact RENAME","",fncact);
+       }
+    }
+    SERVE;                             /* tinit() clears justone... */
+    justone = x;
+#ifdef IKSDB
+    if (ikdbopen) slotstate(what, "SERVER", "", "");
+#endif /* IKSDB */
+}
+
+a {
+    int b1 = 0, b2 = 0;
+    if (!data) TINIT;                  /* "ABEND" -- Tell other side. */
+#ifndef pdp11
+    if (epktflg) {                     /* If because of E-PACKET command */
+       b1 = bctl; b2 = bctu;           /* Save block check type */
+       bctl = bctu = 1;                /* set it to 1 */
+    }
+#endif /* pdp11 */
+    errpkt((CHAR *)"User cancelled");  /* Send the packet */
+#ifndef pdp11
+    if (epktflg) {                     /* Restore the block check */
+       epktflg = 0;
+       bctl = b1; bctu = b2;
+    }
+#endif /* pdp11 */
+    success = 0;
+    return(0);                         /* Return from protocol. */
+}
+
+/*
+  Dynamic states: <current-states>input-character { action }
+  nakstate != 0 means we're in a receiving state, in which we send ACKs & NAKs.
+*/
+
+<rgen,get,serve,ropkt>S {              /* Receive Send-Init packet. */
+    rc = rcv_s_pkt();
+    cancel = 0;                                /* Reset cancellation counter */
+    debug(F101,"rcv_s_pkt","",rc);
+    if (rc > -1) return(rc);           /* (see below) */
+}
+
+/* States in which we get replies back from commands sent to a server. */
+/* Complicated because direction of protocol changes, packet number    */
+/* stays at zero through I-G-S sequence, and complicated even more by  */
+/* sliding windows buffer allocation. */
+
+<ipkt>Y {                              /* Get ack for I-packet */
+    int x = 0;
+#ifdef PKTZEROHACK
+    ckstrncpy(ipktack,(char *)rdatap,PKTZEROLEN); /* Save a copy of the ACK */
+    ipktlen = strlen(ipktack);
+#endif /* PKTZEROHACK */
+    spar(rdatap);                      /* Set parameters */
+    cancel = 0;
+    winlo = 0;                         /* Set window-low back to zero */
+    debug(F101,"<ipkt>Y winlo","",winlo);
+    urserver = 1;                      /* So I know I'm talking to a server */
+    if (vcmd) {                                /* If sending a generic command */
+       if (tinit(0) < 0) return(-9);   /* Initialize many things */
+       x = scmd(vcmd,(CHAR *)cmarg);   /* Do that */
+       if (x >= 0) x = 0;              /* (because of O-Packet) */
+       debug(F101,"proto G packet scmd","",x);
+       vcmd = 0;                       /* and then un-remember it. */
+    } else if (vstate == get) {
+       debug(F101,"REGET sstate","",sstate);
+       x = srinit(reget, retrieve, opkt); /* GET or REGET, etc */
+    }
+    if (x < 0) {                       /* If command was too long */
+       if (!srimsg)
+         srimsg = "Error sending string";
+       errpkt((CHAR *)srimsg);         /* cancel both sides. */
+       success = 0;
+       RESUME;
+    } else if (x > 0) {                        /* Need to send more O-Packets */
+       BEGIN ssopkt;
+    } else {
+       rtimer();                       /* Reset the elapsed seconds timer. */
+#ifdef GFTIMER
+       rftimer();
+#endif /* GFTIMER */
+       winlo = 0;                      /* Window back to 0, again. */
+       debug(F101,"<ipkt>Y vstate","",vstate);
+       nakstate = 1;                   /* Can send NAKs from here. */
+       BEGIN vstate;                   /* Switch to desired state */
+    }
+}
+
+<ssopkt>Y {                            /* Got ACK to O-Packet */
+    debug(F100,"CPCPRO <ssopkt>Y","",0);
+    x = sopkt();
+    debug(F101,"CPCPRO <ssopkt>Y x","",x);
+    if (x < 0) {                       /* If error */
+       errpkt((CHAR *)srimsg);         /* cancel both sides. */
+       success = 0;
+       RESUME;
+    } else if (x == 0) {               /* This was the last O-Packet */
+       rtimer();                       /* Reset the elapsed seconds timer. */
+#ifdef GFTIMER
+       rftimer();
+#endif /* GFTIMER */
+       winlo = 0;                      /* Window back to 0, again. */
+       debug(F101,"<ssopkt>Y winlo","",winlo);
+       nakstate = 1;                   /* Can send NAKs from here. */
+       BEGIN vstate;                   /* Switch to desired state */
+    }
+    debug(F101,"CPCPRO <ssopkt>Y not changing state","",x);
+}
+
+<ipkt>E {                              /* Ignore Error reply to I packet */
+    int x = 0;
+    winlo = 0;                         /* Set window-low back to zero */
+    debug(F101,"<ipkt>E winlo","",winlo);
+    if (vcmd) {                                /* In case other Kermit doesn't */
+       if (tinit(0) < 0) return(-9);
+       x = scmd(vcmd,(CHAR *)cmarg);   /* understand I-packets. */
+       if (x >= 0) x = 0;              /* (because of O-Packet) */
+       vcmd = 0;                       /* Otherwise act as above... */
+    } else if (vstate == get) x = srinit(reget, retrieve, opkt);
+    if (x < 0) {                       /* If command was too long */
+       errpkt((CHAR *)srimsg);         /* cancel both sides. */
+       success = 0;
+       RESUME;
+    } else if (x > 0) {                        /* Need to send more O-Packets */
+       BEGIN ssopkt;
+    } else {
+       freerpkt(winlo);                /* Discard the Error packet. */
+       debug(F101,"<ipkt>E winlo","",winlo);
+       winlo = 0;                      /* Back to packet 0 again. */
+       nakstate = 1;                   /* Can send NAKs from here. */
+       BEGIN vstate;
+    }
+}
+
+<get>Y {               /* Resend of previous I-pkt ACK, same seq number */
+    freerpkt(0);                       /* Free the ACK's receive buffer */
+    resend(0);                         /* Send the GET packet again. */
+}
+
+/* States in which we're being a server */
+
+<serve,get>I {                         /* Get I-packet */
+#ifndef NOSERVER
+    spar(rdatap);                      /* Set parameters from it */
+    ack1(rpar());                      /* Respond with our own parameters */
+#ifdef COMMENT
+    pktinit();                         /* Reinitialize packet numbers */
+#else
+#ifdef COMMENT
+    /* This can't be right - it undoes the stuff we just negotiated */
+    x = justone;
+    tinit(1);                          /* Reinitialize EVERYTHING */
+    justone = x;                       /* But this... */
+#else
+    tinit(0);                          /* Initialize most things */
+#endif /* COMMENT */
+#endif /* COMMENT */
+#endif /* NOSERVER */
+    cancel = 0;                                /* Reset cancellation counter */
+}
+
+<serve>R {                             /* GET */
+#ifndef NOSERVER
+    if (x_login && !x_logged) {
+       errpkt((CHAR *)"Login required");
+       SERVE;
+    } else if (sgetinit(0,0) < 0) {
+       RESUME;
+    } else {
+#ifdef CKSYSLOG
+       if (ckxsyslog >= SYSLG_PR && ckxlogging)
+         cksyslog(SYSLG_PR, 1, "server", "GET", (char *)srvcmd);
+#endif /* CKSYSLOG */
+       BEGIN ssinit;
+    }
+#endif /* NOSERVER */
+}
+
+<serve>H {                             /* GET /DELETE (RETRIEVE) */
+#ifndef NOSERVER
+    if (x_login && !x_logged) {
+       errpkt((CHAR *)"Login required");
+       RESUME;
+    } else if (!ENABLED(en_del)) {
+       errpkt((CHAR *)"Deleting files is disabled");
+       RESUME;
+    } else if (sgetinit(0,0) < 0) {
+       RESUME;
+    } else {
+       moving = 1;
+#ifdef CKSYSLOG
+       if (ckxsyslog >= SYSLG_PR && ckxlogging)
+         cksyslog(SYSLG_PR, 1, "server", "GET /DELETE", (char *)srvcmd);
+#endif /* CKSYSLOG */
+       BEGIN ssinit;
+    }
+#endif /* NOSERVER */
+}
+
+<serve>V {                             /* GET /RECURSIVE */
+#ifndef NOSERVER
+    recursive = 1;                     /* Set these before sgetinit() */
+    if (fnspath == PATH_OFF)
+      fnspath = PATH_REL;              /* Don't worry, they will be */
+    if (x_login && !x_logged) {                /* reset next time through. */
+       errpkt((CHAR *)"Login required");
+       RESUME;
+    } else if (sgetinit(0,0) < 0) {
+       RESUME;
+    } else {
+#ifdef CKSYSLOG
+       if (ckxsyslog >= SYSLG_PR && ckxlogging)
+         cksyslog(SYSLG_PR, 1, "server", "GET /RECURSIVE", (char *)srvcmd);
+#endif /* CKSYSLOG */
+       BEGIN ssinit;
+    }
+#endif /* NOSERVER */
+}
+
+<serve>W {                             /* GET /RECURSIVE /DELETE */
+#ifndef NOSERVER
+    recursive = 1;                     /* Set these before sgetinit() */
+    if (fnspath == PATH_OFF)
+      fnspath = PATH_REL;              /* Don't worry, they will be */
+    moving = 1;                                /* reset next time through. */
+    if (x_login && !x_logged) {
+       errpkt((CHAR *)"Login required");
+       RESUME;
+    } else if (!ENABLED(en_del)) {
+       errpkt((CHAR *)"Deleting files is disabled");
+       RESUME;
+    } else if (sgetinit(0,0) < 0) {
+       RESUME;
+    } else {
+#ifdef CKSYSLOG
+       if (ckxsyslog >= SYSLG_PR && ckxlogging)
+         cksyslog(SYSLG_PR,1,"server",
+                  "GET /RECURSIVE /DELETE",(char *)srvcmd);
+#endif /* CKSYSLOG */
+       BEGIN ssinit;
+    }
+#endif /* NOSERVER */
+}
+
+<serve>J {                             /* GET /RECOVER (REGET) */
+#ifndef NOSERVER
+    if (x_login && !x_logged) {
+       errpkt((CHAR *)"Login required");
+       SERVE;
+    } else if (sgetinit(1,0) < 0) {
+       RESUME;
+    } else {
+#ifdef CKSYSLOG
+       if (ckxsyslog >= SYSLG_PR && ckxlogging)
+         cksyslog(SYSLG_PR, 1, "server", "GET /RECOVER", (char *)srvcmd);
+#endif /* CKSYSLOG */
+       BEGIN ssinit;
+    }
+#endif /* NOSERVER */
+}
+
+<serve>O {                             /* Extended GET */
+#ifndef NOSERVER
+    if (x_login && !x_logged) {                /* (any combination of options) */
+       errpkt((CHAR *)"Login required");
+       SERVE;
+    } else if ((x = sgetinit(0,1)) < 0) {
+       debug(F101,"CKCPRO <serve>O sgetinit fail","",x);
+       RESUME;
+    } else if (x == 0) {
+       debug(F101,"CKCPRO <serve>O sgetinit done","",x);
+#ifdef CKSYSLOG
+       if (ckxsyslog >= SYSLG_PR && ckxlogging)
+         cksyslog(SYSLG_PR, 1, "server", "EXTENDED GET", (char *)srvcmd);
+#endif /* CKSYSLOG */
+       BEGIN ssinit;
+    } else {                           /* Otherwise stay in this state */
+       debug(F101,"CKCPRO <serve>O sgetinit TBC","",x);
+       ack();
+       BEGIN ropkt;
+    }
+#endif /* NOSERVER */
+}
+
+<ropkt>O {
+#ifndef NOSERVER
+    if (x_login && !x_logged) {                /* (any combination of options) */
+       errpkt((CHAR *)"Login required");
+       SERVE;
+    } else if ((x = sgetinit(0,1)) < 0) {
+       debug(F101,"CKCPRO <ropkt>O sgetinit fail","",x);
+       RESUME;
+    } else if (x == 0) {
+       debug(F101,"CKCPRO <ropkt>O sgetinit done","",x);
+#ifdef CKSYSLOG
+       if (ckxsyslog >= SYSLG_PR && ckxlogging)
+         cksyslog(SYSLG_PR, 1, "server", "EXTENDED GET", (char *)srvcmd);
+#endif /* CKSYSLOG */
+       BEGIN ssinit;
+    } else {                           /* Otherwise stay in this state */
+       debug(F101,"CKCPRO <ropkt>O sgetinit TBC","",x);
+       ack();
+    }
+#endif /* NOSERVER */
+}
+
+<serve>G {                             /* Generic server command */
+#ifndef NOSERVER
+    srvptr = srvcmd;                   /* Point to command buffer */
+    decode(rdatap,putsrv,0);           /* Decode packet data into it */
+    putsrv(NUL);                       /* Insert a couple nulls */
+    putsrv(NUL);                       /* for termination */
+    if (srvcmd[0]) {
+       sstate = srvcmd[0];             /* Set requested start state */
+       if (x_login && !x_logged &&     /* Login required? */
+           /* Login, Logout, and Help are allowed when not logged in */
+           sstate != 'I' && sstate != 'L' && sstate != 'H') {
+           errpkt((CHAR *)"Login required");
+           SERVE;
+       } else {
+           nakstate = 0;               /* Now I'm the sender. */
+           what = W_REMO;              /* Doing a REMOTE command. */
+#ifdef STREAMING
+           if (!streaming)
+#endif /* STREAMING */
+             if (timint < 1)
+               timint = chktimo(rtimo,timef); /* Switch to per-packet timer */
+           binary = XYFT_T;            /* Switch to text mode */
+           BEGIN generic;              /* Switch to generic command state */
+       }
+    } else {
+       errpkt((CHAR *)"Badly formed server command"); /* report error */
+       RESUME;                 /* & go back to server command wait */
+    }
+#endif /* NOSERVER */
+}
+
+<serve>C {                             /* Receive Host command */
+#ifndef NOSERVER
+    if (x_login && !x_logged) {
+       errpkt((CHAR *)"Login required");
+       SERVE;
+    } else if (!ENABLED(en_hos)) {
+       errpkt((CHAR *)"REMOTE HOST disabled");
+       RESUME;
+    } else if (nopush) {
+       errpkt((CHAR *)"HOST commands not available");
+       RESUME;
+    } else {
+       srvptr = srvcmd;                /* Point to command buffer */
+       decode(rdatap,putsrv,0);        /* Decode command packet into it */
+       putsrv(NUL);                    /* Null-terminate */
+       nakstate = 0;                   /* Now sending, not receiving */
+       binary = XYFT_T;                /* Switch to text mode */
+       if (syscmd((char *)srvcmd,"")) { /* Try to execute the command */
+           what = W_REMO;              /* Doing a REMOTE command. */
+#ifdef STREAMING
+           if (!streaming)
+#endif /* STREAMING */
+             if (timint < 1)
+               timint = chktimo(rtimo,timef); /* Switch to per-packet timer */
+#ifdef CKSYSLOG
+           if (ckxsyslog >= SYSLG_PR && ckxlogging)
+             cksyslog(SYSLG_PR, 1, "server", "REMOTE HOST", (char *)srvcmd);
+#endif /* CKSYSLOG */
+           BEGIN ssinit;               /* If OK, send back its output */
+       } else {                        /* Otherwise */
+           errpkt((CHAR *)"Can't do system command"); /* report error */
+           RESUME;                     /* & go back to server command wait */
+       }
+    }
+#endif /* NOSERVER */
+}
+
+<serve>q {                             /* Interrupted or connection lost */
+    rc = srv_timeout();
+    debug(F101,"srv_timeout","",rc);
+    if (rc > -1) return(rc);           /* (see below) */
+}
+
+<serve>N {                             /* Server got a NAK in command-wait */
+#ifndef NOSERVER
+    errpkt((CHAR *)"Did you say RECEIVE instead of GET?");
+    RESUME;
+#endif /* NOSERVER */
+}
+
+<serve>. {                             /* Any other command in this state */
+#ifndef NOSERVER
+    if (c != ('E' - SP) && c != ('Y' - SP)) /* except E and Y packets. */
+      errpkt((CHAR *)"Unimplemented server function");
+    /* If we answer an E with an E, we get an infinite loop. */
+    /* A Y (ACK) can show up here if we sent back a short-form reply to */
+    /* a G packet and it was echoed.  ACKs can be safely ignored here. */
+    RESUME;                            /* Go back to server command wait. */
+#endif /* NOSERVER */
+}
+
+<generic>I {                           /* Login/Out */
+    rc = srv_login();
+    debug(F101,"<generic>I srv_login","",rc);
+    if (rc > -1) return(rc);           /* (see below) */
+}
+
+<generic>C {                           /* Got REMOTE CD command */
+#ifndef NOSERVER
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE CD", (char *)srvcmd);
+#endif /* CKSYSLOG */
+    if (!ENABLED(en_cwd)) {
+       errpkt((CHAR *)"REMOTE CD disabled");
+       RESUME;
+    } else {
+       char * p = NULL;
+       x = cwd((char *)(srvcmd+1));    /* Try to change directory */
+#ifdef IKSDB
+       if (ikdbopen) slotstate(what,"REMOTE CD", (char *)(srvcmd+2), "");
+#endif /* IKSDB */
+       if (!x) {                       /* Failed */
+           errpkt((CHAR *)"Can't change directory");
+           RESUME;                     /* Back to server command wait */
+       } else if (x == 2) {            /* User wants message */
+           if (!ENABLED(en_typ)) {     /* Messages (REMOTE TYPE) disabled? */
+               errpkt((CHAR *)"REMOTE TYPE disabled");
+               RESUME;
+           } else {                    /* TYPE is enabled */
+               int i;
+               for (i = 0; i < 8; i++) {
+                   if (zchki(cdmsgfile[i]) > -1) {
+                       break;
+                   }
+               }
+               binary = XYFT_T;        /* Use text mode for this. */
+               if (i < 8 && sndtype(cdmsgfile[i])) { /* Have readme file? */
+                   BEGIN ssinit;       /* OK */
+               } else {                /* not OK */
+                   p = zgtdir();
+                   if (!p) p = "";
+                   success = (*p) ? 1 : 0;
+                   ack1((CHAR *)p);    /* ACK with new directory name */
+                   success = 1;
+                   RESUME;             /* wait for next server command */
+               }
+           }
+       } else {                        /* User doesn't want message */
+           p =zgtdir();
+           if (!p) p = "";
+           success = (*p) ? 1 : 0;
+           ack1((CHAR *)p);
+           success = 1;
+           RESUME;                     /* Wait for next server command */
+       }
+    }
+#endif /* NOSERVER */
+}
+
+<generic>A {                           /* Got REMOTE PWD command */
+#ifndef NOSERVER
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE PWD", NULL);
+#endif /* CKSYSLOG */
+    if (!ENABLED(en_cwd)) {
+       errpkt((CHAR *)"REMOTE CD disabled");
+       RESUME;
+    } else {
+       if (encstr((CHAR *)zgtdir()) > -1) { /* Encode current directory */
+           ack1(data);                 /* If it fits, send it back in ACK */
+           success = 1;
+       } else {                        /* Failed */
+           ack();                      /* Send empty ACK */
+           success = 0;                /* and indicate failure locally */
+       }
+       RESUME;                         /* Back to server command wait */
+    }
+#endif /* NOSERVER */
+}
+
+<generic>D {                           /* REMOTE DIRECTORY command */
+#ifndef NOSERVER
+    char *n2;
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE DIRECTORY", (char *)srvcmd);
+#endif /* CKSYSLOG */
+    if (!ENABLED(en_dir)) {            /* If DIR is disabled, */
+       errpkt((CHAR *)"REMOTE DIRECTORY disabled"); /* refuse. */
+       RESUME;
+    } else {                           /* DIR is enabled. */
+#ifdef IKSDB
+       if (ikdbopen) slotstate(what,"REMOTE DIR", (char *)(srvcmd+2), "");
+#endif /* IKSDB */
+       if (!ENABLED(en_cwd)) {         /* But CWD is disabled */
+           zstrip((char *)(srvcmd+2),&n2); /* and they included a pathname, */
+           if (strcmp((char *)(srvcmd+2),n2)) { /* so refuse. */
+               errpkt((CHAR *)"Access denied");
+               RESUME;                 /* Remember, this is not a goto! */
+           }
+       }
+       if (state == generic) {                 /* It's OK to go ahead. */
+#ifdef COMMENT
+           n2 = (*(srvcmd+2)) ? DIRCMD : DIRCM2;
+           if (syscmd(n2,(char *)(srvcmd+2)))  /* If it can be done */
+#else
+           int x;
+           if ((x = snddir((char*)(srvcmd+2))) > 0)
+#endif /* COMMENT */
+           {
+               BEGIN ssinit;           /* send the results back; */
+           } else {                    /* otherwise */
+               if (x < 0)
+                 errpkt((CHAR *)"No files match");
+               else
+                 errpkt((CHAR *)"Can't list directory");
+               RESUME;                 /* return to server command wait */
+           }
+       }
+    }
+#endif /* NOSERVER */
+}
+
+<generic>E {                           /* REMOTE DELETE (Erase) */
+#ifndef NOSERVER
+    char *n2;
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE DELETE", (char *)srvcmd);
+#endif /* CKSYSLOG */
+    if (!ENABLED(en_del)) {
+       errpkt((CHAR *)"REMOTE DELETE disabled");
+       RESUME;
+    } else {                           /* DELETE is enabled */
+#ifdef IKSDB
+       if (ikdbopen) slotstate(what,"REMOTE DELETE", (char *)(srvcmd+2), "");
+#endif /* IKSDB */
+       if (!ENABLED(en_cwd)) {         /* but CWD is disabled */
+           zstrip((char *)(srvcmd+2),&n2); /* and they included a pathname, */
+           if (strcmp((char *)(srvcmd+2),n2)) { /* so refuse. */
+               errpkt((CHAR *)"Access denied");
+               RESUME;                 /* Remember, this is not a goto! */
+           }
+       } else if (isdir((char *)(srvcmd+2))) { /* A directory name? */
+           errpkt((CHAR *)"It's a directory");
+           RESUME;
+       }
+       if (state == generic) {         /* It's OK to go ahead. */
+           int x;
+           if ((x = snddel((char*)(srvcmd+2))) > 0) {
+               BEGIN ssinit;           /* If OK send results back */
+           } else {                    /* otherwise */
+               if (x < 0)
+                 errpkt((CHAR *)"File not found"); /* report failure */
+               else
+                 errpkt((CHAR *)"DELETE failed");
+               RESUME;                 /* & return to server command wait */
+           }
+       }
+    }
+#endif /* NOSERVER */
+}
+
+<generic>F {                           /* FINISH */
+#ifndef NOSERVER
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "FINISH", NULL);
+#endif /* CKSYSLOG */
+#ifdef IKSDB
+    if (ikdbopen) slotstate(what,"SERVER FINISH", "", "");
+#endif /* IKSDB */
+    if (!ENABLED(en_fin)) {
+       errpkt((CHAR *)"FINISH disabled");
+       RESUME;
+    } else {
+       ack();                          /* Acknowledge */
+       xxscreen(SCR_TC,0,0L,"");       /* Display */
+       success = 1;
+       return(0);                      /* Done */
+    }
+#endif /* NOSERVER */
+}
+
+<generic>X {                           /* EXIT */
+#ifndef NOSERVER
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE EXIT", NULL);
+#endif /* CKSYSLOG */
+#ifdef IKSDB
+    if (ikdbopen) slotstate(what,"REMOTE EXIT", "", "");
+#endif /* IKSDB */
+    if (!ENABLED(en_xit)) {
+       errpkt((CHAR *)"EXIT disabled");
+       RESUME;
+    } else {
+       ack();                          /* Acknowledge */
+       xxscreen(SCR_TC,0,0L,"");       /* Display */
+       doexit(GOOD_EXIT,xitsta);
+    }
+#endif /* NOSERVER */
+}
+
+<generic>L {                           /* BYE (Logout) */
+#ifndef NOSERVER
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "BYE", NULL);
+#endif /* CKSYSLOG */
+#ifdef IKSDB
+    if (ikdbopen) slotstate(what,"SERVER BYE", "", "");
+#endif /* IKSDB */
+    if (!ENABLED(en_bye)) {
+       errpkt((CHAR *)"BYE disabled");
+       RESUME;
+    } else {
+       ack();                          /* Acknowledge */
+       success = 1;
+       msleep(750);                    /* Give the ACK time to get out */
+       if (local)
+         ttres();                      /* Reset the terminal */
+       xxscreen(SCR_TC,0,0L,"");       /* Display */
+       doclean(1);                     /* Clean up files, etc */
+#ifdef DEBUG
+       debug(F100,"C-Kermit BYE - Loggin out...","",0);
+       zclose(ZDFILE);
+#endif /* DEBUG */
+#ifdef IKSD
+#ifdef CK_LOGIN
+       if (inserver)
+         ckxlogout();
+       else
+#endif /* CK_LOGIN */
+#endif /* IKSD */
+#ifdef TCPSOCKET
+#ifndef NOLISTEN
+         if (network && tcpsrfd > 0 && !inserver)
+           doexit(GOOD_EXIT,xitsta);
+       else
+#endif /* NOLISTEN */
+#endif /* TCPSOCKET */
+         return(zkself());             /* Try to log self out */
+    }
+#endif /* NOSERVER */
+}
+
+<generic>H {                           /* REMOTE HELP */
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE HELP", NULL);
+#endif /* CKSYSLOG */
+#ifdef IKSDB
+    if (ikdbopen) slotstate(what,"REMOTE HELP", "", "");
+#endif /* IKSDB */
+#ifndef NOSERVER
+    if (sndhlp(NULL)) {
+       BEGIN ssinit;                   /* try to send it */
+    } else {                           /* If not ok, */
+       errpkt((CHAR *)"Can't send help"); /* send error message instead */
+       RESUME;                         /* and return to server command wait */
+    }
+#endif /* NOSERVER */
+}
+
+<generic>R {                            /* REMOTE RENAME */
+    rc = srv_rename();
+    debug(F101,"srv_rename","",rc);
+    if (rc > -1) return(rc);           /* (see below) */
+}
+
+<generic>K {                            /* REMOTE COPY */
+    rc = srv_copy();
+    debug(F101,"srv_copy","",rc);
+    if (rc > -1) return(rc);           /* (see below) */
+}
+
+<generic>S {                           /* REMOTE SET */
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE SET", (char *)srvcmd);
+#endif /* CKSYSLOG */
+#ifndef NOSERVER
+#ifdef IKSDB
+    if (ikdbopen) slotstate(what,"REMOTE SET", (char *)(srvcmd+1), "");
+#endif /* IKSDB */
+    if (!ENABLED(en_set)) {
+       errpkt((CHAR *)"REMOTE SET disabled");
+       RESUME;
+    } else {
+       if (remset((char *)(srvcmd+1))) { /* Try to do what they ask */
+           success = 1;
+           ack();                      /* If OK, then acknowledge */
+       } else                          /* Otherwise */
+         errpkt((CHAR *)"Unknown REMOTE SET parameter"); /* give error msg */
+       RESUME;                         /* Return to server command wait */
+    }
+#endif /* NOSERVER */
+}
+
+<generic>T {                           /* REMOTE TYPE */
+#ifndef NOSERVER
+    char *n2;
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE TYPE", (char *)srvcmd);
+#endif /* CKSYSLOG */
+    if (!ENABLED(en_typ)) {
+       errpkt((CHAR *)"REMOTE TYPE disabled");
+       RESUME;
+    } else {
+#ifdef IKSDB
+       if (ikdbopen) slotstate(what,"REMOTE TYPE", (char *)(srvcmd+2), "");
+#endif /* IKSDB */
+       if (!ENABLED(en_cwd)) {         /* If CWD disabled */
+           zstrip((char *)(srvcmd+2),&n2); /* and they included a pathname, */
+           if (strcmp((char *)(srvcmd+2),n2)) { /* refuse. */
+               errpkt((CHAR *)"Access denied");
+               RESUME;                 /* Remember, this is not a goto! */
+           }
+       }
+       if (state == generic) {         /* It's OK to go ahead. */
+           binary = XYFT_T;            /* Use text mode for this. */
+           if (                        /* (RESUME didn't change state) */
+#ifdef COMMENT
+             syscmd(TYPCMD,(char *)(srvcmd+2)) /* Old way */
+#else
+             sndtype((char *)(srvcmd+2)) /* New way */
+#endif /* COMMENT */
+               )
+             BEGIN ssinit;             /* OK */
+           else {                      /* not OK */
+               errpkt((CHAR *)"Can't type file"); /* give error message */
+               RESUME;                 /* wait for next server command */
+           }
+       }
+    }
+#endif /* NOSERVER */
+}
+
+<generic>m {                           /* REMOTE MKDIR */
+#ifndef NOSERVER
+#ifdef CK_MKDIR
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE MKDIR", (char *)srvcmd);
+#endif /* CKSYSLOG */
+#ifdef IKSDB
+    if (ikdbopen) slotstate(what,"REMOTE MKDIR", (char *)(srvcmd+2), "");
+#endif /* IKSDB */
+    if (!ENABLED(en_mkd)) {
+       errpkt((CHAR *)"REMOTE MKDIR disabled");
+       RESUME;
+    } else if (!ENABLED(en_cwd)) {     /* If CWD disabled */
+       errpkt((CHAR *)"Directory access restricted");
+       RESUME;                         /* Remember, this is not a goto! */
+    }
+    if (state == generic) {            /* OK to go ahead. */
+       char *p = NULL;
+       x = ckmkdir(0,(char *)(srvcmd+2),&p,0,1); /* Make the directory */
+       if (!p) p = "";
+       if (x > -1) {
+           encstr((CHAR *)p);          /* OK - encode the name */
+           ack1(data);                 /* Send short-form response */
+           success = 1;
+           RESUME;
+       } else {                        /* not OK */
+           if (!*p) p = "Directory creation failure";
+           errpkt((CHAR *)p);          /* give error message */
+           RESUME;                     /* Wait for next server command */
+       }
+    }
+#else
+    errpkt((CHAR *)"REMOTE MKDIR not available");
+    RESUME;
+#endif /* CK_MKDIR */
+#endif /* NOSERVER */
+}
+
+<generic>d {                           /* REMOTE RMDIR */
+#ifndef NOSERVER
+#ifdef CK_MKDIR
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE RMDIR", (char *)srvcmd);
+#endif /* CKSYSLOG */
+#ifdef IKSDB
+    if (ikdbopen) slotstate(what,"REMOTE RMDIR", (char *)(srvcmd+2), "");
+#endif /* IKSDB */
+    if (!ENABLED(en_rmd)) {
+       errpkt((CHAR *)"REMOTE RMDIR disabled");
+       RESUME;
+    } else if (!ENABLED(en_cwd)) {     /* If CWD disabled */
+       errpkt((CHAR *)"Directory access restricted");
+       RESUME;                         /* Remember, this is not a goto! */
+    }
+    if (state == generic) {            /* OK to go ahead. */
+       char *p = NULL;
+       x = ckmkdir(1,(char *)(srvcmd+2),&p,0,1);
+       if (!p) p = "";
+       if (x > -1) {
+           encstr((CHAR *)p);          /* OK - encode the name */
+           ack1(data);                 /* Send short-form response */
+           success = 1;
+           RESUME;
+       } else {                        /* not OK */
+           if (!*p) p = "Directory removal failure";
+           errpkt((CHAR *)p);          /* give error message */
+           RESUME;                     /* Wait for next server command */
+       }
+    }
+#else
+    errpkt((CHAR *)"REMOTE RMDIR not available");
+    RESUME;
+#endif /* CK_MKDIR */
+#endif /* NOSERVER */
+}
+
+<generic>U {                           /* REMOTE SPACE */
+#ifndef NOSERVER
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE SPACE", (char *)srvcmd);
+#endif /* CKSYSLOG */
+    if (!ENABLED(en_spa)) {
+       errpkt((CHAR *)"REMOTE SPACE disabled");
+       RESUME;
+    } else {
+       x = srvcmd[1];                  /* Get area to check */
+       x = ((x == NUL) || (x == SP)
+#ifdef OS2
+            || (x == '!') || (srvcmd[3] == ':')
+#endif /* OS2 */
+            );
+#ifdef IKSDB
+       if (ikdbopen) slotstate(what,
+                             "REMOTE SPACE",
+                             (x ? "" : (char *)srvcmd),
+                             ""
+                             );
+#endif /* IKSDB */
+       if (!x && !ENABLED(en_cwd)) {   /* CWD disabled */
+           errpkt((CHAR *)"Access denied"); /* and non-default area given, */
+           RESUME;                     /* refuse. */
+       } else {
+#ifdef OS2
+_PROTOTYP(int sndspace,(int));
+           if (sndspace(x ? toupper(srvcmd[2]) : 0)) {
+               BEGIN ssinit;           /* send the report. */
+           } else {                    /* If not ok, */
+               errpkt((CHAR *)"Can't send space"); /* send error message */
+               RESUME;                 /* and return to server command wait */
+           }
+#else
+            if (nopush)
+              x = 0;
+            else
+              x = (x ? syscmd(SPACMD,"") : syscmd(SPACM2,(char *)(srvcmd+2)));
+           if (x) {                    /* If we got the info */
+               BEGIN ssinit;           /* send it */
+           } else {                    /* otherwise */
+               errpkt((CHAR *)"Can't check space"); /* send error message */
+               RESUME;                 /* and await next server command */
+           }
+#endif /* OS2 */
+       }
+    }
+#endif /* NOSERVER */
+}
+
+<generic>W {                           /* REMOTE WHO */
+#ifndef NOSERVER
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE WHO", (char *)srvcmd);
+#endif /* CKSYSLOG */
+#ifdef IKSDB
+    if (ikdbopen) slotstate(what,"REMOTE WHO", (char *)(srvcmd+2), "");
+#endif /* IKSDB */
+    if (!ENABLED(en_who)) {
+       errpkt((CHAR *)"REMOTE WHO disabled");
+       RESUME;
+    } else {
+#ifdef OS2
+_PROTOTYP(int sndwho,(char *));
+           if (sndwho((char *)(srvcmd+2))) {
+               BEGIN ssinit;           /* try to send it */
+           } else {                    /* If not ok, */
+               errpkt((CHAR *)"Can't do who command"); /* send error msg */
+               RESUME;                 /* and return to server command wait */
+           }
+#else
+       if (syscmd(WHOCMD,(char *)(srvcmd+2))) {
+           BEGIN ssinit;
+       } else {
+           errpkt((CHAR *)"Can't do who command");
+           RESUME;
+       }
+#endif /* OS2 */
+    }
+#endif /* NOSERVER */
+}
+
+<generic>V {                           /* Variable query or set */
+    rc = srv_query();
+    debug(F101,"srv_query","",rc);
+    if (rc > -1) return(rc);
+}
+
+<generic>q {                           /* Interrupted or connection lost */
+#ifndef NOSERVER
+    if (fatalio) {                     /* Connection lost */
+#ifdef CKSYSLOG
+       if (ckxsyslog >= SYSLG_PR && ckxlogging)
+         cksyslog(SYSLG_PR, 1, "server", "Interrupted", NULL);
+#endif /* CKSYSLOG */
+       success = 0;
+       xitsta |= (what & W_KERMIT);
+       QUIT;
+    } else if (interrupted) {
+       if (!ENABLED(en_fin)) {         /* Ctrl-C typed */
+           errpkt((CHAR *)"QUIT disabled");
+           RESUME;
+       } else {
+#ifdef CKSYSLOG
+           if (ckxsyslog >= SYSLG_PR && ckxlogging)
+             cksyslog(SYSLG_PR, 1, "server", "Interrupted", NULL);
+#endif /* CKSYSLOG */
+           success = 0;
+           xitsta |= (what & W_KERMIT);
+           QUIT;
+       }
+    } else {                           /* Shouldn't happen */
+       debug(F100,"SERVER (generic) GOT UNEXPECTED 'q'","",0);
+       QUIT;
+    }
+#endif /* NOSERVER */
+}
+
+<generic>. {                           /* Anything else in this state... */
+#ifndef NOSERVER
+    errpkt((CHAR *)"Unimplemented REMOTE command"); /* Complain */
+    RESUME;                            /* and return to server command wait */
+#endif /* NOSERVER */
+}
+
+<rgen>q {                              /* Sent BYE and connection broken */
+    if (bye_active && ttchk() < 0) {
+       msleep(500);
+       bye_active = 0;
+       ttclos(0);                      /* Close our end of the connection */
+       clsof(0);
+       return(success = 1);
+    } else {                           /* Other generic command */
+       return(success = 0);            /* or connection not broken */
+    }
+}
+
+<rgen>Y {                              /* Short-Form reply */
+    rc = rcv_shortreply();
+    debug(F101,"<rgen>Y rcv_shortreply","",rc);
+    if (rc > -1) return(rc);
+}
+
+<rgen,rfile>F {                                /* File header */
+    /* char *n2; */
+    extern int rsn;
+    debug(F101,"<rfile>F winlo 1","",winlo);
+    xflg = 0;                          /* Not screen data */
+    if (!czseen)
+      cancel = 0;                      /* Reset cancellation counter */
+#ifdef CALIBRATE
+    if (dest == DEST_N)
+      calibrate = 1;
+#endif /* CALIBRATE */
+    if (!rcvfil(filnam)) {             /* Figure out local filename */
+       errpkt((CHAR *)rf_err);         /* Trouble */
+       RESUME;
+    } else {                           /* Real file, OK to receive */
+       char * fnp;
+       debug(F111,"<rfile>F winlo 2",fspec,winlo);
+       if (filcnt == 1)                /* rcvfil set this to 1 for 1st file */
+         crc16 = 0L;                   /* Clear file CRC */
+       fnp = fspec;                    /* This is the full path */
+       if (server && !ENABLED(en_cwd) || /* if DISABLE CD */
+           !fackpath                     /* or F-ACK-PATH OFF */
+           ) {
+           zstrip(fspec,&fnp);         /* don't send back full path */
+       }
+       encstr((CHAR *)fnp);
+       if (fackbug)
+         ack();
+       else
+         ack1(data);                   /* Send it back in ACK */
+       initattr(&iattr);               /* Clear file attribute structure */
+       streamon();
+       if (window(wslotn) < 0) {       /* Allocate negotiated window slots */
+           errpkt((CHAR *)"Can't open window");
+           RESUME;
+       }
+#ifdef IKSDB
+       if (ikdbopen) slotstate(what,
+                             server ? "SERVER" : "",
+                             "RECEIVE",
+                             fspec
+                             );
+#endif /* IKSDB */
+       BEGIN rattr;                    /* Now expect Attribute packets */
+    }
+}
+
+<rgen,rfile>X {                                /* X-packet instead of file header */
+    xflg = 1;                          /* Screen data */
+    if (!czseen)
+      cancel = 0;                      /* Reset cancellation counter */
+    ack();                             /* Acknowledge the X-packet */
+    initattr(&iattr);                  /* Initialize attribute structure */
+    streamon();
+    if (window(wslotn) < 0) {          /* allocate negotiated window slots */
+       errpkt((CHAR *)"Can't open window");
+       RESUME;
+    }
+#ifndef NOSPL
+    if (query) {                       /* If this is the response to */
+       qbufp = querybuf;               /* a query that we sent, initialize */
+       qbufn = 0;                      /* the response buffer */
+       querybuf[0] = NUL;
+    }
+#endif /* NOSPL */
+    what = W_REMO;                     /* we're doing a REMOTE command */
+#ifdef IKSDB
+    if (ikdbopen) slotstate(what,
+                         server ? "SERVER" : "",
+                         "RECEIVE",
+                         fspec
+                         );
+#endif /* IKSDB */
+    BEGIN rattr;                       /* Expect Attribute packets */
+}
+
+<rattr>A {                             /* Attribute packet */
+    if (gattr(rdatap,&iattr) == 0) {   /* Read into attribute structure */
+#ifdef CK_RESEND
+       ack1((CHAR *)iattr.reply.val);  /* Reply with data */
+#else
+       ack();                          /* If OK, acknowledge */
+#endif /* CK_RESEND */
+    } else {                           /* Otherwise */
+       extern long fsize;
+       char *r;
+       r = getreason(iattr.reply.val);
+       ack1((CHAR *)iattr.reply.val);  /* refuse to accept the file */
+       xxscreen(SCR_ST,ST_REFU,0L,r);  /* reason */
+#ifdef TLOG
+       if (tralog && !tlogfmt)
+         doxlog(what,filnam,fsize,binary,1,r);
+#endif /* TLOG */
+    }
+}
+
+<rattr>D {                             /* First data packet */
+    debug(F100,"<rattr> D firstdata","",0);
+    rc = rcv_firstdata();
+    debug(F101,"rcv_firstdata rc","",rc);
+    if (rc > -1) return(rc);           /* (see below) */
+}
+
+<rfile>B {                             /* EOT, no more files */
+    ack();                             /* Acknowledge the B packet */
+    reot();                            /* Do EOT things */
+#ifdef CK_TMPDIR
+/* If we were cd'd temporarily to another device or directory ... */
+    if (f_tmpdir) {
+       int x;
+       x = zchdir((char *) savdir);    /* ... restore previous directory */
+       f_tmpdir = 0;                   /* and remember we did it. */
+       debug(F111,"ckcpro.w B tmpdir restoring",savdir,x);
+    }
+#endif /* CK_TMPDIR */
+    RESUME;                            /* and quit */
+}
+
+<rdpkt>D {                             /* Got Data packet */
+    debug(F101,"<rdpkt>D cxseen","",cxseen);
+    debug(F101,"<rdpkt>D czseen","",czseen);
+    if (cxseen || czseen || discard) { /* If file or group interruption */
+       CHAR * msg;
+       msg = czseen ? (CHAR *)"Z" : (CHAR *)"X";
+#ifdef STREAMING
+       if (streaming) {                /* Need to cancel */
+           debug(F111,"<rdpkt>D streaming cancel",msg,cancel);
+           if (cancel++ == 0) {        /* Only do this once */
+               ack1(msg);              /* Put "X" or "Z" in ACK */
+           } else if (czseen) {
+               errpkt((CHAR *)"User canceled");
+               RESUME;
+           } else {
+               fastack();
+           }
+       } else
+#endif /* STREAMING */
+         ack1(msg);
+    } else {                           /* No interruption */
+       int rc, qf;
+#ifndef NOSPL
+       qf = query;
+#else
+       qf = 0;
+#endif /* NOSPL */
+#ifdef CKTUNING
+       rc = (binary && !parity) ?
+         bdecode(rdatap,putfil):
+           decode(rdatap, qf ? puttrm : putfil, 1);
+#else
+       rc = decode(rdatap, qf ? puttrm : putfil, 1);
+#endif /* CKTUNING */
+       if (rc < 0) {
+           discard = (keep == 0 || (keep == SET_AUTO && binary != XYFT_T));
+           errpkt((CHAR *)"Error writing data"); /* If failure, */
+           RESUME;
+       } else                          /* Data written OK, send ACK */
+#ifdef STREAMING
+         if (streaming)
+           fastack();
+       else
+#endif /* STREAMING */
+         ack();
+    }
+}
+
+<rattr>Z {                             /* EOF immediately after A-Packet. */
+    rf_err = "Can't create file";
+    timint = s_timint;
+    if (discard) {                     /* Discarding a real file... */
+       x = 1;
+    } else if (xflg) {                 /* If screen data */
+       if (remfile) {                  /* redirected to file */
+           if (rempipe)                /* or pipe */
+             x = openc(ZOFILE,remdest); /* Pipe: start command */
+           else
+             x = opena(remdest,&iattr); /* File: open with attributes */
+       } else {                        /* otherwise */
+           x = opent(&iattr);          /* "open" the screen */
+       }
+#ifdef CALIBRATE
+    } else if (calibrate) {            /* If calibration run */
+       x = ckopenx(&iattr);            /* do this */
+#endif /* CALIBRATE */
+    } else {                           /* otherwise */
+       x = opena(filnam,&iattr);       /* open the file, with attributes */
+       if (x == -17) {                 /* REGET skipped because same size */
+           discard = 1;
+           rejection = 1;
+       }
+    }
+    if (!x || reof(filnam, &iattr) < 0) { /* Close output file */
+       errpkt((CHAR *) rf_err);        /* If problem, send error msg */
+       RESUME;                         /* and quit */
+    } else {                           /* otherwise */
+       if (x == -17)
+         xxscreen(SCR_ST,ST_SKIP,SKP_RES,"");
+       ack();                          /* acknowledge the EOF packet */
+       BEGIN rfile;                    /* and await another file */
+    }
+}
+
+<rdpkt>q {                             /* Ctrl-C or connection loss. */
+    timint = s_timint;
+    window(1);                         /* Set window size back to 1... */
+    cxseen = 1;
+    x = clsof(1);                      /* Close file */
+    return(success = 0);               /* Failed */
+}
+
+<rdpkt>Z {                             /* End Of File (EOF) Packet */
+/*  wslots = 1;        */                      /* (don't set) Window size back to 1 */
+#ifndef COHERENT /* Coherent compiler blows up on this switch() statement. */
+    x = reof(filnam, &iattr);          /* Handle the EOF packet */
+    switch (x) {                       /* reof() sets the success flag */
+      case -5:                         /* Handle problems */
+       errpkt((CHAR *)"RENAME failed"); /* Fatal */
+       RESUME;
+       break;
+      case -4:
+       errpkt((CHAR *)"MOVE failed");  /* Fatal */
+       RESUME;
+       break;
+      case -3:                         /* If problem, send error msg */
+       errpkt((CHAR *)"Can't print file"); /* Fatal */
+       RESUME;
+       break;
+      case -2:
+       errpkt((CHAR *)"Can't mail file"); /* Fatal */
+       RESUME;
+       break;
+      case 2:                          /* Not fatal */
+      case 3:
+       xxscreen(SCR_EM,0,0L,"Receiver can't delete temp file");
+       RESUME;
+       break;
+      default:
+       if (x < 0) {                    /* Fatal */
+           errpkt((CHAR *)"Can't close file");
+           RESUME;
+       } else {                        /* Success */
+#ifndef NOSPL
+           if (query)                  /* Query reponses generally */
+             conoll("");               /* don't have line terminators */
+#endif /* NOSPL */
+           if (czseen) {               /* Batch canceled? */
+               if (cancel++ == 0) {    /* If we haven't tried this yet */
+                   ack1((CHAR *)"Z");  /* Try it once */
+               } else {                /* Otherwise */
+                   errpkt((CHAR *)"User canceled"); /* quite with Error */
+                   RESUME;
+               }
+           } else
+             ack();                    /* Acknowledge the EOF packet */
+           BEGIN rfile;                /* and await another file */
+       }
+    }
+#else
+    if (reof(filnam, &iattr) < 0) {    /* Close the file */
+       errpkt((CHAR *)"Error at end of file");
+       RESUME;
+    } else {                           /* reof() sets success flag */
+       ack();
+       BEGIN rfile;
+    }
+#endif /* COHERENT */
+}
+
+<ssinit>Y {                            /* ACK for Send-Init */
+    spar(rdatap);                      /* set parameters from it */
+    cancel = 0;
+    bctu = bctr;                       /* switch to agreed-upon block check */
+    bctl = (bctu == 4) ? 2 : bctu;     /* Set block-check length */
+#ifdef CK_RESEND
+    if ((sendmode == SM_RESEND) && (!atcapu || !rscapu)) { /* RESEND */
+       errpkt((CHAR *) "RESEND capabilities not negotiated");
+       RESUME;
+    } else {
+#endif /* CK_RESEND */
+       what = W_SEND;                  /* Remember we're sending */
+       lastxfer = W_SEND;
+       x = sfile(xflg);                /* Send X or F header packet */
+       cancel = 0;                     /* Reset cancellation counter */
+       if (x) {                        /* If the packet was sent OK */
+           if (!xflg && filcnt == 1)   /* and it's a real file */
+             crc16 = 0L;               /* Clear the file CRC */
+           resetc();                   /* reset per-transaction counters */
+           rtimer();                   /* reset timers */
+#ifdef GFTIMER
+           rftimer();
+#endif /* GFTIMER */
+           streamon();                 /* turn on streaming */
+#ifdef IKSDB
+           if (ikdbopen) slotstate(what,
+                                 (server ? "SERVER" : ""),
+                                 "SEND",
+                                 filnam
+                                 );
+#endif /* IKSDB */
+           BEGIN ssfile;               /* and switch to receive-file state */
+       } else {                        /* otherwise send error msg & quit */
+           s = xflg ? "Can't execute command" : (char *)epktmsg;
+           if (!*s) s = "Can't open file";
+           errpkt((CHAR *)s);
+           RESUME;
+       }
+#ifdef CK_RESEND
+    }
+#endif /* CK_RESEND */
+}
+
+/*
+  These states are necessary to handle the case where we get a server command
+  packet (R, G, or C) reply with an S packet, but the client retransmits the
+  command packet.  The input() function doesn't catch this because the packet
+  number is still zero.
+*/
+<ssinit>R {                            /* R packet was retransmitted. */
+    xsinit();                          /* Resend packet 0 */
+}
+
+<ssinit>G {                            /* Same deal if G packet comes again */
+    xsinit();
+}
+
+/* should probably add cases for O, W, V, H, J, ... */
+
+<ssinit>C {                            /* Same deal if C packet comes again */
+    xsinit();
+}
+
+<ssfile>Y {                            /* ACK for F or X packet */
+    srvptr = srvcmd;                   /* Point to string buffer */
+    decode(rdatap,putsrv,0);           /* Decode data field, if any */
+    putsrv(NUL);                       /* Terminate with null */
+    ffc = 0L;                          /* Reset file byte counter */
+    debug(F101,"<ssfile>Y cxseen","",cxseen);
+    if (*srvcmd) {                     /* If remote name was recorded */
+        if (sendmode != SM_RESEND) {
+           if (fdispla == XYFD_C || fdispla == XYFD_S)
+             xxscreen(SCR_AN,0,0L,(char *)srvcmd);
+           tlog(F110," remote name:",(char *) srvcmd,0L);
+           makestr(&psrfspec,(char *)srvcmd);
+        }
+    }
+    if (cxseen||czseen) {              /* Interrupted? */
+       debug(F101,"<ssfile>Y canceling","",0);
+       x = clsif();                    /* Close input file */
+       sxeof(1);                       /* Send EOF(D) */
+       BEGIN sseof;                    /* and switch to EOF state. */
+    } else if (atcapu) {               /* If attributes are to be used */
+       if (sattr(xflg | stdinf, 1) < 0) { /* send them */
+           errpkt((CHAR *)"Can't send attributes"); /* if problem, say so */
+           RESUME;                     /* and quit */
+       } else BEGIN ssattr;            /* if ok, switch to attribute state */
+    } else {                           /* Attributes not negotiated */
+       if (window(wslotn) < 0) {       /* Open window */
+           errpkt((CHAR *)"Can't open window");
+           RESUME;
+       } else if ((x = sdata()) == -2) { /* Send first data packet data */
+           window(1);                  /* Connection lost, reset window */
+           x = clsif();                /* Close input file */
+           return(success = 0);        /* Return failure */
+       } else if (x == -9) {           /* User interrupted */
+           errpkt((CHAR *)"User cancelled"); /* Send Error packet */
+           window(1);                  /* Set window size back to 1... */
+           timint = s_timint;          /* Restore timeout */
+           return(success = 0);        /* Failed */
+       } else if (x < 0) {             /* EOF (empty file) or interrupted */
+           window(1);                  /* put window size back to 1, */
+           debug(F101,"<ssfile>Y cxseen","",cxseen);
+           x = clsif();                /* If not ok, close input file, */
+           if (x < 0)                  /* treating failure as interruption */
+             cxseen = 1;               /* Send EOF packet */
+           seof(cxseen||czseen);
+           BEGIN sseof;                /* and switch to EOF state. */
+       } else {                        /* First data sent OK */
+           BEGIN ssdata;               /* All ok, switch to send-data state */
+       }
+    }
+}
+
+<ssattr>Y {                            /* Got ACK to A packet */
+    ffc = 0L;                          /* Reset file byte counter */
+    debug(F101,"<ssattr>Y cxseen","",cxseen);
+    if (cxseen||czseen) {              /* Interrupted? */
+       debug(F101,"<sattr>Y canceling","",0);
+       x = clsif();                    /* Close input file */
+       sxeof(1);                       /* Send EOF(D) */
+       BEGIN sseof;                    /* and switch to EOF state. */
+    } else if (rsattr(rdatap) < 0) {   /* Was the file refused? */
+       discard = 1;                    /* Set the discard flag */
+       clsif();                        /* Close the file */
+       sxeof(1);                       /* send EOF with "discard" code */
+       BEGIN sseof;                    /* switch to send-EOF state */
+    } else if ((x = sattr(xflg | stdinf, 0)) < 0) { /* Send more? */
+       errpkt((CHAR *)"Can't send attributes"); /* Trouble... */
+       RESUME;
+    } else if (x == 0) {               /* No more to send so now the data */
+       if (window(wslotn) < 0) {       /* Allocate negotiated window slots */
+           errpkt((CHAR *)"Can't open window");
+           RESUME;
+       }
+       if ((x = sdata()) == -2) {      /* File accepted, send first data */
+           window(1);                  /* Connection broken */
+           x = clsif();                /* Close file */
+           return(success = 0);        /* Return failure */
+       } else if (x == -9) {           /* User interrupted */
+           errpkt((CHAR *)"User cancelled"); /* Send Error packet */
+           window(1);                  /* Set window size back to 1... */
+           timint = s_timint;          /* Restore timeout */
+           return(success = 0);        /* Failed */
+       } else if (x < 0) {             /* If data was not sent */
+           window(1);                  /* put window size back to 1, */
+           debug(F101,"<ssattr>Y cxseen","",cxseen);
+           if (clsif() < 0)            /* Close input file */
+             cxseen = 1;               /* Send EOF packet */
+           seof(cxseen||czseen);
+           BEGIN sseof;                /* and switch to EOF state. */
+       } else {
+           BEGIN ssdata;               /* All ok, switch to send-data state */
+       }
+    }
+}
+
+<ssdata>q {                            /* Ctrl-C or connection loss. */
+    window(1);                         /* Set window size back to 1... */
+    cxseen = 1;                                /* To indicate interruption */
+    x = clsif();                       /* Close file */
+    return(success = 0);               /* Failed */
+}
+
+<ssdata>Y {                            /* Got ACK to Data packet */
+    canned(rdatap);                    /* Check if file transfer cancelled */
+    debug(F111,"<ssdata>Y cxseen",rdatap,cxseen);
+    debug(F111,"<ssdata>Y czseen",rdatap,czseen);
+    if ((x = sdata()) == -2) {         /* Try to send next data */
+       window(1);                      /* Connection lost, reset window */
+       x = clsif();                    /* Close file */
+       return(success = 0);            /* Failed */
+    } else if (x == -9) {              /* User interrupted */
+       errpkt((CHAR *)"User cancelled"); /* Send Error packet */
+       window(1);                      /* Set window size back to 1... */
+       timint = s_timint;              /* Restore original timeout */
+       return(success = 0);            /* Failed */
+    } else if (x < 0) {                        /* EOF - finished sending data */
+       debug(F101,"<ssdata>Y cxseen","",cxseen);
+       window(1);                      /* Set window size back to 1... */
+       if (clsif() < 0)                /* Close input file */
+         cxseen = 1;                   /* Send EOF packet */
+       debug(F101,"<ssdata>Y CALLING SEOF()","",cxseen);
+       seof(cxseen||czseen);
+       BEGIN sseof;                    /* and enter send-eof state */
+    }
+    /* NOTE: If x == 0 it means we're draining: see sdata()! */
+}
+
+<sseof>Y {                             /* Got ACK to EOF */
+    int g, xdiscard;
+    canned(rdatap);                    /* Check if file transfer cancelled */
+    debug(F111,"<sseof>Y cxseen",rdatap,cxseen);
+    debug(F111,"<sseof>Y czseen",rdatap,czseen);
+    debug(F111,"<sseof>Y discard",rdatap,discard);
+    xdiscard = discard;
+    discard = 0;
+    success = (cxseen == 0 && czseen == 0); /* Transfer status... */
+    debug(F101,"<sseof>Y success","",success);
+    if (success && rejection > 0)          /* If rejected, succeed if */
+      if (rejection != '#' &&              /* reason was date */
+         rejection != 1 && rejection != '?') /* or name; */
+       success = 0;                        /* fail otherwise. */
+    cxseen = 0;                                /* This goes back to zero. */
+    if (success) {                     /* Only if transfer succeeded... */
+       xxscreen(SCR_ST,ST_OK,0L,"");
+       if (!xdiscard) {
+           makestr(&sfspec,psfspec);   /* Record filenames for WHERE */
+           makestr(&srfspec,psrfspec);
+       }
+       if (moving) {                   /* If MOVE'ing */
+           x = zdelet(filnam);         /* Try to delete the source file */
+#ifdef TLOG
+           if (tralog) {
+               if (x > -1) {
+                   tlog(F110," deleted",filnam,0);
+               } else {
+                   tlog(F110," delete failed:",ck_errstr(),0);
+               }
+           }
+#endif /* TLOG */
+       } else if (snd_move) {          /* Or move it */
+           int x;
+           x = zrename(filnam,snd_move);
+#ifdef TLOG
+           if (tralog) {
+               if (x > -1) {
+                   tlog(F110," moved to ",snd_move,0);
+               } else {
+                   tlog(F110," move failed:",ck_errstr(),0);
+               }
+           }
+#endif /* TLOG */
+       } else if (snd_rename) {        /* Or rename it */
+           char *s = snd_rename;       /* Renaming string */
+#ifndef NOSPL
+           int y;                      /* Pass it thru the evaluator */
+           extern int cmd_quoting;     /* for \v(filename) */
+           if (cmd_quoting) {          /* But only if cmd_quoting is on */
+               y = MAXRP;
+               s = (char *)srvcmd;
+               zzstring(snd_rename,&s,&y);
+               s = (char *)srvcmd;
+           }
+#endif /* NOSPL */
+           if (s) if (*s) {
+               int x;
+               x = zrename(filnam,s);
+#ifdef TLOG
+           if (tralog) {
+               if (x > -1) {
+                   tlog(F110," renamed to",s,0);
+               } else {
+                   tlog(F110," rename failed:",ck_errstr(),0);
+               }
+           }
+#endif /* TLOG */
+#ifdef COMMENT
+               *s = NUL;
+#endif /* COMMENT */
+           }
+       }
+    }
+    if (czseen) {                      /* Check group interruption flag */
+       g = 0;                          /* No more files if interrupted */
+    } else {                           /* Otherwise... */
+#ifdef COMMENT
+       /* This code makes any open error fatal to a file-group transfer. */
+       g = gnfile();
+       debug(F111,"<sseof>Y gnfile",filnam,g);
+       if (g > 0) {                    /* Any more files to send? */
+           if (sfile(xflg))            /* Yes, try to send next file header */
+             BEGIN ssfile;             /* if ok, enter send-file state */
+           else {                      /* otherwise */
+               s = xflg ? "Can't execute command" : (char *)epktmsg;
+               if (!*s) s = "Can't open file";
+               errpkt((CHAR *)s);      /* send error message */
+               RESUME;                 /* and quit */
+           }
+       } else {                        /* No next file */
+           tsecs = gtimer();           /* get statistics timers */
+#ifdef GFTIMER
+           fptsecs = gftimer();
+#endif /* GFTIMER */
+           seot();                     /* send EOT packet */
+           BEGIN sseot;                /* enter send-eot state */
+       }
+#else  /* COMMENT */
+       while (1) {                     /* Keep trying... */
+           g = gnfile();               /* Get next file */
+           debug(F111,"<sseof>Y gnfile",filnam,g);
+           if (g == 0 && gnferror == 0) /* No more, stop trying */
+             break;
+           if (g > 0) {                /* Have one */
+               if (sfile(xflg)) {      /* Try to open and send F packet */
+                   BEGIN ssfile;       /* If OK, enter send-file state */
+                   break;              /* and break out of loop. */
+               }
+           } /* Otherwise keep trying to get one we can send... */
+       }
+    }
+    if (g == 0) {
+       debug(F101,"<sseof>Y no more files","",czseen);
+       tsecs = gtimer();               /* Get statistics timers */
+#ifdef GFTIMER
+       fptsecs = gftimer();
+#endif /* GFTIMER */
+       seot();                         /* Send EOT packet */
+       BEGIN sseot;                    /* Enter send-eot state */
+    }
+#endif /* COMMENT */
+}
+
+<sseot>Y {                             /* Got ACK to EOT */
+    debug(F101,"sseot justone","",justone);
+    RESUME;                            /* All done, just quit */
+}
+
+E {                                    /* Got Error packet, in any state */
+    char *s = "";
+    window(1);                         /* Close window */
+    timint = s_timint;                 /* Restore original timeout */
+    if (*epktmsg)                      /* Message from Error packet */
+      s = (char *)epktmsg;
+    if (!*s) {                         /* If not there then maybe here */
+       s = (char *)rdatap;
+       ckstrncpy((char *)epktmsg,(char *)rdatap,PKTMSGLEN);
+    }
+    if (!*s)                           /* Hopefully we'll never see this. */
+      s = "Unknown error";
+    success = 0;                       /* For IF SUCCESS/FAIL. */
+    debug(F101,"ckcpro.w justone at E pkt","",justone);
+
+    success = 0;                       /* Transfer failed */
+    xferstat = success;                        /* Remember transfer status */
+    if (!epktsent) {
+       x = quiet; quiet = 1;           /* Close files silently, */
+       epktrcvd = 1;                   /* Prevent messages from clsof() */
+       clsif();
+       clsof(1);                       /* discarding any output file. */
+       ermsg(s);                       /* Issue the message (calls screen). */
+       quiet = x;                      /* Restore quiet state */
+    }
+    tstats();                          /* Get stats */
+/*
+  If we are executing commands from a command file or macro, let the command
+  file or macro decide whether to exit, based on SET { TAKE, MACRO } ERROR.
+*/
+    if (
+#ifndef NOICP
+       !xcmdsrc &&
+#endif /* NOICP */
+       backgrd && !server)
+      fatal("Protocol error");
+    xitsta |= (what & W_KERMIT);       /* Save this for doexit(). */
+#ifdef CK_TMPDIR
+/* If we were cd'd temporarily to another device or directory ... */
+    if (f_tmpdir) {
+       int x;
+       x = zchdir((char *) savdir);    /* ... restore previous directory */
+       f_tmpdir = 0;                   /* and remember we did it. */
+       debug(F111,"ckcpro.w E tmpdir restored",savdir,x);
+    }
+#endif /* CK_TMPDIR */
+#ifdef IKSDB
+    if (ikdbopen) slotstate(what,"ERROR", (char *)epktmsg, "");
+#endif /* IKSDB */
+    RESUME;
+}
+
+q { success = 0; QUIT; }               /* Ctrl-C or connection loss. */
+
+. {                                    /* Anything not accounted for above */
+    errpkt((CHAR *)"Unexpected packet type"); /* Give error message */
+    window(1);
+    xitsta |= (what & W_KERMIT);       /* Save this for doexit(). */
+    RESUME;                            /* and quit */
+}
+
+%%
+
+/*
+  From here down to proto() are routines that were moved out of the state
+  table switcher because the resulting switch() had become too large.
+  To move the contents of a state-table case to a routine:
+    1. Add a prototype to the list above the state table switcher.
+    2. Make a routine with an appropriate name, returning int.
+    3. Move the code into it.
+    4. Put a call to the new routine in the former spot:
+         rc = name_of_routine();
+         if (rc > -1) return(rc);
+    5. Add "return(-1);" after every RESUME, SERVE, or BEGIN macro and
+       at the end if the code is open-ended.
+*/
+static int
+rcv_firstdata() {
+    extern int dispos;
+    debug(F101,"rcv_firstdata","",dispos);
+
+    if (discard) {                     /* if we're discarding the file */
+       ack1((CHAR *)"X");              /* just ack the data like this. */
+       cancel++;                       /* and count it */
+       BEGIN rdpkt;                    /* and wait for more data packets. */
+       return(-1);
+    } else {                           /* Not discarding. */
+       rf_err = "Can't open file";
+       if (xflg) {                     /* If screen data */
+           if (remfile) {              /* redirected to file */
+               if (rempipe)            /* or pipe */
+                 x = openc(ZOFILE,remdest); /* Pipe: start command */
+               else
+                 x = opena(remdest,&iattr); /* File: open with attributes */
+           } else {                    /* otherwise */
+               x = opent(&iattr);      /* "open" the screen */
+           }
+       } else {                        /* otherwise */
+#ifdef CALIBRATE
+           if (calibrate) {            /* If calibration run */
+               x = ckopenx(&iattr);    /* open nothing */
+#ifdef STREAMING
+               if (streaming)          /* Streaming */
+                 fastack();            /* ACK without ACKing. */
+               else
+#endif /* STREAMING */
+                 ack();                /* Send real ACK */
+               BEGIN rdpkt;            /* Proceed to next state */
+               return(-1);
+           } else
+#endif /* CALIBRATE */
+#ifdef UNIX
+/*
+  In UNIX we can pipe the file data into the mail program, which is to be
+  preferred to writing it out to a temp file and then mailing it afterwards.
+  This depends rather heavily on all UNIXes having a mail command that
+  accepts '-s "subject"' on the command line.  MAILCMD (e.g. mail, Mail, mailx)
+  is defined in ckufio.c.
+*/
+           if (dispos == 'M') {        /* Mail... */
+               char *s;
+               char * tmp = NULL;
+               int n = 0;
+               extern char *MAILCMD;
+               s = iattr.disp.val + 1;
+               n = (int)strlen(MAILCMD) +    /* Mail command */
+                 (int)strlen(s) +            /* address */
+                 (int)strlen(ofilnam) + 32;  /* subject */
+               if (tmp = (char *)malloc(n)) {
+                   ckmakxmsg(tmp,n,
+                             MAILCMD," -s \"",ofilnam,"\" ",s,
+                             NULL,NULL,NULL,NULL,NULL,NULL,NULL);
+                   debug(F111,"rcv_firsdata mail",tmp,(int)strlen(tmp));
+                   x = openc(ZOFILE,(char *)tmp);
+                   free(tmp);
+               } else
+                 x = 0;
+           } else if (dispos == 'P') { /* Ditto for print */
+               char * tmp = NULL;
+               int n;
+               extern char *PRINTCMD;
+               n = (int)strlen(PRINTCMD) + (int)strlen(iattr.disp.val+1) + 4;
+               if (tmp = (char *)malloc(n)) {
+                   sprintf(tmp,        /* safe (prechecked) */
+                           "%s %s", PRINTCMD, iattr.disp.val + 1);
+                   x = openc(ZOFILE,(char *)tmp);
+                   free(tmp);
+               } else
+                 x = 0;
+           } else
+#endif /* UNIX */
+             x = opena(filnam,&iattr); /* open the file, with attributes */
+       }
+       if (x) {                        /* If file was opened ok */
+           int rc, qf;
+#ifndef NOSPL
+           qf = query;
+#else
+           qf = 0;
+#endif /* NOSPL */
+
+#ifdef CKTUNING
+           rc = (binary && !parity) ?
+             bdecode(rdatap,putfil):
+              decode(rdatap, qf ? puttrm : putfil, 1);
+#else
+           rc = decode(rdatap, qf ? puttrm : putfil, 1);
+#endif /* CKTUNING */
+           if (rc < 0) {
+               errpkt((CHAR *)"Error writing data");
+               RESUME;
+               return(-1);
+           }
+#ifdef STREAMING
+           if (streaming)              /* Streaming was negotiated */
+             fastack();                /* ACK without ACKing. */
+           else
+#endif /* STREAMING */
+             ack();                    /* acknowledge it */
+           BEGIN rdpkt;                /* and switch to receive-data state */
+           return(-1);
+       } else {                        /* otherwise */
+           errpkt((CHAR *) rf_err);    /* send error packet */
+           RESUME;                     /* and quit. */
+           return(-1);
+       }
+    }
+}
+
+static int
+rcv_shortreply() {
+#ifdef PKTZEROHACK
+    success = 0;
+    debug(F111,"rcv_shortreply",rdatap,ipktlen);
+    if (ipktack[0] && !strncmp(ipktack,(char *)rdatap,ipktlen)) {
+       /* No it's the ACK to the I packet again */
+       x = scmd(vcmd,(CHAR *)cmarg);   /* So send the REMOTE command again */
+       /* Maybe this should be resend() */
+       debug(F110,"IPKTZEROHACK",ipktack,x);
+       if (x < 0) {
+           errpkt((CHAR *)srimsg);
+           RESUME;
+           return(-1);
+       }
+    } else {
+       ipktack[0] = NUL;
+#endif /* PKTZEROHACK */
+       urserver = 1;
+#ifndef NOSERVER
+#ifndef NOSPL
+       if (query) {                    /* If to query, */
+           qbufp = querybuf;           /*  initialize query response buffer */
+           qbufn = 0;
+           querybuf[0] = NUL;
+       }
+#endif /* NOSPL */
+       x = 1;
+       if (remfile) {                  /* Response redirected to file */
+           rf_err = "Can't open file";
+           if (rempipe)                /* or pipe */
+             x =
+#ifndef NOPUSH
+               zxcmd(ZOFILE,remdest)   /* Pipe: Start command */
+#else
+               0
+#endif /* NOPUSH */
+               ;
+           else
+             x = opena(remdest,&iattr); /* File: Open with attributes */
+           debug(F111,"rcv_shortreply remfile",remdest,x);
+       } else {
+           x = opent(&iattr);          /* "open" the screen */
+       }
+       if (x) {                        /* If file was opened ok */
+           if (decode(rdatap,
+#ifndef NOSPL
+                      (query || !remfile) ? puttrm :
+#else
+                      !remfile ? puttrm :
+#endif /* NOSPL */
+                      zputfil, 1) < 0) { /* Note: zputfil, not putfil. */
+               errpkt((CHAR *)"Error writing data");
+               RESUME;
+               return(-1);
+           } else {
+               if (rdatap)             /* If we had data */
+                 if (*rdatap)          /* add a line terminator */
+                   if (remfile) {      /* to file */
+                       zsoutl(ZOFILE,"");
+                   } else {            /* or to screen. */
+#ifndef NOICP
+                       if (!query || !xcmdsrc)
+#endif /* NOICP */
+                         if (!(quiet && rcdactive))
+                           conoll("");
+                   }
+               if (bye_active && network) { /* I sent BYE or REMOTE LOGOUT */
+                   msleep(500);        /* command and got the ACK... */
+                   bye_active = 0;
+                   ttclos(0);
+               }
+               clsof(0);
+               if (!epktsent && !epktrcvd) /* If no error packet... */
+                 success = 1;          /* success. */
+               RESUME;
+               return(-1);
+           }
+       } else {                        /* File not opened OK */
+           errpkt((CHAR *) rf_err);    /* send error message */
+           RESUME;                     /* and quit. */
+           return(-1);
+       }
+#endif /* NOSERVER */
+#ifdef PKTZEROHACK
+    }
+#endif /* PKTZEROHACK */
+    debug(F101,"rcv_shortreply fallthru","",success);
+    return(-1);
+}
+
+
+static int
+srv_query() {
+#ifndef NOSERVER
+#ifndef NOSPL
+    char c;
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE QUERY", (char *)srvcmd);
+#endif /* CKSYSLOG */
+#ifdef IKSDB
+    if (ikdbopen) slotstate(what,"REMOTE QUERY", (char *)(srvcmd+2), "");
+#endif /* IKSDB */
+    c = *(srvcmd+2);                   /* Q = Query, S = Set */
+    if (c == 'Q') {                    /* Query */
+       if (!ENABLED(en_que)) { /* Security */
+           errpkt((CHAR *)"REMOTE QUERY disabled");
+           RESUME;
+           return(-1);
+       } else {                        /* Query allowed */
+           int n; char *p, *q;
+           qbufp = querybuf;           /* Wipe out old stuff */
+           qbufn = 0;
+           querybuf[0] = NUL;
+           p = (char *) srvcmd + 3;    /* Pointer for making wrapper */
+           n = strlen((char *)srvcmd); /* Position of end */
+           c = *(srvcmd+4);            /* Which type of variable */
+
+           if (*(srvcmd+6) == CMDQ) {  /* Starts with command quote? */
+               p = (char *) srvcmd + 6; /* Take it literally */
+               if (*p == CMDQ) p++;
+           } else {                    /* They played by the rules */
+               if (c == 'K') {         /* Kermit variable */
+                   int k;
+                   k = (int) strlen(p);
+                   if (k > 0 && p[k-1] == ')') {
+                       p = (char *)(srvcmd + 4);
+                       *(srvcmd+4) = CMDQ;
+                       *(srvcmd+5) = 'f'; /* Function, so make it \f...() */
+                   } else {
+                       *(srvcmd+3) = CMDQ; /* Stuff wrapping into buffer */
+                       *(srvcmd+4) = 'v';  /* Variable, so make it \v(...) */
+                       *(srvcmd+5) = '(';  /* around variable name */
+                       *(srvcmd+n) = ')';
+                       *(srvcmd+n+1) = NUL;
+                   }
+               } else {
+                   *(srvcmd+3) = CMDQ; /* Stuff wrapping into buffer */
+                   *(srvcmd+4) = 'v'; /*  Variable, so make it \v(...) */
+                   *(srvcmd+5) = '(';  /* around variable name */
+                   *(srvcmd+n) = ')';
+                   *(srvcmd+n+1) = NUL;
+                   if (c == 'S') {     /* System variable */
+                       *(srvcmd+4) = '$'; /*  so it's \$(...) */
+                   } else if (c == 'G') { /* Non-\ Global variable */
+                       *(srvcmd+4) = 'm'; /*  so wrap it in \m(...) */
+                   }
+               }
+           }                           /* Now evaluate it */
+           n = QBUFL;                  /* Max length */
+           q = querybuf;               /* Where to put it */
+           if (zzstring(p,&q,&n) < 0) {
+               errpkt((n > 0) ? (CHAR *)"Can't get value"
+                              : (CHAR *)"Value too long"
+                      );
+               RESUME;
+               return(-1);
+           } else {
+               if (encstr((CHAR *)querybuf) > -1) { /* Encode it */
+                   ack1(data);         /* If it fits, send it back in ACK */
+                   success = 1;
+                   RESUME;
+                   return(-1);
+               } else if (sndstring(querybuf)) { /* Long form response */
+                   BEGIN ssinit;
+                   return(-1);
+               } else {                /* sndhlp() fails */
+                   errpkt((CHAR *)"Can't send value");
+                   RESUME;
+                   return(-1);
+               }
+           }
+       }
+    } else if (c == 'S') {             /* Set (assign) */
+       if (!ENABLED(en_asg)) {         /* Security */
+           errpkt((CHAR *)"REMOTE ASSIGN disabled");
+           RESUME;
+           return(-1);
+       } else {                        /* OK */
+           int n;
+           n = xunchar(*(srvcmd+3));   /* Length of name */
+           n = 3 + n + 1;              /* Position of length of value */
+           *(srvcmd+n) = NUL;          /* Don't need it */
+           if (addmac((char *)(srvcmd+4),(char *)(srvcmd+n+1)) < 0)
+             errpkt((CHAR *)"REMOTE ASSIGN failed");
+           else {
+               ack();
+               success = 1;
+           }
+           RESUME;
+           return(-1);
+       }
+    } else {
+       errpkt((CHAR *)"Badly formed server command");
+       RESUME;
+       return(-1);
+    }
+#else
+    errpkt((CHAR *)"Variable query/set not available");
+    RESUME;
+    return(-1);
+#endif /* NOSPL */
+#endif /* NOSERVER */
+}
+
+static int
+srv_copy() {
+#ifndef NOSERVER
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE COPY", (char *)srvcmd);
+#endif /* CKSYSLOG */
+#ifdef ZCOPY
+    if (!ENABLED(en_cpy)) {
+       errpkt((CHAR *)"REMOTE COPY disabled");
+       RESUME;
+       return(-1);
+    } else {
+       char *str1, *str2, f1[256], f2[256];
+       int  len1, len2;
+        len1 = xunchar(srvcmd[1]);     /* Separate the parameters */
+        len2 = xunchar(srvcmd[2+len1]);
+        strncpy(f1,(char *)(srvcmd+2),len1);
+        f1[len1] = NUL;
+        strncpy(f2,(char *)(srvcmd+3+len1),len2);
+        f2[len2] = NUL;
+#ifdef IKSDB
+       if (ikdbopen) slotstate(what,"REMOTE COPY", f1, f2);
+#endif /* IKSDB */
+       if (!ENABLED(en_cwd)) {         /* If CWD is disabled */
+           zstrip(f1,&str1);           /* and they included a pathname, */
+            zstrip(f2,&str2);
+           if (strcmp(f1,str1) || strcmp(f2,str2)) { /* Refuse. */
+               errpkt((CHAR *)"Access denied");
+               RESUME;                 /* Remember, this is not a goto! */
+               return(-1);
+           }
+       }
+       if (state == generic) {         /* It's OK to go ahead. */
+            if (zcopy(f1,f2)) {                /* Try */
+               errpkt((CHAR *)"Can't copy file"); /* give error message */
+           } else {
+               success = 1;
+               ack();
+           }
+            RESUME;                    /* wait for next server command */
+           return(-1);
+       }
+    }
+    return(-1);
+#else /* no ZCOPY */
+    errpkt((CHAR *)"REMOTE COPY not available"); /* give error message */
+    RESUME;                            /* wait for next server command */
+    return(-1);
+#endif /* ZCOPY */
+#endif /* NOSERVER */
+}
+
+static int
+srv_rename() {
+#ifndef NOSERVER
+#ifdef CKSYSLOG
+    if (ckxsyslog >= SYSLG_PR && ckxlogging)
+      cksyslog(SYSLG_PR, 1, "server", "REMOTE RENAME", (char *)srvcmd);
+#endif /* CKSYSLOG */
+#ifdef ZRENAME
+    if (!ENABLED(en_ren)) {
+       errpkt((CHAR *)"REMOTE RENAME disabled");
+       RESUME;
+       return(-1);
+    } else {                           /* RENAME is enabled */
+       char *str1, *str2, f1[256], f2[256];
+       int len1, len2;
+       len1 = xunchar(srvcmd[1]);      /* Separate the parameters */
+       len2 = xunchar(srvcmd[2+len1]);
+       strncpy(f1,(char *)(srvcmd+2),len1);
+       f1[len1] = NUL;
+       strncpy(f2,(char *)(srvcmd+3+len1),len2);
+       f2[len2] = NUL;
+       len2 = xunchar(srvcmd[2+len1]);
+       strncpy(f1,(char *)(srvcmd+2),len1);
+       f1[len1] = NUL;
+       strncpy(f2,(char *)(srvcmd+3+len1),len2);
+       f2[len2] = NUL;
+#ifdef IKSDB
+       if (ikdbopen) slotstate(what,"REMOTE RENAME", f1, f2);
+#endif /* IKSDB */
+       if (!ENABLED(en_cwd)) {         /* If CWD is disabled */
+           zstrip(f1,&str1);           /* and they included a pathname, */
+           zstrip(f2,&str2);
+           if ( strcmp(f1,str1) || strcmp(f2,str2) ) { /* refuse. */
+               errpkt((CHAR *)"Access denied");
+               RESUME;                 /* Remember, this is not a goto! */
+               return(-1);
+           }
+       }
+       if (state == generic) {         /* It's OK to go ahead. */
+           if (zrename(f1,f2)) {       /* Try */
+               errpkt((CHAR *)"Can't rename file"); /* Give error msg */
+           } else {
+               success = 1;
+               ack();
+           }
+           RESUME;                     /* Wait for next server command */
+           return(-1);
+       }
+    }
+    return(-1);
+#else /* no ZRENAME */
+    /* Give error message */
+    errpkt((CHAR *)"REMOTE RENAME not available");
+    RESUME;                            /* Wait for next server command */
+    return(-1);
+#endif /* ZRENAME */
+#endif /* NOSERVER */
+}
+
+static int
+srv_login() {
+#ifndef NOSERVER
+    char f1[LOGINLEN+1], f2[LOGINLEN+1], f3[LOGINLEN+1];
+    CHAR *p;
+    int len, i;
+
+    debug(F101,"REMOTE LOGIN x_login","",x_login);
+    debug(F101,"REMOTE LOGIN x_logged","",x_logged);
+
+    f1[0] = NUL; f2[0] = NUL; f3[0] = NUL;
+    len = 0;
+    if (srvcmd[1])                     /* First length field */
+      len = xunchar(srvcmd[1]);                /* Separate the parameters */
+
+    if (x_login) {                     /* Login required */
+       if (x_logged) {                 /* And already logged in */
+           if (len > 0) {              /* Logging in again */
+               errpkt((CHAR *)"Already logged in.");
+           } else {                    /* Logging out */
+               debug(F101,"REMOTE LOGOUT","",x_logged);
+#ifdef CKSYSLOG
+               if (ckxsyslog >= SYSLG_PR && ckxlogging)
+                 cksyslog(SYSLG_PR, 1, "server", "REMOTE LOGOUT", NULL);
+#endif /* CKSYSLOG */
+#ifdef IKSDB
+               if (ikdbopen) slotstate(what,"REMOTE LOGOUT", "", "");
+#endif /* IKSDB */
+               tlog(F110,"Logged out",x_user,0);
+               ack1((CHAR *)"Logged out");
+               success = 1;
+               msleep(500);
+#ifdef CK_LOGIN
+               x_logged = 0;
+#ifdef IKSD
+               if (inserver)
+                 ckxlogout();
+#endif /* IKSD */
+#endif /* CK_LOGIN */
+           }
+       } else {                        /* Not logged in yet */
+           debug(F101,"REMOTE LOGIN len","",len);
+           if (len > 0) {              /* Have username */
+#ifdef CKSYSLOG
+               if (ckxsyslog >= SYSLG_PR && ckxlogging)
+                 cksyslog(SYSLG_PR, 1, "server", "REMOTE LOGIN", NULL);
+#endif /* CKSYSLOG */
+               if (len > LOGINLEN) {
+                   errpkt((CHAR *)"Username too long");
+               }
+               p = srvcmd + 2;         /* Point to it */
+               for (i = 0; i < len; i++) /* Copy it */
+                 f1[i] = p[i];
+               f1[len] = NUL;          /* Terminate it */
+               p += len;               /* Point to next length field */
+               if (*p) {               /* If we have one */
+                   len = xunchar(*p++); /* decode it */
+                   if (len > 0 && len <= LOGINLEN) {
+                       for (i = 0; i < len; i++) /* Same deal for password */
+                         f2[i] = p[i];
+                       f2[len] = NUL;
+                       p += len;       /* And account */
+                       if (*p) {
+                           len = xunchar(*p++);
+                           if (len > 0 && len <= LOGINLEN) {
+                               for (i = 0; i < len; i++)
+                                 f3[i] = p[i]; /* Set but never used */
+                               f3[len] = NUL; /* (because account not used) */
+                           }
+                       }
+                   }
+               }
+               debug(F101,"REMOTE LOGIN 1","",x_logged);
+#ifdef IKSD
+#ifdef CK_LOGIN
+               if (inserver) {         /* Log in to system for real */
+                   x_logged = ckxlogin((CHAR *)f1,(CHAR *)f2,NULL,0);
+                   debug(F101,"REMOTE LOGIN 2","",x_logged);
+                   if (x_logged) {     /* Count attempts */
+                       logtries = 0;
+                       justone = 1;
+                   } else {
+                       logtries++;
+                       sleep(logtries);
+                   }
+               } else
+#endif /* CK_LOGIN */
+#endif /* IKSD */
+                 if (x_user && x_passwd) { /* User and password must match */
+                     if (!strcmp(x_user,f1)) /* SET SERVER LOGIN */
+                       if (!strcmp(x_passwd,f2))
+                         x_logged = 1;
+                     debug(F101,"REMOTE LOGIN 3","",x_logged);
+                 } else if (x_user) {  /* Only username given, no password */
+                     if (!strcmp(x_user,f1)) /* so only username must match */
+                       x_logged = 1;
+                     debug(F101,"REMOTE LOGIN 4","",x_logged);
+                 }
+#ifdef CK_LOGIN 
+                else {
+                   x_logged = ckxlogin((CHAR *)f1,(CHAR *)f2,NULL,0);
+                   debug(F101,"REMOTE LOGIN 5","",x_logged);
+                }
+#endif /* CK_LOGIN */
+               if (x_logged) {         /* Logged in? */
+                   tlog(F110,"Logged in", x_user, 0);
+                   if (isguest)
+                     ack1((CHAR *)"Logged in as guest - restrictions apply");
+                   else
+                     ack1((CHAR *)"Logged in");
+                   success = 1;
+               } else {
+                   tlog(F110,"Login failed", f1, 0);
+                   errpkt((CHAR *)"Access denied.");
+#ifdef IKSD
+#ifdef CK_LOGIN
+                   if (inserver && logtries > 2)
+                     ckxlogout();
+#endif /* CK_LOGIN */
+#endif /* IKSD */
+               }
+           } else {                    /* LOGOUT */
+               errpkt((CHAR *)"Logout ignored");
+           }
+       }
+    } else {                           /* Login not required */
+       if (len > 0)
+         errpkt((CHAR *)"Login ignored.");
+       else
+         errpkt((CHAR *)"Logout ignored.");
+    }
+#endif /* NOSERVER */
+    RESUME;
+    return(-1);
+}
+
+static int
+srv_timeout() {
+    /* K95 does this its own way */
+    if (idletmo) {
+#ifdef IKSD
+        if (inserver) {
+           printf("\r\nIKSD IDLE TIMEOUT: %d sec\r\n", srvidl);
+           doexit(GOOD_EXIT,xitsta);
+        }
+#endif /* IKSD */
+       idletmo = 0;
+       printf("\r\nSERVER IDLE TIMEOUT: %d sec\r\n", srvidl);
+       xitsta |= (what & W_KERMIT);
+       QUIT;
+    }
+#ifndef NOSERVER
+    else if (fatalio) {                        /* Connection lost */
+#ifdef CKSYSLOG
+         if (ckxsyslog >= SYSLG_PR && ckxlogging)
+           cksyslog(SYSLG_PR, 1, "server", "Connection lost", NULL);
+#endif /* CKSYSLOG */
+#ifdef IKSDB
+         if (ikdbopen) slotstate(what,"SERVER DISCONNECT",(char *)srvcmd, "");
+#endif /* IKSDB */
+       xitsta |= what;
+       QUIT;
+    } else if (interrupted) {          /* Interrupted by hand */
+       if (!ENABLED(en_fin)) {
+           errpkt((CHAR *)"QUIT disabled");
+           RESUME;
+           return(-1);
+       } else {
+           if (what == W_SEND || what == W_RECV || what == W_REMO) {
+               success = 0;
+#ifdef CKSYSLOG
+               if (ckxsyslog >= SYSLG_PR && ckxlogging)
+                 cksyslog(SYSLG_PR, 1, "server", "Interrupted", NULL);
+#endif /* CKSYSLOG */
+           } else if (what == W_NOTHING && filcnt == 0) {
+               success = 1;
+           } /* Otherwise leave success alone */
+           xitsta |= (what & W_KERMIT);
+           QUIT;
+       }
+    } else {                           /* Shouldn't happen */
+       debug(F100,"SERVER (top) GOT UNEXPECTED 'q'","",0);
+       QUIT;
+    }
+#endif /* NOSERVER */
+}
+
+static int
+rcv_s_pkt() {
+#ifndef NOSERVER
+    if (state == rgen)
+      urserver = 1;
+    if (/* state == serve && */ x_login && !x_logged) {
+       errpkt((CHAR *)"Login required");
+       SERVE;
+    } else
+#endif /* NOSERVER */
+      if (state == serve && !ENABLED(en_sen)) { /* Not in server mode */
+       errpkt((CHAR *)"SEND disabled"); /* when SEND is disabled. */
+       RESUME;
+       return(-1);
+    } else {                           /* OK to go ahead. */
+#ifdef CK_TMPDIR
+       if (dldir && !f_tmpdir) {       /* If they have a download directory */
+           debug(F110,"receive download dir",dldir,0);
+           if (s = zgtdir()) {         /* Get current directory */
+               debug(F110,"receive current dir",s,0);
+               if (zchdir(dldir)) {    /* Change to download directory */
+                   debug(F100,"receive zchdir ok","",0);
+                   ckstrncpy(savdir,s,TMPDIRLEN);
+                   f_tmpdir = 1;       /* Remember that we did this */
+               } else
+                 debug(F100,"receive zchdir failed","",0);
+           }
+       }
+#endif /* CK_TMPDIR */
+       nakstate = 1;                   /* Can send NAKs from here. */
+       rinit(rdatap);                  /* Set parameters */
+       bctu = bctr;                    /* Switch to agreed-upon block check */
+       bctl = (bctu == 4) ? 2 : bctu;  /* Set block-check length */
+       what = W_RECV;                  /* Remember we're receiving */
+       lastxfer = W_RECV;
+       resetc();                       /* Reset counters */
+       rtimer();                       /* Reset timer */
+#ifdef GFTIMER
+       rftimer();
+#endif /* GFTIMER */
+       streamon();
+       BEGIN rfile;                    /* Go into receive-file state */
+    }
+    return(-1);
+}
+
+
+/* END OF ROUTINES MOVED OUT OF STATE MACHINE */
+
+
+/*  P R O T O  --  Protocol entry function  */
+
+static int is_tn = 0;                  /* It's a Telnet connection */
+
+#ifdef CK_SPEED
+int f_ctlp = 0;                                /* Control-character prefix table */
+#ifdef COMMENT
+short s_ctlp[256];
+#endif /* COMMENT */
+#endif /* CK_SPEED */
+
+/*
+  This is simply a wrapper for the real protocol function just below,
+  that saves any items that might be changed automatically by protocol
+  negotiations and then restores them upon exit from protocol mode.
+*/
+VOID
+proto() {
+    extern int b_save, f_save, c_save, ss_save, slostart, reliable, urclear;
+#ifndef NOCSETS
+    extern int fcharset, fcs_save, tcharset, tcs_save;
+#endif /* NOCSETS */
+
+#ifdef PIPESEND
+    extern int pipesend;
+#endif /* PIPESEND */
+#ifndef NOLOCAL
+#ifdef OS2
+    extern int cursorena[], cursor_save, term_io;
+    extern BYTE vmode;
+    extern int display_demo;
+    int term_io_save;
+#endif /* OS2 */
+#endif /* NOLOCAL */
+#ifdef TNCODE
+    int _u_bin=0, _me_bin = 0;
+#ifdef IKS_OPTION
+    int /* _u_start=0, */ _me_start = 0;
+#endif /* IKS_OPTION */
+#endif /* TNCODE */
+#ifdef PATTERNS
+    int pa_save;
+    int i;
+#endif /* PATTERNS */
+    int scan_save;
+
+#ifdef PATTERNS
+    pa_save = patterns;
+#endif /* PATTERNS */
+    scan_save = filepeek;
+
+    myjob = sstate;
+
+#ifdef CK_LOGIN
+    if (isguest) {                     /* If user is anonymous */
+       en_pri = 0;                     /* disable printing */
+       en_mai = 0;                     /* and disable email */
+       en_del = 0;                     /* and file deletion */
+    }
+#endif /* CK_LOGIN */
+
+#ifndef NOLOCAL
+#ifdef OS2
+    cursor_save = cursorena[vmode];
+    cursorena[vmode] = 0;
+    term_io_save = term_io;
+    term_io = 0;
+#endif /* OS2 */
+#endif /* NOLOCAL */
+    b_save = binary;                   /* SET FILE TYPE */
+    f_save = fncnv;                    /* SET FILE NAMES */
+    c_save = bctr;
+    p_save = fnspath;
+    r_save = recursive;
+    s_timint = timint;
+    ss_save = slostart;
+#ifndef NOCSETS
+    fcs_save = fcharset;
+    tcs_save = tcharset;
+#endif /* NOCSETS */
+
+#ifdef COMMENT
+/* Don't do this because then user can never find out what happened. */
+#ifdef CK_SPEED
+    for (i = 0; i < 256; i++)
+      s_ctlp[i] = ctlp[i];
+    f_ctlp = 1;
+#endif /* CK_SPEED */
+#endif /* COMMENT */
+    if (reliable == SET_ON)
+      slostart = 0;
+    is_tn = (!local && sstelnet)
+#ifdef TNCODE
+      || (local && network && ttnproto == NP_TELNET)
+#endif /* TNCODE */
+       ;
+#ifdef TNCODE
+    if (is_tn) {
+        if (tn_b_xfer && !(sstelnet || inserver)) {
+           /* Save the current state of Telnet Binary */
+           _u_bin = TELOPT_U(TELOPT_BINARY);
+           _me_bin = TELOPT_ME(TELOPT_BINARY);
+
+           /* If either direction is not Binary attempt to negotiate it */
+           if (!_u_bin && TELOPT_U_MODE(TELOPT_BINARY) != TN_NG_RF) {
+               tn_sopt(DO,TELOPT_BINARY);
+               TELOPT_UNANSWERED_DO(TELOPT_BINARY) = 1;
+           }
+           if (!_me_bin && TELOPT_ME_MODE(TELOPT_BINARY) != TN_NG_RF) {
+               tn_sopt(WILL,TELOPT_BINARY);
+               TELOPT_UNANSWERED_WILL(TELOPT_BINARY) = 1;
+           }
+           if (!(_me_bin && _u_bin))
+             tn_wait("proto set binary mode");
+        }
+#ifdef IKS_OPTION
+#ifdef CK_XYZ
+        if (protocol != PROTO_K) {     /* Non-Kermit protocol selected */
+            if (TELOPT_U(TELOPT_KERMIT) &&
+                TELOPT_SB(TELOPT_KERMIT).kermit.u_start) {
+                iks_wait(KERMIT_REQ_STOP,0); /* Stop the other Server */
+               /* _u_start = 1; */
+            }
+            if (TELOPT_ME(TELOPT_KERMIT) &&
+                TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
+                tn_siks(KERMIT_STOP);  /* I'm not servering */
+               TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
+               _me_start = 1;
+            }
+        } else
+#endif /* CK_XYZ */
+        if (sstate == 'x' || sstate == 'v') { /* Responding to a request */
+            if (!inserver && TELOPT_U(TELOPT_KERMIT) &&
+                TELOPT_SB(TELOPT_KERMIT).kermit.u_start) {
+                iks_wait(KERMIT_REQ_STOP,0); /* Stop the other Server */
+               /* _u_start = 1; */
+            }
+            if (TELOPT_ME(TELOPT_KERMIT) &&
+                !TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
+                tn_siks(KERMIT_START); /* Send Kermit-Server Start */
+               TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 1;
+            }
+        } else {                       /* Initiating a request */
+            if (TELOPT_ME(TELOPT_KERMIT) &&
+                TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
+                tn_siks(KERMIT_STOP);  /* I'm not servering */
+               TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
+               _me_start = 1;
+            }
+            if (TELOPT_U(TELOPT_KERMIT) &&
+               !TELOPT_SB(TELOPT_KERMIT).kermit.u_start) {
+               /* Send Req-Server-Start */
+                if (!iks_wait(KERMIT_REQ_START,0)) {
+                    if (sstate != 's') {
+                       success = 0;    /* Other Kermit refused to serve */
+                       if (local)
+                         printf("A Kermit Server is not available\r\n");
+                       debug(F110,"proto()",
+                             "A Kermit Server is not available",0);
+                       tlog(F110,"IKS client/server failure",
+                             "A Kermit Server is not available",0);
+                       goto xxprotox;
+                    }
+               }
+            }
+        }
+#endif /* IKS_OPTION */
+#ifdef CK_ENCRYPTION
+        if (tn_no_encrypt_xfer && !(sstelnet || inserver)) {
+            ck_tn_enc_stop();
+        }
+#endif /* CK_ENCRYPTION */
+    }
+#endif /* TNCODE */
+
+    if (!xfrint) connoi();
+    xxproto();                         /* Call the real protocol function */
+
+#ifdef IKS_OPTION
+  xxprotox:
+#endif /* IKS_OPTION */
+    xferstat = success;                        /* Remember transfer status */
+    kactive = 0;
+
+#ifdef TNCODE
+#ifdef CK_ENCRYPTION
+        if (tn_no_encrypt_xfer && !(sstelnet || inserver)) {
+            ck_tn_enc_start();
+        }
+#endif /* CK_ENCRYPTION */
+#ifdef IKS_OPTION
+    if (TELOPT_ME(TELOPT_KERMIT) &&
+        TELOPT_SB(TELOPT_KERMIT).kermit.me_start && !_me_start) {
+        tn_siks(KERMIT_STOP);          /* Server is stopped */
+       TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
+    }
+#endif /* IKS_OPTION */
+    if (is_tn && tn_b_xfer && !(sstelnet || inserver)) {
+        /* if we negotiated Binary mode try to reset it */
+        if (!_u_bin) {
+            /* Check to see if the state changed during the transfer */
+           if (TELOPT_U(TELOPT_BINARY)) {
+               tn_sopt(DONT,TELOPT_BINARY);
+               TELOPT_UNANSWERED_DONT(TELOPT_BINARY) = 1;
+           } else
+             _u_bin = 1;               /* So we don't call tn_wait() */
+        }
+        if (!_me_bin) {
+            /* Check to see if the state changed during the transfer */
+           if (TELOPT_ME(TELOPT_BINARY)) {
+               tn_sopt(WONT,TELOPT_BINARY);
+               TELOPT_UNANSWERED_WONT(TELOPT_BINARY) = 1;
+           } else
+             _me_bin = 1;              /* So we don't call tn_wait() */
+       }
+       if (!(_me_bin && _u_bin))
+         tn_wait("proto reset binary mode");
+    }
+#endif /* TNCODE */
+
+#ifdef PATTERNS
+    patterns = pa_save;
+#endif /* PATTERNS */
+    filepeek = scan_save;
+
+#ifdef STREAMING
+    streaming = 0;
+    /* streamok = 0; */
+#endif /* STREAMING */
+#ifdef COMMENT
+#ifdef CK_SPEED
+    for (i = 0; i < 256; i++)
+      ctlp[i] = s_ctlp[i];
+    f_ctlp = 0;
+#endif /* CK_SPEED */
+#endif /* COMMENT */
+    urclear = 0;
+    if (!success) {
+       xitsta |= (what & W_KERMIT);
+       tlog(F110," failed:",(char *)epktmsg,0);
+    }
+    debug(F111,"proto xferstat",epktmsg,xferstat);
+    slostart = ss_save;
+    if (s_timint > -1) {               /* Because of REMOTE SET */
+       timint = s_timint;
+       s_timint = -1;
+    }
+    recursive = r_save;
+    fnspath = p_save;
+    if (c_save > -1) {                 /* Because of REMOTE SET */
+       bctr = c_save;
+       c_save = -1;
+    }
+    fncnv   = f_save;
+    binary  = b_save;
+#ifdef PIPESEND
+    pipesend = 0;                      /* Next time might not be pipesend */
+#endif /* PIPESEND */
+#ifndef NOLOCAL
+#ifdef OS2
+    cursorena[vmode] = cursor_save;
+    term_io = term_io_save;
+    display_demo = 1;
+#endif /* OS2 */
+#endif /* NOLOCAL */
+}
+
+static VOID
+xxproto() {
+    int x;
+    long lx;
+#ifdef CK_XYZ
+#ifdef XYZ_INTERNAL
+_PROTOTYP( int pxyz, (int) );
+#endif /* XYZ_INTERNAL */
+#endif /* CK_XYZ */
+
+    char xss[2];                       /* String representation of sstate */
+    xss[0] = sstate;
+    xss[1] = NUL;
+    s_timint = timint;
+
+    debug(F101,"xxproto entry justone","",justone);
+    success = 0;
+
+    retrieve = 0;                      /* Reset these ... */
+    reget = 0;
+    opkt = 0;
+
+    if (local && ttchk() < 0) {                /* Giving BYE or FIN */
+       if (bye_active) {               /* but there is no connection */
+           ttclos(0);
+           success = 1;
+           return;
+       }
+       /* Ditto for any REMOTE command */
+       if (sstate == 'g' && cmarg ) {
+           if (*cmarg == 'L' || *cmarg == 'F' || *cmarg == 'X')
+             success = 1;
+           else
+             printf("?No connection\r\n");
+           return;
+       }
+    }
+
+/* Set up the communication line for file transfer. */
+/* NOTE: All of the xxscreen() calls prior to the wart() invocation */
+/* could just as easily be printf's or, for that matter, hints. */
+
+    if (local && (speed < 0L) && (network == 0)) {
+       xxscreen(SCR_EM,0,0L,"Sorry, you must 'set speed' first");
+       return;
+    }
+    x = -1;
+    if (ttopen(ttname,&x,mdmtyp,cdtimo) < 0) {
+       debug(F111,"failed: proto ttopen local",ttname,local);
+       xxscreen(SCR_EM,0,0L,"Can't open line");
+       return;
+    }
+    if (x > -1) local = x;
+    debug(F111,"proto ttopen local",ttname,local);
+
+    lx = (local && !network) ? speed : -1;
+#ifdef NETCONN
+#ifdef CK_SPEED
+    if (is_tn) {
+       ctlp[(unsigned)255] = ctlp[CR] = 1;
+       if (parity == 'e' || parity == 'm') ctlp[127] = 1;
+       if (flow == FLO_XONX) {         /* Also watch out for Xon/Xoff */
+           ctlp[17] = ctlp[19] = 1;
+           ctlp[17+128] = ctlp[19+128] = 1;
+       }
+    }
+#endif /* CK_SPEED */
+#endif /* NETCONN */
+    if (ttpkt(lx,flow,parity) < 0) {   /* Put line in packet mode, */
+       xxscreen(SCR_EM,0,0L,"Can't condition line");
+       return;
+    }
+    if (local && !network && carrier != CAR_OFF) {
+       int x;                          /* Serial connection */
+       x = ttgmdm();                   /* with carrier checking */
+       if (x > -1) {
+           if (!(x & BM_DCD)) {
+               debug(F101,"proto ttgmdm","",0);
+               xxscreen(SCR_EM,0,0L,"Carrier required but not detected");
+               return;
+           }
+       }
+    }
+    /* Send remote side's "receive" or "server" startup string, if any */
+    if (local && ckindex((char *)xss,"srgcjhk",0,0,1)) {
+       char *s = NULL;
+        if (
+#ifdef IKS_OPTION
+           /* Don't send auto-blah string if we know other side is serving */
+           !TELOPT_U(TELOPT_KERMIT) ||
+           !TELOPT_SB(TELOPT_KERMIT).kermit.u_start
+#else
+           1
+#endif /* IKS_OPTION */
+           ) {
+           if (sstate == 's') {        /* Sending file(s) */
+               s = binary ? ptab[protocol].h_b_init : ptab[protocol].h_t_init;
+           } else if (protocol == PROTO_K) { /* Command for server */
+               s = ptab[protocol].h_x_init;
+           }
+       }
+#ifdef CK_SPEED
+#ifndef UNPREFIXZERO
+       if (protocol == PROTO_K)        /* Because of C-strings... */
+         ctlp[0] = 1;
+#endif /* UNPREFIXZERO */
+#endif /* CK_SPEED */
+       if (s) if (*s) {                /* If we have a command to send... */
+           char tmpbuf[356];
+           int tmpbufsiz = 356;
+           int stuff = -1, stuff2 = -1, len = 0;
+           extern int tnlm;
+           if (sstate == 's') {        /* Sending file(s) */
+#ifdef CK_XYZ
+               if (protocol == PROTO_X) {
+                   char * s2;
+                   s2 = cmarg2[0] ? cmarg2 : cmarg;
+                   if ((int)strlen(s) + (int)strlen(s2) + 4 < 356)
+                     sprintf(tmpbuf, s, s2);
+                   else
+                     tmpbuf[0] = NUL;
+               } else {
+#endif /* CK_XYZ */
+                   ckmakmsg(tmpbuf, 356, s, NULL, NULL, NULL);
+#ifdef CK_XYZ
+               }
+#endif /* CK_XYZ */
+           } else {                    /* Command for server */
+               ckstrncpy(tmpbuf,s,356);
+           }
+           ckstrncat(tmpbuf, "\015",sizeof(tmpbuf));
+           if (tnlm)                   /* TERMINAL NEWLINE ON */
+             stuff = LF;               /* Stuff LF */
+#ifdef TNCODE
+           /* TELNET NEWLINE MODE */
+           if (is_tn) {
+               switch (TELOPT_ME(TELOPT_BINARY) ? tn_b_nlm : tn_nlm) {
+                 case TNL_CR:
+                   break;
+                 case TNL_CRNUL:
+                   break;
+                 case TNL_CRLF:
+                   stuff2 = stuff;
+                   stuff = LF;
+                   break;
+               }
+           }
+#endif /* TNCODE */
+
+#ifdef NETCONN
+#ifdef TCPSOCKET
+#ifdef RLOGCODE
+           if (network && ttnproto == NP_RLOGIN) {
+               switch (tn_b_nlm) { /* Always BINARY */
+                 case TNL_CR:
+                   break;
+                 case TNL_CRNUL:
+                   stuff2 = stuff;
+                   stuff  = NUL;
+                   break;
+                 case TNL_CRLF:
+                   stuff2 = stuff;
+                   stuff = LF;
+                   break;
+               }
+           }
+#endif /* RLOGCODE */
+#endif /* TCPSOCKET */
+#endif /* NETCONN */
+
+           len = strlen(tmpbuf);
+           if (stuff >= 0 && len < tmpbufsiz - 1) {
+               tmpbuf[len++] = stuff;
+               if (stuff2 >= 0 && len < tmpbufsiz - 1)
+                 tmpbuf[len++] = stuff2;
+               tmpbuf[len] = NUL;
+           }
+           ttol((CHAR *)tmpbuf,len);
+           if (protocol == PROTO_K)    /* Give remote Kermit time to start */
+             msleep(400);
+       }
+    }
+
+#ifdef CK_XYZ
+    if (protocol != PROTO_K) {         /* Non-Kermit protocol selected */
+       char tmpbuf[356];
+       int tmpbufsiz = 356;
+       char * s = "";
+
+#ifdef CK_TMPDIR
+       if (sstate == 'v') {            /* If receiving and... */
+           if (dldir && !f_tmpdir) {   /* if they have a download directory */
+               if (s = zgtdir()) {     /* Get current directory */
+                   if (zchdir(dldir)) { /* Change to download directory */
+                       ckstrncpy(savdir,s,TMPDIRLEN);
+                       f_tmpdir = 1;   /* Remember that we did this */
+                   }
+               }
+           }
+       }
+#endif /* CK_TMPDIR */
+
+#ifdef XYZ_INTERNAL                    /* Internal */
+       success = !pxyz(sstate);
+#else
+#ifdef CK_REDIR                                /* External */
+       switch (sstate) {
+         case 's':                     /* 'Tis better to SEND... */
+           s = binary ? ptab[protocol].p_b_scmd : ptab[protocol].p_t_scmd;
+           break;
+         case 'v':                     /* ... than RECEIVE */
+           s = binary ? ptab[protocol].p_b_rcmd : ptab[protocol].p_t_rcmd;
+           break;
+       }
+       if (!s) s = "";
+       if (*s) {
+           if (sstate == 's') {
+               if ((int)strlen(s) + (int)strlen(fspec) < tmpbufsiz) {
+                   sprintf(tmpbuf,s,fspec); /* safe (prechecked) */
+                   tlog(F110,"Sending",fspec,0L);
+               }
+           } else {
+               if ((int)strlen(s) + (int)strlen(cmarg2) < tmpbufsiz) {
+                   sprintf(tmpbuf,s,cmarg2); /* safe (prechecked) */
+                   tlog(F110,"Receiving",cmarg2,0L);
+               }
+           }
+           tlog(F110," via external protocol:",tmpbuf,0);
+           debug(F110,"ckcpro ttruncmd",tmpbuf,0);
+           success = ttruncmd(tmpbuf);
+           tlog(F110," status:",success ? "OK" : "FAILED", 0);
+       } else {
+           printf("?Sorry, no external protocol defined for %s\r\n",
+                  ptab[protocol].p_name
+                  );
+       }
+#else
+       printf(
+"Sorry, only Kermit protocol is supported in this version of Kermit\n"
+              );
+#endif /* CK_REDIR */
+#endif /* XYZ_INTERNAL */
+       return;
+    }
+#endif /* CK_XYZ */
+
+#ifdef NTSIGX
+    conraw();
+    connoi();
+#else
+    if (!local)
+      connoi();                                /* No console interrupts if remote */
+#endif /* NTSIG */
+
+    kactive = 1;
+    if (sstate == 'x') {               /* If entering server mode, */
+       extern int howcalled;
+       server = 1;                     /* set flag, */
+       debug(F101,"server backgrd","",backgrd);
+       debug(F101,"server quiet","",quiet);
+       debug(F100,"SHOULD NOT SEE THIS IF IN BACKGROUND!","",0);
+       if (howcalled == I_AM_SSHSUB) { /* and issue appropriate message. */
+           ttol((CHAR *)"KERMIT READY TO SERVE...\015\012",26);
+       } else if (!local) {
+           if (!quiet && !backgrd
+#ifdef IKS_OPTION
+                && !TELOPT_ME(TELOPT_KERMIT) /* User was told by negotiation */
+#endif /* IKS_OPTION */
+               ) {
+               conoll(srvtxt);
+               conoll("KERMIT READY TO SERVE...");
+           }
+       } else {
+           conol("Entering server mode on ");
+           conoll(ttname);
+           conoll("Type Ctrl-C to quit.");
+           if (srvdis) intmsg(-1L);
+#ifdef TCPSOCKET
+#ifndef NOLISTEN
+           if (network && tcpsrfd > 0)
+             ttol((CHAR *)"KERMIT READY TO SERVE...\015\012",26);
+#endif /* NOLISTEN */
+#endif /* TCPSOCKET */
+       }
+    } else
+      server = 0;
+#ifdef VMS
+    if (!quiet && !backgrd)    /* So message doesn't overwrite prompt */
+      conoll("");
+    if (local) conres();       /* So Ctrl-C will work */
+#endif /* VMS */
+/*
+  If in remote mode, not shushed, not in background, and at top command level,
+  issue a helpful message telling what to do...
+*/
+    if (!local && !quiet && !backgrd) {
+       if (sstate == 'v') {
+           conoll("Return to your local Kermit and give a SEND command.");
+           conoll("");
+           conoll("KERMIT READY TO RECEIVE...");
+       } else if (sstate == 's') {
+           conoll("Return to your local Kermit and give a RECEIVE command.");
+           conoll("");
+           conoll("KERMIT READY TO SEND...");
+       } else if ( sstate == 'g' || sstate == 'r' || sstate == 'h' ||
+                   sstate == 'j' || sstate == 'c' ) {
+           conoll("Return to your local Kermit and give a SERVER command.");
+           conoll("");
+           conoll((sstate == 'r' || sstate == 'j' || sstate == 'h') ?
+                  "KERMIT READY TO GET..." :
+                  "KERMIT READY TO SEND SERVER COMMAND...");
+       }
+    }
+#ifdef COMMENT
+    if (!local) sleep(1);
+#endif /* COMMENT */
+/*
+  The 'wart()' function is generated by the wart program.  It gets a
+  character from the input() routine and then based on that character and
+  the current state, selects the appropriate action, according to the state
+  table above, which is transformed by the wart program into a big case
+  statement.  The function is active for one transaction.
+*/
+    rtimer();                          /* Reset elapsed-time timer */
+#ifdef GFTIMER
+    rftimer();
+#endif /* GFTIMER */
+    resetc();                          /* & other per-transaction counters. */
+
+    debug(F101,"proto calling wart, justone","",justone);
+
+    wart();                            /* Enter the state table switcher. */
+/*
+  Note: the following is necessary in case we have just done a remote-mode
+  file transfer, in which case the controlling terminal modes have been
+  changed by ttpkt().  In particular, special characters like Ctrl-C and
+  Ctrl-\ might have been turned off (see ttpkt).  So this call to ttres() is
+  essential.  IMPORTANT: restore interrupt handlers first, otherwise any
+  terminal interrupts that occur before this is done in the normal place
+  later will cause a crash.
+*/
+#ifdef OS2
+    ttres();                           /* Reset the communication device */
+#else
+    if (!local) {
+       setint();                       /* Arm interrupt handlers FIRST */
+       msleep(500);
+       ttres();                        /* Then restore terminal. */
+    }
+#endif /* OS2 */
+    xxscreen(SCR_TC,0,0L,"");          /* Transaction complete */
+    x = quiet;
+    quiet=1;
+    clsif();                           /* Failsafe in case we missed */
+    clsof(1);                          /* a case in the state machine. */
+    quiet = x;
+
+    if (server) {                      /* Back from packet protocol. */
+       if (!quiet && !backgrd
+#ifdef IKSD
+           && !inserver
+#endif /* IKSD */
+           ) {                         /* Give appropriate message */
+           conoll("");
+           conoll("C-Kermit server done");
+        }
+        server = 0;                    /* Not a server any more */
+    }
+}
+
+/*  S G E T I N I T  --  Handle incoming GET-Class packets  */
+
+/*
+  Returns:
+   -1: On error
+    0: GET packet processed OK - ready to Send.
+    1: Extended GET processed OK - wait for another.
+*/
+static int
+sgetinit(reget,xget) int reget, xget; {        /* Server end of GET command */
+    char * fs = NULL;                  /* Pointer to filespec */
+    int i, n, done = 0;
+#ifdef PIPESEND
+    extern int usepipes, pipesend;
+#endif /* PIPESEND */
+    extern int nolinks;
+
+    if (!ENABLED(en_get)) {            /* Only if not disabled!  */
+       errpkt((CHAR *)"GET disabled");
+       return(-1);
+    }
+
+    /* OK to proceed */
+
+    nolinks = recursive;
+    filcnt = 0;
+
+#ifdef WHATAMI
+    /* If they are alike this was already done in whoarewe() */
+    debug(F101,"sgetinit whatru","",whatru);
+    if (whatru & WMI_FLAG) {           /* Did we get WHATAMI info? */
+       debug(F101,"sgetinit binary (1)","",binary);
+#ifdef VMS
+       if (binary != XYFT_I && binary != XYFT_L)
+#else
+#ifdef OS2
+         if (binary != XYFT_L)
+#endif /* OS2 */
+#endif /* VMS */
+           binary = (whatru & WMI_FMODE) ? /* Yes, set file type */
+             XYFT_B : XYFT_T;  /* automatically */
+       debug(F101,"sgetinit binary (2)","",binary);
+       if (!wearealike)
+         fncnv = (whatru & WMI_FNAME) ? 1 : 0; /* And name conversion */
+    }
+#endif /* WHATAMI */
+
+    fs = (char *)srvcmd;
+    srvptr = srvcmd;                   /* Point to server command buffer */
+    decode(rdatap,putsrv,0);           /* Decode the GET command into it */
+    /* Accept multiple filespecs */
+    cmarg2 = "";                       /* Don't use cmarg2 */
+    cmarg = "";                                /* Don't use cmarg */
+
+    done = 1;                          /* Only 1 packet needed... */
+    if (xget) {                                /* Special decoding for Extended GET */
+       char L, next, c;                /* PLV items */
+       int len, val;                   /* More PLV items */
+       char * p = (char *)srvcmd;      /* String to decode */
+
+       done = 0;                       /* Maybe more packets needed */
+       fs = NULL;                      /* We don't know the filespec yet */
+       c = *p++;                       /* Get first parameter */
+
+       while (c) {                     /* For all parameters... */
+           debug(F000,"sgetinit c","",c);
+           L = *p++;                   /* Get length */
+           if (L >= SP)                /* Decode length */
+             len = xunchar(L);
+           else if (c == '@') {        /* Allow missing EOP length field */
+               len = 0;
+           } else {
+               len = (xunchar(*p++) * 95);
+               len += xunchar(*p++);
+           }
+           debug(F101,"sgetinit len","",len);
+           next = *(p+len);            /* Get next parameter */
+           *(p+len) = NUL;             /* Zero it out to terminal value */
+           debug(F110,"sgetinit p",p,0);
+           switch (c) {                /* Do the parameter */
+             case 'O':                 /* GET Options */
+               val = atoi(p);          /* Convert to int */
+               debug(F101,"sgetinit O val","",val);
+               if (val & GOPT_DEL) moving = 1;
+               if (val & GOPT_RES) reget = 1;
+               if (val & GOPT_REC) {
+                   recursive = 1;
+                   nolinks = 2;
+                   if (fnspath == PATH_OFF)
+                     fnspath = PATH_REL;
+               }
+               break;
+             case 'M':                 /* Transfer Mode */
+               val = atoi(p);
+               debug(F101,"sgetinit M val","",val);
+               if (val < 1)
+                 break;
+               patterns = 0;           /* Takes precedence over patterns */
+               filepeek = 0;           /* and FILE SCAN */
+               if (val == GMOD_TXT) binary = XYFT_T; /* Text */
+               if (val == GMOD_BIN) binary = XYFT_B; /* Binary */
+               if (val == GMOD_LBL) binary = XYFT_L; /* Labeled */
+               break;
+             case 'F':                 /* Filename */
+               fs = p;
+               debug(F110,"sgetinit filename",fs,0);
+               break;
+             case '@':                 /* End Of Parameters */
+               done = 1;
+               debug(F100,"sgetinit EOP","",0);
+               break;
+             default:
+               errpkt((CHAR *)"Unknown GET Parameter");
+               debug(F100,"sgetinit unknown parameter","",0);
+               return(-1);
+           }
+           p += (len + 1);
+           c = next;
+       }
+    }
+    if (!fs) fs = "";                  /* A filename is required */
+    if (*fs) {
+       havefs = 1;
+       n = 0;                          /* Check for quoted name */
+       if ((n = strlen(fs)) > 1) {
+           /* Note: this does not allow for multiple quoted names */
+           if ((fs[0] == '{' && fs[n-1] == '}') ||
+               (fs[0] == '"' && fs[n-1] == '"')) {
+               fs[n-1] = '\0';
+               fs++;
+               debug(F111,"sgetinit unquoted filename",fs,n);
+           } else
+             n = 0;                    /* This means no quoting */
+       }
+
+#ifdef PIPESEND
+       debug(F111,"sgetinit",fs,usepipes);
+       if (usepipes && ENABLED(en_hos) && *fs == '!') {
+           cmarg = fs + 1;             /* Point past the bang */
+           *fs = NUL;
+           nfils = -1;
+           pipesend = 1;
+           debug(F111,"sgetinit pipesend",cmarg,pipesend);
+       }
+       if (!pipesend) {                /* If it's not a pipe */
+#endif /* PIPESEND */
+           if (n == 0) {               /* If the name was not quoted */
+#ifndef NOMSEND
+               nfils = fnparse(fs);    /* Allow it to be a list of names */
+               debug(F111,"sgetinit A",fs,nfils);
+#ifdef COMMENT
+/* This doesn't work if a GET-PATH is set. */
+               if (nfils == 1 && !iswild(fs)) { /* Single file */
+                   char * m;
+                   if ((x = zchki(fs)) < 0) { /* Check if it's sendable */
+                       switch (x) {
+                         case -1: m = "File not found"; break;
+                         case -2: m = "Not a regular file"; break;
+                         case -3: m = "Read access denied"; break;
+                       }
+                       errpkt((CHAR *)m);
+                       return(-1);
+                   }
+               }
+#endif /* COMMENT */
+           } else {                    /* If it was quoted */
+#endif /* NOMSEND */
+               nzxopts = 0;
+#ifdef UNIXOROSK
+               if (matchdot)  nzxopts |= ZX_MATCHDOT;
+#endif /* UNIXOROSK */
+               if (recursive) nzxopts |= ZX_RECURSE;
+               /* Treat as a single filespec */
+               nfils = 0 - nzxpand(fs,nzxopts);
+               debug(F111,"sgetinit B",fs,nfils);
+               cmarg = fs;
+           }
+#ifdef PIPESEND
+       }
+#endif /* PIPESEND */
+    }
+    if (!done) {                       /* Need more O packets... */
+       debug(F100,"sgetinit O-Packet TBC","",0); /* To Be Continued */
+       return(1);
+    }
+    debug(F100,"sgetinit O-Packet done - havefs","",havefs);
+    if (!havefs) {                     /* Done - make sure we have filename */
+       errpkt((CHAR *)"GET without filename");
+       return(-1);
+    }
+    freerpkt(winlo);
+    winlo = 0;                         /* Back to packet 0 again. */
+    debug(F101,"sgetinit winlo","",winlo);
+    nakstate = 0;                      /* Now I'm the sender! */
+    if (reget) sendmode = SM_RESEND;
+    if (sinit() > 0) {                 /* Send Send-Init */
+#ifdef STREAMING
+       if (!streaming)
+#endif /* STREAMING */
+         timint = chktimo(rtimo,timef); /* Switch to per-packet timer */
+       return(0);                      /* If successful, switch state */
+    } else return(-1);                 /* Else back to server command wait */
+}
+
+#else  /* NOXFER */
+
+#include "ckcdeb.h"
+
+VOID
+proto() {
+    extern int success;
+    success = 0;
+}
+#endif /* NOXFER */
index cd9d1fa..c74a1aa 100644 (file)
--- a/ckcpro.w
+++ b/ckcpro.w
@@ -1069,7 +1069,7 @@ a {
        xxscreen(SCR_TC,0,0L,"");       /* Display */
        doclean(1);                     /* Clean up files, etc */
 #ifdef DEBUG
-       debug(F100,"C-Kermit BYE - Loggin out...","",0);
+       debug(F100,"C-Kermit BYE - Logging out...","",0);
        zclose(ZDFILE);
 #endif /* DEBUG */
 #ifdef IKSD
index dfca4f3..25ea32d 100644 (file)
@@ -1,8 +1,8 @@
 Fix spelling errors.
 Index: ckermit/ckcftp.c
 ===================================================================
---- ckermit.orig/ckcftp.c      2010-05-12 01:22:31.000000000 +0100
-+++ ckermit/ckcftp.c   2010-05-12 01:22:31.000000000 +0100
+--- ckermit.orig/ckcftp.c      2010-05-12 01:33:56.000000000 +0100
++++ ckermit/ckcftp.c   2010-05-12 01:33:59.000000000 +0100
 @@ -8623,7 +8623,7 @@
  #endif /* NOCSETS */
      "  /SERVER-RENAME:text",
@@ -14,8 +14,8 @@ Index: ckermit/ckcftp.c
      "  /TEXT",                          /* /ASCII */
 Index: ckermit/ckuus2.c
 ===================================================================
---- ckermit.orig/ckuus2.c      2010-05-12 01:22:31.000000000 +0100
-+++ ckermit/ckuus2.c   2010-05-12 01:22:31.000000000 +0100
+--- ckermit.orig/ckuus2.c      2010-05-12 01:33:56.000000000 +0100
++++ ckermit/ckuus2.c   2010-05-12 01:33:59.000000000 +0100
 @@ -3660,7 +3660,7 @@
  " ",
  "SET DIAL RETRIES <number>",
@@ -27,8 +27,8 @@ Index: ckermit/ckuus2.c
  "SET DIAL INTERVAL <number>",
 Index: ckermit/ckuker.nr
 ===================================================================
---- ckermit.orig/ckuker.nr     2010-05-12 01:27:07.000000000 +0100
-+++ ckermit/ckuker.nr  2010-05-12 01:27:46.000000000 +0100
+--- ckermit.orig/ckuker.nr     2010-05-12 01:33:59.000000000 +0100
++++ ckermit/ckuker.nr  2010-05-12 01:33:59.000000000 +0100
 @@ -879,7 +879,7 @@
  Sends all files that match.
  .TP
@@ -49,8 +49,8 @@ Index: ckermit/ckuker.nr
  Asks the server to send the given files. Synonym: G.
 Index: ckermit/ckututor.txt
 ===================================================================
---- ckermit.orig/ckututor.txt  2010-05-12 01:27:16.000000000 +0100
-+++ ckermit/ckututor.txt       2010-05-12 01:28:05.000000000 +0100
+--- ckermit.orig/ckututor.txt  2010-05-12 01:33:56.000000000 +0100
++++ ckermit/ckututor.txt       2010-05-12 01:33:59.000000000 +0100
 @@ -682,7 +682,7 @@
            SEND [ options ] filename [ as-name ]  Sends the given file.
            Synonym: S.
@@ -69,3 +69,16 @@ Index: ckermit/ckututor.txt
            point of failure.
            GET [ options ] remote-filespec Asks the server to send the
            given files. Synonym: G.
+Index: ckermit/ckcpro.w
+===================================================================
+--- ckermit.orig/ckcpro.w      2010-05-12 01:34:08.000000000 +0100
++++ ckermit/ckcpro.w   2010-05-12 01:34:11.000000000 +0100
+@@ -1069,7 +1069,7 @@
+       xxscreen(SCR_TC,0,0L,"");       /* Display */
+       doclean(1);                     /* Clean up files, etc */
+ #ifdef DEBUG
+-      debug(F100,"C-Kermit BYE - Loggin out...","",0);
++      debug(F100,"C-Kermit BYE - Logging out...","",0);
+       zclose(ZDFILE);
+ #endif /* DEBUG */
+ #ifdef IKSD