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