1 | char *protv = "C-Kermit Protocol Module 6.0.095, 6 Sep 96"; /* -*-C-*- */ |
---|
2 | |
---|
3 | /* C K C P R O -- C-Kermit Protocol Module, in Wart preprocessor notation. */ |
---|
4 | /* |
---|
5 | Author: Frank da Cruz <fdc@columbia.edu>, |
---|
6 | Columbia University Academic Information Systems, New York City. |
---|
7 | |
---|
8 | Copyright (C) 1985, 1996, Trustees of Columbia University in the City of New |
---|
9 | York. The C-Kermit software may not be, in whole or in part, licensed or |
---|
10 | sold for profit as a software product itself, nor may it be included in or |
---|
11 | distributed with commercial products or otherwise distributed by commercial |
---|
12 | concerns to their clients or customers without written permission of the |
---|
13 | Office of Kermit Development and Distribution, Columbia University. This |
---|
14 | copyright notice must not be removed, altered, or obscured. |
---|
15 | */ |
---|
16 | #include "ckcsym.h" |
---|
17 | #include "ckcdeb.h" |
---|
18 | #include "ckcasc.h" |
---|
19 | #include "ckcker.h" |
---|
20 | #ifdef OS2 |
---|
21 | #ifndef NT |
---|
22 | #define INCL_NOPM |
---|
23 | #define INCL_VIO /* Needed for ckocon.h */ |
---|
24 | #include <os2.h> |
---|
25 | #undef COMMENT |
---|
26 | #endif /* NT */ |
---|
27 | #include "ckocon.h" |
---|
28 | #endif /* OS2 */ |
---|
29 | |
---|
30 | /* |
---|
31 | Note -- This file may also be preprocessed by the UNIX Lex program, but |
---|
32 | you must indent the above #include statements before using Lex, and then |
---|
33 | restore them to the left margin in the resulting C program before compilation. |
---|
34 | Also, the invocation of the "wart()" function below must be replaced by an |
---|
35 | invocation of the "yylex()" function. It might also be necessary to remove |
---|
36 | comments in the %%...%% section. |
---|
37 | */ |
---|
38 | |
---|
39 | /* State definitions for Wart (or Lex) */ |
---|
40 | %states ipkt rfile rattr rdata ssinit ssfile ssattr ssdata sseof sseot |
---|
41 | %states serve generic get rgen |
---|
42 | |
---|
43 | /* External C-Kermit variable declarations */ |
---|
44 | extern char *versio, *srvtxt, *cmarg, *cmarg2, **cmlist, *rf_err; |
---|
45 | extern char filnam[], fspec[], ttname[]; |
---|
46 | extern CHAR sstate, *rpar(), *srvptr, *data; |
---|
47 | extern int timint, rtimo, nfils, hcflg, xflg, flow, mdmtyp, network; |
---|
48 | extern int rejection, moving, fncact, bye_active; |
---|
49 | extern int protocol, prefixing, filcnt; |
---|
50 | extern struct ck_p ptab[]; |
---|
51 | extern int remfile, rempipe; |
---|
52 | extern char * remdest; |
---|
53 | |
---|
54 | #ifndef NOSERVER |
---|
55 | extern char * x_user, * x_passwd, * x_acct; |
---|
56 | extern int x_login, x_logged; |
---|
57 | #endif /* NOSERVER */ |
---|
58 | |
---|
59 | #ifdef NETCONN |
---|
60 | #ifdef CK_SPEED |
---|
61 | extern int ttnproto; /* Network protocol */ |
---|
62 | extern short ctlp[]; /* Control-character prefix table */ |
---|
63 | #endif /* CK_SPEED */ |
---|
64 | #ifdef TCPSOCKET |
---|
65 | #include "ckcnet.h" |
---|
66 | extern int me_binary, tn_b_nlm, tn_nlm; |
---|
67 | #endif /* TCPSOCKET */ |
---|
68 | #endif /* NETCONN */ |
---|
69 | |
---|
70 | #ifdef TCPSOCKET |
---|
71 | #ifndef NOLISTEN |
---|
72 | extern int tcpsrfd; |
---|
73 | #endif /* NOLISTEN */ |
---|
74 | #endif /* TCPSOCKET */ |
---|
75 | |
---|
76 | extern int cxseen, czseen, server, srvdis, local, displa, bctu, bctr, bctl; |
---|
77 | extern int quiet, tsecs, parity, backgrd, nakstate, atcapu, wslotn, winlo; |
---|
78 | extern int wslots, success, xitsta, rprintf, discard, cdtimo, keep, fdispla; |
---|
79 | extern int timef, stdinf, rscapu, sendmode, epktflg; |
---|
80 | extern int binary, fncnv; |
---|
81 | extern long speed, ffc, crc16; |
---|
82 | extern char *DIRCMD, *DIRCM2, *DELCMD, *TYPCMD, *SPACMD, *SPACM2, *WHOCMD; |
---|
83 | extern CHAR *rdatap; |
---|
84 | extern struct zattr iattr; |
---|
85 | |
---|
86 | #ifdef pdp11 |
---|
87 | extern CHAR srvcmd[]; |
---|
88 | extern CHAR *pktmsg; |
---|
89 | #else |
---|
90 | #ifdef DYNAMIC |
---|
91 | extern CHAR *srvcmd; |
---|
92 | extern CHAR *pktmsg; |
---|
93 | #else |
---|
94 | extern CHAR srvcmd[]; |
---|
95 | extern CHAR pktmsg[]; |
---|
96 | #endif /* DYNAMIC */ |
---|
97 | #endif /* pdp11 */ |
---|
98 | |
---|
99 | #ifdef CK_TMPDIR |
---|
100 | extern int f_tmpdir; /* Directory changed temporarily */ |
---|
101 | extern char savdir[]; /* For saving current directory */ |
---|
102 | extern char * dldir; |
---|
103 | #endif /* CK_TMPDIR */ |
---|
104 | |
---|
105 | #ifndef NOSPL |
---|
106 | extern int cmdlvl; |
---|
107 | char querybuf[QBUFL+1] = { NUL, NUL }; /* QUERY response buffer */ |
---|
108 | char *qbufp = querybuf; /* Pointer to it */ |
---|
109 | int qbufn = 0; /* Length of data in it */ |
---|
110 | extern int query; /* Query-active flag */ |
---|
111 | #else |
---|
112 | extern int tlevel; |
---|
113 | #endif /* NOSPL */ |
---|
114 | |
---|
115 | #ifdef NT |
---|
116 | extern int escape; |
---|
117 | #endif /* NT */ |
---|
118 | /* |
---|
119 | If the following flag is nonzero when the protocol module is entered, |
---|
120 | then server mode persists for exactly one transaction, rather than |
---|
121 | looping until BYE or FINISH is received. |
---|
122 | */ |
---|
123 | int justone = 0; |
---|
124 | |
---|
125 | _PROTOTYP(static VOID xxproto,(void)); |
---|
126 | _PROTOTYP(static int sgetinit,(int)); |
---|
127 | _PROTOTYP(int sndspace,(int)); |
---|
128 | _PROTOTYP(int wart,(void)); |
---|
129 | |
---|
130 | /* Flags for the ENABLE and DISABLE commands */ |
---|
131 | extern int |
---|
132 | en_cpy, en_cwd, en_del, en_dir, en_fin, en_get, en_bye, en_mai, en_pri, |
---|
133 | en_hos, en_ren, en_sen, en_spa, en_set, en_typ, en_who, en_ret; |
---|
134 | #ifndef NOSPL |
---|
135 | extern int en_asg, en_que; |
---|
136 | #endif /* NOSPL */ |
---|
137 | |
---|
138 | /* Global variables declared here */ |
---|
139 | |
---|
140 | int what = W_NOTHING; /* What I am doing */ |
---|
141 | int whatru = 0; /* What are you */ |
---|
142 | |
---|
143 | /* Local variables */ |
---|
144 | |
---|
145 | static char vstate = 0; /* Saved State */ |
---|
146 | static char vcmd = 0; /* Saved Command */ |
---|
147 | static int reget = 0; |
---|
148 | static int retrieve = 0; |
---|
149 | |
---|
150 | static int x; /* General-purpose integer */ |
---|
151 | static char *s; /* General-purpose string pointer */ |
---|
152 | |
---|
153 | /* Macros - Note, BEGIN is predefined by Wart (and Lex) as "state = ", */ |
---|
154 | /* BEGIN is NOT a GOTO! */ |
---|
155 | #define ENABLED(x) ((local && (x & 1)) || (!local && (x & 2))) |
---|
156 | #define TINIT if (tinit() < 0) return(-9) |
---|
157 | #define SERVE TINIT; nakstate=1; what=W_NOTHING; cmarg2=""; \ |
---|
158 | sendmode=SM_SEND; BEGIN serve; |
---|
159 | #define RESUME if (!server) { return(0); } else \ |
---|
160 | if (justone) { justone=0; return(0); } else { SERVE; } |
---|
161 | #define QUIT x=quiet; quiet=1; clsif(); clsof(1); tsecs=gtimer(); quiet=x; \ |
---|
162 | return(1) |
---|
163 | |
---|
164 | %% |
---|
165 | /* |
---|
166 | Protocol entry points, one for each start state (sstate). |
---|
167 | The lowercase letters are internal "inputs" from the user interface. |
---|
168 | */ |
---|
169 | |
---|
170 | s { TINIT; /* Do Send command */ |
---|
171 | if (sinit() > 0) BEGIN ssinit; |
---|
172 | else RESUME; } |
---|
173 | |
---|
174 | v { TINIT; nakstate = 1; BEGIN get; } /* Receive */ |
---|
175 | |
---|
176 | r { /* Get */ |
---|
177 | TINIT; |
---|
178 | vstate = get; |
---|
179 | reget = 0; |
---|
180 | retrieve = 0; |
---|
181 | vcmd = 0; |
---|
182 | if (sipkt('I') >= 0) |
---|
183 | BEGIN ipkt; |
---|
184 | else |
---|
185 | RESUME; |
---|
186 | } |
---|
187 | h { /* RETRIEVE */ |
---|
188 | TINIT; |
---|
189 | vstate = get; |
---|
190 | reget = 0; |
---|
191 | retrieve = 1; |
---|
192 | vcmd = 0; |
---|
193 | if (sipkt('I') >= 0) |
---|
194 | BEGIN ipkt; |
---|
195 | else |
---|
196 | RESUME; |
---|
197 | } |
---|
198 | j { /* REGET */ |
---|
199 | TINIT; |
---|
200 | vstate = get; |
---|
201 | reget = 1; |
---|
202 | retrieve = 0; |
---|
203 | vcmd = 0; |
---|
204 | if (sipkt('I') >= 0) |
---|
205 | BEGIN ipkt; |
---|
206 | else |
---|
207 | RESUME; |
---|
208 | } |
---|
209 | c { /* Host */ |
---|
210 | TINIT; |
---|
211 | vstate = rgen; |
---|
212 | vcmd = 'C'; |
---|
213 | if (sipkt('I') >= 0) |
---|
214 | BEGIN ipkt; |
---|
215 | else |
---|
216 | RESUME; |
---|
217 | } |
---|
218 | k { TINIT; /* Kermit */ |
---|
219 | vstate = rgen; |
---|
220 | vcmd = 'K'; |
---|
221 | if (sipkt('I') >= 0) |
---|
222 | BEGIN ipkt; |
---|
223 | else |
---|
224 | RESUME; |
---|
225 | } |
---|
226 | g { /* Generic */ |
---|
227 | TINIT; |
---|
228 | vstate = rgen; |
---|
229 | vcmd = 'G'; |
---|
230 | if (sipkt('I') >= 0) |
---|
231 | BEGIN ipkt; |
---|
232 | else |
---|
233 | RESUME; |
---|
234 | } |
---|
235 | x { /* Be a Server */ |
---|
236 | int x; |
---|
237 | x = justone; |
---|
238 | debug(F101,"x justone 1","",justone); |
---|
239 | SERVE; /* tinit() clears justone... */ |
---|
240 | debug(F101,"x justone 2","",justone); |
---|
241 | justone = x; |
---|
242 | } |
---|
243 | a { |
---|
244 | int b1 = 0, b2 = 0; |
---|
245 | if (!data) TINIT; /* "ABEND" -- Tell other side. */ |
---|
246 | #ifndef pdp11 |
---|
247 | if (epktflg) { /* If because of E-PACKET command */ |
---|
248 | b1 = bctl; b2 = bctu; /* Save block check type */ |
---|
249 | bctl = bctu = 1; /* set it to 1 */ |
---|
250 | } |
---|
251 | #endif /* pdp11 */ |
---|
252 | errpkt((CHAR *)"User cancelled"); /* Send the packet */ |
---|
253 | #ifndef pdp11 |
---|
254 | if (epktflg) { /* Restore the block check */ |
---|
255 | epktflg = 0; |
---|
256 | bctl = b1; bctu = b2; |
---|
257 | } |
---|
258 | screen(SCR_EM,0,0L,"User cancelled"); |
---|
259 | #endif /* pdp11 */ |
---|
260 | success = 0; |
---|
261 | return(0); /* Return from protocol. */ |
---|
262 | } |
---|
263 | |
---|
264 | /* |
---|
265 | Dynamic states: <current-states>input-character { action } |
---|
266 | nakstate != 0 means we're in a receiving state, in which we send ACKs & NAKs. |
---|
267 | */ |
---|
268 | |
---|
269 | <rgen,get,serve>S { /* Receive Send-Init packet. */ |
---|
270 | #ifndef NOSERVER |
---|
271 | if (state == serve && x_login && !x_logged) { |
---|
272 | errpkt((CHAR *)"Login required"); |
---|
273 | SERVE; |
---|
274 | } else |
---|
275 | #endif /* NOSERVER */ |
---|
276 | |
---|
277 | if (state == serve && !ENABLED(en_sen)) { /* Not in server mode */ |
---|
278 | errpkt((CHAR *)"SEND disabled"); /* when SEND is disabled. */ |
---|
279 | RESUME; |
---|
280 | } else { /* OK to go ahead. */ |
---|
281 | #ifdef CK_TMPDIR |
---|
282 | if (dldir && !f_tmpdir) { /* If they have a download directory */ |
---|
283 | debug(F110,"receive download dir",dldir,0); |
---|
284 | if (s = zgtdir()) { /* Get current directory */ |
---|
285 | debug(F110,"receive current dir",s,0); |
---|
286 | if (zchdir(dldir)) { /* Change to download directory */ |
---|
287 | debug(F100,"receive zchdir ok","",0); |
---|
288 | strncpy(savdir,s,TMPDIRLEN); |
---|
289 | f_tmpdir = 1; /* Remember that we did this */ |
---|
290 | } else |
---|
291 | debug(F100,"receive zchdir failed","",0); |
---|
292 | } |
---|
293 | } |
---|
294 | #endif /* CK_TMPDIR */ |
---|
295 | nakstate = 1; /* Can send NAKs from here. */ |
---|
296 | rinit(rdatap); /* Set parameters */ |
---|
297 | bctu = bctr; /* Switch to agreed-upon block check */ |
---|
298 | bctl = (bctu == 4) ? 2 : bctu; /* Set block-check length */ |
---|
299 | what = W_RECV; /* Remember we're receiving */ |
---|
300 | resetc(); /* Reset counters */ |
---|
301 | rtimer(); /* Reset timer */ |
---|
302 | BEGIN rfile; /* Go into receive-file state */ |
---|
303 | } |
---|
304 | } |
---|
305 | |
---|
306 | /* States in which we get replies back from commands sent to a server. */ |
---|
307 | /* Complicated because direction of protocol changes, packet number */ |
---|
308 | /* stays at zero through I-G-S sequence, and complicated even more by */ |
---|
309 | /* sliding windows buffer allocation. */ |
---|
310 | |
---|
311 | <ipkt>Y { /* Get ack for I-packet */ |
---|
312 | int x = 0; |
---|
313 | spar(rdatap); /* Set parameters */ |
---|
314 | winlo = 0; /* Set window-low back to zero */ |
---|
315 | if (vcmd) { /* If sending a generic command */ |
---|
316 | TINIT; |
---|
317 | x = scmd(vcmd,(CHAR *)cmarg); /* Do that */ |
---|
318 | vcmd = 0; /* and then un-remember it. */ |
---|
319 | } else if (vstate == get) { |
---|
320 | debug(F101,"REGET sstate","",sstate); |
---|
321 | x = srinit(reget, retrieve); /* GET or REGET */ |
---|
322 | } |
---|
323 | if (x < 0) { /* If command was too long */ |
---|
324 | errpkt((CHAR *)"Command too long for server"); /* cancel both sides. */ |
---|
325 | ermsg("Command too long for server"); |
---|
326 | success = 0; |
---|
327 | RESUME; |
---|
328 | } else { |
---|
329 | rtimer(); /* Reset the elapsed seconds timer. */ |
---|
330 | winlo = 0; /* Window back to 0, again. */ |
---|
331 | nakstate = 1; /* Can send NAKs from here. */ |
---|
332 | BEGIN vstate; /* Switch to desired state */ |
---|
333 | } |
---|
334 | } |
---|
335 | |
---|
336 | <ipkt>E { /* Ignore Error reply to I packet */ |
---|
337 | int x = 0; |
---|
338 | winlo = 0; /* Set window-low back to zero */ |
---|
339 | if (vcmd) { /* In case other Kermit doesn't */ |
---|
340 | TINIT; |
---|
341 | x = scmd(vcmd,(CHAR *)cmarg); /* understand I-packets. */ |
---|
342 | vcmd = 0; /* Otherwise act as above... */ |
---|
343 | } else if (vstate == get) x = srinit(reget, retrieve); |
---|
344 | if (x < 0) { /* If command was too long */ |
---|
345 | errpkt((CHAR *)"Command too long for server"); /* cancel both sides. */ |
---|
346 | ermsg("Command too long for server"); |
---|
347 | success = 0; |
---|
348 | RESUME; |
---|
349 | } else { |
---|
350 | winlo = 0; /* Back to packet 0 again. */ |
---|
351 | freerpkt(winlo); /* Discard the Error packet. */ |
---|
352 | nakstate = 1; /* Can send NAKs from here. */ |
---|
353 | BEGIN vstate; |
---|
354 | } |
---|
355 | } |
---|
356 | |
---|
357 | <get>Y { /* Resend of previous I-pkt ACK, same seq number! */ |
---|
358 | srinit(reget, retrieve); /* Send the GET packet again. */ |
---|
359 | } |
---|
360 | |
---|
361 | /* States in which we're being a server */ |
---|
362 | |
---|
363 | <serve,get>I { /* Get I-packet */ |
---|
364 | #ifndef NOSERVER |
---|
365 | spar(rdatap); /* Set parameters from it */ |
---|
366 | ack1(rpar()); /* Respond with our own parameters */ |
---|
367 | pktinit(); /* Reinitialize packet numbers */ |
---|
368 | #endif /* NOSERVER */ |
---|
369 | } |
---|
370 | |
---|
371 | <serve>R { /* Get Receive-Init (GET) */ |
---|
372 | #ifndef NOSERVER |
---|
373 | if (x_login && !x_logged) { |
---|
374 | errpkt((CHAR *)"Login required"); |
---|
375 | SERVE; |
---|
376 | } else if (sgetinit(0) < 0) { |
---|
377 | RESUME; |
---|
378 | } else { |
---|
379 | BEGIN ssinit; |
---|
380 | } |
---|
381 | #endif /* NOSERVER */ |
---|
382 | } |
---|
383 | |
---|
384 | <serve>H { /* GET and DELETE ("retrieve") */ |
---|
385 | #ifndef NOSERVER |
---|
386 | if (x_login && !x_logged) { |
---|
387 | errpkt((CHAR *)"Login required"); |
---|
388 | RESUME; |
---|
389 | } else if (!ENABLED(en_ret)) { |
---|
390 | errpkt((CHAR *)"RETRIEVE disabled - use GET"); |
---|
391 | RESUME; |
---|
392 | } else if (!ENABLED(en_del)) { |
---|
393 | errpkt((CHAR *)"Deleting files disabled - use GET"); |
---|
394 | RESUME; |
---|
395 | } else if (sgetinit(0) < 0) { |
---|
396 | RESUME; |
---|
397 | } else { |
---|
398 | moving = 1; |
---|
399 | BEGIN ssinit; |
---|
400 | } |
---|
401 | #endif /* NOSERVER */ |
---|
402 | } |
---|
403 | |
---|
404 | |
---|
405 | <serve>J { /* Get REGET */ |
---|
406 | #ifndef NOSERVER |
---|
407 | if (x_login && !x_logged) { |
---|
408 | errpkt((CHAR *)"Login required"); |
---|
409 | SERVE; |
---|
410 | } else if (sgetinit(1) < 0) { |
---|
411 | RESUME; |
---|
412 | } else { |
---|
413 | BEGIN ssinit; |
---|
414 | } |
---|
415 | #endif /* NOSERVER */ |
---|
416 | } |
---|
417 | |
---|
418 | <serve>G { /* Generic server command */ |
---|
419 | #ifndef NOSERVER |
---|
420 | srvptr = srvcmd; /* Point to command buffer */ |
---|
421 | decode(rdatap,putsrv,0); /* Decode packet data into it */ |
---|
422 | putsrv(NUL); /* Insert a couple nulls */ |
---|
423 | putsrv(NUL); /* for termination */ |
---|
424 | if (srvcmd[0]) { |
---|
425 | sstate = srvcmd[0]; /* Set requested start state */ |
---|
426 | if (x_login && !x_logged && sstate != 'I') { |
---|
427 | errpkt((CHAR *)"Login required"); |
---|
428 | SERVE; |
---|
429 | } else { |
---|
430 | nakstate = 0; /* Now I'm the sender. */ |
---|
431 | what = W_REMO; /* Doing a REMOTE command. */ |
---|
432 | if (timint < 1) |
---|
433 | timint = chktimo(rtimo,timef); /* Switch to per-packet timer */ |
---|
434 | BEGIN generic; /* Switch to generic command state */ |
---|
435 | } |
---|
436 | } else { |
---|
437 | errpkt((CHAR *)"Badly formed server command"); /* report error */ |
---|
438 | RESUME; /* & go back to server command wait */ |
---|
439 | } |
---|
440 | #endif /* NOSERVER */ |
---|
441 | } |
---|
442 | |
---|
443 | <serve>C { /* Receive Host command */ |
---|
444 | #ifndef NOSERVER |
---|
445 | if (x_login && !x_logged) { |
---|
446 | errpkt((CHAR *)"Login required"); |
---|
447 | SERVE; |
---|
448 | } else |
---|
449 | if (!ENABLED(en_hos)) { |
---|
450 | errpkt((CHAR *)"REMOTE HOST disabled"); |
---|
451 | RESUME; |
---|
452 | } else { |
---|
453 | srvptr = srvcmd; /* Point to command buffer */ |
---|
454 | decode(rdatap,putsrv,0); /* Decode command packet into it */ |
---|
455 | putsrv(NUL); /* Null-terminate */ |
---|
456 | nakstate = 0; /* Now sending, not receiving */ |
---|
457 | if (syscmd((char *)srvcmd,"")) { /* Try to execute the command */ |
---|
458 | what = W_REMO; /* Doing a REMOTE command. */ |
---|
459 | if (timint < 1) |
---|
460 | timint = chktimo(rtimo,timef); /* Switch to per-packet timer */ |
---|
461 | BEGIN ssinit; /* If OK, send back its output */ |
---|
462 | } else { /* Otherwise */ |
---|
463 | errpkt((CHAR *)"Can't do system command"); /* report error */ |
---|
464 | RESUME; /* & go back to server command wait */ |
---|
465 | } |
---|
466 | } |
---|
467 | #endif /* NOSERVER */ |
---|
468 | } |
---|
469 | |
---|
470 | <serve>q { /* User typed Ctrl-C... */ |
---|
471 | #ifndef NOSERVER |
---|
472 | if (!ENABLED(en_fin)) { |
---|
473 | errpkt((CHAR *)"QUIT disabled"); |
---|
474 | RESUME; |
---|
475 | } else { |
---|
476 | success = 0; QUIT; |
---|
477 | } |
---|
478 | #endif /* NOSERVER */ |
---|
479 | } |
---|
480 | |
---|
481 | <serve>N { /* Server got a NAK in command-wait */ |
---|
482 | #ifndef NOSERVER |
---|
483 | errpkt((CHAR *)"Did you say RECEIVE instead of GET?"); |
---|
484 | RESUME; |
---|
485 | #endif /* NOSERVER */ |
---|
486 | } |
---|
487 | |
---|
488 | <serve>. { /* Any other command in this state */ |
---|
489 | #ifndef NOSERVER |
---|
490 | if (c != ('E' - SP) && c != ('Y' - SP)) /* except E and Y packets. */ |
---|
491 | errpkt((CHAR *)"Unimplemented server function"); |
---|
492 | /* If we answer an E with an E, we get an infinite loop. */ |
---|
493 | /* A Y (ACK) can show up here if we sent back a short-form reply to */ |
---|
494 | /* a G packet and it was echoed. ACKs can be safely ignored here. */ |
---|
495 | RESUME; /* Go back to server command wait. */ |
---|
496 | #endif /* NOSERVER */ |
---|
497 | } |
---|
498 | |
---|
499 | <generic>I { /* Login/out */ |
---|
500 | #ifndef NOSERVER |
---|
501 | char f1[LOGINLEN+1], f2[LOGINLEN+1], f3[LOGINLEN+1]; |
---|
502 | CHAR *p; |
---|
503 | int len, i; |
---|
504 | |
---|
505 | f1[0] = NUL; f2[0] = NUL; f3[0] = NUL; |
---|
506 | if (x_login) { /* Login required */ |
---|
507 | len = 0; |
---|
508 | if (srvcmd[1]) /* First length field */ |
---|
509 | len = xunchar(srvcmd[1]); /* Separate the parameters */ |
---|
510 | if (len > 0 && len <= LOGINLEN) { /* Have username */ |
---|
511 | p = srvcmd + 2; /* Point to it */ |
---|
512 | for (i = 0; i < len; i++) /* Copy it */ |
---|
513 | f1[i] = p[i]; |
---|
514 | f1[len] = NUL; /* Terminate it */ |
---|
515 | p += len; /* Point to next length field */ |
---|
516 | if (*p) { /* If we have one */ |
---|
517 | len = xunchar(*p++); /* decode it */ |
---|
518 | if (len > 0 && len <= LOGINLEN) { |
---|
519 | for (i = 0; i < len; i++) /* Same deal for password */ |
---|
520 | f2[i] = p[i]; |
---|
521 | f2[len] = NUL; |
---|
522 | p += len; /* And account */ |
---|
523 | if (*p) { |
---|
524 | len = xunchar(*p++); |
---|
525 | if (len > 0 && len <= LOGINLEN) { |
---|
526 | for (i = 0; i < len; i++) |
---|
527 | f3[i] = p[i]; |
---|
528 | f3[len] = NUL; |
---|
529 | } |
---|
530 | } |
---|
531 | } |
---|
532 | } |
---|
533 | } |
---|
534 | debug(F110,"XXX user",f1,0); |
---|
535 | debug(F110,"XXX pass",f2,0); |
---|
536 | debug(F110,"XXX acct",f3,0); |
---|
537 | if (!f1[0]) { |
---|
538 | if (x_logged) { |
---|
539 | tlog(F110,"Logged out",x_user,0); |
---|
540 | ack1((CHAR *)"Logged out"); |
---|
541 | } else { |
---|
542 | ack1((CHAR *)"You were not logged in"); |
---|
543 | } |
---|
544 | x_logged = 0; |
---|
545 | } else { |
---|
546 | x_logged = 0; |
---|
547 | if (x_user && x_passwd) { /* Username and password must match */ |
---|
548 | if (!strcmp(x_user,f1)) |
---|
549 | if (!strcmp(x_passwd,f2)) |
---|
550 | x_logged = 1; |
---|
551 | } else if (x_user) { /* Only username must match */ |
---|
552 | if (!strcmp(x_user,f1)) |
---|
553 | x_logged = 1; |
---|
554 | } |
---|
555 | if (x_logged) { |
---|
556 | tlog(F110,"Logged in", x_user, 0); |
---|
557 | ack1((CHAR *)"Logged in"); |
---|
558 | } else { |
---|
559 | tlog(F110,"Login failed", f1, 0); |
---|
560 | ack1((CHAR *)"Login failed"); |
---|
561 | } |
---|
562 | } |
---|
563 | } else { |
---|
564 | ack1((CHAR *)"No login required"); |
---|
565 | } |
---|
566 | SERVE; |
---|
567 | #endif /* NOSERVER */ |
---|
568 | } |
---|
569 | |
---|
570 | <generic>C { /* Got REMOTE CD command */ |
---|
571 | #ifndef NOSERVER |
---|
572 | if (!ENABLED(en_cwd)) { |
---|
573 | errpkt((CHAR *)"REMOTE CD disabled"); |
---|
574 | RESUME; |
---|
575 | } else { |
---|
576 | if (!cwd((char *)(srvcmd+1))) errpkt((CHAR *)"Can't change directory"); |
---|
577 | RESUME; /* Back to server command wait */ |
---|
578 | } |
---|
579 | #endif /* NOSERVER */ |
---|
580 | } |
---|
581 | |
---|
582 | <generic>A { /* Got REMOTE PWD command */ |
---|
583 | #ifndef NOSERVER |
---|
584 | if (!ENABLED(en_cwd)) { |
---|
585 | errpkt((CHAR *)"REMOTE CD disabled"); |
---|
586 | RESUME; |
---|
587 | } else { |
---|
588 | if (encstr((CHAR *)zgtdir()) > -1) /* Get & encode current directory */ |
---|
589 | ack1(data); /* If it fits, send it back in ACK */ |
---|
590 | RESUME; /* Back to server command wait */ |
---|
591 | } |
---|
592 | #endif /* NOSERVER */ |
---|
593 | } |
---|
594 | |
---|
595 | <generic>D { /* REMOTE DIRECTORY command */ |
---|
596 | #ifndef NOSERVER |
---|
597 | char *n2; |
---|
598 | if (!ENABLED(en_dir)) { /* If DIR is disabled, */ |
---|
599 | errpkt((CHAR *)"REMOTE DIRECTORY disabled"); /* refuse. */ |
---|
600 | RESUME; |
---|
601 | } else { /* DIR is enabled. */ |
---|
602 | if (!ENABLED(en_cwd)) { /* But CWD is disabled */ |
---|
603 | zstrip((char *)(srvcmd+2),&n2); /* and they included a pathname, */ |
---|
604 | if (strcmp((char *)(srvcmd+2),n2)) { /* so refuse. */ |
---|
605 | errpkt((CHAR *)"Access denied"); |
---|
606 | RESUME; /* Remember, this is not a goto! */ |
---|
607 | } |
---|
608 | } |
---|
609 | if (state == generic) { /* It's OK to go ahead. */ |
---|
610 | #ifdef COMMENT |
---|
611 | n2 = (*(srvcmd+2)) ? DIRCMD : DIRCM2; |
---|
612 | if (syscmd(n2,(char *)(srvcmd+2))) /* If it can be done */ |
---|
613 | #else |
---|
614 | if (snddir((char*)(srvcmd+2))) |
---|
615 | #endif /* COMMENT */ |
---|
616 | BEGIN ssinit; /* send the results back */ |
---|
617 | else { /* otherwise */ |
---|
618 | errpkt((CHAR *)"Can't list directory"); /* report failure, */ |
---|
619 | RESUME; /* return to server command wait */ |
---|
620 | } |
---|
621 | } |
---|
622 | } |
---|
623 | #endif /* NOSERVER */ |
---|
624 | } |
---|
625 | |
---|
626 | <generic>E { /* REMOTE DELETE (Erase) command */ |
---|
627 | #ifndef NOSERVER |
---|
628 | char *n2; |
---|
629 | if (!ENABLED(en_del)) { |
---|
630 | errpkt((CHAR *)"REMOTE DELETE disabled"); |
---|
631 | RESUME; |
---|
632 | } else { /* DELETE is enabled */ |
---|
633 | if (!ENABLED(en_cwd)) { /* but CWD is disabled */ |
---|
634 | zstrip((char *)(srvcmd+2),&n2); /* and they included a pathname, */ |
---|
635 | if (strcmp((char *)(srvcmd+2),n2)) { /* so refuse. */ |
---|
636 | errpkt((CHAR *)"Access denied"); |
---|
637 | RESUME; /* Remember, this is not a goto! */ |
---|
638 | } |
---|
639 | } |
---|
640 | if (state == generic) { /* It's OK to go ahead. */ |
---|
641 | if ( |
---|
642 | #ifdef COMMENT |
---|
643 | syscmd(DELCMD,(char *)(srvcmd+2)) /* Old way */ |
---|
644 | #else |
---|
645 | snddel((char*)(srvcmd+2)) /* New way */ |
---|
646 | #endif /* COMMENT */ |
---|
647 | ) |
---|
648 | BEGIN ssinit; /* If OK send results back */ |
---|
649 | else { /* otherwise */ |
---|
650 | errpkt((CHAR *)"Can't remove file"); /* report failure */ |
---|
651 | RESUME; /* & return to server command wait */ |
---|
652 | } |
---|
653 | } |
---|
654 | } |
---|
655 | #endif /* NOSERVER */ |
---|
656 | } |
---|
657 | |
---|
658 | <generic>F { /* FINISH */ |
---|
659 | #ifndef NOSERVER |
---|
660 | if (!ENABLED(en_fin)) { |
---|
661 | errpkt((CHAR *)"FINISH disabled"); |
---|
662 | RESUME; |
---|
663 | } else { |
---|
664 | ack(); /* Acknowledge */ |
---|
665 | screen(SCR_TC,0,0L,""); /* Display */ |
---|
666 | return(0); /* Done */ |
---|
667 | } |
---|
668 | #endif /* NOSERVER */ |
---|
669 | } |
---|
670 | |
---|
671 | <generic>L { /* BYE */ |
---|
672 | #ifndef NOSERVER |
---|
673 | if (!ENABLED(en_bye)) { |
---|
674 | errpkt((CHAR *)"BYE disabled"); |
---|
675 | RESUME; |
---|
676 | } else { |
---|
677 | ack(); /* Acknowledge */ |
---|
678 | ttres(); /* Reset the terminal */ |
---|
679 | screen(SCR_TC,0,0L,""); /* Display */ |
---|
680 | doclean(); /* Clean up files, etc */ |
---|
681 | #ifdef DEBUG |
---|
682 | debug(F100,"C-Kermit BYE","",0); |
---|
683 | zclose(ZDFILE); |
---|
684 | #endif /* DEBUG */ |
---|
685 | return(zkself()); /* Try to log self out */ |
---|
686 | } |
---|
687 | #endif /* NOSERVER */ |
---|
688 | } |
---|
689 | |
---|
690 | <generic>H { /* REMOTE HELP */ |
---|
691 | #ifndef NOSERVER |
---|
692 | extern char * hlptxt; |
---|
693 | if (sndhlp(hlptxt)) BEGIN ssinit; /* Try to send it */ |
---|
694 | else { /* If not ok, */ |
---|
695 | errpkt((CHAR *)"Can't send help"); /* send error message instead */ |
---|
696 | RESUME; /* and return to server command wait */ |
---|
697 | } |
---|
698 | #endif /* NOSERVER */ |
---|
699 | } |
---|
700 | |
---|
701 | <generic>R { /* REMOTE RENAME */ |
---|
702 | #ifndef NOSERVER |
---|
703 | #ifdef ZRENAME |
---|
704 | char *str1, *str2, f1[256], f2[256]; |
---|
705 | int len1, len2; |
---|
706 | |
---|
707 | if (!ENABLED(en_ren)) { |
---|
708 | errpkt((CHAR *)"REMOTE RENAME disabled"); |
---|
709 | RESUME; |
---|
710 | } else { /* RENAME is enabled */ |
---|
711 | int len1, len2; |
---|
712 | len1 = xunchar(srvcmd[1]); /* Separate the parameters */ |
---|
713 | len2 = xunchar(srvcmd[2+len1]); |
---|
714 | strncpy(f1,(char *)(srvcmd+2),len1); |
---|
715 | f1[len1] = NUL; |
---|
716 | strncpy(f2,(char *)(srvcmd+3+len1),len2); |
---|
717 | f2[len2] = NUL; |
---|
718 | |
---|
719 | len2 = xunchar(srvcmd[2+len1]); |
---|
720 | strncpy(f1,(char *)(srvcmd+2),len1); |
---|
721 | f1[len1] = NUL; |
---|
722 | strncpy(f2,(char *)(srvcmd+3+len1),len2); |
---|
723 | f2[len2] = NUL; |
---|
724 | |
---|
725 | if (!ENABLED(en_cwd)) { /* If CWD is disabled */ |
---|
726 | zstrip(f1,&str1); /* and they included a pathname, */ |
---|
727 | zstrip(f2,&str2); |
---|
728 | if ( strcmp(f1,str1) || strcmp(f2,str2) ) { /* refuse. */ |
---|
729 | errpkt((CHAR *)"Access denied"); |
---|
730 | RESUME; /* Remember, this is not a goto! */ |
---|
731 | } |
---|
732 | } |
---|
733 | if (state == generic) { /* It's OK to go ahead. */ |
---|
734 | if (zrename(f1,f2)) { /* Try */ |
---|
735 | errpkt((CHAR *)"Can't rename file"); /* Give error msg */ |
---|
736 | } else ack(); |
---|
737 | RESUME; /* Wait for next server command */ |
---|
738 | } |
---|
739 | } |
---|
740 | #else /* no ZRENAME */ |
---|
741 | /* Give error message */ |
---|
742 | errpkt((CHAR *)"REMOTE RENAME not available"); |
---|
743 | RESUME; /* Wait for next server command */ |
---|
744 | #endif /* ZRENAME */ |
---|
745 | #endif /* NOSERVER */ |
---|
746 | } |
---|
747 | |
---|
748 | <generic>K { /* REMOTE COPY */ |
---|
749 | #ifndef NOSERVER |
---|
750 | #ifdef ZCOPY |
---|
751 | char *str1, *str2, f1[256], f2[256]; |
---|
752 | int len1, len2; |
---|
753 | if (!ENABLED(en_cpy)) { |
---|
754 | errpkt((CHAR *)"REMOTE COPY disabled"); |
---|
755 | RESUME; |
---|
756 | } else { |
---|
757 | len1 = xunchar(srvcmd[1]); /* Separate the parameters */ |
---|
758 | len2 = xunchar(srvcmd[2+len1]); |
---|
759 | strncpy(f1,(char *)(srvcmd+2),len1); |
---|
760 | f1[len1] = NUL; |
---|
761 | strncpy(f2,(char *)(srvcmd+3+len1),len2); |
---|
762 | f2[len2] = NUL; |
---|
763 | |
---|
764 | if (!ENABLED(en_cwd)) { /* If CWD is disabled */ |
---|
765 | zstrip(f1,&str1); /* and they included a pathname, */ |
---|
766 | zstrip(f2,&str2); |
---|
767 | if (strcmp(f1,str1) || strcmp(f2,str2)) { /* Refuse. */ |
---|
768 | errpkt((CHAR *)"Access denied"); |
---|
769 | RESUME; /* Remember, this is not a goto! */ |
---|
770 | } |
---|
771 | } |
---|
772 | if (state == generic) { /* It's OK to go ahead. */ |
---|
773 | if (zcopy(f1,f2)) { /* Try */ |
---|
774 | errpkt((CHAR *)"Can't copy file"); /* give error message */ |
---|
775 | } else ack(); |
---|
776 | RESUME; /* wait for next server command */ |
---|
777 | } |
---|
778 | } |
---|
779 | #else /* no ZCOPY */ |
---|
780 | errpkt((CHAR *)"REMOTE COPY not available"); /* give error message */ |
---|
781 | RESUME; /* wait for next server command */ |
---|
782 | #endif /* ZCOPY */ |
---|
783 | #endif /* NOSERVER */ |
---|
784 | } |
---|
785 | |
---|
786 | <generic>S { /* REMOTE SET */ |
---|
787 | #ifndef NOSERVER |
---|
788 | if (!ENABLED(en_set)) { |
---|
789 | errpkt((CHAR *)"REMOTE SET disabled"); |
---|
790 | RESUME; |
---|
791 | } else { |
---|
792 | if (remset((char *)(srvcmd+1))) /* Try to do what they ask */ |
---|
793 | ack(); /* If OK, then acknowledge */ |
---|
794 | else /* Otherwise */ |
---|
795 | errpkt((CHAR *)"Unknown REMOTE SET parameter"); /* give error msg */ |
---|
796 | RESUME; /* Return to server command wait */ |
---|
797 | } |
---|
798 | #endif /* NOSERVER */ |
---|
799 | } |
---|
800 | |
---|
801 | <generic>T { /* REMOTE TYPE */ |
---|
802 | #ifndef NOSERVER |
---|
803 | char *n2; |
---|
804 | if (!ENABLED(en_typ)) { |
---|
805 | errpkt((CHAR *)"REMOTE TYPE disabled"); |
---|
806 | RESUME; |
---|
807 | } else { |
---|
808 | if (!ENABLED(en_cwd)) { /* If CWD disabled */ |
---|
809 | zstrip((char *)(srvcmd+2),&n2); /* and they included a pathname, */ |
---|
810 | if (strcmp((char *)(srvcmd+2),n2)) { /* refuse. */ |
---|
811 | errpkt((CHAR *)"Access denied"); |
---|
812 | RESUME; /* Remember, this is not a goto! */ |
---|
813 | } |
---|
814 | } |
---|
815 | if (state == generic) { /* It's OK to go ahead. */ |
---|
816 | binary = XYFT_T; /* Use text mode for this. */ |
---|
817 | if ( /* (RESUME didn't change state) */ |
---|
818 | #ifdef COMMENT |
---|
819 | syscmd(TYPCMD,(char *)(srvcmd+2)) /* Old way */ |
---|
820 | #else |
---|
821 | sndtype((char *)(srvcmd+2)) /* New way */ |
---|
822 | #endif /* COMMENT */ |
---|
823 | ) |
---|
824 | BEGIN ssinit; /* OK */ |
---|
825 | else { /* not OK */ |
---|
826 | errpkt((CHAR *)"Can't type file"); /* give error message */ |
---|
827 | RESUME; /* wait for next server command */ |
---|
828 | } |
---|
829 | } |
---|
830 | } |
---|
831 | #endif /* NOSERVER */ |
---|
832 | } |
---|
833 | |
---|
834 | <generic>U { /* REMOTE SPACE */ |
---|
835 | #ifndef NOSERVER |
---|
836 | if (!ENABLED(en_spa)) { |
---|
837 | errpkt((CHAR *)"REMOTE SPACE disabled"); |
---|
838 | RESUME; |
---|
839 | } else { |
---|
840 | x = srvcmd[1]; /* Get area to check */ |
---|
841 | x = ((x == NUL) || (x == SP) |
---|
842 | #ifdef OS2 |
---|
843 | || (x == '!') || (srvcmd[3] == ':') |
---|
844 | #endif /* OS2 */ |
---|
845 | ); |
---|
846 | if (!x && !ENABLED(en_cwd)) { /* CWD disabled */ |
---|
847 | errpkt((CHAR *)"Access denied"); /* and non-default area given, */ |
---|
848 | RESUME; /* refuse. */ |
---|
849 | } else { |
---|
850 | #ifdef OS2 |
---|
851 | _PROTOTYP(int sndspace,(int)); |
---|
852 | if (sndspace(x ? toupper(srvcmd[2]) : 0)) |
---|
853 | BEGIN ssinit; /* Try to send it */ |
---|
854 | else { /* If not ok, */ |
---|
855 | errpkt((CHAR *)"Can't send space"); /* send error message */ |
---|
856 | RESUME; /* and return to server command wait */ |
---|
857 | } |
---|
858 | #else |
---|
859 | x = (x ? syscmd(SPACMD,"") : syscmd(SPACM2,(char *)(srvcmd+2))); |
---|
860 | if (x) { /* If we got the info */ |
---|
861 | BEGIN ssinit; /* send it */ |
---|
862 | } else { /* otherwise */ |
---|
863 | errpkt((CHAR *)"Can't check space"); /* send error message */ |
---|
864 | RESUME; /* and await next server command */ |
---|
865 | } |
---|
866 | #endif /* OS2 */ |
---|
867 | } |
---|
868 | } |
---|
869 | #endif /* NOSERVER */ |
---|
870 | } |
---|
871 | |
---|
872 | <generic>W { /* REMOTE WHO */ |
---|
873 | #ifndef NOSERVER |
---|
874 | if (!ENABLED(en_who)) { |
---|
875 | errpkt((CHAR *)"REMOTE WHO disabled"); |
---|
876 | RESUME; |
---|
877 | } else { |
---|
878 | #ifdef OS2 |
---|
879 | _PROTOTYP(int sndwho,(char *)); |
---|
880 | if (sndwho((char *)(srvcmd+2))) |
---|
881 | BEGIN ssinit; /* Try to send it */ |
---|
882 | else { /* If not ok, */ |
---|
883 | errpkt((CHAR *)"Can't do who command"); /* send error msg */ |
---|
884 | RESUME; /* and return to server command wait */ |
---|
885 | } |
---|
886 | #else |
---|
887 | if (syscmd(WHOCMD,(char *)(srvcmd+2))) /* The now-familiar scenario. */ |
---|
888 | BEGIN ssinit; |
---|
889 | else { |
---|
890 | errpkt((CHAR *)"Can't do who command"); |
---|
891 | RESUME; |
---|
892 | } |
---|
893 | #endif /* OS2 */ |
---|
894 | } |
---|
895 | #endif /* NOSERVER */ |
---|
896 | } |
---|
897 | |
---|
898 | <generic>V { /* Variable query or set */ |
---|
899 | #ifndef NOSERVER |
---|
900 | #ifndef NOSPL |
---|
901 | _PROTOTYP( int addmac, (char *, char *) ); |
---|
902 | _PROTOTYP( int zzstring, (char *, char **, int *) ); |
---|
903 | char c; |
---|
904 | c = *(srvcmd+2); /* Q = Query, S = Set */ |
---|
905 | if (c == 'Q') { /* Query */ |
---|
906 | if (!ENABLED(en_que)) { /* Security */ |
---|
907 | errpkt((CHAR *)"REMOTE QUERY disabled"); |
---|
908 | RESUME; |
---|
909 | } else { /* Query allowed */ |
---|
910 | int n; char *p, *q; |
---|
911 | qbufp = querybuf; /* Wipe out old stuff */ |
---|
912 | qbufn = 0; |
---|
913 | querybuf[0] = NUL; |
---|
914 | p = (char *) srvcmd + 3; /* Pointer for making wrapper */ |
---|
915 | n = strlen((char *)srvcmd); /* Position of end */ |
---|
916 | c = *(srvcmd+4); /* Which type of variable */ |
---|
917 | |
---|
918 | if (*(srvcmd+6) == CMDQ) { /* Starts with command quote? */ |
---|
919 | p = (char *) srvcmd + 6; /* Take it literally */ |
---|
920 | if (*p == CMDQ) p++; |
---|
921 | } else { /* They played by the rules */ |
---|
922 | if (c == 'K') { /* Kermit variable */ |
---|
923 | int k; |
---|
924 | k = (int) strlen(p); |
---|
925 | if (k > 0 && p[k-1] == ')') { |
---|
926 | p = (char *)(srvcmd + 4); |
---|
927 | *(srvcmd+4) = CMDQ; |
---|
928 | *(srvcmd+5) = 'f'; /* Function, so make it \f...() */ |
---|
929 | } else { |
---|
930 | *(srvcmd+3) = CMDQ; /* Stuff wrapping into buffer */ |
---|
931 | *(srvcmd+4) = 'v'; /* Variable, so make it \v(...) */ |
---|
932 | *(srvcmd+5) = '('; /* around variable name */ |
---|
933 | *(srvcmd+n) = ')'; |
---|
934 | *(srvcmd+n+1) = NUL; |
---|
935 | } |
---|
936 | } else { |
---|
937 | *(srvcmd+3) = CMDQ; /* Stuff wrapping into buffer */ |
---|
938 | *(srvcmd+4) = 'v'; /* Variable, so make it \v(...) */ |
---|
939 | *(srvcmd+5) = '('; /* around variable name */ |
---|
940 | *(srvcmd+n) = ')'; |
---|
941 | *(srvcmd+n+1) = NUL; |
---|
942 | if (c == 'S') { /* System variable */ |
---|
943 | *(srvcmd+4) = '$'; /* so it's \$(...) */ |
---|
944 | } else if (c == 'G') { /* Non-\ Global variable */ |
---|
945 | *(srvcmd+4) = 'm'; /* so wrap it in \m(...) */ |
---|
946 | } |
---|
947 | } |
---|
948 | } /* Now evaluate it */ |
---|
949 | n = QBUFL; /* Max length */ |
---|
950 | q = querybuf; /* Where to put it */ |
---|
951 | if (zzstring(p,&q,&n) < 0) { |
---|
952 | errpkt((n > 0) ? (CHAR *)"Can't get value" |
---|
953 | : (CHAR *)"Value too long" |
---|
954 | ); |
---|
955 | RESUME; |
---|
956 | } else { |
---|
957 | if (encstr((CHAR *)querybuf) > -1) { /* Encode it */ |
---|
958 | ack1(data); /* If it fits, send it back in ACK */ |
---|
959 | RESUME; |
---|
960 | } else if (sndhlp(querybuf)) { /* Long form response */ |
---|
961 | BEGIN ssinit; |
---|
962 | } else { /* sndhlp() fails */ |
---|
963 | errpkt((CHAR *)"Can't send value"); |
---|
964 | RESUME; |
---|
965 | } |
---|
966 | } |
---|
967 | } |
---|
968 | } else if (c == 'S') { /* Set (assign) */ |
---|
969 | if (!ENABLED(en_asg)) { /* Security */ |
---|
970 | errpkt((CHAR *)"REMOTE ASSIGN disabled"); |
---|
971 | RESUME; |
---|
972 | } else { /* OK */ |
---|
973 | int n; |
---|
974 | n = xunchar(*(srvcmd+3)); /* Length of name */ |
---|
975 | n = 3 + n + 1; /* Position of length of value */ |
---|
976 | *(srvcmd+n) = NUL; /* Don't need it */ |
---|
977 | if (addmac((char *)(srvcmd+4),(char *)(srvcmd+n+1)) < 0) |
---|
978 | errpkt((CHAR *)"REMOTE ASSIGN failed"); |
---|
979 | else |
---|
980 | ack(); |
---|
981 | RESUME; |
---|
982 | } |
---|
983 | } else { |
---|
984 | errpkt((CHAR *)"Badly formed server command"); |
---|
985 | RESUME; |
---|
986 | } |
---|
987 | #else |
---|
988 | errpkt((CHAR *)"Variable query/set not available"); |
---|
989 | RESUME; |
---|
990 | #endif /* NOSPL */ |
---|
991 | #endif /* NOSERVER */ |
---|
992 | } |
---|
993 | |
---|
994 | <generic>q { |
---|
995 | #ifndef NOSERVER |
---|
996 | if (!ENABLED(en_fin)) { /* Ctrl-C typed */ |
---|
997 | errpkt((CHAR *)"QUIT disabled"); |
---|
998 | RESUME; |
---|
999 | } else { |
---|
1000 | success = 0; QUIT; |
---|
1001 | } |
---|
1002 | #endif /* NOSERVER */ |
---|
1003 | } |
---|
1004 | |
---|
1005 | <generic>. { /* Anything else in this state... */ |
---|
1006 | #ifndef NOSERVER |
---|
1007 | errpkt((CHAR *)"Unimplemented REMOTE command"); /* Complain */ |
---|
1008 | RESUME; /* and return to server command wait */ |
---|
1009 | #endif /* NOSERVER */ |
---|
1010 | } |
---|
1011 | |
---|
1012 | <rgen>Y { /* Short-Form reply */ |
---|
1013 | #ifndef NOSERVER |
---|
1014 | #ifndef NOSPL |
---|
1015 | if (query) { /* If to query, */ |
---|
1016 | qbufp = querybuf; /* initialize query response buffer */ |
---|
1017 | qbufn = 0; |
---|
1018 | querybuf[0] = NUL; |
---|
1019 | } |
---|
1020 | #endif /* NOSPL */ |
---|
1021 | decode(rdatap,puttrm,0); /* Text is in ACK Data field */ |
---|
1022 | if (rdatap) /* If we had data */ |
---|
1023 | if (*rdatap) |
---|
1024 | conoll(""); /* Then add a CRLF */ |
---|
1025 | if (bye_active && network) { /* I sent a BYE command and got */ |
---|
1026 | msleep(500); /* the ACK... */ |
---|
1027 | tthang(); |
---|
1028 | } |
---|
1029 | success = 1; |
---|
1030 | RESUME; |
---|
1031 | #endif /* NOSERVER */ |
---|
1032 | } |
---|
1033 | |
---|
1034 | <rgen,rfile>F { /* File header */ |
---|
1035 | xflg = 0; /* Not screen data */ |
---|
1036 | if (!rcvfil(filnam)) { /* Figure out local filename */ |
---|
1037 | errpkt((CHAR *)rf_err); /* Trouble */ |
---|
1038 | screen(SCR_EM,0,0L,rf_err); |
---|
1039 | RESUME; |
---|
1040 | } else { /* Real file, OK to receive */ |
---|
1041 | if (filcnt == 1) /* rcvfil set this to 1 for 1st file */ |
---|
1042 | crc16 = 0L; /* Clear file CRC */ |
---|
1043 | #ifndef NOFULLNAME |
---|
1044 | #ifdef ZFNQFP /* Because of zfnqfp() */ |
---|
1045 | #ifdef BIGBUFOK /* Because it's another 1K buffer */ |
---|
1046 | #define USEFULLNAME /* Memory to burn - do it */ |
---|
1047 | #endif /* BIGBUFOK */ |
---|
1048 | #endif /* ZFNQFP */ |
---|
1049 | #endif /* NOFULLNAME */ |
---|
1050 | |
---|
1051 | #ifdef USEFULLNAME /* Name to send back in ACK */ |
---|
1052 | if (!isabsolute(filnam)) { |
---|
1053 | CHAR tmpbuf[91]; /* Must fit in ACK Data field */ |
---|
1054 | struct zfnfp * fnp; |
---|
1055 | fnp = zfnqfp(filnam,90,(char *)tmpbuf); |
---|
1056 | encstr(fnp ? tmpbuf: (CHAR *)filnam); /* Send the full pathname */ |
---|
1057 | } else |
---|
1058 | #endif /* USEFULLNAME */ |
---|
1059 | encstr((CHAR *)filnam); /* Encode the local filename */ |
---|
1060 | |
---|
1061 | ack1(data); /* Send it back in ACK */ |
---|
1062 | initattr(&iattr); /* Clear file attribute structure */ |
---|
1063 | if (window(wslotn) < 0) { /* Allocate negotiated window slots */ |
---|
1064 | errpkt((CHAR *)"Can't open window"); |
---|
1065 | RESUME; |
---|
1066 | } |
---|
1067 | BEGIN rattr; /* Now expect Attribute packets */ |
---|
1068 | } |
---|
1069 | } |
---|
1070 | |
---|
1071 | <rgen,rfile>X { /* X-packet instead of file header */ |
---|
1072 | xflg = 1; /* Screen data */ |
---|
1073 | ack(); /* Acknowledge the X-packet */ |
---|
1074 | initattr(&iattr); /* Initialize attribute structure */ |
---|
1075 | if (window(wslotn) < 0) { /* allocate negotiated window slots */ |
---|
1076 | errpkt((CHAR *)"Can't open window"); |
---|
1077 | RESUME; |
---|
1078 | } |
---|
1079 | #ifndef NOSPL |
---|
1080 | if (query) { /* If this is the response to */ |
---|
1081 | qbufp = querybuf; /* a query that we sent, initialize */ |
---|
1082 | qbufn = 0; /* the response buffer */ |
---|
1083 | querybuf[0] = NUL; |
---|
1084 | } |
---|
1085 | #endif /* NOSPL */ |
---|
1086 | what = W_REMO; /* we're doing a REMOTE command */ |
---|
1087 | BEGIN rattr; /* Expect Attribute packets */ |
---|
1088 | } |
---|
1089 | |
---|
1090 | <rattr>A { /* Attribute packet */ |
---|
1091 | if (gattr(rdatap,&iattr) == 0) { /* Read into attribute structure */ |
---|
1092 | #ifdef CK_RESEND |
---|
1093 | ack1((CHAR *)iattr.reply.val); /* Reply with data */ |
---|
1094 | #else |
---|
1095 | ack(); /* If OK, acknowledge */ |
---|
1096 | #endif /* CK_RESEND */ |
---|
1097 | } else { /* Otherwise */ |
---|
1098 | ack1((CHAR *)iattr.reply.val); /* refuse to accept the file */ |
---|
1099 | screen(SCR_ST,ST_REFU,0L,getreason(iattr.reply.val)); /* give reason */ |
---|
1100 | } |
---|
1101 | } |
---|
1102 | |
---|
1103 | <rattr>D { /* First data packet */ |
---|
1104 | if (discard) { /* if we're discarding the file */ |
---|
1105 | ack1((CHAR *)"X"); /* just ack the data like this. */ |
---|
1106 | BEGIN rdata; /* and wait for more data packets. */ |
---|
1107 | } else { /* Not discarding. */ |
---|
1108 | rf_err = "Can't open file"; |
---|
1109 | if (xflg) { /* If screen data */ |
---|
1110 | if (remfile) { /* redirected to file */ |
---|
1111 | if (rempipe) /* or pipe */ |
---|
1112 | x = zxcmd(ZOFILE,remdest); /* Pipe: start command */ |
---|
1113 | else |
---|
1114 | x = opena(remdest,&iattr); /* File: open with attributes */ |
---|
1115 | } else { /* otherwise */ |
---|
1116 | x = opent(&iattr); /* "open" the screen */ |
---|
1117 | } |
---|
1118 | } else { /* otherwise */ |
---|
1119 | x = opena(filnam,&iattr); /* open the file, with attributes */ |
---|
1120 | } |
---|
1121 | if (x) { /* If file was opened ok */ |
---|
1122 | if (decode(rdatap, |
---|
1123 | #ifndef NOSPL |
---|
1124 | query ? puttrm : |
---|
1125 | #endif /* NOSPL */ |
---|
1126 | putfil, 1) < 0) { |
---|
1127 | |
---|
1128 | errpkt((CHAR *)"Error writing data"); |
---|
1129 | RESUME; |
---|
1130 | } |
---|
1131 | ack(); /* acknowledge it */ |
---|
1132 | BEGIN rdata; /* and switch to receive-data state */ |
---|
1133 | } else { /* otherwise */ |
---|
1134 | errpkt((CHAR *) rf_err); /* send error message */ |
---|
1135 | RESUME; /* and quit. */ |
---|
1136 | } |
---|
1137 | } |
---|
1138 | } |
---|
1139 | |
---|
1140 | <rfile>B { /* EOT, no more files */ |
---|
1141 | ack(); /* Acknowledge */ |
---|
1142 | tsecs = gtimer(); /* Get timing for statistics */ |
---|
1143 | reot(); /* Do EOT things */ |
---|
1144 | #ifdef CK_TMPDIR |
---|
1145 | /* If we were cd'd temporarily to another device or directory ... */ |
---|
1146 | if (f_tmpdir) { |
---|
1147 | int x; |
---|
1148 | x = zchdir((char *) savdir); /* ... restore previous directory */ |
---|
1149 | f_tmpdir = 0; /* and remember we did it. */ |
---|
1150 | debug(F111,"ckcpro.w B tmpdir restoring",savdir,x); |
---|
1151 | } |
---|
1152 | #endif /* CK_TMPDIR */ |
---|
1153 | RESUME; /* and quit */ |
---|
1154 | } |
---|
1155 | |
---|
1156 | <rdata>D { /* Data packet */ |
---|
1157 | if (cxseen || discard) /* If file interrupt */ |
---|
1158 | ack1((CHAR *)"X"); /* put "X" in ACK */ |
---|
1159 | else if (czseen) /* If file-group interrupt */ |
---|
1160 | ack1((CHAR *)"Z"); /* put "Z" in ACK */ |
---|
1161 | else if (decode(rdatap, |
---|
1162 | #ifndef NOSPL |
---|
1163 | query ? puttrm : |
---|
1164 | #endif /* NOSPL */ |
---|
1165 | putfil, 1) < 0) { |
---|
1166 | errpkt((CHAR *)"Error writing data"); /* If failure, */ |
---|
1167 | clsof(!keep); /* Close & keep/discard the file */ |
---|
1168 | RESUME; /* Send ACK only after data */ |
---|
1169 | } else ack(); /* written to file OK. */ |
---|
1170 | } |
---|
1171 | |
---|
1172 | <rattr>Z { /* EOF immediately after A-Packet. */ |
---|
1173 | rf_err = "Can't create file"; |
---|
1174 | if (discard) { /* Discarding a real file... */ |
---|
1175 | x = 1; |
---|
1176 | } else if (xflg) { /* If screen data */ |
---|
1177 | if (remfile) { /* redirected to file */ |
---|
1178 | if (rempipe) /* or pipe */ |
---|
1179 | x = zxcmd(ZOFILE,remdest); /* Pipe: start command */ |
---|
1180 | else |
---|
1181 | x = opena(remdest,&iattr); /* File: open with attributes */ |
---|
1182 | } else { /* otherwise */ |
---|
1183 | x = opent(&iattr); /* "open" the screen */ |
---|
1184 | } |
---|
1185 | } else { /* otherwise */ |
---|
1186 | x = opena(filnam,&iattr); /* open the file, with attributes */ |
---|
1187 | } |
---|
1188 | if (!x || reof(filnam, &iattr) < 0) { /* Now close & dispose of the file */ |
---|
1189 | errpkt((CHAR *) rf_err); /* If problem, send error msg */ |
---|
1190 | RESUME; /* and quit */ |
---|
1191 | } else { /* otherwise */ |
---|
1192 | ack(); /* acknowledge the EOF packet */ |
---|
1193 | BEGIN rfile; /* and await another file */ |
---|
1194 | } |
---|
1195 | } |
---|
1196 | |
---|
1197 | <rdata>Z { /* End Of File (EOF) Packet */ |
---|
1198 | /* wslots = 1; */ /* Window size back to 1 */ |
---|
1199 | #ifndef COHERENT |
---|
1200 | /* |
---|
1201 | Coherent compiler blows up on this switch() statement. |
---|
1202 | */ |
---|
1203 | x = reof(filnam, &iattr); /* Handle the EOF packet */ |
---|
1204 | switch (x) { /* reof() sets the success flag */ |
---|
1205 | case -3: /* If problem, send error msg */ |
---|
1206 | errpkt((CHAR *)"Can't print file"); /* Fatal */ |
---|
1207 | RESUME; |
---|
1208 | break; |
---|
1209 | case -2: |
---|
1210 | errpkt((CHAR *)"Can't mail file"); /* Fatal */ |
---|
1211 | RESUME; |
---|
1212 | break; |
---|
1213 | case 2: |
---|
1214 | case 3: |
---|
1215 | screen(SCR_EM,0,0L,"Can't delete temp file"); /* Not fatal */ |
---|
1216 | RESUME; |
---|
1217 | break; |
---|
1218 | default: |
---|
1219 | if (x < 0) { /* Fatal */ |
---|
1220 | errpkt((CHAR *)"Can't close file"); |
---|
1221 | RESUME; |
---|
1222 | } else { /* Success */ |
---|
1223 | #ifndef NOSPL |
---|
1224 | if (query) /* Query reponses generally */ |
---|
1225 | conoll(""); /* don't have line terminators */ |
---|
1226 | #endif /* NOSPL */ |
---|
1227 | ack(); /* Acknowledge the EOF packet */ |
---|
1228 | BEGIN rfile; /* and await another file */ |
---|
1229 | } |
---|
1230 | } |
---|
1231 | #else |
---|
1232 | if (reof(filnam, &iattr) < 0) { /* Close and dispose of the file */ |
---|
1233 | errpkt((CHAR *)"Error at end of file"); |
---|
1234 | RESUME; |
---|
1235 | } else { /* reof() sets success flag */ |
---|
1236 | ack(); |
---|
1237 | BEGIN rfile; |
---|
1238 | } |
---|
1239 | #endif /* COHERENT */ |
---|
1240 | } |
---|
1241 | |
---|
1242 | <ssinit>Y { /* ACK for Send-Init */ |
---|
1243 | spar(rdatap); /* set parameters from it */ |
---|
1244 | bctu = bctr; /* switch to agreed-upon block check */ |
---|
1245 | bctl = (bctu == 4) ? 2 : bctu; /* Set block-check length */ |
---|
1246 | #ifdef CK_RESEND |
---|
1247 | if ((sendmode == SM_RESEND) && (!atcapu || !rscapu)) { /* RESEND */ |
---|
1248 | errpkt((CHAR *) "RESEND capabilities not negotiated"); |
---|
1249 | ermsg("RESEND capabilities not negotiated"); |
---|
1250 | RESUME; |
---|
1251 | } else { |
---|
1252 | #endif /* CK_RESEND */ |
---|
1253 | what = W_SEND; /* Remember we're sending */ |
---|
1254 | x = sfile(xflg); /* Send X or F header packet */ |
---|
1255 | if (x) { /* If the packet was sent OK */ |
---|
1256 | if (!xflg && filcnt == 1) /* and it's a real file */ |
---|
1257 | crc16 = 0L; /* Clear the file CRC */ |
---|
1258 | resetc(); /* reset per-transaction counters */ |
---|
1259 | rtimer(); /* reset timers */ |
---|
1260 | BEGIN ssfile; /* and switch to receive-file state */ |
---|
1261 | } else { /* otherwise send error msg & quit */ |
---|
1262 | s = xflg ? "Can't execute command" : "Can't open file"; |
---|
1263 | errpkt((CHAR *)s); |
---|
1264 | RESUME; |
---|
1265 | } |
---|
1266 | #ifdef CK_RESEND |
---|
1267 | } |
---|
1268 | #endif /* CK_RESEND */ |
---|
1269 | } |
---|
1270 | |
---|
1271 | /* |
---|
1272 | These states are necessary to handle the case where we get a server command |
---|
1273 | packet (R, G, or C) reply with an S packet, but the client retransmits the |
---|
1274 | command packet. The input() function doesn't catch this because the packet |
---|
1275 | number is still zero. |
---|
1276 | */ |
---|
1277 | <ssinit>R { /* R packet was retransmitted. */ |
---|
1278 | xsinit(); /* Resend packet 0 */ |
---|
1279 | } |
---|
1280 | |
---|
1281 | <ssinit>G { /* Same deal if G packet comes again */ |
---|
1282 | xsinit(); |
---|
1283 | } |
---|
1284 | |
---|
1285 | <ssinit>C { /* Same deal if C packet comes again */ |
---|
1286 | xsinit(); |
---|
1287 | } |
---|
1288 | |
---|
1289 | <ssfile>Y { /* ACK for F packet */ |
---|
1290 | srvptr = srvcmd; /* Point to string buffer */ |
---|
1291 | decode(rdatap,putsrv,0); /* Decode data field, if any */ |
---|
1292 | putsrv(NUL); /* Terminate with null */ |
---|
1293 | ffc = 0L; /* Reset file byte counter */ |
---|
1294 | if (*srvcmd) { /* If remote name was recorded */ |
---|
1295 | if (sendmode != SM_RESEND) { |
---|
1296 | if (fdispla == XYFD_C) |
---|
1297 | screen(SCR_AN,0,0L,(char *)srvcmd); |
---|
1298 | tlog(F110," remote name:",(char *) srvcmd,0L); |
---|
1299 | } |
---|
1300 | } |
---|
1301 | if (atcapu) { /* If attributes are to be used */ |
---|
1302 | if (sattr(xflg | stdinf) < 0) { /* set and send them */ |
---|
1303 | errpkt((CHAR *)"Can't send attributes"); /* if problem, say so */ |
---|
1304 | RESUME; /* and quit */ |
---|
1305 | } else BEGIN ssattr; /* if ok, switch to attribute state */ |
---|
1306 | } else { |
---|
1307 | if (window(wslotn) < 0) { |
---|
1308 | errpkt((CHAR *)"Can't open window"); |
---|
1309 | RESUME; |
---|
1310 | } |
---|
1311 | if ((x = sdata()) == -2) { /* No attributes, send data */ |
---|
1312 | return(success = 0); /* Failed */ |
---|
1313 | } else if (x == -1) { /* EOF (eh?) */ |
---|
1314 | clsif(); /* If not ok, close input file, */ |
---|
1315 | window(1); /* put window size back to 1, */ |
---|
1316 | seof((CHAR *)""); /* send EOF packet, */ |
---|
1317 | BEGIN sseof; /* and switch to EOF state. */ |
---|
1318 | } else BEGIN ssdata; /* All ok, switch to send-data state */ |
---|
1319 | } |
---|
1320 | } |
---|
1321 | |
---|
1322 | <ssattr>Y { /* Got ACK to A packet */ |
---|
1323 | ffc = 0L; /* Reset file byte counter */ |
---|
1324 | if (rsattr(rdatap) < 0) { /* Was the file refused? */ |
---|
1325 | discard = 1; /* Set the discard flag */ |
---|
1326 | clsif(); /* Close the file */ |
---|
1327 | sxeof((CHAR *)"D"); /* send EOF with "discard" code */ |
---|
1328 | BEGIN sseof; /* switch to send-EOF state */ |
---|
1329 | } else { |
---|
1330 | if (window(wslotn) < 0) { /* Allocate negotiated window slots */ |
---|
1331 | errpkt((CHAR *)"Can't open window"); |
---|
1332 | RESUME; |
---|
1333 | } |
---|
1334 | if ((x = sdata()) == -2) { /* File accepted, send data */ |
---|
1335 | return(success = 0); /* Failed */ |
---|
1336 | } else if (x == -1) { /* EOF */ |
---|
1337 | clsif(); /* If not ok, close input file, */ |
---|
1338 | window(1); /* put window size back to 1, */ |
---|
1339 | seof((CHAR *)""); /* send EOF packet, */ |
---|
1340 | BEGIN sseof; /* and switch to EOF state. */ |
---|
1341 | } else BEGIN ssdata; /* All ok, switch to send-data state */ |
---|
1342 | } |
---|
1343 | } |
---|
1344 | |
---|
1345 | <ssdata>Y { /* Got ACK to Data packet */ |
---|
1346 | canned(rdatap); /* Check if file transfer cancelled */ |
---|
1347 | if ((x = sdata()) == -2) { /* Try to send next data */ |
---|
1348 | return(success = 0); /* Failed */ |
---|
1349 | } else if (x == -1) { /* EOF - finished sending data */ |
---|
1350 | clsif(); /* Close file */ |
---|
1351 | window(1); /* Set window size back to 1... */ |
---|
1352 | if (cxseen || czseen) /* If interrupted */ |
---|
1353 | seof((CHAR *)"D"); /* send special EOF packet */ |
---|
1354 | else /* otherwise */ |
---|
1355 | seof((CHAR *)""); /* regular EOF packet */ |
---|
1356 | BEGIN sseof; /* and enter send-eof state */ |
---|
1357 | } |
---|
1358 | } |
---|
1359 | |
---|
1360 | <sseof>Y { /* Got ACK to EOF */ |
---|
1361 | success = (cxseen == 0 && czseen == 0); /* Transfer status... */ |
---|
1362 | if (success && rejection > 0) /* If rejected, succeed if */ |
---|
1363 | if (rejection != '#' && /* reason was date */ |
---|
1364 | rejection != 1 && rejection != '?') /* or name; */ |
---|
1365 | success = 0; /* fail otherwise. */ |
---|
1366 | cxseen = 0; /* This goes back to zero. */ |
---|
1367 | if (success && moving) { /* If MOVE'ing */ |
---|
1368 | tlog(F110," deleting",filnam,0); /* delete the file */ |
---|
1369 | zdelet(filnam); |
---|
1370 | } |
---|
1371 | if (gnfile() > 0) { /* Any more files to send? */ |
---|
1372 | if (sfile(xflg)) /* Yes, try to send next file header */ |
---|
1373 | BEGIN ssfile; /* if ok, enter send-file state */ |
---|
1374 | else { /* otherwise */ |
---|
1375 | errpkt((CHAR *)"Can't open file"); /* send error message */ |
---|
1376 | RESUME; /* and quit */ |
---|
1377 | } |
---|
1378 | } else { /* No next file */ |
---|
1379 | tsecs = gtimer(); /* get statistics timers */ |
---|
1380 | seot(); /* send EOT packet */ |
---|
1381 | BEGIN sseot; /* enter send-eot state */ |
---|
1382 | } |
---|
1383 | } |
---|
1384 | |
---|
1385 | <sseot>Y { /* Got ACK to EOT */ |
---|
1386 | debug(F101,"sseot justone","",justone); |
---|
1387 | RESUME; /* All done, just quit */ |
---|
1388 | } |
---|
1389 | |
---|
1390 | E { /* Got Error packet, in any state */ |
---|
1391 | char *s = ""; |
---|
1392 | if (pktmsg) /* Or we sent one. */ |
---|
1393 | if (*pktmsg) /* If so, this was the message. */ |
---|
1394 | s = (char *)pktmsg; |
---|
1395 | if (!*s) /* We received an Error packet */ |
---|
1396 | s = (char *)rdatap; /* with this message. */ |
---|
1397 | if (!*s) /* Hopefully we'll never see this. */ |
---|
1398 | s = "Unknown error"; |
---|
1399 | ermsg(s); /* Issue the message. */ |
---|
1400 | success = 0; /* For IF SUCCESS/FAIL. */ |
---|
1401 | debug(F101,"ckcpro.w justone at E pkt","",justone); |
---|
1402 | x = quiet; quiet = 1; /* Close files silently, */ |
---|
1403 | clsif(); clsof(1); /* discarding any output file. */ |
---|
1404 | tsecs = gtimer(); /* Get timers */ |
---|
1405 | quiet = x; /* restore quiet state */ |
---|
1406 | /* |
---|
1407 | If we are executing commands from a command file or macro, let the command |
---|
1408 | file or macro decide whether to exit, based on SET { TAKE, MACRO } ERROR. |
---|
1409 | */ |
---|
1410 | if ( |
---|
1411 | #ifndef NOSPL |
---|
1412 | cmdlvl == 0 |
---|
1413 | #else |
---|
1414 | tlevel < 0 |
---|
1415 | #endif /* NOSPL */ |
---|
1416 | ) |
---|
1417 | if (backgrd && !server) |
---|
1418 | fatal("Protocol error"); |
---|
1419 | xitsta |= what; /* Save this for doexit(). */ |
---|
1420 | #ifdef CK_TMPDIR |
---|
1421 | /* If we were cd'd temporarily to another device or directory ... */ |
---|
1422 | if (f_tmpdir) { |
---|
1423 | int x; |
---|
1424 | x = zchdir((char *) savdir); /* ... restore previous directory */ |
---|
1425 | f_tmpdir = 0; /* and remember we did it. */ |
---|
1426 | debug(F111,"ckcpro.w E tmpdir restoring",savdir,x); |
---|
1427 | } |
---|
1428 | #endif /* CK_TMPDIR */ |
---|
1429 | RESUME; |
---|
1430 | } |
---|
1431 | |
---|
1432 | q { success = 0; QUIT; } /* Ctrl-C interrupt during packets. */ |
---|
1433 | |
---|
1434 | . { /* Anything not accounted for above */ |
---|
1435 | errpkt((CHAR *)"Unexpected packet type"); /* Give error message */ |
---|
1436 | xitsta |= what; /* Save this for doexit(). */ |
---|
1437 | RESUME; /* and quit */ |
---|
1438 | } |
---|
1439 | %% |
---|
1440 | |
---|
1441 | /* P R O T O -- Protocol entry function */ |
---|
1442 | |
---|
1443 | VOID |
---|
1444 | proto() { |
---|
1445 | extern int b_save, f_save; |
---|
1446 | #ifdef OS2 |
---|
1447 | extern int cursorena[], cursor_save; |
---|
1448 | extern BYTE vmode; |
---|
1449 | #endif /* OS2 */ |
---|
1450 | /* |
---|
1451 | This is simply a wrapper for the real protocol function just below, |
---|
1452 | that saves any items that might be changed automatically by protocol |
---|
1453 | negotiations, but which should not be sticky, and then restores them |
---|
1454 | upon exit from protocol mode. |
---|
1455 | */ |
---|
1456 | #ifdef OS2 |
---|
1457 | cursor_save = cursorena[vmode] ; |
---|
1458 | cursorena[vmode] = 0 ; |
---|
1459 | #endif /* OS2 */ |
---|
1460 | b_save = binary; /* SET FILE TYPE */ |
---|
1461 | f_save = fncnv; /* SET FILE NAMES */ |
---|
1462 | xxproto(); /* Call the real protocol function */ |
---|
1463 | fncnv = f_save; |
---|
1464 | binary = b_save; |
---|
1465 | #ifdef OS2 |
---|
1466 | cursorena[vmode] = cursor_save ; |
---|
1467 | #endif /* OS2 */ |
---|
1468 | } |
---|
1469 | |
---|
1470 | static VOID |
---|
1471 | xxproto() { |
---|
1472 | |
---|
1473 | int x; |
---|
1474 | long lx; |
---|
1475 | #ifdef CK_XYZ |
---|
1476 | #ifdef XYZ_INTERNAL |
---|
1477 | _PROTOTYP( int pxyz, (int) ); |
---|
1478 | #endif /* XYZ_INTERNAL */ |
---|
1479 | #endif /* CK_XYZ */ |
---|
1480 | |
---|
1481 | debug(F101,"xxproto entry justone","",justone); |
---|
1482 | |
---|
1483 | /* Set up the communication line for file transfer. */ |
---|
1484 | |
---|
1485 | if (local && (speed < 0L) && (network == 0)) { |
---|
1486 | screen(SCR_EM,0,0L,"Sorry, you must 'set speed' first"); |
---|
1487 | return; |
---|
1488 | } |
---|
1489 | x = -1; |
---|
1490 | if (ttopen(ttname,&x,mdmtyp,cdtimo) < 0) { |
---|
1491 | debug(F111,"failed: proto ttopen local",ttname,local); |
---|
1492 | screen(SCR_EM,0,0L,"Can't open line"); |
---|
1493 | success = 0; |
---|
1494 | return; |
---|
1495 | } |
---|
1496 | if (x > -1) local = x; |
---|
1497 | debug(F111,"proto ttopen local",ttname,local); |
---|
1498 | |
---|
1499 | lx = (local && !network) ? speed : -1; |
---|
1500 | #ifdef NETCONN |
---|
1501 | #ifdef CK_SPEED |
---|
1502 | /* |
---|
1503 | If we are a TELNET client, force quoting of IAC. |
---|
1504 | Note hardwired "1" rather than NP_TELNET symbol, so we don't have |
---|
1505 | to schlurp in ckcnet.h. |
---|
1506 | */ |
---|
1507 | if (network && ttnproto == 1) { |
---|
1508 | ctlp[255] = ctlp[CR] = 1; |
---|
1509 | if (parity == 'e' || parity == 'm') ctlp[127] = 1; |
---|
1510 | } |
---|
1511 | #endif /* CK_SPEED */ |
---|
1512 | #endif /* NETCONN */ |
---|
1513 | if (ttpkt(lx,flow,parity) < 0) { /* Put line in packet mode, */ |
---|
1514 | screen(SCR_EM,0,0L,"Can't condition line"); |
---|
1515 | success = 0; |
---|
1516 | return; |
---|
1517 | } |
---|
1518 | /* Send remote side "receive" startup string, if any */ |
---|
1519 | if (local && sstate == 's') { |
---|
1520 | char *s; |
---|
1521 | s = binary ? ptab[protocol].h_b_init : ptab[protocol].h_t_init; |
---|
1522 | if (s) if (*s) { |
---|
1523 | char tmpbuf[356]; |
---|
1524 | int stuff = -1, stuff2 = -1, len = 0; |
---|
1525 | extern int tnlm; |
---|
1526 | |
---|
1527 | sprintf(tmpbuf, s, fspec); /* We need this for XMODEM... */ |
---|
1528 | |
---|
1529 | strcat(tmpbuf, "\015"); |
---|
1530 | if (tnlm) /* TERMINAL NEWLINE ON */ |
---|
1531 | stuff = LF; /* Stuff LF */ |
---|
1532 | #ifdef NETCONN |
---|
1533 | #ifdef TCPSOCKET |
---|
1534 | /* TELNET NEWLINE MODE */ |
---|
1535 | if (network) { |
---|
1536 | if (ttnproto == NP_TELNET) { |
---|
1537 | switch (me_binary ? tn_b_nlm : tn_nlm) { |
---|
1538 | case TNL_CR: |
---|
1539 | break; |
---|
1540 | case TNL_CRNUL: |
---|
1541 | break; |
---|
1542 | case TNL_CRLF: |
---|
1543 | stuff2 = stuff; |
---|
1544 | stuff = LF; |
---|
1545 | break; |
---|
1546 | } |
---|
1547 | } |
---|
1548 | #ifdef RLOGCODE |
---|
1549 | else if (ttnproto == NP_RLOGIN) { |
---|
1550 | switch (tn_b_nlm) { /* Always BINARY */ |
---|
1551 | case TNL_CR: |
---|
1552 | break; |
---|
1553 | case TNL_CRNUL: |
---|
1554 | stuff2 = stuff; |
---|
1555 | stuff = NUL; |
---|
1556 | break; |
---|
1557 | case TNL_CRLF: |
---|
1558 | stuff2 = stuff; |
---|
1559 | stuff = LF; |
---|
1560 | break; |
---|
1561 | } |
---|
1562 | } |
---|
1563 | #endif /* RLOGCODE */ |
---|
1564 | } |
---|
1565 | #endif /* TCPSOCKET */ |
---|
1566 | #endif /* NETCONN */ |
---|
1567 | len = strlen(tmpbuf); |
---|
1568 | if (stuff >= 0) { |
---|
1569 | tmpbuf[len++] = stuff; |
---|
1570 | if (stuff2 >= 0) |
---|
1571 | tmpbuf[len++] = stuff2; |
---|
1572 | tmpbuf[len] = NUL; |
---|
1573 | } |
---|
1574 | ttol((CHAR *)tmpbuf,len); |
---|
1575 | } |
---|
1576 | } |
---|
1577 | #ifdef CK_XYZ |
---|
1578 | if (protocol != PROTO_K) { /* Non-Kermit protocol selected */ |
---|
1579 | char tmpbuf[356]; |
---|
1580 | char * s = ""; |
---|
1581 | #ifdef XYZ_INTERNAL /* Internal */ |
---|
1582 | success = !pxyz(sstate); |
---|
1583 | #else |
---|
1584 | #ifdef CK_REDIR /* External */ |
---|
1585 | switch (sstate) { |
---|
1586 | case 's': /* 'Tis better to SEND... */ |
---|
1587 | s = binary ? ptab[protocol].p_b_scmd : ptab[protocol].p_t_scmd; |
---|
1588 | break; |
---|
1589 | case 'v': /* ... than RECEIVE */ |
---|
1590 | s = binary ? ptab[protocol].p_b_rcmd : ptab[protocol].p_t_rcmd; |
---|
1591 | break; |
---|
1592 | } |
---|
1593 | if (!s) s = ""; |
---|
1594 | if (*s) { |
---|
1595 | sprintf(tmpbuf,s,(sstate == 's') ? fspec : cmarg2); |
---|
1596 | ttruncmd(tmpbuf); |
---|
1597 | } else { |
---|
1598 | printf("?Sorry, no external protocol defined for %s\r\n", |
---|
1599 | ptab[protocol].p_name |
---|
1600 | ); |
---|
1601 | } |
---|
1602 | #else |
---|
1603 | printf( |
---|
1604 | "Sorry, only Kermit protocol is supported in this version of Kermit\n" |
---|
1605 | ); |
---|
1606 | #endif /* CK_REDIR */ |
---|
1607 | #endif /* XYZ_INTERNAL */ |
---|
1608 | return; |
---|
1609 | } |
---|
1610 | #endif /* CK_XYZ */ |
---|
1611 | |
---|
1612 | #ifdef NTSIGX |
---|
1613 | conraw(); |
---|
1614 | connoi(); |
---|
1615 | #else |
---|
1616 | if (!local) |
---|
1617 | connoi(); /* No console interrupts if remote */ |
---|
1618 | #endif /* NTSIG */ |
---|
1619 | |
---|
1620 | if (sstate == 'x') { /* If entering server mode, */ |
---|
1621 | server = 1; /* set flag, */ |
---|
1622 | debug(F101,"server backgrd","",backgrd); |
---|
1623 | debug(F101,"server quiet","",quiet); |
---|
1624 | if (!quiet && !backgrd) { |
---|
1625 | debug(F100,"SHOULD NOT SEE THIS IF IN BACKGROUND!","",0); |
---|
1626 | if (!local) { /* and issue appropriate message. */ |
---|
1627 | conoll(srvtxt); |
---|
1628 | conoll("KERMIT READY TO SERVE..."); |
---|
1629 | } else { |
---|
1630 | conol("Entering server mode on "); |
---|
1631 | conoll(ttname); |
---|
1632 | conoll("Type Ctrl-C to quit."); |
---|
1633 | if (srvdis) intmsg(-1L); |
---|
1634 | } |
---|
1635 | } |
---|
1636 | #ifdef TCPSOCKET |
---|
1637 | #ifndef NOLISTEN |
---|
1638 | #ifndef NOSPL |
---|
1639 | if (network && tcpsrfd > 0) { |
---|
1640 | dooutput("KERMIT READY TO SERVE...\015\012"); |
---|
1641 | } |
---|
1642 | #endif /* NOSPL */ |
---|
1643 | #endif /* NOLISTEN */ |
---|
1644 | #endif /* TCPSOCKET */ |
---|
1645 | } else server = 0; |
---|
1646 | #ifdef VMS |
---|
1647 | if (!quiet && !backgrd) /* So message doesn't overwrite prompt */ |
---|
1648 | conoll(""); |
---|
1649 | if (local) conres(); /* So Ctrl-C will work */ |
---|
1650 | #endif /* VMS */ |
---|
1651 | /* |
---|
1652 | If in remote mode, not shushed, not in background, and at top command level, |
---|
1653 | issue a helpful message telling what to do... |
---|
1654 | */ |
---|
1655 | if (!local && !quiet && !backgrd) { |
---|
1656 | if (sstate == 'v') { |
---|
1657 | conoll("Return to your local Kermit and give a SEND command."); |
---|
1658 | conoll(""); |
---|
1659 | conoll("KERMIT READY TO RECEIVE..."); |
---|
1660 | } else if (sstate == 's') { |
---|
1661 | conoll("Return to your local Kermit and give a RECEIVE command."); |
---|
1662 | conoll(""); |
---|
1663 | conoll("KERMIT READY TO SEND..."); |
---|
1664 | } else if ( sstate == 'g' || sstate == 'r' || sstate == 'h' || |
---|
1665 | sstate == 'j' || sstate == 'c' ) { |
---|
1666 | conoll("Return to your local Kermit and give a SERVER command."); |
---|
1667 | conoll(""); |
---|
1668 | conoll((sstate == 'r' || sstate == 'j' || sstate == 'h') ? |
---|
1669 | "KERMIT READY TO GET..." : |
---|
1670 | "KERMIT READY TO SEND SERVER COMMAND..."); |
---|
1671 | } |
---|
1672 | } |
---|
1673 | #ifdef COMMENT |
---|
1674 | if (!local) sleep(1); |
---|
1675 | #endif /* COMMENT */ |
---|
1676 | /* |
---|
1677 | The 'wart()' function is generated by the wart program. It gets a |
---|
1678 | character from the input() routine and then based on that character and |
---|
1679 | the current state, selects the appropriate action, according to the state |
---|
1680 | table above, which is transformed by the wart program into a big case |
---|
1681 | statement. The function is active for one transaction. |
---|
1682 | */ |
---|
1683 | rtimer(); /* Reset elapsed-time timer */ |
---|
1684 | resetc(); /* & other per-transaction counters. */ |
---|
1685 | |
---|
1686 | debug(F101,"proto calling wart, justone","",justone); |
---|
1687 | |
---|
1688 | wart(); /* Enter the state table switcher. */ |
---|
1689 | |
---|
1690 | if (server) { /* Back from packet protocol. */ |
---|
1691 | if (!quiet && !backgrd) { /* Give appropriate message */ |
---|
1692 | conoll(""); |
---|
1693 | conoll("C-Kermit server done"); |
---|
1694 | } |
---|
1695 | } |
---|
1696 | /* |
---|
1697 | Note: the following is necessary in case we have just done a remote-mode |
---|
1698 | file transfer, in which case the controlling terminal modes have been |
---|
1699 | changed by ttpkt(). In particular, special characters like Ctrl-C and |
---|
1700 | Ctrl-\ might have been turned off (see ttpkt). So this call to ttres() is |
---|
1701 | essential. |
---|
1702 | */ |
---|
1703 | #ifdef OS2 |
---|
1704 | ttres(); /* Reset the communication device */ |
---|
1705 | #else |
---|
1706 | if (!local) { |
---|
1707 | msleep(500); |
---|
1708 | ttres(); /* Reset the communication device */ |
---|
1709 | } |
---|
1710 | #endif /* OS2 */ |
---|
1711 | screen(SCR_TC,0,0L,""); /* Transaction complete */ |
---|
1712 | server = 0; /* Not a server any more */ |
---|
1713 | } |
---|
1714 | |
---|
1715 | static int |
---|
1716 | sgetinit(reget) int reget; { |
---|
1717 | if (!ENABLED(en_get)) { /* Only if not disabled! */ |
---|
1718 | errpkt((CHAR *)"GET disabled"); |
---|
1719 | return(-1); |
---|
1720 | } else { /* OK to go ahead. */ |
---|
1721 | #ifdef WHATAMI |
---|
1722 | debug(F101,"sgetinit whatru","",whatru); |
---|
1723 | if (whatru & WM_FLAG) { /* Did we get WHATAMI info? */ |
---|
1724 | debug(F101,"sgetinit binary (1)","",binary); |
---|
1725 | #ifdef VMS |
---|
1726 | if (binary != XYFT_I && binary != XYFT_L) |
---|
1727 | #else |
---|
1728 | #ifdef OS2 |
---|
1729 | if (binary != XYFT_L) |
---|
1730 | #endif /* OS2 */ |
---|
1731 | #endif /* VMS */ |
---|
1732 | binary = (whatru & WM_FMODE) ? /* Yes, set transfer mode */ |
---|
1733 | XYFT_B : XYFT_T; /* automatically */ |
---|
1734 | debug(F101,"sgetinit binary (2)","",binary); |
---|
1735 | fncnv = (whatru & WM_FNAME) ? 1 : 0; /* And name conversion */ |
---|
1736 | } |
---|
1737 | #endif /* WHATAMI */ |
---|
1738 | srvptr = srvcmd; /* Point to server command buffer */ |
---|
1739 | decode(rdatap,putsrv,0); /* Decode the GET command into it */ |
---|
1740 | /* Accept multiple filespecs */ |
---|
1741 | cmarg2 = ""; /* Don't use cmarg2 */ |
---|
1742 | cmarg = ""; /* Don't use cmarg */ |
---|
1743 | #ifndef NOMSEND /* New way. */ |
---|
1744 | nfils = fnparse((char *)srvcmd); /* Use cmlist instead */ |
---|
1745 | #else |
---|
1746 | nfils = 0 - zxpand((char *)srvcmd); |
---|
1747 | #endif /* NOMSEND */ |
---|
1748 | nakstate = 0; /* Now I'm the sender! */ |
---|
1749 | if (reget) sendmode = SM_RESEND; |
---|
1750 | if (sinit() > 0) { /* Send Send-Init */ |
---|
1751 | timint = chktimo(rtimo,timef); /* Switch to per-packet timer */ |
---|
1752 | return(0); /* If successful, switch state */ |
---|
1753 | } else return(-1); /* Else back to server command wait */ |
---|
1754 | } |
---|
1755 | } |
---|