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. */
6 /* Wart Version Info: */
7 char *wartv = "Wart Version 2.14, 10 Nov 1999";
9 char *protv = /* -*-C-*- */
10 "C-Kermit Protocol Module 9.0.160, 16 Oct 2009";
12 int kactive = 0; /* Kermit protocol is active */
16 /* C K C P R O -- C-Kermit Protocol Module, in Wart preprocessor notation. */
18 Author: Frank da Cruz <fdc@columbia.edu>,
19 Columbia University Academic Information Systems, New York City.
21 Copyright (C) 1985, 2009,
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.
34 #define INCL_VIO /* Needed for ckocon.h */
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.
50 /* State definitions for Wart (or Lex) */
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));
74 /* External C-Kermit variable declarations */
75 extern char *versio, *srvtxt, *cmarg, *cmarg2, **cmlist, *rf_err;
76 extern char * rfspec, * sfspec, * srfspec, * rrfspec;
77 extern char * prfspec, * psfspec, * psrfspec, * prrfspec;
78 extern char *cdmsgfile[];
79 extern char * snd_move, * snd_rename, * srimsg;
80 extern char filnam[], ofilnam[], fspec[], ttname[], ofn1[];
81 extern CHAR sstate, *srvptr, *data;
82 extern int timint, rtimo, nfils, hcflg, xflg, flow, mdmtyp, network;
83 extern int oopts, omode, oname, opath, nopush, isguest, xcmdsrc, rcdactive;
84 extern int rejection, moving, fncact, bye_active, urserver, fatalio;
85 extern int protocol, prefixing, filcnt, carrier, fnspath, interrupted;
86 extern int recursive, inserver, nzxopts, idletmo, srvidl, xfrint;
87 extern struct ck_p ptab[];
88 extern int remfile, rempipe, xferstat, filestatus, wearealike, fackpath;
89 extern int patterns, filepeek, gnferror;
90 extern char * remdest;
94 static char ipktack[PKTZEROLEN];
95 static int ipktlen = 0;
96 #endif /* PKTZEROHACK */
98 static int s_timint = -1; /* For saving timeout value */
100 static int havefs = 0;
102 static int logtries = 0;
103 #endif /* CK_LOGIN */
105 static int cancel = 0;
109 extern int streaming, streamok;
114 debug(F100,"streamon","",0);
116 timint = 0; /* No timeouts while streaming. */
120 #ifdef COMMENT /* (not used) */
124 debug(F100,"streamoff","",0);
126 timint = s_timint; /* Restore timeout */
130 #else /* STREAMING */
133 #endif /* STREAMING */
136 _PROTOTYP( int addmac, (char *, char *) );
137 _PROTOTYP( int zzstring, (char *, char **, int *) );
140 _PROTOTYP( int cmdsrc, (void) );
144 extern char * x_user, * x_passwd, * x_acct;
145 extern int x_login, x_logged;
146 #endif /* NOSERVER */
151 extern int ttnproto; /* Network protocol */
155 extern short ctlp[]; /* Control-character prefix table */
156 #endif /* CK_SPEED */
159 extern int tn_b_nlm, tn_b_xfer, tn_nlm;
161 extern int tn_no_encrypt_xfer;
162 #endif /* CK_ENCRYPTION */
168 #endif /* NOLISTEN */
169 #endif /* TCPSOCKET */
171 extern int cxseen, czseen, server, srvdis, local, displa, bctu, bctr, bctl;
173 extern int quiet, tsecs, parity, backgrd, nakstate, atcapu, wslotn, winlo;
174 extern int wslots, success, xitsta, rprintf, discard, cdtimo, keep, fdispla;
175 extern int timef, stdinf, rscapu, sendmode, epktflg, epktrcvd, epktsent;
176 extern int binary, fncnv;
177 extern long speed, ffc, crc16, calibrate, dest;
179 extern char *TYPCMD, *DIRCMD, *DIRCM2;
182 extern char *SPACMD, *SPACM2, *WHOCMD;
185 extern struct zattr iattr;
192 extern CKFLOAT fptsecs;
196 extern CHAR *epktmsg;
199 extern int f_tmpdir; /* Directory changed temporarily */
200 extern char savdir[]; /* For saving current directory */
202 #endif /* CK_TMPDIR */
204 extern int query; /* Query-active flag */
207 char querybuf[QBUFL+1] = { NUL, NUL }; /* QUERY response buffer */
208 char *qbufp = querybuf; /* Pointer to it */
209 int qbufn = 0; /* Length of data in it */
218 If the following flag is nonzero when the protocol module is entered,
219 then server mode persists for exactly one transaction, rather than
220 looping until BYE or FINISH is received.
224 static int r_save = -1;
225 static int p_save = -1;
227 /* Function to let remote-mode user know where their file(s) went */
229 int whereflg = 1; /* Unset with SET XFER REPORT */
233 extern int quiet, filrej;
236 debug(F101,"wheremsg n","",n);
238 debug(F110,"wheremsg prfspec",prfspec,0);
239 debug(F110,"wheremsg rfspec",rfspec,0);
240 debug(F110,"wheremsg psfspec",psfspec,0);
241 debug(F110,"wheremsg sfspec",sfspec,0);
243 debug(F110,"wheremsg prrfspec",prrfspec,0);
244 debug(F110,"wheremsg rrfspec",rrfspec,0);
245 debug(F110,"wheremsg psrfspec",psrfspec,0);
246 debug(F110,"wheremsg srfspec",srfspec,0);
248 if (!quiet && !local) {
253 printf(" SENT: [%s]",sfspec);
255 printf(" To: [%s]",srfspec);
256 printf(" (%s)\r\n", success ? "OK" : "FAILED");
262 printf(" RCVD: [%s]",rrfspec);
264 printf(" To: [%s]",rfspec);
265 printf(" (%s)\r\n", success ? "OK" : "FAILED");
272 printf(" SENT: (%d files)",n);
274 printf(" Last: [%s]",srfspec);
275 printf(" (%s)\r\n", success ? "OK" : "FAILED");
281 printf(" RCVD: (%d files)",n);
283 printf(" Last: [%s]",rfspec);
284 printf(" (%s)\r\n", success ? "OK" : "FAILED");
289 printf(" SENT: (0 files) \r\n");
290 else if (myjob == 'r' || myjob == 'v')
291 printf(" RCVD: (0 files) \r\n");
299 debug(F111,"RESUME","server=1",justone);
301 debug(F111,"RESUME","server=0",justone);
304 /* Flags for the ENABLE and DISABLE commands */
306 en_cpy, en_cwd, en_del, en_dir, en_fin, en_get, en_bye, en_mai, en_pri,
307 en_hos, en_ren, en_sen, en_spa, en_set, en_typ, en_who, en_ret, en_xit,
310 extern int en_asg, en_que;
312 extern int what, lastxfer;
314 /* Global variables declared here */
316 int whatru = 0; /* What are you. */
317 int whatru2 = 0; /* What are you, cont'd. */
319 /* Local variables */
321 static char vstate = 0; /* Saved State */
322 static char vcmd = 0; /* Saved Command */
323 static int reget = 0; /* Flag for executing REGET */
324 static int retrieve = 0; /* Flag for executing RETRIEVE */
325 static int opkt = 0; /* Send Extended GET packet */
327 static int x; /* General-purpose integer */
328 static char *s; /* General-purpose string pointer */
330 /* Macros - Note, BEGIN is predefined by Wart (and Lex) as "state = ", */
331 /* BEGIN is NOT a GOTO! */
332 #define TINIT if (tinit(1) < 0) return(-9)
333 #define SERVE { TINIT; resetc(); nakstate=1; what=W_NOTHING; cmarg2=""; \
334 sendmode=SM_SEND; havefs=0; recursive=r_save; fnspath=p_save; BEGIN serve; }
335 #define RESUME { rdebug(); if (!server) { wheremsg(); return(0); } else \
336 if (justone) { justone=0; wheremsg(); return(0); } else { SERVE; } }
339 #define QUIT x=quiet; quiet=1; clsif(); clsof(1); tsecs=gtimer(); \
340 fptsecs=gftimer(); quiet=x; return(success)
342 #define QUIT x=quiet; quiet=1; clsif(); clsof(1); tsecs=gtimer(); quiet=x; \
347 By late 1999, the big switch() statement generated from the following state
348 table began choking even gcc, so here we extract the code from the larger
349 states into static routines to reduce the size of the cases and the
350 switch() overall. The routines follow the state table; the prototypes are
351 here. Each of these routines simply contains the text from the
352 corresponding case, but with return(-1) added in appropriate places; see
353 instructions after the state table switcher.
355 static int rc; /* Return code for these routines */
356 static int rcv_s_pkt(); /* Received an S packet */
357 static int rcv_firstdata(); /* Received first Data packet */
358 static int rcv_shortreply(); /* Short reply to a REMOTE command */
359 static int srv_query(); /* Server answers an query */
360 static int srv_copy(); /* Server executes REMOTE COPY */
361 static int srv_rename(); /* Server executes REMOTE RENAME */
362 static int srv_login(); /* Server executes REMOTE LOGIN */
363 static int srv_timeout(); /* Server times out */
366 #define BEGIN state =
377 debug(F000,"PROTO input",ckitoa(state),c+32);
378 if (c < 0 || c > 95) c = 0;
379 if ((actno = tbl[c + state*96]) != -1)
382 { TINIT; /* Send file(s) */
383 if (sinit() > 0) BEGIN ssinit;
387 { TINIT; nakstate = 1; BEGIN get; }
390 { /* Client sends a GET command */
399 #endif /* PKTZEROHACK */
407 { /* Client sends a RETRIEVE command */
421 { /* Client sends a REGET command */
435 { /* Client sends Extended GET Packet */
438 reget = oopts & GOPT_RES;
439 retrieve = oopts & GOPT_DEL;
449 { /* Client sends a Host command */
460 { TINIT; /* Client sends a Kermit command */
470 { /* Client sends a REMOTE command */
481 { /* Enter server mode */
484 if (!ENABLED(en_del)) { /* If DELETE is disabled */
485 if (fncact == XYFX_B || /* undo any file collision action */
486 fncact == XYFX_U || /* that could result in deletion or */
487 fncact == XYFX_A || /* modification of existing files. */
491 g_fncact = fncact; /* Save current setting */
493 fncact = XYFX_R; /* Change to RENAME */
494 debug(F101,"server DELETE disabled so fncact RENAME","",fncact);
497 SERVE; /* tinit() clears justone... */
500 if (ikdbopen) slotstate(what, "SERVER", "", "");
507 if (!data) TINIT; /* "ABEND" -- Tell other side. */
509 if (!bctf) { /* Block check 3 forced on all packets */
511 if (epktflg) { /* If because of E-PACKET command */
512 b1 = bctl; b2 = bctu; /* Save block check type */
513 bctl = bctu = 1; /* set it to 1 */
517 errpkt((CHAR *)"User cancelled"); /* Send the packet */
518 if (!bctf) { /* Block check 3 forced on all packets */
520 if (epktflg) { /* Restore the block check */
522 bctl = b1; bctu = b2;
527 return(0); /* Return from protocol. */
531 { /* Receive Send-Init packet. */
533 cancel = 0; /* Reset cancellation counter */
534 debug(F101,"rcv_s_pkt","",rc);
535 if (rc > -1) return(rc); /* (see below) */
539 { /* Get ack for I-packet */
542 ckstrncpy(ipktack,(char *)rdatap,PKTZEROLEN); /* Save a copy of the ACK */
543 ipktlen = strlen(ipktack);
544 #endif /* PKTZEROHACK */
545 spar(rdatap); /* Set parameters */
547 winlo = 0; /* Set window-low back to zero */
548 debug(F101,"<ipkt>Y winlo","",winlo);
549 urserver = 1; /* So I know I'm talking to a server */
550 if (vcmd) { /* If sending a generic command */
551 if (tinit(0) < 0) return(-9); /* Initialize many things */
552 x = scmd(vcmd,(CHAR *)cmarg); /* Do that */
553 if (x >= 0) x = 0; /* (because of O-Packet) */
554 debug(F101,"proto G packet scmd","",x);
555 vcmd = 0; /* and then un-remember it. */
556 } else if (vstate == get) {
557 debug(F101,"REGET sstate","",sstate);
558 x = srinit(reget, retrieve, opkt); /* GET or REGET, etc */
560 if (x < 0) { /* If command was too long */
562 srimsg = "Error sending string";
563 errpkt((CHAR *)srimsg); /* cancel both sides. */
566 } else if (x > 0) { /* Need to send more O-Packets */
569 rtimer(); /* Reset the elapsed seconds timer. */
573 winlo = 0; /* Window back to 0, again. */
574 debug(F101,"<ipkt>Y vstate","",vstate);
575 nakstate = 1; /* Can send NAKs from here. */
576 BEGIN vstate; /* Switch to desired state */
581 { /* Got ACK to O-Packet */
582 debug(F100,"CPCPRO <ssopkt>Y","",0);
584 debug(F101,"CPCPRO <ssopkt>Y x","",x);
585 if (x < 0) { /* If error */
586 errpkt((CHAR *)srimsg); /* cancel both sides. */
589 } else if (x == 0) { /* This was the last O-Packet */
590 rtimer(); /* Reset the elapsed seconds timer. */
594 winlo = 0; /* Window back to 0, again. */
595 debug(F101,"<ssopkt>Y winlo","",winlo);
596 nakstate = 1; /* Can send NAKs from here. */
597 BEGIN vstate; /* Switch to desired state */
599 debug(F101,"CPCPRO <ssopkt>Y not changing state","",x);
603 { /* Ignore Error reply to I packet */
605 winlo = 0; /* Set window-low back to zero */
606 debug(F101,"<ipkt>E winlo","",winlo);
607 if (vcmd) { /* In case other Kermit doesn't */
608 if (tinit(0) < 0) return(-9);
609 x = scmd(vcmd,(CHAR *)cmarg); /* understand I-packets. */
610 if (x >= 0) x = 0; /* (because of O-Packet) */
611 vcmd = 0; /* Otherwise act as above... */
612 } else if (vstate == get) x = srinit(reget, retrieve, opkt);
613 if (x < 0) { /* If command was too long */
614 errpkt((CHAR *)srimsg); /* cancel both sides. */
617 } else if (x > 0) { /* Need to send more O-Packets */
620 freerpkt(winlo); /* Discard the Error packet. */
621 debug(F101,"<ipkt>E winlo","",winlo);
622 winlo = 0; /* Back to packet 0 again. */
623 nakstate = 1; /* Can send NAKs from here. */
629 { /* Resend of previous I-pkt ACK, same seq number */
630 freerpkt(0); /* Free the ACK's receive buffer */
631 resend(0); /* Send the GET packet again. */
637 spar(rdatap); /* Set parameters from it */
638 ack1(rpar()); /* Respond with our own parameters */
640 pktinit(); /* Reinitialize packet numbers */
643 /* This can't be right - it undoes the stuff we just negotiated */
645 tinit(1); /* Reinitialize EVERYTHING */
646 justone = x; /* But this... */
648 tinit(0); /* Initialize most things */
651 #endif /* NOSERVER */
652 cancel = 0; /* Reset cancellation counter */
658 if (x_login && !x_logged) {
659 errpkt((CHAR *)"Login required");
661 } else if (sgetinit(0,0) < 0) {
665 if (ckxsyslog >= SYSLG_PR && ckxlogging)
666 cksyslog(SYSLG_PR, 1, "server", "GET", (char *)srvcmd);
667 #endif /* CKSYSLOG */
670 #endif /* NOSERVER */
674 { /* GET /DELETE (RETRIEVE) */
676 if (x_login && !x_logged) {
677 errpkt((CHAR *)"Login required");
679 } else if (!ENABLED(en_del)) {
680 errpkt((CHAR *)"Deleting files is disabled");
682 } else if (sgetinit(0,0) < 0) {
687 if (ckxsyslog >= SYSLG_PR && ckxlogging)
688 cksyslog(SYSLG_PR, 1, "server", "GET /DELETE", (char *)srvcmd);
689 #endif /* CKSYSLOG */
692 #endif /* NOSERVER */
696 { /* GET /RECURSIVE */
698 recursive = 1; /* Set these before sgetinit() */
699 if (fnspath == PATH_OFF)
700 fnspath = PATH_REL; /* Don't worry, they will be */
701 if (x_login && !x_logged) { /* reset next time through. */
702 errpkt((CHAR *)"Login required");
704 } else if (sgetinit(0,0) < 0) {
708 if (ckxsyslog >= SYSLG_PR && ckxlogging)
709 cksyslog(SYSLG_PR, 1, "server", "GET /RECURSIVE", (char *)srvcmd);
710 #endif /* CKSYSLOG */
713 #endif /* NOSERVER */
717 { /* GET /RECURSIVE /DELETE */
719 recursive = 1; /* Set these before sgetinit() */
720 if (fnspath == PATH_OFF)
721 fnspath = PATH_REL; /* Don't worry, they will be */
722 moving = 1; /* reset next time through. */
723 if (x_login && !x_logged) {
724 errpkt((CHAR *)"Login required");
726 } else if (!ENABLED(en_del)) {
727 errpkt((CHAR *)"Deleting files is disabled");
729 } else if (sgetinit(0,0) < 0) {
733 if (ckxsyslog >= SYSLG_PR && ckxlogging)
734 cksyslog(SYSLG_PR,1,"server",
735 "GET /RECURSIVE /DELETE",(char *)srvcmd);
736 #endif /* CKSYSLOG */
739 #endif /* NOSERVER */
743 { /* GET /RECOVER (REGET) */
745 if (x_login && !x_logged) {
746 errpkt((CHAR *)"Login required");
748 } else if (sgetinit(1,0) < 0) {
752 if (ckxsyslog >= SYSLG_PR && ckxlogging)
753 cksyslog(SYSLG_PR, 1, "server", "GET /RECOVER", (char *)srvcmd);
754 #endif /* CKSYSLOG */
757 #endif /* NOSERVER */
763 if (x_login && !x_logged) { /* (any combination of options) */
764 errpkt((CHAR *)"Login required");
766 } else if ((x = sgetinit(0,1)) < 0) {
767 debug(F101,"CKCPRO <serve>O sgetinit fail","",x);
770 debug(F101,"CKCPRO <serve>O sgetinit done","",x);
772 if (ckxsyslog >= SYSLG_PR && ckxlogging)
773 cksyslog(SYSLG_PR, 1, "server", "EXTENDED GET", (char *)srvcmd);
774 #endif /* CKSYSLOG */
776 } else { /* Otherwise stay in this state */
777 debug(F101,"CKCPRO <serve>O sgetinit TBC","",x);
781 #endif /* NOSERVER */
787 if (x_login && !x_logged) { /* (any combination of options) */
788 errpkt((CHAR *)"Login required");
790 } else if ((x = sgetinit(0,1)) < 0) {
791 debug(F101,"CKCPRO <ropkt>O sgetinit fail","",x);
794 debug(F101,"CKCPRO <ropkt>O sgetinit done","",x);
796 if (ckxsyslog >= SYSLG_PR && ckxlogging)
797 cksyslog(SYSLG_PR, 1, "server", "EXTENDED GET", (char *)srvcmd);
798 #endif /* CKSYSLOG */
800 } else { /* Otherwise stay in this state */
801 debug(F101,"CKCPRO <ropkt>O sgetinit TBC","",x);
804 #endif /* NOSERVER */
808 { /* Generic server command */
810 srvptr = srvcmd; /* Point to command buffer */
811 decode(rdatap,putsrv,0); /* Decode packet data into it */
812 putsrv(NUL); /* Insert a couple nulls */
813 putsrv(NUL); /* for termination */
815 sstate = srvcmd[0]; /* Set requested start state */
816 if (x_login && !x_logged && /* Login required? */
817 /* Login, Logout, and Help are allowed when not logged in */
818 sstate != 'I' && sstate != 'L' && sstate != 'H') {
819 errpkt((CHAR *)"Login required");
822 nakstate = 0; /* Now I'm the sender. */
823 what = W_REMO; /* Doing a REMOTE command. */
826 #endif /* STREAMING */
828 timint = chktimo(rtimo,timef); /* Switch to per-packet timer */
829 binary = XYFT_T; /* Switch to text mode */
830 BEGIN generic; /* Switch to generic command state */
833 errpkt((CHAR *)"Badly formed server command"); /* report error */
834 RESUME; /* & go back to server command wait */
836 #endif /* NOSERVER */
840 { /* Receive Host command */
842 if (x_login && !x_logged) {
843 errpkt((CHAR *)"Login required");
845 } else if (!ENABLED(en_hos)) {
846 errpkt((CHAR *)"REMOTE HOST disabled");
849 errpkt((CHAR *)"HOST commands not available");
852 srvptr = srvcmd; /* Point to command buffer */
853 decode(rdatap,putsrv,0); /* Decode command packet into it */
854 putsrv(NUL); /* Null-terminate */
855 nakstate = 0; /* Now sending, not receiving */
856 binary = XYFT_T; /* Switch to text mode */
857 if (syscmd((char *)srvcmd,"")) { /* Try to execute the command */
858 what = W_REMO; /* Doing a REMOTE command. */
861 #endif /* STREAMING */
863 timint = chktimo(rtimo,timef); /* Switch to per-packet timer */
865 if (ckxsyslog >= SYSLG_PR && ckxlogging)
866 cksyslog(SYSLG_PR, 1, "server", "REMOTE HOST", (char *)srvcmd);
867 #endif /* CKSYSLOG */
868 BEGIN ssinit; /* If OK, send back its output */
869 } else { /* Otherwise */
870 errpkt((CHAR *)"Can't do system command"); /* report error */
871 RESUME; /* & go back to server command wait */
874 #endif /* NOSERVER */
878 { /* Interrupted or connection lost */
880 debug(F101,"srv_timeout","",rc);
881 if (rc > -1) return(rc); /* (see below) */
885 { /* Server got a NAK in command-wait */
887 errpkt((CHAR *)"Did you say RECEIVE instead of GET?");
889 #endif /* NOSERVER */
893 { /* Any other command in this state */
895 if (c != ('E' - SP) && c != ('Y' - SP)) /* except E and Y packets. */
896 errpkt((CHAR *)"Unimplemented server function");
897 /* If we answer an E with an E, we get an infinite loop. */
898 /* A Y (ACK) can show up here if we sent back a short-form reply to */
899 /* a G packet and it was echoed. ACKs can be safely ignored here. */
900 RESUME; /* Go back to server command wait. */
901 #endif /* NOSERVER */
907 debug(F101,"<generic>I srv_login","",rc);
908 if (rc > -1) return(rc); /* (see below) */
912 { /* Got REMOTE CD command */
915 if (ckxsyslog >= SYSLG_PR && ckxlogging)
916 cksyslog(SYSLG_PR, 1, "server", "REMOTE CD", (char *)srvcmd);
917 #endif /* CKSYSLOG */
918 if (!ENABLED(en_cwd)) {
919 errpkt((CHAR *)"REMOTE CD disabled");
923 x = cwd((char *)(srvcmd+1)); /* Try to change directory */
925 if (ikdbopen) slotstate(what,"REMOTE CD", (char *)(srvcmd+2), "");
927 if (!x) { /* Failed */
928 errpkt((CHAR *)"Can't change directory");
929 RESUME; /* Back to server command wait */
930 } else if (x == 2) { /* User wants message */
931 if (!ENABLED(en_typ)) { /* Messages (REMOTE TYPE) disabled? */
932 errpkt((CHAR *)"REMOTE TYPE disabled");
934 } else { /* TYPE is enabled */
936 for (i = 0; i < 8; i++) {
937 if (zchki(cdmsgfile[i]) > -1) {
941 binary = XYFT_T; /* Use text mode for this. */
942 if (i < 8 && sndtype(cdmsgfile[i])) { /* Have readme file? */
943 BEGIN ssinit; /* OK */
944 } else { /* not OK */
947 success = (*p) ? 1 : 0;
948 ack1((CHAR *)p); /* ACK with new directory name */
950 RESUME; /* wait for next server command */
953 } else { /* User doesn't want message */
956 success = (*p) ? 1 : 0;
959 RESUME; /* Wait for next server command */
962 #endif /* NOSERVER */
966 { /* Got REMOTE PWD command */
969 if (ckxsyslog >= SYSLG_PR && ckxlogging)
970 cksyslog(SYSLG_PR, 1, "server", "REMOTE PWD", NULL);
971 #endif /* CKSYSLOG */
972 if (!ENABLED(en_cwd)) {
973 errpkt((CHAR *)"REMOTE CD disabled");
976 if (encstr((CHAR *)zgtdir()) > -1) { /* Encode current directory */
977 ack1(data); /* If it fits, send it back in ACK */
979 } else { /* Failed */
980 ack(); /* Send empty ACK */
981 success = 0; /* and indicate failure locally */
983 RESUME; /* Back to server command wait */
985 #endif /* NOSERVER */
989 { /* REMOTE DIRECTORY command */
993 if (ckxsyslog >= SYSLG_PR && ckxlogging)
994 cksyslog(SYSLG_PR, 1, "server", "REMOTE DIRECTORY", (char *)srvcmd);
995 #endif /* CKSYSLOG */
996 if (!ENABLED(en_dir)) { /* If DIR is disabled, */
997 errpkt((CHAR *)"REMOTE DIRECTORY disabled"); /* refuse. */
999 } else { /* DIR is enabled. */
1001 if (ikdbopen) slotstate(what,"REMOTE DIR", (char *)(srvcmd+2), "");
1003 if (!ENABLED(en_cwd)) { /* But CWD is disabled */
1004 zstrip((char *)(srvcmd+2),&n2); /* and they included a pathname, */
1005 if (strcmp((char *)(srvcmd+2),n2)) { /* so refuse. */
1006 errpkt((CHAR *)"Access denied");
1007 RESUME; /* Remember, this is not a goto! */
1010 if (state == generic) { /* It's OK to go ahead. */
1012 n2 = (*(srvcmd+2)) ? DIRCMD : DIRCM2;
1013 if (syscmd(n2,(char *)(srvcmd+2))) /* If it can be done */
1016 if ((x = snddir((char*)(srvcmd+2))) > 0)
1017 #endif /* COMMENT */
1019 BEGIN ssinit; /* send the results back; */
1020 } else { /* otherwise */
1022 errpkt((CHAR *)"No files match");
1024 errpkt((CHAR *)"Can't list directory");
1025 RESUME; /* return to server command wait */
1029 #endif /* NOSERVER */
1033 { /* REMOTE DELETE (Erase) */
1037 if (ckxsyslog >= SYSLG_PR && ckxlogging)
1038 cksyslog(SYSLG_PR, 1, "server", "REMOTE DELETE", (char *)srvcmd);
1039 #endif /* CKSYSLOG */
1040 if (!ENABLED(en_del)) {
1041 errpkt((CHAR *)"REMOTE DELETE disabled");
1043 } else { /* DELETE is enabled */
1045 if (ikdbopen) slotstate(what,"REMOTE DELETE", (char *)(srvcmd+2), "");
1047 if (!ENABLED(en_cwd)) { /* but CWD is disabled */
1048 zstrip((char *)(srvcmd+2),&n2); /* and they included a pathname, */
1049 if (strcmp((char *)(srvcmd+2),n2)) { /* so refuse. */
1050 errpkt((CHAR *)"Access denied");
1051 RESUME; /* Remember, this is not a goto! */
1053 } else if (isdir((char *)(srvcmd+2))) { /* A directory name? */
1054 errpkt((CHAR *)"It's a directory");
1057 if (state == generic) { /* It's OK to go ahead. */
1059 if ((x = snddel((char*)(srvcmd+2))) > 0) {
1060 BEGIN ssinit; /* If OK send results back */
1061 } else { /* otherwise */
1063 errpkt((CHAR *)"File not found"); /* report failure */
1065 errpkt((CHAR *)"DELETE failed");
1066 RESUME; /* & return to server command wait */
1070 #endif /* NOSERVER */
1077 if (ckxsyslog >= SYSLG_PR && ckxlogging)
1078 cksyslog(SYSLG_PR, 1, "server", "FINISH", NULL);
1079 #endif /* CKSYSLOG */
1081 if (ikdbopen) slotstate(what,"SERVER FINISH", "", "");
1083 if (!ENABLED(en_fin)) {
1084 errpkt((CHAR *)"FINISH disabled");
1087 ack(); /* Acknowledge */
1088 xxscreen(SCR_TC,0,0L,""); /* Display */
1090 return(0); /* Done */
1092 #endif /* NOSERVER */
1099 if (ckxsyslog >= SYSLG_PR && ckxlogging)
1100 cksyslog(SYSLG_PR, 1, "server", "REMOTE EXIT", NULL);
1101 #endif /* CKSYSLOG */
1103 if (ikdbopen) slotstate(what,"REMOTE EXIT", "", "");
1105 if (!ENABLED(en_xit)) {
1106 errpkt((CHAR *)"EXIT disabled");
1109 ack(); /* Acknowledge */
1110 xxscreen(SCR_TC,0,0L,""); /* Display */
1111 doexit(GOOD_EXIT,xitsta);
1113 #endif /* NOSERVER */
1117 { /* BYE (Logout) */
1120 if (ckxsyslog >= SYSLG_PR && ckxlogging)
1121 cksyslog(SYSLG_PR, 1, "server", "BYE", NULL);
1122 #endif /* CKSYSLOG */
1124 if (ikdbopen) slotstate(what,"SERVER BYE", "", "");
1126 if (!ENABLED(en_bye)) {
1127 errpkt((CHAR *)"BYE disabled");
1130 ack(); /* Acknowledge */
1132 msleep(750); /* Give the ACK time to get out */
1134 ttres(); /* Reset the terminal */
1135 xxscreen(SCR_TC,0,0L,""); /* Display */
1136 doclean(1); /* Clean up files, etc */
1138 debug(F100,"C-Kermit BYE - Logging out...","",0);
1146 #endif /* CK_LOGIN */
1150 if (network && tcpsrfd > 0 && !inserver)
1151 doexit(GOOD_EXIT,xitsta);
1153 #endif /* NOLISTEN */
1154 #endif /* TCPSOCKET */
1155 return(zkself()); /* Try to log self out */
1157 #endif /* NOSERVER */
1163 if (ckxsyslog >= SYSLG_PR && ckxlogging)
1164 cksyslog(SYSLG_PR, 1, "server", "REMOTE HELP", NULL);
1165 #endif /* CKSYSLOG */
1167 if (ikdbopen) slotstate(what,"REMOTE HELP", "", "");
1171 BEGIN ssinit; /* try to send it */
1172 } else { /* If not ok, */
1173 errpkt((CHAR *)"Can't send help"); /* send error message instead */
1174 RESUME; /* and return to server command wait */
1176 #endif /* NOSERVER */
1180 { /* REMOTE RENAME */
1182 debug(F101,"srv_rename","",rc);
1183 if (rc > -1) return(rc); /* (see below) */
1189 debug(F101,"srv_copy","",rc);
1190 if (rc > -1) return(rc); /* (see below) */
1196 if (ckxsyslog >= SYSLG_PR && ckxlogging)
1197 cksyslog(SYSLG_PR, 1, "server", "REMOTE SET", (char *)srvcmd);
1198 #endif /* CKSYSLOG */
1201 if (ikdbopen) slotstate(what,"REMOTE SET", (char *)(srvcmd+1), "");
1203 if (!ENABLED(en_set)) {
1204 errpkt((CHAR *)"REMOTE SET disabled");
1207 if (remset((char *)(srvcmd+1))) { /* Try to do what they ask */
1209 ack(); /* If OK, then acknowledge */
1210 } else /* Otherwise */
1211 errpkt((CHAR *)"Unknown REMOTE SET parameter"); /* give error msg */
1212 RESUME; /* Return to server command wait */
1214 #endif /* NOSERVER */
1222 if (ckxsyslog >= SYSLG_PR && ckxlogging)
1223 cksyslog(SYSLG_PR, 1, "server", "REMOTE TYPE", (char *)srvcmd);
1224 #endif /* CKSYSLOG */
1225 if (!ENABLED(en_typ)) {
1226 errpkt((CHAR *)"REMOTE TYPE disabled");
1230 if (ikdbopen) slotstate(what,"REMOTE TYPE", (char *)(srvcmd+2), "");
1232 if (!ENABLED(en_cwd)) { /* If CWD disabled */
1233 zstrip((char *)(srvcmd+2),&n2); /* and they included a pathname, */
1234 if (strcmp((char *)(srvcmd+2),n2)) { /* refuse. */
1235 errpkt((CHAR *)"Access denied");
1236 RESUME; /* Remember, this is not a goto! */
1239 if (state == generic) { /* It's OK to go ahead. */
1240 binary = XYFT_T; /* Use text mode for this. */
1241 if ( /* (RESUME didn't change state) */
1243 syscmd(TYPCMD,(char *)(srvcmd+2)) /* Old way */
1245 sndtype((char *)(srvcmd+2)) /* New way */
1246 #endif /* COMMENT */
1248 BEGIN ssinit; /* OK */
1250 errpkt((CHAR *)"Can't type file"); /* give error message */
1251 RESUME; /* wait for next server command */
1255 #endif /* NOSERVER */
1259 { /* REMOTE MKDIR */
1263 if (ckxsyslog >= SYSLG_PR && ckxlogging)
1264 cksyslog(SYSLG_PR, 1, "server", "REMOTE MKDIR", (char *)srvcmd);
1265 #endif /* CKSYSLOG */
1267 if (ikdbopen) slotstate(what,"REMOTE MKDIR", (char *)(srvcmd+2), "");
1269 if (!ENABLED(en_mkd)) {
1270 errpkt((CHAR *)"REMOTE MKDIR disabled");
1272 } else if (!ENABLED(en_cwd)) { /* If CWD disabled */
1273 errpkt((CHAR *)"Directory access restricted");
1274 RESUME; /* Remember, this is not a goto! */
1276 if (state == generic) { /* OK to go ahead. */
1278 x = ckmkdir(0,(char *)(srvcmd+2),&p,0,1); /* Make the directory */
1281 encstr((CHAR *)p); /* OK - encode the name */
1282 ack1(data); /* Send short-form response */
1285 } else { /* not OK */
1286 if (!*p) p = "Directory creation failure";
1287 errpkt((CHAR *)p); /* give error message */
1288 RESUME; /* Wait for next server command */
1292 errpkt((CHAR *)"REMOTE MKDIR not available");
1294 #endif /* CK_MKDIR */
1295 #endif /* NOSERVER */
1299 { /* REMOTE RMDIR */
1303 if (ckxsyslog >= SYSLG_PR && ckxlogging)
1304 cksyslog(SYSLG_PR, 1, "server", "REMOTE RMDIR", (char *)srvcmd);
1305 #endif /* CKSYSLOG */
1307 if (ikdbopen) slotstate(what,"REMOTE RMDIR", (char *)(srvcmd+2), "");
1309 if (!ENABLED(en_rmd)) {
1310 errpkt((CHAR *)"REMOTE RMDIR disabled");
1312 } else if (!ENABLED(en_cwd)) { /* If CWD disabled */
1313 errpkt((CHAR *)"Directory access restricted");
1314 RESUME; /* Remember, this is not a goto! */
1316 if (state == generic) { /* OK to go ahead. */
1318 x = ckmkdir(1,(char *)(srvcmd+2),&p,0,1);
1321 encstr((CHAR *)p); /* OK - encode the name */
1322 ack1(data); /* Send short-form response */
1325 } else { /* not OK */
1326 if (!*p) p = "Directory removal failure";
1327 errpkt((CHAR *)p); /* give error message */
1328 RESUME; /* Wait for next server command */
1332 errpkt((CHAR *)"REMOTE RMDIR not available");
1334 #endif /* CK_MKDIR */
1335 #endif /* NOSERVER */
1339 { /* REMOTE SPACE */
1342 if (ckxsyslog >= SYSLG_PR && ckxlogging)
1343 cksyslog(SYSLG_PR, 1, "server", "REMOTE SPACE", (char *)srvcmd);
1344 #endif /* CKSYSLOG */
1345 if (!ENABLED(en_spa)) {
1346 errpkt((CHAR *)"REMOTE SPACE disabled");
1349 x = srvcmd[1]; /* Get area to check */
1350 x = ((x == NUL) || (x == SP)
1352 || (x == '!') || (srvcmd[3] == ':')
1356 if (ikdbopen) slotstate(what,
1358 (x ? "" : (char *)srvcmd),
1362 if (!x && !ENABLED(en_cwd)) { /* CWD disabled */
1363 errpkt((CHAR *)"Access denied"); /* and non-default area given, */
1364 RESUME; /* refuse. */
1367 _PROTOTYP(int sndspace,(int));
1368 if (sndspace(x ? toupper(srvcmd[2]) : 0)) {
1369 BEGIN ssinit; /* send the report. */
1370 } else { /* If not ok, */
1371 errpkt((CHAR *)"Can't send space"); /* send error message */
1372 RESUME; /* and return to server command wait */
1378 x = (x ? syscmd(SPACMD,"") : syscmd(SPACM2,(char *)(srvcmd+2)));
1379 if (x) { /* If we got the info */
1380 BEGIN ssinit; /* send it */
1381 } else { /* otherwise */
1382 errpkt((CHAR *)"Can't check space"); /* send error message */
1383 RESUME; /* and await next server command */
1388 #endif /* NOSERVER */
1395 if (ckxsyslog >= SYSLG_PR && ckxlogging)
1396 cksyslog(SYSLG_PR, 1, "server", "REMOTE WHO", (char *)srvcmd);
1397 #endif /* CKSYSLOG */
1399 if (ikdbopen) slotstate(what,"REMOTE WHO", (char *)(srvcmd+2), "");
1401 if (!ENABLED(en_who)) {
1402 errpkt((CHAR *)"REMOTE WHO disabled");
1406 _PROTOTYP(int sndwho,(char *));
1407 if (sndwho((char *)(srvcmd+2))) {
1408 BEGIN ssinit; /* try to send it */
1409 } else { /* If not ok, */
1410 errpkt((CHAR *)"Can't do who command"); /* send error msg */
1411 RESUME; /* and return to server command wait */
1414 if (syscmd(WHOCMD,(char *)(srvcmd+2))) {
1417 errpkt((CHAR *)"Can't do who command");
1422 #endif /* NOSERVER */
1426 { /* Variable query or set */
1428 debug(F101,"srv_query","",rc);
1429 if (rc > -1) return(rc);
1433 { /* REMOTE MESSAGE command */
1435 debug(F110,"RMSG",(char *)srvcmd+2,0);
1436 xxscreen(SCR_MS,0,0L,(char *)(srvcmd+2));
1439 #endif /* NOSERVER */
1443 { /* Interrupted or connection lost */
1445 if (fatalio) { /* Connection lost */
1447 if (ckxsyslog >= SYSLG_PR && ckxlogging)
1448 cksyslog(SYSLG_PR, 1, "server", "Interrupted", NULL);
1449 #endif /* CKSYSLOG */
1451 xitsta |= (what & W_KERMIT);
1453 } else if (interrupted) {
1454 if (!ENABLED(en_fin)) { /* Ctrl-C typed */
1455 errpkt((CHAR *)"QUIT disabled");
1459 if (ckxsyslog >= SYSLG_PR && ckxlogging)
1460 cksyslog(SYSLG_PR, 1, "server", "Interrupted", NULL);
1461 #endif /* CKSYSLOG */
1463 xitsta |= (what & W_KERMIT);
1466 } else { /* Shouldn't happen */
1467 debug(F100,"SERVER (generic) GOT UNEXPECTED 'q'","",0);
1470 #endif /* NOSERVER */
1474 { /* Anything else in this state... */
1476 errpkt((CHAR *)"Unimplemented REMOTE command"); /* Complain */
1477 RESUME; /* and return to server command wait */
1478 #endif /* NOSERVER */
1482 { /* Sent BYE and connection broken */
1483 if (bye_active && ttchk() < 0) {
1486 ttclos(0); /* Close our end of the connection */
1488 return(success = 1);
1489 } else { /* Other generic command */
1490 return(success = 0); /* or connection not broken */
1495 { /* Short-Form reply */
1496 rc = rcv_shortreply();
1497 debug(F101,"<rgen>Y rcv_shortreply","",rc);
1498 if (rc > -1) return(rc);
1505 debug(F101,"<rfile>F winlo 1","",winlo);
1506 xflg = 0; /* Not screen data */
1508 cancel = 0; /* Reset cancellation counter */
1512 #endif /* CALIBRATE */
1513 if (!rcvfil(filnam)) { /* Figure out local filename */
1514 errpkt((CHAR *)rf_err); /* Trouble */
1516 } else { /* Real file, OK to receive */
1518 debug(F111,"<rfile>F winlo 2",fspec,winlo);
1519 if (filcnt == 1) /* rcvfil set this to 1 for 1st file */
1520 crc16 = 0L; /* Clear file CRC */
1521 fnp = fspec; /* This is the full path */
1522 if (server && !ENABLED(en_cwd) || /* if DISABLE CD */
1523 !fackpath /* or F-ACK-PATH OFF */
1525 zstrip(fspec,&fnp); /* don't send back full path */
1527 encstr((CHAR *)fnp);
1531 ack1(data); /* Send it back in ACK */
1532 initattr(&iattr); /* Clear file attribute structure */
1534 if (window(wslotn) < 0) { /* Allocate negotiated window slots */
1535 errpkt((CHAR *)"Can't open window");
1539 if (ikdbopen) slotstate(what,
1540 server ? "SERVER" : "",
1545 BEGIN rattr; /* Now expect Attribute packets */
1550 { /* X-packet instead of file header */
1551 xflg = 1; /* Screen data */
1553 cancel = 0; /* Reset cancellation counter */
1554 ack(); /* Acknowledge the X-packet */
1555 initattr(&iattr); /* Initialize attribute structure */
1557 if (window(wslotn) < 0) { /* allocate negotiated window slots */
1558 errpkt((CHAR *)"Can't open window");
1562 if (query) { /* If this is the response to */
1563 qbufp = querybuf; /* a query that we sent, initialize */
1564 qbufn = 0; /* the response buffer */
1568 what = W_REMO; /* we're doing a REMOTE command */
1570 if (ikdbopen) slotstate(what,
1571 server ? "SERVER" : "",
1576 BEGIN rattr; /* Expect Attribute packets */
1580 { /* Attribute packet */
1581 if (gattr(rdatap,&iattr) == 0) { /* Read into attribute structure */
1583 ack1((CHAR *)iattr.reply.val); /* Reply with data */
1585 ack(); /* If OK, acknowledge */
1586 #endif /* CK_RESEND */
1587 } else { /* Otherwise */
1590 r = getreason(iattr.reply.val);
1591 ack1((CHAR *)iattr.reply.val); /* refuse to accept the file */
1592 xxscreen(SCR_ST,ST_REFU,0L,r); /* reason */
1594 if (tralog && !tlogfmt)
1595 doxlog(what,filnam,fsize,binary,1,r);
1601 { /* First data packet */
1602 debug(F100,"<rattr> D firstdata","",0);
1603 rc = rcv_firstdata();
1604 debug(F101,"rcv_firstdata rc","",rc);
1605 if (rc > -1) return(rc); /* (see below) */
1609 { /* EOT, no more files */
1610 ack(); /* Acknowledge the B packet */
1611 reot(); /* Do EOT things */
1613 /* If we were cd'd temporarily to another device or directory ... */
1616 x = zchdir((char *) savdir); /* ... restore previous directory */
1617 f_tmpdir = 0; /* and remember we did it. */
1618 debug(F111,"ckcpro.w B tmpdir restoring",savdir,x);
1620 #endif /* CK_TMPDIR */
1621 RESUME; /* and quit */
1625 { /* Got Data packet */
1626 debug(F101,"<rdpkt>D cxseen","",cxseen);
1627 debug(F101,"<rdpkt>D czseen","",czseen);
1628 if (cxseen || czseen || discard) { /* If file or group interruption */
1630 msg = czseen ? (CHAR *)"Z" : (CHAR *)"X";
1632 if (streaming) { /* Need to cancel */
1633 debug(F111,"<rdpkt>D streaming cancel",msg,cancel);
1634 if (cancel++ == 0) { /* Only do this once */
1635 ack1(msg); /* Put "X" or "Z" in ACK */
1636 } else if (czseen) {
1637 errpkt((CHAR *)"User canceled");
1643 #endif /* STREAMING */
1645 } else { /* No interruption */
1653 rc = (binary && !parity) ?
1654 bdecode(rdatap,putfil):
1655 decode(rdatap, qf ? puttrm : putfil, 1);
1657 rc = decode(rdatap, qf ? puttrm : putfil, 1);
1658 #endif /* CKTUNING */
1660 discard = (keep == 0 || (keep == SET_AUTO && binary != XYFT_T));
1661 errpkt((CHAR *)"Error writing data"); /* If failure, */
1663 } else /* Data written OK, send ACK */
1668 #endif /* STREAMING */
1674 { /* EOF immediately after A-Packet. */
1675 rf_err = "Can't create file";
1677 if (discard) { /* Discarding a real file... */
1679 } else if (xflg) { /* If screen data */
1680 if (remfile) { /* redirected to file */
1681 if (rempipe) /* or pipe */
1682 x = openc(ZOFILE,remdest); /* Pipe: start command */
1684 x = opena(remdest,&iattr); /* File: open with attributes */
1685 } else { /* otherwise */
1686 x = opent(&iattr); /* "open" the screen */
1689 } else if (calibrate) { /* If calibration run */
1690 x = ckopenx(&iattr); /* do this */
1691 #endif /* CALIBRATE */
1692 } else { /* otherwise */
1693 x = opena(filnam,&iattr); /* open the file, with attributes */
1694 if (x == -17) { /* REGET skipped because same size */
1699 if (!x || reof(filnam, &iattr) < 0) { /* Close output file */
1700 errpkt((CHAR *) rf_err); /* If problem, send error msg */
1701 RESUME; /* and quit */
1702 } else { /* otherwise */
1704 xxscreen(SCR_ST,ST_SKIP,SKP_RES,"");
1705 ack(); /* acknowledge the EOF packet */
1706 BEGIN rfile; /* and await another file */
1711 { /* Ctrl-C or connection loss. */
1713 window(1); /* Set window size back to 1... */
1715 x = clsof(1); /* Close file */
1716 return(success = 0); /* Failed */
1720 { /* End Of File (EOF) Packet */
1721 /* wslots = 1; */ /* (don't set) Window size back to 1 */
1722 #ifndef COHERENT /* Coherent compiler blows up on this switch() statement. */
1723 x = reof(filnam, &iattr); /* Handle the EOF packet */
1724 switch (x) { /* reof() sets the success flag */
1725 case -5: /* Handle problems */
1726 errpkt((CHAR *)"RENAME failed"); /* Fatal */
1730 errpkt((CHAR *)"MOVE failed"); /* Fatal */
1733 case -3: /* If problem, send error msg */
1734 errpkt((CHAR *)"Can't print file"); /* Fatal */
1738 errpkt((CHAR *)"Can't mail file"); /* Fatal */
1741 case 2: /* Not fatal */
1743 xxscreen(SCR_EM,0,0L,"Receiver can't delete temp file");
1747 if (x < 0) { /* Fatal */
1748 errpkt((CHAR *)"Can't close file");
1750 } else { /* Success */
1752 if (query) /* Query reponses generally */
1753 conoll(""); /* don't have line terminators */
1755 if (czseen) { /* Batch canceled? */
1756 if (cancel++ == 0) { /* If we haven't tried this yet */
1757 ack1((CHAR *)"Z"); /* Try it once */
1758 } else { /* Otherwise */
1759 errpkt((CHAR *)"User canceled"); /* quite with Error */
1763 ack(); /* Acknowledge the EOF packet */
1764 BEGIN rfile; /* and await another file */
1768 if (reof(filnam, &iattr) < 0) { /* Close the file */
1769 errpkt((CHAR *)"Error at end of file");
1771 } else { /* reof() sets success flag */
1775 #endif /* COHERENT */
1779 { /* ACK for Send-Init */
1780 spar(rdatap); /* set parameters from it */
1786 bctu = bctr; /* switch to agreed-upon block check */
1787 bctl = (bctu == 4) ? 2 : bctu; /* Set block-check length */
1791 if ((sendmode == SM_RESEND) && (!atcapu || !rscapu)) { /* RESEND */
1792 errpkt((CHAR *) "RESEND capabilities not negotiated");
1795 #endif /* CK_RESEND */
1796 what = W_SEND; /* Remember we're sending */
1798 x = sfile(xflg); /* Send X or F header packet */
1799 cancel = 0; /* Reset cancellation counter */
1800 if (x) { /* If the packet was sent OK */
1801 if (!xflg && filcnt == 1) /* and it's a real file */
1802 crc16 = 0L; /* Clear the file CRC */
1803 resetc(); /* reset per-transaction counters */
1804 rtimer(); /* reset timers */
1807 #endif /* GFTIMER */
1808 streamon(); /* turn on streaming */
1810 if (ikdbopen) slotstate(what,
1811 (server ? "SERVER" : ""),
1816 BEGIN ssfile; /* and switch to receive-file state */
1817 } else { /* otherwise send error msg & quit */
1818 s = xflg ? "Can't execute command" : (char *)epktmsg;
1819 if (!*s) s = "Can't open file";
1825 #endif /* CK_RESEND */
1829 { /* R packet was retransmitted. */
1830 xsinit(); /* Resend packet 0 */
1834 { /* Same deal if G packet comes again */
1839 { /* Same deal if C packet comes again */
1844 { /* ACK for F or X packet */
1845 srvptr = srvcmd; /* Point to string buffer */
1846 decode(rdatap,putsrv,0); /* Decode data field, if any */
1847 putsrv(NUL); /* Terminate with null */
1848 ffc = 0L; /* Reset file byte counter */
1849 debug(F101,"<ssfile>Y cxseen","",cxseen);
1850 if (*srvcmd) { /* If remote name was recorded */
1851 if (sendmode != SM_RESEND) {
1852 if (fdispla == XYFD_C || fdispla == XYFD_S)
1853 xxscreen(SCR_AN,0,0L,(char *)srvcmd);
1854 tlog(F110," remote name:",(char *) srvcmd,0L);
1855 makestr(&psrfspec,(char *)srvcmd);
1858 if (cxseen||czseen) { /* Interrupted? */
1859 debug(F101,"<ssfile>Y canceling","",0);
1860 x = clsif(); /* Close input file */
1861 sxeof(1); /* Send EOF(D) */
1862 BEGIN sseof; /* and switch to EOF state. */
1863 } else if (atcapu) { /* If attributes are to be used */
1864 if (sattr(xflg | stdinf, 1) < 0) { /* send them */
1865 errpkt((CHAR *)"Can't send attributes"); /* if problem, say so */
1866 RESUME; /* and quit */
1867 } else BEGIN ssattr; /* if ok, switch to attribute state */
1868 } else { /* Attributes not negotiated */
1869 if (window(wslotn) < 0) { /* Open window */
1870 errpkt((CHAR *)"Can't open window");
1872 } else if ((x = sdata()) == -2) { /* Send first data packet data */
1873 window(1); /* Connection lost, reset window */
1874 x = clsif(); /* Close input file */
1875 return(success = 0); /* Return failure */
1876 } else if (x == -9) { /* User interrupted */
1877 errpkt((CHAR *)"User cancelled"); /* Send Error packet */
1878 window(1); /* Set window size back to 1... */
1879 timint = s_timint; /* Restore timeout */
1880 return(success = 0); /* Failed */
1881 } else if (x < 0) { /* EOF (empty file) or interrupted */
1882 window(1); /* put window size back to 1, */
1883 debug(F101,"<ssfile>Y cxseen","",cxseen);
1884 x = clsif(); /* If not ok, close input file, */
1885 if (x < 0) /* treating failure as interruption */
1886 cxseen = 1; /* Send EOF packet */
1887 seof(cxseen||czseen);
1888 BEGIN sseof; /* and switch to EOF state. */
1889 } else { /* First data sent OK */
1890 BEGIN ssdata; /* All ok, switch to send-data state */
1896 { /* Got ACK to A packet */
1897 ffc = 0L; /* Reset file byte counter */
1898 debug(F101,"<ssattr>Y cxseen","",cxseen);
1899 if (cxseen||czseen) { /* Interrupted? */
1900 debug(F101,"<sattr>Y canceling","",0);
1901 x = clsif(); /* Close input file */
1902 sxeof(1); /* Send EOF(D) */
1903 BEGIN sseof; /* and switch to EOF state. */
1904 } else if (rsattr(rdatap) < 0) { /* Was the file refused? */
1905 discard = 1; /* Set the discard flag */
1906 clsif(); /* Close the file */
1907 sxeof(1); /* send EOF with "discard" code */
1908 BEGIN sseof; /* switch to send-EOF state */
1909 } else if ((x = sattr(xflg | stdinf, 0)) < 0) { /* Send more? */
1910 errpkt((CHAR *)"Can't send attributes"); /* Trouble... */
1912 } else if (x == 0) { /* No more to send so now the data */
1913 if (window(wslotn) < 0) { /* Allocate negotiated window slots */
1914 errpkt((CHAR *)"Can't open window");
1917 if ((x = sdata()) == -2) { /* File accepted, send first data */
1918 window(1); /* Connection broken */
1919 x = clsif(); /* Close file */
1920 return(success = 0); /* Return failure */
1921 } else if (x == -9) { /* User interrupted */
1922 errpkt((CHAR *)"User cancelled"); /* Send Error packet */
1923 window(1); /* Set window size back to 1... */
1924 timint = s_timint; /* Restore timeout */
1925 return(success = 0); /* Failed */
1926 } else if (x < 0) { /* If data was not sent */
1927 window(1); /* put window size back to 1, */
1928 debug(F101,"<ssattr>Y cxseen","",cxseen);
1929 if (clsif() < 0) /* Close input file */
1930 cxseen = 1; /* Send EOF packet */
1931 seof(cxseen||czseen);
1932 BEGIN sseof; /* and switch to EOF state. */
1934 BEGIN ssdata; /* All ok, switch to send-data state */
1940 { /* Ctrl-C or connection loss. */
1941 window(1); /* Set window size back to 1... */
1942 cxseen = 1; /* To indicate interruption */
1943 x = clsif(); /* Close file */
1944 return(success = 0); /* Failed */
1948 { /* Got ACK to Data packet */
1949 canned(rdatap); /* Check if file transfer cancelled */
1950 debug(F111,"<ssdata>Y cxseen",rdatap,cxseen);
1951 debug(F111,"<ssdata>Y czseen",rdatap,czseen);
1952 if ((x = sdata()) == -2) { /* Try to send next data */
1953 window(1); /* Connection lost, reset window */
1954 x = clsif(); /* Close file */
1955 return(success = 0); /* Failed */
1956 } else if (x == -9) { /* User interrupted */
1957 errpkt((CHAR *)"User cancelled"); /* Send Error packet */
1958 window(1); /* Set window size back to 1... */
1959 timint = s_timint; /* Restore original timeout */
1960 return(success = 0); /* Failed */
1961 } else if (x < 0) { /* EOF - finished sending data */
1962 debug(F101,"<ssdata>Y cxseen","",cxseen);
1963 window(1); /* Set window size back to 1... */
1964 if (clsif() < 0) /* Close input file */
1965 cxseen = 1; /* Send EOF packet */
1966 debug(F101,"<ssdata>Y CALLING SEOF()","",cxseen);
1967 seof(cxseen||czseen);
1968 BEGIN sseof; /* and enter send-eof state */
1970 /* NOTE: If x == 0 it means we're draining: see sdata()! */
1974 { /* Got ACK to EOF */
1976 canned(rdatap); /* Check if file transfer cancelled */
1977 debug(F111,"<sseof>Y cxseen",rdatap,cxseen);
1978 debug(F111,"<sseof>Y czseen",rdatap,czseen);
1979 debug(F111,"<sseof>Y discard",rdatap,discard);
1982 success = (cxseen == 0 && czseen == 0); /* Transfer status... */
1983 debug(F101,"<sseof>Y success","",success);
1984 if (success && rejection > 0) /* If rejected, succeed if */
1985 if (rejection != '#' && /* reason was date */
1986 rejection != 1 && rejection != '?') /* or name; */
1987 success = 0; /* fail otherwise. */
1988 cxseen = 0; /* This goes back to zero. */
1989 if (success) { /* Only if transfer succeeded... */
1990 xxscreen(SCR_ST,ST_OK,0L,"");
1992 makestr(&sfspec,psfspec); /* Record filenames for WHERE */
1993 makestr(&srfspec,psrfspec);
1995 if (moving) { /* If MOVE'ing */
1996 x = zdelet(filnam); /* Try to delete the source file */
2000 tlog(F110," deleted",filnam,0);
2002 tlog(F110," delete failed:",ck_errstr(),0);
2006 } else if (snd_move) { /* Or move it */
2008 x = zrename(filnam,snd_move);
2012 tlog(F110," moved to ",snd_move,0);
2014 tlog(F110," move failed:",ck_errstr(),0);
2018 } else if (snd_rename) { /* Or rename it */
2019 char *s = snd_rename; /* Renaming string */
2021 int y; /* Pass it thru the evaluator */
2022 extern int cmd_quoting; /* for \v(filename) */
2023 if (cmd_quoting) { /* But only if cmd_quoting is on */
2026 zzstring(snd_rename,&s,&y);
2032 x = zrename(filnam,s);
2036 tlog(F110," renamed to",s,0);
2038 tlog(F110," rename failed:",ck_errstr(),0);
2044 #endif /* COMMENT */
2048 if (czseen) { /* Check group interruption flag */
2049 g = 0; /* No more files if interrupted */
2050 } else { /* Otherwise... */
2052 /* This code makes any open error fatal to a file-group transfer. */
2054 debug(F111,"<sseof>Y gnfile",filnam,g);
2055 if (g > 0) { /* Any more files to send? */
2056 if (sfile(xflg)) /* Yes, try to send next file header */
2057 BEGIN ssfile; /* if ok, enter send-file state */
2058 else { /* otherwise */
2059 s = xflg ? "Can't execute command" : (char *)epktmsg;
2060 if (!*s) s = "Can't open file";
2061 errpkt((CHAR *)s); /* send error message */
2062 RESUME; /* and quit */
2064 } else { /* No next file */
2065 tsecs = gtimer(); /* get statistics timers */
2067 fptsecs = gftimer();
2068 #endif /* GFTIMER */
2069 seot(); /* send EOT packet */
2070 BEGIN sseot; /* enter send-eot state */
2073 while (1) { /* Keep trying... */
2074 g = gnfile(); /* Get next file */
2075 debug(F111,"<sseof>Y gnfile",filnam,g);
2076 if (g == 0 && gnferror == 0) /* No more, stop trying */
2078 if (g > 0) { /* Have one */
2079 if (sfile(xflg)) { /* Try to open and send F packet */
2080 BEGIN ssfile; /* If OK, enter send-file state */
2081 break; /* and break out of loop. */
2083 } /* Otherwise keep trying to get one we can send... */
2087 debug(F101,"<sseof>Y no more files","",czseen);
2088 tsecs = gtimer(); /* Get statistics timers */
2090 fptsecs = gftimer();
2091 #endif /* GFTIMER */
2092 seot(); /* Send EOT packet */
2093 BEGIN sseot; /* Enter send-eot state */
2095 #endif /* COMMENT */
2099 { /* Got ACK to EOT */
2100 debug(F101,"sseot justone","",justone);
2101 RESUME; /* All done, just quit */
2105 { /* Got Error packet, in any state */
2107 window(1); /* Close window */
2108 timint = s_timint; /* Restore original timeout */
2109 if (*epktmsg) /* Message from Error packet */
2110 s = (char *)epktmsg;
2111 if (!*s) { /* If not there then maybe here */
2113 ckstrncpy((char *)epktmsg,(char *)rdatap,PKTMSGLEN);
2115 if (!*s) /* Hopefully we'll never see this. */
2116 s = "Unknown error";
2117 success = 0; /* For IF SUCCESS/FAIL. */
2118 debug(F101,"ckcpro.w justone at E pkt","",justone);
2120 success = 0; /* Transfer failed */
2121 xferstat = success; /* Remember transfer status */
2123 x = quiet; quiet = 1; /* Close files silently, */
2124 epktrcvd = 1; /* Prevent messages from clsof() */
2126 clsof(1); /* discarding any output file. */
2127 ermsg(s); /* Issue the message (calls screen). */
2128 quiet = x; /* Restore quiet state */
2130 tstats(); /* Get stats */
2132 If we are executing commands from a command file or macro, let the command
2133 file or macro decide whether to exit, based on SET { TAKE, MACRO } ERROR.
2140 fatal("Protocol error");
2141 xitsta |= (what & W_KERMIT); /* Save this for doexit(). */
2143 /* If we were cd'd temporarily to another device or directory ... */
2146 x = zchdir((char *) savdir); /* ... restore previous directory */
2147 f_tmpdir = 0; /* and remember we did it. */
2148 debug(F111,"ckcpro.w E tmpdir restored",savdir,x);
2150 #endif /* CK_TMPDIR */
2152 if (ikdbopen) slotstate(what,"ERROR", (char *)epktmsg, "");
2158 { success = 0; QUIT; }
2161 { /* Anything not accounted for above */
2162 errpkt((CHAR *)"Unexpected packet type"); /* Give error message */
2164 xitsta |= (what & W_KERMIT); /* Save this for doexit(). */
2165 RESUME; /* and quit */
2174 -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2175 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2176 74, 74, 74, 74, 74, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2177 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2178 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2179 74, 73, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
2180 -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2181 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2182 74, 74, 74, 74, 74, 15, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2183 74, 74, 74, 74, 74, 74, 74, 74, 74, 13, 74, 74, 74, 74, 74, 74,
2184 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2185 74, 73, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
2186 -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2187 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2188 74, 74, 57, 74, 74, 72, 53, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2189 74, 74, 74, 74, 74, 74, 74, 74, 54, 74, 74, 74, 74, 74, 74, 74,
2190 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2191 74, 73, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
2192 -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2193 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2194 74, 55, 74, 74, 56, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2195 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 59, 74, 74, 74, 74, 74,
2196 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2197 74, 73, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
2198 -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2199 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2200 74, 74, 74, 74, 58, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2201 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 61, 74, 74, 74, 74, 74,
2202 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2203 74, 60, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
2204 -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2205 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2206 74, 74, 74, 65, 74, 72, 74, 64, 74, 74, 74, 74, 74, 74, 74, 74,
2207 74, 74, 63, 74, 74, 74, 74, 74, 74, 62, 74, 74, 74, 74, 74, 74,
2208 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2209 74, 73, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
2210 -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2211 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2212 74, 74, 74, 74, 74, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2213 74, 74, 74, 74, 74, 74, 74, 74, 74, 66, 74, 74, 74, 74, 74, 74,
2214 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2215 74, 73, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
2216 -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2217 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2218 74, 74, 74, 74, 74, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2219 74, 74, 74, 74, 74, 74, 74, 74, 74, 67, 74, 74, 74, 74, 74, 74,
2220 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2221 74, 73, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
2222 -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2223 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2224 74, 74, 74, 74, 74, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2225 74, 74, 74, 74, 74, 74, 74, 74, 74, 69, 74, 74, 74, 74, 74, 74,
2226 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2227 74, 68, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
2228 -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2229 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2230 74, 74, 74, 74, 74, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2231 74, 74, 74, 74, 74, 74, 74, 74, 74, 70, 74, 74, 74, 74, 74, 74,
2232 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2233 74, 73, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
2234 -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2235 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2236 74, 74, 74, 74, 74, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2237 74, 74, 74, 74, 74, 74, 74, 74, 74, 71, 74, 74, 74, 74, 74, 74,
2238 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2239 74, 73, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
2240 -1, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
2241 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
2242 29, 29, 29, 26, 29, 29, 29, 25, 19, 17, 22, 29, 29, 29, 28, 23,
2243 29, 29, 18, 12, 29, 29, 20, 21, 29, 29, 29, 29, 29, 29, 29, 29,
2244 29, 11, 29, 7, 29, 29, 29, 9, 4, 29, 5, 8, 29, 29, 29, 6,
2245 29, 27, 3, 1, 29, 29, 2, 29, 10, 29, 29, 29, 29, 29, 29, 29,
2246 -1, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
2247 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
2248 50, 32, 50, 31, 33, 34, 35, 50, 38, 30, 50, 40, 37, 48, 50, 50,
2249 50, 50, 39, 41, 42, 45, 47, 46, 36, 50, 50, 50, 50, 50, 50, 50,
2250 50, 11, 50, 7, 44, 50, 50, 9, 4, 50, 5, 8, 50, 43, 50, 6,
2251 50, 49, 3, 1, 50, 50, 2, 50, 10, 50, 50, 50, 50, 50, 50, 50,
2252 -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2253 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2254 74, 74, 74, 74, 74, 72, 74, 74, 74, 17, 74, 74, 74, 74, 74, 74,
2255 74, 74, 74, 12, 74, 74, 74, 74, 74, 16, 74, 74, 74, 74, 74, 74,
2256 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2257 74, 73, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
2258 -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2259 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2260 74, 74, 74, 74, 74, 72, 53, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2261 74, 74, 74, 12, 74, 74, 74, 74, 54, 52, 74, 74, 74, 74, 74, 74,
2262 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2263 74, 51, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
2264 -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2265 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2266 74, 74, 74, 74, 74, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2267 74, 74, 74, 74, 74, 74, 74, 74, 74, 14, 74, 74, 74, 74, 74, 74,
2268 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2269 74, 73, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
2270 0, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2271 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2272 74, 74, 74, 74, 74, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 24,
2273 74, 74, 74, 12, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2274 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2275 74, 73, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74,74
2280 From here down to proto() are routines that were moved out of the state
2281 table switcher because the resulting switch() had become too large.
2282 To move the contents of a state-table case to a routine:
2283 1. Add a prototype to the list above the state table switcher.
2284 2. Make a routine with an appropriate name, returning int.
2285 3. Move the code into it.
2286 4. Put a call to the new routine in the former spot:
2287 rc = name_of_routine();
2288 if (rc > -1) return(rc);
2289 5. Add "return(-1);" after every RESUME, SERVE, or BEGIN macro and
2290 at the end if the code is open-ended.
2295 debug(F101,"rcv_firstdata","",dispos);
2297 if (discard) { /* if we're discarding the file */
2298 ack1((CHAR *)"X"); /* just ack the data like this. */
2299 cancel++; /* and count it */
2300 BEGIN rdpkt; /* and wait for more data packets. */
2302 } else { /* Not discarding. */
2303 rf_err = "Can't open file";
2304 if (xflg) { /* If screen data */
2305 if (remfile) { /* redirected to file */
2306 if (rempipe) /* or pipe */
2307 x = openc(ZOFILE,remdest); /* Pipe: start command */
2309 x = opena(remdest,&iattr); /* File: open with attributes */
2310 } else { /* otherwise */
2311 x = opent(&iattr); /* "open" the screen */
2313 } else { /* otherwise */
2315 if (calibrate) { /* If calibration run */
2316 x = ckopenx(&iattr); /* open nothing */
2318 if (streaming) /* Streaming */
2319 fastack(); /* ACK without ACKing. */
2321 #endif /* STREAMING */
2322 ack(); /* Send real ACK */
2323 BEGIN rdpkt; /* Proceed to next state */
2326 #endif /* CALIBRATE */
2329 In UNIX we can pipe the file data into the mail program, which is to be
2330 preferred to writing it out to a temp file and then mailing it afterwards.
2331 This depends rather heavily on all UNIXes having a mail command that
2332 accepts '-s "subject"' on the command line. MAILCMD (e.g. mail, Mail, mailx)
2333 is defined in ckufio.c.
2335 if (dispos == 'M') { /* Mail... */
2339 extern char *MAILCMD;
2340 s = iattr.disp.val + 1;
2341 n = (int)strlen(MAILCMD) + /* Mail command */
2342 (int)strlen(s) + /* address */
2343 (int)strlen(ofilnam) + 32; /* subject */
2344 if (tmp = (char *)malloc(n)) {
2346 MAILCMD," -s \"",ofilnam,"\" ",s,
2347 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
2348 debug(F111,"rcv_firsdata mail",tmp,(int)strlen(tmp));
2349 x = openc(ZOFILE,(char *)tmp);
2353 } else if (dispos == 'P') { /* Ditto for print */
2356 extern char *PRINTCMD;
2357 n = (int)strlen(PRINTCMD) + (int)strlen(iattr.disp.val+1) + 4;
2358 if (tmp = (char *)malloc(n)) {
2359 sprintf(tmp, /* safe (prechecked) */
2360 "%s %s", PRINTCMD, iattr.disp.val + 1);
2361 x = openc(ZOFILE,(char *)tmp);
2367 x = opena(filnam,&iattr); /* open the file, with attributes */
2369 if (x) { /* If file was opened ok */
2378 rc = (binary && !parity) ?
2379 bdecode(rdatap,putfil):
2380 decode(rdatap, qf ? puttrm : putfil, 1);
2382 rc = decode(rdatap, qf ? puttrm : putfil, 1);
2383 #endif /* CKTUNING */
2385 errpkt((CHAR *)"Error writing data");
2390 if (streaming) /* Streaming was negotiated */
2391 fastack(); /* ACK without ACKing. */
2393 #endif /* STREAMING */
2394 ack(); /* acknowledge it */
2395 BEGIN rdpkt; /* and switch to receive-data state */
2397 } else { /* otherwise */
2398 errpkt((CHAR *) rf_err); /* send error packet */
2399 RESUME; /* and quit. */
2409 debug(F111,"rcv_shortreply",rdatap,ipktlen);
2410 if (ipktack[0] && !strncmp(ipktack,(char *)rdatap,ipktlen)) {
2411 /* No it's the ACK to the I packet again */
2412 x = scmd(vcmd,(CHAR *)cmarg); /* So send the REMOTE command again */
2413 /* Maybe this should be resend() */
2414 debug(F110,"IPKTZEROHACK",ipktack,x);
2416 errpkt((CHAR *)srimsg);
2422 #endif /* PKTZEROHACK */
2426 if (query) { /* If to query, */
2427 qbufp = querybuf; /* initialize query response buffer */
2433 if (remfile) { /* Response redirected to file */
2434 rf_err = "Can't open file";
2435 if (rempipe) /* or pipe */
2438 zxcmd(ZOFILE,remdest) /* Pipe: Start command */
2444 x = opena(remdest,&iattr); /* File: Open with attributes */
2445 debug(F111,"rcv_shortreply remfile",remdest,x);
2447 x = opent(&iattr); /* "open" the screen */
2449 if (x) { /* If file was opened ok */
2452 (query || !remfile) ? puttrm :
2456 zputfil, 1) < 0) { /* Note: zputfil, not putfil. */
2457 errpkt((CHAR *)"Error writing data");
2461 if (rdatap) /* If we had data */
2462 if (*rdatap) /* add a line terminator */
2463 if (remfile) { /* to file */
2465 } else { /* or to screen. */
2467 if (!query || !xcmdsrc)
2469 if (!(quiet && rcdactive))
2472 if (bye_active && network) { /* I sent BYE or REMOTE LOGOUT */
2473 msleep(500); /* command and got the ACK... */
2478 if (!epktsent && !epktrcvd) /* If no error packet... */
2479 success = 1; /* success. */
2483 } else { /* File not opened OK */
2484 errpkt((CHAR *) rf_err); /* send error message */
2485 RESUME; /* and quit. */
2488 #endif /* NOSERVER */
2491 #endif /* PKTZEROHACK */
2492 debug(F101,"rcv_shortreply fallthru","",success);
2503 if (ckxsyslog >= SYSLG_PR && ckxlogging)
2504 cksyslog(SYSLG_PR, 1, "server", "REMOTE QUERY", (char *)srvcmd);
2505 #endif /* CKSYSLOG */
2507 if (ikdbopen) slotstate(what,"REMOTE QUERY", (char *)(srvcmd+2), "");
2509 c = *(srvcmd+2); /* Q = Query, S = Set */
2510 if (c == 'Q') { /* Query */
2511 if (!ENABLED(en_que)) { /* Security */
2512 errpkt((CHAR *)"REMOTE QUERY disabled");
2515 } else { /* Query allowed */
2517 qbufp = querybuf; /* Wipe out old stuff */
2520 p = (char *) srvcmd + 3; /* Pointer for making wrapper */
2521 n = strlen((char *)srvcmd); /* Position of end */
2522 c = *(srvcmd+4); /* Which type of variable */
2524 if (*(srvcmd+6) == CMDQ) { /* Starts with command quote? */
2525 p = (char *) srvcmd + 6; /* Take it literally */
2526 if (*p == CMDQ) p++;
2527 } else { /* They played by the rules */
2528 if (c == 'K') { /* Kermit variable */
2530 k = (int) strlen(p);
2531 if (k > 0 && p[k-1] == ')') {
2532 p = (char *)(srvcmd + 4);
2534 *(srvcmd+5) = 'f'; /* Function, so make it \f...() */
2536 *(srvcmd+3) = CMDQ; /* Stuff wrapping into buffer */
2537 *(srvcmd+4) = 'v'; /* Variable, so make it \v(...) */
2538 *(srvcmd+5) = '('; /* around variable name */
2540 *(srvcmd+n+1) = NUL;
2543 *(srvcmd+3) = CMDQ; /* Stuff wrapping into buffer */
2544 *(srvcmd+4) = 'v'; /* Variable, so make it \v(...) */
2545 *(srvcmd+5) = '('; /* around variable name */
2547 *(srvcmd+n+1) = NUL;
2548 if (c == 'S') { /* System variable */
2549 *(srvcmd+4) = '$'; /* so it's \$(...) */
2550 } else if (c == 'G') { /* Non-\ Global variable */
2551 *(srvcmd+4) = 'm'; /* so wrap it in \m(...) */
2554 } /* Now evaluate it */
2555 n = QBUFL; /* Max length */
2556 q = querybuf; /* Where to put it */
2557 if (zzstring(p,&q,&n) < 0) {
2558 errpkt((n > 0) ? (CHAR *)"Can't get value"
2559 : (CHAR *)"Value too long"
2564 if (encstr((CHAR *)querybuf) > -1) { /* Encode it */
2565 ack1(data); /* If it fits, send it back in ACK */
2569 } else if (sndstring(querybuf)) { /* Long form response */
2572 } else { /* sndhlp() fails */
2573 errpkt((CHAR *)"Can't send value");
2579 } else if (c == 'S') { /* Set (assign) */
2580 if (!ENABLED(en_asg)) { /* Security */
2581 errpkt((CHAR *)"REMOTE ASSIGN disabled");
2586 n = xunchar(*(srvcmd+3)); /* Length of name */
2587 n = 3 + n + 1; /* Position of length of value */
2588 *(srvcmd+n) = NUL; /* Don't need it */
2589 if (addmac((char *)(srvcmd+4),(char *)(srvcmd+n+1)) < 0)
2590 errpkt((CHAR *)"REMOTE ASSIGN failed");
2599 errpkt((CHAR *)"Badly formed server command");
2604 errpkt((CHAR *)"Variable query/set not available");
2608 #endif /* NOSERVER */
2615 if (ckxsyslog >= SYSLG_PR && ckxlogging)
2616 cksyslog(SYSLG_PR, 1, "server", "REMOTE COPY", (char *)srvcmd);
2617 #endif /* CKSYSLOG */
2619 if (!ENABLED(en_cpy)) {
2620 errpkt((CHAR *)"REMOTE COPY disabled");
2624 char *str1, *str2, f1[256], f2[256];
2626 len1 = xunchar(srvcmd[1]); /* Separate the parameters */
2627 len2 = xunchar(srvcmd[2+len1]);
2628 strncpy(f1,(char *)(srvcmd+2),len1);
2630 strncpy(f2,(char *)(srvcmd+3+len1),len2);
2633 if (ikdbopen) slotstate(what,"REMOTE COPY", f1, f2);
2635 if (!ENABLED(en_cwd)) { /* If CWD is disabled */
2636 zstrip(f1,&str1); /* and they included a pathname, */
2638 if (strcmp(f1,str1) || strcmp(f2,str2)) { /* Refuse. */
2639 errpkt((CHAR *)"Access denied");
2640 RESUME; /* Remember, this is not a goto! */
2644 if (state == generic) { /* It's OK to go ahead. */
2645 if (zcopy(f1,f2)) { /* Try */
2646 errpkt((CHAR *)"Can't copy file"); /* give error message */
2651 RESUME; /* wait for next server command */
2656 #else /* no ZCOPY */
2657 errpkt((CHAR *)"REMOTE COPY not available"); /* give error message */
2658 RESUME; /* wait for next server command */
2661 #endif /* NOSERVER */
2668 if (ckxsyslog >= SYSLG_PR && ckxlogging)
2669 cksyslog(SYSLG_PR, 1, "server", "REMOTE RENAME", (char *)srvcmd);
2670 #endif /* CKSYSLOG */
2672 if (!ENABLED(en_ren)) {
2673 errpkt((CHAR *)"REMOTE RENAME disabled");
2676 } else { /* RENAME is enabled */
2677 char *str1, *str2, f1[256], f2[256];
2679 len1 = xunchar(srvcmd[1]); /* Separate the parameters */
2680 len2 = xunchar(srvcmd[2+len1]);
2681 strncpy(f1,(char *)(srvcmd+2),len1);
2683 strncpy(f2,(char *)(srvcmd+3+len1),len2);
2685 len2 = xunchar(srvcmd[2+len1]);
2686 strncpy(f1,(char *)(srvcmd+2),len1);
2688 strncpy(f2,(char *)(srvcmd+3+len1),len2);
2691 if (ikdbopen) slotstate(what,"REMOTE RENAME", f1, f2);
2693 if (!ENABLED(en_cwd)) { /* If CWD is disabled */
2694 zstrip(f1,&str1); /* and they included a pathname, */
2696 if ( strcmp(f1,str1) || strcmp(f2,str2) ) { /* refuse. */
2697 errpkt((CHAR *)"Access denied");
2698 RESUME; /* Remember, this is not a goto! */
2702 if (state == generic) { /* It's OK to go ahead. */
2703 if (zrename(f1,f2)) { /* Try */
2704 errpkt((CHAR *)"Can't rename file"); /* Give error msg */
2709 RESUME; /* Wait for next server command */
2714 #else /* no ZRENAME */
2715 /* Give error message */
2716 errpkt((CHAR *)"REMOTE RENAME not available");
2717 RESUME; /* Wait for next server command */
2719 #endif /* ZRENAME */
2720 #endif /* NOSERVER */
2726 char f1[LOGINLEN+1], f2[LOGINLEN+1], f3[LOGINLEN+1];
2730 debug(F101,"REMOTE LOGIN x_login","",x_login);
2731 debug(F101,"REMOTE LOGIN x_logged","",x_logged);
2733 f1[0] = NUL; f2[0] = NUL; f3[0] = NUL;
2735 if (srvcmd[1]) /* First length field */
2736 len = xunchar(srvcmd[1]); /* Separate the parameters */
2738 if (x_login) { /* Login required */
2739 if (x_logged) { /* And already logged in */
2740 if (len > 0) { /* Logging in again */
2741 errpkt((CHAR *)"Already logged in.");
2742 } else { /* Logging out */
2743 debug(F101,"REMOTE LOGOUT","",x_logged);
2745 if (ckxsyslog >= SYSLG_PR && ckxlogging)
2746 cksyslog(SYSLG_PR, 1, "server", "REMOTE LOGOUT", NULL);
2747 #endif /* CKSYSLOG */
2749 if (ikdbopen) slotstate(what,"REMOTE LOGOUT", "", "");
2751 tlog(F110,"Logged out",x_user,0);
2752 ack1((CHAR *)"Logged out");
2761 #endif /* CK_LOGIN */
2763 } else { /* Not logged in yet */
2764 debug(F101,"REMOTE LOGIN len","",len);
2765 if (len > 0) { /* Have username */
2767 if (ckxsyslog >= SYSLG_PR && ckxlogging)
2768 cksyslog(SYSLG_PR, 1, "server", "REMOTE LOGIN", NULL);
2769 #endif /* CKSYSLOG */
2770 if (len > LOGINLEN) {
2771 errpkt((CHAR *)"Username too long");
2773 p = srvcmd + 2; /* Point to it */
2774 for (i = 0; i < len; i++) /* Copy it */
2776 f1[len] = NUL; /* Terminate it */
2777 p += len; /* Point to next length field */
2778 if (*p) { /* If we have one */
2779 len = xunchar(*p++); /* decode it */
2780 if (len > 0 && len <= LOGINLEN) {
2781 for (i = 0; i < len; i++) /* Same deal for password */
2784 p += len; /* And account */
2786 len = xunchar(*p++);
2787 if (len > 0 && len <= LOGINLEN) {
2788 for (i = 0; i < len; i++)
2789 f3[i] = p[i]; /* Set but never used */
2790 f3[len] = NUL; /* (because account not used) */
2795 debug(F101,"REMOTE LOGIN 1","",x_logged);
2798 if (inserver) { /* Log in to system for real */
2799 x_logged = ckxlogin((CHAR *)f1,(CHAR *)f2,NULL,0);
2800 debug(F101,"REMOTE LOGIN 2","",x_logged);
2801 if (x_logged) { /* Count attempts */
2809 #endif /* CK_LOGIN */
2811 if (x_user && x_passwd) { /* User and password must match */
2812 if (!strcmp(x_user,f1)) /* SET SERVER LOGIN */
2813 if (!strcmp(x_passwd,f2))
2815 debug(F101,"REMOTE LOGIN 3","",x_logged);
2816 } else if (x_user) { /* Only username given, no password */
2817 if (!strcmp(x_user,f1)) /* so only username must match */
2819 debug(F101,"REMOTE LOGIN 4","",x_logged);
2823 x_logged = ckxlogin((CHAR *)f1,(CHAR *)f2,NULL,0);
2824 debug(F101,"REMOTE LOGIN 5","",x_logged);
2826 #endif /* CK_LOGIN */
2827 if (x_logged) { /* Logged in? */
2828 tlog(F110,"Logged in", x_user, 0);
2830 ack1((CHAR *)"Logged in as guest - restrictions apply");
2832 ack1((CHAR *)"Logged in");
2835 tlog(F110,"Login failed", f1, 0);
2836 errpkt((CHAR *)"Access denied.");
2839 if (inserver && logtries > 2)
2841 #endif /* CK_LOGIN */
2844 } else { /* LOGOUT */
2845 errpkt((CHAR *)"Logout ignored");
2848 } else { /* Login not required */
2850 errpkt((CHAR *)"Login ignored.");
2852 errpkt((CHAR *)"Logout ignored.");
2854 #endif /* NOSERVER */
2861 /* K95 does this its own way */
2865 printf("\r\nIKSD IDLE TIMEOUT: %d sec\r\n", srvidl);
2866 doexit(GOOD_EXIT,xitsta);
2870 printf("\r\nSERVER IDLE TIMEOUT: %d sec\r\n", srvidl);
2871 xitsta |= (what & W_KERMIT);
2875 else if (fatalio) { /* Connection lost */
2877 if (ckxsyslog >= SYSLG_PR && ckxlogging)
2878 cksyslog(SYSLG_PR, 1, "server", "Connection lost", NULL);
2879 #endif /* CKSYSLOG */
2881 if (ikdbopen) slotstate(what,"SERVER DISCONNECT",(char *)srvcmd, "");
2885 } else if (interrupted) { /* Interrupted by hand */
2886 if (!ENABLED(en_fin)) {
2887 errpkt((CHAR *)"QUIT disabled");
2891 if (what == W_SEND || what == W_RECV || what == W_REMO) {
2894 if (ckxsyslog >= SYSLG_PR && ckxlogging)
2895 cksyslog(SYSLG_PR, 1, "server", "Interrupted", NULL);
2896 #endif /* CKSYSLOG */
2897 } else if (what == W_NOTHING && filcnt == 0) {
2899 } /* Otherwise leave success alone */
2900 xitsta |= (what & W_KERMIT);
2903 } else { /* Shouldn't happen */
2904 debug(F100,"SERVER (top) GOT UNEXPECTED 'q'","",0);
2907 #endif /* NOSERVER */
2915 if (/* state == serve && */ x_login && !x_logged) {
2916 errpkt((CHAR *)"Login required");
2919 #endif /* NOSERVER */
2920 if (state == serve && !ENABLED(en_sen)) { /* Not in server mode */
2921 errpkt((CHAR *)"SEND disabled"); /* when SEND is disabled. */
2924 } else { /* OK to go ahead. */
2926 if (dldir && !f_tmpdir) { /* If they have a download directory */
2927 debug(F110,"receive download dir",dldir,0);
2928 if (s = zgtdir()) { /* Get current directory */
2929 debug(F110,"receive current dir",s,0);
2930 if (zchdir(dldir)) { /* Change to download directory */
2931 debug(F100,"receive zchdir ok","",0);
2932 ckstrncpy(savdir,s,TMPDIRLEN);
2933 f_tmpdir = 1; /* Remember that we did this */
2935 debug(F100,"receive zchdir failed","",0);
2938 #endif /* CK_TMPDIR */
2939 nakstate = 1; /* Can send NAKs from here. */
2940 rinit(rdatap); /* Set parameters */
2945 bctu = bctr; /* switch to agreed-upon block check */
2946 bctl = (bctu == 4) ? 2 : bctu; /* Set block-check length */
2948 what = W_RECV; /* Remember we're receiving */
2950 resetc(); /* Reset counters */
2951 rtimer(); /* Reset timer */
2954 #endif /* GFTIMER */
2956 BEGIN rfile; /* Go into receive-file state */
2962 /* END OF ROUTINES MOVED OUT OF STATE MACHINE */
2965 /* P R O T O -- Protocol entry function */
2967 static int is_tn = 0; /* It's a Telnet connection */
2970 int f_ctlp = 0; /* Control-character prefix table */
2973 #endif /* COMMENT */
2974 #endif /* CK_SPEED */
2977 This is simply a wrapper for the real protocol function just below,
2978 that saves any items that might be changed automatically by protocol
2979 negotiations and then restores them upon exit from protocol mode.
2983 extern int b_save, f_save, c_save, ss_save, slostart, reliable, urclear;
2985 extern int fcharset, fcs_save, tcharset, tcs_save;
2986 #endif /* NOCSETS */
2989 extern int pipesend;
2990 #endif /* PIPESEND */
2993 extern int cursorena[], cursor_save, term_io;
2995 extern int display_demo;
2998 #endif /* NOLOCAL */
3000 int _u_bin=0, _me_bin = 0;
3002 int /* _u_start=0, */ _me_start = 0;
3003 #endif /* IKS_OPTION */
3008 #endif /* PATTERNS */
3013 #endif /* PATTERNS */
3014 scan_save = filepeek;
3019 if (isguest) { /* If user is anonymous */
3020 en_pri = 0; /* disable printing */
3021 en_mai = 0; /* and disable email */
3022 en_del = 0; /* and file deletion */
3024 #endif /* CK_LOGIN */
3028 cursor_save = cursorena[vmode];
3029 cursorena[vmode] = 0;
3030 term_io_save = term_io;
3033 #endif /* NOLOCAL */
3034 b_save = binary; /* SET FILE TYPE */
3035 f_save = fncnv; /* SET FILE NAMES */
3042 fcs_save = fcharset;
3043 tcs_save = tcharset;
3044 #endif /* NOCSETS */
3047 /* Don't do this because then user can never find out what happened. */
3049 for (i = 0; i < 256; i++)
3050 s_ctlp[i] = ctlp[i];
3052 #endif /* CK_SPEED */
3053 #endif /* COMMENT */
3054 if (reliable == SET_ON)
3056 is_tn = (!local && sstelnet)
3058 || (local && network && ttnproto == NP_TELNET)
3063 if (tn_b_xfer && !(sstelnet || inserver)) {
3064 /* Save the current state of Telnet Binary */
3065 _u_bin = TELOPT_U(TELOPT_BINARY);
3066 _me_bin = TELOPT_ME(TELOPT_BINARY);
3068 /* If either direction is not Binary attempt to negotiate it */
3069 if (!_u_bin && TELOPT_U_MODE(TELOPT_BINARY) != TN_NG_RF) {
3070 tn_sopt(DO,TELOPT_BINARY);
3071 TELOPT_UNANSWERED_DO(TELOPT_BINARY) = 1;
3073 if (!_me_bin && TELOPT_ME_MODE(TELOPT_BINARY) != TN_NG_RF) {
3074 tn_sopt(WILL,TELOPT_BINARY);
3075 TELOPT_UNANSWERED_WILL(TELOPT_BINARY) = 1;
3077 if (!(_me_bin && _u_bin))
3078 tn_wait("proto set binary mode");
3082 if (protocol != PROTO_K) { /* Non-Kermit protocol selected */
3083 if (TELOPT_U(TELOPT_KERMIT) &&
3084 TELOPT_SB(TELOPT_KERMIT).kermit.u_start) {
3085 iks_wait(KERMIT_REQ_STOP,0); /* Stop the other Server */
3088 if (TELOPT_ME(TELOPT_KERMIT) &&
3089 TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
3090 tn_siks(KERMIT_STOP); /* I'm not servering */
3091 TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
3096 if (sstate == 'x' || sstate == 'v') { /* Responding to a request */
3097 if (!inserver && TELOPT_U(TELOPT_KERMIT) &&
3098 TELOPT_SB(TELOPT_KERMIT).kermit.u_start) {
3099 iks_wait(KERMIT_REQ_STOP,0); /* Stop the other Server */
3102 if (TELOPT_ME(TELOPT_KERMIT) &&
3103 !TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
3104 tn_siks(KERMIT_START); /* Send Kermit-Server Start */
3105 TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 1;
3107 } else { /* Initiating a request */
3108 if (TELOPT_ME(TELOPT_KERMIT) &&
3109 TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
3110 tn_siks(KERMIT_STOP); /* I'm not servering */
3111 TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
3114 if (TELOPT_U(TELOPT_KERMIT) &&
3115 !TELOPT_SB(TELOPT_KERMIT).kermit.u_start) {
3116 /* Send Req-Server-Start */
3117 if (!iks_wait(KERMIT_REQ_START,0)) {
3118 if (sstate != 's') {
3119 success = 0; /* Other Kermit refused to serve */
3121 printf("A Kermit Server is not available\r\n");
3122 debug(F110,"proto()",
3123 "A Kermit Server is not available",0);
3124 tlog(F110,"IKS client/server failure",
3125 "A Kermit Server is not available",0);
3131 #endif /* IKS_OPTION */
3132 #ifdef CK_ENCRYPTION
3133 if (tn_no_encrypt_xfer && !(sstelnet || inserver)) {
3136 #endif /* CK_ENCRYPTION */
3140 if (!xfrint) connoi();
3141 xxproto(); /* Call the real protocol function */
3145 #endif /* IKS_OPTION */
3146 xferstat = success; /* Remember transfer status */
3150 #ifdef CK_ENCRYPTION
3151 if (tn_no_encrypt_xfer && !(sstelnet || inserver)) {
3154 #endif /* CK_ENCRYPTION */
3156 if (TELOPT_ME(TELOPT_KERMIT) &&
3157 TELOPT_SB(TELOPT_KERMIT).kermit.me_start && !_me_start) {
3158 tn_siks(KERMIT_STOP); /* Server is stopped */
3159 TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
3161 #endif /* IKS_OPTION */
3162 if (is_tn && tn_b_xfer && !(sstelnet || inserver)) {
3163 /* if we negotiated Binary mode try to reset it */
3165 /* Check to see if the state changed during the transfer */
3166 if (TELOPT_U(TELOPT_BINARY)) {
3167 tn_sopt(DONT,TELOPT_BINARY);
3168 TELOPT_UNANSWERED_DONT(TELOPT_BINARY) = 1;
3170 _u_bin = 1; /* So we don't call tn_wait() */
3173 /* Check to see if the state changed during the transfer */
3174 if (TELOPT_ME(TELOPT_BINARY)) {
3175 tn_sopt(WONT,TELOPT_BINARY);
3176 TELOPT_UNANSWERED_WONT(TELOPT_BINARY) = 1;
3178 _me_bin = 1; /* So we don't call tn_wait() */
3180 if (!(_me_bin && _u_bin))
3181 tn_wait("proto reset binary mode");
3187 #endif /* PATTERNS */
3188 filepeek = scan_save;
3193 #endif /* STREAMING */
3196 for (i = 0; i < 256; i++)
3197 ctlp[i] = s_ctlp[i];
3199 #endif /* CK_SPEED */
3200 #endif /* COMMENT */
3203 xitsta |= (what & W_KERMIT);
3204 tlog(F110," failed:",(char *)epktmsg,0);
3206 debug(F111,"proto xferstat",epktmsg,xferstat);
3208 if (s_timint > -1) { /* Because of REMOTE SET */
3214 if (c_save > -1) { /* Because of REMOTE SET */
3221 pipesend = 0; /* Next time might not be pipesend */
3222 #endif /* PIPESEND */
3225 cursorena[vmode] = cursor_save;
3226 term_io = term_io_save;
3229 #endif /* NOLOCAL */
3238 _PROTOTYP( int pxyz, (int) );
3239 #endif /* XYZ_INTERNAL */
3242 char xss[2]; /* String representation of sstate */
3247 debug(F101,"xxproto entry justone","",justone);
3250 retrieve = 0; /* Reset these ... */
3254 if (local && ttchk() < 0) { /* Giving BYE or FIN */
3255 if (bye_active) { /* but there is no connection */
3260 /* Ditto for any REMOTE command */
3261 if (sstate == 'g' && cmarg ) {
3262 if (*cmarg == 'L' || *cmarg == 'F' || *cmarg == 'X')
3265 printf("?No connection\r\n");
3270 /* Set up the communication line for file transfer. */
3271 /* NOTE: All of the xxscreen() calls prior to the wart() invocation */
3272 /* could just as easily be printf's or, for that matter, hints. */
3274 if (local && (speed < 0L) && (network == 0)) {
3275 xxscreen(SCR_EM,0,0L,"Sorry, you must 'set speed' first");
3279 if (ttopen(ttname,&x,mdmtyp,cdtimo) < 0) {
3280 debug(F111,"failed: proto ttopen local",ttname,local);
3281 xxscreen(SCR_EM,0,0L,"Can't open line");
3284 if (x > -1) local = x;
3285 debug(F111,"proto ttopen local",ttname,local);
3287 lx = (local && !network) ? speed : -1;
3291 ctlp[(unsigned)255] = ctlp[CR] = 1;
3292 if (parity == 'e' || parity == 'm') ctlp[127] = 1;
3293 if (flow == FLO_XONX) { /* Also watch out for Xon/Xoff */
3294 ctlp[17] = ctlp[19] = 1;
3295 ctlp[17+128] = ctlp[19+128] = 1;
3298 #endif /* CK_SPEED */
3299 #endif /* NETCONN */
3300 if (ttpkt(lx,flow,parity) < 0) { /* Put line in packet mode, */
3301 xxscreen(SCR_EM,0,0L,"Can't condition line");
3304 if (local && !network && carrier != CAR_OFF) {
3305 int x; /* Serial connection */
3306 x = ttgmdm(); /* with carrier checking */
3308 if (!(x & BM_DCD)) {
3309 debug(F101,"proto ttgmdm","",0);
3310 xxscreen(SCR_EM,0,0L,"Carrier required but not detected");
3315 /* Send remote side's "receive" or "server" startup string, if any */
3316 if (local && ckindex((char *)xss,"srgcjhk",0,0,1)) {
3320 /* Don't send auto-blah string if we know other side is serving */
3321 !TELOPT_U(TELOPT_KERMIT) ||
3322 !TELOPT_SB(TELOPT_KERMIT).kermit.u_start
3325 #endif /* IKS_OPTION */
3327 if (sstate == 's') { /* Sending file(s) */
3328 s = binary ? ptab[protocol].h_b_init : ptab[protocol].h_t_init;
3329 } else if (protocol == PROTO_K) { /* Command for server */
3330 s = ptab[protocol].h_x_init;
3334 #ifndef UNPREFIXZERO
3335 if (protocol == PROTO_K) /* Because of C-strings... */
3337 #endif /* UNPREFIXZERO */
3338 #endif /* CK_SPEED */
3339 if (s) if (*s) { /* If we have a command to send... */
3341 int tmpbufsiz = 356;
3342 int stuff = -1, stuff2 = -1, len = 0;
3344 if (sstate == 's') { /* Sending file(s) */
3346 if (protocol == PROTO_X) {
3348 s2 = cmarg2[0] ? cmarg2 : cmarg;
3349 if ((int)strlen(s) + (int)strlen(s2) + 4 < 356)
3350 sprintf(tmpbuf, s, s2);
3355 ckmakmsg(tmpbuf, 356, s, NULL, NULL, NULL);
3359 } else { /* Command for server */
3360 ckstrncpy(tmpbuf,s,356);
3362 ckstrncat(tmpbuf, "\015",sizeof(tmpbuf));
3363 if (tnlm) /* TERMINAL NEWLINE ON */
3364 stuff = LF; /* Stuff LF */
3366 /* TELNET NEWLINE MODE */
3368 switch (TELOPT_ME(TELOPT_BINARY) ? tn_b_nlm : tn_nlm) {
3384 if (network && ttnproto == NP_RLOGIN) {
3385 switch (tn_b_nlm) { /* Always BINARY */
3398 #endif /* RLOGCODE */
3399 #endif /* TCPSOCKET */
3400 #endif /* NETCONN */
3402 len = strlen(tmpbuf);
3403 if (stuff >= 0 && len < tmpbufsiz - 1) {
3404 tmpbuf[len++] = stuff;
3405 if (stuff2 >= 0 && len < tmpbufsiz - 1)
3406 tmpbuf[len++] = stuff2;
3409 ttol((CHAR *)tmpbuf,len);
3410 if (protocol == PROTO_K) /* Give remote Kermit time to start */
3416 if (protocol != PROTO_K) { /* Non-Kermit protocol selected */
3418 int tmpbufsiz = 356;
3422 if (sstate == 'v') { /* If receiving and... */
3423 if (dldir && !f_tmpdir) { /* if they have a download directory */
3424 if (s = zgtdir()) { /* Get current directory */
3425 if (zchdir(dldir)) { /* Change to download directory */
3426 ckstrncpy(savdir,s,TMPDIRLEN);
3427 f_tmpdir = 1; /* Remember that we did this */
3432 #endif /* CK_TMPDIR */
3434 #ifdef XYZ_INTERNAL /* Internal */
3435 success = !pxyz(sstate);
3437 #ifdef CK_REDIR /* External */
3439 case 's': /* 'Tis better to SEND... */
3440 s = binary ? ptab[protocol].p_b_scmd : ptab[protocol].p_t_scmd;
3442 case 'v': /* ... than RECEIVE */
3443 s = binary ? ptab[protocol].p_b_rcmd : ptab[protocol].p_t_rcmd;
3448 if (sstate == 's') { /* Sending */
3449 extern int xfermode;
3450 int k = 0, x = 0, b = binary;
3452 If just one file we can scan it to set the xfer mode.
3453 Otherwise it's up to the external protocol program.
3455 if (patterns && xfermode == XMODE_A && !iswild(fspec)) {
3456 extern int nscanfile;
3457 k = scanfile(fspec,&x,nscanfile);
3459 b = (k == FT_BIN) ? XYFT_B : XYFT_T;
3461 ptab[protocol].p_b_scmd :
3462 ptab[protocol].p_t_scmd;
3465 if ((int)strlen(s) + (int)strlen(fspec) < tmpbufsiz) {
3466 sprintf(tmpbuf,s,fspec); /* safe (prechecked) */
3467 tlog(F110,"Sending",fspec,0L);
3469 } else { /* Receiving */
3470 if ((int)strlen(s) + (int)strlen(cmarg2) < tmpbufsiz) {
3471 sprintf(tmpbuf,s,cmarg2); /* safe (prechecked) */
3472 tlog(F110,"Receiving",cmarg2,0L);
3475 tlog(F110," via external protocol:",tmpbuf,0);
3476 debug(F110,"ckcpro ttruncmd",tmpbuf,0);
3477 success = ttruncmd(tmpbuf);
3478 tlog(F110," status:",success ? "OK" : "FAILED", 0);
3480 printf("?Sorry, no external protocol defined for %s\r\n",
3481 ptab[protocol].p_name
3486 "Sorry, only Kermit protocol is supported in this version of Kermit\n"
3488 #endif /* CK_REDIR */
3489 #endif /* XYZ_INTERNAL */
3499 connoi(); /* No console interrupts if remote */
3503 if (sstate == 'x') { /* If entering server mode, */
3504 extern int howcalled;
3505 server = 1; /* set flag, */
3506 debug(F101,"server backgrd","",backgrd);
3507 debug(F101,"server quiet","",quiet);
3508 debug(F100,"SHOULD NOT SEE THIS IF IN BACKGROUND!","",0);
3509 if (howcalled == I_AM_SSHSUB) { /* and issue appropriate message. */
3510 ttol((CHAR *)"KERMIT READY TO SERVE...\015\012",26);
3511 } else if (!local) {
3512 if (!quiet && !backgrd
3514 && !TELOPT_ME(TELOPT_KERMIT) /* User was told by negotiation */
3515 #endif /* IKS_OPTION */
3518 conoll("KERMIT READY TO SERVE...");
3521 conol("Entering server mode on ");
3523 conoll("Type Ctrl-C to quit.");
3524 if (srvdis) intmsg(-1L);
3527 if (network && tcpsrfd > 0)
3528 ttol((CHAR *)"KERMIT READY TO SERVE...\015\012",26);
3529 #endif /* NOLISTEN */
3530 #endif /* TCPSOCKET */
3535 if (!quiet && !backgrd) /* So message doesn't overwrite prompt */
3537 if (local) conres(); /* So Ctrl-C will work */
3540 If in remote mode, not shushed, not in background, and at top command level,
3541 issue a helpful message telling what to do...
3543 if (!local && !quiet && !backgrd) {
3544 if (sstate == 'v') {
3545 conoll("Return to your local Kermit and give a SEND command.");
3547 conoll("KERMIT READY TO RECEIVE...");
3548 } else if (sstate == 's') {
3549 conoll("Return to your local Kermit and give a RECEIVE command.");
3551 conoll("KERMIT READY TO SEND...");
3552 } else if ( sstate == 'g' || sstate == 'r' || sstate == 'h' ||
3553 sstate == 'j' || sstate == 'c' ) {
3554 conoll("Return to your local Kermit and give a SERVER command.");
3556 conoll((sstate == 'r' || sstate == 'j' || sstate == 'h') ?
3557 "KERMIT READY TO GET..." :
3558 "KERMIT READY TO SEND SERVER COMMAND...");
3562 if (!local) sleep(1);
3563 #endif /* COMMENT */
3565 The 'wart()' function is generated by the wart program. It gets a
3566 character from the input() routine and then based on that character and
3567 the current state, selects the appropriate action, according to the state
3568 table above, which is transformed by the wart program into a big case
3569 statement. The function is active for one transaction.
3571 rtimer(); /* Reset elapsed-time timer */
3574 #endif /* GFTIMER */
3575 resetc(); /* & other per-transaction counters. */
3577 debug(F101,"proto calling wart, justone","",justone);
3579 wart(); /* Enter the state table switcher. */
3581 Note: the following is necessary in case we have just done a remote-mode
3582 file transfer, in which case the controlling terminal modes have been
3583 changed by ttpkt(). In particular, special characters like Ctrl-C and
3584 Ctrl-\ might have been turned off (see ttpkt). So this call to ttres() is
3585 essential. IMPORTANT: restore interrupt handlers first, otherwise any
3586 terminal interrupts that occur before this is done in the normal place
3587 later will cause a crash.
3590 ttres(); /* Reset the communication device */
3593 setint(); /* Arm interrupt handlers FIRST */
3595 ttres(); /* Then restore terminal. */
3598 xxscreen(SCR_TC,0,0L,""); /* Transaction complete */
3601 clsif(); /* Failsafe in case we missed */
3602 clsof(1); /* a case in the state machine. */
3605 if (server) { /* Back from packet protocol. */
3606 if (!quiet && !backgrd
3610 ) { /* Give appropriate message */
3612 conoll("C-Kermit server done");
3614 server = 0; /* Not a server any more */
3618 /* S G E T I N I T -- Handle incoming GET-Class packets */
3623 0: GET packet processed OK - ready to Send.
3624 1: Extended GET processed OK - wait for another.
3627 sgetinit(reget,xget) int reget, xget; { /* Server end of GET command */
3628 char * fs = NULL; /* Pointer to filespec */
3631 extern int usepipes, pipesend;
3632 #endif /* PIPESEND */
3635 if (!ENABLED(en_get)) { /* Only if not disabled! */
3636 errpkt((CHAR *)"GET disabled");
3642 nolinks = recursive;
3646 /* If they are alike this was already done in whoarewe() */
3647 debug(F101,"sgetinit whatru","",whatru);
3648 if (whatru & WMI_FLAG) { /* Did we get WHATAMI info? */
3649 debug(F101,"sgetinit binary (1)","",binary);
3651 if (binary != XYFT_I && binary != XYFT_L)
3654 if (binary != XYFT_L)
3657 binary = (whatru & WMI_FMODE) ? /* Yes, set file type */
3658 XYFT_B : XYFT_T; /* automatically */
3659 debug(F101,"sgetinit binary (2)","",binary);
3661 fncnv = (whatru & WMI_FNAME) ? 1 : 0; /* And name conversion */
3663 #endif /* WHATAMI */
3665 fs = (char *)srvcmd;
3666 srvptr = srvcmd; /* Point to server command buffer */
3667 decode(rdatap,putsrv,0); /* Decode the GET command into it */
3668 /* Accept multiple filespecs */
3669 cmarg2 = ""; /* Don't use cmarg2 */
3670 cmarg = ""; /* Don't use cmarg */
3672 done = 1; /* Only 1 packet needed... */
3673 if (xget) { /* Special decoding for Extended GET */
3674 char L, next, c; /* PLV items */
3675 int len, val; /* More PLV items */
3676 char * p = (char *)srvcmd; /* String to decode */
3678 done = 0; /* Maybe more packets needed */
3679 fs = NULL; /* We don't know the filespec yet */
3680 c = *p++; /* Get first parameter */
3682 while (c) { /* For all parameters... */
3683 debug(F000,"sgetinit c","",c);
3684 L = *p++; /* Get length */
3685 if (L >= SP) /* Decode length */
3687 else if (c == '@') { /* Allow missing EOP length field */
3690 len = (xunchar(*p++) * 95);
3691 len += xunchar(*p++);
3693 debug(F101,"sgetinit len","",len);
3694 next = *(p+len); /* Get next parameter */
3695 *(p+len) = NUL; /* Zero it out to terminal value */
3696 debug(F110,"sgetinit p",p,0);
3697 switch (c) { /* Do the parameter */
3698 case 'O': /* GET Options */
3699 val = atoi(p); /* Convert to int */
3700 debug(F101,"sgetinit O val","",val);
3701 if (val & GOPT_DEL) moving = 1;
3702 if (val & GOPT_RES) reget = 1;
3703 if (val & GOPT_REC) {
3706 if (fnspath == PATH_OFF)
3710 case 'M': /* Transfer Mode */
3712 debug(F101,"sgetinit M val","",val);
3715 patterns = 0; /* Takes precedence over patterns */
3716 filepeek = 0; /* and FILE SCAN */
3717 if (val == GMOD_TXT) binary = XYFT_T; /* Text */
3718 if (val == GMOD_BIN) binary = XYFT_B; /* Binary */
3719 if (val == GMOD_LBL) binary = XYFT_L; /* Labeled */
3721 case 'F': /* Filename */
3723 debug(F110,"sgetinit filename",fs,0);
3725 case '@': /* End Of Parameters */
3727 debug(F100,"sgetinit EOP","",0);
3730 errpkt((CHAR *)"Unknown GET Parameter");
3731 debug(F100,"sgetinit unknown parameter","",0);
3738 if (!fs) fs = ""; /* A filename is required */
3741 n = 0; /* Check for quoted name */
3742 if ((n = strlen(fs)) > 1) {
3743 /* Note: this does not allow for multiple quoted names */
3744 if ((fs[0] == '{' && fs[n-1] == '}') ||
3745 (fs[0] == '"' && fs[n-1] == '"')) {
3748 debug(F111,"sgetinit unquoted filename",fs,n);
3750 n = 0; /* This means no quoting */
3754 debug(F111,"sgetinit",fs,usepipes);
3755 if (usepipes && ENABLED(en_hos) && *fs == '!') {
3756 cmarg = fs + 1; /* Point past the bang */
3760 debug(F111,"sgetinit pipesend",cmarg,pipesend);
3762 if (!pipesend) { /* If it's not a pipe */
3763 #endif /* PIPESEND */
3764 if (n == 0) { /* If the name was not quoted */
3766 nfils = fnparse(fs); /* Allow it to be a list of names */
3767 debug(F111,"sgetinit A",fs,nfils);
3769 /* This doesn't work if a GET-PATH is set. */
3770 if (nfils == 1 && !iswild(fs)) { /* Single file */
3772 if ((x = zchki(fs)) < 0) { /* Check if it's sendable */
3774 case -1: m = "File not found"; break;
3775 case -2: m = "Not a regular file"; break;
3776 case -3: m = "Read access denied"; break;
3782 #endif /* COMMENT */
3783 } else { /* If it was quoted */
3784 #endif /* NOMSEND */
3787 if (matchdot) nzxopts |= ZX_MATCHDOT;
3788 #endif /* UNIXOROSK */
3789 if (recursive) nzxopts |= ZX_RECURSE;
3790 /* Treat as a single filespec */
3791 nfils = 0 - nzxpand(fs,nzxopts);
3792 debug(F111,"sgetinit B",fs,nfils);
3797 #endif /* PIPESEND */
3799 if (!done) { /* Need more O packets... */
3800 debug(F100,"sgetinit O-Packet TBC","",0); /* To Be Continued */
3803 debug(F100,"sgetinit O-Packet done - havefs","",havefs);
3804 if (!havefs) { /* Done - make sure we have filename */
3805 errpkt((CHAR *)"GET without filename");
3809 winlo = 0; /* Back to packet 0 again. */
3810 debug(F101,"sgetinit winlo","",winlo);
3811 nakstate = 0; /* Now I'm the sender! */
3812 if (reget) sendmode = SM_RESEND;
3813 if (sinit() > 0) { /* Send Send-Init */
3816 #endif /* STREAMING */
3817 timint = chktimo(rtimo,timef); /* Switch to per-packet timer */
3818 return(0); /* If successful, switch state */
3819 } else return(-1); /* Else back to server command wait */