source: trunk/third/kermit/ckucns.c @ 20081

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