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