📄 ckcpro.w
字号:
char *protv = "C-Kermit Protocol Module 6.0.095, 6 Sep 96"; /* -*-C-*- *//* C K C P R O -- C-Kermit Protocol Module, in Wart preprocessor notation. *//* Author: Frank da Cruz <fdc@columbia.edu>, Columbia University Academic Information Systems, New York City. Copyright (C) 1985, 1996, Trustees of Columbia University in the City of New York. The C-Kermit software may not be, in whole or in part, licensed or sold for profit as a software product itself, nor may it be included in or distributed with commercial products or otherwise distributed by commercial concerns to their clients or customers without written permission of the Office of Kermit Development and Distribution, Columbia University. This copyright notice must not be removed, altered, or obscured.*/#include "ckcsym.h"#include "ckcdeb.h"#include "ckcasc.h"#include "ckcker.h"#ifdef OS2#ifndef NT#define INCL_NOPM#define INCL_VIO /* Needed for ckocon.h */#include <os2.h> #undef COMMENT#endif /* NT */#include "ckocon.h"#endif /* OS2 *//* Note -- This file may also be preprocessed by the UNIX Lex program, but you must indent the above #include statements before using Lex, and then restore them to the left margin in the resulting C program before compilation. Also, the invocation of the "wart()" function below must be replaced by an invocation of the "yylex()" function. It might also be necessary to remove comments in the %%...%% section.*//* State definitions for Wart (or Lex) */%states ipkt rfile rattr rdata ssinit ssfile ssattr ssdata sseof sseot%states serve generic get rgen/* External C-Kermit variable declarations */ extern char *versio, *srvtxt, *cmarg, *cmarg2, **cmlist, *rf_err; extern char filnam[], fspec[], ttname[]; extern CHAR sstate, *rpar(), *srvptr, *data; extern int timint, rtimo, nfils, hcflg, xflg, flow, mdmtyp, network; extern int rejection, moving, fncact, bye_active; extern int protocol, prefixing, filcnt; extern struct ck_p ptab[]; extern int remfile, rempipe; extern char * remdest;#ifndef NOSERVER extern char * x_user, * x_passwd, * x_acct; extern int x_login, x_logged;#endif /* NOSERVER */#ifdef NETCONN#ifdef CK_SPEED extern int ttnproto; /* Network protocol */ extern short ctlp[]; /* Control-character prefix table */#endif /* CK_SPEED */#ifdef TCPSOCKET#include "ckcnet.h" extern int me_binary, tn_b_nlm, tn_nlm;#endif /* TCPSOCKET */#endif /* NETCONN */#ifdef TCPSOCKET#ifndef NOLISTEN extern int tcpsrfd;#endif /* NOLISTEN */#endif /* TCPSOCKET */ extern int cxseen, czseen, server, srvdis, local, displa, bctu, bctr, bctl; extern int quiet, tsecs, parity, backgrd, nakstate, atcapu, wslotn, winlo; extern int wslots, success, xitsta, rprintf, discard, cdtimo, keep, fdispla; extern int timef, stdinf, rscapu, sendmode, epktflg; extern int binary, fncnv; extern long speed, ffc, crc16; extern char *DIRCMD, *DIRCM2, *DELCMD, *TYPCMD, *SPACMD, *SPACM2, *WHOCMD; extern CHAR *rdatap; extern struct zattr iattr;#ifdef pdp11 extern CHAR srvcmd[]; extern CHAR *pktmsg;#else#ifdef DYNAMIC extern CHAR *srvcmd; extern CHAR *pktmsg;#else extern CHAR srvcmd[]; extern CHAR pktmsg[];#endif /* DYNAMIC */#endif /* pdp11 */#ifdef CK_TMPDIRextern int f_tmpdir; /* Directory changed temporarily */extern char savdir[]; /* For saving current directory */extern char * dldir;#endif /* CK_TMPDIR */#ifndef NOSPL extern int cmdlvl; char querybuf[QBUFL+1] = { NUL, NUL }; /* QUERY response buffer */ char *qbufp = querybuf; /* Pointer to it */ int qbufn = 0; /* Length of data in it */ extern int query; /* Query-active flag */#else extern int tlevel;#endif /* NOSPL */#ifdef NT extern int escape;#endif /* NT *//* If the following flag is nonzero when the protocol module is entered, then server mode persists for exactly one transaction, rather than looping until BYE or FINISH is received.*/int justone = 0;_PROTOTYP(static VOID xxproto,(void));_PROTOTYP(static int sgetinit,(int));_PROTOTYP(int sndspace,(int));_PROTOTYP(int wart,(void));/* Flags for the ENABLE and DISABLE commands */extern int en_cpy, en_cwd, en_del, en_dir, en_fin, en_get, en_bye, en_mai, en_pri, en_hos, en_ren, en_sen, en_spa, en_set, en_typ, en_who, en_ret;#ifndef NOSPLextern int en_asg, en_que;#endif /* NOSPL *//* Global variables declared here */ int what = W_NOTHING; /* What I am doing */ int whatru = 0; /* What are you *//* Local variables */ static char vstate = 0; /* Saved State */ static char vcmd = 0; /* Saved Command */ static int reget = 0; static int retrieve = 0; static int x; /* General-purpose integer */ static char *s; /* General-purpose string pointer *//* Macros - Note, BEGIN is predefined by Wart (and Lex) as "state = ", *//* BEGIN is NOT a GOTO! */#define ENABLED(x) ((local && (x & 1)) || (!local && (x & 2)))#define TINIT if (tinit() < 0) return(-9)#define SERVE TINIT; nakstate=1; what=W_NOTHING; cmarg2=""; \sendmode=SM_SEND; BEGIN serve;#define RESUME if (!server) { return(0); } else \if (justone) { justone=0; return(0); } else { SERVE; }#define QUIT x=quiet; quiet=1; clsif(); clsof(1); tsecs=gtimer(); quiet=x; \ return(1)%%/* Protocol entry points, one for each start state (sstate). The lowercase letters are internal "inputs" from the user interface.*/s { TINIT; /* Do Send command */ if (sinit() > 0) BEGIN ssinit; else RESUME; }v { TINIT; nakstate = 1; BEGIN get; } /* Receive */r { /* Get */ TINIT; vstate = get; reget = 0; retrieve = 0; vcmd = 0; if (sipkt('I') >= 0) BEGIN ipkt; else RESUME;}h { /* RETRIEVE */ TINIT; vstate = get; reget = 0; retrieve = 1; vcmd = 0; if (sipkt('I') >= 0) BEGIN ipkt; else RESUME;}j { /* REGET */ TINIT; vstate = get; reget = 1; retrieve = 0; vcmd = 0; if (sipkt('I') >= 0) BEGIN ipkt; else RESUME;}c { /* Host */ TINIT; vstate = rgen; vcmd = 'C'; if (sipkt('I') >= 0) BEGIN ipkt; else RESUME;}k { TINIT; /* Kermit */ vstate = rgen; vcmd = 'K'; if (sipkt('I') >= 0) BEGIN ipkt; else RESUME;}g { /* Generic */ TINIT; vstate = rgen; vcmd = 'G'; if (sipkt('I') >= 0) BEGIN ipkt; else RESUME;}x { /* Be a Server */ int x; x = justone; debug(F101,"x justone 1","",justone); SERVE; /* tinit() clears justone... */ debug(F101,"x justone 2","",justone); justone = x;}a { int b1 = 0, b2 = 0; if (!data) TINIT; /* "ABEND" -- Tell other side. */#ifndef pdp11 if (epktflg) { /* If because of E-PACKET command */ b1 = bctl; b2 = bctu; /* Save block check type */ bctl = bctu = 1; /* set it to 1 */ }#endif /* pdp11 */ errpkt((CHAR *)"User cancelled"); /* Send the packet */#ifndef pdp11 if (epktflg) { /* Restore the block check */ epktflg = 0; bctl = b1; bctu = b2; } screen(SCR_EM,0,0L,"User cancelled");#endif /* pdp11 */ success = 0; return(0); /* Return from protocol. */}/* Dynamic states: <current-states>input-character { action } nakstate != 0 means we're in a receiving state, in which we send ACKs & NAKs.*/<rgen,get,serve>S { /* Receive Send-Init packet. */#ifndef NOSERVER if (state == serve && x_login && !x_logged) { errpkt((CHAR *)"Login required"); SERVE; } else#endif /* NOSERVER */ if (state == serve && !ENABLED(en_sen)) { /* Not in server mode */ errpkt((CHAR *)"SEND disabled"); /* when SEND is disabled. */ RESUME; } else { /* OK to go ahead. */#ifdef CK_TMPDIR if (dldir && !f_tmpdir) { /* If they have a download directory */ debug(F110,"receive download dir",dldir,0); if (s = zgtdir()) { /* Get current directory */ debug(F110,"receive current dir",s,0); if (zchdir(dldir)) { /* Change to download directory */ debug(F100,"receive zchdir ok","",0); strncpy(savdir,s,TMPDIRLEN); f_tmpdir = 1; /* Remember that we did this */ } else debug(F100,"receive zchdir failed","",0); } }#endif /* CK_TMPDIR */ nakstate = 1; /* Can send NAKs from here. */ rinit(rdatap); /* Set parameters */ bctu = bctr; /* Switch to agreed-upon block check */ bctl = (bctu == 4) ? 2 : bctu; /* Set block-check length */ what = W_RECV; /* Remember we're receiving */ resetc(); /* Reset counters */ rtimer(); /* Reset timer */ BEGIN rfile; /* Go into receive-file state */ }}/* States in which we get replies back from commands sent to a server. *//* Complicated because direction of protocol changes, packet number *//* stays at zero through I-G-S sequence, and complicated even more by *//* sliding windows buffer allocation. */<ipkt>Y { /* Get ack for I-packet */ int x = 0; spar(rdatap); /* Set parameters */ winlo = 0; /* Set window-low back to zero */ if (vcmd) { /* If sending a generic command */ TINIT; x = scmd(vcmd,(CHAR *)cmarg); /* Do that */ vcmd = 0; /* and then un-remember it. */ } else if (vstate == get) { debug(F101,"REGET sstate","",sstate); x = srinit(reget, retrieve); /* GET or REGET */ } if (x < 0) { /* If command was too long */ errpkt((CHAR *)"Command too long for server"); /* cancel both sides. */ ermsg("Command too long for server"); success = 0; RESUME; } else { rtimer(); /* Reset the elapsed seconds timer. */ winlo = 0; /* Window back to 0, again. */ nakstate = 1; /* Can send NAKs from here. */ BEGIN vstate; /* Switch to desired state */ }}<ipkt>E { /* Ignore Error reply to I packet */ int x = 0; winlo = 0; /* Set window-low back to zero */ if (vcmd) { /* In case other Kermit doesn't */ TINIT; x = scmd(vcmd,(CHAR *)cmarg); /* understand I-packets. */ vcmd = 0; /* Otherwise act as above... */ } else if (vstate == get) x = srinit(reget, retrieve); if (x < 0) { /* If command was too long */ errpkt((CHAR *)"Command too long for server"); /* cancel both sides. */ ermsg("Command too long for server"); success = 0; RESUME; } else { winlo = 0; /* Back to packet 0 again. */ freerpkt(winlo); /* Discard the Error packet. */ nakstate = 1; /* Can send NAKs from here. */ BEGIN vstate; }}<get>Y { /* Resend of previous I-pkt ACK, same seq number! */ srinit(reget, retrieve); /* Send the GET packet again. */}/* States in which we're being a server */<serve,get>I { /* Get I-packet */#ifndef NOSERVER spar(rdatap); /* Set parameters from it */ ack1(rpar()); /* Respond with our own parameters */ pktinit(); /* Reinitialize packet numbers */#endif /* NOSERVER */}<serve>R { /* Get Receive-Init (GET) */#ifndef NOSERVER if (x_login && !x_logged) { errpkt((CHAR *)"Login required"); SERVE; } else if (sgetinit(0) < 0) { RESUME; } else { BEGIN ssinit; }#endif /* NOSERVER */}<serve>H { /* GET and DELETE ("retrieve") */#ifndef NOSERVER if (x_login && !x_logged) { errpkt((CHAR *)"Login required"); RESUME; } else if (!ENABLED(en_ret)) { errpkt((CHAR *)"RETRIEVE disabled - use GET"); RESUME; } else if (!ENABLED(en_del)) { errpkt((CHAR *)"Deleting files disabled - use GET"); RESUME; } else if (sgetinit(0) < 0) { RESUME; } else { moving = 1; BEGIN ssinit; }#endif /* NOSERVER */}<serve>J { /* Get REGET */#ifndef NOSERVER if (x_login && !x_logged) { errpkt((CHAR *)"Login required"); SERVE; } else if (sgetinit(1) < 0) { RESUME; } else { BEGIN ssinit; }#endif /* NOSERVER */}<serve>G { /* Generic server command */#ifndef NOSERVER srvptr = srvcmd; /* Point to command buffer */ decode(rdatap,putsrv,0); /* Decode packet data into it */ putsrv(NUL); /* Insert a couple nulls */ putsrv(NUL); /* for termination */ if (srvcmd[0]) { sstate = srvcmd[0]; /* Set requested start state */ if (x_login && !x_logged && sstate != 'I') { errpkt((CHAR *)"Login required"); SERVE; } else { nakstate = 0; /* Now I'm the sender. */ what = W_REMO; /* Doing a REMOTE command. */ if (timint < 1) timint = chktimo(rtimo,timef); /* Switch to per-packet timer */ BEGIN generic; /* Switch to generic command state */ } } else { errpkt((CHAR *)"Badly formed server command"); /* report error */ RESUME; /* & go back to server command wait */ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -