home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / c-kermit / ckucns.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  78KB  |  2,721 lines

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