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