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 8.0.160, 12 Aug 2007";
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, 2007,
22 Trustees of Columbia University in the City of New York.
23 All rights reserved. See the C-Kermit COPYING.TXT file or the
24 copyright text in the ckcmai.c module for disclaimer and permissions.
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;
172 extern int quiet, tsecs, parity, backgrd, nakstate, atcapu, wslotn, winlo;
173 extern int wslots, success, xitsta, rprintf, discard, cdtimo, keep, fdispla;
174 extern int timef, stdinf, rscapu, sendmode, epktflg, epktrcvd, epktsent;
175 extern int binary, fncnv;
176 extern long speed, ffc, crc16, calibrate, dest;
178 extern char *TYPCMD, *DIRCMD, *DIRCM2;
181 extern char *SPACMD, *SPACM2, *WHOCMD;
184 extern struct zattr iattr;
191 extern CKFLOAT fptsecs;
195 extern CHAR *epktmsg;
198 extern int f_tmpdir; /* Directory changed temporarily */
199 extern char savdir[]; /* For saving current directory */
201 #endif /* CK_TMPDIR */
203 extern int query; /* Query-active flag */
206 char querybuf[QBUFL+1] = { NUL, NUL }; /* QUERY response buffer */
207 char *qbufp = querybuf; /* Pointer to it */
208 int qbufn = 0; /* Length of data in it */
217 If the following flag is nonzero when the protocol module is entered,
218 then server mode persists for exactly one transaction, rather than
219 looping until BYE or FINISH is received.
223 static int r_save = -1;
224 static int p_save = -1;
226 /* Function to let remote-mode user know where their file(s) went */
228 int whereflg = 1; /* Unset with SET XFER REPORT */
232 extern int quiet, filrej;
235 debug(F101,"wheremsg n","",n);
237 debug(F110,"wheremsg prfspec",prfspec,0);
238 debug(F110,"wheremsg rfspec",rfspec,0);
239 debug(F110,"wheremsg psfspec",psfspec,0);
240 debug(F110,"wheremsg sfspec",sfspec,0);
242 debug(F110,"wheremsg prrfspec",prrfspec,0);
243 debug(F110,"wheremsg rrfspec",rrfspec,0);
244 debug(F110,"wheremsg psrfspec",psrfspec,0);
245 debug(F110,"wheremsg srfspec",srfspec,0);
247 if (!quiet && !local) {
252 printf(" SENT: [%s]",sfspec);
254 printf(" To: [%s]",srfspec);
255 printf(" (%s)\r\n", success ? "OK" : "FAILED");
261 printf(" RCVD: [%s]",rrfspec);
263 printf(" To: [%s]",rfspec);
264 printf(" (%s)\r\n", success ? "OK" : "FAILED");
271 printf(" SENT: (%d files)",n);
273 printf(" Last: [%s]",srfspec);
274 printf(" (%s)\r\n", success ? "OK" : "FAILED");
280 printf(" RCVD: (%d files)",n);
282 printf(" Last: [%s]",rfspec);
283 printf(" (%s)\r\n", success ? "OK" : "FAILED");
288 printf(" SENT: (0 files) \r\n");
289 else if (myjob == 'r' || myjob == 'v')
290 printf(" RCVD: (0 files) \r\n");
298 debug(F111,"RESUME","server=1",justone);
300 debug(F111,"RESUME","server=0",justone);
303 /* Flags for the ENABLE and DISABLE commands */
305 en_cpy, en_cwd, en_del, en_dir, en_fin, en_get, en_bye, en_mai, en_pri,
306 en_hos, en_ren, en_sen, en_spa, en_set, en_typ, en_who, en_ret, en_xit,
309 extern int en_asg, en_que;
311 extern int what, lastxfer;
313 /* Global variables declared here */
315 int whatru = 0; /* What are you. */
316 int whatru2 = 0; /* What are you, cont'd. */
318 /* Local variables */
320 static char vstate = 0; /* Saved State */
321 static char vcmd = 0; /* Saved Command */
322 static int reget = 0; /* Flag for executing REGET */
323 static int retrieve = 0; /* Flag for executing RETRIEVE */
324 static int opkt = 0; /* Send Extended GET packet */
326 static int x; /* General-purpose integer */
327 static char *s; /* General-purpose string pointer */
329 /* Macros - Note, BEGIN is predefined by Wart (and Lex) as "state = ", */
330 /* BEGIN is NOT a GOTO! */
331 #define TINIT if (tinit(1) < 0) return(-9)
332 #define SERVE { TINIT; resetc(); nakstate=1; what=W_NOTHING; cmarg2=""; \
333 sendmode=SM_SEND; havefs=0; recursive=r_save; fnspath=p_save; BEGIN serve; }
334 #define RESUME { rdebug(); if (!server) { wheremsg(); return(0); } else \
335 if (justone) { justone=0; wheremsg(); return(0); } else { SERVE; } }
338 #define QUIT x=quiet; quiet=1; clsif(); clsof(1); tsecs=gtimer(); \
339 fptsecs=gftimer(); quiet=x; return(success)
341 #define QUIT x=quiet; quiet=1; clsif(); clsof(1); tsecs=gtimer(); quiet=x; \
346 By late 1999, the big switch() statement generated from the following state
347 table began choking even gcc, so here we extract the code from the larger
348 states into static routines to reduce the size of the cases and the
349 switch() overall. The routines follow the state table; the prototypes are
350 here. Each of these routines simply contains the text from the
351 corresponding case, but with return(-1) added in appropriate places; see
352 instructions after the state table switcher.
354 static int rc; /* Return code for these routines */
355 static int rcv_s_pkt(); /* Received an S packet */
356 static int rcv_firstdata(); /* Received first Data packet */
357 static int rcv_shortreply(); /* Short reply to a REMOTE command */
358 static int srv_query(); /* Server answers an query */
359 static int srv_copy(); /* Server executes REMOTE COPY */
360 static int srv_rename(); /* Server executes REMOTE RENAME */
361 static int srv_login(); /* Server executes REMOTE LOGIN */
362 static int srv_timeout(); /* Server times out */
365 #define BEGIN state =
376 debug(F000,"PROTO input",ckitoa(state),c+32);
377 if (c < 0 || c > 95) c = 0;
378 if ((actno = tbl[c + state*96]) != -1)
381 { TINIT; /* Send file(s) */
382 if (sinit() > 0) BEGIN ssinit;
386 { TINIT; nakstate = 1; BEGIN get; }
389 { /* Client sends a GET command */
398 #endif /* PKTZEROHACK */
406 { /* Client sends a RETRIEVE command */
420 { /* Client sends a REGET command */
434 { /* Client sends Extended GET Packet */
437 reget = oopts & GOPT_RES;
438 retrieve = oopts & GOPT_DEL;
448 { /* Client sends a Host command */
459 { TINIT; /* Client sends a Kermit command */
469 { /* Client sends a REMOTE command */
480 { /* Enter server mode */
483 if (!ENABLED(en_del)) { /* If DELETE is disabled */
484 if (fncact == XYFX_B || /* undo any file collision action */
485 fncact == XYFX_U || /* that could result in deletion or */
486 fncact == XYFX_A || /* modification of existing files. */
490 g_fncact = fncact; /* Save current setting */
492 fncact = XYFX_R; /* Change to RENAME */
493 debug(F101,"server DELETE disabled so fncact RENAME","",fncact);
496 SERVE; /* tinit() clears justone... */
499 if (ikdbopen) slotstate(what, "SERVER", "", "");
506 if (!data) TINIT; /* "ABEND" -- Tell other side. */
508 if (epktflg) { /* If because of E-PACKET command */
509 b1 = bctl; b2 = bctu; /* Save block check type */
510 bctl = bctu = 1; /* set it to 1 */
513 errpkt((CHAR *)"User cancelled"); /* Send the packet */
515 if (epktflg) { /* Restore the block check */
517 bctl = b1; bctu = b2;
521 return(0); /* Return from protocol. */
525 { /* Receive Send-Init packet. */
527 cancel = 0; /* Reset cancellation counter */
528 debug(F101,"rcv_s_pkt","",rc);
529 if (rc > -1) return(rc); /* (see below) */
533 { /* Get ack for I-packet */
536 ckstrncpy(ipktack,(char *)rdatap,PKTZEROLEN); /* Save a copy of the ACK */
537 ipktlen = strlen(ipktack);
538 #endif /* PKTZEROHACK */
539 spar(rdatap); /* Set parameters */
541 winlo = 0; /* Set window-low back to zero */
542 debug(F101,"<ipkt>Y winlo","",winlo);
543 urserver = 1; /* So I know I'm talking to a server */
544 if (vcmd) { /* If sending a generic command */
545 if (tinit(0) < 0) return(-9); /* Initialize many things */
546 x = scmd(vcmd,(CHAR *)cmarg); /* Do that */
547 if (x >= 0) x = 0; /* (because of O-Packet) */
548 debug(F101,"proto G packet scmd","",x);
549 vcmd = 0; /* and then un-remember it. */
550 } else if (vstate == get) {
551 debug(F101,"REGET sstate","",sstate);
552 x = srinit(reget, retrieve, opkt); /* GET or REGET, etc */
554 if (x < 0) { /* If command was too long */
556 srimsg = "Error sending string";
557 errpkt((CHAR *)srimsg); /* cancel both sides. */
560 } else if (x > 0) { /* Need to send more O-Packets */
563 rtimer(); /* Reset the elapsed seconds timer. */
567 winlo = 0; /* Window back to 0, again. */
568 debug(F101,"<ipkt>Y vstate","",vstate);
569 nakstate = 1; /* Can send NAKs from here. */
570 BEGIN vstate; /* Switch to desired state */
575 { /* Got ACK to O-Packet */
576 debug(F100,"CPCPRO <ssopkt>Y","",0);
578 debug(F101,"CPCPRO <ssopkt>Y x","",x);
579 if (x < 0) { /* If error */
580 errpkt((CHAR *)srimsg); /* cancel both sides. */
583 } else if (x == 0) { /* This was the last O-Packet */
584 rtimer(); /* Reset the elapsed seconds timer. */
588 winlo = 0; /* Window back to 0, again. */
589 debug(F101,"<ssopkt>Y winlo","",winlo);
590 nakstate = 1; /* Can send NAKs from here. */
591 BEGIN vstate; /* Switch to desired state */
593 debug(F101,"CPCPRO <ssopkt>Y not changing state","",x);
597 { /* Ignore Error reply to I packet */
599 winlo = 0; /* Set window-low back to zero */
600 debug(F101,"<ipkt>E winlo","",winlo);
601 if (vcmd) { /* In case other Kermit doesn't */
602 if (tinit(0) < 0) return(-9);
603 x = scmd(vcmd,(CHAR *)cmarg); /* understand I-packets. */
604 if (x >= 0) x = 0; /* (because of O-Packet) */
605 vcmd = 0; /* Otherwise act as above... */
606 } else if (vstate == get) x = srinit(reget, retrieve, opkt);
607 if (x < 0) { /* If command was too long */
608 errpkt((CHAR *)srimsg); /* cancel both sides. */
611 } else if (x > 0) { /* Need to send more O-Packets */
614 freerpkt(winlo); /* Discard the Error packet. */
615 debug(F101,"<ipkt>E winlo","",winlo);
616 winlo = 0; /* Back to packet 0 again. */
617 nakstate = 1; /* Can send NAKs from here. */
623 { /* Resend of previous I-pkt ACK, same seq number */
624 freerpkt(0); /* Free the ACK's receive buffer */
625 resend(0); /* Send the GET packet again. */
631 spar(rdatap); /* Set parameters from it */
632 ack1(rpar()); /* Respond with our own parameters */
634 pktinit(); /* Reinitialize packet numbers */
637 /* This can't be right - it undoes the stuff we just negotiated */
639 tinit(1); /* Reinitialize EVERYTHING */
640 justone = x; /* But this... */
642 tinit(0); /* Initialize most things */
645 #endif /* NOSERVER */
646 cancel = 0; /* Reset cancellation counter */
652 if (x_login && !x_logged) {
653 errpkt((CHAR *)"Login required");
655 } else if (sgetinit(0,0) < 0) {
659 if (ckxsyslog >= SYSLG_PR && ckxlogging)
660 cksyslog(SYSLG_PR, 1, "server", "GET", (char *)srvcmd);
661 #endif /* CKSYSLOG */
664 #endif /* NOSERVER */
668 { /* GET /DELETE (RETRIEVE) */
670 if (x_login && !x_logged) {
671 errpkt((CHAR *)"Login required");
673 } else if (!ENABLED(en_del)) {
674 errpkt((CHAR *)"Deleting files is disabled");
676 } else if (sgetinit(0,0) < 0) {
681 if (ckxsyslog >= SYSLG_PR && ckxlogging)
682 cksyslog(SYSLG_PR, 1, "server", "GET /DELETE", (char *)srvcmd);
683 #endif /* CKSYSLOG */
686 #endif /* NOSERVER */
690 { /* GET /RECURSIVE */
692 recursive = 1; /* Set these before sgetinit() */
693 if (fnspath == PATH_OFF)
694 fnspath = PATH_REL; /* Don't worry, they will be */
695 if (x_login && !x_logged) { /* reset next time through. */
696 errpkt((CHAR *)"Login required");
698 } else if (sgetinit(0,0) < 0) {
702 if (ckxsyslog >= SYSLG_PR && ckxlogging)
703 cksyslog(SYSLG_PR, 1, "server", "GET /RECURSIVE", (char *)srvcmd);
704 #endif /* CKSYSLOG */
707 #endif /* NOSERVER */
711 { /* GET /RECURSIVE /DELETE */
713 recursive = 1; /* Set these before sgetinit() */
714 if (fnspath == PATH_OFF)
715 fnspath = PATH_REL; /* Don't worry, they will be */
716 moving = 1; /* reset next time through. */
717 if (x_login && !x_logged) {
718 errpkt((CHAR *)"Login required");
720 } else if (!ENABLED(en_del)) {
721 errpkt((CHAR *)"Deleting files is disabled");
723 } else if (sgetinit(0,0) < 0) {
727 if (ckxsyslog >= SYSLG_PR && ckxlogging)
728 cksyslog(SYSLG_PR,1,"server",
729 "GET /RECURSIVE /DELETE",(char *)srvcmd);
730 #endif /* CKSYSLOG */
733 #endif /* NOSERVER */
737 { /* GET /RECOVER (REGET) */
739 if (x_login && !x_logged) {
740 errpkt((CHAR *)"Login required");
742 } else if (sgetinit(1,0) < 0) {
746 if (ckxsyslog >= SYSLG_PR && ckxlogging)
747 cksyslog(SYSLG_PR, 1, "server", "GET /RECOVER", (char *)srvcmd);
748 #endif /* CKSYSLOG */
751 #endif /* NOSERVER */
757 if (x_login && !x_logged) { /* (any combination of options) */
758 errpkt((CHAR *)"Login required");
760 } else if ((x = sgetinit(0,1)) < 0) {
761 debug(F101,"CKCPRO <serve>O sgetinit fail","",x);
764 debug(F101,"CKCPRO <serve>O sgetinit done","",x);
766 if (ckxsyslog >= SYSLG_PR && ckxlogging)
767 cksyslog(SYSLG_PR, 1, "server", "EXTENDED GET", (char *)srvcmd);
768 #endif /* CKSYSLOG */
770 } else { /* Otherwise stay in this state */
771 debug(F101,"CKCPRO <serve>O sgetinit TBC","",x);
775 #endif /* NOSERVER */
781 if (x_login && !x_logged) { /* (any combination of options) */
782 errpkt((CHAR *)"Login required");
784 } else if ((x = sgetinit(0,1)) < 0) {
785 debug(F101,"CKCPRO <ropkt>O sgetinit fail","",x);
788 debug(F101,"CKCPRO <ropkt>O sgetinit done","",x);
790 if (ckxsyslog >= SYSLG_PR && ckxlogging)
791 cksyslog(SYSLG_PR, 1, "server", "EXTENDED GET", (char *)srvcmd);
792 #endif /* CKSYSLOG */
794 } else { /* Otherwise stay in this state */
795 debug(F101,"CKCPRO <ropkt>O sgetinit TBC","",x);
798 #endif /* NOSERVER */
802 { /* Generic server command */
804 srvptr = srvcmd; /* Point to command buffer */
805 decode(rdatap,putsrv,0); /* Decode packet data into it */
806 putsrv(NUL); /* Insert a couple nulls */
807 putsrv(NUL); /* for termination */
809 sstate = srvcmd[0]; /* Set requested start state */
810 if (x_login && !x_logged && /* Login required? */
811 /* Login, Logout, and Help are allowed when not logged in */
812 sstate != 'I' && sstate != 'L' && sstate != 'H') {
813 errpkt((CHAR *)"Login required");
816 nakstate = 0; /* Now I'm the sender. */
817 what = W_REMO; /* Doing a REMOTE command. */
820 #endif /* STREAMING */
822 timint = chktimo(rtimo,timef); /* Switch to per-packet timer */
823 binary = XYFT_T; /* Switch to text mode */
824 BEGIN generic; /* Switch to generic command state */
827 errpkt((CHAR *)"Badly formed server command"); /* report error */
828 RESUME; /* & go back to server command wait */
830 #endif /* NOSERVER */
834 { /* Receive Host command */
836 if (x_login && !x_logged) {
837 errpkt((CHAR *)"Login required");
839 } else if (!ENABLED(en_hos)) {
840 errpkt((CHAR *)"REMOTE HOST disabled");
843 errpkt((CHAR *)"HOST commands not available");
846 srvptr = srvcmd; /* Point to command buffer */
847 decode(rdatap,putsrv,0); /* Decode command packet into it */
848 putsrv(NUL); /* Null-terminate */
849 nakstate = 0; /* Now sending, not receiving */
850 binary = XYFT_T; /* Switch to text mode */
851 if (syscmd((char *)srvcmd,"")) { /* Try to execute the command */
852 what = W_REMO; /* Doing a REMOTE command. */
855 #endif /* STREAMING */
857 timint = chktimo(rtimo,timef); /* Switch to per-packet timer */
859 if (ckxsyslog >= SYSLG_PR && ckxlogging)
860 cksyslog(SYSLG_PR, 1, "server", "REMOTE HOST", (char *)srvcmd);
861 #endif /* CKSYSLOG */
862 BEGIN ssinit; /* If OK, send back its output */
863 } else { /* Otherwise */
864 errpkt((CHAR *)"Can't do system command"); /* report error */
865 RESUME; /* & go back to server command wait */
868 #endif /* NOSERVER */
872 { /* Interrupted or connection lost */
874 debug(F101,"srv_timeout","",rc);
875 if (rc > -1) return(rc); /* (see below) */
879 { /* Server got a NAK in command-wait */
881 errpkt((CHAR *)"Did you say RECEIVE instead of GET?");
883 #endif /* NOSERVER */
887 { /* Any other command in this state */
889 if (c != ('E' - SP) && c != ('Y' - SP)) /* except E and Y packets. */
890 errpkt((CHAR *)"Unimplemented server function");
891 /* If we answer an E with an E, we get an infinite loop. */
892 /* A Y (ACK) can show up here if we sent back a short-form reply to */
893 /* a G packet and it was echoed. ACKs can be safely ignored here. */
894 RESUME; /* Go back to server command wait. */
895 #endif /* NOSERVER */
901 debug(F101,"<generic>I srv_login","",rc);
902 if (rc > -1) return(rc); /* (see below) */
906 { /* Got REMOTE CD command */
909 if (ckxsyslog >= SYSLG_PR && ckxlogging)
910 cksyslog(SYSLG_PR, 1, "server", "REMOTE CD", (char *)srvcmd);
911 #endif /* CKSYSLOG */
912 if (!ENABLED(en_cwd)) {
913 errpkt((CHAR *)"REMOTE CD disabled");
917 x = cwd((char *)(srvcmd+1)); /* Try to change directory */
919 if (ikdbopen) slotstate(what,"REMOTE CD", (char *)(srvcmd+2), "");
921 if (!x) { /* Failed */
922 errpkt((CHAR *)"Can't change directory");
923 RESUME; /* Back to server command wait */
924 } else if (x == 2) { /* User wants message */
925 if (!ENABLED(en_typ)) { /* Messages (REMOTE TYPE) disabled? */
926 errpkt((CHAR *)"REMOTE TYPE disabled");
928 } else { /* TYPE is enabled */
930 for (i = 0; i < 8; i++) {
931 if (zchki(cdmsgfile[i]) > -1) {
935 binary = XYFT_T; /* Use text mode for this. */
936 if (i < 8 && sndtype(cdmsgfile[i])) { /* Have readme file? */
937 BEGIN ssinit; /* OK */
938 } else { /* not OK */
941 success = (*p) ? 1 : 0;
942 ack1((CHAR *)p); /* ACK with new directory name */
944 RESUME; /* wait for next server command */
947 } else { /* User doesn't want message */
950 success = (*p) ? 1 : 0;
953 RESUME; /* Wait for next server command */
956 #endif /* NOSERVER */
960 { /* Got REMOTE PWD command */
963 if (ckxsyslog >= SYSLG_PR && ckxlogging)
964 cksyslog(SYSLG_PR, 1, "server", "REMOTE PWD", NULL);
965 #endif /* CKSYSLOG */
966 if (!ENABLED(en_cwd)) {
967 errpkt((CHAR *)"REMOTE CD disabled");
970 if (encstr((CHAR *)zgtdir()) > -1) { /* Encode current directory */
971 ack1(data); /* If it fits, send it back in ACK */
973 } else { /* Failed */
974 ack(); /* Send empty ACK */
975 success = 0; /* and indicate failure locally */
977 RESUME; /* Back to server command wait */
979 #endif /* NOSERVER */
983 { /* REMOTE DIRECTORY command */
987 if (ckxsyslog >= SYSLG_PR && ckxlogging)
988 cksyslog(SYSLG_PR, 1, "server", "REMOTE DIRECTORY", (char *)srvcmd);
989 #endif /* CKSYSLOG */
990 if (!ENABLED(en_dir)) { /* If DIR is disabled, */
991 errpkt((CHAR *)"REMOTE DIRECTORY disabled"); /* refuse. */
993 } else { /* DIR is enabled. */
995 if (ikdbopen) slotstate(what,"REMOTE DIR", (char *)(srvcmd+2), "");
997 if (!ENABLED(en_cwd)) { /* But CWD is disabled */
998 zstrip((char *)(srvcmd+2),&n2); /* and they included a pathname, */
999 if (strcmp((char *)(srvcmd+2),n2)) { /* so refuse. */
1000 errpkt((CHAR *)"Access denied");
1001 RESUME; /* Remember, this is not a goto! */
1004 if (state == generic) { /* It's OK to go ahead. */
1006 n2 = (*(srvcmd+2)) ? DIRCMD : DIRCM2;
1007 if (syscmd(n2,(char *)(srvcmd+2))) /* If it can be done */
1010 if ((x = snddir((char*)(srvcmd+2))) > 0)
1011 #endif /* COMMENT */
1013 BEGIN ssinit; /* send the results back; */
1014 } else { /* otherwise */
1016 errpkt((CHAR *)"No files match");
1018 errpkt((CHAR *)"Can't list directory");
1019 RESUME; /* return to server command wait */
1023 #endif /* NOSERVER */
1027 { /* REMOTE DELETE (Erase) */
1031 if (ckxsyslog >= SYSLG_PR && ckxlogging)
1032 cksyslog(SYSLG_PR, 1, "server", "REMOTE DELETE", (char *)srvcmd);
1033 #endif /* CKSYSLOG */
1034 if (!ENABLED(en_del)) {
1035 errpkt((CHAR *)"REMOTE DELETE disabled");
1037 } else { /* DELETE is enabled */
1039 if (ikdbopen) slotstate(what,"REMOTE DELETE", (char *)(srvcmd+2), "");
1041 if (!ENABLED(en_cwd)) { /* but CWD is disabled */
1042 zstrip((char *)(srvcmd+2),&n2); /* and they included a pathname, */
1043 if (strcmp((char *)(srvcmd+2),n2)) { /* so refuse. */
1044 errpkt((CHAR *)"Access denied");
1045 RESUME; /* Remember, this is not a goto! */
1047 } else if (isdir((char *)(srvcmd+2))) { /* A directory name? */
1048 errpkt((CHAR *)"It's a directory");
1051 if (state == generic) { /* It's OK to go ahead. */
1053 if ((x = snddel((char*)(srvcmd+2))) > 0) {
1054 BEGIN ssinit; /* If OK send results back */
1055 } else { /* otherwise */
1057 errpkt((CHAR *)"File not found"); /* report failure */
1059 errpkt((CHAR *)"DELETE failed");
1060 RESUME; /* & return to server command wait */
1064 #endif /* NOSERVER */
1071 if (ckxsyslog >= SYSLG_PR && ckxlogging)
1072 cksyslog(SYSLG_PR, 1, "server", "FINISH", NULL);
1073 #endif /* CKSYSLOG */
1075 if (ikdbopen) slotstate(what,"SERVER FINISH", "", "");
1077 if (!ENABLED(en_fin)) {
1078 errpkt((CHAR *)"FINISH disabled");
1081 ack(); /* Acknowledge */
1082 xxscreen(SCR_TC,0,0L,""); /* Display */
1084 return(0); /* Done */
1086 #endif /* NOSERVER */
1093 if (ckxsyslog >= SYSLG_PR && ckxlogging)
1094 cksyslog(SYSLG_PR, 1, "server", "REMOTE EXIT", NULL);
1095 #endif /* CKSYSLOG */
1097 if (ikdbopen) slotstate(what,"REMOTE EXIT", "", "");
1099 if (!ENABLED(en_xit)) {
1100 errpkt((CHAR *)"EXIT disabled");
1103 ack(); /* Acknowledge */
1104 xxscreen(SCR_TC,0,0L,""); /* Display */
1105 doexit(GOOD_EXIT,xitsta);
1107 #endif /* NOSERVER */
1111 { /* BYE (Logout) */
1114 if (ckxsyslog >= SYSLG_PR && ckxlogging)
1115 cksyslog(SYSLG_PR, 1, "server", "BYE", NULL);
1116 #endif /* CKSYSLOG */
1118 if (ikdbopen) slotstate(what,"SERVER BYE", "", "");
1120 if (!ENABLED(en_bye)) {
1121 errpkt((CHAR *)"BYE disabled");
1124 ack(); /* Acknowledge */
1126 msleep(750); /* Give the ACK time to get out */
1128 ttres(); /* Reset the terminal */
1129 xxscreen(SCR_TC,0,0L,""); /* Display */
1130 doclean(1); /* Clean up files, etc */
1132 debug(F100,"C-Kermit BYE - Loggin out...","",0);
1140 #endif /* CK_LOGIN */
1144 if (network && tcpsrfd > 0 && !inserver)
1145 doexit(GOOD_EXIT,xitsta);
1147 #endif /* NOLISTEN */
1148 #endif /* TCPSOCKET */
1149 return(zkself()); /* Try to log self out */
1151 #endif /* NOSERVER */
1157 if (ckxsyslog >= SYSLG_PR && ckxlogging)
1158 cksyslog(SYSLG_PR, 1, "server", "REMOTE HELP", NULL);
1159 #endif /* CKSYSLOG */
1161 if (ikdbopen) slotstate(what,"REMOTE HELP", "", "");
1165 BEGIN ssinit; /* try to send it */
1166 } else { /* If not ok, */
1167 errpkt((CHAR *)"Can't send help"); /* send error message instead */
1168 RESUME; /* and return to server command wait */
1170 #endif /* NOSERVER */
1174 { /* REMOTE RENAME */
1176 debug(F101,"srv_rename","",rc);
1177 if (rc > -1) return(rc); /* (see below) */
1183 debug(F101,"srv_copy","",rc);
1184 if (rc > -1) return(rc); /* (see below) */
1190 if (ckxsyslog >= SYSLG_PR && ckxlogging)
1191 cksyslog(SYSLG_PR, 1, "server", "REMOTE SET", (char *)srvcmd);
1192 #endif /* CKSYSLOG */
1195 if (ikdbopen) slotstate(what,"REMOTE SET", (char *)(srvcmd+1), "");
1197 if (!ENABLED(en_set)) {
1198 errpkt((CHAR *)"REMOTE SET disabled");
1201 if (remset((char *)(srvcmd+1))) { /* Try to do what they ask */
1203 ack(); /* If OK, then acknowledge */
1204 } else /* Otherwise */
1205 errpkt((CHAR *)"Unknown REMOTE SET parameter"); /* give error msg */
1206 RESUME; /* Return to server command wait */
1208 #endif /* NOSERVER */
1216 if (ckxsyslog >= SYSLG_PR && ckxlogging)
1217 cksyslog(SYSLG_PR, 1, "server", "REMOTE TYPE", (char *)srvcmd);
1218 #endif /* CKSYSLOG */
1219 if (!ENABLED(en_typ)) {
1220 errpkt((CHAR *)"REMOTE TYPE disabled");
1224 if (ikdbopen) slotstate(what,"REMOTE TYPE", (char *)(srvcmd+2), "");
1226 if (!ENABLED(en_cwd)) { /* If CWD disabled */
1227 zstrip((char *)(srvcmd+2),&n2); /* and they included a pathname, */
1228 if (strcmp((char *)(srvcmd+2),n2)) { /* refuse. */
1229 errpkt((CHAR *)"Access denied");
1230 RESUME; /* Remember, this is not a goto! */
1233 if (state == generic) { /* It's OK to go ahead. */
1234 binary = XYFT_T; /* Use text mode for this. */
1235 if ( /* (RESUME didn't change state) */
1237 syscmd(TYPCMD,(char *)(srvcmd+2)) /* Old way */
1239 sndtype((char *)(srvcmd+2)) /* New way */
1240 #endif /* COMMENT */
1242 BEGIN ssinit; /* OK */
1244 errpkt((CHAR *)"Can't type file"); /* give error message */
1245 RESUME; /* wait for next server command */
1249 #endif /* NOSERVER */
1253 { /* REMOTE MKDIR */
1257 if (ckxsyslog >= SYSLG_PR && ckxlogging)
1258 cksyslog(SYSLG_PR, 1, "server", "REMOTE MKDIR", (char *)srvcmd);
1259 #endif /* CKSYSLOG */
1261 if (ikdbopen) slotstate(what,"REMOTE MKDIR", (char *)(srvcmd+2), "");
1263 if (!ENABLED(en_mkd)) {
1264 errpkt((CHAR *)"REMOTE MKDIR disabled");
1266 } else if (!ENABLED(en_cwd)) { /* If CWD disabled */
1267 errpkt((CHAR *)"Directory access restricted");
1268 RESUME; /* Remember, this is not a goto! */
1270 if (state == generic) { /* OK to go ahead. */
1272 x = ckmkdir(0,(char *)(srvcmd+2),&p,0,1); /* Make the directory */
1275 encstr((CHAR *)p); /* OK - encode the name */
1276 ack1(data); /* Send short-form response */
1279 } else { /* not OK */
1280 if (!*p) p = "Directory creation failure";
1281 errpkt((CHAR *)p); /* give error message */
1282 RESUME; /* Wait for next server command */
1286 errpkt((CHAR *)"REMOTE MKDIR not available");
1288 #endif /* CK_MKDIR */
1289 #endif /* NOSERVER */
1293 { /* REMOTE RMDIR */
1297 if (ckxsyslog >= SYSLG_PR && ckxlogging)
1298 cksyslog(SYSLG_PR, 1, "server", "REMOTE RMDIR", (char *)srvcmd);
1299 #endif /* CKSYSLOG */
1301 if (ikdbopen) slotstate(what,"REMOTE RMDIR", (char *)(srvcmd+2), "");
1303 if (!ENABLED(en_rmd)) {
1304 errpkt((CHAR *)"REMOTE RMDIR disabled");
1306 } else if (!ENABLED(en_cwd)) { /* If CWD disabled */
1307 errpkt((CHAR *)"Directory access restricted");
1308 RESUME; /* Remember, this is not a goto! */
1310 if (state == generic) { /* OK to go ahead. */
1312 x = ckmkdir(1,(char *)(srvcmd+2),&p,0,1);
1315 encstr((CHAR *)p); /* OK - encode the name */
1316 ack1(data); /* Send short-form response */
1319 } else { /* not OK */
1320 if (!*p) p = "Directory removal failure";
1321 errpkt((CHAR *)p); /* give error message */
1322 RESUME; /* Wait for next server command */
1326 errpkt((CHAR *)"REMOTE RMDIR not available");
1328 #endif /* CK_MKDIR */
1329 #endif /* NOSERVER */
1333 { /* REMOTE SPACE */
1336 if (ckxsyslog >= SYSLG_PR && ckxlogging)
1337 cksyslog(SYSLG_PR, 1, "server", "REMOTE SPACE", (char *)srvcmd);
1338 #endif /* CKSYSLOG */
1339 if (!ENABLED(en_spa)) {
1340 errpkt((CHAR *)"REMOTE SPACE disabled");
1343 x = srvcmd[1]; /* Get area to check */
1344 x = ((x == NUL) || (x == SP)
1346 || (x == '!') || (srvcmd[3] == ':')
1350 if (ikdbopen) slotstate(what,
1352 (x ? "" : (char *)srvcmd),
1356 if (!x && !ENABLED(en_cwd)) { /* CWD disabled */
1357 errpkt((CHAR *)"Access denied"); /* and non-default area given, */
1358 RESUME; /* refuse. */
1361 _PROTOTYP(int sndspace,(int));
1362 if (sndspace(x ? toupper(srvcmd[2]) : 0)) {
1363 BEGIN ssinit; /* send the report. */
1364 } else { /* If not ok, */
1365 errpkt((CHAR *)"Can't send space"); /* send error message */
1366 RESUME; /* and return to server command wait */
1372 x = (x ? syscmd(SPACMD,"") : syscmd(SPACM2,(char *)(srvcmd+2)));
1373 if (x) { /* If we got the info */
1374 BEGIN ssinit; /* send it */
1375 } else { /* otherwise */
1376 errpkt((CHAR *)"Can't check space"); /* send error message */
1377 RESUME; /* and await next server command */
1382 #endif /* NOSERVER */
1389 if (ckxsyslog >= SYSLG_PR && ckxlogging)
1390 cksyslog(SYSLG_PR, 1, "server", "REMOTE WHO", (char *)srvcmd);
1391 #endif /* CKSYSLOG */
1393 if (ikdbopen) slotstate(what,"REMOTE WHO", (char *)(srvcmd+2), "");
1395 if (!ENABLED(en_who)) {
1396 errpkt((CHAR *)"REMOTE WHO disabled");
1400 _PROTOTYP(int sndwho,(char *));
1401 if (sndwho((char *)(srvcmd+2))) {
1402 BEGIN ssinit; /* try to send it */
1403 } else { /* If not ok, */
1404 errpkt((CHAR *)"Can't do who command"); /* send error msg */
1405 RESUME; /* and return to server command wait */
1408 if (syscmd(WHOCMD,(char *)(srvcmd+2))) {
1411 errpkt((CHAR *)"Can't do who command");
1416 #endif /* NOSERVER */
1420 { /* Variable query or set */
1422 debug(F101,"srv_query","",rc);
1423 if (rc > -1) return(rc);
1427 { /* REMOTE MESSAGE command */
1429 debug(F110,"RMSG",(char *)srvcmd+2,0);
1430 xxscreen(SCR_MS,0,0L,(char *)(srvcmd+2));
1433 #endif /* NOSERVER */
1437 { /* Interrupted or connection lost */
1439 if (fatalio) { /* Connection lost */
1441 if (ckxsyslog >= SYSLG_PR && ckxlogging)
1442 cksyslog(SYSLG_PR, 1, "server", "Interrupted", NULL);
1443 #endif /* CKSYSLOG */
1445 xitsta |= (what & W_KERMIT);
1447 } else if (interrupted) {
1448 if (!ENABLED(en_fin)) { /* Ctrl-C typed */
1449 errpkt((CHAR *)"QUIT disabled");
1453 if (ckxsyslog >= SYSLG_PR && ckxlogging)
1454 cksyslog(SYSLG_PR, 1, "server", "Interrupted", NULL);
1455 #endif /* CKSYSLOG */
1457 xitsta |= (what & W_KERMIT);
1460 } else { /* Shouldn't happen */
1461 debug(F100,"SERVER (generic) GOT UNEXPECTED 'q'","",0);
1464 #endif /* NOSERVER */
1468 { /* Anything else in this state... */
1470 errpkt((CHAR *)"Unimplemented REMOTE command"); /* Complain */
1471 RESUME; /* and return to server command wait */
1472 #endif /* NOSERVER */
1476 { /* Sent BYE and connection broken */
1477 if (bye_active && ttchk() < 0) {
1480 ttclos(0); /* Close our end of the connection */
1482 return(success = 1);
1483 } else { /* Other generic command */
1484 return(success = 0); /* or connection not broken */
1489 { /* Short-Form reply */
1490 rc = rcv_shortreply();
1491 debug(F101,"<rgen>Y rcv_shortreply","",rc);
1492 if (rc > -1) return(rc);
1499 debug(F101,"<rfile>F winlo 1","",winlo);
1500 xflg = 0; /* Not screen data */
1502 cancel = 0; /* Reset cancellation counter */
1506 #endif /* CALIBRATE */
1507 if (!rcvfil(filnam)) { /* Figure out local filename */
1508 errpkt((CHAR *)rf_err); /* Trouble */
1510 } else { /* Real file, OK to receive */
1512 debug(F111,"<rfile>F winlo 2",fspec,winlo);
1513 if (filcnt == 1) /* rcvfil set this to 1 for 1st file */
1514 crc16 = 0L; /* Clear file CRC */
1515 fnp = fspec; /* This is the full path */
1516 if (server && !ENABLED(en_cwd) || /* if DISABLE CD */
1517 !fackpath /* or F-ACK-PATH OFF */
1519 zstrip(fspec,&fnp); /* don't send back full path */
1521 encstr((CHAR *)fnp);
1525 ack1(data); /* Send it back in ACK */
1526 initattr(&iattr); /* Clear file attribute structure */
1528 if (window(wslotn) < 0) { /* Allocate negotiated window slots */
1529 errpkt((CHAR *)"Can't open window");
1533 if (ikdbopen) slotstate(what,
1534 server ? "SERVER" : "",
1539 BEGIN rattr; /* Now expect Attribute packets */
1544 { /* X-packet instead of file header */
1545 xflg = 1; /* Screen data */
1547 cancel = 0; /* Reset cancellation counter */
1548 ack(); /* Acknowledge the X-packet */
1549 initattr(&iattr); /* Initialize attribute structure */
1551 if (window(wslotn) < 0) { /* allocate negotiated window slots */
1552 errpkt((CHAR *)"Can't open window");
1556 if (query) { /* If this is the response to */
1557 qbufp = querybuf; /* a query that we sent, initialize */
1558 qbufn = 0; /* the response buffer */
1562 what = W_REMO; /* we're doing a REMOTE command */
1564 if (ikdbopen) slotstate(what,
1565 server ? "SERVER" : "",
1570 BEGIN rattr; /* Expect Attribute packets */
1574 { /* Attribute packet */
1575 if (gattr(rdatap,&iattr) == 0) { /* Read into attribute structure */
1577 ack1((CHAR *)iattr.reply.val); /* Reply with data */
1579 ack(); /* If OK, acknowledge */
1580 #endif /* CK_RESEND */
1581 } else { /* Otherwise */
1584 r = getreason(iattr.reply.val);
1585 ack1((CHAR *)iattr.reply.val); /* refuse to accept the file */
1586 xxscreen(SCR_ST,ST_REFU,0L,r); /* reason */
1588 if (tralog && !tlogfmt)
1589 doxlog(what,filnam,fsize,binary,1,r);
1595 { /* First data packet */
1596 debug(F100,"<rattr> D firstdata","",0);
1597 rc = rcv_firstdata();
1598 debug(F101,"rcv_firstdata rc","",rc);
1599 if (rc > -1) return(rc); /* (see below) */
1603 { /* EOT, no more files */
1604 ack(); /* Acknowledge the B packet */
1605 reot(); /* Do EOT things */
1607 /* If we were cd'd temporarily to another device or directory ... */
1610 x = zchdir((char *) savdir); /* ... restore previous directory */
1611 f_tmpdir = 0; /* and remember we did it. */
1612 debug(F111,"ckcpro.w B tmpdir restoring",savdir,x);
1614 #endif /* CK_TMPDIR */
1615 RESUME; /* and quit */
1619 { /* Got Data packet */
1620 debug(F101,"<rdpkt>D cxseen","",cxseen);
1621 debug(F101,"<rdpkt>D czseen","",czseen);
1622 if (cxseen || czseen || discard) { /* If file or group interruption */
1624 msg = czseen ? (CHAR *)"Z" : (CHAR *)"X";
1626 if (streaming) { /* Need to cancel */
1627 debug(F111,"<rdpkt>D streaming cancel",msg,cancel);
1628 if (cancel++ == 0) { /* Only do this once */
1629 ack1(msg); /* Put "X" or "Z" in ACK */
1630 } else if (czseen) {
1631 errpkt((CHAR *)"User canceled");
1637 #endif /* STREAMING */
1639 } else { /* No interruption */
1647 rc = (binary && !parity) ?
1648 bdecode(rdatap,putfil):
1649 decode(rdatap, qf ? puttrm : putfil, 1);
1651 rc = decode(rdatap, qf ? puttrm : putfil, 1);
1652 #endif /* CKTUNING */
1654 discard = (keep == 0 || (keep == SET_AUTO && binary != XYFT_T));
1655 errpkt((CHAR *)"Error writing data"); /* If failure, */
1657 } else /* Data written OK, send ACK */
1662 #endif /* STREAMING */
1668 { /* EOF immediately after A-Packet. */
1669 rf_err = "Can't create file";
1671 if (discard) { /* Discarding a real file... */
1673 } else if (xflg) { /* If screen data */
1674 if (remfile) { /* redirected to file */
1675 if (rempipe) /* or pipe */
1676 x = openc(ZOFILE,remdest); /* Pipe: start command */
1678 x = opena(remdest,&iattr); /* File: open with attributes */
1679 } else { /* otherwise */
1680 x = opent(&iattr); /* "open" the screen */
1683 } else if (calibrate) { /* If calibration run */
1684 x = ckopenx(&iattr); /* do this */
1685 #endif /* CALIBRATE */
1686 } else { /* otherwise */
1687 x = opena(filnam,&iattr); /* open the file, with attributes */
1688 if (x == -17) { /* REGET skipped because same size */
1693 if (!x || reof(filnam, &iattr) < 0) { /* Close output file */
1694 errpkt((CHAR *) rf_err); /* If problem, send error msg */
1695 RESUME; /* and quit */
1696 } else { /* otherwise */
1698 xxscreen(SCR_ST,ST_SKIP,SKP_RES,"");
1699 ack(); /* acknowledge the EOF packet */
1700 BEGIN rfile; /* and await another file */
1705 { /* Ctrl-C or connection loss. */
1707 window(1); /* Set window size back to 1... */
1709 x = clsof(1); /* Close file */
1710 return(success = 0); /* Failed */
1714 { /* End Of File (EOF) Packet */
1715 /* wslots = 1; */ /* (don't set) Window size back to 1 */
1716 #ifndef COHERENT /* Coherent compiler blows up on this switch() statement. */
1717 x = reof(filnam, &iattr); /* Handle the EOF packet */
1718 switch (x) { /* reof() sets the success flag */
1719 case -5: /* Handle problems */
1720 errpkt((CHAR *)"RENAME failed"); /* Fatal */
1724 errpkt((CHAR *)"MOVE failed"); /* Fatal */
1727 case -3: /* If problem, send error msg */
1728 errpkt((CHAR *)"Can't print file"); /* Fatal */
1732 errpkt((CHAR *)"Can't mail file"); /* Fatal */
1735 case 2: /* Not fatal */
1737 xxscreen(SCR_EM,0,0L,"Receiver can't delete temp file");
1741 if (x < 0) { /* Fatal */
1742 errpkt((CHAR *)"Can't close file");
1744 } else { /* Success */
1746 if (query) /* Query reponses generally */
1747 conoll(""); /* don't have line terminators */
1749 if (czseen) { /* Batch canceled? */
1750 if (cancel++ == 0) { /* If we haven't tried this yet */
1751 ack1((CHAR *)"Z"); /* Try it once */
1752 } else { /* Otherwise */
1753 errpkt((CHAR *)"User canceled"); /* quite with Error */
1757 ack(); /* Acknowledge the EOF packet */
1758 BEGIN rfile; /* and await another file */
1762 if (reof(filnam, &iattr) < 0) { /* Close the file */
1763 errpkt((CHAR *)"Error at end of file");
1765 } else { /* reof() sets success flag */
1769 #endif /* COHERENT */
1773 { /* ACK for Send-Init */
1774 spar(rdatap); /* set parameters from it */
1776 bctu = bctr; /* switch to agreed-upon block check */
1777 bctl = (bctu == 4) ? 2 : bctu; /* Set block-check length */
1779 if ((sendmode == SM_RESEND) && (!atcapu || !rscapu)) { /* RESEND */
1780 errpkt((CHAR *) "RESEND capabilities not negotiated");
1783 #endif /* CK_RESEND */
1784 what = W_SEND; /* Remember we're sending */
1786 x = sfile(xflg); /* Send X or F header packet */
1787 cancel = 0; /* Reset cancellation counter */
1788 if (x) { /* If the packet was sent OK */
1789 if (!xflg && filcnt == 1) /* and it's a real file */
1790 crc16 = 0L; /* Clear the file CRC */
1791 resetc(); /* reset per-transaction counters */
1792 rtimer(); /* reset timers */
1795 #endif /* GFTIMER */
1796 streamon(); /* turn on streaming */
1798 if (ikdbopen) slotstate(what,
1799 (server ? "SERVER" : ""),
1804 BEGIN ssfile; /* and switch to receive-file state */
1805 } else { /* otherwise send error msg & quit */
1806 s = xflg ? "Can't execute command" : (char *)epktmsg;
1807 if (!*s) s = "Can't open file";
1813 #endif /* CK_RESEND */
1817 { /* R packet was retransmitted. */
1818 xsinit(); /* Resend packet 0 */
1822 { /* Same deal if G packet comes again */
1827 { /* Same deal if C packet comes again */
1832 { /* ACK for F or X packet */
1833 srvptr = srvcmd; /* Point to string buffer */
1834 decode(rdatap,putsrv,0); /* Decode data field, if any */
1835 putsrv(NUL); /* Terminate with null */
1836 ffc = 0L; /* Reset file byte counter */
1837 debug(F101,"<ssfile>Y cxseen","",cxseen);
1838 if (*srvcmd) { /* If remote name was recorded */
1839 if (sendmode != SM_RESEND) {
1840 if (fdispla == XYFD_C || fdispla == XYFD_S)
1841 xxscreen(SCR_AN,0,0L,(char *)srvcmd);
1842 tlog(F110," remote name:",(char *) srvcmd,0L);
1843 makestr(&psrfspec,(char *)srvcmd);
1846 if (cxseen||czseen) { /* Interrupted? */
1847 debug(F101,"<ssfile>Y canceling","",0);
1848 x = clsif(); /* Close input file */
1849 sxeof(1); /* Send EOF(D) */
1850 BEGIN sseof; /* and switch to EOF state. */
1851 } else if (atcapu) { /* If attributes are to be used */
1852 if (sattr(xflg | stdinf, 1) < 0) { /* send them */
1853 errpkt((CHAR *)"Can't send attributes"); /* if problem, say so */
1854 RESUME; /* and quit */
1855 } else BEGIN ssattr; /* if ok, switch to attribute state */
1856 } else { /* Attributes not negotiated */
1857 if (window(wslotn) < 0) { /* Open window */
1858 errpkt((CHAR *)"Can't open window");
1860 } else if ((x = sdata()) == -2) { /* Send first data packet data */
1861 window(1); /* Connection lost, reset window */
1862 x = clsif(); /* Close input file */
1863 return(success = 0); /* Return failure */
1864 } else if (x == -9) { /* User interrupted */
1865 errpkt((CHAR *)"User cancelled"); /* Send Error packet */
1866 window(1); /* Set window size back to 1... */
1867 timint = s_timint; /* Restore timeout */
1868 return(success = 0); /* Failed */
1869 } else if (x < 0) { /* EOF (empty file) or interrupted */
1870 window(1); /* put window size back to 1, */
1871 debug(F101,"<ssfile>Y cxseen","",cxseen);
1872 x = clsif(); /* If not ok, close input file, */
1873 if (x < 0) /* treating failure as interruption */
1874 cxseen = 1; /* Send EOF packet */
1875 seof(cxseen||czseen);
1876 BEGIN sseof; /* and switch to EOF state. */
1877 } else { /* First data sent OK */
1878 BEGIN ssdata; /* All ok, switch to send-data state */
1884 { /* Got ACK to A packet */
1885 ffc = 0L; /* Reset file byte counter */
1886 debug(F101,"<ssattr>Y cxseen","",cxseen);
1887 if (cxseen||czseen) { /* Interrupted? */
1888 debug(F101,"<sattr>Y canceling","",0);
1889 x = clsif(); /* Close input file */
1890 sxeof(1); /* Send EOF(D) */
1891 BEGIN sseof; /* and switch to EOF state. */
1892 } else if (rsattr(rdatap) < 0) { /* Was the file refused? */
1893 discard = 1; /* Set the discard flag */
1894 clsif(); /* Close the file */
1895 sxeof(1); /* send EOF with "discard" code */
1896 BEGIN sseof; /* switch to send-EOF state */
1897 } else if ((x = sattr(xflg | stdinf, 0)) < 0) { /* Send more? */
1898 errpkt((CHAR *)"Can't send attributes"); /* Trouble... */
1900 } else if (x == 0) { /* No more to send so now the data */
1901 if (window(wslotn) < 0) { /* Allocate negotiated window slots */
1902 errpkt((CHAR *)"Can't open window");
1905 if ((x = sdata()) == -2) { /* File accepted, send first data */
1906 window(1); /* Connection broken */
1907 x = clsif(); /* Close file */
1908 return(success = 0); /* Return failure */
1909 } else if (x == -9) { /* User interrupted */
1910 errpkt((CHAR *)"User cancelled"); /* Send Error packet */
1911 window(1); /* Set window size back to 1... */
1912 timint = s_timint; /* Restore timeout */
1913 return(success = 0); /* Failed */
1914 } else if (x < 0) { /* If data was not sent */
1915 window(1); /* put window size back to 1, */
1916 debug(F101,"<ssattr>Y cxseen","",cxseen);
1917 if (clsif() < 0) /* Close input file */
1918 cxseen = 1; /* Send EOF packet */
1919 seof(cxseen||czseen);
1920 BEGIN sseof; /* and switch to EOF state. */
1922 BEGIN ssdata; /* All ok, switch to send-data state */
1928 { /* Ctrl-C or connection loss. */
1929 window(1); /* Set window size back to 1... */
1930 cxseen = 1; /* To indicate interruption */
1931 x = clsif(); /* Close file */
1932 return(success = 0); /* Failed */
1936 { /* Got ACK to Data packet */
1937 canned(rdatap); /* Check if file transfer cancelled */
1938 debug(F111,"<ssdata>Y cxseen",rdatap,cxseen);
1939 debug(F111,"<ssdata>Y czseen",rdatap,czseen);
1940 if ((x = sdata()) == -2) { /* Try to send next data */
1941 window(1); /* Connection lost, reset window */
1942 x = clsif(); /* Close file */
1943 return(success = 0); /* Failed */
1944 } else if (x == -9) { /* User interrupted */
1945 errpkt((CHAR *)"User cancelled"); /* Send Error packet */
1946 window(1); /* Set window size back to 1... */
1947 timint = s_timint; /* Restore original timeout */
1948 return(success = 0); /* Failed */
1949 } else if (x < 0) { /* EOF - finished sending data */
1950 debug(F101,"<ssdata>Y cxseen","",cxseen);
1951 window(1); /* Set window size back to 1... */
1952 if (clsif() < 0) /* Close input file */
1953 cxseen = 1; /* Send EOF packet */
1954 debug(F101,"<ssdata>Y CALLING SEOF()","",cxseen);
1955 seof(cxseen||czseen);
1956 BEGIN sseof; /* and enter send-eof state */
1958 /* NOTE: If x == 0 it means we're draining: see sdata()! */
1962 { /* Got ACK to EOF */
1964 canned(rdatap); /* Check if file transfer cancelled */
1965 debug(F111,"<sseof>Y cxseen",rdatap,cxseen);
1966 debug(F111,"<sseof>Y czseen",rdatap,czseen);
1967 debug(F111,"<sseof>Y discard",rdatap,discard);
1970 success = (cxseen == 0 && czseen == 0); /* Transfer status... */
1971 debug(F101,"<sseof>Y success","",success);
1972 if (success && rejection > 0) /* If rejected, succeed if */
1973 if (rejection != '#' && /* reason was date */
1974 rejection != 1 && rejection != '?') /* or name; */
1975 success = 0; /* fail otherwise. */
1976 cxseen = 0; /* This goes back to zero. */
1977 if (success) { /* Only if transfer succeeded... */
1978 xxscreen(SCR_ST,ST_OK,0L,"");
1980 makestr(&sfspec,psfspec); /* Record filenames for WHERE */
1981 makestr(&srfspec,psrfspec);
1983 if (moving) { /* If MOVE'ing */
1984 x = zdelet(filnam); /* Try to delete the source file */
1988 tlog(F110," deleted",filnam,0);
1990 tlog(F110," delete failed:",ck_errstr(),0);
1994 } else if (snd_move) { /* Or move it */
1996 x = zrename(filnam,snd_move);
2000 tlog(F110," moved to ",snd_move,0);
2002 tlog(F110," move failed:",ck_errstr(),0);
2006 } else if (snd_rename) { /* Or rename it */
2007 char *s = snd_rename; /* Renaming string */
2009 int y; /* Pass it thru the evaluator */
2010 extern int cmd_quoting; /* for \v(filename) */
2011 if (cmd_quoting) { /* But only if cmd_quoting is on */
2014 zzstring(snd_rename,&s,&y);
2020 x = zrename(filnam,s);
2024 tlog(F110," renamed to",s,0);
2026 tlog(F110," rename failed:",ck_errstr(),0);
2032 #endif /* COMMENT */
2036 if (czseen) { /* Check group interruption flag */
2037 g = 0; /* No more files if interrupted */
2038 } else { /* Otherwise... */
2040 /* This code makes any open error fatal to a file-group transfer. */
2042 debug(F111,"<sseof>Y gnfile",filnam,g);
2043 if (g > 0) { /* Any more files to send? */
2044 if (sfile(xflg)) /* Yes, try to send next file header */
2045 BEGIN ssfile; /* if ok, enter send-file state */
2046 else { /* otherwise */
2047 s = xflg ? "Can't execute command" : (char *)epktmsg;
2048 if (!*s) s = "Can't open file";
2049 errpkt((CHAR *)s); /* send error message */
2050 RESUME; /* and quit */
2052 } else { /* No next file */
2053 tsecs = gtimer(); /* get statistics timers */
2055 fptsecs = gftimer();
2056 #endif /* GFTIMER */
2057 seot(); /* send EOT packet */
2058 BEGIN sseot; /* enter send-eot state */
2061 while (1) { /* Keep trying... */
2062 g = gnfile(); /* Get next file */
2063 debug(F111,"<sseof>Y gnfile",filnam,g);
2064 if (g == 0 && gnferror == 0) /* No more, stop trying */
2066 if (g > 0) { /* Have one */
2067 if (sfile(xflg)) { /* Try to open and send F packet */
2068 BEGIN ssfile; /* If OK, enter send-file state */
2069 break; /* and break out of loop. */
2071 } /* Otherwise keep trying to get one we can send... */
2075 debug(F101,"<sseof>Y no more files","",czseen);
2076 tsecs = gtimer(); /* Get statistics timers */
2078 fptsecs = gftimer();
2079 #endif /* GFTIMER */
2080 seot(); /* Send EOT packet */
2081 BEGIN sseot; /* Enter send-eot state */
2083 #endif /* COMMENT */
2087 { /* Got ACK to EOT */
2088 debug(F101,"sseot justone","",justone);
2089 RESUME; /* All done, just quit */
2093 { /* Got Error packet, in any state */
2095 window(1); /* Close window */
2096 timint = s_timint; /* Restore original timeout */
2097 if (*epktmsg) /* Message from Error packet */
2098 s = (char *)epktmsg;
2099 if (!*s) { /* If not there then maybe here */
2101 ckstrncpy((char *)epktmsg,(char *)rdatap,PKTMSGLEN);
2103 if (!*s) /* Hopefully we'll never see this. */
2104 s = "Unknown error";
2105 success = 0; /* For IF SUCCESS/FAIL. */
2106 debug(F101,"ckcpro.w justone at E pkt","",justone);
2108 success = 0; /* Transfer failed */
2109 xferstat = success; /* Remember transfer status */
2111 x = quiet; quiet = 1; /* Close files silently, */
2112 epktrcvd = 1; /* Prevent messages from clsof() */
2114 clsof(1); /* discarding any output file. */
2115 ermsg(s); /* Issue the message (calls screen). */
2116 quiet = x; /* Restore quiet state */
2118 tstats(); /* Get stats */
2120 If we are executing commands from a command file or macro, let the command
2121 file or macro decide whether to exit, based on SET { TAKE, MACRO } ERROR.
2128 fatal("Protocol error");
2129 xitsta |= (what & W_KERMIT); /* Save this for doexit(). */
2131 /* If we were cd'd temporarily to another device or directory ... */
2134 x = zchdir((char *) savdir); /* ... restore previous directory */
2135 f_tmpdir = 0; /* and remember we did it. */
2136 debug(F111,"ckcpro.w E tmpdir restored",savdir,x);
2138 #endif /* CK_TMPDIR */
2140 if (ikdbopen) slotstate(what,"ERROR", (char *)epktmsg, "");
2146 { success = 0; QUIT; }
2149 { /* Anything not accounted for above */
2150 errpkt((CHAR *)"Unexpected packet type"); /* Give error message */
2152 xitsta |= (what & W_KERMIT); /* Save this for doexit(). */
2153 RESUME; /* and quit */
2162 -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2163 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2164 74, 74, 74, 74, 74, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2165 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2166 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2167 74, 73, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
2168 -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2169 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2170 74, 74, 74, 74, 74, 15, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2171 74, 74, 74, 74, 74, 74, 74, 74, 74, 13, 74, 74, 74, 74, 74, 74,
2172 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2173 74, 73, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
2174 -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2175 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2176 74, 74, 57, 74, 74, 72, 53, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2177 74, 74, 74, 74, 74, 74, 74, 74, 54, 74, 74, 74, 74, 74, 74, 74,
2178 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2179 74, 73, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
2180 -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2181 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2182 74, 55, 74, 74, 56, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2183 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 59, 74, 74, 74, 74, 74,
2184 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2185 74, 73, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
2186 -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2187 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2188 74, 74, 74, 74, 58, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2189 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 61, 74, 74, 74, 74, 74,
2190 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2191 74, 60, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
2192 -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2193 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2194 74, 74, 74, 65, 74, 72, 74, 64, 74, 74, 74, 74, 74, 74, 74, 74,
2195 74, 74, 63, 74, 74, 74, 74, 74, 74, 62, 74, 74, 74, 74, 74, 74,
2196 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2197 74, 73, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
2198 -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2199 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2200 74, 74, 74, 74, 74, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2201 74, 74, 74, 74, 74, 74, 74, 74, 74, 66, 74, 74, 74, 74, 74, 74,
2202 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2203 74, 73, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
2204 -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2205 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2206 74, 74, 74, 74, 74, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2207 74, 74, 74, 74, 74, 74, 74, 74, 74, 67, 74, 74, 74, 74, 74, 74,
2208 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2209 74, 73, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
2210 -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2211 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2212 74, 74, 74, 74, 74, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2213 74, 74, 74, 74, 74, 74, 74, 74, 74, 69, 74, 74, 74, 74, 74, 74,
2214 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2215 74, 68, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
2216 -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2217 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2218 74, 74, 74, 74, 74, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2219 74, 74, 74, 74, 74, 74, 74, 74, 74, 70, 74, 74, 74, 74, 74, 74,
2220 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2221 74, 73, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
2222 -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2223 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2224 74, 74, 74, 74, 74, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2225 74, 74, 74, 74, 74, 74, 74, 74, 74, 71, 74, 74, 74, 74, 74, 74,
2226 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2227 74, 73, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
2228 -1, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
2229 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
2230 29, 29, 29, 26, 29, 29, 29, 25, 19, 17, 22, 29, 29, 29, 28, 23,
2231 29, 29, 18, 12, 29, 29, 20, 21, 29, 29, 29, 29, 29, 29, 29, 29,
2232 29, 11, 29, 7, 29, 29, 29, 9, 4, 29, 5, 8, 29, 29, 29, 6,
2233 29, 27, 3, 1, 29, 29, 2, 29, 10, 29, 29, 29, 29, 29, 29, 29,
2234 -1, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
2235 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
2236 50, 32, 50, 31, 33, 34, 35, 50, 38, 30, 50, 40, 37, 48, 50, 50,
2237 50, 50, 39, 41, 42, 45, 47, 46, 36, 50, 50, 50, 50, 50, 50, 50,
2238 50, 11, 50, 7, 44, 50, 50, 9, 4, 50, 5, 8, 50, 43, 50, 6,
2239 50, 49, 3, 1, 50, 50, 2, 50, 10, 50, 50, 50, 50, 50, 50, 50,
2240 -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2241 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2242 74, 74, 74, 74, 74, 72, 74, 74, 74, 17, 74, 74, 74, 74, 74, 74,
2243 74, 74, 74, 12, 74, 74, 74, 74, 74, 16, 74, 74, 74, 74, 74, 74,
2244 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2245 74, 73, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
2246 -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2247 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2248 74, 74, 74, 74, 74, 72, 53, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2249 74, 74, 74, 12, 74, 74, 74, 74, 54, 52, 74, 74, 74, 74, 74, 74,
2250 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2251 74, 51, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
2252 -1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2253 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2254 74, 74, 74, 74, 74, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2255 74, 74, 74, 74, 74, 74, 74, 74, 74, 14, 74, 74, 74, 74, 74, 74,
2256 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2257 74, 73, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74, 74,
2258 0, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2259 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2260 74, 74, 74, 74, 74, 72, 74, 74, 74, 74, 74, 74, 74, 74, 74, 24,
2261 74, 74, 74, 12, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
2262 74, 11, 74, 7, 74, 74, 74, 9, 4, 74, 5, 8, 74, 74, 74, 6,
2263 74, 73, 3, 1, 74, 74, 2, 74, 10, 74, 74, 74, 74, 74, 74,74
2268 From here down to proto() are routines that were moved out of the state
2269 table switcher because the resulting switch() had become too large.
2270 To move the contents of a state-table case to a routine:
2271 1. Add a prototype to the list above the state table switcher.
2272 2. Make a routine with an appropriate name, returning int.
2273 3. Move the code into it.
2274 4. Put a call to the new routine in the former spot:
2275 rc = name_of_routine();
2276 if (rc > -1) return(rc);
2277 5. Add "return(-1);" after every RESUME, SERVE, or BEGIN macro and
2278 at the end if the code is open-ended.
2283 debug(F101,"rcv_firstdata","",dispos);
2285 if (discard) { /* if we're discarding the file */
2286 ack1((CHAR *)"X"); /* just ack the data like this. */
2287 cancel++; /* and count it */
2288 BEGIN rdpkt; /* and wait for more data packets. */
2290 } else { /* Not discarding. */
2291 rf_err = "Can't open file";
2292 if (xflg) { /* If screen data */
2293 if (remfile) { /* redirected to file */
2294 if (rempipe) /* or pipe */
2295 x = openc(ZOFILE,remdest); /* Pipe: start command */
2297 x = opena(remdest,&iattr); /* File: open with attributes */
2298 } else { /* otherwise */
2299 x = opent(&iattr); /* "open" the screen */
2301 } else { /* otherwise */
2303 if (calibrate) { /* If calibration run */
2304 x = ckopenx(&iattr); /* open nothing */
2306 if (streaming) /* Streaming */
2307 fastack(); /* ACK without ACKing. */
2309 #endif /* STREAMING */
2310 ack(); /* Send real ACK */
2311 BEGIN rdpkt; /* Proceed to next state */
2314 #endif /* CALIBRATE */
2317 In UNIX we can pipe the file data into the mail program, which is to be
2318 preferred to writing it out to a temp file and then mailing it afterwards.
2319 This depends rather heavily on all UNIXes having a mail command that
2320 accepts '-s "subject"' on the command line. MAILCMD (e.g. mail, Mail, mailx)
2321 is defined in ckufio.c.
2323 if (dispos == 'M') { /* Mail... */
2327 extern char *MAILCMD;
2328 s = iattr.disp.val + 1;
2329 n = (int)strlen(MAILCMD) + /* Mail command */
2330 (int)strlen(s) + /* address */
2331 (int)strlen(ofilnam) + 32; /* subject */
2332 if (tmp = (char *)malloc(n)) {
2334 MAILCMD," -s \"",ofilnam,"\" ",s,
2335 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
2336 debug(F111,"rcv_firsdata mail",tmp,(int)strlen(tmp));
2337 x = openc(ZOFILE,(char *)tmp);
2341 } else if (dispos == 'P') { /* Ditto for print */
2344 extern char *PRINTCMD;
2345 n = (int)strlen(PRINTCMD) + (int)strlen(iattr.disp.val+1) + 4;
2346 if (tmp = (char *)malloc(n)) {
2347 sprintf(tmp, /* safe (prechecked) */
2348 "%s %s", PRINTCMD, iattr.disp.val + 1);
2349 x = openc(ZOFILE,(char *)tmp);
2355 x = opena(filnam,&iattr); /* open the file, with attributes */
2357 if (x) { /* If file was opened ok */
2366 rc = (binary && !parity) ?
2367 bdecode(rdatap,putfil):
2368 decode(rdatap, qf ? puttrm : putfil, 1);
2370 rc = decode(rdatap, qf ? puttrm : putfil, 1);
2371 #endif /* CKTUNING */
2373 errpkt((CHAR *)"Error writing data");
2378 if (streaming) /* Streaming was negotiated */
2379 fastack(); /* ACK without ACKing. */
2381 #endif /* STREAMING */
2382 ack(); /* acknowledge it */
2383 BEGIN rdpkt; /* and switch to receive-data state */
2385 } else { /* otherwise */
2386 errpkt((CHAR *) rf_err); /* send error packet */
2387 RESUME; /* and quit. */
2397 debug(F111,"rcv_shortreply",rdatap,ipktlen);
2398 if (ipktack[0] && !strncmp(ipktack,(char *)rdatap,ipktlen)) {
2399 /* No it's the ACK to the I packet again */
2400 x = scmd(vcmd,(CHAR *)cmarg); /* So send the REMOTE command again */
2401 /* Maybe this should be resend() */
2402 debug(F110,"IPKTZEROHACK",ipktack,x);
2404 errpkt((CHAR *)srimsg);
2410 #endif /* PKTZEROHACK */
2414 if (query) { /* If to query, */
2415 qbufp = querybuf; /* initialize query response buffer */
2421 if (remfile) { /* Response redirected to file */
2422 rf_err = "Can't open file";
2423 if (rempipe) /* or pipe */
2426 zxcmd(ZOFILE,remdest) /* Pipe: Start command */
2432 x = opena(remdest,&iattr); /* File: Open with attributes */
2433 debug(F111,"rcv_shortreply remfile",remdest,x);
2435 x = opent(&iattr); /* "open" the screen */
2437 if (x) { /* If file was opened ok */
2440 (query || !remfile) ? puttrm :
2444 zputfil, 1) < 0) { /* Note: zputfil, not putfil. */
2445 errpkt((CHAR *)"Error writing data");
2449 if (rdatap) /* If we had data */
2450 if (*rdatap) /* add a line terminator */
2451 if (remfile) { /* to file */
2453 } else { /* or to screen. */
2455 if (!query || !xcmdsrc)
2457 if (!(quiet && rcdactive))
2460 if (bye_active && network) { /* I sent BYE or REMOTE LOGOUT */
2461 msleep(500); /* command and got the ACK... */
2466 if (!epktsent && !epktrcvd) /* If no error packet... */
2467 success = 1; /* success. */
2471 } else { /* File not opened OK */
2472 errpkt((CHAR *) rf_err); /* send error message */
2473 RESUME; /* and quit. */
2476 #endif /* NOSERVER */
2479 #endif /* PKTZEROHACK */
2480 debug(F101,"rcv_shortreply fallthru","",success);
2491 if (ckxsyslog >= SYSLG_PR && ckxlogging)
2492 cksyslog(SYSLG_PR, 1, "server", "REMOTE QUERY", (char *)srvcmd);
2493 #endif /* CKSYSLOG */
2495 if (ikdbopen) slotstate(what,"REMOTE QUERY", (char *)(srvcmd+2), "");
2497 c = *(srvcmd+2); /* Q = Query, S = Set */
2498 if (c == 'Q') { /* Query */
2499 if (!ENABLED(en_que)) { /* Security */
2500 errpkt((CHAR *)"REMOTE QUERY disabled");
2503 } else { /* Query allowed */
2505 qbufp = querybuf; /* Wipe out old stuff */
2508 p = (char *) srvcmd + 3; /* Pointer for making wrapper */
2509 n = strlen((char *)srvcmd); /* Position of end */
2510 c = *(srvcmd+4); /* Which type of variable */
2512 if (*(srvcmd+6) == CMDQ) { /* Starts with command quote? */
2513 p = (char *) srvcmd + 6; /* Take it literally */
2514 if (*p == CMDQ) p++;
2515 } else { /* They played by the rules */
2516 if (c == 'K') { /* Kermit variable */
2518 k = (int) strlen(p);
2519 if (k > 0 && p[k-1] == ')') {
2520 p = (char *)(srvcmd + 4);
2522 *(srvcmd+5) = 'f'; /* Function, so make it \f...() */
2524 *(srvcmd+3) = CMDQ; /* Stuff wrapping into buffer */
2525 *(srvcmd+4) = 'v'; /* Variable, so make it \v(...) */
2526 *(srvcmd+5) = '('; /* around variable name */
2528 *(srvcmd+n+1) = NUL;
2531 *(srvcmd+3) = CMDQ; /* Stuff wrapping into buffer */
2532 *(srvcmd+4) = 'v'; /* Variable, so make it \v(...) */
2533 *(srvcmd+5) = '('; /* around variable name */
2535 *(srvcmd+n+1) = NUL;
2536 if (c == 'S') { /* System variable */
2537 *(srvcmd+4) = '$'; /* so it's \$(...) */
2538 } else if (c == 'G') { /* Non-\ Global variable */
2539 *(srvcmd+4) = 'm'; /* so wrap it in \m(...) */
2542 } /* Now evaluate it */
2543 n = QBUFL; /* Max length */
2544 q = querybuf; /* Where to put it */
2545 if (zzstring(p,&q,&n) < 0) {
2546 errpkt((n > 0) ? (CHAR *)"Can't get value"
2547 : (CHAR *)"Value too long"
2552 if (encstr((CHAR *)querybuf) > -1) { /* Encode it */
2553 ack1(data); /* If it fits, send it back in ACK */
2557 } else if (sndstring(querybuf)) { /* Long form response */
2560 } else { /* sndhlp() fails */
2561 errpkt((CHAR *)"Can't send value");
2567 } else if (c == 'S') { /* Set (assign) */
2568 if (!ENABLED(en_asg)) { /* Security */
2569 errpkt((CHAR *)"REMOTE ASSIGN disabled");
2574 n = xunchar(*(srvcmd+3)); /* Length of name */
2575 n = 3 + n + 1; /* Position of length of value */
2576 *(srvcmd+n) = NUL; /* Don't need it */
2577 if (addmac((char *)(srvcmd+4),(char *)(srvcmd+n+1)) < 0)
2578 errpkt((CHAR *)"REMOTE ASSIGN failed");
2587 errpkt((CHAR *)"Badly formed server command");
2592 errpkt((CHAR *)"Variable query/set not available");
2596 #endif /* NOSERVER */
2603 if (ckxsyslog >= SYSLG_PR && ckxlogging)
2604 cksyslog(SYSLG_PR, 1, "server", "REMOTE COPY", (char *)srvcmd);
2605 #endif /* CKSYSLOG */
2607 if (!ENABLED(en_cpy)) {
2608 errpkt((CHAR *)"REMOTE COPY disabled");
2612 char *str1, *str2, f1[256], f2[256];
2614 len1 = xunchar(srvcmd[1]); /* Separate the parameters */
2615 len2 = xunchar(srvcmd[2+len1]);
2616 strncpy(f1,(char *)(srvcmd+2),len1);
2618 strncpy(f2,(char *)(srvcmd+3+len1),len2);
2621 if (ikdbopen) slotstate(what,"REMOTE COPY", f1, f2);
2623 if (!ENABLED(en_cwd)) { /* If CWD is disabled */
2624 zstrip(f1,&str1); /* and they included a pathname, */
2626 if (strcmp(f1,str1) || strcmp(f2,str2)) { /* Refuse. */
2627 errpkt((CHAR *)"Access denied");
2628 RESUME; /* Remember, this is not a goto! */
2632 if (state == generic) { /* It's OK to go ahead. */
2633 if (zcopy(f1,f2)) { /* Try */
2634 errpkt((CHAR *)"Can't copy file"); /* give error message */
2639 RESUME; /* wait for next server command */
2644 #else /* no ZCOPY */
2645 errpkt((CHAR *)"REMOTE COPY not available"); /* give error message */
2646 RESUME; /* wait for next server command */
2649 #endif /* NOSERVER */
2656 if (ckxsyslog >= SYSLG_PR && ckxlogging)
2657 cksyslog(SYSLG_PR, 1, "server", "REMOTE RENAME", (char *)srvcmd);
2658 #endif /* CKSYSLOG */
2660 if (!ENABLED(en_ren)) {
2661 errpkt((CHAR *)"REMOTE RENAME disabled");
2664 } else { /* RENAME is enabled */
2665 char *str1, *str2, f1[256], f2[256];
2667 len1 = xunchar(srvcmd[1]); /* Separate the parameters */
2668 len2 = xunchar(srvcmd[2+len1]);
2669 strncpy(f1,(char *)(srvcmd+2),len1);
2671 strncpy(f2,(char *)(srvcmd+3+len1),len2);
2673 len2 = xunchar(srvcmd[2+len1]);
2674 strncpy(f1,(char *)(srvcmd+2),len1);
2676 strncpy(f2,(char *)(srvcmd+3+len1),len2);
2679 if (ikdbopen) slotstate(what,"REMOTE RENAME", f1, f2);
2681 if (!ENABLED(en_cwd)) { /* If CWD is disabled */
2682 zstrip(f1,&str1); /* and they included a pathname, */
2684 if ( strcmp(f1,str1) || strcmp(f2,str2) ) { /* refuse. */
2685 errpkt((CHAR *)"Access denied");
2686 RESUME; /* Remember, this is not a goto! */
2690 if (state == generic) { /* It's OK to go ahead. */
2691 if (zrename(f1,f2)) { /* Try */
2692 errpkt((CHAR *)"Can't rename file"); /* Give error msg */
2697 RESUME; /* Wait for next server command */
2702 #else /* no ZRENAME */
2703 /* Give error message */
2704 errpkt((CHAR *)"REMOTE RENAME not available");
2705 RESUME; /* Wait for next server command */
2707 #endif /* ZRENAME */
2708 #endif /* NOSERVER */
2714 char f1[LOGINLEN+1], f2[LOGINLEN+1], f3[LOGINLEN+1];
2718 debug(F101,"REMOTE LOGIN x_login","",x_login);
2719 debug(F101,"REMOTE LOGIN x_logged","",x_logged);
2721 f1[0] = NUL; f2[0] = NUL; f3[0] = NUL;
2723 if (srvcmd[1]) /* First length field */
2724 len = xunchar(srvcmd[1]); /* Separate the parameters */
2726 if (x_login) { /* Login required */
2727 if (x_logged) { /* And already logged in */
2728 if (len > 0) { /* Logging in again */
2729 errpkt((CHAR *)"Already logged in.");
2730 } else { /* Logging out */
2731 debug(F101,"REMOTE LOGOUT","",x_logged);
2733 if (ckxsyslog >= SYSLG_PR && ckxlogging)
2734 cksyslog(SYSLG_PR, 1, "server", "REMOTE LOGOUT", NULL);
2735 #endif /* CKSYSLOG */
2737 if (ikdbopen) slotstate(what,"REMOTE LOGOUT", "", "");
2739 tlog(F110,"Logged out",x_user,0);
2740 ack1((CHAR *)"Logged out");
2749 #endif /* CK_LOGIN */
2751 } else { /* Not logged in yet */
2752 debug(F101,"REMOTE LOGIN len","",len);
2753 if (len > 0) { /* Have username */
2755 if (ckxsyslog >= SYSLG_PR && ckxlogging)
2756 cksyslog(SYSLG_PR, 1, "server", "REMOTE LOGIN", NULL);
2757 #endif /* CKSYSLOG */
2758 if (len > LOGINLEN) {
2759 errpkt((CHAR *)"Username too long");
2761 p = srvcmd + 2; /* Point to it */
2762 for (i = 0; i < len; i++) /* Copy it */
2764 f1[len] = NUL; /* Terminate it */
2765 p += len; /* Point to next length field */
2766 if (*p) { /* If we have one */
2767 len = xunchar(*p++); /* decode it */
2768 if (len > 0 && len <= LOGINLEN) {
2769 for (i = 0; i < len; i++) /* Same deal for password */
2772 p += len; /* And account */
2774 len = xunchar(*p++);
2775 if (len > 0 && len <= LOGINLEN) {
2776 for (i = 0; i < len; i++)
2777 f3[i] = p[i]; /* Set but never used */
2778 f3[len] = NUL; /* (because account not used) */
2783 debug(F101,"REMOTE LOGIN 1","",x_logged);
2786 if (inserver) { /* Log in to system for real */
2787 x_logged = ckxlogin((CHAR *)f1,(CHAR *)f2,NULL,0);
2788 debug(F101,"REMOTE LOGIN 2","",x_logged);
2789 if (x_logged) { /* Count attempts */
2797 #endif /* CK_LOGIN */
2799 if (x_user && x_passwd) { /* User and password must match */
2800 if (!strcmp(x_user,f1)) /* SET SERVER LOGIN */
2801 if (!strcmp(x_passwd,f2))
2803 debug(F101,"REMOTE LOGIN 3","",x_logged);
2804 } else if (x_user) { /* Only username given, no password */
2805 if (!strcmp(x_user,f1)) /* so only username must match */
2807 debug(F101,"REMOTE LOGIN 4","",x_logged);
2811 x_logged = ckxlogin((CHAR *)f1,(CHAR *)f2,NULL,0);
2812 debug(F101,"REMOTE LOGIN 5","",x_logged);
2814 #endif /* CK_LOGIN */
2815 if (x_logged) { /* Logged in? */
2816 tlog(F110,"Logged in", x_user, 0);
2818 ack1((CHAR *)"Logged in as guest - restrictions apply");
2820 ack1((CHAR *)"Logged in");
2823 tlog(F110,"Login failed", f1, 0);
2824 errpkt((CHAR *)"Access denied.");
2827 if (inserver && logtries > 2)
2829 #endif /* CK_LOGIN */
2832 } else { /* LOGOUT */
2833 errpkt((CHAR *)"Logout ignored");
2836 } else { /* Login not required */
2838 errpkt((CHAR *)"Login ignored.");
2840 errpkt((CHAR *)"Logout ignored.");
2842 #endif /* NOSERVER */
2849 /* K95 does this its own way */
2853 printf("\r\nIKSD IDLE TIMEOUT: %d sec\r\n", srvidl);
2854 doexit(GOOD_EXIT,xitsta);
2858 printf("\r\nSERVER IDLE TIMEOUT: %d sec\r\n", srvidl);
2859 xitsta |= (what & W_KERMIT);
2863 else if (fatalio) { /* Connection lost */
2865 if (ckxsyslog >= SYSLG_PR && ckxlogging)
2866 cksyslog(SYSLG_PR, 1, "server", "Connection lost", NULL);
2867 #endif /* CKSYSLOG */
2869 if (ikdbopen) slotstate(what,"SERVER DISCONNECT",(char *)srvcmd, "");
2873 } else if (interrupted) { /* Interrupted by hand */
2874 if (!ENABLED(en_fin)) {
2875 errpkt((CHAR *)"QUIT disabled");
2879 if (what == W_SEND || what == W_RECV || what == W_REMO) {
2882 if (ckxsyslog >= SYSLG_PR && ckxlogging)
2883 cksyslog(SYSLG_PR, 1, "server", "Interrupted", NULL);
2884 #endif /* CKSYSLOG */
2885 } else if (what == W_NOTHING && filcnt == 0) {
2887 } /* Otherwise leave success alone */
2888 xitsta |= (what & W_KERMIT);
2891 } else { /* Shouldn't happen */
2892 debug(F100,"SERVER (top) GOT UNEXPECTED 'q'","",0);
2895 #endif /* NOSERVER */
2903 if (/* state == serve && */ x_login && !x_logged) {
2904 errpkt((CHAR *)"Login required");
2907 #endif /* NOSERVER */
2908 if (state == serve && !ENABLED(en_sen)) { /* Not in server mode */
2909 errpkt((CHAR *)"SEND disabled"); /* when SEND is disabled. */
2912 } else { /* OK to go ahead. */
2914 if (dldir && !f_tmpdir) { /* If they have a download directory */
2915 debug(F110,"receive download dir",dldir,0);
2916 if (s = zgtdir()) { /* Get current directory */
2917 debug(F110,"receive current dir",s,0);
2918 if (zchdir(dldir)) { /* Change to download directory */
2919 debug(F100,"receive zchdir ok","",0);
2920 ckstrncpy(savdir,s,TMPDIRLEN);
2921 f_tmpdir = 1; /* Remember that we did this */
2923 debug(F100,"receive zchdir failed","",0);
2926 #endif /* CK_TMPDIR */
2927 nakstate = 1; /* Can send NAKs from here. */
2928 rinit(rdatap); /* Set parameters */
2929 bctu = bctr; /* Switch to agreed-upon block check */
2930 bctl = (bctu == 4) ? 2 : bctu; /* Set block-check length */
2931 what = W_RECV; /* Remember we're receiving */
2933 resetc(); /* Reset counters */
2934 rtimer(); /* Reset timer */
2937 #endif /* GFTIMER */
2939 BEGIN rfile; /* Go into receive-file state */
2945 /* END OF ROUTINES MOVED OUT OF STATE MACHINE */
2948 /* P R O T O -- Protocol entry function */
2950 static int is_tn = 0; /* It's a Telnet connection */
2953 int f_ctlp = 0; /* Control-character prefix table */
2956 #endif /* COMMENT */
2957 #endif /* CK_SPEED */
2960 This is simply a wrapper for the real protocol function just below,
2961 that saves any items that might be changed automatically by protocol
2962 negotiations and then restores them upon exit from protocol mode.
2966 extern int b_save, f_save, c_save, ss_save, slostart, reliable, urclear;
2968 extern int fcharset, fcs_save, tcharset, tcs_save;
2969 #endif /* NOCSETS */
2972 extern int pipesend;
2973 #endif /* PIPESEND */
2976 extern int cursorena[], cursor_save, term_io;
2978 extern int display_demo;
2981 #endif /* NOLOCAL */
2983 int _u_bin=0, _me_bin = 0;
2985 int /* _u_start=0, */ _me_start = 0;
2986 #endif /* IKS_OPTION */
2991 #endif /* PATTERNS */
2996 #endif /* PATTERNS */
2997 scan_save = filepeek;
3002 if (isguest) { /* If user is anonymous */
3003 en_pri = 0; /* disable printing */
3004 en_mai = 0; /* and disable email */
3005 en_del = 0; /* and file deletion */
3007 #endif /* CK_LOGIN */
3011 cursor_save = cursorena[vmode];
3012 cursorena[vmode] = 0;
3013 term_io_save = term_io;
3016 #endif /* NOLOCAL */
3017 b_save = binary; /* SET FILE TYPE */
3018 f_save = fncnv; /* SET FILE NAMES */
3025 fcs_save = fcharset;
3026 tcs_save = tcharset;
3027 #endif /* NOCSETS */
3030 /* Don't do this because then user can never find out what happened. */
3032 for (i = 0; i < 256; i++)
3033 s_ctlp[i] = ctlp[i];
3035 #endif /* CK_SPEED */
3036 #endif /* COMMENT */
3037 if (reliable == SET_ON)
3039 is_tn = (!local && sstelnet)
3041 || (local && network && ttnproto == NP_TELNET)
3046 if (tn_b_xfer && !(sstelnet || inserver)) {
3047 /* Save the current state of Telnet Binary */
3048 _u_bin = TELOPT_U(TELOPT_BINARY);
3049 _me_bin = TELOPT_ME(TELOPT_BINARY);
3051 /* If either direction is not Binary attempt to negotiate it */
3052 if (!_u_bin && TELOPT_U_MODE(TELOPT_BINARY) != TN_NG_RF) {
3053 tn_sopt(DO,TELOPT_BINARY);
3054 TELOPT_UNANSWERED_DO(TELOPT_BINARY) = 1;
3056 if (!_me_bin && TELOPT_ME_MODE(TELOPT_BINARY) != TN_NG_RF) {
3057 tn_sopt(WILL,TELOPT_BINARY);
3058 TELOPT_UNANSWERED_WILL(TELOPT_BINARY) = 1;
3060 if (!(_me_bin && _u_bin))
3061 tn_wait("proto set binary mode");
3065 if (protocol != PROTO_K) { /* Non-Kermit protocol selected */
3066 if (TELOPT_U(TELOPT_KERMIT) &&
3067 TELOPT_SB(TELOPT_KERMIT).kermit.u_start) {
3068 iks_wait(KERMIT_REQ_STOP,0); /* Stop the other Server */
3071 if (TELOPT_ME(TELOPT_KERMIT) &&
3072 TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
3073 tn_siks(KERMIT_STOP); /* I'm not servering */
3074 TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
3079 if (sstate == 'x' || sstate == 'v') { /* Responding to a request */
3080 if (!inserver && TELOPT_U(TELOPT_KERMIT) &&
3081 TELOPT_SB(TELOPT_KERMIT).kermit.u_start) {
3082 iks_wait(KERMIT_REQ_STOP,0); /* Stop the other Server */
3085 if (TELOPT_ME(TELOPT_KERMIT) &&
3086 !TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
3087 tn_siks(KERMIT_START); /* Send Kermit-Server Start */
3088 TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 1;
3090 } else { /* Initiating a request */
3091 if (TELOPT_ME(TELOPT_KERMIT) &&
3092 TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
3093 tn_siks(KERMIT_STOP); /* I'm not servering */
3094 TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
3097 if (TELOPT_U(TELOPT_KERMIT) &&
3098 !TELOPT_SB(TELOPT_KERMIT).kermit.u_start) {
3099 /* Send Req-Server-Start */
3100 if (!iks_wait(KERMIT_REQ_START,0)) {
3101 if (sstate != 's') {
3102 success = 0; /* Other Kermit refused to serve */
3104 printf("A Kermit Server is not available\r\n");
3105 debug(F110,"proto()",
3106 "A Kermit Server is not available",0);
3107 tlog(F110,"IKS client/server failure",
3108 "A Kermit Server is not available",0);
3114 #endif /* IKS_OPTION */
3115 #ifdef CK_ENCRYPTION
3116 if (tn_no_encrypt_xfer && !(sstelnet || inserver)) {
3119 #endif /* CK_ENCRYPTION */
3123 if (!xfrint) connoi();
3124 xxproto(); /* Call the real protocol function */
3128 #endif /* IKS_OPTION */
3129 xferstat = success; /* Remember transfer status */
3133 #ifdef CK_ENCRYPTION
3134 if (tn_no_encrypt_xfer && !(sstelnet || inserver)) {
3137 #endif /* CK_ENCRYPTION */
3139 if (TELOPT_ME(TELOPT_KERMIT) &&
3140 TELOPT_SB(TELOPT_KERMIT).kermit.me_start && !_me_start) {
3141 tn_siks(KERMIT_STOP); /* Server is stopped */
3142 TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
3144 #endif /* IKS_OPTION */
3145 if (is_tn && tn_b_xfer && !(sstelnet || inserver)) {
3146 /* if we negotiated Binary mode try to reset it */
3148 /* Check to see if the state changed during the transfer */
3149 if (TELOPT_U(TELOPT_BINARY)) {
3150 tn_sopt(DONT,TELOPT_BINARY);
3151 TELOPT_UNANSWERED_DONT(TELOPT_BINARY) = 1;
3153 _u_bin = 1; /* So we don't call tn_wait() */
3156 /* Check to see if the state changed during the transfer */
3157 if (TELOPT_ME(TELOPT_BINARY)) {
3158 tn_sopt(WONT,TELOPT_BINARY);
3159 TELOPT_UNANSWERED_WONT(TELOPT_BINARY) = 1;
3161 _me_bin = 1; /* So we don't call tn_wait() */
3163 if (!(_me_bin && _u_bin))
3164 tn_wait("proto reset binary mode");
3170 #endif /* PATTERNS */
3171 filepeek = scan_save;
3176 #endif /* STREAMING */
3179 for (i = 0; i < 256; i++)
3180 ctlp[i] = s_ctlp[i];
3182 #endif /* CK_SPEED */
3183 #endif /* COMMENT */
3186 xitsta |= (what & W_KERMIT);
3187 tlog(F110," failed:",(char *)epktmsg,0);
3189 debug(F111,"proto xferstat",epktmsg,xferstat);
3191 if (s_timint > -1) { /* Because of REMOTE SET */
3197 if (c_save > -1) { /* Because of REMOTE SET */
3204 pipesend = 0; /* Next time might not be pipesend */
3205 #endif /* PIPESEND */
3208 cursorena[vmode] = cursor_save;
3209 term_io = term_io_save;
3212 #endif /* NOLOCAL */
3221 _PROTOTYP( int pxyz, (int) );
3222 #endif /* XYZ_INTERNAL */
3225 char xss[2]; /* String representation of sstate */
3230 debug(F101,"xxproto entry justone","",justone);
3233 retrieve = 0; /* Reset these ... */
3237 if (local && ttchk() < 0) { /* Giving BYE or FIN */
3238 if (bye_active) { /* but there is no connection */
3243 /* Ditto for any REMOTE command */
3244 if (sstate == 'g' && cmarg ) {
3245 if (*cmarg == 'L' || *cmarg == 'F' || *cmarg == 'X')
3248 printf("?No connection\r\n");
3253 /* Set up the communication line for file transfer. */
3254 /* NOTE: All of the xxscreen() calls prior to the wart() invocation */
3255 /* could just as easily be printf's or, for that matter, hints. */
3257 if (local && (speed < 0L) && (network == 0)) {
3258 xxscreen(SCR_EM,0,0L,"Sorry, you must 'set speed' first");
3262 if (ttopen(ttname,&x,mdmtyp,cdtimo) < 0) {
3263 debug(F111,"failed: proto ttopen local",ttname,local);
3264 xxscreen(SCR_EM,0,0L,"Can't open line");
3267 if (x > -1) local = x;
3268 debug(F111,"proto ttopen local",ttname,local);
3270 lx = (local && !network) ? speed : -1;
3274 ctlp[(unsigned)255] = ctlp[CR] = 1;
3275 if (parity == 'e' || parity == 'm') ctlp[127] = 1;
3276 if (flow == FLO_XONX) { /* Also watch out for Xon/Xoff */
3277 ctlp[17] = ctlp[19] = 1;
3278 ctlp[17+128] = ctlp[19+128] = 1;
3281 #endif /* CK_SPEED */
3282 #endif /* NETCONN */
3283 if (ttpkt(lx,flow,parity) < 0) { /* Put line in packet mode, */
3284 xxscreen(SCR_EM,0,0L,"Can't condition line");
3287 if (local && !network && carrier != CAR_OFF) {
3288 int x; /* Serial connection */
3289 x = ttgmdm(); /* with carrier checking */
3291 if (!(x & BM_DCD)) {
3292 debug(F101,"proto ttgmdm","",0);
3293 xxscreen(SCR_EM,0,0L,"Carrier required but not detected");
3298 /* Send remote side's "receive" or "server" startup string, if any */
3299 if (local && ckindex((char *)xss,"srgcjhk",0,0,1)) {
3303 /* Don't send auto-blah string if we know other side is serving */
3304 !TELOPT_U(TELOPT_KERMIT) ||
3305 !TELOPT_SB(TELOPT_KERMIT).kermit.u_start
3308 #endif /* IKS_OPTION */
3310 if (sstate == 's') { /* Sending file(s) */
3311 s = binary ? ptab[protocol].h_b_init : ptab[protocol].h_t_init;
3312 } else if (protocol == PROTO_K) { /* Command for server */
3313 s = ptab[protocol].h_x_init;
3317 #ifndef UNPREFIXZERO
3318 if (protocol == PROTO_K) /* Because of C-strings... */
3320 #endif /* UNPREFIXZERO */
3321 #endif /* CK_SPEED */
3322 if (s) if (*s) { /* If we have a command to send... */
3324 int tmpbufsiz = 356;
3325 int stuff = -1, stuff2 = -1, len = 0;
3327 if (sstate == 's') { /* Sending file(s) */
3329 if (protocol == PROTO_X) {
3331 s2 = cmarg2[0] ? cmarg2 : cmarg;
3332 if ((int)strlen(s) + (int)strlen(s2) + 4 < 356)
3333 sprintf(tmpbuf, s, s2);
3338 ckmakmsg(tmpbuf, 356, s, NULL, NULL, NULL);
3342 } else { /* Command for server */
3343 ckstrncpy(tmpbuf,s,356);
3345 ckstrncat(tmpbuf, "\015",sizeof(tmpbuf));
3346 if (tnlm) /* TERMINAL NEWLINE ON */
3347 stuff = LF; /* Stuff LF */
3349 /* TELNET NEWLINE MODE */
3351 switch (TELOPT_ME(TELOPT_BINARY) ? tn_b_nlm : tn_nlm) {
3367 if (network && ttnproto == NP_RLOGIN) {
3368 switch (tn_b_nlm) { /* Always BINARY */
3381 #endif /* RLOGCODE */
3382 #endif /* TCPSOCKET */
3383 #endif /* NETCONN */
3385 len = strlen(tmpbuf);
3386 if (stuff >= 0 && len < tmpbufsiz - 1) {
3387 tmpbuf[len++] = stuff;
3388 if (stuff2 >= 0 && len < tmpbufsiz - 1)
3389 tmpbuf[len++] = stuff2;
3392 ttol((CHAR *)tmpbuf,len);
3393 if (protocol == PROTO_K) /* Give remote Kermit time to start */
3399 if (protocol != PROTO_K) { /* Non-Kermit protocol selected */
3401 int tmpbufsiz = 356;
3405 if (sstate == 'v') { /* If receiving and... */
3406 if (dldir && !f_tmpdir) { /* if they have a download directory */
3407 if (s = zgtdir()) { /* Get current directory */
3408 if (zchdir(dldir)) { /* Change to download directory */
3409 ckstrncpy(savdir,s,TMPDIRLEN);
3410 f_tmpdir = 1; /* Remember that we did this */
3415 #endif /* CK_TMPDIR */
3417 #ifdef XYZ_INTERNAL /* Internal */
3418 success = !pxyz(sstate);
3420 #ifdef CK_REDIR /* External */
3422 case 's': /* 'Tis better to SEND... */
3423 s = binary ? ptab[protocol].p_b_scmd : ptab[protocol].p_t_scmd;
3425 case 'v': /* ... than RECEIVE */
3426 s = binary ? ptab[protocol].p_b_rcmd : ptab[protocol].p_t_rcmd;
3431 if (sstate == 's') { /* Sending */
3432 extern int xfermode;
3433 int k = 0, x = 0, b = binary;
3435 If just one file we can scan it to set the xfer mode.
3436 Otherwise it's up to the external protocol program.
3438 if (patterns && xfermode == XMODE_A && !iswild(fspec)) {
3439 extern int nscanfile;
3440 k = scanfile(fspec,&x,nscanfile);
3442 b = (k == FT_BIN) ? XYFT_B : XYFT_T;
3444 ptab[protocol].p_b_scmd :
3445 ptab[protocol].p_t_scmd;
3448 if ((int)strlen(s) + (int)strlen(fspec) < tmpbufsiz) {
3449 sprintf(tmpbuf,s,fspec); /* safe (prechecked) */
3450 tlog(F110,"Sending",fspec,0L);
3452 } else { /* Receiving */
3453 if ((int)strlen(s) + (int)strlen(cmarg2) < tmpbufsiz) {
3454 sprintf(tmpbuf,s,cmarg2); /* safe (prechecked) */
3455 tlog(F110,"Receiving",cmarg2,0L);
3458 tlog(F110," via external protocol:",tmpbuf,0);
3459 debug(F110,"ckcpro ttruncmd",tmpbuf,0);
3460 success = ttruncmd(tmpbuf);
3461 tlog(F110," status:",success ? "OK" : "FAILED", 0);
3463 printf("?Sorry, no external protocol defined for %s\r\n",
3464 ptab[protocol].p_name
3469 "Sorry, only Kermit protocol is supported in this version of Kermit\n"
3471 #endif /* CK_REDIR */
3472 #endif /* XYZ_INTERNAL */
3482 connoi(); /* No console interrupts if remote */
3486 if (sstate == 'x') { /* If entering server mode, */
3487 extern int howcalled;
3488 server = 1; /* set flag, */
3489 debug(F101,"server backgrd","",backgrd);
3490 debug(F101,"server quiet","",quiet);
3491 debug(F100,"SHOULD NOT SEE THIS IF IN BACKGROUND!","",0);
3492 if (howcalled == I_AM_SSHSUB) { /* and issue appropriate message. */
3493 ttol((CHAR *)"KERMIT READY TO SERVE...\015\012",26);
3494 } else if (!local) {
3495 if (!quiet && !backgrd
3497 && !TELOPT_ME(TELOPT_KERMIT) /* User was told by negotiation */
3498 #endif /* IKS_OPTION */
3501 conoll("KERMIT READY TO SERVE...");
3504 conol("Entering server mode on ");
3506 conoll("Type Ctrl-C to quit.");
3507 if (srvdis) intmsg(-1L);
3510 if (network && tcpsrfd > 0)
3511 ttol((CHAR *)"KERMIT READY TO SERVE...\015\012",26);
3512 #endif /* NOLISTEN */
3513 #endif /* TCPSOCKET */
3518 if (!quiet && !backgrd) /* So message doesn't overwrite prompt */
3520 if (local) conres(); /* So Ctrl-C will work */
3523 If in remote mode, not shushed, not in background, and at top command level,
3524 issue a helpful message telling what to do...
3526 if (!local && !quiet && !backgrd) {
3527 if (sstate == 'v') {
3528 conoll("Return to your local Kermit and give a SEND command.");
3530 conoll("KERMIT READY TO RECEIVE...");
3531 } else if (sstate == 's') {
3532 conoll("Return to your local Kermit and give a RECEIVE command.");
3534 conoll("KERMIT READY TO SEND...");
3535 } else if ( sstate == 'g' || sstate == 'r' || sstate == 'h' ||
3536 sstate == 'j' || sstate == 'c' ) {
3537 conoll("Return to your local Kermit and give a SERVER command.");
3539 conoll((sstate == 'r' || sstate == 'j' || sstate == 'h') ?
3540 "KERMIT READY TO GET..." :
3541 "KERMIT READY TO SEND SERVER COMMAND...");
3545 if (!local) sleep(1);
3546 #endif /* COMMENT */
3548 The 'wart()' function is generated by the wart program. It gets a
3549 character from the input() routine and then based on that character and
3550 the current state, selects the appropriate action, according to the state
3551 table above, which is transformed by the wart program into a big case
3552 statement. The function is active for one transaction.
3554 rtimer(); /* Reset elapsed-time timer */
3557 #endif /* GFTIMER */
3558 resetc(); /* & other per-transaction counters. */
3560 debug(F101,"proto calling wart, justone","",justone);
3562 wart(); /* Enter the state table switcher. */
3564 Note: the following is necessary in case we have just done a remote-mode
3565 file transfer, in which case the controlling terminal modes have been
3566 changed by ttpkt(). In particular, special characters like Ctrl-C and
3567 Ctrl-\ might have been turned off (see ttpkt). So this call to ttres() is
3568 essential. IMPORTANT: restore interrupt handlers first, otherwise any
3569 terminal interrupts that occur before this is done in the normal place
3570 later will cause a crash.
3573 ttres(); /* Reset the communication device */
3576 setint(); /* Arm interrupt handlers FIRST */
3578 ttres(); /* Then restore terminal. */
3581 xxscreen(SCR_TC,0,0L,""); /* Transaction complete */
3584 clsif(); /* Failsafe in case we missed */
3585 clsof(1); /* a case in the state machine. */
3588 if (server) { /* Back from packet protocol. */
3589 if (!quiet && !backgrd
3593 ) { /* Give appropriate message */
3595 conoll("C-Kermit server done");
3597 server = 0; /* Not a server any more */
3601 /* S G E T I N I T -- Handle incoming GET-Class packets */
3606 0: GET packet processed OK - ready to Send.
3607 1: Extended GET processed OK - wait for another.
3610 sgetinit(reget,xget) int reget, xget; { /* Server end of GET command */
3611 char * fs = NULL; /* Pointer to filespec */
3614 extern int usepipes, pipesend;
3615 #endif /* PIPESEND */
3618 if (!ENABLED(en_get)) { /* Only if not disabled! */
3619 errpkt((CHAR *)"GET disabled");
3625 nolinks = recursive;
3629 /* If they are alike this was already done in whoarewe() */
3630 debug(F101,"sgetinit whatru","",whatru);
3631 if (whatru & WMI_FLAG) { /* Did we get WHATAMI info? */
3632 debug(F101,"sgetinit binary (1)","",binary);
3634 if (binary != XYFT_I && binary != XYFT_L)
3637 if (binary != XYFT_L)
3640 binary = (whatru & WMI_FMODE) ? /* Yes, set file type */
3641 XYFT_B : XYFT_T; /* automatically */
3642 debug(F101,"sgetinit binary (2)","",binary);
3644 fncnv = (whatru & WMI_FNAME) ? 1 : 0; /* And name conversion */
3646 #endif /* WHATAMI */
3648 fs = (char *)srvcmd;
3649 srvptr = srvcmd; /* Point to server command buffer */
3650 decode(rdatap,putsrv,0); /* Decode the GET command into it */
3651 /* Accept multiple filespecs */
3652 cmarg2 = ""; /* Don't use cmarg2 */
3653 cmarg = ""; /* Don't use cmarg */
3655 done = 1; /* Only 1 packet needed... */
3656 if (xget) { /* Special decoding for Extended GET */
3657 char L, next, c; /* PLV items */
3658 int len, val; /* More PLV items */
3659 char * p = (char *)srvcmd; /* String to decode */
3661 done = 0; /* Maybe more packets needed */
3662 fs = NULL; /* We don't know the filespec yet */
3663 c = *p++; /* Get first parameter */
3665 while (c) { /* For all parameters... */
3666 debug(F000,"sgetinit c","",c);
3667 L = *p++; /* Get length */
3668 if (L >= SP) /* Decode length */
3670 else if (c == '@') { /* Allow missing EOP length field */
3673 len = (xunchar(*p++) * 95);
3674 len += xunchar(*p++);
3676 debug(F101,"sgetinit len","",len);
3677 next = *(p+len); /* Get next parameter */
3678 *(p+len) = NUL; /* Zero it out to terminal value */
3679 debug(F110,"sgetinit p",p,0);
3680 switch (c) { /* Do the parameter */
3681 case 'O': /* GET Options */
3682 val = atoi(p); /* Convert to int */
3683 debug(F101,"sgetinit O val","",val);
3684 if (val & GOPT_DEL) moving = 1;
3685 if (val & GOPT_RES) reget = 1;
3686 if (val & GOPT_REC) {
3689 if (fnspath == PATH_OFF)
3693 case 'M': /* Transfer Mode */
3695 debug(F101,"sgetinit M val","",val);
3698 patterns = 0; /* Takes precedence over patterns */
3699 filepeek = 0; /* and FILE SCAN */
3700 if (val == GMOD_TXT) binary = XYFT_T; /* Text */
3701 if (val == GMOD_BIN) binary = XYFT_B; /* Binary */
3702 if (val == GMOD_LBL) binary = XYFT_L; /* Labeled */
3704 case 'F': /* Filename */
3706 debug(F110,"sgetinit filename",fs,0);
3708 case '@': /* End Of Parameters */
3710 debug(F100,"sgetinit EOP","",0);
3713 errpkt((CHAR *)"Unknown GET Parameter");
3714 debug(F100,"sgetinit unknown parameter","",0);
3721 if (!fs) fs = ""; /* A filename is required */
3724 n = 0; /* Check for quoted name */
3725 if ((n = strlen(fs)) > 1) {
3726 /* Note: this does not allow for multiple quoted names */
3727 if ((fs[0] == '{' && fs[n-1] == '}') ||
3728 (fs[0] == '"' && fs[n-1] == '"')) {
3731 debug(F111,"sgetinit unquoted filename",fs,n);
3733 n = 0; /* This means no quoting */
3737 debug(F111,"sgetinit",fs,usepipes);
3738 if (usepipes && ENABLED(en_hos) && *fs == '!') {
3739 cmarg = fs + 1; /* Point past the bang */
3743 debug(F111,"sgetinit pipesend",cmarg,pipesend);
3745 if (!pipesend) { /* If it's not a pipe */
3746 #endif /* PIPESEND */
3747 if (n == 0) { /* If the name was not quoted */
3749 nfils = fnparse(fs); /* Allow it to be a list of names */
3750 debug(F111,"sgetinit A",fs,nfils);
3752 /* This doesn't work if a GET-PATH is set. */
3753 if (nfils == 1 && !iswild(fs)) { /* Single file */
3755 if ((x = zchki(fs)) < 0) { /* Check if it's sendable */
3757 case -1: m = "File not found"; break;
3758 case -2: m = "Not a regular file"; break;
3759 case -3: m = "Read access denied"; break;
3765 #endif /* COMMENT */
3766 } else { /* If it was quoted */
3767 #endif /* NOMSEND */
3770 if (matchdot) nzxopts |= ZX_MATCHDOT;
3771 #endif /* UNIXOROSK */
3772 if (recursive) nzxopts |= ZX_RECURSE;
3773 /* Treat as a single filespec */
3774 nfils = 0 - nzxpand(fs,nzxopts);
3775 debug(F111,"sgetinit B",fs,nfils);
3780 #endif /* PIPESEND */
3782 if (!done) { /* Need more O packets... */
3783 debug(F100,"sgetinit O-Packet TBC","",0); /* To Be Continued */
3786 debug(F100,"sgetinit O-Packet done - havefs","",havefs);
3787 if (!havefs) { /* Done - make sure we have filename */
3788 errpkt((CHAR *)"GET without filename");
3792 winlo = 0; /* Back to packet 0 again. */
3793 debug(F101,"sgetinit winlo","",winlo);
3794 nakstate = 0; /* Now I'm the sender! */
3795 if (reget) sendmode = SM_RESEND;
3796 if (sinit() > 0) { /* Send Send-Init */
3799 #endif /* STREAMING */
3800 timint = chktimo(rtimo,timef); /* Switch to per-packet timer */
3801 return(0); /* If successful, switch state */
3802 } else return(-1); /* Else back to server command wait */