1 #include "ckcsym.h"
2
3 char *connv = "CONNECT Command for UNIX:fork(), 9.0.117, 14 Jul 2011";
4
5 /* C K U C O N -- Terminal connection to remote system, for UNIX */
6 /*
7 Author: Frank da Cruz <fdc@columbia.edu>,
8 Columbia University Academic Information Systems, New York City.
9
10 Copyright (C) 1985, 2011,
11 Trustees of Columbia University in the City of New York.
12 All rights reserved. See the C-Kermit COPYING.TXT file or the
13 copyright text in the ckcmai.c module for disclaimer and permissions.
14
15 NOTE: This module has been superseded on most platforms by ckucns.c, which
16 uses select() rather than fork() for multiplexing its i/o. This module
17 is still needed for platforms that do not support select(), and also for
18 its X.25 support. Although the two modules share large amounts of code,
19 their structure is radically different and therefore attempts at merging
20 them have so far been unsuccessful. (November 1998.)
21
22 Special thanks to Eduard Vopicka, Prague University of Economics,
23 Czech Republic, for valuable contributions to this module in July 1994,
24 and to Neal P. Murphy of the Motorola Cellular Infrastructure Group in 1996
25 for rearranging the code to allow operation on the BeBox, yet still work
26 in regular UNIX.
27 */
28 #include "ckcdeb.h" /* Common things first */
29
30 #ifndef NOLOCAL
31
32 #ifdef BEOSORBEBOX
33 static double time_started = 0.0;
34 #include <kernel/OS.h>
35 _PROTOTYP( static long concld, (void *) );
36 #else
37 _PROTOTYP( static VOID concld, (void) );
38 #endif /* BEOSORBEBOX */
39
40 #ifdef NEXT
41 #undef NSIG
42 #include <sys/wait.h> /* For wait() */
43 #endif /* NEXT */
44
45 #include <signal.h> /* Signals */
46
47 #ifndef HPUXPRE65
48 #include <errno.h> /* Error number symbols */
49 #else
50 #ifndef ERRNO_INCLUDED
51 #include <errno.h> /* Error number symbols */
52 #endif /* ERRNO_INCLUDED */
53 #endif /* HPUXPRE65 */
54
55 #ifdef ZILOG /* Longjumps */
56 #include <setret.h>
57 #else
58 #include <setjmp.h>
59 #endif /* ZILOG */
60 #include "ckcsig.h"
61
62 /* Kermit-specific includes */
63
64 #include "ckcasc.h" /* ASCII characters */
65 #include "ckcker.h" /* Kermit things */
66 #include "ckucmd.h" /* For xxesc() prototype */
67 #include "ckcnet.h" /* Network symbols */
68 #ifndef NOCSETS
69 #include "ckcxla.h" /* Character set translation */
70 #endif /* NOCSETS */
71
72 /* Internal function prototypes */
73
74 _PROTOTYP( VOID ttflux, (void) );
75 _PROTOTYP( VOID doesc, (char) );
76 _PROTOTYP( VOID logchar, (char) );
77 _PROTOTYP( int hconne, (void) );
78 #ifndef NOSHOW
79 _PROTOTYP( VOID shomdm, (void) );
80 #endif /* NOSHOW */
81 _PROTOTYP( static int kbget, (void) );
82 _PROTOTYP( static int pipemsg, (int) );
83 _PROTOTYP( static int ckcputf, (void) );
84 _PROTOTYP( static VOID ck_sndmsg, (void) );
85 /*
86 For inter-fork signaling. Normally we use SIGUSR1, except on SCO, where
87 we use SIGUSR2 because SIGUSR1 is used by the system. You can define
88 CK_FORK_SIG to be whatever other signal you might want to use at compile
89 time. We don't use SIGUSR2 everywhere because in some systems, like
90 UnixWare, the default action for SIGUSR2 is to kill the process that gets it.
91 */
92 #ifndef CK_FORK_SIG
93
94 #ifndef SIGUSR1 /* User-defined signals */
95 #define SIGUSR1 30
96 #endif /* SIGUSR1 */
97
98 #ifndef SIGUSR2
99 #define SIGUSR2 31
100 #endif /* SIGUSR2 */
101
102 #ifdef M_UNIX
103 #define CK_FORK_SIG SIGUSR2 /* SCO - use SIGUSR2 */
104 #else
105 #define CK_FORK_SIG SIGUSR1 /* Others - use SIGUSR1 */
106 #endif /* M_UNIX */
107
108 #endif /* CK_FORK_SIG */
109
110 /* External variables */
111
112 extern struct ck_p ptab[];
113
114 extern int local, escape, duplex, parity, flow, seslog, sessft, debses,
115 mdmtyp, ttnproto, cmask, cmdmsk, network, nettype, deblog, sosi, tnlm,
116 xitsta, what, ttyfd, ttpipe, quiet, backgrd, pflag, tt_crd, tt_lfd,
117 tn_nlm, ttfdflg,
118 tt_escape, justone, carrier, hwparity;
119
120 extern long speed;
121 extern char ttname[], sesfil[], myhost[], *ccntab[];
122 #ifdef TNCODE
123 extern int tn_b_nlm, tn_rem_echo;
124 #endif /* TNCODE */
125
126 #ifdef CK_TRIGGER
127 extern char * tt_trigger[], * triggerval;
128 #endif /* CK_TRIGGER */
129
130 extern int nopush;
131
132 #ifdef CK_APC
133 extern int apcactive; /* Application Program Command (APC) */
134 extern int apcstatus; /* items ... */
135 static int apclength = 0;
136 #ifdef DCMDBUF
137 extern char *apcbuf;
138 #else
139 extern char apcbuf[];
140 #endif /* DCMDBUF */
141 static int apcbuflen = APCBUFLEN - 2;
142 extern int protocol; /* Auto download */
143 #endif /* CK_APC */
144
145 extern int autodl;
146 #ifdef CK_AUTODL
147 extern CHAR ksbuf[];
148 #endif /* CK_AUTODL */
149
150 #ifdef CK_XYZ
151 #ifdef XYZ_INTERNAL
152 static int zmdlok = 1; /* Zmodem autodownloads available */
153 #else
154 static int zmdlok = 0; /* Depends on external protocol def */
155 #endif /* XYZ_INTERNAL */
156 #else
157 static int zmdlok = 0; /* Not available at all */
158 #endif /* CK_XYZ */
159
160 #ifndef NOSETKEY /* Keyboard mapping */
161 extern KEY *keymap; /* Single-character key map */
162 extern MACRO *macrotab; /* Key macro pointer table */
163 static MACRO kmptr = NULL; /* Pointer to current key macro */
164 #endif /* NOSETKEY */
165
166 /* Global variables local to this module */
167
168 static int
169 quitnow = 0, /* <esc-char>Q was typed */
170 jbset = 0, /* Flag whether jmp buf is set. */
171 dohangup = 0, /* <esc-char>H was typed */
172 sjval, /* Setjump return value */
173 goterr = 0, /* Fork/pipe creation error flag */
174 inshift = 0, /* SO/SI shift states */
175 outshift = 0;
176
177 int active = 0; /* Lower fork active flag */
178
179 static PID_T parent_id = (PID_T)0; /* Process ID of keyboard fork */
180
181 static char ecbuf[10], *ecbp; /* Escape char buffer & pointer */
182
183 #ifdef CK_SMALL
184 #define IBUFL 1536 /* Input buffer length */
185 #else
186 #define IBUFL 4096
187 #endif /* CK_SMALL */
188
189 static int obc = 0; /* Output buffer count */
190
191 #ifndef OXOS
192 #define OBUFL 1024 /* Output buffer length */
193 #else
194 #define OBUFL IBUFL
195 #endif /* OXOS */
196
197 #ifdef BIGBUFOK
198 #define TMPLEN 4096 /* Temporary message buffer length */
199 #else
200 #define TMPLEN 200
201 #endif /* BIGBUFOK */
202
203 #ifdef DYNAMIC
204 static char *ibuf = NULL, *obuf = NULL, *temp = NULL; /* Buffers */
205 #else
206 static char ibuf[IBUFL], obuf[OBUFL], temp[TMPLEN];
207 #endif /* DYNAMIC */
208
209 #ifdef DYNAMIC
210 static char *ibp; /* Input buffer pointer */
211 #else
212 static char *ibp = ibuf; /* Input buffer pointer */
213 #endif /*DYNAMIC */
214 static int ibc = 0; /* Input buffer count */
215
216 #ifdef DYNAMIC
217 static char *obp; /* Output buffer pointer */
218 #else
219 static char *obp = obuf; /* Output buffer pointer */
220 #endif /* DYNAMIC */
221
222 /* X.25 items */
223
224 #ifdef ANYX25
225 static char *p; /* General purpose pointer */
226 char x25ibuf[MAXIX25]; /* Input buffer */
227 char x25obuf[MAXOX25]; /* Output buffer */
228 int ibufl; /* Length of input buffer */
229 int obufl; /* Length of output buffer */
230 unsigned char tosend = 0;
231 int linkid, lcn;
232 static int dox25clr = 0;
233 #ifndef IBMX25
234 extern CHAR padparms[];
235 #endif /* IBMX25 */
236 #endif /* ANYX25 */
237
238 static int xpipe[2] = {-1, -1}; /* Pipe descriptor for child-parent messages */
239 static PID_T pid = (PID_T) 0; /* Process ID of child */
240
241 /* Character-set items */
242
243 static int unicode = 0;
244
245 static int escseq = 0; /* 1 = Recognizer is active */
246 int inesc = 0; /* State of sequence recognizer */
247 int oldesc = -1; /* Previous state of recognizer */
248
249 #define OUTXBUFSIZ 15
250 static CHAR inxbuf[OUTXBUFSIZ+1]; /* Host-to-screen expansion buffer */
251 static int inxcount = 0; /* and count */
252 static CHAR outxbuf[OUTXBUFSIZ+1]; /* Keyboard-to-host expansion buf */
253 static int outxcount = 0; /* and count */
254
255 #ifndef NOCSETS
256 #ifdef CK_ANSIC /* ANSI C prototypes... */
257 extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* Character set */
258 extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* translation functions */
259 static CHAR (*sxo)(CHAR); /* Local translation functions */
260 static CHAR (*rxo)(CHAR); /* for output (sending) terminal chars */
261 static CHAR (*sxi)(CHAR); /* and for input (receiving) terminal chars. */
262 static CHAR (*rxi)(CHAR);
263 #else /* Not ANSI C... */
264 extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])(); /* Character set */
265 extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(); /* translation functions. */
266 static CHAR (*sxo)(); /* Local translation functions */
267 static CHAR (*rxo)(); /* for output (sending) terminal chars */
268 static CHAR (*sxi)(); /* and for input (receiving) terminal chars. */
269 static CHAR (*rxi)();
270 #endif /* CK_ANSIC */
271 extern int language; /* Current language. */
272 static int langsv; /* For remembering language setting. */
273 extern struct csinfo fcsinfo[]; /* File character set info. */
274 extern int tcsr, tcsl; /* Terminal character sets, remote & local. */
275 static int tcs; /* Intermediate ("transfer") character set. */
276 static int tcssize = 0; /* Size of tcs */
277 #ifdef UNICODE /* UTF-8 support */
278 #ifdef CK_ANSIC
279 extern int (*xl_ufc[MAXFCSETS+1])(USHORT); /* Unicode to FCS */
280 extern USHORT (*xl_fcu[MAXFCSETS+1])(CHAR); /* FCS to Unicode */
281 extern int (*xuf)(USHORT); /* Translation function UCS to FCS */
282 extern USHORT (*xfu)(CHAR); /* Translation function FCS to UCS */
283 #else
284 extern int (*xl_ufc[MAXFCSETS+1])();
285 extern USHORT (*xl_fcu[MAXFCSETS+1])();
286 extern int (*xuf)();
287 extern USHORT (*xfu)();
288 #endif /* CK_ANSIC */
289 #endif /* UNICODE */
290 #endif /* NOCSETS */
291
292 /*
293 We do not need to parse and recognize escape sequences if we are being built
294 without character-set support AND without APC support.
295 */
296 #ifdef NOCSETS /* No character sets */
297 #ifndef CK_APC /* No APC */
298 #ifndef NOESCSEQ
299 #define NOESCSEQ /* So no escape sequence recognizer */
300 #endif /* NOESCSEQ */
301 #endif /* CK_APC */
302 #endif /* NOCSETS */
303
304 /* Child process events and messages */
305
306 #define CEV_NO 0 /* No event */
307 #define CEV_HUP 1 /* Communications hangup */
308 #define CEV_PAD 2 /* X.25 - change PAD parameters */
309 #define CEV_DUP 3 /* Toggle duplex */
310 #define CEV_APC 4 /* Execute APC */
311 #ifdef TNCODE
312 #define CEV_MEBIN 5 /* Change of me_binary */
313 #define CEV_UBIN 6 /* Change of u_binary */
314 #endif /* TNCODE */
315 #define CEV_ADL 7 /* Autodownload */
316 #define CEV_AUL 8 /* Autoupload */
317 #define CEV_TRI 9 /* Trigger string */
318
319 #ifdef NOESCSEQ
320 #define chkaes(x) 0
321 #else
322 /*
323 As of edit 178, the CONNECT command skips past ANSI escape sequences to
324 avoid translating the characters within them. This allows the CONNECT
325 command to work correctly with a host that uses a 7-bit ISO 646 national
326 character set, in which characters like '[' would normally be translated
327 into accented characters, ruining the terminal's interpretation (and
328 generation) of escape sequences.
329
330 As of edit 190, the CONNECT command responds to APC escape sequences
331 (ESC _ text ESC \) if the user SETs TERMINAL APC ON or UNCHECKED, and the
332 program was built with CK_APC defined.
333
334 Non-ANSI/ISO-compliant escape sequences are not handled.
335 */
336
337 /* States for the escape-sequence recognizer. */
338
339 #define ES_NORMAL 0 /* Normal, not in an escape sequence */
340 #define ES_GOTESC 1 /* Current character is ESC */
341 #define ES_ESCSEQ 2 /* Inside an escape sequence */
342 #define ES_GOTCSI 3 /* Inside a control sequence */
343 #define ES_STRING 4 /* Inside DCS,OSC,PM, or APC string */
344 #define ES_TERMIN 5 /* 1st char of string terminator */
345
346 /*
347 ANSI escape sequence handling. Only the 7-bit form is treated, because
348 translation is not a problem in the 8-bit environment, in which all GL
349 characters are ASCII and no translation takes place. So we don't check
350 for the 8-bit single-character versions of CSI, DCS, OSC, APC, or ST.
351 Here is the ANSI sequence recognizer state table, followed by the code
352 that implements it.
353
354 Definitions:
355 CAN = Cancel 01/08 Ctrl-X
356 SUB = Substitute 01/10 Ctrl-Z
357 DCS = Device Control Sequence 01/11 05/00 ESC P
358 CSI = Control Sequence Introducer 01/11 05/11 ESC [
359 ST = String Terminator 01/11 05/12 ESC \
360 OSC = Operating System Command 01/11 05/13 ESC ]
361 PM = Privacy Message 01/11 05/14 ESC ^
362 APC = Application Program Command 01/11 05/15 ESC _
363
364 ANSI escape sequence recognizer:
365
366 State Input New State ; Commentary
367
368 NORMAL (start) ; Start in NORMAL state
369
370 (any) CAN NORMAL ; ^X cancels
371 (any) SUB NORMAL ; ^Z cancels
372
373 NORMAL ESC GOTESC ; Begin escape sequence
374 NORMAL other ; NORMAL control or graphic character
375
376 GOTESC ESC ; Start again
377 GOTESC [ GOTCSI ; CSI
378 GOTESC P STRING ; DCS introducer, consume through ST
379 GOTESC ] STRING ; OSC introducer, consume through ST
380 GOTESC ^ STRING ; PM introducer, consume through ST
381 GOTESC _ STRING ; APC introducer, consume through ST
382 GOTESC 0..~ NORMAL ; 03/00 through 17/14 = Final character
383 GOTESC other ESCSEQ ; Intermediate or ignored control character
384
385 ESCSEQ ESC GOTESC ; Start again
386 ESCSEQ 0..~ NORMAL ; 03/00 through 17/14 = Final character
387 ESCSEQ other ; Intermediate or ignored control character
388
389 GOTCSI ESC GOTESC ; Start again
390 GOTCSI @..~ NORMAL ; 04/00 through 17/14 = Final character
391 GOTCSI other ; Intermediate char or ignored control char
392
393 STRING ESC TERMIN ; Maybe have ST
394 STRING other ; Consume all else
395
396 TERMIN \ NORMAL ; End of string
397 TERMIN other STRING ; Still in string
398 */
399 /*
400 chkaes() -- Check ANSI Escape Sequence.
401 Call with EACH character in input stream.
402 Sets global inesc variable according to escape sequence state.
403 Returns 0 normally, 1 if an APC sequence is to be executed.
404 */
405 int
406 #ifdef CK_ANSIC
chkaes(char c)407 chkaes(char c)
408 #else
409 chkaes(c) char c;
410 #endif /* CK_ANSIC */
411 /* chkaes */ {
412
413 oldesc = inesc; /* Remember previous state */
414 if (c == CAN || c == SUB) /* CAN and SUB cancel any sequence */
415 inesc = ES_NORMAL;
416 else /* Otherwise */
417 switch (inesc) { /* enter state switcher */
418
419 case ES_NORMAL: /* NORMAL state */
420 if (c == ESC) /* Got an ESC */
421 inesc = ES_GOTESC; /* Change state to GOTESC */
422 break; /* Otherwise stay in NORMAL state */
423
424 case ES_GOTESC: /* GOTESC state */
425 if (c == '[') /* Left bracket after ESC is CSI */
426 inesc = ES_GOTCSI; /* Change to GOTCSI state */
427 else if (c == 'P' || (c > 0134 && c < 0140)) { /* P, [, ^, or _ */
428 inesc = ES_STRING; /* Switch to STRING-absorption state */
429 #ifdef CK_APC
430 if (c == '_' && pid == 0 && /* APC handled in child only */
431 (apcstatus & APC_ON)) { /* and only if not disabled. */
432 debug(F100,"CONNECT APC begin","",0);
433 apcactive = APC_REMOTE; /* Set APC-Active flag */
434 apclength = 0; /* and reset APC buffer pointer */
435 }
436 #endif /* CK_APC */
437 } else if (c > 057 && c < 0177) /* Final character '0' thru '~' */
438 inesc = ES_NORMAL; /* Back to normal */
439 else if (c != ESC) /* ESC in an escape sequence... */
440 inesc = ES_ESCSEQ; /* starts a new escape sequence */
441 break; /* Intermediate or ignored ctrl char */
442
443 case ES_ESCSEQ: /* ESCSEQ -- in an escape sequence */
444 if (c > 057 && c < 0177) /* Final character '0' thru '~' */
445 inesc = ES_NORMAL; /* Return to NORMAL state. */
446 else if (c == ESC) /* ESC ... */
447 inesc = ES_GOTESC; /* starts a new escape sequence */
448 break; /* Intermediate or ignored ctrl char */
449
450 case ES_GOTCSI: /* GOTCSI -- In a control sequence */
451 if (c > 077 && c < 0177) /* Final character '@' thru '~' */
452 inesc = ES_NORMAL; /* Return to NORMAL. */
453 else if (c == ESC) /* ESC ... */
454 inesc = ES_GOTESC; /* starts over. */
455 break; /* Intermediate or ignored ctrl char */
456
457 case ES_STRING: /* Inside a string */
458 if (c == ESC) /* ESC may be 1st char of terminator */
459 inesc = ES_TERMIN; /* Go see. */
460 #ifdef CK_APC
461 else if (apcactive && (apclength < apcbuflen)) /* If in APC, */
462 apcbuf[apclength++] = c; /* deposit this character. */
463 else { /* Buffer overrun */
464 apcactive = 0; /* Discard what we got */
465 apclength = 0; /* and go back to normal */
466 apcbuf[0] = 0; /* Not pretty, but what else */
467 inesc = ES_NORMAL; /* can we do? (ST might not come) */
468 }
469 #endif /* CK_APC */
470 break; /* Absorb all other characters. */
471
472 case ES_TERMIN: /* May have a string terminator */
473 if (c == '\\') { /* which must be backslash */
474 inesc = ES_NORMAL; /* If so, back to NORMAL */
475 #ifdef CK_APC
476 if (apcactive) { /* If it was an APC string, */
477 debug(F101,"CONNECT APC terminated","",c);
478 apcbuf[apclength] = NUL; /* terminate it and then ... */
479 return(1);
480 }
481 #endif /* CK_APC */
482 } else { /* Otherwise */
483 inesc = ES_STRING; /* Back to string absorption. */
484 #ifdef CK_APC
485 if (apcactive && (apclength+1 < apcbuflen)) { /* In APC string */
486 apcbuf[apclength++] = ESC; /* deposit the Esc character */
487 apcbuf[apclength++] = c; /* and this character too */
488 }
489 #endif /* CK_APC */
490 }
491 }
492 return(0);
493 }
494 #endif /* NOESCSEQ */
495
496 /* Connect state parent/child communication signal handlers */
497
498 /* Routines used by the child process */
499
500 static int
pipemsg(n)501 pipemsg(n) int n; { /* Send message ID to parent */
502 int code = n & 255;
503 return(write(xpipe[1], &code, sizeof(code)));
504 }
505
506 /* Environment pointer for CK_FORK_SIG signal handling in child... */
507
508 #ifdef CK_POSIX_SIG
509 static sigjmp_buf sig_env;
510 #else
511 static jmp_buf sig_env;
512 #endif /* CK_POSIX_SIG */
513
514 static SIGTYP /* CK_FORK_SIG handling in child ... */
forkint(foo)515 forkint(foo) int foo; {
516 /* It is important to disable CK_FORK_SIG before longjmp */
517 signal(CK_FORK_SIG, SIG_IGN); /* Set to ignore CK_FORK_SIG */
518 debug(F100,"CONNECT forkint - CK_FORK_SIG", "", 0);
519 /* Force return from ck_sndmsg() */
520 cklongjmp(sig_env, 1);
521 /* NOTREACHED */
522 }
523
524 static VOID
ck_sndmsg()525 ck_sndmsg() { /* Executed by child only ... */
526 debug(F100,"CONNECT ck_sndmsg, active", "", active);
527 if (
528 #ifdef CK_POSIX_SIG
529 sigsetjmp(sig_env,1)
530 #else
531 setjmp(sig_env)
532 #endif /* CK_POSIX_SIG */
533 == 0) {
534 debug(F100,"CONNECT ck_sndmsg signaling parent","",0);
535 signal(CK_FORK_SIG, forkint); /* Set up signal handler */
536 kill(parent_id, CK_FORK_SIG); /* Kick the parent */
537 debug(F100,"ck_sndmsg pausing","",0);
538 for (;;) pause(); /* Wait for CK_FORK_SIG or SIGKILL */
539 /* NOTREACHED */
540 }
541 /* We come here from forkint() via [sig]cklongjmp(sig_env,1) */
542 debug(F100,"CONNECT ck_sndmsg is parent - returning", "", 0);
543 }
544
545 /* Routines used by the parent process */
546
547 #ifdef CK_POSIX_SIG /* Environment pointer for CONNECT errors */
548 static sigjmp_buf con_env;
549 #else
550 static jmp_buf con_env;
551 #endif /* CK_POSIX_SIG */
552 /*
553 pipeint() handles CK_FORK_SIG signals from the lower (port) fork.
554 It reads a function code from the pipe that connects the two forks,
555 then reads additional data from the pipe, then handles it.
556 */
557 static SIGTYP
pipeint(arg)558 pipeint(arg) int arg; { /* Dummy argument */
559 int code, cx, x, i /* , n */ ;
560
561 #ifndef NOCCTRAP
562 extern ckjmpbuf cmjbuf;
563 #endif /* NOCCTRAP */
564 /*
565 IMPORTANT: At this point, the child fork is waiting for CK_FORK_SIG
566 (eventually for SIGKILL) inside of ck_sndmsg(). So we can't get any
567 subsequent CK_FORK_SIG from child before we send it CK_FORK_SIG.
568 */
569 signal(CK_FORK_SIG, SIG_IGN); /* Ignore CK_FORK_SIG now */
570 debug(F101,"CONNECT pipeint arg","",arg);
571
572 read(xpipe[0], &code, sizeof(code)); /* Get function code from pipe */
573 debug(F101,"CONNECT pipeint code","",code);
574 cx = code & 255; /* 8-bit version of function code */
575
576 #ifndef NOCCTRAP
577 #ifndef NOICP
578 #define USECCJMPBUF
579 #endif /* NOICP */
580 #endif /* NOCCTRAP */
581 /*
582 Read info passed back up to us by the lower fork, depending on the function
583 requested. The same number of items must be read from the pipe in the same
584 order as the lower fork put them there. Trying to read something that's not
585 there makes the program hang uninterruptibly. Pay close attention -- notice
586 how we fall through some of the cases rather than break; that's deliberate.
587 */
588 switch (cx) {
589 #ifdef CK_TRIGGER
590 case CEV_TRI: /* Trigger string */
591 debug(F100,"CONNECT trigger","",0);
592 read(xpipe[0], (char *)&i, sizeof(i)); /* Trigger index */
593 debug(F101,"CONNECT trigger index","",i);
594 makestr(&triggerval,tt_trigger[i]); /* Make a copy of the trigger */
595 debug(F110,"CONNECT triggerval",triggerval,0);
596 read(xpipe[0], (char *)&ibc, sizeof(ibc)); /* Copy child's */
597 debug(F101,"CONNECT trigger ibc (upper)","",ibc); /* input buffer. */
598 if (ibc > 0) {
599 read(xpipe[0], (char *)&ibp, sizeof(ibp));
600 read(xpipe[0], ibp, ibc);
601 }
602 /* Fall thru... */
603
604 #endif /* CK_TRIGGER */
605
606 case CEV_HUP:
607 /*
608 The CEV_HUP case is executed when the other side has hung up on us.
609 In some cases, this happens before we have had a chance to execute the
610 setjmp(con_env,1) call, and in that case we'd better not take the longjmp!
611 A good example is when you TELNET to port 13 on the local host; it prints
612 its asctime() string (26 chars) and then closes the connection.
613 */
614 #ifdef CK_TRIGGER
615 if (cx == CEV_TRI)
616 sjval = CEV_TRI; /* Set global variable. */
617 else
618 #endif /* CK_TRIGGER */
619 sjval = CEV_HUP;
620 if (jbset) { /* jmp_buf is initialized */
621 cklongjmp(con_env,sjval); /* so do the right thing. */
622 } else {
623 int x = 0;
624 #ifdef USECCJMPBUF
625 /* jmp_buf not init'd yet a close approximation... */
626 #ifdef CK_TRIGGER
627 if (cx == CEV_HUP)
628 #endif /* CK_TRIGGER */
629 ttclos(0); /* Close our end of the connection */
630 if (pid) {
631 debug(F101,"CONNECT trigger killing pid","",pid);
632 #ifdef BEOSORBEBOX
633 {
634 long ret_val;
635 x = kill(pid,SIGKILLTHR); /* Kill lower fork */
636 wait_for_thread (pid, &ret_val);
637 }
638 #else
639 #ifdef Plan9
640 x = kill(pid, SIGKILL); /* (should always use this really) */
641 #else
642 x = kill(pid,9); /* Kill lower fork (history) */
643 #endif /* Plan9 */
644 wait((WAIT_T *)0); /* Wait till gone. */
645 if (x < 0) {
646 printf("ERROR: Failure to kill pid %ld: %s, errno=%d\n",
647 (long) pid, ck_errstr(), errno);
648 debug(F111,"CONNECT error killing stale pid",
649 ck_errstr(),errno);
650 }
651 pid = (PID_T) 0;
652 #endif /* BEOSORBEBOX */
653 }
654 conres(); /* Reset the console. */
655 if (!quiet) {
656 printf("\r\n(Back at %s)\r\n",
657 *myhost ? myhost :
658 #ifdef UNIX
659 "local UNIX system"
660 #else
661 "local system"
662 #endif /* UNIX */
663 );
664 }
665 what = W_NOTHING; /* So console modes are set right. */
666 printf("\r\n"); /* prevent prompt-stomping */
667 cklongjmp(cmjbuf,0); /* Do what the Ctrl-C handler does */
668 #else
669 printf("\r\nLongjump failure - fatal\r\n");
670 doexit(GOOD_EXIT,-1); /* Better than dumping core... */
671 #endif /* USECCJMPBUF */
672 }
673 #ifdef USECCJMPBUF
674 #undef USECCJMPBUF
675 #endif /* USECCJMPBUF */
676
677 case CEV_DUP: /* Child sends duplex change */
678 read(xpipe[0], (char *)&duplex, sizeof(duplex));
679 debug(F101,"CONNECT pipeint duplex","",duplex);
680 break;
681 #ifdef TNCODE
682 case CEV_MEBIN: /* Child sends me_binary change */
683 read(xpipe[0],
684 (char *)&TELOPT_ME(TELOPT_BINARY),
685 sizeof(TELOPT_ME(TELOPT_BINARY))
686 );
687 debug(F101,"CONNECT pipeint me_binary","",TELOPT_ME(TELOPT_BINARY));
688 break;
689 case CEV_UBIN: /* Child sends u_binary change */
690 read(xpipe[0],
691 (char *)&TELOPT_U(TELOPT_BINARY),
692 sizeof(TELOPT_U(TELOPT_BINARY))
693 );
694 debug(F101,"CONNECT pipeint u_binary","",TELOPT_U(TELOPT_BINARY));
695 break;
696 #endif /* TNCODE */
697
698 #ifdef CK_APC
699 case CEV_AUL: /* Autoupload */
700 justone = 1;
701 debug(F100,"CONNECT autoupload at parent","",0);
702 #ifdef CK_AUTODL
703 case CEV_ADL: /* Autodownload */
704 apcactive = APC_LOCAL;
705 if (!justone) debug(F100,"CONNECT autodownload at parent","",0);
706 /* Copy child's Kermit packet if any */
707 read(xpipe[0], (char *)&x, sizeof(x));
708 debug(F101,"CONNECT trigger ibc (upper)","",ibc);
709 if (x > 0)
710 read(xpipe[0], (char *)ksbuf, x+1);
711 #endif /* CK_AUTODL */
712 case CEV_APC: /* Application Program Command */
713 read(xpipe[0], (char *)&apclength, sizeof(apclength));
714 read(xpipe[0], apcbuf, apclength+1); /* Include trailing zero byte */
715 debug(F111,"CONNECT APC at parent",apcbuf,apclength);
716 read(xpipe[0], (char *)&ibc, sizeof(ibc)); /* Copy child's */
717 if (ibc > 0) { /* input buffer. */
718 read(xpipe[0], (char *)&ibp, sizeof(ibp));
719 read(xpipe[0], ibp, ibc);
720 }
721 obc = 0; obp = obuf; *obuf = NUL; /* Because port fork flushed */
722 sjval = CEV_APC;
723 cklongjmp(con_env,sjval);
724 /* NOTREACHED */
725 #endif /* CK_APC */
726
727 #ifdef SUNX25
728 case CEV_PAD: /* X.25 PAD parameter change */
729 debug(F100,"CONNECT pipeint PAD change","",0);
730 read(xpipe[0],padparms,MAXPADPARMS);
731 sjval = CEV_PAD; /* Set global variable. */
732 #ifdef COMMENT /* We might not need to do this... */
733 cklongjmp(con_env,sjval);
734 /* NOTREACHED */
735 #else /* COMMENT */
736 break;
737 #endif /* COMMENT */
738 #endif /* SUNX25 */
739 }
740 signal(CK_FORK_SIG, pipeint); /* Set up signal handler */
741 kill(pid, CK_FORK_SIG); /* Signal the port fork ... */
742 }
743
744 /* C K C P U T C -- C-Kermit CONNECT Put Character to Screen */
745 /*
746 Output is buffered to avoid slow screen writes on fast connections.
747 NOTE: These could (easily?) become macros ...
748 */
749 static int
ckcputf()750 ckcputf() { /* Dump the output buffer */
751 int x = 0;
752 if (obc > 0) /* If we have any characters, */
753 x = conxo(obc,obuf); /* dump them, */
754 obp = obuf; /* reset the pointer */
755 obc = 0; /* and the counter. */
756 return(x); /* Return conxo's return code */
757 }
758
759 int
ckcputc(c)760 ckcputc(c) int c; {
761 int x;
762
763 *obp++ = c & 0xff; /* Deposit the character */
764 obc++; /* Count it */
765 if (ibc == 0 || /* If input buffer about empty */
766 obc == OBUFL) { /* or output buffer full */
767 debug(F101,"CONNECT CKCPUTC obc","",obc);
768 x = conxo(obc,obuf); /* dump the buffer, */
769 obp = obuf; /* reset the pointer */
770 obc = 0; /* and the counter. */
771 return(x); /* Return conxo's return code */
772 } else return(0);
773 }
774
775 /* C K C G E T C -- C-Kermit CONNECT Get Character */
776 /*
777 Buffered read from communication device.
778 Returns the next character, refilling the buffer if necessary.
779 On error, returns ttinc's return code (see ttinc() description).
780 Dummy argument for compatible calling conventions with ttinc().
781 NOTE: We don't have a macro for this because we have to pass
782 a pointer to this function as an argument to tn_doop().
783 */
784 int
ckcgetc(dummy)785 ckcgetc(dummy) int dummy; {
786 int c, n;
787 #ifdef CK_SSL
788 extern int ssl_active_flag, tls_active_flag;
789 #endif /* CK_SSL */
790
791 #ifdef CK_ENCRYPTION
792 /* No buffering for possibly encrypted connections */
793 if (network && IS_TELNET() && TELOPT_ME(TELOPT_AUTHENTICATION))
794 return(ttinc(0));
795 #endif /* CK_ENCRYPTION */
796 #ifdef CK_SSL
797 if (ssl_active_flag || tls_active_flag)
798 return(ttinc(0));
799 #endif /* CK_SSL */
800 #ifdef COMMENT
801 /* too much */
802 debug(F101,"CONNECT CKCGETC 1 ibc","",ibc); /* Log */
803 #endif /* COMMENT */
804 if (ibc < 1) { /* Need to refill buffer? */
805 ibc = 0; /* Yes, reset count */
806 ibp = ibuf; /* and buffer pointer */
807 /* debug(F100,"CONNECT CKCGETC 1 calling ttinc(0)","",0); */
808 #ifdef COMMENT
809 /*
810 This check is not worth the overhead. Scenario: ttchk() returns 0, so we
811 fall through to the blocking ttinc(). While in ttinc(), the connection is
812 lost. But the read() that ttinc() calls does not notice, and never returns.
813 This happens at least in HP-UX, and can be seen when we turn off the modem.
814 */
815 if (!network && (carrier != CAR_OFF))
816 if ((n = ttchk()) < 0) /* Make sure connection is not lost */
817 return(n);
818 #endif /* COMMENT */
819 c = ttinc(0); /* Read one character, blocking */
820 /* debug(F101,"CONNECT CKCGETC 1 ttinc(0)","",c); */
821 if (c < 0) { /* If error, return error code */
822 return(c);
823 } else { /* Otherwise, got one character */
824 *ibp++ = c; /* Advance buffer pointer */
825 ibc++; /* and count. */
826 }
827 if ((n = ttchk()) > 0) { /* Any more waiting? */
828 if (n > (IBUFL - ibc)) /* Get them all at once. */
829 n = IBUFL - ibc; /* Don't overflow buffer */
830 if ((n = ttxin(n,(CHAR *)ibp)) > 0) {
831 #ifdef CK_ENCRYPTION
832 if (TELOPT_U(TELOPT_ENCRYPTION))
833 ck_tn_decrypt(ibp,n);
834 #endif /* CK_ENCRYPTION */
835 ibc += n; /* Advance counter */
836 }
837 } else if (n < 0) { /* Error? */
838 return(n); /* Return the error code */
839 }
840 debug(F101,"CONNECT CKCGETC 2 ibc","",ibc); /* Log how many */
841 ibp = ibuf; /* Point to beginning of buffer */
842 }
843 c = *ibp++ & 0xff; /* Get next character from buffer */
844 ibc--; /* Reduce buffer count */
845 return(c); /* Return the character */
846 }
847
848 /*
849 Keyboard handling, buffered for speed, which is needed when C-Kermit is
850 in CONNECT mode between two other computers that are transferring data.
851 */
852 static char *kbp; /* Keyboard input buffer pointer */
853 static int kbc; /* Keyboard input buffer count */
854
855 #ifdef CK_SMALL /* Keyboard input buffer length */
856 #define KBUFL 32 /* Small for PDP-11 UNIX */
857 #else
858 #define KBUFL 257 /* Regular kernel size for others */
859 #endif /* CK_SMALL */
860
861 #ifdef DYNAMIC
862 static char *kbuf = NULL;
863 #else
864 static char kbuf[KBUFL];
865 #endif /* DYNAMIC */
866
867 /* Macro for reading keystrokes. */
868
869 #define CONGKS() (((--kbc)>=0) ? ((int)(*kbp++) & 0377) : kbget())
870
871 /*
872 Note that we call read() directly here, normally a no-no, but in this case
873 we know it's UNIX and we're only doing what coninc(0) would have done,
874 except we're reading a block of characters rather than just one. There is,
875 at present, no conxin() analog to ttxin() for chunk reads, and instituting
876 one would only add function-call overhead as it would only be a wrapper for
877 a read() call anyway.
878 */
879 /*
880 Another note: We stick in this read() till the user types something.
881 But the other (lower) fork is running too, and on TELNET connections,
882 it will signal us to indicate echo-change negotiations, and this can
883 interrupt the read(). Some UNIXes automatically restart the interrupted
884 system call, others return from it with errno == EINTR.
885 */
886 static int /* Keyboard buffer filler */
kbget()887 kbget() {
888 #ifdef EINTR
889 int tries = 10; /* If read() is interrupted, */
890 int ok = 0;
891 while (tries-- > 0) { /* try a few times... */
892 #endif /* EINTR */
893 if ((kbc = conchk()) < 1) /* How many chars waiting? */
894 kbc = 1; /* If none or dunno, wait for one. */
895 else if (kbc > KBUFL) /* If too many, */
896 kbc = KBUFL; /* only read this many. */
897 if ((kbc = read(0, kbuf, kbc)) < 1) { /* Now read it/them. */
898 debug(F101,"CONNECT kbget errno","",errno); /* Got an error. */
899 #ifdef EINTR
900 if (errno == EINTR) /* Interrupted system call. */
901 continue; /* Try again, up to limit. */
902 else /* Something else. */
903 #endif /* EINTR */
904 return(-1); /* Pass along read() error. */
905 }
906 #ifdef EINTR
907 else { ok = 1; break; }
908 }
909 if (!ok) return(-1);
910 #endif /* EINTR */
911 kbp = kbuf; /* Adjust buffer pointer, */
912 kbc--; /* count, */
913 return((int)(*kbp++) & 0377); /* and return first character. */
914 }
915
916 /* C O N C L D -- Interactive terminal connection child function */
917
918 static
919 #ifdef BEOSORBEBOX
920 long
921 #else
922 VOID
923 #endif /* BEOSORBEBOX */
concld(void * bevoid)924 concld (
925 #ifdef BEOSORBEBOX
926 void *bevoid
927 #endif /* BEOSORBEBOX */
928 ) {
929 int n; /* General purpose counter */
930 int i; /* For loops... */
931 int c = -1; /* c is a character, but must be signed
932 integer to pass thru -1, which is the
933 modem disconnection signal, and is
934 different from the character 0377 */
935 int prev;
936 #ifdef TNCODE
937 int tx; /* tn_doop() return code */
938 #endif /* TNCODE */
939 #ifdef CK_TRIGGER
940 int ix; /* Trigger index */
941 #endif /* CK_TRIGGER */
942 #ifndef NOESCSEQ
943 int apcrc;
944 #endif /* NOESCSEQ */
945
946 #ifdef COMMENT
947 int conret = 0; /* Return value from conect() */
948 jbchksum = -1L;
949 #endif /* COMMENT */
950 jbset = 0; /* jmp_buf not set yet, don't use it */
951 debug(F101,"CONNECT concld entry","",CK_FORK_SIG);
952 /* *** */ /* Inferior reads, prints port input */
953
954 if (priv_can()) { /* Cancel all privs */
955 printf("?setuid error - fatal\n");
956 doexit(BAD_EXIT,-1);
957 }
958 signal(SIGINT, SIG_IGN); /* In case these haven't been */
959 signal(SIGQUIT, SIG_IGN); /* inherited from above... */
960 signal(CK_FORK_SIG, SIG_IGN); /* CK_FORK_SIG not expected yet */
961
962 inshift = outshift = 0; /* Initial SO/SI shift state. */
963 { /* Wait for parent's setup */
964 int i;
965 while ((i = read(xpipe[0], &c, 1)) <= 0) {
966 if (i < 0) {
967 debug(F101,"CONNECT concld setup error","",i);
968 debug(F111,"CONNECT concld setup error",ck_errstr(),errno);
969 pipemsg(CEV_HUP); /* Read error - hangup */
970 ck_sndmsg(); /* Send and wait to be killed */
971 /* NOTREACHED */
972 } /* Restart interrupted read() */
973 }
974 }
975 close(xpipe[0]); xpipe[0] = -1; /* Child - prevent future reads */
976 #ifdef DEBUG
977 if (deblog) {
978 debug(F100,"CONNECT starting port fork","",0);
979 debug(F101,"CONNECT port fork ibc","",ibc);
980 debug(F101,"CONNECT port fork obc","",obc);
981 }
982 #endif /* DEBUG */
983 what = W_CONNECT;
984
985 while (1) { /* Fresh read, wait for a character. */
986 #ifdef ANYX25
987 if (network && (nettype == NET_SX25)) {
988 bzero(x25ibuf,sizeof(x25ibuf)) ;
989 if ((ibufl = ttxin(MAXIX25,(CHAR *)x25ibuf)) < 0) {
990 #ifndef IBMX25
991 if (ibufl == -2) { /* PAD parms changes */
992 pipemsg(CEV_PAD);
993 write(xpipe[1],padparms,MAXPADPARMS);
994 ck_sndmsg();
995 } else {
996 #endif /* IBMX25 */
997 if (!quiet)
998 printf("\r\nCommunications disconnect ");
999 dologend();
1000 pipemsg(CEV_HUP);
1001 ck_sndmsg(); /* Wait to be killed */
1002 /* NOTREACHED */
1003 #ifndef IBMX25
1004 }
1005 #endif /* IBMX25 */
1006 /* pause(); <--- SHOULD BE OBSOLETE NOW! */
1007 /* BECAUSE pause() is done inside of ck_sndmsg() */
1008 }
1009 if (debses) { /* Debugging output */
1010 p = x25ibuf ;
1011 while (ibufl--) { c = *p++; conol(dbchr(c)); }
1012 } else {
1013 if (seslog && sessft) /* Binary session log */
1014 logchar((char)c); /* Log char before translation */
1015
1016 if (sosi
1017 #ifndef NOCSETS
1018 || tcsl != tcsr
1019 #endif /* NOCSETS */
1020 ) { /* Character at a time */
1021 for (i = 1; i < ibufl; i++) {
1022 c = x25ibuf[i] & cmask;
1023 if (sosi) { /* Handle SI/SO */
1024 if (c == SO) {
1025 inshift = 1;
1026 continue;
1027 } else if (c == SI) {
1028 inshift = 0;
1029 continue;
1030 }
1031 if (inshift)
1032 c |= 0200;
1033 }
1034 #ifndef NOCSETS
1035 if (inesc == ES_NORMAL) {
1036 #ifdef UNICODE
1037 int x;
1038 if (unicode == 1) { /* Remote is UTF-8 */
1039 x = u_to_b((CHAR)c);
1040 if (x == -1)
1041 continue;
1042 else if (x == -2) { /* LS or PS */
1043 inxbuf[0] = CR;
1044 inxbuf[1] = LF;
1045 inxcount = 2;
1046 } else {
1047 inxbuf[0] = (unsigned)(x & 0xff);
1048 }
1049 c = inxbuf[0];
1050 } else if (unicode == 2) { /* Local is UTF-8 */
1051 inxcount =
1052 b_to_u((CHAR)c,inxbuf,OUTXBUFSIZ,tcssize);
1053 c = inxbuf[0];
1054 } else {
1055 #endif /* UNICODE */
1056 if (sxi) c = (*sxi)((CHAR)c);
1057 if (rxi) c = (*rxi)((CHAR)c);
1058 inxbuf[0] = c;
1059 #ifdef UNICODE
1060 }
1061 #endif /* UNICODE */
1062 }
1063 #endif /* NOCSETS */
1064 c &= cmdmsk; /* Apply command mask. */
1065 conoc(c); /* Output to screen */
1066 if (seslog && !sessft) /* and session log */
1067 logchar(c);
1068 }
1069 } else { /* All at once */
1070 for (i = 1; i < ibufl; i++)
1071 x25ibuf[i] &= (cmask & cmdmsk);
1072 conxo(ibufl,x25ibuf);
1073 if (seslog) zsoutx(ZSFILE,x25ibuf,ibufl);
1074 }
1075 }
1076 continue;
1077
1078 } else { /* Not X.25... */
1079 #endif /* ANYX25 */
1080 /*
1081 Get the next communication line character from our internal buffer.
1082 If the buffer is empty, refill it.
1083 */
1084 prev = c; /* Remember previous character */
1085 c = ckcgetc(0); /* Get next character */
1086 /* debug(F101,"CONNECT c","",c); */
1087 if (c < 0) { /* Failed... */
1088 debug(F101,"CONNECT disconnect ibc","",ibc);
1089 debug(F101,"CONNECT disconnect obc","",obc);
1090 ckcputf(); /* Flush CONNECT output buffer */
1091 if (!quiet) {
1092 printf("\r\nCommunications disconnect ");
1093 #ifdef COMMENT
1094 if ( c == -3
1095 #ifdef ultrix
1096 /* This happens on Ultrix if there's no carrier */
1097 && errno != EIO
1098 #endif /* ultrix */
1099 #ifdef UTEK
1100 /* This happens on UTEK if there's no carrier */
1101 && errno != EWOULDBLOCK
1102 #endif /* UTEK */
1103 )
1104 perror("\r\nCan't read character");
1105 #endif /* COMMENT */
1106 }
1107 #ifdef NOSETBUF
1108 fflush(stdout);
1109 #endif /* NOSETBUF */
1110 tthang(); /* Hang up the connection */
1111 debug(F111,"CONNECT concld i/o error",ck_errstr(),errno);
1112 pipemsg(CEV_HUP);
1113 ck_sndmsg(); /* Wait to be killed */
1114 }
1115 #ifdef COMMENT
1116 /* too much... */
1117 debug(F101,"CONNECT ** PORT","",c); /* Got character c OK. */
1118 #endif /* COMMENT */
1119 #ifdef TNCODE
1120 /* Handle TELNET negotiations... */
1121
1122 if ((c == NUL) && network && IS_TELNET()) {
1123 if (prev == CR) /* Discard <NUL> of <CR><NUL> */
1124 if (!TELOPT_U(TELOPT_BINARY))
1125 continue;
1126 }
1127 if ((c == IAC) && network && IS_TELNET()) {
1128 int me_bin = TELOPT_ME(TELOPT_BINARY);
1129 int u_bin = TELOPT_U(TELOPT_BINARY);
1130 debug(F100,"CONNECT got IAC","",0);
1131 ckcputf(); /* Dump screen-output buffer */
1132 if ((tx = tn_doop((CHAR)(c & 0xff),duplex,ckcgetc)) == 0) {
1133 if (me_bin != TELOPT_ME(TELOPT_BINARY)) {
1134 debug(F101,
1135 "CONNECT TELNET me_bin",
1136 "",
1137 TELOPT_ME(TELOPT_BINARY)
1138 );
1139 pipemsg(CEV_MEBIN); /* Tell parent */
1140 write(xpipe[1],
1141 &TELOPT_ME(TELOPT_BINARY),
1142 sizeof(TELOPT_ME(TELOPT_BINARY))
1143 );
1144 ck_sndmsg(); /* Tell the parent fork */
1145 } else if (u_bin != TELOPT_U(TELOPT_BINARY)) {
1146 debug(F101,
1147 "CONNECT TELNET u_bin",
1148 "",
1149 TELOPT_U(TELOPT_BINARY)
1150 );
1151 pipemsg(CEV_UBIN); /* Tell parent */
1152 write(xpipe[1],
1153 &TELOPT_U(TELOPT_BINARY),
1154 sizeof(TELOPT_U(TELOPT_BINARY))
1155 );
1156 ck_sndmsg(); /* Tell the parent fork */
1157 }
1158 continue;
1159 } else if (tx == -1) { /* I/O error */
1160 if (!quiet)
1161 printf("\r\nCommunications disconnect ");
1162 #ifdef NOSETBUF
1163 fflush(stdout);
1164 #endif /* NOSETBUF */
1165 dologend();
1166 debug(F111,"CONNECT concld i/o error 2",ck_errstr(),errno);
1167 pipemsg(CEV_HUP);
1168 ck_sndmsg(); /* Wait to be killed */
1169 /* NOTREACHED */
1170 } else if (tx == -3) { /* I/O error */
1171 if (!quiet)
1172 printf("\r\nConnection closed due to telnet policy ");
1173 #ifdef NOSETBUF
1174 fflush(stdout);
1175 #endif /* NOSETBUF */
1176 dologend();
1177 debug(F111,"CONNECT concld i/o error 2",ck_errstr(),errno);
1178 pipemsg(CEV_HUP);
1179 ck_sndmsg(); /* Wait to be killed */
1180 /* NOTREACHED */
1181 } else if (tx == -2) { /* I/O error */
1182 if (!quiet)
1183 printf("\r\nConnection closed by peer ");
1184 #ifdef NOSETBUF
1185 fflush(stdout);
1186 #endif /* NOSETBUF */
1187 dologend();
1188 debug(F111,"CONNECT concld i/o error 2",ck_errstr(),errno);
1189 pipemsg(CEV_HUP);
1190 ck_sndmsg(); /* Wait to be killed */
1191 /* NOTREACHED */
1192 } else if ((tx == 1) && (!duplex)) { /* ECHO change */
1193 duplex = 1; /* Turn on local echo */
1194 debug(F101,"CONNECT TELNET duplex change","",duplex);
1195 pipemsg(CEV_DUP); /* Tell parent */
1196 write(xpipe[1], &duplex, sizeof(duplex));
1197 ck_sndmsg(); /* Tell the parent fork */
1198 continue;
1199 } else if ((tx == 2) && (duplex)) { /* ECHO change */
1200 duplex = 0;
1201 debug(F101,"CONNECT TELNET duplex change","",duplex);
1202 pipemsg(CEV_DUP);
1203 write(xpipe[1], &duplex, sizeof(duplex));
1204 ck_sndmsg();
1205 continue;
1206 } else if (tx == 3) { /* Quoted IAC */
1207 c = parity ? 127 : 255;
1208 }
1209 #ifdef IKS_OPTION
1210 else if (tx == 4) { /* IKS State Change */
1211 if (TELOPT_SB(TELOPT_KERMIT).kermit.u_start &&
1212 !tcp_incoming
1213 ) {
1214 /* here we need to print a msg that the other */
1215 /* side is in SERVER mode and that REMOTE */
1216 /* commands should be used. And CONNECT mode */
1217 /* should be ended. */
1218 active = 0;
1219 }
1220 }
1221 #endif /* IKS_OPTION */
1222 else if (tx == 6) {
1223 /* DO LOGOUT received */
1224 if (!quiet)
1225 printf("\r\nRemote Logout ");
1226 #ifdef NOSETBUF
1227 fflush(stdout);
1228 #endif /* NOSETBUF */
1229 debug(F100,"CONNECT Remote Logout","",0);
1230 pipemsg(CEV_HUP);
1231 ck_sndmsg(); /* Wait to be killed */
1232 /* NOTREACHED */
1233 } else
1234 continue; /* Negotiation OK, get next char. */
1235
1236 } else if (parity)
1237 c &= 0x7f;
1238
1239 if (TELOPT_ME(TELOPT_ECHO) && tn_rem_echo)
1240 ttoc(c); /* I'm echoing for the remote */
1241 #endif /* TNCODE */
1242
1243 if (debses) { /* Output character to screen */
1244 char *s; /* Debugging display... */
1245 s = dbchr(c);
1246 while (*s)
1247 ckcputc(*s++);
1248 } else { /* Regular display ... */
1249 c &= cmask; /* Apply Kermit-to-remote mask */
1250 #ifdef CK_AUTODL
1251 /*
1252 Autodownload. Check for Kermit S packet prior to translation, since that
1253 can change the packet and make it unrecognizable (as when the terminal
1254 character set is an ISO 646 one)... Ditto for Zmodem start packet.
1255 */
1256 if (autodl /* Autodownload enabled? */
1257 #ifdef IKS_OPTION
1258 || TELOPT_SB(TELOPT_KERMIT).kermit.me_start
1259 #endif /* IKS_OPTION */
1260 ) {
1261 int k;
1262 k = kstart((CHAR)c); /* Kermit S or I packet? */
1263 #ifdef CK_XYZ
1264 if (!k && zmdlok) /* Or an "sz" start? */
1265 k = zstart((CHAR)c);
1266 #endif /* CK_XYZ */
1267 if (k) {
1268 int ksign = 0;
1269 debug(F101,"CONNECT autodownload k","",k);
1270 if (k < 0) { /* Minus-Protocol? */
1271 #ifdef NOSERVER
1272 goto noserver; /* Need server mode for this */
1273 #else
1274 ksign = 1; /* Remember */
1275 k = 0 - k; /* Convert to actual protocol */
1276 justone = 1; /* Flag for protocol module */
1277 #endif /* NOSERVER */
1278 } else
1279 justone = 0;
1280 k--; /* Adjust [kz]start's return value */
1281 if (k == PROTO_K
1282 #ifdef CK_XYZ
1283 || k == PROTO_Z
1284 #endif /* CK_XYZ */
1285 ) {
1286
1287 /* Now damage the packet so that it does not */
1288 /* trigger autodownload detection on subsquent */
1289 /* links. */
1290
1291 if (k == PROTO_K) {
1292 int i, len = strlen((char*)ksbuf);
1293 for (i = 0; i < len; i++)
1294 ckcputc(BS);
1295 }
1296 #ifdef CK_XYZ
1297 else {
1298 int i;
1299 for (i = 0; i < 3; i++)
1300 ckcputc(CAN);
1301 }
1302 #endif /* CK_XYZ */
1303 /* Notify parent */
1304 pipemsg(justone ? CEV_AUL : CEV_ADL);
1305 /*
1306 Send our memory back up to the top fork thru the pipe.
1307 CAREFUL -- Write this stuff in the same order it is to be read!
1308 */
1309 /* Copy our Kermit packet to the parent fork */
1310 n = (int) strlen((char *)ksbuf);
1311 write(xpipe[1], (char *)&n, sizeof(n));
1312 if (n > 0)
1313 write(xpipe[1], (char *)ksbuf, n+1);
1314 debug(F111,"CONNECT autodownload ksbuf",ksbuf,n);
1315 debug(F101,"CONNECT autodownload justone","",
1316 justone);
1317 /* Construct the APC command */
1318 sprintf(apcbuf,
1319 "set proto %s, %s, set proto %s",
1320 ptab[k].p_name,
1321 ksign ? "server" : "receive",
1322 ptab[protocol].p_name
1323 );
1324 apclength = strlen(apcbuf);
1325 debug(F111,"CONNECT ksbuf",ksbuf,k);
1326 debug(F110,"CONNECT autodownload",apcbuf,0);
1327 apcactive = APC_LOCAL;
1328 ckcputf(); /* Force screen update */
1329
1330 /* Write buffer including trailing NUL byte */
1331 debug(F101,"CONNECT write xpipe apclength","",
1332 apclength);
1333 write(xpipe[1],
1334 (char *)&apclength,
1335 sizeof(apclength)
1336 );
1337 debug(F110,"CONNECT write xpipe apcbuf",apcbuf,0);
1338 write(xpipe[1], apcbuf, apclength+1);
1339
1340 /* Copy our input buffer to the parent fork */
1341
1342 debug(F101,"CONNECT autodownload complete ibc",
1343 "",ibc);
1344 debug(F101,"CONNECT autodownload complete obc",
1345 "",obc);
1346 write(xpipe[1], (char *)&ibc, sizeof(ibc));
1347 if (ibc > 0) {
1348 write(xpipe[1], (char *)&ibp, sizeof(ibp));
1349 write(xpipe[1], ibp, ibc);
1350 }
1351 ck_sndmsg(); /* Wait to be killed */
1352 /* NOTREACHED */
1353 }
1354 }
1355 }
1356 #ifdef NOSERVER
1357 noserver:
1358 #endif /* NOSERVER */
1359 #endif /* CK_AUTODL */
1360 if (sosi) { /* Handle SI/SO */
1361 if (c == SO) { /* Shift Out */
1362 inshift = 1;
1363 continue;
1364 } else if (c == SI) { /* Shift In */
1365 inshift = 0;
1366 continue;
1367 }
1368 if (inshift) c |= 0200;
1369 }
1370 inxbuf[0] = c; /* In case there is no translation */
1371 inxcount = 1; /* ... */
1372 #ifndef NOCSETS
1373 if (inesc == ES_NORMAL) { /* If not in an escape sequence */
1374 #ifdef UNICODE
1375 int x; /* Translate character sets */
1376 CHAR ch;
1377 ch = c;
1378 if (unicode == 1) { /* Remote is UTF-8 */
1379 x = u_to_b(ch);
1380 if (x < 0)
1381 continue;
1382 inxbuf[0] = (unsigned)(x & 0xff);
1383 c = inxbuf[0];
1384 } else if (unicode == 2) { /* Local is UTF-8 */
1385 inxcount = b_to_u(ch,inxbuf,OUTXBUFSIZ,tcssize);
1386 c = inxbuf[0];
1387 } else {
1388 #endif /* UNICODE */
1389 if (sxi) c = (*sxi)((CHAR)c);
1390 if (rxi) c = (*rxi)((CHAR)c);
1391 inxbuf[0] = c;
1392 #ifdef UNICODE
1393 }
1394 #endif /* UNICODE */
1395 }
1396 #endif /* NOCSETS */
1397
1398 #ifndef NOESCSEQ
1399 if (escseq) /* If handling escape sequences */
1400 apcrc = chkaes((char)c); /* update our state */
1401 #ifdef CK_APC
1402 /*
1403 If we are handling APCs, we have several possibilities at this point:
1404 1. Ordinary character to be written to the screen.
1405 2. An Esc; we can't write it because it might be the beginning of an APC.
1406 3. The character following an Esc, in which case we write Esc, then char,
1407 but only if we have not just entered an APC sequence.
1408 */
1409 if (escseq && (apcstatus & APC_ON)) {
1410 if (inesc == ES_GOTESC) /* Don't write ESC yet */
1411 continue;
1412 else if (oldesc == ES_GOTESC && !apcactive) {
1413 ckcputc(ESC); /* Write saved ESC */
1414 if (seslog && !sessft)
1415 logchar((char)ESC);
1416 } else if (apcrc) { /* We have an APC */
1417 debug(F111,"CONNECT APC complete",apcbuf,apclength);
1418 ckcputf(); /* Force screen update */
1419 pipemsg(CEV_APC); /* Notify parent */
1420 write(xpipe[1],
1421 (char *)&apclength,
1422 sizeof(apclength)
1423 );
1424 /* Write buffer including trailing NUL byte */
1425
1426 write(xpipe[1], apcbuf, apclength+1);
1427
1428 /* Copy our input buffer to the parent fork */
1429
1430 debug(F101,"CONNECT APC complete ibc","",ibc);
1431 debug(F101,"CONNECT APC complete obc","",obc);
1432 write(xpipe[1], (char *)&ibc, sizeof(ibc));
1433 if (ibc > 0) {
1434 write(xpipe[1], (char *)&ibp, sizeof(ibp));
1435 write(xpipe[1], ibp, ibc);
1436 }
1437 ck_sndmsg(); /* Wait to be killed */
1438 /* NOTREACHED */
1439 }
1440 }
1441 #endif /* CK_APC */
1442 #endif /* NOESCSEQ */
1443
1444 for (i = 0; i < inxcount; i++) { /* Loop thru */
1445 c = inxbuf[i]; /* input expansion buffer... */
1446 if (
1447 #ifdef CK_APC
1448 !apcactive /* Ignore APC sequences */
1449 #else
1450 1
1451 #endif /* CK_APC */
1452 ) {
1453 c &= cmdmsk; /* Apply command mask. */
1454 if (c == CR && tt_crd) { /* SET TERM CR-DISPLA CRLF? */
1455 ckcputc(c); /* Yes, output CR */
1456 if (seslog && !sessft)
1457 logchar((char)c);
1458 c = LF; /* and insert a linefeed */
1459 }
1460 if (c == LF && tt_lfd) { /* SET TERM CR-DISPLA CRLF? */
1461 ckcputc(CR); /* Yes, output CR */
1462 if (seslog && !sessft) logchar((char)CR);
1463 }
1464 ckcputc(c); /* Write character to screen */
1465 }
1466 if (seslog && !sessft) /* Handle session log */
1467 logchar((char)c);
1468 #ifdef CK_TRIGGER
1469 /* Check for trigger string */
1470 if (tt_trigger[0]) if ((ix = autoexitchk((CHAR)c)) > -1) {
1471 ckcputf(); /* Force screen update */
1472 #ifdef NOSETBUF
1473 fflush(stdout); /* I mean really force it */
1474 #endif /* NOSETBUF */
1475 pipemsg(CEV_TRI); /* Send up trigger indication */
1476 write(xpipe[1], (char *)&ix, sizeof(ix)); /* index */
1477 write(xpipe[1], (char *)&ibc, sizeof(ibc));
1478 if (ibc > 0) {
1479 write(xpipe[1], (char *)&ibp, sizeof(ibp));
1480 write(xpipe[1], ibp, ibc);
1481 }
1482 debug(F100,"CONNECT concld trigger","",0);
1483 ck_sndmsg(); /* Wait to be killed */
1484 active = 0; /* Shouldn't be necessary... */
1485 break;
1486 }
1487 /* NOTREACHED */
1488 #endif /* CK_TRIGGER */
1489 }
1490 }
1491 #ifdef ANYX25
1492 }
1493 #endif /* ANYX25 */
1494 }
1495 }
1496
1497
1498 /* C O N E C T -- Interactive terminal connection */
1499
1500 int
conect()1501 conect() {
1502 int n; /* General purpose counter */
1503 int i; /* For loops... */
1504 int c; /* c is a character, but must be signed
1505 integer to pass thru -1, which is the
1506 modem disconnection signal, and is
1507 different from the character 0377 */
1508 int c2; /* A copy of c */
1509 int csave; /* Another copy of c */
1510 #ifndef NOESCSEQ
1511 int apcrc;
1512 #endif /* NOESCSEQ */
1513
1514 int conret = 0; /* Return value from conect() */
1515 int msgflg = 0;
1516 /* jbchksum = -1L; */
1517 jbset = 0; /* jmp_buf not set yet, don't use it */
1518 debok = 1;
1519
1520 debug(F101,"CONNECT fork signal","",CK_FORK_SIG);
1521 debug(F101,"CONNECT entry pid","",pid);
1522
1523 msgflg = !quiet
1524 #ifdef CK_APC
1525 && !apcactive
1526 #endif /* CK_APC */
1527 ;
1528 /*
1529 The following is to handle a fork left behind if we exit CONNECT mode
1530 without killing it, and then return to CONNECT mode. This happened in
1531 HP-UX, where the Reset key would raise SIGINT even though SIGINT was set to
1532 SIG_IGN. The code below fixes the symptom; the real fix is in the main
1533 SIGINT handler (if SIGINT shows up during CONNECT, just return rather than
1534 taking the longjmp).
1535 */
1536 if (pid) { /* This should be 0 */
1537 int x = 0;
1538 debug(F101,"CONNECT entry killing stale pid","",pid);
1539 printf("WARNING: Old CONNECT fork seems to be active.\n");
1540 printf("Attempting to remove it...");
1541 #ifdef BEOSORBEBOX
1542 {
1543 long ret_val;
1544 x = kill(pid,SIGKILLTHR); /* Kill lower fork */
1545 wait_for_thread (pid, &ret_val);
1546 }
1547 #else
1548 #ifdef Plan9
1549 x = kill(pid,SIGKILL); /* Kill lower fork */
1550 #else
1551 x = kill(pid,9);
1552 #endif /* Plan9 */
1553 #endif /* BEOSORBEBOX */
1554 wait((WAIT_T *)0); /* Wait till gone. */
1555 if (x < 0) {
1556 printf("ERROR: Failure to kill pid %d: %s, errno=%d\n",
1557 (int) pid, ck_errstr(), errno);
1558 debug(F111,"CONNECT error killing stale pid",ck_errstr(),pid);
1559 }
1560 pid = (PID_T) 0;
1561 printf("\n");
1562 }
1563 signal(CK_FORK_SIG, SIG_IGN); /* Initial CK_FORK_SIG handling, */
1564 /*
1565 The following ttimoff() call should not be necessary, but evidently there
1566 are cases where a timer is left active and then goes off, taking a longjmp
1567 to nowhere after the program's stack has changed. In any case, this is
1568 safe because the CONNECT module uses no timer of any kind, and no other timer
1569 should be armed while Kermit is in CONNECT mode.
1570 */
1571 ttimoff(); /* Turn off any timer interrupts */
1572
1573 #ifdef CK_TRIGGER
1574 makestr(&triggerval,NULL); /* Reset trigger */
1575 #endif /* CK_TRIGGER */
1576
1577 if (!local) {
1578 #ifdef NETCONN
1579 printf("Sorry, you must SET LINE or SET HOST first\n");
1580 #else
1581 printf("Sorry, you must SET LINE first\n");
1582 #endif /* NETCONN */
1583 goto conret0;
1584 }
1585 if (speed < 0L && network == 0 && ttfdflg == 0) {
1586 printf("Sorry, you must SET SPEED first\n");
1587 goto conret0;
1588 }
1589 #ifdef TCPSOCKET
1590 if (network && (nettype != NET_TCPB)
1591 #ifdef SUNX25
1592 && (nettype != NET_SX25)
1593 #endif /* SUNX25 */
1594 #ifdef IBMX25
1595 && (nettype != NET_IX25)
1596 #endif /* IBMX25 */
1597 #ifdef NETCMD
1598 && (nettype != NET_CMD)
1599 #endif /* NETCMD */
1600 #ifdef NETPTY
1601 && (nettype != NET_PTY)
1602 #endif /* NETPTY */
1603 ) {
1604 printf("Sorry, network type not supported\n");
1605 goto conret0;
1606 }
1607 #endif /* TCPSOCKET */
1608
1609 #ifdef DYNAMIC
1610 if (!ibuf) {
1611 if (!(ibuf = malloc(IBUFL+1))) { /* Allocate input line buffer */
1612 printf("Sorry, CONNECT input buffer can't be allocated\n");
1613 goto conret0;
1614 } else {
1615 ibp = ibuf;
1616 ibc = 0;
1617 }
1618 }
1619 if (!obuf) {
1620 if (!(obuf = malloc(OBUFL+1))) { /* Allocate output line buffer */
1621 printf("Sorry, CONNECT output buffer can't be allocated\n");
1622 goto conret0;
1623 } else {
1624 obp = obuf;
1625 obc = 0;
1626 }
1627 }
1628 if (!kbuf) {
1629 if (!(kbuf = malloc(KBUFL+1))) { /* Allocate keyboard input buffer */
1630 printf("Sorry, CONNECT keyboard buffer can't be allocated\n");
1631 goto conret0;
1632 }
1633 }
1634 if (!temp) {
1635 if (!(temp = malloc(TMPLEN+1))) { /* Allocate temporary buffer */
1636 printf("Sorry, CONNECT temporary buffer can't be allocated\n");
1637 goto conret0;
1638 }
1639 }
1640 #else
1641 #ifdef COMMENT
1642 ibp = ibuf;
1643 ibc = 0;
1644 #endif /* COMMENT */
1645 obp = obuf;
1646 obc = 0;
1647 #endif /* DYNAMIC */
1648
1649 kbp = kbuf; /* Always clear these. */
1650 *kbp = NUL; /* No need to preserve them between */
1651 kbc = 0; /* CONNECT sessions. */
1652
1653 #ifdef DEBUG
1654 if (deblog) {
1655 debug(F101,"CONNECT conect entry ttyfd","",ttyfd);
1656 debug(F101,"CONNECT conect entry ibc","",ibc);
1657 debug(F101,"CONNECT conect entry obc","",obc);
1658 debug(F101,"CONNECT conect entry kbc","",kbc);
1659 #ifdef CK_TRIGGER
1660 debug(F110,"CONNECT conect trigger",tt_trigger[0],0);
1661 #endif /* CK_TRIGGER */
1662 if (ttyfd > -1) {
1663 n = ttchk();
1664 debug(F101,"CONNECT conect entry ttchk","",n);
1665 }
1666 }
1667 #endif /* DEBUG */
1668
1669 if (ttyfd < 0) { /* If communication device not open */
1670 debug(F101,"CONNECT ttnproto","",ttnproto);
1671 debug(F111,"CONNECT opening",ttname,0); /* Open it now */
1672 if (ttopen(ttname,
1673 &local,
1674 network ? -nettype : mdmtyp,
1675 0
1676 ) < 0) {
1677 ckmakmsg(temp,TMPLEN,"Sorry, can't open ",ttname,NULL,NULL);
1678 perror(temp);
1679 debug(F110,"CONNECT open failure",ttname,0);
1680 goto conret0;
1681 }
1682 #ifdef IKS_OPTION
1683 /* If peer is in Kermit server mode, return now. */
1684 if (TELOPT_SB(TELOPT_KERMIT).kermit.u_start)
1685 return(0);
1686 #endif /* IKS_OPTION */
1687 }
1688 dohangup = 0; /* Hangup not requested yet */
1689 #ifdef ANYX25
1690 dox25clr = 0; /* X.25 clear not requested yet */
1691 #endif /* ANYX25 */
1692
1693 if (msgflg) {
1694 #ifdef NETCONN
1695 if (network) {
1696 if (ttpipe)
1697 printf("Connecting via command \"%s\"",ttname);
1698 else
1699 printf("Connecting to host %s",ttname);
1700 #ifdef ANYX25
1701 if (nettype == NET_SX25 || nettype == NET_IX25)
1702 printf(", Link ID %d, LCN %d",linkid,lcn);
1703 #endif /* ANYX25 */
1704 } else {
1705 #endif /* NETCONN */
1706 printf("Connecting to %s",ttname);
1707 if (speed > -1L) printf(", speed %ld",speed);
1708 #ifdef NETCONN
1709 }
1710 #endif /* NETCONN */
1711 if (tt_escape) {
1712 printf("\r\n");
1713 shoesc(escape);
1714 printf("Type the escape character followed by C to get back,\r\n");
1715 printf("or followed by ? to see other options.\r\n");
1716 } else {
1717 printf(".\r\n\nESCAPE CHARACTER IS DISABLED\r\n\n");
1718 }
1719 if (seslog) {
1720 extern int slogts;
1721 char * s = "";
1722 switch (sessft) {
1723 case XYFT_D:
1724 s = "debug"; break;
1725 case XYFT_T:
1726 s = slogts ? "timestamped-text" : "text"; break;
1727 default:
1728 s = "binary";
1729 }
1730 printf("Session Log: %s, %s\r\n",sesfil,s);
1731 }
1732 if (debses) printf("Debugging Display...)\r\n");
1733 printf("----------------------------------------------------\r\n");
1734 fflush(stdout);
1735 }
1736
1737 /* Condition console terminal and communication line */
1738
1739 if (conbin((char)escape) < 0) {
1740 printf("Sorry, can't condition console terminal\n");
1741 goto conret0;
1742 }
1743 debug(F101,"CONNECT cmask","",cmask);
1744 debug(F101,"CONNECT cmdmsk","",cmdmsk);
1745 debug(F101,"CONNECT speed before ttvt","",speed);
1746 if ((n = ttvt(speed,flow)) < 0) { /* Enter "virtual terminal" mode */
1747 if (!network) {
1748 debug(F101,"CONNECT ttvt","",n);
1749 tthang(); /* Hang up and close the device. */
1750 ttclos(0);
1751 dologend();
1752 if (ttopen(ttname, /* Open it again... */
1753 &local,
1754 network ? -nettype : mdmtyp,
1755 0
1756 ) < 0) {
1757 ckmakmsg(temp,TMPLEN,"Sorry, can't reopen ",ttname,NULL,NULL);
1758 perror(temp);
1759 goto conret0;
1760 }
1761 #ifdef IKS_OPTION
1762 if (TELOPT_SB(TELOPT_KERMIT).kermit.u_start)
1763 return(0);
1764 #endif /* IKS_OPTION */
1765 if (ttvt(speed,flow) < 0) { /* Try virtual terminal mode again. */
1766 conres(); /* Failure this time is fatal. */
1767 printf("Sorry, Can't condition communication line\n");
1768 goto conret0;
1769 }
1770 }
1771 }
1772 debug(F101,"CONNECT ttvt ok, escape","",escape);
1773
1774 debug(F101,"CONNECT carrier-watch","",carrier);
1775 if ((!network
1776 #ifdef TN_COMPORT
1777 || istncomport()
1778 #endif /* TN_COMPORT */
1779 ) && (carrier != CAR_OFF)) {
1780 int x;
1781 x = ttgmdm();
1782 debug(F100,"CONNECT ttgmdm","",x);
1783 if ((x > -1) && !(x & BM_DCD)) {
1784 #ifndef NOHINTS
1785 extern int hints;
1786 #endif /* NOHINTS */
1787 debug(F100,"CONNECT ttgmdm CD test fails","",x);
1788 conres();
1789 printf("?Carrier required but not detected.\n");
1790 #ifndef NOHINTS
1791 if (!hints)
1792 return(0);
1793 printf("***********************************\n");
1794 printf(" Hint: To CONNECT to a serial device that\n");
1795 printf(" is not presenting the Carrier Detect signal,\n");
1796 printf(" first tell C-Kermit to:\n\n");
1797 printf(" SET CARRIER-WATCH OFF\n\n");
1798 printf("***********************************\n\n");
1799 #endif /* NOHINTS */
1800 goto conret0;
1801 }
1802 debug(F100,"CONNECT ttgmdm ok","",0);
1803 }
1804 #ifndef NOCSETS
1805 /* Set up character set translations */
1806
1807 unicode = 0; /* Assume Unicode won't be involved */
1808 tcs = 0; /* "Transfer" or "Other" charset */
1809 sxo = rxo = NULL; /* Initialize byte-to-byte functions */
1810 sxi = rxi = NULL;
1811 if (tcsr != tcsl) { /* Remote and local sets differ... */
1812 #ifdef UNICODE
1813 if (tcsr == FC_UTF8 || /* Remote charset is UTF-8 */
1814 tcsl == FC_UTF8) { /* or local one is. */
1815 xuf = xl_ufc[tcsl]; /* Incoming Unicode to local */
1816 if (xuf || tcsl == FC_UTF8) {
1817 tcs = (tcsr == FC_UTF8) ? tcsl : tcsr; /* The "other" set */
1818 xfu = xl_fcu[tcs]; /* Local byte to remote Unicode */
1819 if (xfu)
1820 unicode = (tcsr == FC_UTF8) ? 1 : 2;
1821 }
1822 tcssize = fcsinfo[tcs].size; /* Size of other character set. */
1823 } else {
1824 #endif /* UNICODE */
1825 tcs = gettcs(tcsr,tcsl); /* Get intermediate set. */
1826 sxo = xls[tcs][tcsl]; /* translation function */
1827 rxo = xlr[tcs][tcsr]; /* pointers for output functions */
1828 sxi = xls[tcs][tcsr]; /* and for input functions. */
1829 rxi = xlr[tcs][tcsl];
1830 #ifdef UNICODE
1831 }
1832 #endif /* UNICODE */
1833 }
1834 /*
1835 This is to prevent use of zmstuff() and zdstuff() by translation functions.
1836 They only work with disk i/o, not with communication i/o. Luckily Russian
1837 translation functions don't do any stuffing...
1838 */
1839 langsv = language;
1840 #ifndef NOCYRIL
1841 if (language != L_RUSSIAN)
1842 #endif /* NOCYRIL */
1843 language = L_USASCII;
1844
1845 #ifdef COMMENT
1846 #ifdef DEBUG
1847 if (deblog) {
1848 debug(F101,"CONNECT tcs","",tcs);
1849 debug(F101,"CONNECT tcsl","",tcsl);
1850 debug(F101,"CONNECT tcsr","",tcsr);
1851 debug(F101,"CONNECT fcsinfo[tcsl].size","",fcsinfo[tcsl].size);
1852 debug(F101,"CONNECT fcsinfo[tcsr].size","",fcsinfo[tcsr].size);
1853 debug(F101,"CONNECT unicode","",unicode);
1854 }
1855 #endif /* DEBUG */
1856 #endif /* COMMENT */
1857
1858 #ifdef CK_XYZ
1859 #ifndef XYZ_INTERNAL
1860 {
1861 extern int binary; /* See about ZMODEM autodownloads */
1862 char * s;
1863 s = binary ? ptab[PROTO_Z].p_b_rcmd : ptab[PROTO_Z].p_t_rcmd;
1864 if (!s) s = "";
1865 zmdlok = (*s != NUL); /* OK if we have external commands */
1866 }
1867 #endif /* XYZ_INTERNAL */
1868 #endif /* CK_XYZ */
1869
1870 #ifndef NOESCSEQ
1871 /*
1872 We need to activate the escape-sequence recognition feature when:
1873 (a) translation is elected, AND
1874 (b) the local and/or remote set is a 7-bit set other than US ASCII.
1875 Or:
1876 SET TERMINAL APC is not OFF (handled in the next statement).
1877 */
1878 escseq = (tcs != TC_TRANSP) && /* Not transparent */
1879 (fcsinfo[tcsl].size == 128 || fcsinfo[tcsr].size == 128) && /* 7 bits */
1880 (fcsinfo[tcsl].code != FC_USASCII); /* But not ASCII */
1881 #endif /* NOESCSEQ */
1882 #endif /* NOCSETS */
1883
1884 #ifndef NOESCSEQ
1885 #ifdef CK_APC
1886 escseq = escseq || (apcstatus & APC_ON);
1887 apcactive = 0; /* An APC command is not active */
1888 apclength = 0; /* ... */
1889 #endif /* CK_APC */
1890 inesc = ES_NORMAL; /* Initial state of recognizer */
1891 debug(F101,"CONNECT escseq","",escseq);
1892 #endif /* NOESCSEQ */
1893
1894 parent_id = getpid(); /* Get parent's pid for signalling */
1895 debug(F101,"CONNECT parent pid","",parent_id);
1896
1897 if (xpipe[0] > -1) /* If old pipe hanging around, close */
1898 close(xpipe[0]);
1899 xpipe[0] = -1;
1900 if (xpipe[1] > -1)
1901 close(xpipe[1]);
1902 xpipe[1] = -1;
1903 goterr = 0; /* Error flag for pipe & fork */
1904 if (pipe(xpipe) != 0) { /* Create new pipe to pass info */
1905 perror("Can't make pipe"); /* between forks. */
1906 debug(F101,"CONNECT pipe error","",errno);
1907 goterr = 1;
1908 } else
1909 #ifdef BEOSORBEBOX
1910 {
1911 pid = spawn_thread(concld, "Lower Fork", B_NORMAL_PRIORITY, NULL);
1912 resume_thread(pid);
1913 }
1914 #else
1915 if ((pid = fork()) == (PID_T) -1) { /* Pipe OK, make port fork. */
1916 perror("Can't make port fork");
1917 debug(F101,"CONNECT fork error","",errno);
1918 goterr = 1;
1919 }
1920 #endif /* BEOSORBEBOX */
1921 debug(F101,"CONNECT created fork, pid","",pid);
1922 if (goterr) { /* Failed to make pipe or fork */
1923 conres(); /* Reset the console. */
1924 if (msgflg) {
1925 printf("\r\nCommunications disconnect (Back at %s)\r\n",
1926 *myhost ?
1927 myhost :
1928 #ifdef UNIX
1929 "local UNIX system"
1930 #else
1931 "local system"
1932 #endif /* UNIX */
1933 );
1934 }
1935 printf("\n");
1936 what = W_NOTHING; /* So console modes are set right. */
1937 #ifndef NOCSETS
1938 language = langsv; /* Restore language */
1939 #endif /* NOCSETS */
1940 parent_id = (PID_T) 0; /* Clean up */
1941 goto conret1;
1942 }
1943 debug(F101,"CONNECT fork pid","",pid);
1944
1945 /* Upper fork (KEYB fork) reads keystrokes and sends them out. */
1946
1947 if (pid) { /* pid != 0, so I am the upper fork. */
1948 /*
1949 Before doing anything significant, the child fork must wait for a go-ahead
1950 character from xpipe[0]. Before starting to wait, we have enough time to
1951 clear buffers and set up the signal handler. When done with this, we will
1952 allow the child to continue by satisfying its pending read.
1953
1954 Remember the child and parent have separate address space. The child has
1955 its own copy of input buffers, so we must clear the input buffers in the
1956 parent. Otherwise strange effects may occur, like chunks of characters
1957 repeatedly echoed on terminal screen. The child process is designed to
1958 empty its input buffers by reading all available characters and either
1959 echoing them on the terminal screen or saving them for future use in the
1960 parent. The latter case happens during APC processing - see the code around
1961 CEV_APC occurrences to see how the child passes its ibuf etc to parent via
1962 xpipe, for preservation until the next entry to this module, to ensure that
1963 no characters are lost between CONNECT sessions.
1964 */
1965
1966 /*
1967 This one needs a bit of extra explanation... In addition to the CONNECT
1968 module's own buffers, which are communicated and synchronized via xpipe,
1969 the low-level UNIX communication routines (ttinc, ttxin, etc) are also
1970 buffered, statically, in the ckutio.c module. But when the two CONNECT
1971 forks split off, the lower fork is updating this buffer's pointers and
1972 counts, but the upper fork never finds out about it and still has the old
1973 ones. The following UNIX-specific call to the ckutio.c module takes care
1974 of this... Without it, we get dual echoing of incoming characters.
1975 */
1976 ttflux();
1977 /*
1978 At this point, perhaps you are wondering why we use forks at all. It is
1979 simply because there is no other method portable among all UNIX variations.
1980 Not threads, not select(), ... (Yes, select() is more common now; it might
1981 actually be worth writing a variation of this module that works like BSD
1982 Telnet, one fork, driven by select()).
1983 */
1984 ibp = ibuf; /* Clear ibuf[]. */
1985 ibc = 0; /* Child now has its own copy */
1986 signal(CK_FORK_SIG, pipeint); /* Handler for messages from child. */
1987 write(xpipe[1], ibuf, 1); /* Allow child to proceed */
1988 close(xpipe[1]); xpipe[1] = -1; /* Parent - prevent future writes */
1989
1990 what = W_CONNECT; /* Keep track of what we're doing */
1991 active = 1;
1992 debug(F101,"CONNECT keyboard fork duplex","",duplex);
1993 /*
1994 Catch communication errors or mode changes in lower fork.
1995
1996 Note: Some C compilers (e.g. Cray UNICOS) interpret the ANSI C standard
1997 about setjmp() in a way that disallows constructions like:
1998
1999 if ((var = [sig]setjmp(env)) == 0) ...
2000
2001 which prevents the value returned by cklongjmp() from being used at all.
2002 So the signal handlers set a global variable, sjval, instead.
2003 */
2004 if (
2005 #ifdef CK_POSIX_SIG
2006 sigsetjmp(con_env,1)
2007 #else
2008 setjmp(con_env)
2009 #endif /* CK_POSIX_SIG */
2010 == 0) { /* Normal entry... */
2011 jbset = 1; /* Now we have a longjmp buffer */
2012 sjval = CEV_NO; /* Initialize setjmp return code. */
2013
2014 debug(F101,"CONNECT setjmp normal entry","",sjval);
2015
2016 #ifdef ANYX25
2017 if (network && (nettype == NET_SX25 || nettype == NET_IX25)) {
2018 obufl = 0;
2019 bzero (x25obuf,sizeof(x25obuf));
2020 }
2021 #endif /* ANYX25 */
2022 /*
2023 Here is the big loop that gets characters from the keyboard and sends them
2024 out the communication device. There are two components to the communication
2025 path: the connection from the keyboard to C-Kermit, and from C-Kermit to
2026 the remote computer. The treatment of the 8th bit of keyboard characters
2027 is governed by SET COMMAND BYTESIZE (cmdmsk). The treatment of the 8th bit
2028 of characters sent to the remote is governed by SET TERMINAL BYTESIZE
2029 (cmask). This distinction was introduced in edit 5A(164).
2030 */
2031 while (active) {
2032 #ifndef NOSETKEY
2033 if (kmptr) { /* Have current macro? */
2034 debug(F100,"CONNECT kmptr non NULL","",0);
2035 if ((c = (CHAR) *kmptr++) == NUL) { /* Get char from it */
2036 kmptr = NULL; /* If no more chars, */
2037 debug(F100,"CONNECT macro empty, continuing","",0);
2038 continue; /* reset pointer and continue */
2039 }
2040 debug(F000,"CONNECT char from macro","",c);
2041 } else /* No macro... */
2042 #endif /* NOSETKEY */
2043 c = CONGKS(); /* Read from keyboard */
2044
2045 #ifdef COMMENT
2046 /* too much... */
2047 debug(F101,"CONNECT ** KEYB","",c);
2048 #endif /* COMMENT */
2049 if (c == -1) { /* If read() got an error... */
2050 debug(F101,"CONNECT keyboard read errno","",errno);
2051 #ifdef COMMENT
2052 /*
2053 This seems to cause problems. If read() returns -1, the signal has already
2054 been delivered, and nothing will wake up the pause().
2055 */
2056 pause(); /* Wait for transmitter to finish. */
2057 #else
2058 #ifdef A986
2059 /*
2060 On Altos machines with Xenix 3.0, pressing DEL in connect mode brings us
2061 here (reason unknown). The console line discipline at this point has
2062 intr = ^C. The communications tty has intr = DEL but we get here after
2063 pressing DEL on the keyboard, even when the remote system has been set not
2064 to echo. With A986 defined, we stay in the read loop and beep only if the
2065 offending character is not DEL.
2066 */
2067 if ((c & 127) != 127) conoc(BEL);
2068 #else
2069 #ifdef EINTR
2070 /*
2071 This can be caused by the other fork signalling this one about
2072 an echoing change during TELNET negotiations.
2073 */
2074 if (errno == EINTR)
2075 continue;
2076 #endif /* EINTR */
2077 conoc(BEL); /* Otherwise, beep */
2078 active = 0; /* and terminate the read loop */
2079 continue;
2080 #endif /* A986 */
2081 #endif /* COMMENT */
2082 }
2083 c &= cmdmsk; /* Do any requested masking */
2084 #ifndef NOSETKEY
2085 /*
2086 Note: kmptr is NULL if we got character c from the keyboard, and it is
2087 not NULL if it came from a macro. In the latter case, we must avoid
2088 expanding it again.
2089 */
2090 if (!kmptr && macrotab[c]) { /* Macro definition for c? */
2091 kmptr = macrotab[c]; /* Yes, set up macro pointer */
2092 continue; /* and restart the loop, */
2093 } else c = keymap[c]; /* else use single-char keymap */
2094 #endif /* NOSETKEY */
2095 if (
2096 #ifndef NOSETKEY
2097 !kmptr &&
2098 #endif /* NOSETKEY */
2099 (tt_escape && (c & 0xff) == escape)) { /* Escape char? */
2100 debug(F000,"CONNECT got escape","",c);
2101 c = CONGKS() & 0177; /* Got esc, get its arg */
2102 /* No key mapping here */
2103 doesc((char) c); /* Now process it */
2104
2105 } else { /* It's not the escape character */
2106 csave = c; /* Save it before translation */
2107 /* for local echoing. */
2108 #ifndef NOCSETS
2109 if (inesc == ES_NORMAL) { /* If not inside escape seq.. */
2110 /* Translate character sets */
2111 #ifdef UNICODE
2112 int x;
2113 CHAR ch;
2114 ch = c;
2115 if (unicode == 1) { /* Remote is UTF-8 */
2116 outxcount = b_to_u(ch,outxbuf,OUTXBUFSIZ,tcssize);
2117 outxbuf[outxcount] = NUL;
2118 } else if (unicode == 2) { /* Local is UTF-8 */
2119 x = u_to_b(ch); /* So translate to remote byte */
2120 if (x < 0)
2121 continue;
2122 outxbuf[0] = (unsigned)(x & 0xff);
2123 outxcount = 1;
2124 outxbuf[outxcount] = NUL;
2125 } else {
2126 #endif /* UNICODE */
2127 /* Local-to-intermediate */
2128 if (sxo) c = (*sxo)((char)c);
2129 /* Intermediate-to-remote */
2130 if (rxo) c = (*rxo)((char)c);
2131 outxbuf[0] = c;
2132 outxcount = 1;
2133 outxbuf[outxcount] = NUL;
2134 #ifdef UNICODE
2135 }
2136 #endif /* UNICODE */
2137 }
2138 if (escseq)
2139 apcrc = chkaes((char)c);
2140 #else
2141 outxbuf[0] = c;
2142 outxcount = 1;
2143 outxbuf[outxcount] = NUL;
2144 #endif /* NOCSETS */
2145 for (i = 0; i < outxcount; i++) {
2146 c = outxbuf[i];
2147 /*
2148 If Shift-In/Shift-Out is selected and we have a 7-bit connection,
2149 handle shifting here.
2150 */
2151 if (sosi) { /* Shift-In/Out selected? */
2152 if (cmask == 0177) { /* In 7-bit environment? */
2153 if (c & 0200) { /* 8-bit character? */
2154 if (outshift == 0) { /* If not shifted, */
2155 ttoc(dopar(SO)); /* shift. */
2156 outshift = 1;
2157 }
2158 } else {
2159 if (outshift == 1) { /* 7-bit character */
2160 ttoc(dopar(SI)); /* If shifted, */
2161 outshift = 0; /* unshift. */
2162 }
2163 }
2164 }
2165 if (c == SO) outshift = 1; /* User typed SO */
2166 if (c == SI) outshift = 0; /* User typed SI */
2167 }
2168 c &= cmask; /* Apply Kermit-to-host mask now. */
2169 #ifdef SUNX25
2170 if (network && nettype == NET_SX25) {
2171 if (padparms[PAD_ECHO]) {
2172 if (debses)
2173 conol(dbchr(c)) ;
2174 else
2175 if ((c != padparms[PAD_CHAR_DELETE_CHAR]) &&
2176 (c != padparms[PAD_BUFFER_DELETE_CHAR]) &&
2177 (c != padparms[PAD_BUFFER_DISPLAY_CHAR]))
2178 conoc(c) ;
2179 if (seslog && !sessft)
2180 logchar(c);
2181 }
2182 if (c == CR && (padparms[PAD_LF_AFTER_CR] == 4 ||
2183 padparms[PAD_LF_AFTER_CR] == 5)) {
2184 if (debses)
2185 conol(dbchr(LF)) ;
2186 else
2187 conoc(LF) ;
2188 if (seslog && !sessft)
2189 logchar(LF);
2190 }
2191 if (c == padparms[PAD_BREAK_CHARACTER]) {
2192 breakact();
2193 } else if (padparms[PAD_DATA_FORWARD_TIMEOUT]) {
2194 tosend = 1;
2195 x25obuf [obufl++] = c;
2196 } else if (((c == padparms[PAD_CHAR_DELETE_CHAR])||
2197 (c == padparms[PAD_BUFFER_DELETE_CHAR]) ||
2198 (c == padparms[PAD_BUFFER_DISPLAY_CHAR]))
2199 && (padparms[PAD_EDITING])) {
2200 if (c == padparms[PAD_CHAR_DELETE_CHAR]) {
2201 if (obufl > 0) {
2202 conol("\b \b"); obufl--;
2203 } else {}
2204 } else if
2205 (c == padparms[PAD_BUFFER_DELETE_CHAR]) {
2206 conol ("\r\nPAD Buffer Deleted\r\n");
2207 obufl = 0;
2208 } else if
2209 (c==padparms[PAD_BUFFER_DISPLAY_CHAR]) {
2210 conol("\r\n");
2211 conol(x25obuf);
2212 conol("\r\n");
2213 } else {}
2214 } else {
2215 x25obuf [obufl++] = c;
2216 if (obufl == MAXOX25) tosend = 1;
2217 else if (c == CR) tosend = 1;
2218 }
2219 if (tosend) {
2220 if (ttol((CHAR *)x25obuf,obufl) < 0) {
2221 perror ("\r\nCan't send characters");
2222 active = 0;
2223 } else {
2224 bzero (x25obuf,sizeof(x25obuf));
2225 obufl = 0;
2226 tosend = 0;
2227 }
2228 } else {};
2229 } else {
2230 #endif /* SUNX25 */
2231 if (c == '\015') { /* Carriage Return */
2232 int stuff = -1;
2233 if (tnlm) { /* TERMINAL NEWLINE ON */
2234 stuff = LF; /* Stuff LF */
2235 #ifdef TNCODE
2236 } else if (network && /* TELNET NEWLINE */
2237 IS_TELNET()) {
2238 switch (!TELOPT_ME(TELOPT_BINARY) ?
2239 tn_nlm :
2240 tn_b_nlm
2241 ) {
2242 case TNL_CRLF:
2243 stuff = LF;
2244 break;
2245 case TNL_CRNUL:
2246 stuff = NUL;
2247 break;
2248 }
2249 #endif /* TNCODE */
2250 }
2251 if (stuff > -1) {
2252 ttoc(dopar('\015')); /* Send CR */
2253 if (duplex) conoc('\015'); /* Echo CR */
2254 c = stuff; /* Char to stuff */
2255 csave = c;
2256 }
2257 }
2258 #ifdef TNCODE
2259 /* If user types the 0xff character (TELNET IAC), it must be doubled. */
2260 else /* Not CR */
2261 if ((dopar((CHAR) c) == IAC) && /* IAC (0xff) */
2262 network && IS_TELNET()) {
2263 /* Send one copy now */
2264 /* and the other one just below. */
2265 ttoc((char)IAC);
2266 }
2267 #endif /* TNCODE */
2268 /* Send the character */
2269
2270 if (ttoc((char)dopar((CHAR) c)) > -1) {
2271 if (duplex) { /* If half duplex, must echo */
2272 if (debses)
2273 conol(dbchr(csave)); /* original char */
2274 else /* not the translated one */
2275 conoc((char)csave);
2276 if (seslog) { /* And maybe log it too */
2277 c2 = csave;
2278 if (sessft == 0 && csave == '\r')
2279 c2 = '\n';
2280 logchar((char)c2);
2281 }
2282 }
2283 } else {
2284 perror("\r\nCan't send character");
2285 active = 0;
2286 }
2287 #ifdef SUNX25
2288 }
2289 #endif /* SUNX25 */
2290 } /* for... */
2291 }
2292 }
2293
2294 /* now active == 0 */
2295 signal(CK_FORK_SIG, SIG_IGN); /* Turn off CK_FORK_SIG */
2296 sjval = CEV_NO; /* Set to hangup */
2297 } /* Come here on termination of child */
2298
2299 /* cklongjmp() executed in pipeint() (parent only!) comes here */
2300
2301 /*
2302 Now the child fork is gone or is waiting for CK_FORK_SIG in ck_sndmsg().
2303 So we can't get (in the parent) any subsequent CK_FORK_SIG signals until
2304 we signal the child with CK_FORK_SIG.
2305 */
2306 debug(F100,"CONNECT signaling port fork","",0);
2307 signal(CK_FORK_SIG, SIG_IGN); /* Turn this off */
2308 debug(F101,"CONNECT killing port fork","",pid);
2309 if (pid) {
2310 int x = 0;
2311 #ifdef BEOSORBEBOX
2312 {
2313 long ret_val;
2314 x = kill(pid,SIGKILLTHR); /* Kill lower fork */
2315 wait_for_thread(pid, &ret_val);
2316 }
2317 #else
2318 #ifdef Plan9
2319 x = kill(pid,SIGKILL); /* Kill lower fork */
2320 #else
2321 x = kill(pid,9);
2322 #endif /* Plan9 */
2323 #endif /* BEOSORBEBOX */
2324 wait((WAIT_T *)0); /* Wait till gone. */
2325 if (x < 0) {
2326 printf("WARNING: Failure to kill fork, pid %d: %s, errno=%d\n",
2327 (int) pid, ck_errstr(), errno);
2328 debug(F111,"CONNECT error killing pid",ck_errstr(),errno);
2329 }
2330 debug(F101,"CONNECT killed port fork","",pid);
2331 pid = (PID_T) 0;
2332 }
2333 if (sjval == CEV_HUP) { /* Read error on comm device */
2334 dohangup = 1; /* so we want to hang up our side */
2335 #ifdef NETCONN
2336 if (network) { /* and/or close network connection */
2337 ttclos(0);
2338 dologend();
2339 #ifdef SUNX25
2340 if (nettype == NET_SX25) /* If X.25, restore the PAD params */
2341 initpad();
2342 #endif /* SUNX25 */
2343 }
2344 #endif /* NETCONN */
2345 }
2346 #ifdef CK_APC
2347 if (sjval == CEV_APC) { /* Application Program Command rec'd */
2348 apcactive = APC_REMOTE; /* Flag APC as active */
2349 active = 0; /* Flag CONNECT as inactive */
2350 }
2351 #endif /* CK_APC */
2352 conres(); /* Reset the console. */
2353 if (dohangup > 0) { /* If hangup requested, do that. */
2354 #ifndef NODIAL
2355 if (dohangup > 1) /* User asked for it */
2356 if (mdmhup() < 1) /* Maybe hang up via modem */
2357 #endif /* NODIAL */
2358 tthang(); /* And make sure we don't hang up */
2359 dohangup = 0; /* again unless requested again. */
2360 }
2361
2362 #ifdef COMMENT
2363 #ifdef NETCONN
2364 #ifdef SIGPIPE
2365 if (network && sigpiph) /* Restore previous SIGPIPE handler */
2366 (VOID) signal(SIGPIPE, sigpiph);
2367 #endif /* SIGPIPE */
2368 #endif /* NETCONN */
2369 #endif /* COMMENT */
2370
2371 #ifdef ANYX25
2372 if (dox25clr) { /* If X.25 Clear requested */
2373 x25clear(); /* do that. */
2374 #ifndef IBMX25
2375 initpad();
2376 #endif /* IBMX25 */
2377 dox25clr = 0; /* But only once. */
2378 }
2379 #endif /* ANYX25 */
2380
2381 if (quitnow) doexit(GOOD_EXIT,xitsta); /* Exit now if requested. */
2382 if (msgflg)
2383 printf("(Back at %s)", *myhost ? myhost : "local UNIX system");
2384 #ifdef CK_APC
2385 if (!apcactive)
2386 #endif /* CK_APC */
2387 printf("\n");
2388 what = W_NOTHING; /* So console modes set right. */
2389 #ifndef NOCSETS
2390 language = langsv; /* Restore language */
2391 #endif /* NOCSETS */
2392 parent_id = (PID_T) 0;
2393 goto conret1;
2394
2395 }
2396 #ifndef BEOSORBEBOX
2397 else { /* *** */ /* Inferior reads, prints port input */
2398 concld(/* (void *)&pid */);
2399 }
2400 #endif /* BEOSORBEBOX */
2401
2402 conret1:
2403 conret = 1;
2404 conret0:
2405 signal(CK_FORK_SIG, SIG_IGN); /* In case this wasn't done already */
2406 debug(F101,"CONNECT conect exit ibc","",ibc);
2407 debug(F101,"CONNECT conect exit obc","",obc);
2408 close(xpipe[0]); xpipe[0] = -1; /* Close the pipe */
2409 close(xpipe[1]); xpipe[1] = -1;
2410 if (msgflg) {
2411 #ifdef CK_APC
2412 if (apcactive == APC_LOCAL)
2413 printf("\n");
2414 #endif /* CK_APC */
2415 printf("----------------------------------------------------\r\n");
2416 }
2417 fflush(stdout);
2418 return(conret);
2419 }
2420
2421
2422 /* H C O N N E -- Give help message for connect. */
2423
2424 int
hconne()2425 hconne() {
2426 int c;
2427 static char *hlpmsg[] = {
2428 "\r\n ? for this message",
2429 "\r\n 0 (zero) to send a null",
2430 "\r\n B to send a BREAK",
2431 #ifdef CK_LBRK
2432 "\r\n L to send a Long BREAK",
2433 #endif /* CK_LBRK */
2434 #ifdef NETCONN
2435 "\r\n I to send a network interrupt packet",
2436 #ifdef TCPSOCKET
2437 "\r\n A to send Are You There?",
2438 #endif /* TCPSOCKET */
2439 #ifdef ANYX25
2440 "\r\n R to reset X.25 virtual circuit",
2441 #endif /* ANYX25 */
2442 #endif /* NETCONN */
2443 "\r\n U to hangup and close the connection",
2444 "\r\n Q to hangup and quit Kermit",
2445 "\r\n S for status",
2446 #ifdef NOPUSH
2447 "\r\n ! to push to local shell (disabled)",
2448 "\r\n Z to suspend (disabled)",
2449 #else
2450 "\r\n ! to push to local shell",
2451 #ifdef NOJC
2452 "\r\n Z to suspend (disabled)",
2453 #else
2454 "\r\n Z to suspend",
2455 #endif /* NOJC */
2456 #endif /* NOPUSH */
2457 "\r\n \\ backslash code:",
2458 "\r\n \\nnn decimal character code",
2459 "\r\n \\Onnn octal character code",
2460 "\r\n \\Xhh hexadecimal character code",
2461 "\r\n terminate with carriage return.",
2462 "\r\n Type the escape character again to send the escape character, or",
2463 "\r\n press the space-bar to resume the CONNECT command.\r\n",
2464 "" };
2465
2466 conol("\r\n----------------------------------------------------");
2467 conol("\r\nPress C to return to ");
2468 conol(*myhost ? myhost : "the C-Kermit prompt");
2469 conol(", or:");
2470 conola(hlpmsg); /* Print the help message. */
2471 conol("Command>"); /* Prompt for command. */
2472 c = CONGKS() & 0177; /* Get character, strip any parity. */
2473 /* No key mapping or translation here */
2474 if (c != CMDQ)
2475 conoll("");
2476 conoll("----------------------------------------------------");
2477 return(c); /* Return it. */
2478 }
2479
2480
2481 /* D O E S C -- Process an escape character argument */
2482
2483 VOID
2484 #ifdef CK_ANSIC
doesc(char c)2485 doesc(char c)
2486 #else
2487 doesc(c) char c;
2488 #endif /* CK_ANSIC */
2489 /* doesc */ {
2490 CHAR d;
2491
2492 debug(F101,"CONNECT doesc","",c);
2493 while (1) {
2494 if (c == escape) { /* Send escape character */
2495 d = dopar((CHAR) c); ttoc((char) d); return;
2496 } else /* Or else look it up below. */
2497 if (isupper(c)) c = tolower(c);
2498
2499 switch(c) {
2500
2501 case 'c': /* Escape back to prompt */
2502 case '\03':
2503 active = 0; conol("\r\n"); return;
2504
2505 case 'b': /* Send a BREAK signal */
2506 case '\02':
2507 ttsndb(); return;
2508
2509 #ifdef NETCONN
2510 case 'i': /* Send Interrupt */
2511 case '\011':
2512 #ifdef TCPSOCKET
2513 #ifndef IP
2514 #define IP 244
2515 #endif /* IP */
2516 if (network && IS_TELNET()) { /* TELNET */
2517 temp[0] = (CHAR) IAC; /* I Am a Command */
2518 temp[1] = (CHAR) IP; /* Interrupt Process */
2519 temp[2] = NUL;
2520 ttol((CHAR *)temp,2);
2521 } else
2522 #endif /* TCPSOCKET */
2523 #ifdef SUNX25
2524 if (network && (nettype == NET_SX25)) {
2525 (VOID) x25intr(0); /* X.25 interrupt packet */
2526 conol("\r\n");
2527 } else
2528 #endif /* SUNX25 */
2529 conoc(BEL);
2530 return;
2531
2532 #ifdef TCPSOCKET
2533 case 'a': /* "Are You There?" */
2534 case '\01':
2535 #ifndef AYT
2536 #define AYT 246
2537 #endif /* AYT */
2538 if (network && IS_TELNET()) {
2539 temp[0] = (CHAR) IAC; /* I Am a Command */
2540 temp[1] = (CHAR) AYT; /* Are You There? */
2541 temp[2] = NUL;
2542 ttol((CHAR *)temp,2);
2543 } else conoc(BEL);
2544 return;
2545 #endif /* TCPSOCKET */
2546 #endif /* NETCONN */
2547
2548 #ifdef CK_LBRK
2549 case 'l': /* Send a Long BREAK signal */
2550 ttsndlb(); return;
2551 #endif /* CK_LBRK */
2552
2553 case 'u': /* Hangup */
2554 /* case '\010': */ /* No, too dangerous */
2555 #ifdef ANYX25
2556 if (network && (nettype == NET_SX25 || nettype == NET_IX25))
2557 dox25clr = 1;
2558 else
2559 #endif /* ANYX25 */
2560 dohangup = 2; active = 0; conol("\r\nHanging up "); return;
2561
2562 #ifdef ANYX25
2563 case 'r': /* Reset the X.25 virtual circuit */
2564 case '\022':
2565 if (network && (nettype == NET_SX25 || nettype == NET_IX25))
2566 (VOID) x25reset(0,0);
2567 conol("\r\n");
2568 return;
2569 #endif /* ANYX25 */
2570
2571 case 'q': /* Quit */
2572 dohangup = 2; quitnow = 1; active = 0; conol("\r\n"); return;
2573
2574 case 's': /* Status */
2575 conoll("");
2576 conoll("----------------------------------------------------");
2577 #ifdef NETCMD
2578 if (ttpipe)
2579 ckmakmsg(temp,TMPLEN," Pipe: \"",ttname,"\"",NULL);
2580 else
2581 #endif /* NETCMD */
2582 ckmakmsg(temp,
2583 TMPLEN,
2584 " ",
2585 (network ? "Host" : "Device"),
2586 ": ",
2587 ttname
2588 );
2589 conoll(temp);
2590 if (!network && speed >= 0L) {
2591 sprintf(temp,"Speed %ld", speed);
2592 conoll(temp);
2593 }
2594 sprintf(temp," Terminal echo: %s", duplex ? "local" : "remote");
2595 conoll(temp);
2596 sprintf(temp," Terminal bytesize: %d", (cmask == 0177) ? 7 : 8);
2597 conoll(temp);
2598 sprintf(temp," Command bytesize: %d", (cmdmsk == 0177) ? 7 : 8 );
2599 conoll(temp);
2600 if (hwparity)
2601 sprintf(temp," Parity[hardware]: %s",parnam((char)hwparity));
2602 else
2603 sprintf(temp," Parity: %s", parnam((char)parity));
2604 conoll(temp);
2605 sprintf(temp," Autodownload: %s", autodl ? "on" : "off");
2606 conoll(temp);
2607 ckmakmsg(temp, /* (would not be safe for sprintf) */
2608 TMPLEN,
2609 " Session log: ",
2610 *sesfil ? sesfil : "(none)",
2611 NULL,
2612 NULL
2613 );
2614 conoll(temp);
2615 #ifndef NOSHOW
2616 if (!network) shomdm();
2617 #endif /* NOSHOW */
2618 #ifdef CKLOGDIAL
2619 {
2620 long z;
2621 z = dologshow(0);
2622 if (z > -1L) {
2623 sprintf(temp," Elapsed time: %s",hhmmss(z));
2624 conoll(temp);
2625 }
2626 }
2627 #endif /* CKLOGDIAL */
2628 conoll("----------------------------------------------------");
2629 return;
2630
2631 case 'h': /* Help */
2632 case '?': /* Help */
2633 c = hconne(); continue;
2634
2635 case '0': /* Send a null */
2636 c = '\0'; d = dopar((CHAR) c); ttoc((char) d); return;
2637
2638 case 'z': case '\032': /* Suspend */
2639 #ifndef NOPUSH
2640 if (!nopush)
2641 stptrap(0);
2642 else
2643 conoc(BEL);
2644 #else
2645 conoc(BEL);
2646 #endif /* NOPUSH */
2647 return;
2648
2649 case '@': /* Start inferior command processor */
2650 case '!':
2651 #ifndef NOPUSH
2652 if (!nopush) {
2653 conres(); /* Put console back to normal */
2654 zshcmd(""); /* Fork a shell. */
2655 if (conbin((char)escape) < 0) {
2656 printf("Error resuming CONNECT session\n");
2657 active = 0;
2658 }
2659 } else conoc(BEL);
2660 #else
2661 conoc(BEL);
2662 #endif /* NOPUSH */
2663 return;
2664
2665 case SP: /* Space, ignore */
2666 return;
2667
2668 default: /* Other */
2669 if (c == CMDQ) { /* Backslash escape */
2670 int x;
2671 ecbp = ecbuf;
2672 *ecbp++ = c;
2673 while (((c = (CONGKS() & cmdmsk)) != '\r') && (c != '\n'))
2674 *ecbp++ = c;
2675 *ecbp = NUL; ecbp = ecbuf;
2676 x = xxesc(&ecbp); /* Interpret it */
2677 if (x >= 0) { /* No key mapping here */
2678 c = dopar((CHAR) x);
2679 ttoc((char) c);
2680 return;
2681 } else { /* Invalid backslash code. */
2682 conoc(BEL);
2683 return;
2684 }
2685 }
2686 conoc(BEL); return; /* Invalid esc arg, beep */
2687 }
2688 }
2689 }
2690 #endif /* NOLOCAL */
2691