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