source: trunk/third/kermit/ckcpro.c @ 20085

Revision 20085, 109.2 KB checked in by zacheiss, 21 years ago (diff)
Merge with kermit 8.0.
Line 
1
2/* WARNING -- This C source program generated by Wart preprocessor. */
3/* Do not edit this file; edit the Wart-format source file instead, */
4/* and then run it through Wart to produce a new C source file.     */
5
6/* Wart Version Info: */
7char *wartv = "Wart Version 2.14, 10 Nov 1999";
8
9char *protv =                                                     /* -*-C-*- */
10"C-Kermit Protocol Module 8.0.158, 11 Sep 2002";
11
12int kactive = 0;                        /* Kermit protocol is active */
13
14#define PKTZEROHACK
15
16/* C K C P R O  -- C-Kermit Protocol Module, in Wart preprocessor notation. */
17/*
18  Author: Frank da Cruz <fdc@columbia.edu>,
19  Columbia University Academic Information Systems, New York City.
20
21  Copyright (C) 1985, 2002,
22    Trustees of Columbia University in the City of New York.
23    All rights reserved.  See the C-Kermit COPYING.TXT file or the
24    copyright text in the ckcmai.c module for disclaimer and permissions.
25*/
26#ifndef NOXFER
27#include "ckcsym.h"
28#include "ckcdeb.h"
29#include "ckcasc.h"
30#include "ckcker.h"
31#ifdef OS2
32#ifndef NT
33#define INCL_NOPM
34#define INCL_VIO                        /* Needed for ckocon.h */
35#include <os2.h>
36#undef COMMENT
37#endif /* NT */
38#include "ckocon.h"
39#endif /* OS2 */
40
41/*
42 Note -- This file may also be preprocessed by the UNIX Lex program, but
43 you must indent the above #include statements before using Lex, and then
44 restore them to the left margin in the resulting C program before compilation.
45 Also, the invocation of the "wart()" function below must be replaced by an
46 invocation  of the "yylex()" function.  It might also be necessary to remove
47 comments in the (%)(%)...(%)(%) section.
48*/
49
50/* State definitions for Wart (or Lex) */
51#define ipkt 1
52#define rfile 2
53#define rattr 3
54#define rdpkt 4
55#define ssinit 5
56#define ssfile 6
57#define ssattr 7
58#define ssdata 8
59#define sseof 9
60#define sseot 10
61#define serve 11
62#define generic 12
63#define get 13
64#define rgen 14
65#define ssopkt 15
66#define ropkt 16
67
68_PROTOTYP(static VOID xxproto,(void));
69_PROTOTYP(static VOID wheremsg,(void));
70_PROTOTYP(int wart,(void));
71_PROTOTYP(static int sgetinit,(int,int));
72_PROTOTYP(int sndspace,(int));
73
74/* External C-Kermit variable declarations */
75  extern char *versio, *srvtxt, *cmarg, *cmarg2, **cmlist, *rf_err;
76  extern char * rfspec, * sfspec, * srfspec, * rrfspec;
77  extern char * prfspec, * psfspec, * psrfspec, * prrfspec;
78  extern char *cdmsgfile[];
79  extern char * snd_move, * snd_rename, * srimsg;
80  extern char filnam[], ofilnam[], fspec[], ttname[], ofn1[];
81  extern CHAR sstate, *srvptr, *data;
82  extern int timint, rtimo, nfils, hcflg, xflg, flow, mdmtyp, network;
83  extern int oopts, omode, oname, opath, nopush, isguest, xcmdsrc, rcdactive;
84  extern int rejection, moving, fncact, bye_active, urserver, fatalio;
85  extern int protocol, prefixing, filcnt, carrier, fnspath, interrupted;
86  extern int recursive, inserver, nzxopts, idletmo, srvidl, xfrint;
87  extern struct ck_p ptab[];
88  extern int remfile, rempipe, xferstat, filestatus, wearealike, fackpath;
89  extern int patterns, filepeek, gnferror;
90  extern char * remdest;
91
92#ifdef PKTZEROHACK
93#define PKTZEROLEN 32
94static char ipktack[PKTZEROLEN];
95static int ipktlen = 0;
96#endif /* PKTZEROHACK */
97
98static int s_timint = -1;               /* For saving timeout value */
99static int myjob = 0;
100static int havefs = 0;
101#ifdef CK_LOGIN
102static int logtries = 0;
103#endif /* CK_LOGIN */
104
105static int cancel = 0;
106int fackbug = 0;
107
108#ifdef STREAMING
109extern int streaming, streamok;
110
111static VOID
112streamon() {
113    if (streamok) {
114        debug(F100,"streamon","",0);
115        streaming = 1;
116        timint = 0;                     /* No timeouts while streaming. */
117    }
118}
119
120#ifdef COMMENT                          /* (not used) */
121static VOID
122streamoff() {
123    if (streaming) {
124        debug(F100,"streamoff","",0);
125        streaming = 0;
126        timint = s_timint;              /* Restore timeout */
127    }
128}
129#endif /* COMMENT */
130#else /* STREAMING */
131#define streamon()
132#define streamoff()
133#endif /* STREAMING */
134
135#ifndef NOSPL
136_PROTOTYP( int addmac, (char *, char *) );
137_PROTOTYP( int zzstring, (char *, char **, int *) );
138#endif /* NOSPL */
139#ifndef NOICP
140_PROTOTYP( int cmdsrc, (void) );
141#endif /* NOICP */
142
143#ifndef NOSERVER
144  extern char * x_user, * x_passwd, * x_acct;
145  extern int x_login, x_logged;
146#endif /* NOSERVER */
147
148#ifdef TNCODE
149  extern int ttnproto;                  /* Network protocol */
150#endif /* TNCODE */
151
152#ifdef CK_SPEED
153  extern short ctlp[];                  /* Control-character prefix table */
154#endif /* CK_SPEED */
155
156#include "ckcnet.h"
157#ifdef TNCODE
158  extern int tn_b_nlm, tn_b_xfer, tn_nlm;
159#ifdef CK_ENCRYPTION
160  extern int tn_no_encrypt_xfer;
161#endif /* CK_ENCRYPTION */
162#endif /* TNCODE */
163
164#ifdef TCPSOCKET
165#ifndef NOLISTEN
166  extern int tcpsrfd;
167#endif /* NOLISTEN */
168#endif /* TCPSOCKET */
169
170  extern int cxseen, czseen, server, srvdis, local, displa, bctu, bctr, bctl;
171  extern int quiet, tsecs, parity, backgrd, nakstate, atcapu, wslotn, winlo;
172  extern int wslots, success, xitsta, rprintf, discard, cdtimo, keep, fdispla;
173  extern int timef, stdinf, rscapu, sendmode, epktflg, epktrcvd, epktsent;
174  extern int binary, fncnv;
175  extern long speed, ffc, crc16, calibrate, dest;
176#ifdef COMMENT
177  extern char *TYPCMD, *DIRCMD, *DIRCM2;
178#endif /* COMMENT */
179#ifndef OS2
180  extern char *SPACMD, *SPACM2, *WHOCMD;
181#endif /* OS2 */
182  extern CHAR *rdatap;
183  extern struct zattr iattr;
184
185#ifdef VMS
186  extern int batch;
187#endif /* VMS */
188
189#ifdef GFTIMER
190  extern CKFLOAT fptsecs;
191#endif /* GFTIMER */
192
193  extern CHAR *srvcmd;
194  extern CHAR *epktmsg;
195
196#ifdef CK_TMPDIR
197extern int f_tmpdir;                    /* Directory changed temporarily */
198extern char savdir[];                   /* For saving current directory */
199extern char * dldir;
200#endif /* CK_TMPDIR */
201
202  extern int query;                     /* Query-active flag */
203#ifndef NOSPL
204  extern int cmdlvl;
205  char querybuf[QBUFL+1] = { NUL, NUL }; /* QUERY response buffer */
206  char *qbufp = querybuf;               /* Pointer to it */
207  int qbufn = 0;                        /* Length of data in it */
208#else
209  extern int tlevel;
210#endif /* NOSPL */
211
212#ifndef NOICP
213  extern int escape;
214#endif /* NOICP */
215/*
216  If the following flag is nonzero when the protocol module is entered,
217  then server mode persists for exactly one transaction, rather than
218  looping until BYE or FINISH is received.
219*/
220extern int justone;
221
222static int r_save = -1;
223static int p_save = -1;
224
225/* Function to let remote-mode user know where their file(s) went */
226
227int whereflg = 1;                       /* Unset with SET XFER REPORT */
228
229static VOID
230wheremsg() {
231    extern int quiet, filrej;
232    int n;
233    n = filcnt - filrej;
234    debug(F101,"wheremsg n","",n);
235
236    debug(F110,"wheremsg prfspec",prfspec,0);
237    debug(F110,"wheremsg rfspec",rfspec,0);
238    debug(F110,"wheremsg psfspec",psfspec,0);
239    debug(F110,"wheremsg sfspec",sfspec,0);
240
241    debug(F110,"wheremsg prrfspec",prrfspec,0);
242    debug(F110,"wheremsg rrfspec",rrfspec,0);
243    debug(F110,"wheremsg psrfspec",psrfspec,0);
244    debug(F110,"wheremsg srfspec",srfspec,0);
245
246    if (!quiet && !local) {
247        if (n == 1) {
248            switch (myjob) {
249              case 's':
250                if (sfspec) {
251                    printf(" SENT: [%s]",sfspec);
252                    if (srfspec)
253                      printf(" To: [%s]",srfspec);
254                    printf(" (%s)\n", success ? "OK" : "FAILED");
255                }
256                break;
257              case 'r':
258              case 'v':
259                if (rrfspec) {
260                    printf(" RCVD: [%s]",rrfspec);
261                    if (rfspec)
262                      printf(" To: [%s]",rfspec);
263                    printf(" (%s)\n", success ? "OK" : "FAILED");
264                }
265            }
266        } else if (n > 1) {
267            switch (myjob) {
268              case 's':
269                if (sfspec) {
270                    printf(" SENT: (%d files)",n);
271                    if (srfspec)
272                      printf(" Last: [%s]",srfspec);
273                    printf(" (%s)\n", success ? "OK" : "FAILED");
274                }
275                break;
276              case 'r':
277              case 'v':
278                if (rrfspec) {
279                    printf(" RCVD: (%d files)",n);
280                    if (rfspec)
281                      printf(" Last: [%s]",rfspec);
282                    printf(" (%s)\n", success ? "OK" : "FAILED");
283                }
284            }
285        } else if (n == 0) {
286            if (myjob == 's')
287              printf(" SENT: (0 files)          \n");
288            else if (myjob == 'r' || myjob == 'v')
289              printf(" RCVD: (0 files)          \n");
290        }
291    }
292}
293
294static VOID
295rdebug() {
296    if (server)
297      debug(F111,"RESUME","server=1",justone);
298    else
299      debug(F111,"RESUME","server=0",justone);
300}
301
302/* Flags for the ENABLE and DISABLE commands */
303extern int
304  en_cpy, en_cwd, en_del, en_dir, en_fin, en_get, en_bye, en_mai, en_pri,
305  en_hos, en_ren, en_sen, en_spa, en_set, en_typ, en_who, en_ret, en_xit,
306  en_mkd, en_rmd;
307#ifndef NOSPL
308extern int en_asg, en_que;
309#endif /* NOSPL */
310extern int what, lastxfer;
311
312/* Global variables declared here */
313
314  int whatru = 0;                       /* What are you. */
315  int whatru2 = 0;                      /* What are you, cont'd. */
316
317/* Local variables */
318
319  static char vstate = 0;               /* Saved State   */
320  static char vcmd = 0;                 /* Saved Command */
321  static int reget = 0;                 /* Flag for executing REGET */
322  static int retrieve = 0;              /* Flag for executing RETRIEVE */
323  static int opkt = 0;                  /* Send Extended GET packet */
324
325  static int x;                         /* General-purpose integer */
326  static char *s;                       /* General-purpose string pointer */
327
328/* Macros - Note, BEGIN is predefined by Wart (and Lex) as "state = ", */
329/* BEGIN is NOT a GOTO! */
330#define TINIT if (tinit(1) < 0) return(-9)
331#define SERVE { TINIT; resetc(); nakstate=1; what=W_NOTHING; cmarg2=""; \
332sendmode=SM_SEND; havefs=0; recursive=r_save; fnspath=p_save; BEGIN serve; }
333#define RESUME { rdebug(); if (!server) { wheremsg(); return(0); } else \
334if (justone) { justone=0; wheremsg(); return(0); } else { SERVE; } }
335
336#ifdef GFTIMER
337#define QUIT x=quiet; quiet=1; clsif(); clsof(1); tsecs=gtimer(); \
338 fptsecs=gftimer(); quiet=x; return(success)
339#else
340#define QUIT x=quiet; quiet=1; clsif(); clsof(1); tsecs=gtimer(); quiet=x; \
341 return(success)
342#endif /* GFTIMER */
343
344/*
345  By late 1999, the big switch() statement generated from the following state
346  table began choking even gcc, so here we extract the code from the larger
347  states into static routines to reduce the size of the cases and the
348  switch() overall.  The routines follow the state table; the prototypes are
349  here.  Each of these routines simply contains the text from the
350  corresponding case, but with return(-1) added in appropriate places; see
351  instructions after the state table switcher.
352*/
353static int rc;                          /* Return code for these routines */
354static int rcv_s_pkt();                 /* Received an S packet */
355static int rcv_firstdata();             /* Received first Data packet */
356static int rcv_shortreply();            /* Short reply to a REMOTE command  */
357static int srv_query();                 /* Server answers an query */
358static int srv_copy();                  /* Server executes REMOTE COPY */
359static int srv_rename();                /* Server executes REMOTE RENAME */
360static int srv_login();                 /* Server executes REMOTE LOGIN */
361static int srv_timeout();               /* Server times out */
362
363
364#define BEGIN state =
365
366int state = 0;
367
368int
369wart()
370{
371    int c,actno;
372    extern char tbl[];
373    while (1) {
374        c = input() - 32;
375        debug(F000,"PROTO input",ckitoa(state),c+32);
376        if (c < 0 || c > 95) c = 0;
377        if ((actno = tbl[c + state*96]) != -1)
378            switch(actno) {
379case 1:
380    { TINIT;                            /* Send file(s) */
381    if (sinit() > 0) BEGIN ssinit;
382       else RESUME; }
383    break;
384case 2:
385    { TINIT; nakstate = 1; BEGIN get; }
386    break;
387case 3:
388    {                                   /* Client sends a GET command */
389    TINIT;
390    vstate = get;
391    reget = 0;
392    retrieve = 0;
393    opkt = 0;
394    vcmd = 0;
395#ifdef PKTZEROHACK
396    ipktack[0] = NUL;
397#endif /* PKTZEROHACK */
398    if (sipkt('I') >= 0)
399      BEGIN ipkt;
400    else
401      RESUME;
402}
403    break;
404case 4:
405    {                                   /* Client sends a RETRIEVE command */
406    TINIT;
407    vstate = get;
408    reget = 0;
409    retrieve = 1;
410    opkt = 0;
411    vcmd = 0;
412    if (sipkt('I') >= 0)
413      BEGIN ipkt;
414    else
415      RESUME;
416}
417    break;
418case 5:
419    {                                   /* Client sends a REGET command */
420    TINIT;
421    vstate = get;
422    reget = 1;
423    retrieve = 0;
424    opkt = 0;
425    vcmd = 0;
426    if (sipkt('I') >= 0)
427      BEGIN ipkt;
428    else
429      RESUME;
430}
431    break;
432case 6:
433    {                                   /* Client sends Extended GET Packet */
434    TINIT;
435    vstate = get;
436    reget = oopts & GOPT_RES;
437    retrieve = oopts & GOPT_DEL;
438    opkt = 1;
439    vcmd = 0;
440    if (sipkt('I') >= 0)
441      BEGIN ipkt;
442    else
443      RESUME;
444}
445    break;
446case 7:
447    {                                   /* Client sends a Host command */
448    TINIT;
449    vstate = rgen;
450    vcmd = 'C';
451    if (sipkt('I') >= 0)
452      BEGIN ipkt;
453    else
454      RESUME;
455}
456    break;
457case 8:
458    { TINIT;                            /* Client sends a Kermit command */
459    vstate = rgen;
460    vcmd = 'K';
461    if (sipkt('I') >= 0)
462      BEGIN ipkt;
463    else
464      RESUME;
465}
466    break;
467case 9:
468    {                                   /* Client sends a REMOTE command */
469    TINIT;
470    vstate = rgen;
471    vcmd = 'G';
472    if (sipkt('I') >= 0)
473      BEGIN ipkt;
474    else
475      RESUME;
476}
477    break;
478case 10:
479    {                                   /* Enter server mode */
480    int x;
481    x = justone;
482    if (!ENABLED(en_del)) {             /* If DELETE is disabled */
483        if (fncact == XYFX_B ||         /* undo any file collision action */
484            fncact == XYFX_U ||         /* that could result in deletion or */
485            fncact == XYFX_A ||         /* modification of existing files. */
486            fncact == XYFX_X) {
487#ifndef NOICP
488            extern int g_fncact;
489            g_fncact = fncact;          /* Save current setting */
490#endif /* NOICP */
491            fncact = XYFX_R;            /* Change to RENAME */
492            debug(F101,"server DELETE disabled so fncact RENAME","",fncact);
493        }
494    }
495    SERVE;                              /* tinit() clears justone... */
496    justone = x;
497#ifdef IKSDB
498    if (ikdbopen) slotstate(what, "SERVER", "", "");
499#endif /* IKSDB */
500}
501    break;
502case 11:
503    {
504    int b1 = 0, b2 = 0;
505    if (!data) TINIT;                   /* "ABEND" -- Tell other side. */
506#ifndef pdp11
507    if (epktflg) {                      /* If because of E-PACKET command */
508        b1 = bctl; b2 = bctu;           /* Save block check type */
509        bctl = bctu = 1;                /* set it to 1 */
510    }
511#endif /* pdp11 */
512    errpkt((CHAR *)"User cancelled");   /* Send the packet */
513#ifndef pdp11
514    if (epktflg) {                      /* Restore the block check */
515        epktflg = 0;
516        bctl = b1; bctu = b2;
517    }
518#endif /* pdp11 */
519    success = 0;
520    return(0);                          /* Return from protocol. */
521}
522    break;
523case 12:
524    {           /* Receive Send-Init packet. */
525    rc = rcv_s_pkt();
526    cancel = 0;                         /* Reset cancellation counter */
527    debug(F101,"rcv_s_pkt","",rc);
528    if (rc > -1) return(rc);            /* (see below) */
529}
530    break;
531case 13:
532    {                           /* Get ack for I-packet */
533    int x = 0;
534#ifdef PKTZEROHACK
535    ckstrncpy(ipktack,(char *)rdatap,PKTZEROLEN); /* Save a copy of the ACK */
536    ipktlen = strlen(ipktack);
537#endif /* PKTZEROHACK */
538    spar(rdatap);                       /* Set parameters */
539    cancel = 0;
540    winlo = 0;                          /* Set window-low back to zero */
541    debug(F101,"<ipkt>Y winlo","",winlo);
542    urserver = 1;                       /* So I know I'm talking to a server */
543    if (vcmd) {                         /* If sending a generic command */
544        if (tinit(0) < 0) return(-9);   /* Initialize many things */
545        x = scmd(vcmd,(CHAR *)cmarg);   /* Do that */
546        if (x >= 0) x = 0;              /* (because of O-Packet) */
547        debug(F101,"proto G packet scmd","",x);
548        vcmd = 0;                       /* and then un-remember it. */
549    } else if (vstate == get) {
550        debug(F101,"REGET sstate","",sstate);
551        x = srinit(reget, retrieve, opkt); /* GET or REGET, etc */
552    }
553    if (x < 0) {                        /* If command was too long */
554        if (!srimsg)
555          srimsg = "Error sending string";
556        errpkt((CHAR *)srimsg);         /* cancel both sides. */
557        success = 0;
558        RESUME;
559    } else if (x > 0) {                 /* Need to send more O-Packets */
560        BEGIN ssopkt;
561    } else {
562        rtimer();                       /* Reset the elapsed seconds timer. */
563#ifdef GFTIMER
564        rftimer();
565#endif /* GFTIMER */
566        winlo = 0;                      /* Window back to 0, again. */
567        debug(F101,"<ipkt>Y vstate","",vstate);
568        nakstate = 1;                   /* Can send NAKs from here. */
569        BEGIN vstate;                   /* Switch to desired state */
570    }
571}
572    break;
573case 14:
574    {                           /* Got ACK to O-Packet */
575    debug(F100,"CPCPRO <ssopkt>Y","",0);
576    x = sopkt();
577    debug(F101,"CPCPRO <ssopkt>Y x","",x);
578    if (x < 0) {                        /* If error */
579        errpkt((CHAR *)srimsg);         /* cancel both sides. */
580        success = 0;
581        RESUME;
582    } else if (x == 0) {                /* This was the last O-Packet */
583        rtimer();                       /* Reset the elapsed seconds timer. */
584#ifdef GFTIMER
585        rftimer();
586#endif /* GFTIMER */
587        winlo = 0;                      /* Window back to 0, again. */
588        debug(F101,"<ssopkt>Y winlo","",winlo);
589        nakstate = 1;                   /* Can send NAKs from here. */
590        BEGIN vstate;                   /* Switch to desired state */
591    }
592    debug(F101,"CPCPRO <ssopkt>Y not changing state","",x);
593}
594    break;
595case 15:
596    {                           /* Ignore Error reply to I packet */
597    int x = 0;
598    winlo = 0;                          /* Set window-low back to zero */
599    debug(F101,"<ipkt>E winlo","",winlo);
600    if (vcmd) {                         /* In case other Kermit doesn't */
601        if (tinit(0) < 0) return(-9);
602        x = scmd(vcmd,(CHAR *)cmarg);   /* understand I-packets. */
603        if (x >= 0) x = 0;              /* (because of O-Packet) */
604        vcmd = 0;                       /* Otherwise act as above... */
605    } else if (vstate == get) x = srinit(reget, retrieve, opkt);
606    if (x < 0) {                        /* If command was too long */
607        errpkt((CHAR *)srimsg);         /* cancel both sides. */
608        success = 0;
609        RESUME;
610    } else if (x > 0) {                 /* Need to send more O-Packets */
611        BEGIN ssopkt;
612    } else {
613        freerpkt(winlo);                /* Discard the Error packet. */
614        debug(F101,"<ipkt>E winlo","",winlo);
615        winlo = 0;                      /* Back to packet 0 again. */
616        nakstate = 1;                   /* Can send NAKs from here. */
617        BEGIN vstate;
618    }
619}
620    break;
621case 16:
622    {           /* Resend of previous I-pkt ACK, same seq number */
623    freerpkt(0);                        /* Free the ACK's receive buffer */
624    resend(0);                          /* Send the GET packet again. */
625}
626    break;
627case 17:
628    {                           /* Get I-packet */
629#ifndef NOSERVER
630    spar(rdatap);                       /* Set parameters from it */
631    ack1(rpar());                       /* Respond with our own parameters */
632#ifdef COMMENT
633    pktinit();                          /* Reinitialize packet numbers */
634#else
635#ifdef COMMENT
636    /* This can't be right - it undoes the stuff we just negotiated */
637    x = justone;
638    tinit(1);                           /* Reinitialize EVERYTHING */
639    justone = x;                        /* But this... */
640#else
641    tinit(0);                           /* Initialize most things */
642#endif /* COMMENT */
643#endif /* COMMENT */
644#endif /* NOSERVER */
645    cancel = 0;                         /* Reset cancellation counter */
646}
647    break;
648case 18:
649    {                           /* GET */
650#ifndef NOSERVER
651    if (x_login && !x_logged) {
652        errpkt((CHAR *)"Login required");
653        SERVE;
654    } else if (sgetinit(0,0) < 0) {
655        RESUME;
656    } else {
657#ifdef CKSYSLOG
658        if (ckxsyslog >= SYSLG_PR && ckxlogging)
659          cksyslog(SYSLG_PR, 1, "server", "GET", (char *)srvcmd);
660#endif /* CKSYSLOG */
661        BEGIN ssinit;
662    }
663#endif /* NOSERVER */
664}
665    break;
666case 19:
667    {                           /* GET /DELETE (RETRIEVE) */
668#ifndef NOSERVER
669    if (x_login && !x_logged) {
670        errpkt((CHAR *)"Login required");
671        RESUME;
672    } else if (!ENABLED(en_del)) {
673        errpkt((CHAR *)"Deleting files is disabled");
674        RESUME;
675    } else if (sgetinit(0,0) < 0) {
676        RESUME;
677    } else {
678        moving = 1;
679#ifdef CKSYSLOG
680        if (ckxsyslog >= SYSLG_PR && ckxlogging)
681          cksyslog(SYSLG_PR, 1, "server", "GET /DELETE", (char *)srvcmd);
682#endif /* CKSYSLOG */
683        BEGIN ssinit;
684    }
685#endif /* NOSERVER */
686}
687    break;
688case 20:
689    {                           /* GET /RECURSIVE */
690#ifndef NOSERVER
691    recursive = 1;                      /* Set these before sgetinit() */
692    if (fnspath == PATH_OFF)
693      fnspath = PATH_REL;               /* Don't worry, they will be */
694    if (x_login && !x_logged) {         /* reset next time through. */
695        errpkt((CHAR *)"Login required");
696        RESUME;
697    } else if (sgetinit(0,0) < 0) {
698        RESUME;
699    } else {
700#ifdef CKSYSLOG
701        if (ckxsyslog >= SYSLG_PR && ckxlogging)
702          cksyslog(SYSLG_PR, 1, "server", "GET /RECURSIVE", (char *)srvcmd);
703#endif /* CKSYSLOG */
704        BEGIN ssinit;
705    }
706#endif /* NOSERVER */
707}
708    break;
709case 21:
710    {                           /* GET /RECURSIVE /DELETE */
711#ifndef NOSERVER
712    recursive = 1;                      /* Set these before sgetinit() */
713    if (fnspath == PATH_OFF)
714      fnspath = PATH_REL;               /* Don't worry, they will be */
715    moving = 1;                         /* reset next time through. */
716    if (x_login && !x_logged) {
717        errpkt((CHAR *)"Login required");
718        RESUME;
719    } else if (!ENABLED(en_del)) {
720        errpkt((CHAR *)"Deleting files is disabled");
721        RESUME;
722    } else if (sgetinit(0,0) < 0) {
723        RESUME;
724    } else {
725#ifdef CKSYSLOG
726        if (ckxsyslog >= SYSLG_PR && ckxlogging)
727          cksyslog(SYSLG_PR,1,"server",
728                   "GET /RECURSIVE /DELETE",(char *)srvcmd);
729#endif /* CKSYSLOG */
730        BEGIN ssinit;
731    }
732#endif /* NOSERVER */
733}
734    break;
735case 22:
736    {                           /* GET /RECOVER (REGET) */
737#ifndef NOSERVER
738    if (x_login && !x_logged) {
739        errpkt((CHAR *)"Login required");
740        SERVE;
741    } else if (sgetinit(1,0) < 0) {
742        RESUME;
743    } else {
744#ifdef CKSYSLOG
745        if (ckxsyslog >= SYSLG_PR && ckxlogging)
746          cksyslog(SYSLG_PR, 1, "server", "GET /RECOVER", (char *)srvcmd);
747#endif /* CKSYSLOG */
748        BEGIN ssinit;
749    }
750#endif /* NOSERVER */
751}
752    break;
753case 23:
754    {                           /* Extended GET */
755#ifndef NOSERVER
756    if (x_login && !x_logged) {         /* (any combination of options) */
757        errpkt((CHAR *)"Login required");
758        SERVE;
759    } else if ((x = sgetinit(0,1)) < 0) {
760        debug(F101,"CKCPRO <serve>O sgetinit fail","",x);
761        RESUME;
762    } else if (x == 0) {
763        debug(F101,"CKCPRO <serve>O sgetinit done","",x);
764#ifdef CKSYSLOG
765        if (ckxsyslog >= SYSLG_PR && ckxlogging)
766          cksyslog(SYSLG_PR, 1, "server", "EXTENDED GET", (char *)srvcmd);
767#endif /* CKSYSLOG */
768        BEGIN ssinit;
769    } else {                            /* Otherwise stay in this state */
770        debug(F101,"CKCPRO <serve>O sgetinit TBC","",x);
771        ack();
772        BEGIN ropkt;
773    }
774#endif /* NOSERVER */
775}
776    break;
777case 24:
778    {
779#ifndef NOSERVER
780    if (x_login && !x_logged) {         /* (any combination of options) */
781        errpkt((CHAR *)"Login required");
782        SERVE;
783    } else if ((x = sgetinit(0,1)) < 0) {
784        debug(F101,"CKCPRO <ropkt>O sgetinit fail","",x);
785        RESUME;
786    } else if (x == 0) {
787        debug(F101,"CKCPRO <ropkt>O sgetinit done","",x);
788#ifdef CKSYSLOG
789        if (ckxsyslog >= SYSLG_PR && ckxlogging)
790          cksyslog(SYSLG_PR, 1, "server", "EXTENDED GET", (char *)srvcmd);
791#endif /* CKSYSLOG */
792        BEGIN ssinit;
793    } else {                            /* Otherwise stay in this state */
794        debug(F101,"CKCPRO <ropkt>O sgetinit TBC","",x);
795        ack();
796    }
797#endif /* NOSERVER */
798}
799    break;
800case 25:
801    {                           /* Generic server command */
802#ifndef NOSERVER
803    srvptr = srvcmd;                    /* Point to command buffer */
804    decode(rdatap,putsrv,0);            /* Decode packet data into it */
805    putsrv(NUL);                        /* Insert a couple nulls */
806    putsrv(NUL);                        /* for termination */
807    if (srvcmd[0]) {
808        sstate = srvcmd[0];             /* Set requested start state */
809        if (x_login && !x_logged &&     /* Login required? */
810            /* Login, Logout, and Help are allowed when not logged in */
811            sstate != 'I' && sstate != 'L' && sstate != 'H') {
812            errpkt((CHAR *)"Login required");
813            SERVE;
814        } else {
815            nakstate = 0;               /* Now I'm the sender. */
816            what = W_REMO;              /* Doing a REMOTE command. */
817#ifdef STREAMING
818            if (!streaming)
819#endif /* STREAMING */
820              if (timint < 1)
821                timint = chktimo(rtimo,timef); /* Switch to per-packet timer */
822            binary = XYFT_T;            /* Switch to text mode */
823            BEGIN generic;              /* Switch to generic command state */
824        }
825    } else {
826        errpkt((CHAR *)"Badly formed server command"); /* report error */
827        RESUME;                 /* & go back to server command wait */
828    }
829#endif /* NOSERVER */
830}
831    break;
832case 26:
833    {                           /* Receive Host command */
834#ifndef NOSERVER
835    if (x_login && !x_logged) {
836        errpkt((CHAR *)"Login required");
837        SERVE;
838    } else if (!ENABLED(en_hos)) {
839        errpkt((CHAR *)"REMOTE HOST disabled");
840        RESUME;
841    } else if (nopush) {
842        errpkt((CHAR *)"HOST commands not available");
843        RESUME;
844    } else {
845        srvptr = srvcmd;                /* Point to command buffer */
846        decode(rdatap,putsrv,0);        /* Decode command packet into it */
847        putsrv(NUL);                    /* Null-terminate */
848        nakstate = 0;                   /* Now sending, not receiving */
849        binary = XYFT_T;                /* Switch to text mode */
850        if (syscmd((char *)srvcmd,"")) { /* Try to execute the command */
851            what = W_REMO;              /* Doing a REMOTE command. */
852#ifdef STREAMING
853            if (!streaming)
854#endif /* STREAMING */
855              if (timint < 1)
856                timint = chktimo(rtimo,timef); /* Switch to per-packet timer */
857#ifdef CKSYSLOG
858            if (ckxsyslog >= SYSLG_PR && ckxlogging)
859              cksyslog(SYSLG_PR, 1, "server", "REMOTE HOST", (char *)srvcmd);
860#endif /* CKSYSLOG */
861            BEGIN ssinit;               /* If OK, send back its output */
862        } else {                        /* Otherwise */
863            errpkt((CHAR *)"Can't do system command"); /* report error */
864            RESUME;                     /* & go back to server command wait */
865        }
866    }
867#endif /* NOSERVER */
868}
869    break;
870case 27:
871    {                           /* Interrupted or connection lost */
872    rc = srv_timeout();
873    debug(F101,"srv_timeout","",rc);
874    if (rc > -1) return(rc);            /* (see below) */
875}
876    break;
877case 28:
878    {                           /* Server got a NAK in command-wait */
879#ifndef NOSERVER
880    errpkt((CHAR *)"Did you say RECEIVE instead of GET?");
881    RESUME;
882#endif /* NOSERVER */
883}
884    break;
885case 29:
886    {                           /* Any other command in this state */
887#ifndef NOSERVER
888    if (c != ('E' - SP) && c != ('Y' - SP)) /* except E and Y packets. */
889      errpkt((CHAR *)"Unimplemented server function");
890    /* If we answer an E with an E, we get an infinite loop. */
891    /* A Y (ACK) can show up here if we sent back a short-form reply to */
892    /* a G packet and it was echoed.  ACKs can be safely ignored here. */
893    RESUME;                             /* Go back to server command wait. */
894#endif /* NOSERVER */
895}
896    break;
897case 30:
898    {                           /* Login/Out */
899    rc = srv_login();
900    debug(F101,"<generic>I srv_login","",rc);
901    if (rc > -1) return(rc);            /* (see below) */
902}
903    break;
904case 31:
905    {                           /* Got REMOTE CD command */
906#ifndef NOSERVER
907#ifdef CKSYSLOG
908    if (ckxsyslog >= SYSLG_PR && ckxlogging)
909      cksyslog(SYSLG_PR, 1, "server", "REMOTE CD", (char *)srvcmd);
910#endif /* CKSYSLOG */
911    if (!ENABLED(en_cwd)) {
912        errpkt((CHAR *)"REMOTE CD disabled");
913        RESUME;
914    } else {
915        char * p = NULL;
916        x = cwd((char *)(srvcmd+1));    /* Try to change directory */
917#ifdef IKSDB
918        if (ikdbopen) slotstate(what,"REMOTE CD", (char *)(srvcmd+2), "");
919#endif /* IKSDB */
920        if (!x) {                       /* Failed */
921            errpkt((CHAR *)"Can't change directory");
922            RESUME;                     /* Back to server command wait */
923        } else if (x == 2) {            /* User wants message */
924            if (!ENABLED(en_typ)) {     /* Messages (REMOTE TYPE) disabled? */
925                errpkt((CHAR *)"REMOTE TYPE disabled");
926                RESUME;
927            } else {                    /* TYPE is enabled */
928                int i;
929                for (i = 0; i < 8; i++) {
930                    if (zchki(cdmsgfile[i]) > -1) {
931                        break;
932                    }
933                }
934                binary = XYFT_T;        /* Use text mode for this. */
935                if (i < 8 && sndtype(cdmsgfile[i])) { /* Have readme file? */
936                    BEGIN ssinit;       /* OK */
937                } else {                /* not OK */
938                    p = zgtdir();
939                    if (!p) p = "";
940                    success = (*p) ? 1 : 0;
941                    ack1((CHAR *)p);    /* ACK with new directory name */
942                    success = 1;
943                    RESUME;             /* wait for next server command */
944                }
945            }
946        } else {                        /* User doesn't want message */
947            p =zgtdir();
948            if (!p) p = "";
949            success = (*p) ? 1 : 0;
950            ack1((CHAR *)p);
951            success = 1;
952            RESUME;                     /* Wait for next server command */
953        }
954    }
955#endif /* NOSERVER */
956}
957    break;
958case 32:
959    {                           /* Got REMOTE PWD command */
960#ifndef NOSERVER
961#ifdef CKSYSLOG
962    if (ckxsyslog >= SYSLG_PR && ckxlogging)
963      cksyslog(SYSLG_PR, 1, "server", "REMOTE PWD", NULL);
964#endif /* CKSYSLOG */
965    if (!ENABLED(en_cwd)) {
966        errpkt((CHAR *)"REMOTE CD disabled");
967        RESUME;
968    } else {
969        if (encstr((CHAR *)zgtdir()) > -1) { /* Encode current directory */
970            ack1(data);                 /* If it fits, send it back in ACK */
971            success = 1;
972        } else {                        /* Failed */
973            ack();                      /* Send empty ACK */
974            success = 0;                /* and indicate failure locally */
975        }
976        RESUME;                         /* Back to server command wait */
977    }
978#endif /* NOSERVER */
979}
980    break;
981case 33:
982    {                           /* REMOTE DIRECTORY command */
983#ifndef NOSERVER
984    char *n2;
985#ifdef CKSYSLOG
986    if (ckxsyslog >= SYSLG_PR && ckxlogging)
987      cksyslog(SYSLG_PR, 1, "server", "REMOTE DIRECTORY", (char *)srvcmd);
988#endif /* CKSYSLOG */
989    if (!ENABLED(en_dir)) {             /* If DIR is disabled, */
990        errpkt((CHAR *)"REMOTE DIRECTORY disabled"); /* refuse. */
991        RESUME;
992    } else {                            /* DIR is enabled. */
993#ifdef IKSDB
994        if (ikdbopen) slotstate(what,"REMOTE DIR", (char *)(srvcmd+2), "");
995#endif /* IKSDB */
996        if (!ENABLED(en_cwd)) {         /* But CWD is disabled */
997            zstrip((char *)(srvcmd+2),&n2); /* and they included a pathname, */
998            if (strcmp((char *)(srvcmd+2),n2)) { /* so refuse. */
999                errpkt((CHAR *)"Access denied");
1000                RESUME;                 /* Remember, this is not a goto! */
1001            }
1002        }
1003        if (state == generic) {                 /* It's OK to go ahead. */
1004#ifdef COMMENT
1005            n2 = (*(srvcmd+2)) ? DIRCMD : DIRCM2;
1006            if (syscmd(n2,(char *)(srvcmd+2)))  /* If it can be done */
1007#else
1008            int x;
1009            if ((x = snddir((char*)(srvcmd+2))) > 0)
1010#endif /* COMMENT */
1011            {
1012                BEGIN ssinit;           /* send the results back; */
1013            } else {                    /* otherwise */
1014                if (x < 0)
1015                  errpkt((CHAR *)"No files match");
1016                else
1017                  errpkt((CHAR *)"Can't list directory");
1018                RESUME;                 /* return to server command wait */
1019            }
1020        }
1021    }
1022#endif /* NOSERVER */
1023}
1024    break;
1025case 34:
1026    {                           /* REMOTE DELETE (Erase) */
1027#ifndef NOSERVER
1028    char *n2;
1029#ifdef CKSYSLOG
1030    if (ckxsyslog >= SYSLG_PR && ckxlogging)
1031      cksyslog(SYSLG_PR, 1, "server", "REMOTE DELETE", (char *)srvcmd);
1032#endif /* CKSYSLOG */
1033    if (!ENABLED(en_del)) {
1034        errpkt((CHAR *)"REMOTE DELETE disabled");
1035        RESUME;
1036    } else {                            /* DELETE is enabled */
1037#ifdef IKSDB
1038        if (ikdbopen) slotstate(what,"REMOTE DELETE", (char *)(srvcmd+2), "");
1039#endif /* IKSDB */
1040        if (!ENABLED(en_cwd)) {         /* but CWD is disabled */
1041            zstrip((char *)(srvcmd+2),&n2); /* and they included a pathname, */
1042            if (strcmp((char *)(srvcmd+2),n2)) { /* so refuse. */
1043                errpkt((CHAR *)"Access denied");
1044                RESUME;                 /* Remember, this is not a goto! */
1045            }
1046        } else if (isdir((char *)(srvcmd+2))) { /* A directory name? */
1047            errpkt((CHAR *)"It's a directory");
1048            RESUME;
1049        }
1050        if (state == generic) {         /* It's OK to go ahead. */
1051            int x;
1052            if ((x = snddel((char*)(srvcmd+2))) > 0) {
1053                BEGIN ssinit;           /* If OK send results back */
1054            } else {                    /* otherwise */
1055                if (x < 0)
1056                  errpkt((CHAR *)"File not found"); /* report failure */
1057                else
1058                  errpkt((CHAR *)"DELETE failed");
1059                RESUME;                 /* & return to server command wait */
1060            }
1061        }
1062    }
1063#endif /* NOSERVER */
1064}
1065    break;
1066case 35:
1067    {                           /* FINISH */
1068#ifndef NOSERVER
1069#ifdef CKSYSLOG
1070    if (ckxsyslog >= SYSLG_PR && ckxlogging)
1071      cksyslog(SYSLG_PR, 1, "server", "FINISH", NULL);
1072#endif /* CKSYSLOG */
1073#ifdef IKSDB
1074    if (ikdbopen) slotstate(what,"SERVER FINISH", "", "");
1075#endif /* IKSDB */
1076    if (!ENABLED(en_fin)) {
1077        errpkt((CHAR *)"FINISH disabled");
1078        RESUME;
1079    } else {
1080        ack();                          /* Acknowledge */
1081        xxscreen(SCR_TC,0,0L,"");       /* Display */
1082        success = 1;
1083        return(0);                      /* Done */
1084    }
1085#endif /* NOSERVER */
1086}
1087    break;
1088case 36:
1089    {                           /* EXIT */
1090#ifndef NOSERVER
1091#ifdef CKSYSLOG
1092    if (ckxsyslog >= SYSLG_PR && ckxlogging)
1093      cksyslog(SYSLG_PR, 1, "server", "REMOTE EXIT", NULL);
1094#endif /* CKSYSLOG */
1095#ifdef IKSDB
1096    if (ikdbopen) slotstate(what,"REMOTE EXIT", "", "");
1097#endif /* IKSDB */
1098    if (!ENABLED(en_xit)) {
1099        errpkt((CHAR *)"EXIT disabled");
1100        RESUME;
1101    } else {
1102        ack();                          /* Acknowledge */
1103        xxscreen(SCR_TC,0,0L,"");       /* Display */
1104        doexit(GOOD_EXIT,xitsta);
1105    }
1106#endif /* NOSERVER */
1107}
1108    break;
1109case 37:
1110    {                           /* BYE (Logout) */
1111#ifndef NOSERVER
1112#ifdef CKSYSLOG
1113    if (ckxsyslog >= SYSLG_PR && ckxlogging)
1114      cksyslog(SYSLG_PR, 1, "server", "BYE", NULL);
1115#endif /* CKSYSLOG */
1116#ifdef IKSDB
1117    if (ikdbopen) slotstate(what,"SERVER BYE", "", "");
1118#endif /* IKSDB */
1119    if (!ENABLED(en_bye)) {
1120        errpkt((CHAR *)"BYE disabled");
1121        RESUME;
1122    } else {
1123        ack();                          /* Acknowledge */
1124        success = 1;
1125        msleep(750);                    /* Give the ACK time to get out */
1126        if (local)
1127          ttres();                      /* Reset the terminal */
1128        xxscreen(SCR_TC,0,0L,"");       /* Display */
1129        doclean(1);                     /* Clean up files, etc */
1130#ifdef DEBUG
1131        debug(F100,"C-Kermit BYE - Loggin out...","",0);
1132        zclose(ZDFILE);
1133#endif /* DEBUG */
1134#ifdef IKSD
1135#ifdef CK_LOGIN
1136        if (inserver)
1137          ckxlogout();
1138        else
1139#endif /* CK_LOGIN */
1140#endif /* IKSD */
1141#ifdef TCPSOCKET
1142#ifndef NOLISTEN
1143          if (network && tcpsrfd > 0 && !inserver)
1144            doexit(GOOD_EXIT,xitsta);
1145        else
1146#endif /* NOLISTEN */
1147#endif /* TCPSOCKET */
1148          return(zkself());             /* Try to log self out */
1149    }
1150#endif /* NOSERVER */
1151}
1152    break;
1153case 38:
1154    {                           /* REMOTE HELP */
1155#ifdef CKSYSLOG
1156    if (ckxsyslog >= SYSLG_PR && ckxlogging)
1157      cksyslog(SYSLG_PR, 1, "server", "REMOTE HELP", NULL);
1158#endif /* CKSYSLOG */
1159#ifdef IKSDB
1160    if (ikdbopen) slotstate(what,"REMOTE HELP", "", "");
1161#endif /* IKSDB */
1162#ifndef NOSERVER
1163    if (sndhlp(NULL)) {
1164        BEGIN ssinit;                   /* try to send it */
1165    } else {                            /* If not ok, */
1166        errpkt((CHAR *)"Can't send help"); /* send error message instead */
1167        RESUME;                         /* and return to server command wait */
1168    }
1169#endif /* NOSERVER */
1170}
1171    break;
1172case 39:
1173    {                            /* REMOTE RENAME */
1174    rc = srv_rename();
1175    debug(F101,"srv_rename","",rc);
1176    if (rc > -1) return(rc);            /* (see below) */
1177}
1178    break;
1179case 40:
1180    {                            /* REMOTE COPY */
1181    rc = srv_copy();
1182    debug(F101,"srv_copy","",rc);
1183    if (rc > -1) return(rc);            /* (see below) */
1184}
1185    break;
1186case 41:
1187    {                           /* REMOTE SET */
1188#ifdef CKSYSLOG
1189    if (ckxsyslog >= SYSLG_PR && ckxlogging)
1190      cksyslog(SYSLG_PR, 1, "server", "REMOTE SET", (char *)srvcmd);
1191#endif /* CKSYSLOG */
1192#ifndef NOSERVER
1193#ifdef IKSDB
1194    if (ikdbopen) slotstate(what,"REMOTE SET", (char *)(srvcmd+1), "");
1195#endif /* IKSDB */
1196    if (!ENABLED(en_set)) {
1197        errpkt((CHAR *)"REMOTE SET disabled");
1198        RESUME;
1199    } else {
1200        if (remset((char *)(srvcmd+1))) { /* Try to do what they ask */
1201            success = 1;
1202            ack();                      /* If OK, then acknowledge */
1203        } else                          /* Otherwise */
1204          errpkt((CHAR *)"Unknown REMOTE SET parameter"); /* give error msg */
1205        RESUME;                         /* Return to server command wait */
1206    }
1207#endif /* NOSERVER */
1208}
1209    break;
1210case 42:
1211    {                           /* REMOTE TYPE */
1212#ifndef NOSERVER
1213    char *n2;
1214#ifdef CKSYSLOG
1215    if (ckxsyslog >= SYSLG_PR && ckxlogging)
1216      cksyslog(SYSLG_PR, 1, "server", "REMOTE TYPE", (char *)srvcmd);
1217#endif /* CKSYSLOG */
1218    if (!ENABLED(en_typ)) {
1219        errpkt((CHAR *)"REMOTE TYPE disabled");
1220        RESUME;
1221    } else {
1222#ifdef IKSDB
1223        if (ikdbopen) slotstate(what,"REMOTE TYPE", (char *)(srvcmd+2), "");
1224#endif /* IKSDB */
1225        if (!ENABLED(en_cwd)) {         /* If CWD disabled */
1226            zstrip((char *)(srvcmd+2),&n2); /* and they included a pathname, */
1227            if (strcmp((char *)(srvcmd+2),n2)) { /* refuse. */
1228                errpkt((CHAR *)"Access denied");
1229                RESUME;                 /* Remember, this is not a goto! */
1230            }
1231        }
1232        if (state == generic) {         /* It's OK to go ahead. */
1233            binary = XYFT_T;            /* Use text mode for this. */
1234            if (                        /* (RESUME didn't change state) */
1235#ifdef COMMENT
1236              syscmd(TYPCMD,(char *)(srvcmd+2)) /* Old way */
1237#else
1238              sndtype((char *)(srvcmd+2)) /* New way */
1239#endif /* COMMENT */
1240                )
1241              BEGIN ssinit;             /* OK */
1242            else {                      /* not OK */
1243                errpkt((CHAR *)"Can't type file"); /* give error message */
1244                RESUME;                 /* wait for next server command */
1245            }
1246        }
1247    }
1248#endif /* NOSERVER */
1249}
1250    break;
1251case 43:
1252    {                           /* REMOTE MKDIR */
1253#ifndef NOSERVER
1254#ifdef CK_MKDIR
1255#ifdef CKSYSLOG
1256    if (ckxsyslog >= SYSLG_PR && ckxlogging)
1257      cksyslog(SYSLG_PR, 1, "server", "REMOTE MKDIR", (char *)srvcmd);
1258#endif /* CKSYSLOG */
1259#ifdef IKSDB
1260    if (ikdbopen) slotstate(what,"REMOTE MKDIR", (char *)(srvcmd+2), "");
1261#endif /* IKSDB */
1262    if (!ENABLED(en_mkd)) {
1263        errpkt((CHAR *)"REMOTE MKDIR disabled");
1264        RESUME;
1265    } else if (!ENABLED(en_cwd)) {      /* If CWD disabled */
1266        errpkt((CHAR *)"Directory access restricted");
1267        RESUME;                         /* Remember, this is not a goto! */
1268    }
1269    if (state == generic) {             /* OK to go ahead. */
1270        char *p = NULL;
1271        x = ckmkdir(0,(char *)(srvcmd+2),&p,0,1); /* Make the directory */
1272        if (!p) p = "";
1273        if (x > -1) {
1274            encstr((CHAR *)p);          /* OK - encode the name */
1275            ack1(data);                 /* Send short-form response */
1276            success = 1;
1277            RESUME;
1278        } else {                        /* not OK */
1279            if (!*p) p = "Directory creation failure";
1280            errpkt((CHAR *)p);          /* give error message */
1281            RESUME;                     /* Wait for next server command */
1282        }
1283    }
1284#else
1285    errpkt((CHAR *)"REMOTE MKDIR not available");
1286    RESUME;
1287#endif /* CK_MKDIR */
1288#endif /* NOSERVER */
1289}
1290    break;
1291case 44:
1292    {                           /* REMOTE RMDIR */
1293#ifndef NOSERVER
1294#ifdef CK_MKDIR
1295#ifdef CKSYSLOG
1296    if (ckxsyslog >= SYSLG_PR && ckxlogging)
1297      cksyslog(SYSLG_PR, 1, "server", "REMOTE RMDIR", (char *)srvcmd);
1298#endif /* CKSYSLOG */
1299#ifdef IKSDB
1300    if (ikdbopen) slotstate(what,"REMOTE RMDIR", (char *)(srvcmd+2), "");
1301#endif /* IKSDB */
1302    if (!ENABLED(en_rmd)) {
1303        errpkt((CHAR *)"REMOTE RMDIR disabled");
1304        RESUME;
1305    } else if (!ENABLED(en_cwd)) {      /* If CWD disabled */
1306        errpkt((CHAR *)"Directory access restricted");
1307        RESUME;                         /* Remember, this is not a goto! */
1308    }
1309    if (state == generic) {             /* OK to go ahead. */
1310        char *p = NULL;
1311        x = ckmkdir(1,(char *)(srvcmd+2),&p,0,1);
1312        if (!p) p = "";
1313        if (x > -1) {
1314            encstr((CHAR *)p);          /* OK - encode the name */
1315            ack1(data);                 /* Send short-form response */
1316            success = 1;
1317            RESUME;
1318        } else {                        /* not OK */
1319            if (!*p) p = "Directory removal failure";
1320            errpkt((CHAR *)p);          /* give error message */
1321            RESUME;                     /* Wait for next server command */
1322        }
1323    }
1324#else
1325    errpkt((CHAR *)"REMOTE RMDIR not available");
1326    RESUME;
1327#endif /* CK_MKDIR */
1328#endif /* NOSERVER */
1329}
1330    break;
1331case 45:
1332    {                           /* REMOTE SPACE */
1333#ifndef NOSERVER
1334#ifdef CKSYSLOG
1335    if (ckxsyslog >= SYSLG_PR && ckxlogging)
1336      cksyslog(SYSLG_PR, 1, "server", "REMOTE SPACE", (char *)srvcmd);
1337#endif /* CKSYSLOG */
1338    if (!ENABLED(en_spa)) {
1339        errpkt((CHAR *)"REMOTE SPACE disabled");
1340        RESUME;
1341    } else {
1342        x = srvcmd[1];                  /* Get area to check */
1343        x = ((x == NUL) || (x == SP)
1344#ifdef OS2
1345             || (x == '!') || (srvcmd[3] == ':')
1346#endif /* OS2 */
1347             );
1348#ifdef IKSDB
1349        if (ikdbopen) slotstate(what,
1350                              "REMOTE SPACE",
1351                              (x ? "" : (char *)srvcmd),
1352                              ""
1353                              );
1354#endif /* IKSDB */
1355        if (!x && !ENABLED(en_cwd)) {   /* CWD disabled */
1356            errpkt((CHAR *)"Access denied"); /* and non-default area given, */
1357            RESUME;                     /* refuse. */
1358        } else {
1359#ifdef OS2
1360_PROTOTYP(int sndspace,(int));
1361            if (sndspace(x ? toupper(srvcmd[2]) : 0)) {
1362                BEGIN ssinit;           /* send the report. */
1363            } else {                    /* If not ok, */
1364                errpkt((CHAR *)"Can't send space"); /* send error message */
1365                RESUME;                 /* and return to server command wait */
1366            }
1367#else
1368            if (nopush)
1369              x = 0;
1370            else
1371              x = (x ? syscmd(SPACMD,"") : syscmd(SPACM2,(char *)(srvcmd+2)));
1372            if (x) {                    /* If we got the info */
1373                BEGIN ssinit;           /* send it */
1374            } else {                    /* otherwise */
1375                errpkt((CHAR *)"Can't check space"); /* send error message */
1376                RESUME;                 /* and await next server command */
1377            }
1378#endif /* OS2 */
1379        }
1380    }
1381#endif /* NOSERVER */
1382}
1383    break;
1384case 46:
1385    {                           /* REMOTE WHO */
1386#ifndef NOSERVER
1387#ifdef CKSYSLOG
1388    if (ckxsyslog >= SYSLG_PR && ckxlogging)
1389      cksyslog(SYSLG_PR, 1, "server", "REMOTE WHO", (char *)srvcmd);
1390#endif /* CKSYSLOG */
1391#ifdef IKSDB
1392    if (ikdbopen) slotstate(what,"REMOTE WHO", (char *)(srvcmd+2), "");
1393#endif /* IKSDB */
1394    if (!ENABLED(en_who)) {
1395        errpkt((CHAR *)"REMOTE WHO disabled");
1396        RESUME;
1397    } else {
1398#ifdef OS2
1399_PROTOTYP(int sndwho,(char *));
1400            if (sndwho((char *)(srvcmd+2))) {
1401                BEGIN ssinit;           /* try to send it */
1402            } else {                    /* If not ok, */
1403                errpkt((CHAR *)"Can't do who command"); /* send error msg */
1404                RESUME;                 /* and return to server command wait */
1405            }
1406#else
1407        if (syscmd(WHOCMD,(char *)(srvcmd+2))) {
1408            BEGIN ssinit;
1409        } else {
1410            errpkt((CHAR *)"Can't do who command");
1411            RESUME;
1412        }
1413#endif /* OS2 */
1414    }
1415#endif /* NOSERVER */
1416}
1417    break;
1418case 47:
1419    {                           /* Variable query or set */
1420    rc = srv_query();
1421    debug(F101,"srv_query","",rc);
1422    if (rc > -1) return(rc);
1423}
1424    break;
1425case 48:
1426    {                           /* Interrupted or connection lost */
1427#ifndef NOSERVER
1428    if (fatalio) {                      /* Connection lost */
1429#ifdef CKSYSLOG
1430        if (ckxsyslog >= SYSLG_PR && ckxlogging)
1431          cksyslog(SYSLG_PR, 1, "server", "Interrupted", NULL);
1432#endif /* CKSYSLOG */
1433        success = 0;
1434        xitsta |= (what & W_KERMIT);
1435        QUIT;
1436    } else if (interrupted) {
1437        if (!ENABLED(en_fin)) {         /* Ctrl-C typed */
1438            errpkt((CHAR *)"QUIT disabled");
1439            RESUME;
1440        } else {
1441#ifdef CKSYSLOG
1442            if (ckxsyslog >= SYSLG_PR && ckxlogging)
1443              cksyslog(SYSLG_PR, 1, "server", "Interrupted", NULL);
1444#endif /* CKSYSLOG */
1445            success = 0;
1446            xitsta |= (what & W_KERMIT);
1447            QUIT;
1448        }
1449    } else {                            /* Shouldn't happen */
1450        debug(F100,"SERVER (generic) GOT UNEXPECTED 'q'","",0);
1451        QUIT;
1452    }
1453#endif /* NOSERVER */
1454}
1455    break;
1456case 49:
1457    {                           /* Anything else in this state... */
1458#ifndef NOSERVER
1459    errpkt((CHAR *)"Unimplemented REMOTE command"); /* Complain */
1460    RESUME;                             /* and return to server command wait */
1461#endif /* NOSERVER */
1462}
1463    break;
1464case 50:
1465    {                           /* Sent BYE and connection broken */
1466    if (bye_active && ttchk() < 0) {
1467        msleep(500);
1468        bye_active = 0;
1469        ttclos(0);                      /* Close our end of the connection */
1470        clsof(0);
1471        return(success = 1);
1472    } else {                            /* Other generic command */
1473        return(success = 0);            /* or connection not broken */
1474    }
1475}
1476    break;
1477case 51:
1478    {                           /* Short-Form reply */
1479    rc = rcv_shortreply();
1480    debug(F101,"<rgen>Y rcv_shortreply","",rc);
1481    if (rc > -1) return(rc);
1482}
1483    break;
1484case 52:
1485    {                           /* File header */
1486    /* char *n2; */
1487    extern int rsn;
1488    debug(F101,"<rfile>F winlo 1","",winlo);
1489    xflg = 0;                           /* Not screen data */
1490    if (!czseen)
1491      cancel = 0;                       /* Reset cancellation counter */
1492#ifdef CALIBRATE
1493    if (dest == DEST_N)
1494      calibrate = 1;
1495#endif /* CALIBRATE */
1496    if (!rcvfil(filnam)) {              /* Figure out local filename */
1497        errpkt((CHAR *)rf_err);         /* Trouble */
1498        RESUME;
1499    } else {                            /* Real file, OK to receive */
1500        char * fnp;
1501        debug(F111,"<rfile>F winlo 2",fspec,winlo);
1502        if (filcnt == 1)                /* rcvfil set this to 1 for 1st file */
1503          crc16 = 0L;                   /* Clear file CRC */
1504        fnp = fspec;                    /* This is the full path */
1505        if (server && !ENABLED(en_cwd) || /* if DISABLE CD */
1506            !fackpath                     /* or F-ACK-PATH OFF */
1507            ) {
1508            zstrip(fspec,&fnp);         /* don't send back full path */
1509        }
1510        encstr((CHAR *)fnp);
1511        if (fackbug)
1512          ack();
1513        else
1514          ack1(data);                   /* Send it back in ACK */
1515        initattr(&iattr);               /* Clear file attribute structure */
1516        streamon();
1517        if (window(wslotn) < 0) {       /* Allocate negotiated window slots */
1518            errpkt((CHAR *)"Can't open window");
1519            RESUME;
1520        }
1521#ifdef IKSDB
1522        if (ikdbopen) slotstate(what,
1523                              server ? "SERVER" : "",
1524                              "RECEIVE",
1525                              fspec
1526                              );
1527#endif /* IKSDB */
1528        BEGIN rattr;                    /* Now expect Attribute packets */
1529    }
1530}
1531    break;
1532case 53:
1533    {                           /* X-packet instead of file header */
1534    xflg = 1;                           /* Screen data */
1535    if (!czseen)
1536      cancel = 0;                       /* Reset cancellation counter */
1537    ack();                              /* Acknowledge the X-packet */
1538    initattr(&iattr);                   /* Initialize attribute structure */
1539    streamon();
1540    if (window(wslotn) < 0) {           /* allocate negotiated window slots */
1541        errpkt((CHAR *)"Can't open window");
1542        RESUME;
1543    }
1544#ifndef NOSPL
1545    if (query) {                        /* If this is the response to */
1546        qbufp = querybuf;               /* a query that we sent, initialize */
1547        qbufn = 0;                      /* the response buffer */
1548        querybuf[0] = NUL;
1549    }
1550#endif /* NOSPL */
1551    what = W_REMO;                      /* we're doing a REMOTE command */
1552#ifdef IKSDB
1553    if (ikdbopen) slotstate(what,
1554                          server ? "SERVER" : "",
1555                          "RECEIVE",
1556                          fspec
1557                          );
1558#endif /* IKSDB */
1559    BEGIN rattr;                        /* Expect Attribute packets */
1560}
1561    break;
1562case 54:
1563    {                           /* Attribute packet */
1564    if (gattr(rdatap,&iattr) == 0) {    /* Read into attribute structure */
1565#ifdef CK_RESEND
1566        ack1((CHAR *)iattr.reply.val);  /* Reply with data */
1567#else
1568        ack();                          /* If OK, acknowledge */
1569#endif /* CK_RESEND */
1570    } else {                            /* Otherwise */
1571        extern long fsize;
1572        char *r;
1573        r = getreason(iattr.reply.val);
1574        ack1((CHAR *)iattr.reply.val);  /* refuse to accept the file */
1575        xxscreen(SCR_ST,ST_REFU,0L,r);  /* reason */
1576#ifdef TLOG
1577        if (tralog && !tlogfmt)
1578          doxlog(what,filnam,fsize,binary,1,r);
1579#endif /* TLOG */
1580    }
1581}
1582    break;
1583case 55:
1584    {                           /* First data packet */
1585    debug(F100,"<rattr> D firstdata","",0);
1586    rc = rcv_firstdata();
1587    debug(F101,"rcv_firstdata rc","",rc);
1588    if (rc > -1) return(rc);            /* (see below) */
1589}
1590    break;
1591case 56:
1592    {                           /* EOT, no more files */
1593    ack();                              /* Acknowledge the B packet */
1594    reot();                             /* Do EOT things */
1595#ifdef CK_TMPDIR
1596/* If we were cd'd temporarily to another device or directory ... */
1597    if (f_tmpdir) {
1598        int x;
1599        x = zchdir((char *) savdir);    /* ... restore previous directory */
1600        f_tmpdir = 0;                   /* and remember we did it. */
1601        debug(F111,"ckcpro.w B tmpdir restoring",savdir,x);
1602    }
1603#endif /* CK_TMPDIR */
1604    RESUME;                             /* and quit */
1605}
1606    break;
1607case 57:
1608    {                           /* Got Data packet */
1609    debug(F101,"<rdpkt>D cxseen","",cxseen);
1610    debug(F101,"<rdpkt>D czseen","",czseen);
1611    if (cxseen || czseen || discard) {  /* If file or group interruption */
1612        CHAR * msg;
1613        msg = czseen ? (CHAR *)"Z" : (CHAR *)"X";
1614#ifdef STREAMING
1615        if (streaming) {                /* Need to cancel */
1616            debug(F111,"<rdpkt>D streaming cancel",msg,cancel);
1617            if (cancel++ == 0) {        /* Only do this once */
1618                ack1(msg);              /* Put "X" or "Z" in ACK */
1619            } else if (czseen) {
1620                errpkt((CHAR *)"User canceled");
1621                RESUME;
1622            } else {
1623                fastack();
1624            }
1625        } else
1626#endif /* STREAMING */
1627          ack1(msg);
1628    } else {                            /* No interruption */
1629        int rc, qf;
1630#ifndef NOSPL
1631        qf = query;
1632#else
1633        qf = 0;
1634#endif /* NOSPL */
1635#ifdef CKTUNING
1636        rc = (binary && !parity) ?
1637          bdecode(rdatap,putfil):
1638            decode(rdatap, qf ? puttrm : putfil, 1);
1639#else
1640        rc = decode(rdatap, qf ? puttrm : putfil, 1);
1641#endif /* CKTUNING */
1642        if (rc < 0) {
1643            discard = (keep == 0 || (keep == SET_AUTO && binary != XYFT_T));
1644            errpkt((CHAR *)"Error writing data"); /* If failure, */
1645            RESUME;
1646        } else                          /* Data written OK, send ACK */
1647#ifdef STREAMING
1648          if (streaming)
1649            fastack();
1650        else
1651#endif /* STREAMING */
1652          ack();
1653    }
1654}
1655    break;
1656case 58:
1657    {                           /* EOF immediately after A-Packet. */
1658    rf_err = "Can't create file";
1659    timint = s_timint;
1660    if (discard) {                      /* Discarding a real file... */
1661        x = 1;
1662    } else if (xflg) {                  /* If screen data */
1663        if (remfile) {                  /* redirected to file */
1664            if (rempipe)                /* or pipe */
1665              x = openc(ZOFILE,remdest); /* Pipe: start command */
1666            else
1667              x = opena(remdest,&iattr); /* File: open with attributes */
1668        } else {                        /* otherwise */
1669            x = opent(&iattr);          /* "open" the screen */
1670        }
1671#ifdef CALIBRATE
1672    } else if (calibrate) {             /* If calibration run */
1673        x = ckopenx(&iattr);            /* do this */
1674#endif /* CALIBRATE */
1675    } else {                            /* otherwise */
1676        x = opena(filnam,&iattr);       /* open the file, with attributes */
1677        if (x == -17) {                 /* REGET skipped because same size */
1678            discard = 1;
1679            rejection = 1;
1680        }
1681    }
1682    if (!x || reof(filnam, &iattr) < 0) { /* Close output file */
1683        errpkt((CHAR *) rf_err);        /* If problem, send error msg */
1684        RESUME;                         /* and quit */
1685    } else {                            /* otherwise */
1686        if (x == -17)
1687          xxscreen(SCR_ST,ST_SKIP,SKP_RES,"");
1688        ack();                          /* acknowledge the EOF packet */
1689        BEGIN rfile;                    /* and await another file */
1690    }
1691}
1692    break;
1693case 59:
1694    {                           /* Ctrl-C or connection loss. */
1695    timint = s_timint;
1696    window(1);                          /* Set window size back to 1... */
1697    cxseen = 1;
1698    x = clsof(1);                       /* Close file */
1699    return(success = 0);                /* Failed */
1700}
1701    break;
1702case 60:
1703    {                           /* End Of File (EOF) Packet */
1704/*  wslots = 1; */                      /* (don't set) Window size back to 1 */
1705#ifndef COHERENT /* Coherent compiler blows up on this switch() statement. */
1706    x = reof(filnam, &iattr);           /* Handle the EOF packet */
1707    switch (x) {                        /* reof() sets the success flag */
1708      case -5:                          /* Handle problems */
1709        errpkt((CHAR *)"RENAME failed"); /* Fatal */
1710        RESUME;
1711        break;
1712      case -4:
1713        errpkt((CHAR *)"MOVE failed");  /* Fatal */
1714        RESUME;
1715        break;
1716      case -3:                          /* If problem, send error msg */
1717        errpkt((CHAR *)"Can't print file"); /* Fatal */
1718        RESUME;
1719        break;
1720      case -2:
1721        errpkt((CHAR *)"Can't mail file"); /* Fatal */
1722        RESUME;
1723        break;
1724      case 2:                           /* Not fatal */
1725      case 3:
1726        xxscreen(SCR_EM,0,0L,"Receiver can't delete temp file");
1727        RESUME;
1728        break;
1729      default:
1730        if (x < 0) {                    /* Fatal */
1731            errpkt((CHAR *)"Can't close file");
1732            RESUME;
1733        } else {                        /* Success */
1734#ifndef NOSPL
1735            if (query)                  /* Query reponses generally */
1736              conoll("");               /* don't have line terminators */
1737#endif /* NOSPL */
1738            if (czseen) {               /* Batch canceled? */
1739                if (cancel++ == 0) {    /* If we haven't tried this yet */
1740                    ack1((CHAR *)"Z");  /* Try it once */
1741                } else {                /* Otherwise */
1742                    errpkt((CHAR *)"User canceled"); /* quite with Error */
1743                    RESUME;
1744                }
1745            } else
1746              ack();                    /* Acknowledge the EOF packet */
1747            BEGIN rfile;                /* and await another file */
1748        }
1749    }
1750#else
1751    if (reof(filnam, &iattr) < 0) {     /* Close the file */
1752        errpkt((CHAR *)"Error at end of file");
1753        RESUME;
1754    } else {                            /* reof() sets success flag */
1755        ack();
1756        BEGIN rfile;
1757    }
1758#endif /* COHERENT */
1759}
1760    break;
1761case 61:
1762    {                           /* ACK for Send-Init */
1763    spar(rdatap);                       /* set parameters from it */
1764    cancel = 0;
1765    bctu = bctr;                        /* switch to agreed-upon block check */
1766    bctl = (bctu == 4) ? 2 : bctu;      /* Set block-check length */
1767#ifdef CK_RESEND
1768    if ((sendmode == SM_RESEND) && (!atcapu || !rscapu)) { /* RESEND */
1769        errpkt((CHAR *) "RESEND capabilities not negotiated");
1770        RESUME;
1771    } else {
1772#endif /* CK_RESEND */
1773        what = W_SEND;                  /* Remember we're sending */
1774        lastxfer = W_SEND;
1775        x = sfile(xflg);                /* Send X or F header packet */
1776        cancel = 0;                     /* Reset cancellation counter */
1777        if (x) {                        /* If the packet was sent OK */
1778            if (!xflg && filcnt == 1)   /* and it's a real file */
1779              crc16 = 0L;               /* Clear the file CRC */
1780            resetc();                   /* reset per-transaction counters */
1781            rtimer();                   /* reset timers */
1782#ifdef GFTIMER
1783            rftimer();
1784#endif /* GFTIMER */
1785            streamon();                 /* turn on streaming */
1786#ifdef IKSDB
1787            if (ikdbopen) slotstate(what,
1788                                  (server ? "SERVER" : ""),
1789                                  "SEND",
1790                                  filnam
1791                                  );
1792#endif /* IKSDB */
1793            BEGIN ssfile;               /* and switch to receive-file state */
1794        } else {                        /* otherwise send error msg & quit */
1795            s = xflg ? "Can't execute command" : (char *)epktmsg;
1796            if (!*s) s = "Can't open file";
1797            errpkt((CHAR *)s);
1798            RESUME;
1799        }
1800#ifdef CK_RESEND
1801    }
1802#endif /* CK_RESEND */
1803}
1804    break;
1805case 62:
1806    {                           /* R packet was retransmitted. */
1807    xsinit();                           /* Resend packet 0 */
1808}
1809    break;
1810case 63:
1811    {                           /* Same deal if G packet comes again */
1812    xsinit();
1813}
1814    break;
1815case 64:
1816    {                           /* Same deal if C packet comes again */
1817    xsinit();
1818}
1819    break;
1820case 65:
1821    {                           /* ACK for F or X packet */
1822    srvptr = srvcmd;                    /* Point to string buffer */
1823    decode(rdatap,putsrv,0);            /* Decode data field, if any */
1824    putsrv(NUL);                        /* Terminate with null */
1825    ffc = 0L;                           /* Reset file byte counter */
1826    debug(F101,"<ssfile>Y cxseen","",cxseen);
1827    if (*srvcmd) {                      /* If remote name was recorded */
1828        if (sendmode != SM_RESEND) {
1829            if (fdispla == XYFD_C || fdispla == XYFD_S)
1830              xxscreen(SCR_AN,0,0L,(char *)srvcmd);
1831            tlog(F110," remote name:",(char *) srvcmd,0L);
1832            makestr(&psrfspec,(char *)srvcmd);
1833        }
1834    }
1835    if (cxseen||czseen) {               /* Interrupted? */
1836        debug(F101,"<ssfile>Y canceling","",0);
1837        x = clsif();                    /* Close input file */
1838        sxeof(1);                       /* Send EOF(D) */
1839        BEGIN sseof;                    /* and switch to EOF state. */
1840    } else if (atcapu) {                /* If attributes are to be used */
1841        if (sattr(xflg | stdinf, 1) < 0) { /* send them */
1842            errpkt((CHAR *)"Can't send attributes"); /* if problem, say so */
1843            RESUME;                     /* and quit */
1844        } else BEGIN ssattr;            /* if ok, switch to attribute state */
1845    } else {                            /* Attributes not negotiated */
1846        if (window(wslotn) < 0) {       /* Open window */
1847            errpkt((CHAR *)"Can't open window");
1848            RESUME;
1849        } else if ((x = sdata()) == -2) { /* Send first data packet data */
1850            window(1);                  /* Connection lost, reset window */
1851            x = clsif();                /* Close input file */
1852            return(success = 0);        /* Return failure */
1853        } else if (x == -9) {           /* User interrupted */
1854            errpkt((CHAR *)"User cancelled"); /* Send Error packet */
1855            window(1);                  /* Set window size back to 1... */
1856            timint = s_timint;          /* Restore timeout */
1857            return(success = 0);        /* Failed */
1858        } else if (x < 0) {             /* EOF (empty file) or interrupted */
1859            window(1);                  /* put window size back to 1, */
1860            debug(F101,"<ssfile>Y cxseen","",cxseen);
1861            x = clsif();                /* If not ok, close input file, */
1862            if (x < 0)                  /* treating failure as interruption */
1863              cxseen = 1;               /* Send EOF packet */
1864            seof(cxseen||czseen);
1865            BEGIN sseof;                /* and switch to EOF state. */
1866        } else {                        /* First data sent OK */
1867            BEGIN ssdata;               /* All ok, switch to send-data state */
1868        }
1869    }
1870}
1871    break;
1872case 66:
1873    {                           /* Got ACK to A packet */
1874    ffc = 0L;                           /* Reset file byte counter */
1875    debug(F101,"<ssattr>Y cxseen","",cxseen);
1876    if (cxseen||czseen) {               /* Interrupted? */
1877        debug(F101,"<sattr>Y canceling","",0);
1878        x = clsif();                    /* Close input file */
1879        sxeof(1);                       /* Send EOF(D) */
1880        BEGIN sseof;                    /* and switch to EOF state. */
1881    } else if (rsattr(rdatap) < 0) {    /* Was the file refused? */
1882        discard = 1;                    /* Set the discard flag */
1883        clsif();                        /* Close the file */
1884        sxeof(1);                       /* send EOF with "discard" code */
1885        BEGIN sseof;                    /* switch to send-EOF state */
1886    } else if ((x = sattr(xflg | stdinf, 0)) < 0) { /* Send more? */
1887        errpkt((CHAR *)"Can't send attributes"); /* Trouble... */
1888        RESUME;
1889    } else if (x == 0) {                /* No more to send so now the data */
1890        if (window(wslotn) < 0) {       /* Allocate negotiated window slots */
1891            errpkt((CHAR *)"Can't open window");
1892            RESUME;
1893        }
1894        if ((x = sdata()) == -2) {      /* File accepted, send first data */
1895            window(1);                  /* Connection broken */
1896            x = clsif();                /* Close file */
1897            return(success = 0);        /* Return failure */
1898        } else if (x == -9) {           /* User interrupted */
1899            errpkt((CHAR *)"User cancelled"); /* Send Error packet */
1900            window(1);                  /* Set window size back to 1... */
1901            timint = s_timint;          /* Restore timeout */
1902            return(success = 0);        /* Failed */
1903        } else if (x < 0) {             /* If data was not sent */
1904            window(1);                  /* put window size back to 1, */
1905            debug(F101,"<ssattr>Y cxseen","",cxseen);
1906            if (clsif() < 0)            /* Close input file */
1907              cxseen = 1;               /* Send EOF packet */
1908            seof(cxseen||czseen);
1909            BEGIN sseof;                /* and switch to EOF state. */
1910        } else {
1911            BEGIN ssdata;               /* All ok, switch to send-data state */
1912        }
1913    }
1914}
1915    break;
1916case 67:
1917    {                           /* Ctrl-C or connection loss. */
1918    window(1);                          /* Set window size back to 1... */
1919    cxseen = 1;                         /* To indicate interruption */
1920    x = clsif();                        /* Close file */
1921    return(success = 0);                /* Failed */
1922}
1923    break;
1924case 68:
1925    {                           /* Got ACK to Data packet */
1926    canned(rdatap);                     /* Check if file transfer cancelled */
1927    debug(F111,"<ssdata>Y cxseen",rdatap,cxseen);
1928    debug(F111,"<ssdata>Y czseen",rdatap,czseen);
1929    if ((x = sdata()) == -2) {          /* Try to send next data */
1930        window(1);                      /* Connection lost, reset window */
1931        x = clsif();                    /* Close file */
1932        return(success = 0);            /* Failed */
1933    } else if (x == -9) {               /* User interrupted */
1934        errpkt((CHAR *)"User cancelled"); /* Send Error packet */
1935        window(1);                      /* Set window size back to 1... */
1936        timint = s_timint;              /* Restore original timeout */
1937        return(success = 0);            /* Failed */
1938    } else if (x < 0) {                 /* EOF - finished sending data */
1939        debug(F101,"<ssdata>Y cxseen","",cxseen);
1940        window(1);                      /* Set window size back to 1... */
1941        if (clsif() < 0)                /* Close input file */
1942          cxseen = 1;                   /* Send EOF packet */
1943        debug(F101,"<ssdata>Y CALLING SEOF()","",cxseen);
1944        seof(cxseen||czseen);
1945        BEGIN sseof;                    /* and enter send-eof state */
1946    }
1947    /* NOTE: If x == 0 it means we're draining: see sdata()! */
1948}
1949    break;
1950case 69:
1951    {                           /* Got ACK to EOF */
1952    int g, xdiscard;
1953    canned(rdatap);                     /* Check if file transfer cancelled */
1954    debug(F111,"<sseof>Y cxseen",rdatap,cxseen);
1955    debug(F111,"<sseof>Y czseen",rdatap,czseen);
1956    debug(F111,"<sseof>Y discard",rdatap,discard);
1957    xdiscard = discard;
1958    discard = 0;
1959    success = (cxseen == 0 && czseen == 0); /* Transfer status... */
1960    debug(F101,"<sseof>Y success","",success);
1961    if (success && rejection > 0)           /* If rejected, succeed if */
1962      if (rejection != '#' &&               /* reason was date */
1963          rejection != 1 && rejection != '?') /* or name; */
1964        success = 0;                        /* fail otherwise. */
1965    cxseen = 0;                         /* This goes back to zero. */
1966    if (success) {                      /* Only if transfer succeeded... */
1967        xxscreen(SCR_ST,ST_OK,0L,"");
1968        if (!xdiscard) {
1969            makestr(&sfspec,psfspec);   /* Record filenames for WHERE */
1970            makestr(&srfspec,psrfspec);
1971        }
1972        if (moving) {                   /* If MOVE'ing */
1973            x = zdelet(filnam);         /* Try to delete the source file */
1974#ifdef TLOG
1975            if (tralog) {
1976                if (x > -1) {
1977                    tlog(F110," deleted",filnam,0);
1978                } else {
1979                    tlog(F110," delete failed:",ck_errstr(),0);
1980                }
1981            }
1982#endif /* TLOG */
1983        } else if (snd_move) {          /* Or move it */
1984            int x;
1985            x = zrename(filnam,snd_move);
1986#ifdef TLOG
1987            if (tralog) {
1988                if (x > -1) {
1989                    tlog(F110," moved to ",snd_move,0);
1990                } else {
1991                    tlog(F110," move failed:",ck_errstr(),0);
1992                }
1993            }
1994#endif /* TLOG */
1995        } else if (snd_rename) {        /* Or rename it */
1996            char *s = snd_rename;       /* Renaming string */
1997#ifndef NOSPL
1998            int y;                      /* Pass it thru the evaluator */
1999            extern int cmd_quoting;     /* for \v(filename) */
2000            if (cmd_quoting) {          /* But only if cmd_quoting is on */
2001                y = MAXRP;
2002                s = (char *)srvcmd;
2003                zzstring(snd_rename,&s,&y);
2004                s = (char *)srvcmd;
2005            }
2006#endif /* NOSPL */
2007            if (s) if (*s) {
2008                int x;
2009                x = zrename(filnam,s);
2010#ifdef TLOG
2011            if (tralog) {
2012                if (x > -1) {
2013                    tlog(F110," renamed to",s,0);
2014                } else {
2015                    tlog(F110," rename failed:",ck_errstr(),0);
2016                }
2017            }
2018#endif /* TLOG */
2019#ifdef COMMENT
2020                *s = NUL;
2021#endif /* COMMENT */
2022            }
2023        }
2024    }
2025    if (czseen) {                       /* Check group interruption flag */
2026        g = 0;                          /* No more files if interrupted */
2027    } else {                            /* Otherwise... */
2028#ifdef COMMENT
2029        /* This code makes any open error fatal to a file-group transfer. */
2030        g = gnfile();
2031        debug(F111,"<sseof>Y gnfile",filnam,g);
2032        if (g > 0) {                    /* Any more files to send? */
2033            if (sfile(xflg))            /* Yes, try to send next file header */
2034              BEGIN ssfile;             /* if ok, enter send-file state */
2035            else {                      /* otherwise */
2036                s = xflg ? "Can't execute command" : (char *)epktmsg;
2037                if (!*s) s = "Can't open file";
2038                errpkt((CHAR *)s);      /* send error message */
2039                RESUME;                 /* and quit */
2040            }
2041        } else {                        /* No next file */
2042            tsecs = gtimer();           /* get statistics timers */
2043#ifdef GFTIMER
2044            fptsecs = gftimer();
2045#endif /* GFTIMER */
2046            seot();                     /* send EOT packet */
2047            BEGIN sseot;                /* enter send-eot state */
2048        }
2049#else  /* COMMENT */
2050        while (1) {                     /* Keep trying... */
2051            g = gnfile();               /* Get next file */
2052            debug(F111,"<sseof>Y gnfile",filnam,g);
2053            if (g == 0 && gnferror == 0) /* No more, stop trying */
2054              break;
2055            if (g > 0) {                /* Have one */
2056                if (sfile(xflg)) {      /* Try to open and send F packet */
2057                    BEGIN ssfile;       /* If OK, enter send-file state */
2058                    break;              /* and break out of loop. */
2059                }
2060            } /* Otherwise keep trying to get one we can send... */
2061        }
2062    }
2063    if (g == 0) {
2064        debug(F101,"<sseof>Y no more files","",czseen);
2065        tsecs = gtimer();               /* Get statistics timers */
2066#ifdef GFTIMER
2067        fptsecs = gftimer();
2068#endif /* GFTIMER */
2069        seot();                         /* Send EOT packet */
2070        BEGIN sseot;                    /* Enter send-eot state */
2071    }
2072#endif /* COMMENT */
2073}
2074    break;
2075case 70:
2076    {                           /* Got ACK to EOT */
2077    debug(F101,"sseot justone","",justone);
2078    RESUME;                             /* All done, just quit */
2079}
2080    break;
2081case 71:
2082    {                                   /* Got Error packet, in any state */
2083    char *s = "";
2084    window(1);                          /* Close window */
2085    timint = s_timint;                  /* Restore original timeout */
2086    if (*epktmsg)                       /* Message from Error packet */
2087      s = (char *)epktmsg;
2088    if (!*s) {                          /* If not there then maybe here */
2089        s = (char *)rdatap;
2090        ckstrncpy((char *)epktmsg,(char *)rdatap,PKTMSGLEN);
2091    }
2092    if (!*s)                            /* Hopefully we'll never see this. */
2093      s = "Unknown error";
2094    success = 0;                        /* For IF SUCCESS/FAIL. */
2095    debug(F101,"ckcpro.w justone at E pkt","",justone);
2096
2097    success = 0;                        /* Transfer failed */
2098    xferstat = success;                 /* Remember transfer status */
2099    if (!epktsent) {
2100        x = quiet; quiet = 1;           /* Close files silently, */
2101        epktrcvd = 1;                   /* Prevent messages from clsof() */
2102        clsif();
2103        clsof(1);                       /* discarding any output file. */
2104        ermsg(s);                       /* Issue the message (calls screen). */
2105        quiet = x;                      /* Restore quiet state */
2106    }
2107    tstats();                           /* Get stats */
2108/*
2109  If we are executing commands from a command file or macro, let the command
2110  file or macro decide whether to exit, based on SET { TAKE, MACRO } ERROR.
2111*/
2112    if (
2113#ifndef NOICP
2114        !xcmdsrc &&
2115#endif /* NOICP */
2116        backgrd && !server)
2117      fatal("Protocol error");
2118    xitsta |= (what & W_KERMIT);        /* Save this for doexit(). */
2119#ifdef CK_TMPDIR
2120/* If we were cd'd temporarily to another device or directory ... */
2121    if (f_tmpdir) {
2122        int x;
2123        x = zchdir((char *) savdir);    /* ... restore previous directory */
2124        f_tmpdir = 0;                   /* and remember we did it. */
2125        debug(F111,"ckcpro.w E tmpdir restored",savdir,x);
2126    }
2127#endif /* CK_TMPDIR */
2128#ifdef IKSDB
2129    if (ikdbopen) slotstate(what,"ERROR", (char *)epktmsg, "");
2130#endif /* IKSDB */
2131    RESUME;
2132}
2133    break;
2134case 72:
2135    { success = 0; QUIT; }
2136    break;
2137case 73:
2138    {                                   /* Anything not accounted for above */
2139    errpkt((CHAR *)"Unexpected packet type"); /* Give error message */
2140    window(1);
2141    xitsta |= (what & W_KERMIT);        /* Save this for doexit(). */
2142    RESUME;                             /* and quit */
2143}
2144    break;
2145
2146            }
2147    }
2148}
2149
2150char tbl[] = {
2151 -1, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2152 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2153 73, 73, 73, 73, 73, 71, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2154 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2155 73, 11, 73,  7, 73, 73, 73,  9,  4, 73,  5,  8, 73, 73, 73,  6,
2156 73, 72,  3,  1, 73, 73,  2, 73, 10, 73, 73, 73, 73, 73, 73, 73,
2157 -1, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2158 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2159 73, 73, 73, 73, 73, 15, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2160 73, 73, 73, 73, 73, 73, 73, 73, 73, 13, 73, 73, 73, 73, 73, 73,
2161 73, 11, 73,  7, 73, 73, 73,  9,  4, 73,  5,  8, 73, 73, 73,  6,
2162 73, 72,  3,  1, 73, 73,  2, 73, 10, 73, 73, 73, 73, 73, 73, 73,
2163 -1, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2164 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2165 73, 73, 56, 73, 73, 71, 52, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2166 73, 73, 73, 73, 73, 73, 73, 73, 53, 73, 73, 73, 73, 73, 73, 73,
2167 73, 11, 73,  7, 73, 73, 73,  9,  4, 73,  5,  8, 73, 73, 73,  6,
2168 73, 72,  3,  1, 73, 73,  2, 73, 10, 73, 73, 73, 73, 73, 73, 73,
2169 -1, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2170 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2171 73, 54, 73, 73, 55, 71, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2172 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 58, 73, 73, 73, 73, 73,
2173 73, 11, 73,  7, 73, 73, 73,  9,  4, 73,  5,  8, 73, 73, 73,  6,
2174 73, 72,  3,  1, 73, 73,  2, 73, 10, 73, 73, 73, 73, 73, 73, 73,
2175 -1, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2176 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2177 73, 73, 73, 73, 57, 71, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2178 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 60, 73, 73, 73, 73, 73,
2179 73, 11, 73,  7, 73, 73, 73,  9,  4, 73,  5,  8, 73, 73, 73,  6,
2180 73, 59,  3,  1, 73, 73,  2, 73, 10, 73, 73, 73, 73, 73, 73, 73,
2181 -1, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2182 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2183 73, 73, 73, 64, 73, 71, 73, 63, 73, 73, 73, 73, 73, 73, 73, 73,
2184 73, 73, 62, 73, 73, 73, 73, 73, 73, 61, 73, 73, 73, 73, 73, 73,
2185 73, 11, 73,  7, 73, 73, 73,  9,  4, 73,  5,  8, 73, 73, 73,  6,
2186 73, 72,  3,  1, 73, 73,  2, 73, 10, 73, 73, 73, 73, 73, 73, 73,
2187 -1, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2188 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2189 73, 73, 73, 73, 73, 71, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2190 73, 73, 73, 73, 73, 73, 73, 73, 73, 65, 73, 73, 73, 73, 73, 73,
2191 73, 11, 73,  7, 73, 73, 73,  9,  4, 73,  5,  8, 73, 73, 73,  6,
2192 73, 72,  3,  1, 73, 73,  2, 73, 10, 73, 73, 73, 73, 73, 73, 73,
2193 -1, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2194 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2195 73, 73, 73, 73, 73, 71, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2196 73, 73, 73, 73, 73, 73, 73, 73, 73, 66, 73, 73, 73, 73, 73, 73,
2197 73, 11, 73,  7, 73, 73, 73,  9,  4, 73,  5,  8, 73, 73, 73,  6,
2198 73, 72,  3,  1, 73, 73,  2, 73, 10, 73, 73, 73, 73, 73, 73, 73,
2199 -1, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2200 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2201 73, 73, 73, 73, 73, 71, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2202 73, 73, 73, 73, 73, 73, 73, 73, 73, 68, 73, 73, 73, 73, 73, 73,
2203 73, 11, 73,  7, 73, 73, 73,  9,  4, 73,  5,  8, 73, 73, 73,  6,
2204 73, 67,  3,  1, 73, 73,  2, 73, 10, 73, 73, 73, 73, 73, 73, 73,
2205 -1, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2206 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2207 73, 73, 73, 73, 73, 71, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2208 73, 73, 73, 73, 73, 73, 73, 73, 73, 69, 73, 73, 73, 73, 73, 73,
2209 73, 11, 73,  7, 73, 73, 73,  9,  4, 73,  5,  8, 73, 73, 73,  6,
2210 73, 72,  3,  1, 73, 73,  2, 73, 10, 73, 73, 73, 73, 73, 73, 73,
2211 -1, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2212 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2213 73, 73, 73, 73, 73, 71, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2214 73, 73, 73, 73, 73, 73, 73, 73, 73, 70, 73, 73, 73, 73, 73, 73,
2215 73, 11, 73,  7, 73, 73, 73,  9,  4, 73,  5,  8, 73, 73, 73,  6,
2216 73, 72,  3,  1, 73, 73,  2, 73, 10, 73, 73, 73, 73, 73, 73, 73,
2217 -1, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
2218 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
2219 29, 29, 29, 26, 29, 29, 29, 25, 19, 17, 22, 29, 29, 29, 28, 23,
2220 29, 29, 18, 12, 29, 29, 20, 21, 29, 29, 29, 29, 29, 29, 29, 29,
2221 29, 11, 29,  7, 29, 29, 29,  9,  4, 29,  5,  8, 29, 29, 29,  6,
2222 29, 27,  3,  1, 29, 29,  2, 29, 10, 29, 29, 29, 29, 29, 29, 29,
2223 -1, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
2224 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
2225 49, 32, 49, 31, 33, 34, 35, 49, 38, 30, 49, 40, 37, 49, 49, 49,
2226 49, 49, 39, 41, 42, 45, 47, 46, 36, 49, 49, 49, 49, 49, 49, 49,
2227 49, 11, 49,  7, 44, 49, 49,  9,  4, 49,  5,  8, 49, 43, 49,  6,
2228 49, 48,  3,  1, 49, 49,  2, 49, 10, 49, 49, 49, 49, 49, 49, 49,
2229 -1, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2230 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2231 73, 73, 73, 73, 73, 71, 73, 73, 73, 17, 73, 73, 73, 73, 73, 73,
2232 73, 73, 73, 12, 73, 73, 73, 73, 73, 16, 73, 73, 73, 73, 73, 73,
2233 73, 11, 73,  7, 73, 73, 73,  9,  4, 73,  5,  8, 73, 73, 73,  6,
2234 73, 72,  3,  1, 73, 73,  2, 73, 10, 73, 73, 73, 73, 73, 73, 73,
2235 -1, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2236 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2237 73, 73, 73, 73, 73, 71, 52, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2238 73, 73, 73, 12, 73, 73, 73, 73, 53, 51, 73, 73, 73, 73, 73, 73,
2239 73, 11, 73,  7, 73, 73, 73,  9,  4, 73,  5,  8, 73, 73, 73,  6,
2240 73, 50,  3,  1, 73, 73,  2, 73, 10, 73, 73, 73, 73, 73, 73, 73,
2241 -1, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2242 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2243 73, 73, 73, 73, 73, 71, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2244 73, 73, 73, 73, 73, 73, 73, 73, 73, 14, 73, 73, 73, 73, 73, 73,
2245 73, 11, 73,  7, 73, 73, 73,  9,  4, 73,  5,  8, 73, 73, 73,  6,
2246 73, 72,  3,  1, 73, 73,  2, 73, 10, 73, 73, 73, 73, 73, 73, 73,
2247  0, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2248 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2249 73, 73, 73, 73, 73, 71, 73, 73, 73, 73, 73, 73, 73, 73, 73, 24,
2250 73, 73, 73, 12, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
2251 73, 11, 73,  7, 73, 73, 73,  9,  4, 73,  5,  8, 73, 73, 73,  6,
2252 73, 72,  3,  1, 73, 73,  2, 73, 10, 73, 73, 73, 73, 73, 73,73
2253};
2254
2255
2256/*
2257  From here down to proto() are routines that were moved out of the state
2258  table switcher because the resulting switch() had become too large.
2259  To move the contents of a state-table case to a routine:
2260    1. Add a prototype to the list above the state table switcher.
2261    2. Make a routine with an appropriate name, returning int.
2262    3. Move the code into it.
2263    4. Put a call to the new routine in the former spot:
2264         rc = name_of_routine();
2265         if (rc > -1) return(rc);
2266    5. Add "return(-1);" after every RESUME, SERVE, or BEGIN macro and
2267       at the end if the code is open-ended.
2268*/
2269static int
2270rcv_firstdata() {
2271    extern int dispos;
2272    debug(F101,"rcv_firstdata","",dispos);
2273
2274    if (discard) {                      /* if we're discarding the file */
2275        ack1((CHAR *)"X");              /* just ack the data like this. */
2276        cancel++;                       /* and count it */
2277        BEGIN rdpkt;                    /* and wait for more data packets. */
2278        return(-1);
2279    } else {                            /* Not discarding. */
2280        rf_err = "Can't open file";
2281        if (xflg) {                     /* If screen data */
2282            if (remfile) {              /* redirected to file */
2283                if (rempipe)            /* or pipe */
2284                  x = openc(ZOFILE,remdest); /* Pipe: start command */
2285                else
2286                  x = opena(remdest,&iattr); /* File: open with attributes */
2287            } else {                    /* otherwise */
2288                x = opent(&iattr);      /* "open" the screen */
2289            }
2290        } else {                        /* otherwise */
2291#ifdef CALIBRATE
2292            if (calibrate) {            /* If calibration run */
2293                x = ckopenx(&iattr);    /* open nothing */
2294#ifdef STREAMING
2295                if (streaming)          /* Streaming */
2296                  fastack();            /* ACK without ACKing. */
2297                else
2298#endif /* STREAMING */
2299                  ack();                /* Send real ACK */
2300                BEGIN rdpkt;            /* Proceed to next state */
2301                return(-1);
2302            } else
2303#endif /* CALIBRATE */
2304#ifdef UNIX
2305/*
2306  In UNIX we can pipe the file data into the mail program, which is to be
2307  preferred to writing it out to a temp file and then mailing it afterwards.
2308  This depends rather heavily on all UNIXes having a mail command that
2309  accepts '-s "subject"' on the command line.  MAILCMD (e.g. mail, Mail, mailx)
2310  is defined in ckufio.c.
2311*/
2312            if (dispos == 'M') {        /* Mail... */
2313                char *s;
2314                char * tmp = NULL;
2315                int n = 0;
2316                extern char *MAILCMD;
2317                s = iattr.disp.val + 1;
2318                n = (int)strlen(MAILCMD) +    /* Mail command */
2319                  (int)strlen(s) +            /* address */
2320                  (int)strlen(ofilnam) + 32;  /* subject */
2321                if (tmp = (char *)malloc(n)) {
2322                    ckmakxmsg(tmp,n,
2323                              MAILCMD," -s \"",ofilnam,"\" ",s,
2324                              NULL,NULL,NULL,NULL,NULL,NULL,NULL);
2325                    debug(F111,"rcv_firsdata mail",tmp,(int)strlen(tmp));
2326                    x = openc(ZOFILE,(char *)tmp);
2327                    free(tmp);
2328                } else
2329                  x = 0;
2330            } else if (dispos == 'P') { /* Ditto for print */
2331                char * tmp = NULL;
2332                int n;
2333                extern char *PRINTCMD;
2334                n = (int)strlen(PRINTCMD) + (int)strlen(iattr.disp.val+1) + 4;
2335                if (tmp = (char *)malloc(n)) {
2336                    sprintf(tmp,        /* safe (prechecked) */
2337                            "%s %s", PRINTCMD, iattr.disp.val + 1);
2338                    x = openc(ZOFILE,(char *)tmp);
2339                    free(tmp);
2340                } else
2341                  x = 0;
2342            } else
2343#endif /* UNIX */
2344              x = opena(filnam,&iattr); /* open the file, with attributes */
2345        }
2346        if (x) {                        /* If file was opened ok */
2347            int rc, qf;
2348#ifndef NOSPL
2349            qf = query;
2350#else
2351            qf = 0;
2352#endif /* NOSPL */
2353
2354#ifdef CKTUNING
2355            rc = (binary && !parity) ?
2356              bdecode(rdatap,putfil):
2357               decode(rdatap, qf ? puttrm : putfil, 1);
2358#else
2359            rc = decode(rdatap, qf ? puttrm : putfil, 1);
2360#endif /* CKTUNING */
2361            if (rc < 0) {
2362                errpkt((CHAR *)"Error writing data");
2363                RESUME;
2364                return(-1);
2365            }
2366#ifdef STREAMING
2367            if (streaming)              /* Streaming was negotiated */
2368              fastack();                /* ACK without ACKing. */
2369            else
2370#endif /* STREAMING */
2371              ack();                    /* acknowledge it */
2372            BEGIN rdpkt;                /* and switch to receive-data state */
2373            return(-1);
2374        } else {                        /* otherwise */
2375            errpkt((CHAR *) rf_err);    /* send error packet */
2376            RESUME;                     /* and quit. */
2377            return(-1);
2378        }
2379    }
2380}
2381
2382static int
2383rcv_shortreply() {
2384#ifdef PKTZEROHACK
2385    success = 0;
2386    debug(F111,"rcv_shortreply",rdatap,ipktlen);
2387    if (ipktack[0] && !strncmp(ipktack,(char *)rdatap,ipktlen)) {
2388        /* No it's the ACK to the I packet again */
2389        x = scmd(vcmd,(CHAR *)cmarg);   /* So send the REMOTE command again */
2390        /* Maybe this should be resend() */
2391        debug(F110,"IPKTZEROHACK",ipktack,x);
2392        if (x < 0) {
2393            errpkt((CHAR *)srimsg);
2394            RESUME;
2395            return(-1);
2396        }
2397    } else {
2398        ipktack[0] = NUL;
2399#endif /* PKTZEROHACK */
2400        urserver = 1;
2401#ifndef NOSERVER
2402#ifndef NOSPL
2403        if (query) {                    /* If to query, */
2404            qbufp = querybuf;           /*  initialize query response buffer */
2405            qbufn = 0;
2406            querybuf[0] = NUL;
2407        }
2408#endif /* NOSPL */
2409        x = 1;
2410        if (remfile) {                  /* Response redirected to file */
2411            rf_err = "Can't open file";
2412            if (rempipe)                /* or pipe */
2413              x =
2414#ifndef NOPUSH
2415                zxcmd(ZOFILE,remdest)   /* Pipe: Start command */
2416#else
2417                0
2418#endif /* NOPUSH */
2419                ;
2420            else
2421              x = opena(remdest,&iattr); /* File: Open with attributes */
2422            debug(F111,"rcv_shortreply remfile",remdest,x);
2423        } else {
2424            x = opent(&iattr);          /* "open" the screen */
2425        }
2426        if (x) {                        /* If file was opened ok */
2427            if (decode(rdatap,
2428#ifndef NOSPL
2429                       (query || !remfile) ? puttrm :
2430#else
2431                       !remfile ? puttrm :
2432#endif /* NOSPL */
2433                       zputfil, 1) < 0) { /* Note: zputfil, not putfil. */
2434                errpkt((CHAR *)"Error writing data");
2435                RESUME;
2436                return(-1);
2437            } else {
2438                if (rdatap)             /* If we had data */
2439                  if (*rdatap)          /* add a line terminator */
2440                    if (remfile) {      /* to file */
2441                        zsoutl(ZOFILE,"");
2442                    } else {            /* or to screen. */
2443#ifndef NOICP
2444                        if (!query || !xcmdsrc)
2445#endif /* NOICP */
2446                          if (!(quiet && rcdactive))
2447                            conoll("");
2448                    }
2449                if (bye_active && network) { /* I sent BYE or REMOTE LOGOUT */
2450                    msleep(500);        /* command and got the ACK... */
2451                    bye_active = 0;
2452                    ttclos(0);
2453                }
2454                clsof(0);
2455                if (!epktsent && !epktrcvd) /* If no error packet... */
2456                  success = 1;          /* success. */
2457                RESUME;
2458                return(-1);
2459            }
2460        } else {                        /* File not opened OK */
2461            errpkt((CHAR *) rf_err);    /* send error message */
2462            RESUME;                     /* and quit. */
2463            return(-1);
2464        }
2465#endif /* NOSERVER */
2466#ifdef PKTZEROHACK
2467    }
2468#endif /* PKTZEROHACK */
2469    debug(F101,"rcv_shortreply fallthru","",success);
2470    return(-1);
2471}
2472
2473
2474static int
2475srv_query() {
2476#ifndef NOSERVER
2477#ifndef NOSPL
2478    char c;
2479#ifdef CKSYSLOG
2480    if (ckxsyslog >= SYSLG_PR && ckxlogging)
2481      cksyslog(SYSLG_PR, 1, "server", "REMOTE QUERY", (char *)srvcmd);
2482#endif /* CKSYSLOG */
2483#ifdef IKSDB
2484    if (ikdbopen) slotstate(what,"REMOTE QUERY", (char *)(srvcmd+2), "");
2485#endif /* IKSDB */
2486    c = *(srvcmd+2);                    /* Q = Query, S = Set */
2487    if (c == 'Q') {                     /* Query */
2488        if (!ENABLED(en_que)) { /* Security */
2489            errpkt((CHAR *)"REMOTE QUERY disabled");
2490            RESUME;
2491            return(-1);
2492        } else {                        /* Query allowed */
2493            int n; char *p, *q;
2494            qbufp = querybuf;           /* Wipe out old stuff */
2495            qbufn = 0;
2496            querybuf[0] = NUL;
2497            p = (char *) srvcmd + 3;    /* Pointer for making wrapper */
2498            n = strlen((char *)srvcmd); /* Position of end */
2499            c = *(srvcmd+4);            /* Which type of variable */
2500
2501            if (*(srvcmd+6) == CMDQ) {  /* Starts with command quote? */
2502                p = (char *) srvcmd + 6; /* Take it literally */
2503                if (*p == CMDQ) p++;
2504            } else {                    /* They played by the rules */
2505                if (c == 'K') {         /* Kermit variable */
2506                    int k;
2507                    k = (int) strlen(p);
2508                    if (k > 0 && p[k-1] == ')') {
2509                        p = (char *)(srvcmd + 4);
2510                        *(srvcmd+4) = CMDQ;
2511                        *(srvcmd+5) = 'f'; /* Function, so make it \f...() */
2512                    } else {
2513                        *(srvcmd+3) = CMDQ; /* Stuff wrapping into buffer */
2514                        *(srvcmd+4) = 'v';  /* Variable, so make it \v(...) */
2515                        *(srvcmd+5) = '(';  /* around variable name */
2516                        *(srvcmd+n) = ')';
2517                        *(srvcmd+n+1) = NUL;
2518                    }
2519                } else {
2520                    *(srvcmd+3) = CMDQ; /* Stuff wrapping into buffer */
2521                    *(srvcmd+4) = 'v'; /*  Variable, so make it \v(...) */
2522                    *(srvcmd+5) = '(';  /* around variable name */
2523                    *(srvcmd+n) = ')';
2524                    *(srvcmd+n+1) = NUL;
2525                    if (c == 'S') {     /* System variable */
2526                        *(srvcmd+4) = '$'; /*  so it's \$(...) */
2527                    } else if (c == 'G') { /* Non-\ Global variable */
2528                        *(srvcmd+4) = 'm'; /*  so wrap it in \m(...) */
2529                    }
2530                }
2531            }                           /* Now evaluate it */
2532            n = QBUFL;                  /* Max length */
2533            q = querybuf;               /* Where to put it */
2534            if (zzstring(p,&q,&n) < 0) {
2535                errpkt((n > 0) ? (CHAR *)"Can't get value"
2536                               : (CHAR *)"Value too long"
2537                       );
2538                RESUME;
2539                return(-1);
2540            } else {
2541                if (encstr((CHAR *)querybuf) > -1) { /* Encode it */
2542                    ack1(data);         /* If it fits, send it back in ACK */
2543                    success = 1;
2544                    RESUME;
2545                    return(-1);
2546                } else if (sndstring(querybuf)) { /* Long form response */
2547                    BEGIN ssinit;
2548                    return(-1);
2549                } else {                /* sndhlp() fails */
2550                    errpkt((CHAR *)"Can't send value");
2551                    RESUME;
2552                    return(-1);
2553                }
2554            }
2555        }
2556    } else if (c == 'S') {              /* Set (assign) */
2557        if (!ENABLED(en_asg)) {         /* Security */
2558            errpkt((CHAR *)"REMOTE ASSIGN disabled");
2559            RESUME;
2560            return(-1);
2561        } else {                        /* OK */
2562            int n;
2563            n = xunchar(*(srvcmd+3));   /* Length of name */
2564            n = 3 + n + 1;              /* Position of length of value */
2565            *(srvcmd+n) = NUL;          /* Don't need it */
2566            if (addmac((char *)(srvcmd+4),(char *)(srvcmd+n+1)) < 0)
2567              errpkt((CHAR *)"REMOTE ASSIGN failed");
2568            else {
2569                ack();
2570                success = 1;
2571            }
2572            RESUME;
2573            return(-1);
2574        }
2575    } else {
2576        errpkt((CHAR *)"Badly formed server command");
2577        RESUME;
2578        return(-1);
2579    }
2580#else
2581    errpkt((CHAR *)"Variable query/set not available");
2582    RESUME;
2583    return(-1);
2584#endif /* NOSPL */
2585#endif /* NOSERVER */
2586}
2587
2588static int
2589srv_copy() {
2590#ifndef NOSERVER
2591#ifdef CKSYSLOG
2592    if (ckxsyslog >= SYSLG_PR && ckxlogging)
2593      cksyslog(SYSLG_PR, 1, "server", "REMOTE COPY", (char *)srvcmd);
2594#endif /* CKSYSLOG */
2595#ifdef ZCOPY
2596    if (!ENABLED(en_cpy)) {
2597        errpkt((CHAR *)"REMOTE COPY disabled");
2598        RESUME;
2599        return(-1);
2600    } else {
2601        char *str1, *str2, f1[256], f2[256];
2602        int  len1, len2;
2603        len1 = xunchar(srvcmd[1]);      /* Separate the parameters */
2604        len2 = xunchar(srvcmd[2+len1]);
2605        strncpy(f1,(char *)(srvcmd+2),len1);
2606        f1[len1] = NUL;
2607        strncpy(f2,(char *)(srvcmd+3+len1),len2);
2608        f2[len2] = NUL;
2609#ifdef IKSDB
2610        if (ikdbopen) slotstate(what,"REMOTE COPY", f1, f2);
2611#endif /* IKSDB */
2612        if (!ENABLED(en_cwd)) {         /* If CWD is disabled */
2613            zstrip(f1,&str1);           /* and they included a pathname, */
2614            zstrip(f2,&str2);
2615            if (strcmp(f1,str1) || strcmp(f2,str2)) { /* Refuse. */
2616                errpkt((CHAR *)"Access denied");
2617                RESUME;                 /* Remember, this is not a goto! */
2618                return(-1);
2619            }
2620        }
2621        if (state == generic) {         /* It's OK to go ahead. */
2622            if (zcopy(f1,f2)) {         /* Try */
2623                errpkt((CHAR *)"Can't copy file"); /* give error message */
2624            } else {
2625                success = 1;
2626                ack();
2627            }
2628            RESUME;                     /* wait for next server command */
2629            return(-1);
2630        }
2631    }
2632    return(-1);
2633#else /* no ZCOPY */
2634    errpkt((CHAR *)"REMOTE COPY not available"); /* give error message */
2635    RESUME;                             /* wait for next server command */
2636    return(-1);
2637#endif /* ZCOPY */
2638#endif /* NOSERVER */
2639}
2640
2641static int
2642srv_rename() {
2643#ifndef NOSERVER
2644#ifdef CKSYSLOG
2645    if (ckxsyslog >= SYSLG_PR && ckxlogging)
2646      cksyslog(SYSLG_PR, 1, "server", "REMOTE RENAME", (char *)srvcmd);
2647#endif /* CKSYSLOG */
2648#ifdef ZRENAME
2649    if (!ENABLED(en_ren)) {
2650        errpkt((CHAR *)"REMOTE RENAME disabled");
2651        RESUME;
2652        return(-1);
2653    } else {                            /* RENAME is enabled */
2654        char *str1, *str2, f1[256], f2[256];
2655        int len1, len2;
2656        len1 = xunchar(srvcmd[1]);      /* Separate the parameters */
2657        len2 = xunchar(srvcmd[2+len1]);
2658        strncpy(f1,(char *)(srvcmd+2),len1);
2659        f1[len1] = NUL;
2660        strncpy(f2,(char *)(srvcmd+3+len1),len2);
2661        f2[len2] = NUL;
2662        len2 = xunchar(srvcmd[2+len1]);
2663        strncpy(f1,(char *)(srvcmd+2),len1);
2664        f1[len1] = NUL;
2665        strncpy(f2,(char *)(srvcmd+3+len1),len2);
2666        f2[len2] = NUL;
2667#ifdef IKSDB
2668        if (ikdbopen) slotstate(what,"REMOTE RENAME", f1, f2);
2669#endif /* IKSDB */
2670        if (!ENABLED(en_cwd)) {         /* If CWD is disabled */
2671            zstrip(f1,&str1);           /* and they included a pathname, */
2672            zstrip(f2,&str2);
2673            if ( strcmp(f1,str1) || strcmp(f2,str2) ) { /* refuse. */
2674                errpkt((CHAR *)"Access denied");
2675                RESUME;                 /* Remember, this is not a goto! */
2676                return(-1);
2677            }
2678        }
2679        if (state == generic) {         /* It's OK to go ahead. */
2680            if (zrename(f1,f2)) {       /* Try */
2681                errpkt((CHAR *)"Can't rename file"); /* Give error msg */
2682            } else {
2683                success = 1;
2684                ack();
2685            }
2686            RESUME;                     /* Wait for next server command */
2687            return(-1);
2688        }
2689    }
2690    return(-1);
2691#else /* no ZRENAME */
2692    /* Give error message */
2693    errpkt((CHAR *)"REMOTE RENAME not available");
2694    RESUME;                             /* Wait for next server command */
2695    return(-1);
2696#endif /* ZRENAME */
2697#endif /* NOSERVER */
2698}
2699
2700static int
2701srv_login() {
2702#ifndef NOSERVER
2703    char f1[LOGINLEN+1], f2[LOGINLEN+1], f3[LOGINLEN+1];
2704    CHAR *p;
2705    int len, i;
2706
2707    debug(F101,"REMOTE LOGIN x_login","",x_login);
2708    debug(F101,"REMOTE LOGIN x_logged","",x_logged);
2709
2710    f1[0] = NUL; f2[0] = NUL; f3[0] = NUL;
2711    len = 0;
2712    if (srvcmd[1])                      /* First length field */
2713      len = xunchar(srvcmd[1]);         /* Separate the parameters */
2714
2715    if (x_login) {                      /* Login required */
2716        if (x_logged) {                 /* And already logged in */
2717            if (len > 0) {              /* Logging in again */
2718                errpkt((CHAR *)"Already logged in.");
2719            } else {                    /* Logging out */
2720                debug(F101,"REMOTE LOGOUT","",x_logged);
2721#ifdef CKSYSLOG
2722                if (ckxsyslog >= SYSLG_PR && ckxlogging)
2723                  cksyslog(SYSLG_PR, 1, "server", "REMOTE LOGOUT", NULL);
2724#endif /* CKSYSLOG */
2725#ifdef IKSDB
2726                if (ikdbopen) slotstate(what,"REMOTE LOGOUT", "", "");
2727#endif /* IKSDB */
2728                tlog(F110,"Logged out",x_user,0);
2729                ack1((CHAR *)"Logged out");
2730                success = 1;
2731                msleep(500);
2732#ifdef CK_LOGIN
2733                x_logged = 0;
2734#ifdef IKSD
2735                if (inserver)
2736                  ckxlogout();
2737#endif /* IKSD */
2738#endif /* CK_LOGIN */
2739            }
2740        } else {                        /* Not logged in yet */
2741            debug(F101,"REMOTE LOGIN len","",len);
2742            if (len > 0) {              /* Have username */
2743#ifdef CKSYSLOG
2744                if (ckxsyslog >= SYSLG_PR && ckxlogging)
2745                  cksyslog(SYSLG_PR, 1, "server", "REMOTE LOGIN", NULL);
2746#endif /* CKSYSLOG */
2747                if (len > LOGINLEN) {
2748                    errpkt((CHAR *)"Username too long");
2749                }
2750                p = srvcmd + 2;         /* Point to it */
2751                for (i = 0; i < len; i++) /* Copy it */
2752                  f1[i] = p[i];
2753                f1[len] = NUL;          /* Terminate it */
2754                p += len;               /* Point to next length field */
2755                if (*p) {               /* If we have one */
2756                    len = xunchar(*p++); /* decode it */
2757                    if (len > 0 && len <= LOGINLEN) {
2758                        for (i = 0; i < len; i++) /* Same deal for password */
2759                          f2[i] = p[i];
2760                        f2[len] = NUL;
2761                        p += len;       /* And account */
2762                        if (*p) {
2763                            len = xunchar(*p++);
2764                            if (len > 0 && len <= LOGINLEN) {
2765                                for (i = 0; i < len; i++)
2766                                  f3[i] = p[i]; /* Set but never used */
2767                                f3[len] = NUL; /* (because account not used) */
2768                            }
2769                        }
2770                    }
2771                }
2772                debug(F101,"REMOTE LOGIN 1","",x_logged);
2773#ifdef IKSD
2774#ifdef CK_LOGIN
2775                if (inserver) {         /* Log in to system for real */
2776                    x_logged = ckxlogin((CHAR *)f1,(CHAR *)f2,NULL,0);
2777                    debug(F101,"REMOTE LOGIN 2","",x_logged);
2778                    if (x_logged) {     /* Count attempts */
2779                        logtries = 0;
2780                        justone = 1;
2781                    } else {
2782                        logtries++;
2783                        sleep(logtries);
2784                    }
2785                } else
2786#endif /* CK_LOGIN */
2787#endif /* IKSD */
2788                  if (x_user && x_passwd) { /* User and password must match */
2789                      if (!strcmp(x_user,f1)) /* SET SERVER LOGIN */
2790                        if (!strcmp(x_passwd,f2))
2791                          x_logged = 1;
2792                      debug(F101,"REMOTE LOGIN 3","",x_logged);
2793                  } else if (x_user) {  /* Only username given, no password */
2794                      if (!strcmp(x_user,f1)) /* so only username must match */
2795                        x_logged = 1;
2796                      debug(F101,"REMOTE LOGIN 4","",x_logged);
2797                  }
2798#ifdef CK_LOGIN
2799                else {
2800                    x_logged = ckxlogin((CHAR *)f1,(CHAR *)f2,NULL,0);
2801                    debug(F101,"REMOTE LOGIN 5","",x_logged);
2802                }
2803#endif /* CK_LOGIN */
2804                if (x_logged) {         /* Logged in? */
2805                    tlog(F110,"Logged in", x_user, 0);
2806                    if (isguest)
2807                      ack1((CHAR *)"Logged in as guest - restrictions apply");
2808                    else
2809                      ack1((CHAR *)"Logged in");
2810                    success = 1;
2811                } else {
2812                    tlog(F110,"Login failed", f1, 0);
2813                    errpkt((CHAR *)"Access denied.");
2814#ifdef IKSD
2815#ifdef CK_LOGIN
2816                    if (inserver && logtries > 2)
2817                      ckxlogout();
2818#endif /* CK_LOGIN */
2819#endif /* IKSD */
2820                }
2821            } else {                    /* LOGOUT */
2822                errpkt((CHAR *)"Logout ignored");
2823            }
2824        }
2825    } else {                            /* Login not required */
2826        if (len > 0)
2827          errpkt((CHAR *)"Login ignored.");
2828        else
2829          errpkt((CHAR *)"Logout ignored.");
2830    }
2831#endif /* NOSERVER */
2832    RESUME;
2833    return(-1);
2834}
2835
2836static int
2837srv_timeout() {
2838    /* K95 does this its own way */
2839    if (idletmo) {
2840#ifdef IKSD
2841        if (inserver) {
2842           printf("\r\nIKSD IDLE TIMEOUT: %d sec\r\n", srvidl);
2843           doexit(GOOD_EXIT,xitsta);
2844        }
2845#endif /* IKSD */
2846        idletmo = 0;
2847        printf("\r\nSERVER IDLE TIMEOUT: %d sec\r\n", srvidl);
2848        xitsta |= (what & W_KERMIT);
2849        QUIT;
2850    }
2851#ifndef NOSERVER
2852    else if (fatalio) {                 /* Connection lost */
2853#ifdef CKSYSLOG
2854          if (ckxsyslog >= SYSLG_PR && ckxlogging)
2855            cksyslog(SYSLG_PR, 1, "server", "Connection lost", NULL);
2856#endif /* CKSYSLOG */
2857#ifdef IKSDB
2858          if (ikdbopen) slotstate(what,"SERVER DISCONNECT",(char *)srvcmd, "");
2859#endif /* IKSDB */
2860        xitsta |= what;
2861        QUIT;
2862    } else if (interrupted) {           /* Interrupted by hand */
2863        if (!ENABLED(en_fin)) {
2864            errpkt((CHAR *)"QUIT disabled");
2865            RESUME;
2866            return(-1);
2867        } else {
2868            if (what == W_SEND || what == W_RECV || what == W_REMO) {
2869                success = 0;
2870#ifdef CKSYSLOG
2871                if (ckxsyslog >= SYSLG_PR && ckxlogging)
2872                  cksyslog(SYSLG_PR, 1, "server", "Interrupted", NULL);
2873#endif /* CKSYSLOG */
2874            } else if (what == W_NOTHING && filcnt == 0) {
2875                success = 1;
2876            } /* Otherwise leave success alone */
2877            xitsta |= (what & W_KERMIT);
2878            QUIT;
2879        }
2880    } else {                            /* Shouldn't happen */
2881        debug(F100,"SERVER (top) GOT UNEXPECTED 'q'","",0);
2882        QUIT;
2883    }
2884#endif /* NOSERVER */
2885}
2886
2887static int
2888rcv_s_pkt() {
2889#ifndef NOSERVER
2890    if (state == rgen)
2891      urserver = 1;
2892    if (/* state == serve && */ x_login && !x_logged) {
2893        errpkt((CHAR *)"Login required");
2894        SERVE;
2895    } else
2896#endif /* NOSERVER */
2897      if (state == serve && !ENABLED(en_sen)) { /* Not in server mode */
2898        errpkt((CHAR *)"SEND disabled"); /* when SEND is disabled. */
2899        RESUME;
2900        return(-1);
2901    } else {                            /* OK to go ahead. */
2902#ifdef CK_TMPDIR
2903        if (dldir && !f_tmpdir) {       /* If they have a download directory */
2904            debug(F110,"receive download dir",dldir,0);
2905            if (s = zgtdir()) {         /* Get current directory */
2906                debug(F110,"receive current dir",s,0);
2907                if (zchdir(dldir)) {    /* Change to download directory */
2908                    debug(F100,"receive zchdir ok","",0);
2909                    ckstrncpy(savdir,s,TMPDIRLEN);
2910                    f_tmpdir = 1;       /* Remember that we did this */
2911                } else
2912                  debug(F100,"receive zchdir failed","",0);
2913            }
2914        }
2915#endif /* CK_TMPDIR */
2916        nakstate = 1;                   /* Can send NAKs from here. */
2917        rinit(rdatap);                  /* Set parameters */
2918        bctu = bctr;                    /* Switch to agreed-upon block check */
2919        bctl = (bctu == 4) ? 2 : bctu;  /* Set block-check length */
2920        what = W_RECV;                  /* Remember we're receiving */
2921        lastxfer = W_RECV;
2922        resetc();                       /* Reset counters */
2923        rtimer();                       /* Reset timer */
2924#ifdef GFTIMER
2925        rftimer();
2926#endif /* GFTIMER */
2927        streamon();
2928        BEGIN rfile;                    /* Go into receive-file state */
2929    }
2930    return(-1);
2931}
2932
2933
2934/* END OF ROUTINES MOVED OUT OF STATE MACHINE */
2935
2936
2937/*  P R O T O  --  Protocol entry function  */
2938
2939static int is_tn = 0;                   /* It's a Telnet connection */
2940
2941#ifdef CK_SPEED
2942int f_ctlp = 0;                         /* Control-character prefix table */
2943#ifdef COMMENT
2944short s_ctlp[256];
2945#endif /* COMMENT */
2946#endif /* CK_SPEED */
2947
2948/*
2949  This is simply a wrapper for the real protocol function just below,
2950  that saves any items that might be changed automatically by protocol
2951  negotiations and then restores them upon exit from protocol mode.
2952*/
2953VOID
2954proto() {
2955    extern int b_save, f_save, c_save, ss_save, slostart, reliable, urclear;
2956#ifndef NOCSETS
2957    extern int fcharset, fcs_save, tcharset, tcs_save;
2958#endif /* NOCSETS */
2959
2960#ifdef PIPESEND
2961    extern int pipesend;
2962#endif /* PIPESEND */
2963#ifndef NOLOCAL
2964#ifdef OS2
2965    extern int cursorena[], cursor_save, term_io;
2966    extern BYTE vmode;
2967    extern int display_demo;
2968    int term_io_save;
2969#endif /* OS2 */
2970#endif /* NOLOCAL */
2971#ifdef TNCODE
2972    int _u_bin=0, _me_bin = 0;
2973#ifdef IKS_OPTION
2974    int /* _u_start=0, */ _me_start = 0;
2975#endif /* IKS_OPTION */
2976#endif /* TNCODE */
2977#ifdef PATTERNS
2978    int pa_save;
2979    int i;
2980#endif /* PATTERNS */
2981    int scan_save;
2982
2983#ifdef PATTERNS
2984    pa_save = patterns;
2985#endif /* PATTERNS */
2986    scan_save = filepeek;
2987
2988    myjob = sstate;
2989
2990#ifdef CK_LOGIN
2991    if (isguest) {                      /* If user is anonymous */
2992        en_pri = 0;                     /* disable printing */
2993        en_mai = 0;                     /* and disable email */
2994        en_del = 0;                     /* and file deletion */
2995    }
2996#endif /* CK_LOGIN */
2997
2998#ifndef NOLOCAL
2999#ifdef OS2
3000    cursor_save = cursorena[vmode];
3001    cursorena[vmode] = 0;
3002    term_io_save = term_io;
3003    term_io = 0;
3004#endif /* OS2 */
3005#endif /* NOLOCAL */
3006    b_save = binary;                    /* SET FILE TYPE */
3007    f_save = fncnv;                     /* SET FILE NAMES */
3008    c_save = bctr;
3009    p_save = fnspath;
3010    r_save = recursive;
3011    s_timint = timint;
3012    ss_save = slostart;
3013#ifndef NOCSETS
3014    fcs_save = fcharset;
3015    tcs_save = tcharset;
3016#endif /* NOCSETS */
3017
3018#ifdef COMMENT
3019/* Don't do this because then user can never find out what happened. */
3020#ifdef CK_SPEED
3021    for (i = 0; i < 256; i++)
3022      s_ctlp[i] = ctlp[i];
3023    f_ctlp = 1;
3024#endif /* CK_SPEED */
3025#endif /* COMMENT */
3026    if (reliable == SET_ON)
3027      slostart = 0;
3028    is_tn = (!local && sstelnet)
3029#ifdef TNCODE
3030      || (local && network && ttnproto == NP_TELNET)
3031#endif /* TNCODE */
3032        ;
3033#ifdef TNCODE
3034    if (is_tn) {
3035        if (tn_b_xfer && !(sstelnet || inserver)) {
3036            /* Save the current state of Telnet Binary */
3037            _u_bin = TELOPT_U(TELOPT_BINARY);
3038            _me_bin = TELOPT_ME(TELOPT_BINARY);
3039
3040            /* If either direction is not Binary attempt to negotiate it */
3041            if (!_u_bin && TELOPT_U_MODE(TELOPT_BINARY) != TN_NG_RF) {
3042                tn_sopt(DO,TELOPT_BINARY);
3043                TELOPT_UNANSWERED_DO(TELOPT_BINARY) = 1;
3044            }
3045            if (!_me_bin && TELOPT_ME_MODE(TELOPT_BINARY) != TN_NG_RF) {
3046                tn_sopt(WILL,TELOPT_BINARY);
3047                TELOPT_UNANSWERED_WILL(TELOPT_BINARY) = 1;
3048            }
3049            if (!(_me_bin && _u_bin))
3050              tn_wait("proto set binary mode");
3051        }
3052#ifdef IKS_OPTION
3053#ifdef CK_XYZ
3054        if (protocol != PROTO_K) {      /* Non-Kermit protocol selected */
3055            if (TELOPT_U(TELOPT_KERMIT) &&
3056                TELOPT_SB(TELOPT_KERMIT).kermit.u_start) {
3057                iks_wait(KERMIT_REQ_STOP,0); /* Stop the other Server */
3058                /* _u_start = 1; */
3059            }
3060            if (TELOPT_ME(TELOPT_KERMIT) &&
3061                TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
3062                tn_siks(KERMIT_STOP);   /* I'm not servering */
3063                TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
3064                _me_start = 1;
3065            }
3066        } else
3067#endif /* CK_XYZ */
3068        if (sstate == 'x' || sstate == 'v') { /* Responding to a request */
3069            if (!inserver && TELOPT_U(TELOPT_KERMIT) &&
3070                TELOPT_SB(TELOPT_KERMIT).kermit.u_start) {
3071                iks_wait(KERMIT_REQ_STOP,0); /* Stop the other Server */
3072                /* _u_start = 1; */
3073            }
3074            if (TELOPT_ME(TELOPT_KERMIT) &&
3075                !TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
3076                tn_siks(KERMIT_START);  /* Send Kermit-Server Start */
3077                TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 1;
3078            }
3079        } else {                        /* Initiating a request */
3080            if (TELOPT_ME(TELOPT_KERMIT) &&
3081                TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
3082                tn_siks(KERMIT_STOP);   /* I'm not servering */
3083                TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
3084                _me_start = 1;
3085            }
3086            if (TELOPT_U(TELOPT_KERMIT) &&
3087                !TELOPT_SB(TELOPT_KERMIT).kermit.u_start) {
3088                /* Send Req-Server-Start */
3089                if (!iks_wait(KERMIT_REQ_START,0)) {
3090                    if (sstate != 's') {
3091                        success = 0;    /* Other Kermit refused to serve */
3092                        if (local)
3093                          printf("A Kermit Server is not available\r\n");
3094                        debug(F110,"proto()",
3095                             "A Kermit Server is not available",0);
3096                        tlog(F110,"IKS client/server failure",
3097                             "A Kermit Server is not available",0);
3098                        goto xxprotox;
3099                    }
3100                }
3101            }
3102        }
3103#endif /* IKS_OPTION */
3104#ifdef CK_ENCRYPTION
3105        if (tn_no_encrypt_xfer && !(sstelnet || inserver)) {
3106            ck_tn_enc_stop();
3107        }
3108#endif /* CK_ENCRYPTION */
3109    }
3110#endif /* TNCODE */
3111
3112    if (!xfrint) connoi();
3113    xxproto();                          /* Call the real protocol function */
3114
3115#ifdef IKS_OPTION
3116  xxprotox:
3117#endif /* IKS_OPTION */
3118    xferstat = success;                 /* Remember transfer status */
3119    kactive = 0;
3120
3121#ifdef TNCODE
3122#ifdef CK_ENCRYPTION
3123        if (tn_no_encrypt_xfer && !(sstelnet || inserver)) {
3124            ck_tn_enc_start();
3125        }
3126#endif /* CK_ENCRYPTION */
3127#ifdef IKS_OPTION
3128    if (TELOPT_ME(TELOPT_KERMIT) &&
3129        TELOPT_SB(TELOPT_KERMIT).kermit.me_start && !_me_start) {
3130        tn_siks(KERMIT_STOP);           /* Server is stopped */
3131        TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
3132    }
3133#endif /* IKS_OPTION */
3134    if (is_tn && tn_b_xfer && !(sstelnet || inserver)) {
3135        /* if we negotiated Binary mode try to reset it */
3136        if (!_u_bin) {
3137            /* Check to see if the state changed during the transfer */
3138            if (TELOPT_U(TELOPT_BINARY)) {
3139                tn_sopt(DONT,TELOPT_BINARY);
3140                TELOPT_UNANSWERED_DONT(TELOPT_BINARY) = 1;
3141            } else
3142              _u_bin = 1;               /* So we don't call tn_wait() */
3143        }
3144        if (!_me_bin) {
3145            /* Check to see if the state changed during the transfer */
3146            if (TELOPT_ME(TELOPT_BINARY)) {
3147                tn_sopt(WONT,TELOPT_BINARY);
3148                TELOPT_UNANSWERED_WONT(TELOPT_BINARY) = 1;
3149            } else
3150              _me_bin = 1;              /* So we don't call tn_wait() */
3151        }
3152        if (!(_me_bin && _u_bin))
3153          tn_wait("proto reset binary mode");
3154    }
3155#endif /* TNCODE */
3156
3157#ifdef PATTERNS
3158    patterns = pa_save;
3159#endif /* PATTERNS */
3160    filepeek = scan_save;
3161
3162#ifdef STREAMING
3163    streaming = 0;
3164    /* streamok = 0; */
3165#endif /* STREAMING */
3166#ifdef COMMENT
3167#ifdef CK_SPEED
3168    for (i = 0; i < 256; i++)
3169      ctlp[i] = s_ctlp[i];
3170    f_ctlp = 0;
3171#endif /* CK_SPEED */
3172#endif /* COMMENT */
3173    urclear = 0;
3174    if (!success) {
3175        xitsta |= (what & W_KERMIT);
3176        tlog(F110," failed:",(char *)epktmsg,0);
3177    }
3178    debug(F111,"proto xferstat",epktmsg,xferstat);
3179    slostart = ss_save;
3180    if (s_timint > -1) {                /* Because of REMOTE SET */
3181        timint = s_timint;
3182        s_timint = -1;
3183    }
3184    recursive = r_save;
3185    fnspath = p_save;
3186    if (c_save > -1) {                  /* Because of REMOTE SET */
3187        bctr = c_save;
3188        c_save = -1;
3189    }
3190    fncnv   = f_save;
3191    binary  = b_save;
3192#ifdef PIPESEND
3193    pipesend = 0;                       /* Next time might not be pipesend */
3194#endif /* PIPESEND */
3195#ifndef NOLOCAL
3196#ifdef OS2
3197    cursorena[vmode] = cursor_save;
3198    term_io = term_io_save;
3199    display_demo = 1;
3200#endif /* OS2 */
3201#endif /* NOLOCAL */
3202}
3203
3204static VOID
3205xxproto() {
3206    int x;
3207    long lx;
3208#ifdef CK_XYZ
3209#ifdef XYZ_INTERNAL
3210_PROTOTYP( int pxyz, (int) );
3211#endif /* XYZ_INTERNAL */
3212#endif /* CK_XYZ */
3213
3214    char xss[2];                        /* String representation of sstate */
3215    xss[0] = sstate;
3216    xss[1] = NUL;
3217    s_timint = timint;
3218
3219    debug(F101,"xxproto entry justone","",justone);
3220    success = 0;
3221
3222    retrieve = 0;                       /* Reset these ... */
3223    reget = 0;
3224    opkt = 0;
3225
3226    if (local && ttchk() < 0) {         /* Giving BYE or FIN */
3227        if (bye_active) {               /* but there is no connection */
3228            ttclos(0);
3229            success = 1;
3230            return;
3231        }
3232        /* Ditto for any REMOTE command */
3233        if (sstate == 'g' && cmarg ) {
3234            if (*cmarg == 'L' || *cmarg == 'F' || *cmarg == 'X')
3235              success = 1;
3236            else
3237              printf("?No connection\r\n");
3238            return;
3239        }
3240    }
3241
3242/* Set up the communication line for file transfer. */
3243/* NOTE: All of the xxscreen() calls prior to the wart() invocation */
3244/* could just as easily be printf's or, for that matter, hints. */
3245
3246    if (local && (speed < 0L) && (network == 0)) {
3247        xxscreen(SCR_EM,0,0L,"Sorry, you must 'set speed' first");
3248        return;
3249    }
3250    x = -1;
3251    if (ttopen(ttname,&x,mdmtyp,cdtimo) < 0) {
3252        debug(F111,"failed: proto ttopen local",ttname,local);
3253        xxscreen(SCR_EM,0,0L,"Can't open line");
3254        return;
3255    }
3256    if (x > -1) local = x;
3257    debug(F111,"proto ttopen local",ttname,local);
3258
3259    lx = (local && !network) ? speed : -1;
3260#ifdef NETCONN
3261#ifdef CK_SPEED
3262    if (is_tn) {
3263        ctlp[(unsigned)255] = ctlp[CR] = 1;
3264        if (parity == 'e' || parity == 'm') ctlp[127] = 1;
3265        if (flow == FLO_XONX) {         /* Also watch out for Xon/Xoff */
3266            ctlp[17] = ctlp[19] = 1;
3267            ctlp[17+128] = ctlp[19+128] = 1;
3268        }
3269    }
3270#endif /* CK_SPEED */
3271#endif /* NETCONN */
3272    if (ttpkt(lx,flow,parity) < 0) {    /* Put line in packet mode, */
3273        xxscreen(SCR_EM,0,0L,"Can't condition line");
3274        return;
3275    }
3276    if (local && !network && carrier != CAR_OFF) {
3277        int x;                          /* Serial connection */
3278        x = ttgmdm();                   /* with carrier checking */
3279        if (x > -1) {
3280            if (!(x & BM_DCD)) {
3281                debug(F101,"proto ttgmdm","",0);
3282                xxscreen(SCR_EM,0,0L,"Carrier required but not detected");
3283                return;
3284            }
3285        }
3286    }
3287    /* Send remote side's "receive" or "server" startup string, if any */
3288    if (local && ckindex((char *)xss,"srgcjhk",0,0,1)) {
3289        char *s = NULL;
3290        if (
3291#ifdef IKS_OPTION
3292            /* Don't send auto-blah string if we know other side is serving */
3293            !TELOPT_U(TELOPT_KERMIT) ||
3294            !TELOPT_SB(TELOPT_KERMIT).kermit.u_start
3295#else
3296            1
3297#endif /* IKS_OPTION */
3298            ) {
3299            if (sstate == 's') {        /* Sending file(s) */
3300                s = binary ? ptab[protocol].h_b_init : ptab[protocol].h_t_init;
3301            } else if (protocol == PROTO_K) { /* Command for server */
3302                s = ptab[protocol].h_x_init;
3303            }
3304        }
3305#ifdef CK_SPEED
3306#ifndef UNPREFIXZERO
3307        if (protocol == PROTO_K)        /* Because of C-strings... */
3308          ctlp[0] = 1;
3309#endif /* UNPREFIXZERO */
3310#endif /* CK_SPEED */
3311        if (s) if (*s) {                /* If we have a command to send... */
3312            char tmpbuf[356];
3313            int tmpbufsiz = 356;
3314            int stuff = -1, stuff2 = -1, len = 0;
3315            extern int tnlm;
3316            if (sstate == 's') {        /* Sending file(s) */
3317#ifdef CK_XYZ
3318                if (protocol == PROTO_X) {
3319                    char * s2;
3320                    s2 = cmarg2[0] ? cmarg2 : cmarg;
3321                    if ((int)strlen(s) + (int)strlen(s2) + 4 < 356)
3322                      sprintf(tmpbuf, s, s2);
3323                    else
3324                      tmpbuf[0] = NUL;
3325                } else {
3326#endif /* CK_XYZ */
3327                    ckmakmsg(tmpbuf, 356, s, NULL, NULL, NULL);
3328#ifdef CK_XYZ
3329                }
3330#endif /* CK_XYZ */
3331            } else {                    /* Command for server */
3332                ckstrncpy(tmpbuf,s,356);
3333            }
3334            ckstrncat(tmpbuf, "\015",sizeof(tmpbuf));
3335            if (tnlm)                   /* TERMINAL NEWLINE ON */
3336              stuff = LF;               /* Stuff LF */
3337#ifdef TNCODE
3338            /* TELNET NEWLINE MODE */
3339            if (is_tn) {
3340                switch (TELOPT_ME(TELOPT_BINARY) ? tn_b_nlm : tn_nlm) {
3341                  case TNL_CR:
3342                    break;
3343                  case TNL_CRNUL:
3344                    break;
3345                  case TNL_CRLF:
3346                    stuff2 = stuff;
3347                    stuff = LF;
3348                    break;
3349                }
3350            }
3351#endif /* TNCODE */
3352
3353#ifdef NETCONN
3354#ifdef TCPSOCKET
3355#ifdef RLOGCODE
3356            if (network && ttnproto == NP_RLOGIN) {
3357                switch (tn_b_nlm) { /* Always BINARY */
3358                  case TNL_CR:
3359                    break;
3360                  case TNL_CRNUL:
3361                    stuff2 = stuff;
3362                    stuff  = NUL;
3363                    break;
3364                  case TNL_CRLF:
3365                    stuff2 = stuff;
3366                    stuff = LF;
3367                    break;
3368                }
3369            }
3370#endif /* RLOGCODE */
3371#endif /* TCPSOCKET */
3372#endif /* NETCONN */
3373
3374            len = strlen(tmpbuf);
3375            if (stuff >= 0 && len < tmpbufsiz - 1) {
3376                tmpbuf[len++] = stuff;
3377                if (stuff2 >= 0 && len < tmpbufsiz - 1)
3378                  tmpbuf[len++] = stuff2;
3379                tmpbuf[len] = NUL;
3380            }
3381            ttol((CHAR *)tmpbuf,len);
3382            if (protocol == PROTO_K)    /* Give remote Kermit time to start */
3383              msleep(400);
3384        }
3385    }
3386
3387#ifdef CK_XYZ
3388    if (protocol != PROTO_K) {          /* Non-Kermit protocol selected */
3389        char tmpbuf[356];
3390        int tmpbufsiz = 356;
3391        char * s = "";
3392
3393#ifdef CK_TMPDIR
3394        if (sstate == 'v') {            /* If receiving and... */
3395            if (dldir && !f_tmpdir) {   /* if they have a download directory */
3396                if (s = zgtdir()) {     /* Get current directory */
3397                    if (zchdir(dldir)) { /* Change to download directory */
3398                        ckstrncpy(savdir,s,TMPDIRLEN);
3399                        f_tmpdir = 1;   /* Remember that we did this */
3400                    }
3401                }
3402            }
3403        }
3404#endif /* CK_TMPDIR */
3405
3406#ifdef XYZ_INTERNAL                     /* Internal */
3407        success = !pxyz(sstate);
3408#else
3409#ifdef CK_REDIR                         /* External */
3410        switch (sstate) {
3411          case 's':                     /* 'Tis better to SEND... */
3412            s = binary ? ptab[protocol].p_b_scmd : ptab[protocol].p_t_scmd;
3413            break;
3414          case 'v':                     /* ... than RECEIVE */
3415            s = binary ? ptab[protocol].p_b_rcmd : ptab[protocol].p_t_rcmd;
3416            break;
3417        }
3418        if (!s) s = "";
3419        if (*s) {
3420            if (sstate == 's') {
3421                if ((int)strlen(s) + (int)strlen(fspec) < tmpbufsiz) {
3422                    sprintf(tmpbuf,s,fspec); /* safe (prechecked) */
3423                    tlog(F110,"Sending",fspec,0L);
3424                }
3425            } else {
3426                if ((int)strlen(s) + (int)strlen(cmarg2) < tmpbufsiz) {
3427                    sprintf(tmpbuf,s,cmarg2); /* safe (prechecked) */
3428                    tlog(F110,"Receiving",cmarg2,0L);
3429                }
3430            }
3431            tlog(F110," via external protocol:",tmpbuf,0);
3432            debug(F110,"ckcpro ttruncmd",tmpbuf,0);
3433            success = ttruncmd(tmpbuf);
3434            tlog(F110," status:",success ? "OK" : "FAILED", 0);
3435        } else {
3436            printf("?Sorry, no external protocol defined for %s\r\n",
3437                   ptab[protocol].p_name
3438                   );
3439        }
3440#else
3441        printf(
3442"Sorry, only Kermit protocol is supported in this version of Kermit\n"
3443               );
3444#endif /* CK_REDIR */
3445#endif /* XYZ_INTERNAL */
3446        return;
3447    }
3448#endif /* CK_XYZ */
3449
3450#ifdef NTSIGX
3451    conraw();
3452    connoi();
3453#else
3454    if (!local)
3455      connoi();                         /* No console interrupts if remote */
3456#endif /* NTSIG */
3457
3458    kactive = 1;
3459    if (sstate == 'x') {                /* If entering server mode, */
3460        extern int howcalled;
3461        server = 1;                     /* set flag, */
3462        debug(F101,"server backgrd","",backgrd);
3463        debug(F101,"server quiet","",quiet);
3464        debug(F100,"SHOULD NOT SEE THIS IF IN BACKGROUND!","",0);
3465        if (howcalled == I_AM_SSHSUB) { /* and issue appropriate message. */
3466            ttol((CHAR *)"KERMIT READY TO SERVE...\015\012",26);
3467        } else if (!local) {
3468            if (!quiet && !backgrd
3469#ifdef IKS_OPTION
3470                && !TELOPT_ME(TELOPT_KERMIT) /* User was told by negotiation */
3471#endif /* IKS_OPTION */
3472                ) {
3473                conoll(srvtxt);
3474                conoll("KERMIT READY TO SERVE...");
3475            }
3476        } else {
3477            conol("Entering server mode on ");
3478            conoll(ttname);
3479            conoll("Type Ctrl-C to quit.");
3480            if (srvdis) intmsg(-1L);
3481#ifdef TCPSOCKET
3482#ifndef NOLISTEN
3483            if (network && tcpsrfd > 0)
3484              ttol((CHAR *)"KERMIT READY TO SERVE...\015\012",26);
3485#endif /* NOLISTEN */
3486#endif /* TCPSOCKET */
3487        }
3488    } else
3489      server = 0;
3490#ifdef VMS
3491    if (!quiet && !backgrd)    /* So message doesn't overwrite prompt */
3492      conoll("");
3493    if (local) conres();       /* So Ctrl-C will work */
3494#endif /* VMS */
3495/*
3496  If in remote mode, not shushed, not in background, and at top command level,
3497  issue a helpful message telling what to do...
3498*/
3499    if (!local && !quiet && !backgrd) {
3500        if (sstate == 'v') {
3501            conoll("Return to your local Kermit and give a SEND command.");
3502            conoll("");
3503            conoll("KERMIT READY TO RECEIVE...");
3504        } else if (sstate == 's') {
3505            conoll("Return to your local Kermit and give a RECEIVE command.");
3506            conoll("");
3507            conoll("KERMIT READY TO SEND...");
3508        } else if ( sstate == 'g' || sstate == 'r' || sstate == 'h' ||
3509                    sstate == 'j' || sstate == 'c' ) {
3510            conoll("Return to your local Kermit and give a SERVER command.");
3511            conoll("");
3512            conoll((sstate == 'r' || sstate == 'j' || sstate == 'h') ?
3513                   "KERMIT READY TO GET..." :
3514                   "KERMIT READY TO SEND SERVER COMMAND...");
3515        }
3516    }
3517#ifdef COMMENT
3518    if (!local) sleep(1);
3519#endif /* COMMENT */
3520/*
3521  The 'wart()' function is generated by the wart program.  It gets a
3522  character from the input() routine and then based on that character and
3523  the current state, selects the appropriate action, according to the state
3524  table above, which is transformed by the wart program into a big case
3525  statement.  The function is active for one transaction.
3526*/
3527    rtimer();                           /* Reset elapsed-time timer */
3528#ifdef GFTIMER
3529    rftimer();
3530#endif /* GFTIMER */
3531    resetc();                           /* & other per-transaction counters. */
3532
3533    debug(F101,"proto calling wart, justone","",justone);
3534
3535    wart();                             /* Enter the state table switcher. */
3536/*
3537  Note: the following is necessary in case we have just done a remote-mode
3538  file transfer, in which case the controlling terminal modes have been
3539  changed by ttpkt().  In particular, special characters like Ctrl-C and
3540  Ctrl-\ might have been turned off (see ttpkt).  So this call to ttres() is
3541  essential.  IMPORTANT: restore interrupt handlers first, otherwise any
3542  terminal interrupts that occur before this is done in the normal place
3543  later will cause a crash.
3544*/
3545#ifdef OS2
3546    ttres();                            /* Reset the communication device */
3547#else
3548    if (!local) {
3549        setint();                       /* Arm interrupt handlers FIRST */
3550        msleep(500);
3551        ttres();                        /* Then restore terminal. */
3552    }
3553#endif /* OS2 */
3554    xxscreen(SCR_TC,0,0L,"");           /* Transaction complete */
3555    x = quiet;
3556    quiet=1;
3557    clsif();                            /* Failsafe in case we missed */
3558    clsof(1);                           /* a case in the state machine. */
3559    quiet = x;
3560
3561    if (server) {                       /* Back from packet protocol. */
3562        if (!quiet && !backgrd
3563#ifdef IKSD
3564            && !inserver
3565#endif /* IKSD */
3566            ) {                         /* Give appropriate message */
3567            conoll("");
3568            conoll("C-Kermit server done");
3569        }
3570        server = 0;                     /* Not a server any more */
3571    }
3572}
3573
3574/*  S G E T I N I T  --  Handle incoming GET-Class packets  */
3575
3576/*
3577  Returns:
3578   -1: On error
3579    0: GET packet processed OK - ready to Send.
3580    1: Extended GET processed OK - wait for another.
3581*/
3582static int
3583sgetinit(reget,xget) int reget, xget; { /* Server end of GET command */
3584    char * fs = NULL;                   /* Pointer to filespec */
3585    int i, n, done = 0;
3586#ifdef PIPESEND
3587    extern int usepipes, pipesend;
3588#endif /* PIPESEND */
3589    extern int nolinks;
3590
3591    if (!ENABLED(en_get)) {             /* Only if not disabled!  */
3592        errpkt((CHAR *)"GET disabled");
3593        return(-1);
3594    }
3595
3596    /* OK to proceed */
3597
3598    nolinks = recursive;
3599    filcnt = 0;
3600
3601#ifdef WHATAMI
3602    /* If they are alike this was already done in whoarewe() */
3603    debug(F101,"sgetinit whatru","",whatru);
3604    if (whatru & WMI_FLAG) {            /* Did we get WHATAMI info? */
3605        debug(F101,"sgetinit binary (1)","",binary);
3606#ifdef VMS
3607        if (binary != XYFT_I && binary != XYFT_L)
3608#else
3609#ifdef OS2
3610          if (binary != XYFT_L)
3611#endif /* OS2 */
3612#endif /* VMS */
3613            binary = (whatru & WMI_FMODE) ? /* Yes, set file type */
3614              XYFT_B : XYFT_T;  /* automatically */
3615        debug(F101,"sgetinit binary (2)","",binary);
3616        if (!wearealike)
3617          fncnv = (whatru & WMI_FNAME) ? 1 : 0; /* And name conversion */
3618    }
3619#endif /* WHATAMI */
3620
3621    fs = (char *)srvcmd;
3622    srvptr = srvcmd;                    /* Point to server command buffer */
3623    decode(rdatap,putsrv,0);            /* Decode the GET command into it */
3624    /* Accept multiple filespecs */
3625    cmarg2 = "";                        /* Don't use cmarg2 */
3626    cmarg = "";                         /* Don't use cmarg */
3627
3628    done = 1;                           /* Only 1 packet needed... */
3629    if (xget) {                         /* Special decoding for Extended GET */
3630        char L, next, c;                /* PLV items */
3631        int len, val;                   /* More PLV items */
3632        char * p = (char *)srvcmd;      /* String to decode */
3633
3634        done = 0;                       /* Maybe more packets needed */
3635        fs = NULL;                      /* We don't know the filespec yet */
3636        c = *p++;                       /* Get first parameter */
3637
3638        while (c) {                     /* For all parameters... */
3639            debug(F000,"sgetinit c","",c);
3640            L = *p++;                   /* Get length */
3641            if (L >= SP)                /* Decode length */
3642              len = xunchar(L);
3643            else if (c == '@') {        /* Allow missing EOP length field */
3644                len = 0;
3645            } else {
3646                len = (xunchar(*p++) * 95);
3647                len += xunchar(*p++);
3648            }
3649            debug(F101,"sgetinit len","",len);
3650            next = *(p+len);            /* Get next parameter */
3651            *(p+len) = NUL;             /* Zero it out to terminal value */
3652            debug(F110,"sgetinit p",p,0);
3653            switch (c) {                /* Do the parameter */
3654              case 'O':                 /* GET Options */
3655                val = atoi(p);          /* Convert to int */
3656                debug(F101,"sgetinit O val","",val);
3657                if (val & GOPT_DEL) moving = 1;
3658                if (val & GOPT_RES) reget = 1;
3659                if (val & GOPT_REC) {
3660                    recursive = 1;
3661                    nolinks = 2;
3662                    if (fnspath == PATH_OFF)
3663                      fnspath = PATH_REL;
3664                }
3665                break;
3666              case 'M':                 /* Transfer Mode */
3667                val = atoi(p);
3668                debug(F101,"sgetinit M val","",val);
3669                if (val < 1)
3670                  break;
3671                patterns = 0;           /* Takes precedence over patterns */
3672                filepeek = 0;           /* and FILE SCAN */
3673                if (val == GMOD_TXT) binary = XYFT_T; /* Text */
3674                if (val == GMOD_BIN) binary = XYFT_B; /* Binary */
3675                if (val == GMOD_LBL) binary = XYFT_L; /* Labeled */
3676                break;
3677              case 'F':                 /* Filename */
3678                fs = p;
3679                debug(F110,"sgetinit filename",fs,0);
3680                break;
3681              case '@':                 /* End Of Parameters */
3682                done = 1;
3683                debug(F100,"sgetinit EOP","",0);
3684                break;
3685              default:
3686                errpkt((CHAR *)"Unknown GET Parameter");
3687                debug(F100,"sgetinit unknown parameter","",0);
3688                return(-1);
3689            }
3690            p += (len + 1);
3691            c = next;
3692        }
3693    }
3694    if (!fs) fs = "";                   /* A filename is required */
3695    if (*fs) {
3696        havefs = 1;
3697        n = 0;                          /* Check for quoted name */
3698        if ((n = strlen(fs)) > 1) {
3699            /* Note: this does not allow for multiple quoted names */
3700            if ((fs[0] == '{' && fs[n-1] == '}') ||
3701                (fs[0] == '"' && fs[n-1] == '"')) {
3702                fs[n-1] = '\0';
3703                fs++;
3704                debug(F111,"sgetinit unquoted filename",fs,n);
3705            } else
3706              n = 0;                    /* This means no quoting */
3707        }
3708
3709#ifdef PIPESEND
3710        debug(F111,"sgetinit",fs,usepipes);
3711        if (usepipes && ENABLED(en_hos) && *fs == '!') {
3712            cmarg = fs + 1;             /* Point past the bang */
3713            *fs = NUL;
3714            nfils = -1;
3715            pipesend = 1;
3716            debug(F111,"sgetinit pipesend",cmarg,pipesend);
3717        }
3718        if (!pipesend) {                /* If it's not a pipe */
3719#endif /* PIPESEND */
3720            if (n == 0) {               /* If the name was not quoted */
3721#ifndef NOMSEND
3722                nfils = fnparse(fs);    /* Allow it to be a list of names */
3723                debug(F111,"sgetinit A",fs,nfils);
3724#ifdef COMMENT
3725/* This doesn't work if a GET-PATH is set. */
3726                if (nfils == 1 && !iswild(fs)) { /* Single file */
3727                    char * m;
3728                    if ((x = zchki(fs)) < 0) { /* Check if it's sendable */
3729                        switch (x) {
3730                          case -1: m = "File not found"; break;
3731                          case -2: m = "Not a regular file"; break;
3732                          case -3: m = "Read access denied"; break;
3733                        }
3734                        errpkt((CHAR *)m);
3735                        return(-1);
3736                    }
3737                }
3738#endif /* COMMENT */
3739            } else {                    /* If it was quoted */
3740#endif /* NOMSEND */
3741                nzxopts = 0;
3742#ifdef UNIXOROSK
3743                if (matchdot)  nzxopts |= ZX_MATCHDOT;
3744#endif /* UNIXOROSK */
3745                if (recursive) nzxopts |= ZX_RECURSE;
3746                /* Treat as a single filespec */
3747                nfils = 0 - nzxpand(fs,nzxopts);
3748                debug(F111,"sgetinit B",fs,nfils);
3749                cmarg = fs;
3750            }
3751#ifdef PIPESEND
3752        }
3753#endif /* PIPESEND */
3754    }
3755    if (!done) {                        /* Need more O packets... */
3756        debug(F100,"sgetinit O-Packet TBC","",0); /* To Be Continued */
3757        return(1);
3758    }
3759    debug(F100,"sgetinit O-Packet done - havefs","",havefs);
3760    if (!havefs) {                      /* Done - make sure we have filename */
3761        errpkt((CHAR *)"GET without filename");
3762        return(-1);
3763    }
3764    freerpkt(winlo);
3765    winlo = 0;                          /* Back to packet 0 again. */
3766    debug(F101,"sgetinit winlo","",winlo);
3767    nakstate = 0;                       /* Now I'm the sender! */
3768    if (reget) sendmode = SM_RESEND;
3769    if (sinit() > 0) {                  /* Send Send-Init */
3770#ifdef STREAMING
3771        if (!streaming)
3772#endif /* STREAMING */
3773          timint = chktimo(rtimo,timef); /* Switch to per-packet timer */
3774        return(0);                      /* If successful, switch state */
3775    } else return(-1);                  /* Else back to server command wait */
3776}
3777
3778#else  /* NOXFER */
3779
3780#include "ckcdeb.h"
3781
3782VOID
3783proto() {
3784    extern int success;
3785    success = 0;
3786}
3787#endif /* NOXFER */
Note: See TracBrowser for help on using the repository browser.