|
|
1.1 ! root 1: char *connv = "CONNECT Command for UNIX, 5A(047) 23 Nov 92"; ! 2: ! 3: /* C K U C O N -- Dumb terminal connection to remote system, for UNIX */ ! 4: /* ! 5: Author: Frank da Cruz ([email protected], [email protected]), ! 6: Columbia University Center for Computing Activities. ! 7: First released January 1985. ! 8: Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New ! 9: York. Permission is granted to any individual or institution to use this ! 10: software as long as it is not sold for profit. This copyright notice must be ! 11: retained. This software may not be included in commercial products without ! 12: written permission of Columbia University. ! 13: */ ! 14: ! 15: #include "ckcdeb.h" /* Common things first */ ! 16: ! 17: #ifdef NEXT ! 18: #undef NSIG ! 19: #include <sys/wait.h> /* For wait() */ ! 20: #endif /* NEXT */ ! 21: ! 22: #include <signal.h> /* Signals */ ! 23: #include <errno.h> /* Error numbers */ ! 24: ! 25: #ifdef ZILOG /* Longjumps */ ! 26: #include <setret.h> ! 27: #else ! 28: #include <setjmp.h> ! 29: #endif /* ZILOG */ ! 30: ! 31: /* Kermit-specific includes */ ! 32: ! 33: #include "ckcasc.h" /* ASCII characters */ ! 34: #include "ckcker.h" /* Kermit things */ ! 35: #include "ckucmd.h" /* For xxesc() prototype */ ! 36: #include "ckcnet.h" /* Network symbols */ ! 37: #ifndef NOCSETS ! 38: #include "ckcxla.h" /* Character set translation */ ! 39: #endif /* NOCSETS */ ! 40: ! 41: /* Internal function prototypes */ ! 42: ! 43: _PROTOTYP( VOID doesc, (char) ); ! 44: _PROTOTYP( VOID logchar, (char) ); ! 45: _PROTOTYP( int hconne, (void) ); ! 46: _PROTOTYP( VOID shomdm, (void) ); ! 47: ! 48: #ifndef SIGUSR1 /* User-defined signals */ ! 49: #define SIGUSR1 30 ! 50: #endif /* SIGUSR1 */ ! 51: ! 52: #ifndef SIGUSR2 ! 53: #define SIGUSR2 31 ! 54: #endif /* SIGUSR2 */ ! 55: ! 56: /* External variables */ ! 57: ! 58: extern int local, escape, duplex, parity, flow, seslog, sessft, debses, ! 59: mdmtyp, ttnproto, cmask, cmdmsk, network, nettype, deblog, sosi, tnlm, ! 60: xitsta, what, ttyfd, quiet, backgrd, pflag, tt_crd, tn_nlm; ! 61: extern long speed; ! 62: extern char ttname[], sesfil[], myhost[], *ccntab[]; ! 63: ! 64: #ifndef NOSETKEY /* Keyboard mapping */ ! 65: extern KEY *keymap; /* Single-character key map */ ! 66: extern MACRO *macrotab; /* Key macro pointer table */ ! 67: static MACRO kmptr = NULL; /* Pointer to current key macro */ ! 68: #endif /* NOSETKEY */ ! 69: ! 70: /* Global variables local to this module */ ! 71: ! 72: static int quitnow = 0, /* <esc-char>Q was typed */ ! 73: dohangup = 0, /* <esc-char>H was typed */ ! 74: sjval = 0, /* Setjump return value */ ! 75: goterr = 0, /* I/O error flag */ ! 76: #ifndef SUNX25 ! 77: active = 0, /* Lower fork active flag */ ! 78: #endif /* SUNX25 */ ! 79: inshift = 0, /* SO/SI shift states */ ! 80: outshift = 0; ! 81: ! 82: static char kbuf[10], *kbp; /* Keyboard buffer & pointer */ ! 83: static PID_T parent_id = (PID_T)0; /* Process id of keyboard fork */ ! 84: ! 85: static char *ibp; /* Input buffer pointer */ ! 86: static int ibc = 0; /* Input buffer count */ ! 87: #ifdef pdp11 ! 88: #define IBUFL 1536 /* Input buffer length */ ! 89: #else ! 90: #define IBUFL 4096 ! 91: #endif /* pdp11 */ ! 92: ! 93: static char *obp; /* Output buffer pointer */ ! 94: static int obc = 0; /* Output buffer count */ ! 95: #define OBUFL 1024 /* Output buffer length */ ! 96: ! 97: #define TMPLEN 200 /* Temporary message buffer length */ ! 98: #ifdef DYNAMIC ! 99: static char *ibuf = NULL, *obuf = NULL, *temp = NULL; /* Buffers */ ! 100: #else ! 101: static char ibuf[IBUFL], obuf[OBUFL], temp[TMPLEN]; ! 102: #endif /* DYNAMIC */ ! 103: ! 104: /* SunLink X.25 items */ ! 105: ! 106: #ifdef SUNX25 ! 107: static char *p; /* General purpose pointer */ ! 108: char x25ibuf[MAXIX25]; /* Input buffer */ ! 109: char x25obuf[MAXOX25]; /* Output buffer */ ! 110: int active = 0; /* Lower fork active flag */ ! 111: int ibufl; /* Length of input buffer */ ! 112: int obufl; /* Length of output buffer */ ! 113: unsigned char tosend = 0; ! 114: int linkid, lcn; ! 115: static int dox25clr = 0; ! 116: CHAR padparms[MAXPADPARMS+1]; ! 117: static int padpipe[2]; /* Pipe descriptor to pass PAD parms */ ! 118: #endif /* SUNX25 */ ! 119: ! 120: /* Character-set items */ ! 121: ! 122: #ifndef NOCSETS ! 123: #ifdef CK_ANSIC /* ANSI C prototypes... */ ! 124: extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* Character set */ ! 125: extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* translation functions */ ! 126: static CHAR (*sxo)(CHAR); /* Local translation functions */ ! 127: static CHAR (*rxo)(CHAR); /* for output (sending) terminal chars */ ! 128: static CHAR (*sxi)(CHAR); /* and for input (receiving) terminal chars. */ ! 129: static CHAR (*rxi)(CHAR); ! 130: #else /* Not ANSI C... */ ! 131: extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])(); /* Character set */ ! 132: extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(); /* translation functions. */ ! 133: static CHAR (*sxo)(); /* Local translation functions */ ! 134: static CHAR (*rxo)(); /* for output (sending) terminal chars */ ! 135: static CHAR (*sxi)(); /* and for input (receiving) terminal chars. */ ! 136: static CHAR (*rxi)(); ! 137: #endif /* CK_ANSIC */ ! 138: extern int language; /* Current language. */ ! 139: static int langsv; /* For remembering language setting. */ ! 140: extern struct csinfo fcsinfo[]; /* File character set info. */ ! 141: extern int tcsr, tcsl; /* Terminal character sets, remote & local. */ ! 142: static int tcs; /* Intermediate ("transfer") character set. */ ! 143: ! 144: #ifndef NOESCSEQ ! 145: /* ! 146: As of edit 178, the CONNECT command will skip past ANSI escape sequences ! 147: to avoid translating the characters within them. This allows the CONNECT ! 148: command to work correctly when connected to a remote host that uses a ! 149: 7-bit ISO 646 national character set, in which characters like '[' would ! 150: normally be translated into accented characters, ruining the terminal's ! 151: interpretation (and generation) of escape sequences. ! 152: ! 153: Escape sequences of non-ANSI/ISO-compliant terminals are not handled. ! 154: */ ! 155: #ifndef SKIPESC ! 156: #define SKIPESC ! 157: #endif /* SKIPESC */ ! 158: /* ! 159: States for the escape-sequence recognizer. ! 160: */ ! 161: #define ES_NORMAL 0 /* Normal, not in escape sequence */ ! 162: #define ES_GOTESC 1 /* Current character is ESC */ ! 163: #define ES_ESCSEQ 2 /* Inside an escape sequence */ ! 164: #define ES_GOTCSI 3 /* Inside a control sequence */ ! 165: #define ES_STRING 4 /* Inside DCS,OSC,PM, or APC string */ ! 166: #define ES_TERMIN 5 /* 1st char of string terminator */ ! 167: ! 168: static int ! 169: skipesc = 0, /* Skip over ANSI escape sequences */ ! 170: inesc = ES_NORMAL; /* State of sequence recognizer */ ! 171: /* ! 172: ANSI escape sequence handling. Only the 7-bit form is treated, because ! 173: translation is not a problem in the 8-bit environment, in which all GL ! 174: characters are ASCII and no translation takes place. So we don't check ! 175: for the 8-bit single-character versions of CSI, DCS, OSC, APC, or ST. ! 176: Here is the ANSI sequence recognizer state table, followed by the code ! 177: that implements it. ! 178: ! 179: Definitions: ! 180: CAN = Cancel 01/08 Ctrl-X ! 181: SUB = Substitute 01/10 Ctrl-Z ! 182: DCS = Device Control Sequence 01/11 05/00 ESC P ! 183: CSI = Control Sequence Introducer 01/11 05/11 ESC [ ! 184: ST = String Terminator 01/11 05/12 ESC \ ! 185: OSC = Operating System Command 01/11 05/13 ESC ] ! 186: PM = Privacy Message 01/11 05/14 ESC ^ ! 187: APC = Application Program Command 01/11 05/15 ESC _ ! 188: ! 189: ANSI escape sequence recognizer: ! 190: ! 191: State Input New State ; Commentary ! 192: ! 193: NORMAL (start) ; Start in NORMAL state ! 194: ! 195: (any) CAN NORMAL ; ^X cancels ! 196: (any) SUB NORMAL ; ^Z cancels ! 197: ! 198: NORMAL ESC GOTESC ; Begin escape sequence ! 199: NORMAL other ; NORMAL control or graphic character ! 200: ! 201: GOTESC ESC ; Start again ! 202: GOTESC [ GOTCSI ; CSI ! 203: GOTESC P STRING ; DCS introducer, consume through ST ! 204: GOTESC ] STRING ; OSC introducer, consume through ST ! 205: GOTESC ^ STRING ; PM introducer, consume through ST ! 206: GOTESC _ STRING ; APC introducer, consume through ST ! 207: GOTESC 0..~ NORMAL ; 03/00 through 17/14 = Final character ! 208: GOTESC other ESCSEQ ; Intermediate or ignored control character ! 209: ! 210: ESCSEQ ESC GOTESC ; Start again ! 211: ESCSEQ 0..~ NORMAL ; 03/00 through 17/14 = Final character ! 212: ESCSEQ other ; Intermediate or ignored control character ! 213: ! 214: GOTCSI ESC GOTESC ; Start again ! 215: GOTCSI @..~ NORMAL ; 04/00 through 17/14 = Final character ! 216: GOTCSI other ; Intermediate char or ignored control char ! 217: ! 218: STRING ESC TERMIN ; Maybe have ST ! 219: STRING other ; Consume all else ! 220: ! 221: TERMIN \ NORMAL ; End of string ! 222: TERMIN other STRING ; Still in string ! 223: */ ! 224: /* ! 225: chkaes() -- Check ANSI Escape Sequence. ! 226: Call with EACH character in input stream. ! 227: Sets global inesc variable according to escape sequence state. ! 228: */ ! 229: VOID ! 230: #ifdef CK_ANSIC ! 231: chkaes(char c) ! 232: #else ! 233: chkaes(c) char c; ! 234: #endif /* CK_ANSIC */ ! 235: /* chkaes */ { ! 236: ! 237: if (c == CAN || c == SUB) /* CAN and SUB cancel any sequence */ ! 238: inesc = ES_NORMAL; ! 239: else /* Otherwise */ ! 240: switch (inesc) { /* enter state switcher */ ! 241: ! 242: case ES_NORMAL: /* NORMAL state */ ! 243: if (c == ESC) /* Got an ESC */ ! 244: inesc = ES_GOTESC; /* Change state to GOTESC */ ! 245: break; /* Otherwise stay in NORMAL state */ ! 246: ! 247: case ES_GOTESC: /* GOTESC state */ ! 248: if (c == '[') /* Left bracket after ESC is CSI */ ! 249: inesc = ES_GOTCSI; /* Change to GOTCSI state */ ! 250: else if (c > 057 && c < 0177) /* Final character '0' thru '~' */ ! 251: inesc = ES_NORMAL; /* Back to normal */ ! 252: else if (c == 'P' || (c > 0134 && c < 0140)) /* P, [, ^, or _ */ ! 253: inesc = ES_STRING; /* Switch to STRING-absorption state */ ! 254: else if (c != ESC) /* ESC in an escape sequence... */ ! 255: inesc = ES_ESCSEQ; /* starts a new escape sequence */ ! 256: break; /* Intermediate or ignored ctrl char */ ! 257: ! 258: case ES_ESCSEQ: /* ESCSEQ -- in an escape sequence */ ! 259: if (c > 057 && c < 0177) /* Final character '0' thru '~' */ ! 260: inesc = ES_NORMAL; /* Return to NORMAL state. */ ! 261: else if (c == ESC) /* ESC ... */ ! 262: inesc = ES_GOTESC; /* starts a new escape sequence */ ! 263: break; /* Intermediate or ignored ctrl char */ ! 264: ! 265: case ES_GOTCSI: /* GOTCSI -- In a control sequence */ ! 266: if (c > 077 && c < 0177) /* Final character '@' thru '~' */ ! 267: inesc = ES_NORMAL; /* Return to NORMAL. */ ! 268: else if (c == ESC) /* ESC ... */ ! 269: inesc = ES_GOTESC; /* starts over. */ ! 270: break; /* Intermediate or ignored ctrl char */ ! 271: ! 272: case ES_STRING: /* Inside a string */ ! 273: if (c == ESC) /* ESC may be 1st char of terminator */ ! 274: inesc = ES_TERMIN; /* Go see. */ ! 275: break; /* Absorb all other characters. */ ! 276: ! 277: case ES_TERMIN: /* May have a string terminator */ ! 278: if (c == '\\') /* which must be backslash */ ! 279: inesc = ES_NORMAL; /* If so, back to NORMAL */ ! 280: else /* Otherwise */ ! 281: inesc = ES_STRING; /* Back to string absorption. */ ! 282: } ! 283: } ! 284: #endif /* NOESCSEQ */ ! 285: #endif /* NOCSETS */ ! 286: ! 287: /* Connect state parent/child communication signal handlers */ ! 288: ! 289: static jmp_buf con_env; /* Environment pointer for connect errors */ ! 290: /* ! 291: Note: Some C compilers (e.g. Cray UNICOS) interpret the ANSI C standard ! 292: about setjmp() in a way that disallows constructions like: ! 293: ! 294: if ((var = setjmp(env)) == 0) ... ! 295: ! 296: which prevents the value returned by longjmp() from being used at all. ! 297: So the following handlers set a global variable instead. ! 298: */ ! 299: static ! 300: SIGTYP ! 301: conn_int(foo) int foo; { /* Modem read failure handler, */ ! 302: signal(SIGUSR1,SIG_IGN); /* Disarm the interrupt */ ! 303: sjval = 1; /* Set global variable */ ! 304: longjmp(con_env,sjval); /* Notifies parent process to stop */ ! 305: } ! 306: ! 307: static ! 308: SIGTYP ! 309: mode_chg(foo) int foo; { ! 310: signal(SIGUSR2,mode_chg); /* Re-arm the signal immediately. */ ! 311: ! 312: #ifdef SUNX25 /* X.25 read new params from pipe */ ! 313: if (nettype == NET_SX25) { ! 314: read(padpipe[0],padparms,MAXPADPARMS); ! 315: debug(F100,"pad_chg","",0); ! 316: /* ! 317: NOTE: we can probably skip this longjmp, just as we do in the "else" case. ! 318: But I don't (yet) have any way to test this. ! 319: */ ! 320: sjval = 2; /* Set global variable. */ ! 321: longjmp(con_env,sjval); ! 322: debug(F100,"mode_chg X.25","",0); ! 323: } else { ! 324: #endif /* SUNX25 */ ! 325: duplex = 1 - duplex; /* Toggle duplex mode. */ ! 326: debug(F101,"mode_chg duplex","",duplex); ! 327: #ifdef SUNX25 ! 328: } ! 329: #endif /* SUNX25 */ ! 330: } ! 331: ! 332: /* C K C P U T C -- C-Kermit CONNECT Put Character to Screen */ ! 333: /* ! 334: Output is buffered to avoid slow screen writes on fast connections. ! 335: */ ! 336: int ! 337: ckcputf() { /* Dump the output buffer */ ! 338: int x = 0; ! 339: if (obc > 0) /* If we have any characters, */ ! 340: x = conxo(obc,obuf); /* dump them, */ ! 341: obp = obuf; /* reset the pointer */ ! 342: obc = 0; /* and the counter. */ ! 343: return(x); /* Return conxo's return code */ ! 344: } ! 345: ! 346: int ! 347: ckcputc(c) int c; { ! 348: int x; ! 349: ! 350: *obp++ = c & 0xff; /* Deposit the character */ ! 351: obc++; /* Count it */ ! 352: if (ibc == 0 || /* If input buffer about empty */ ! 353: obc == OBUFL) { /* or output buffer full */ ! 354: debug(F101,"CKCPUTC obc","",obc); ! 355: x = conxo(obc,obuf); /* dump the buffer, */ ! 356: obp = obuf; /* reset the pointer */ ! 357: obc = 0; /* and the counter. */ ! 358: return(x); /* Return conxo's return code */ ! 359: } else return(0); ! 360: } ! 361: ! 362: /* C K C G E T C -- C-Kermit CONNECT Get Character */ ! 363: /* ! 364: Buffered read from communication device. ! 365: Returns the next character, refilling the buffer if necessary. ! 366: On error, returns ttinc's return code (see ttinc() description). ! 367: Dummy argument for compatible calling conventions with ttinc(). ! 368: */ ! 369: int ! 370: ckcgetc(dummy) int dummy; { ! 371: int c, n; ! 372: ! 373: debug(F101,"CKCGETC 1 ibc","",ibc); /* Log */ ! 374: if (ibc < 1) { /* Need to refill buffer? */ ! 375: ibc = 0; /* Yes, reset count */ ! 376: ibp = ibuf; /* and buffer pointer */ ! 377: debug(F100,"CKCGETC 1 calling ttinc(0)","",0); /* Log */ ! 378: c = ttinc(0); /* Read one character, blocking */ ! 379: debug(F101,"CKCGETC 1 ttinc(0)","",c); /* Log */ ! 380: if (c < 0) { /* If error, return error code */ ! 381: return(c); ! 382: } else { /* Otherwise, got one character */ ! 383: *ibp++ = c; /* Advance buffer pointer */ ! 384: ibc++; /* and count. */ ! 385: } ! 386: ! 387: /* Now quickly read any more that might have arrived */ ! 388: ! 389: if ((n = ttchk()) > 0) { /* Any more waiting? */ ! 390: if (n > (IBUFL - ibc)) /* Get them all at once. */ ! 391: n = IBUFL - ibc; /* Don't overflow buffer */ ! 392: if ((n = ttxin(n,(CHAR *)ibp)) > 0) { ! 393: ibp += n; /* Advance pointer */ ! 394: ibc += n; /* and counter */ ! 395: } else return(-1); ! 396: } ! 397: debug(F101,"CKCGETC 2 ibc","",ibc); /* Log how many */ ! 398: ibp = ibuf; ! 399: } ! 400: c = *ibp++ & 0xff; /* Get next character from buffer */ ! 401: ibc--; /* Reduce buffer count */ ! 402: return(c); /* Return the character */ ! 403: } ! 404: ! 405: /* C O N E C T -- Perform terminal connection */ ! 406: ! 407: int ! 408: conect() { ! 409: PID_T pid; /* Process id of child (modem reader) */ ! 410: int n; /* General purpose counter */ ! 411: ! 412: int c; /* c is a character, but must be signed ! 413: integer to pass thru -1, which is the ! 414: modem disconnection signal, and is ! 415: different from the character 0377 */ ! 416: int c2; /* A copy of c */ ! 417: int csave; /* Another copy of c */ ! 418: int tx; /* tn_doop() return code */ ! 419: #ifdef SUNX25 ! 420: int i; /* Worker for X.25 code*/ ! 421: #endif /* SUNX25 */ ! 422: ! 423: #ifdef DYNAMIC ! 424: if (!(ibuf = malloc(IBUFL+1))) { /* Allocate input line buffer */ ! 425: printf("Sorry, CONNECT input buffer can't be allocated\n"); ! 426: return(0); ! 427: } ! 428: if (!(obuf = malloc(OBUFL+1))) { /* Allocate input line buffer */ ! 429: printf("Sorry, CONNECT output buffer can't be allocated\n"); ! 430: free(ibuf); ! 431: return(0); ! 432: } ! 433: if (!(temp = malloc(TMPLEN+1))) { /* Allocate temporary buffer */ ! 434: printf("Sorry, CONNECT temporary buffer can't be allocated\n"); ! 435: free(obuf); ! 436: return(0); ! 437: } ! 438: #endif /* DYNAMIC */ ! 439: ! 440: if (!local) { ! 441: #ifdef NETCONN ! 442: printf("Sorry, you must SET LINE or SET HOST first\n"); ! 443: #else ! 444: printf("Sorry, you must SET LINE first\n"); ! 445: #endif /* NETCONN */ ! 446: return(0); ! 447: } ! 448: if (speed < 0L && network == 0) { ! 449: printf("Sorry, you must SET SPEED first\n"); ! 450: return(0); ! 451: } ! 452: #ifdef TCPSOCKET ! 453: if (network && (nettype != NET_TCPB) ! 454: #ifdef SUNX25 ! 455: && (nettype != NET_SX25) ! 456: #endif /* SUNX25 */ ! 457: ) { ! 458: printf("Sorry, network type not supported\n"); ! 459: return(0); ! 460: } ! 461: #endif /* TCPSOCKET */ ! 462: ! 463: if (ttyfd < 0) { /* If communication device not open */ ! 464: debug(F111,"ckucon opening",ttname,0); /* Open it now */ ! 465: if (ttopen(ttname, ! 466: &local, ! 467: network ? -nettype : mdmtyp, ! 468: 0 ! 469: ) < 0) { ! 470: sprintf(temp,"Sorry, can't open %s",ttname); ! 471: perror(temp); ! 472: debug(F110,"ckucon open failure",temp,0); ! 473: return(0); ! 474: } ! 475: } ! 476: dohangup = 0; /* Hangup not requested yet */ ! 477: #ifdef SUNX25 ! 478: dox25clr = 0; /* X.25 clear not requested yet */ ! 479: #endif /* SUNX25 */ ! 480: ! 481: if (!quiet) { ! 482: #ifdef NETCONN ! 483: if (network) { ! 484: printf("Connecting to host %s",ttname); ! 485: #ifdef SUNX25 ! 486: if (nettype == NET_SX25) ! 487: printf(", Link ID %d, LCN %d",linkid,lcn); ! 488: #endif /* SUNX25 */ ! 489: } else { ! 490: #endif /* NETCONN */ ! 491: printf("Connecting to %s",ttname); ! 492: if (speed > -1L) printf(", speed %ld",speed); ! 493: #ifdef NETCONN ! 494: } ! 495: #endif /* NETCONN */ ! 496: printf(".\r\nThe escape character is Ctrl-%c (ASCII %d, %s)\r\n", ! 497: ctl(escape), escape, (escape == 127 ? "DEL" : ccntab[escape])); ! 498: printf("Type the escape character followed by C to get back,\r\n"); ! 499: printf("or followed by ? to see other options.\r\n"); ! 500: if (seslog) { ! 501: printf("(Session logged to %s, ",sesfil); ! 502: printf("%s)\r\n", sessft ? "binary" : "text"); ! 503: } ! 504: if (debses) printf("Debugging Display...)\r\n"); ! 505: fflush(stdout); ! 506: } ! 507: ! 508: /* Condition console terminal and communication line */ ! 509: ! 510: if (conbin((char)escape) < 0) { ! 511: printf("Sorry, can't condition console terminal\n"); ! 512: return(0); ! 513: } ! 514: debug(F101,"connect cmask","",cmask); ! 515: debug(F101,"connect cmdmsk","",cmdmsk); ! 516: goterr = 0; ! 517: if ((n = ttvt(speed,flow)) < 0) { /* Enter "virtual terminal" mode */ ! 518: debug(F101,"CONNECT ttvt","",n); ! 519: goterr = 1; /* Error recovery... */ ! 520: tthang(); /* Hang up and close the device. */ ! 521: ttclos(0); ! 522: if (ttopen(ttname, /* Open it again... */ ! 523: &local, ! 524: network ? -nettype : mdmtyp, ! 525: 0 ! 526: ) < 0) { ! 527: sprintf(temp,"Sorry, can't reopen %s",ttname); ! 528: perror(temp); ! 529: return(0); ! 530: } ! 531: if (ttvt(speed,flow) < 0) { /* Try virtual terminal mode again. */ ! 532: conres(); /* Failure this time is fatal. */ ! 533: printf("Sorry, Can't condition communication line\n"); ! 534: return(0); ! 535: } ! 536: #ifdef NETCONN ! 537: if (network && ttnproto == NP_TELNET) ! 538: tn_ini(); /* Just in case ttopen didn't... */ ! 539: #endif /* NETCONN */ ! 540: } ! 541: debug(F101,"connect ttvt ok, escape","",escape); ! 542: ! 543: #ifndef NOCSETS ! 544: /* Set up character set translations */ ! 545: ! 546: tcs = gettcs(tcsr,tcsl); /* Get intermediate set. */ ! 547: ! 548: if (tcsr == tcsl) { /* Remote and local sets the same? */ ! 549: sxo = rxo = NULL; /* If so, no translation. */ ! 550: sxi = rxi = NULL; ! 551: } else { /* Otherwise, set up */ ! 552: sxo = xls[tcs][tcsl]; /* translation function */ ! 553: rxo = xlr[tcs][tcsr]; /* pointers for output functions */ ! 554: sxi = xls[tcs][tcsr]; /* and for input functions. */ ! 555: rxi = xlr[tcs][tcsl]; ! 556: } ! 557: /* ! 558: This is to prevent use of zmstuff() and zdstuff() by translation functions. ! 559: They only work with disk i/o, not with communication i/o. Luckily Russian ! 560: translation functions don't do any stuffing... ! 561: */ ! 562: langsv = language; ! 563: #ifndef NOCYRIL ! 564: if (language != L_RUSSIAN) ! 565: #endif /* NOCYRIL */ ! 566: language = L_USASCII; ! 567: ! 568: #ifdef SKIPESC ! 569: /* ! 570: We need to activate the "skip escape sequence" feature when: ! 571: (a) translation is elected, and ! 572: (b) the local and/or remote set is a 7-bit set other than US ASCII. ! 573: */ ! 574: skipesc = (tcs != TC_TRANSP) && /* Not transparent */ ! 575: (fcsinfo[tcsl].size == 128 || fcsinfo[tcsr].size == 128) && /* 7 bits */ ! 576: (fcsinfo[tcsl].code != FC_USASCII); /* But not ASCII */ ! 577: inesc = ES_NORMAL; /* Initial state of recognizer */ ! 578: #ifdef COMMENT ! 579: debug(F101,"tcs","",tcs); ! 580: debug(F101,"tcsl","",tcsl); ! 581: debug(F101,"tcsr","",tcsr); ! 582: debug(F101,"fcsinfo[tcsl].size","",fcsinfo[tcsl].size); ! 583: debug(F101,"fcsinfo[tcsr].size","",fcsinfo[tcsr].size); ! 584: #endif /* COMMENT */ ! 585: debug(F101,"skipesc","",skipesc); ! 586: #endif /* SKIPESC */ ! 587: #endif /* NOCSETS */ ! 588: ! 589: /* ! 590: This is a label we jump back to when the lower fork sensed the need ! 591: to change modes. As of 5A(178), this is used only by X.25 code ! 592: (perhaps unnecessarily? -- The X.25 code needs a lot of testing and ! 593: cleaning up...) ! 594: */ ! 595: newfork: ! 596: debug(F100,"CONNECT newfork","",0); ! 597: parent_id = getpid(); /* Get parent id for signalling */ ! 598: signal(SIGUSR1,SIG_IGN); /* Don't kill myself */ ! 599: #ifdef SUNX25 ! 600: pipe(padpipe); /* Create pipe to pass PAD parms */ ! 601: #endif /* SUNX25 */ ! 602: pid = fork(); /* All ok, make a fork */ ! 603: if (pid == (PID_T) -1) { /* Can't create it. */ ! 604: conres(); /* Reset the console. */ ! 605: perror("Can't create keyboard fork"); ! 606: if (!quiet) { ! 607: printf("\r\nCommunications disconnect (Back at %s)\r\n", ! 608: *myhost ? ! 609: myhost : ! 610: #ifdef COHERENT ! 611: "Local COHERENT system" ! 612: #else ! 613: #endif /* COHERENT */ ! 614: ! 615: #ifdef UNIX ! 616: "local UNIX system" ! 617: #else ! 618: "local system" ! 619: #endif /* UNIX */ ! 620: ); ! 621: } ! 622: printf("\n"); ! 623: what = W_NOTHING; /* So console modes are set right. */ ! 624: #ifndef NOCSETS ! 625: language = langsv; /* Restore language */ ! 626: #endif /* NOCSETS */ ! 627: parent_id = (PID_T) 0; /* Clean up */ ! 628: #ifdef DYNAMIC ! 629: if (temp) free(temp); /* Free allocated memory */ ! 630: if (ibuf) free(ibuf); ! 631: if (obuf) free(obuf); ! 632: #endif /* DYNAMIC */ ! 633: return(1); ! 634: } ! 635: if (pid) { /* Top fork reads, sends keystrokes */ ! 636: what = W_CONNECT; /* Keep track of what we're doing */ ! 637: active = 1; ! 638: debug(F101,"CONNECT keyboard fork duplex","",duplex); ! 639: ! 640: /* Catch communication errors or mode changes in lower fork */ ! 641: ! 642: if (setjmp(con_env) == 0) { /* Normal entry... */ ! 643: sjval = 0; /* Initialize setjmp return code. */ ! 644: signal(SIGUSR1,conn_int); /* Routine for child process exit. */ ! 645: signal(SIGUSR2,mode_chg); /* Routine for mode change. */ ! 646: #ifdef SUNX25 ! 647: if (network && nettype == NET_SX25) { ! 648: obufl = 0; ! 649: bzero (x25obuf,sizeof(x25obuf)) ; ! 650: } ! 651: #endif /* SUNX25 */ ! 652: ! 653: /* ! 654: Here is the big loop that gets characters from the keyboard and sends them ! 655: out the communication device. There are two components to the communication ! 656: path: the connection from the keyboard to C-Kermit, and from C-Kermit to ! 657: the remote computer. The treatment of the 8th bit of keyboard characters ! 658: is governed by SET COMMAND BYTESIZE (cmdmsk). The treatment of the 8th bit ! 659: of characters sent to the remote is governed by SET TERMINAL BYTESIZE ! 660: (cmask). This distinction was introduced in edit 5A(164). ! 661: */ ! 662: while (active) { ! 663: #ifndef NOSETKEY ! 664: if (kmptr) { /* Have current macro? */ ! 665: debug(F100,"kmptr non NULL","",0); ! 666: if ((c = (CHAR) *kmptr++) == NUL) { /* Get char from it */ ! 667: kmptr = NULL; /* If no more chars, */ ! 668: debug(F100,"macro empty, continuing","",0); ! 669: continue; /* reset pointer and continue */ ! 670: } ! 671: debug(F000,"char from macro","",c); ! 672: } else /* No macro... */ ! 673: #endif /* NOSETKEY */ ! 674: c = congks(0); /* Read from keyboard */ ! 675: ! 676: debug(F111,"** KEYB",dbchr(c),c); ! 677: ! 678: if (c == -1) { /* If read() got an error... */ ! 679: #ifdef COMMENT ! 680: /* ! 681: This seems to cause problems. If read() returns -1, the signal has already ! 682: been delivered, and nothing will wake up the pause(). ! 683: */ ! 684: pause(); /* Wait for transmitter to finish. */ ! 685: #else ! 686: #ifdef A986 ! 687: /* ! 688: On Altos machines with Xenix 3.0, pressing DEL in connect mode brings us ! 689: here (reason unknown). The console line discipline at this point has ! 690: intr = ^C. The communications tty has intr = DEL but we get here after ! 691: pressing DEL on the keyboard, even when the remote system has been set not ! 692: to echo. With A986 defined, we stay in the read loop and beep only if the ! 693: offending character is not DEL. ! 694: */ ! 695: if ((c & 127) != 127) conoc(BEL); ! 696: #else ! 697: conoc(BEL); /* Beep */ ! 698: active = 0; /* and terminate the read loop */ ! 699: continue; ! 700: #endif /* A986 */ ! 701: #endif /* COMMENT */ ! 702: } ! 703: c &= cmdmsk; /* Do any requested masking */ ! 704: #ifndef NOSETKEY ! 705: /* ! 706: Note: kmptr is NULL if we got character c from the keyboard, and it is ! 707: not NULL if it came from a macro. In the latter case, we must avoid ! 708: expanding it again. ! 709: */ ! 710: if (!kmptr && macrotab[c]) { /* Macro definition for c? */ ! 711: kmptr = macrotab[c]; /* Yes, set up macro pointer */ ! 712: continue; /* and restart the loop, */ ! 713: } else c = keymap[c]; /* else use single-char keymap */ ! 714: #endif /* NOSETKEY */ ! 715: if ( ! 716: #ifndef NOSETKEY ! 717: !kmptr && ! 718: #endif /* NOSETKEY */ ! 719: ((c & 0x7f) == escape)) { /* Escape character? */ ! 720: debug(F000,"connect got escape","",c); ! 721: c = congks(0) & 0177; /* Got esc, get its arg */ ! 722: /* No key mapping here */ ! 723: doesc((char) c); /* Now process it */ ! 724: ! 725: } else { /* It's not the escape character */ ! 726: csave = c; /* Save it before translation */ ! 727: /* for local echoing. */ ! 728: #ifndef NOCSETS ! 729: #ifndef SKIPESC ! 730: /* Translate character sets */ ! 731: if (sxo) c = (*sxo)(c); /* From local to intermediate. */ ! 732: if (rxo) c = (*rxo)(c); /* From intermediate to remote. */ ! 733: #else ! 734: if (inesc == ES_NORMAL) { /* If not inside escape seq.. */ ! 735: /* Translate character sets */ ! 736: if (sxo) c = (*sxo)((char)c); /* Local-intermediate */ ! 737: if (rxo) c = (*rxo)((char)c); /* Intermediate-remote */ ! 738: } ! 739: if (skipesc) chkaes((char)c); /* Check escape seq status */ ! 740: #endif /* SKIPESC */ ! 741: #endif /* NOCSETS */ ! 742: /* ! 743: If Shift-In/Shift-Out is selected and we have a 7-bit connection, ! 744: handle shifting here. ! 745: */ ! 746: if (sosi) { /* Shift-In/Out selected? */ ! 747: if (cmask == 0177) { /* In 7-bit environment? */ ! 748: if (c & 0200) { /* 8-bit character? */ ! 749: if (outshift == 0) { /* If not shifted, */ ! 750: ttoc(dopar(SO)); /* shift. */ ! 751: outshift = 1; ! 752: } ! 753: } else { ! 754: if (outshift == 1) { /* 7-bit character */ ! 755: ttoc(dopar(SI)); /* If shifted, */ ! 756: outshift = 0; /* unshift. */ ! 757: } ! 758: } ! 759: } ! 760: if (c == SO) outshift = 1; /* User typed SO */ ! 761: if (c == SI) outshift = 0; /* User typed SI */ ! 762: } ! 763: c &= cmask; /* Apply Kermit-to-host mask now. */ ! 764: #ifdef SUNX25 ! 765: if (network && nettype == NET_SX25) { ! 766: if (padparms[PAD_ECHO]) { ! 767: if (debses) ! 768: conol(dbchr(c)) ; ! 769: else ! 770: if ((c != padparms[PAD_CHAR_DELETE_CHAR]) && ! 771: (c != padparms[PAD_BUFFER_DELETE_CHAR]) && ! 772: (c != padparms[PAD_BUFFER_DISPLAY_CHAR])) ! 773: conoc(c) ; ! 774: if (seslog) logchar(c); ! 775: } ! 776: if (c == CR && (padparms[PAD_LF_AFTER_CR] == 4 || ! 777: padparms[PAD_LF_AFTER_CR] == 5)) { ! 778: if (debses) ! 779: conol(dbchr(LF)) ; ! 780: else ! 781: conoc(LF) ; ! 782: if (seslog) logchar(LF); ! 783: } ! 784: if (c == padparms[PAD_BREAK_CHARACTER]) ! 785: breakact(); ! 786: else if (padparms[PAD_DATA_FORWARD_TIMEOUT]) { ! 787: tosend = 1; ! 788: x25obuf [obufl++] = c; ! 789: } else if (((c == padparms[PAD_CHAR_DELETE_CHAR]) || ! 790: (c == padparms[PAD_BUFFER_DELETE_CHAR]) || ! 791: (c == padparms[PAD_BUFFER_DISPLAY_CHAR])) ! 792: && (padparms[PAD_EDITING])) ! 793: if (c == padparms[PAD_CHAR_DELETE_CHAR]) ! 794: if (obufl > 0) { ! 795: conol("\b \b"); obufl--; ! 796: } else {} ! 797: else if (c == padparms[PAD_BUFFER_DELETE_CHAR]) { ! 798: conol ("\r\nPAD Buffer Deleted\r\n"); ! 799: obufl = 0; ! 800: } ! 801: else if (c == padparms[PAD_BUFFER_DISPLAY_CHAR]) { ! 802: conol("\r\n"); ! 803: conol(x25obuf); ! 804: conol("\r\n"); ! 805: } else {} ! 806: else { ! 807: x25obuf [obufl++] = c; ! 808: if (obufl == MAXOX25) tosend = 1; ! 809: else if (c == CR) tosend = 1; ! 810: } ! 811: if (tosend) ! 812: if (ttol(x25obuf,obufl) < 0) { ! 813: perror ("\r\nCan't send characters"); ! 814: active = 0; ! 815: } else { ! 816: bzero (x25obuf,sizeof(x25obuf)); ! 817: obufl = 0; ! 818: tosend = 0; ! 819: } else {}; ! 820: } else { ! 821: #endif /* SUNX25 */ ! 822: ! 823: /* If we have a CR, handle CR/CRLF mapping... */ ! 824: ! 825: if (c == '\015') { ! 826: if (tnlm /* TERMINAL NEWLINE ON */ ! 827: #ifdef TNCODE /* And for TELNET... */ ! 828: || (network && ttnproto == NP_TELNET) ! 829: #endif /* TNCODE */ ! 830: ) { ! 831: ttoc(dopar('\015')); /* Send CR */ ! 832: if (duplex) conoc('\015'); /* Maybe echo CR */ ! 833: #ifdef TNCODE ! 834: if (network && !tn_nlm && ttnproto == NP_TELNET) ! 835: c = '\0'; /* Stuff NUL */ ! 836: else ! 837: #endif /* TNCODE */ ! 838: c = '\012'; /* Stuff LF */ ! 839: csave = c; ! 840: } ! 841: } /* Now process the LF or NUL... */ ! 842: #ifdef TNCODE ! 843: /* If user types the 0xff character (TELNET IAC), it must be doubled. */ ! 844: else ! 845: if (c == IAC && network && ttnproto == NP_TELNET) { ! 846: /* Send one copy now */ ! 847: ttoc((char)IAC); /* and the other one just below. */ ! 848: } ! 849: #endif /* TNCODE */ ! 850: ! 851: /* Send the character */ ! 852: ! 853: if (ttoc((char)dopar((CHAR) c)) > -1) { ! 854: if (duplex) { /* If half duplex, must echo */ ! 855: if (debses) ! 856: conol(dbchr(csave)); /* the original char */ ! 857: else /* not the translated one */ ! 858: conoc((char)csave); ! 859: if (seslog) { /* And maybe log it too */ ! 860: c2 = csave; ! 861: if (sessft == 0 && csave == '\r') ! 862: c2 = '\n'; ! 863: logchar((char)c2); ! 864: } ! 865: } ! 866: } else { ! 867: perror("\r\nCan't send character"); ! 868: active = 0; ! 869: } ! 870: #ifdef SUNX25 ! 871: } ! 872: #endif /* SUNX25 */ ! 873: } ! 874: } ! 875: } /* Come here on death of child */ ! 876: debug(F100,"CONNECT killing port fork","",0); ! 877: kill(pid,9); /* Done, kill inferior fork. */ ! 878: wait((WAIT_T *)0); /* Wait till gone. */ ! 879: if (sjval == 1) { /* Read error on comm device */ ! 880: dohangup = 1; ! 881: #ifdef NETCONN ! 882: if (network) { ! 883: ttclos(0); ! 884: #ifdef SUNX25 ! 885: if (nettype == NET_SX25) initpad(); ! 886: #endif /* SUNX25 */ ! 887: } ! 888: #endif /* NETCONN */ ! 889: } ! 890: if (sjval == 2) /* If it was a mode change, go back */ ! 891: goto newfork; /* and coordinate with other fork. */ ! 892: conres(); /* Reset the console. */ ! 893: if (quitnow) doexit(GOOD_EXIT,xitsta); /* Exit now if requested. */ ! 894: if (dohangup > 0) { /* If hangup requested, do that. */ ! 895: #ifndef NODIAL ! 896: if (dohangup > 1) /* User asked for it */ ! 897: if (mdmhup() < 1) /* Maybe hang up via modem */ ! 898: #endif /* NODIAL */ ! 899: tthang(); /* And make sure we don't hang up */ ! 900: dohangup = 0; /* again unless requested again. */ ! 901: } ! 902: #ifdef SUNX25 ! 903: if (dox25clr) { /* If X.25 clear requested */ ! 904: x25clear(); /* do that. */ ! 905: initpad(); ! 906: dox25clr = 0; /* But only once. */ ! 907: } ! 908: #endif /* SUNX25 */ ! 909: if (!quiet) ! 910: #ifdef COHERENT ! 911: printf("(Back at %s)", *myhost ? myhost : "local COHERENT system"); ! 912: #else ! 913: printf("(Back at %s)", *myhost ? myhost : "local UNIX system"); ! 914: #endif /* COHERENT */ ! 915: printf("\n"); ! 916: what = W_NOTHING; /* So console modes set right. */ ! 917: #ifndef NOCSETS ! 918: language = langsv; /* Restore language */ ! 919: #endif /* NOCSETS */ ! 920: parent_id = (PID_T) 0; ! 921: #ifdef DYNAMIC ! 922: if (temp) free(temp); /* Free allocated memory */ ! 923: if (ibuf) free(ibuf); ! 924: if (obuf) free(obuf); ! 925: #endif /* DYNAMIC */ ! 926: return(1); ! 927: ! 928: } else { /* Inferior reads, prints port input */ ! 929: ! 930: #ifndef OXOS ! 931: if (priv_can()) { /* Cancel all privs */ ! 932: printf("?setuid error - fatal\n"); ! 933: doexit(BAD_EXIT,-1); ! 934: } ! 935: #endif /* OXOS */ ! 936: signal(SIGINT, SIG_IGN); /* In case these haven't been */ ! 937: signal(SIGQUIT, SIG_IGN); /* inherited from above... */ ! 938: ! 939: inshift = outshift = 0; /* Initial SO/SI shift state. */ ! 940: sleep(1); /* Wait for parent's handler setup. */ ! 941: ibp = ibuf; /* Initialize input buffering */ ! 942: ibc = 0; /* And output buffering. */ ! 943: obp = obuf; ! 944: obc = 0; ! 945: debug(F100,"CONNECT starting port fork","",0); ! 946: while (1) { /* Fresh read, wait for a character. */ ! 947: #ifdef SUNX25 ! 948: if (network && (nettype == NET_SX25)) { ! 949: bzero(x25ibuf,sizeof(x25ibuf)) ; ! 950: if ((ibufl = ttxin(MAXIX25,x25ibuf)) < 0) { ! 951: if (ibufl == -2) { /* PAD parms changes */ ! 952: write(padpipe[1],padparms,MAXPADPARMS); ! 953: kill(parent_id,SIGUSR2); ! 954: } else { ! 955: if (!quiet) ! 956: printf("\r\nCommunications disconnect "); ! 957: kill(parent_id,SIGUSR1); ! 958: } ! 959: pause(); ! 960: } ! 961: if (debses) { /* Debugging output */ ! 962: p = x25ibuf ; ! 963: while (ibufl--) { c = *p++; conol(dbchr(c)); } ! 964: } else { ! 965: if (sosi ! 966: #ifndef NOCSETS ! 967: || tcsl != tcsr ! 968: #endif /* NOCSETS */ ! 969: ) { /* Character at a time */ ! 970: for (i = 1; i < ibufl; i++) { ! 971: c = x25ibuf[i] & cmask; ! 972: if (sosi) { /* Handle SI/SO */ ! 973: if (c == SO) { ! 974: inshift = 1; ! 975: continue; ! 976: } else if (c == SI) { ! 977: inshift = 0; ! 978: continue; ! 979: } ! 980: if (inshift) ! 981: c |= 0200; ! 982: } ! 983: #ifndef NOCSETS ! 984: #ifndef SKIPESC ! 985: /* Translate character sets */ ! 986: if (sxo) c = (*sxo)(c); /* From local to intermediate. */ ! 987: if (rxo) c = (*rxo)(c); /* From intermediate to remote. */ ! 988: ! 989: #else /* Skipping escape sequences... */ ! 990: ! 991: if (inesc == ES_NORMAL) { /* If not inside escape seq.. */ ! 992: /* Translate character sets */ ! 993: if (sxo) c = (*sxo)(c); /* Local to intermediate. */ ! 994: if (rxo) c = (*rxo)(c); /* Intermediate to remote. */ ! 995: } ! 996: if (skipesc) chkaes(c); /* Check escape sequence status */ ! 997: #endif /* SKIPESC */ ! 998: #endif /* NOCSETS */ ! 999: c &= cmdmsk; /* Apply command mask. */ ! 1000: conoc(c); /* Output to screen */ ! 1001: logchar(c); /* and session log */ ! 1002: } ! 1003: } else { /* All at once */ ! 1004: for (i = 1; i < ibufl; i++) ! 1005: x25ibuf[i] &= (cmask & cmdmsk); ! 1006: conxo(ibufl,x25ibuf); ! 1007: if (seslog) zsoutx(ZSFILE,x25ibuf,ibufl); ! 1008: } ! 1009: } ! 1010: continue; ! 1011: ! 1012: } else { /* Not X.25... */ ! 1013: #endif /* SUNX25 */ ! 1014: /* ! 1015: Get the next communication line character from our internal buffer. ! 1016: If the buffer is empty, refill it. ! 1017: */ ! 1018: c = ckcgetc(0); /* Get next character */ ! 1019: /* debug(F101,"CONNECT c","",c); */ ! 1020: if (c < 0) { ! 1021: if (!quiet) { /* Failed... */ ! 1022: printf("\r\nCommunications disconnect "); ! 1023: if ( c == -3 ! 1024: #ifdef UTEK ! 1025: /* This happens on UTEK if there's no carrier */ ! 1026: && errno != EWOULDBLOCK ! 1027: #endif /* UTEK */ ! 1028: ) ! 1029: perror("\r\nCan't read character"); ! 1030: } ! 1031: tthang(); /* Hang up the connection */ ! 1032: kill(parent_id,SIGUSR1); /* Notify parent */ ! 1033: for (;;) pause(); /* and wait to be killed */ ! 1034: } ! 1035: debug(F111,"** PORT",dbchr(c),c); ! 1036: #ifdef TNCODE ! 1037: /* Handle TELNET negotiations here */ ! 1038: if (c == IAC && network && ttnproto == NP_TELNET) { ! 1039: ckcputf(); /* Dump output buffer */ ! 1040: if ((tx = tn_doop((CHAR)(c & 0xff),duplex,ckcgetc)) == 0) { ! 1041: continue; ! 1042: } else if (tx == -1) { /* I/O error */ ! 1043: if (!quiet) ! 1044: printf("\r\nCommunications disconnect "); ! 1045: kill(parent_id,SIGUSR1); /* Notify parent. */ ! 1046: for (;;) pause(); /* Wait to be killed. */ ! 1047: } else if ((tx == 1) && (!duplex)) { /* ECHO change */ ! 1048: kill(parent_id,SIGUSR2); /* Tell the parent fork */ ! 1049: duplex = 1; ! 1050: } else if ((tx == 2) && (duplex)) { /* ECHO change */ ! 1051: kill(parent_id,SIGUSR2); ! 1052: duplex = 0; ! 1053: } else if (tx == 3) { /* Quoted IAC */ ! 1054: c = 255; ! 1055: } else continue; /* Negotiation OK, get next char. */ ! 1056: } ! 1057: #endif /* TNCODE */ ! 1058: if (debses) { /* Output character to screen */ ! 1059: char *s; /* Debugging display... */ ! 1060: s = dbchr(c); ! 1061: while (*s) ! 1062: ckcputc(*s++); ! 1063: } else { /* Regular display ... */ ! 1064: c &= cmask; /* Apply Kermit-to-remote mask */ ! 1065: if (sosi) { /* Handle SI/SO */ ! 1066: if (c == SO) { /* Shift Out */ ! 1067: inshift = 1; ! 1068: continue; ! 1069: } else if (c == SI) { /* Shift In */ ! 1070: inshift = 0; ! 1071: continue; ! 1072: } ! 1073: if (inshift) c |= 0200; ! 1074: } ! 1075: #ifndef NOCSETS ! 1076: #ifndef SKIPESC ! 1077: /* Translate character sets */ ! 1078: if (sxi) c = (*sxi)((CHAR)c); ! 1079: if (rxi) c = (*rxi)((CHAR)c); ! 1080: #else ! 1081: if (inesc == ES_NORMAL) { ! 1082: /* Translate character sets */ ! 1083: if (sxi) c = (*sxi)((CHAR)c); ! 1084: if (rxi) c = (*rxi)((CHAR)c); ! 1085: } ! 1086: /* Adjust escape sequence status */ ! 1087: if (skipesc) chkaes((char)c); ! 1088: #endif /* SKIPESC */ ! 1089: #endif /* NOCSETS */ ! 1090: c &= cmdmsk; /* Apply command mask. */ ! 1091: if (c == CR && tt_crd) { /* SET TERM CR-DISPLAY CRLF ? */ ! 1092: ckcputc(c); /* Yes, output CR */ ! 1093: if (seslog) logchar((char)c); ! 1094: c = LF; /* and insert a linefeed */ ! 1095: } ! 1096: ckcputc(c); /* Output character to screen */ ! 1097: if (seslog) logchar((char)c); /* Do session log */ ! 1098: } ! 1099: #ifdef SUNX25 ! 1100: } ! 1101: #endif /* SUNX25 */ ! 1102: } ! 1103: } ! 1104: } ! 1105: ! 1106: ! 1107: /* H C O N N E -- Give help message for connect. */ ! 1108: ! 1109: int ! 1110: hconne() { ! 1111: int c; ! 1112: static char *hlpmsg[] = { ! 1113: "\r\n ? for this message", ! 1114: "\r\n 0 (zero) to send a null", ! 1115: "\r\n B to send a BREAK", ! 1116: #ifdef CK_LBRK ! 1117: "\r\n L to send a Long BREAK", ! 1118: #endif /* CK_LBRK */ ! 1119: #ifdef NETCONN ! 1120: "\r\n I to send a network interrupt packet", ! 1121: #ifdef TCPSOCKET ! 1122: "\r\n A to send Are You There?", ! 1123: #endif /* TCPSOCKET */ ! 1124: #ifdef SUNX25 ! 1125: "\r\n R to reset X.25 virtual circuit", ! 1126: #endif /* SUNX25 */ ! 1127: #endif /* NETCONN */ ! 1128: "\r\n H to hangup and close the connection", ! 1129: "\r\n Q to hangup and quit Kermit", ! 1130: "\r\n S for status", ! 1131: "\r\n ! to push to local shell", ! 1132: "\r\n Z to suspend", ! 1133: "\r\n \\ backslash code:", ! 1134: "\r\n \\nnn decimal character code", ! 1135: "\r\n \\Onnn octal character code", ! 1136: "\r\n \\Xhh hexadecimal character code", ! 1137: "\r\n terminate with carriage return.", ! 1138: "\r\n Type the escape character again to send the escape character, or", ! 1139: "\r\n press the space-bar to resume the CONNECT command.\r\n\r\n", ! 1140: "" }; ! 1141: conol("\r\nPress C to return to "); ! 1142: conol(*myhost ? myhost : "the C-Kermit prompt"); ! 1143: conol(", or:"); ! 1144: conola(hlpmsg); /* Print the help message. */ ! 1145: conol("Command>"); /* Prompt for command. */ ! 1146: c = congks(0) & 0177; /* Get character, strip any parity. */ ! 1147: /* No key mapping or translation here */ ! 1148: if (c != CMDQ) ! 1149: conoll(""); ! 1150: return(c); /* Return it. */ ! 1151: } ! 1152: ! 1153: ! 1154: /* D O E S C -- Process an escape character argument */ ! 1155: ! 1156: VOID ! 1157: #ifdef CK_ANSIC ! 1158: doesc(char c) ! 1159: #else ! 1160: doesc(c) char c; ! 1161: #endif /* CK_ANSIC */ ! 1162: /* doesc */ { ! 1163: CHAR d; ! 1164: ! 1165: while (1) { ! 1166: if (c == escape) { /* Send escape character */ ! 1167: d = dopar((CHAR) c); ttoc((char) d); return; ! 1168: } else /* Or else look it up below. */ ! 1169: if (isupper(c)) c = tolower(c); ! 1170: ! 1171: switch(c) { ! 1172: ! 1173: case 'c': /* Escape back to prompt */ ! 1174: case '\03': ! 1175: active = 0; conol("\r\n"); return; ! 1176: ! 1177: case 'b': /* Send a BREAK signal */ ! 1178: case '\02': ! 1179: ttsndb(); return; ! 1180: ! 1181: #ifdef NETCONN ! 1182: case 'i': /* Send Interrupt */ ! 1183: case '\011': ! 1184: #ifdef TCPSOCKET ! 1185: #ifndef IP ! 1186: #define IP 244 ! 1187: #endif /* IP */ ! 1188: if (network && ttnproto == NP_TELNET) { /* TELNET */ ! 1189: temp[0] = IAC; /* I Am a Command */ ! 1190: temp[1] = IP; /* Interrupt Process */ ! 1191: temp[2] = NUL; ! 1192: ttol((CHAR *)temp,2); ! 1193: } else ! 1194: #endif /* TCPSOCKET */ ! 1195: #ifdef SUNX25 ! 1196: if (network && (nettype == NET_SX25)) { /* X.25 */ ! 1197: (VOID) x25intr(0); /* X.25 interrupt packet */ ! 1198: conol("\r\n"); ! 1199: } else ! 1200: #endif /* SUNX25 */ ! 1201: conoc(BEL); ! 1202: return; ! 1203: ! 1204: #ifdef TCPSOCKET ! 1205: case 'a': /* "Are You There?" */ ! 1206: case '\01': ! 1207: #ifndef AYT ! 1208: #define AYT 246 ! 1209: #endif /* AYT */ ! 1210: if (network && ttnproto == NP_TELNET) { ! 1211: temp[0] = IAC; /* I Am a Command */ ! 1212: temp[1] = AYT; /* Are You There? */ ! 1213: temp[2] = NUL; ! 1214: ttol((CHAR *)temp,2); ! 1215: } else conoc(BEL); ! 1216: return; ! 1217: #endif /* TCPSOCKET */ ! 1218: #endif /* NETCONN */ ! 1219: ! 1220: #ifdef CK_LBRK ! 1221: case 'l': /* Send a Long BREAK signal */ ! 1222: ttsndlb(); return; ! 1223: #endif /* CK_LBRK */ ! 1224: ! 1225: case 'h': /* Hangup */ ! 1226: case '\010': ! 1227: #ifdef SUNX25 ! 1228: if (network && (nettype == NET_SX25)) dox25clr = 1; ! 1229: else ! 1230: #endif /* SUNX25 */ ! 1231: dohangup = 2; active = 0; conol("\r\nHanging up "); return; ! 1232: ! 1233: #ifdef SUNX25 ! 1234: case 'r': /* Reset the X.25 virtual circuit */ ! 1235: case '\022': ! 1236: if (network && (nettype == NET_SX25)) (VOID) x25reset(); ! 1237: conol("\r\n"); return; ! 1238: #endif /* SUNX25 */ ! 1239: ! 1240: case 'q': /* Quit */ ! 1241: quitnow = 1; active = 0; conol("\r\n"); return; ! 1242: ! 1243: case 's': /* Status */ ! 1244: sprintf(temp, ! 1245: "\r\nConnected %s %s", network ? "to" : "through", ttname); ! 1246: conol(temp); ! 1247: #ifdef SUNX25 ! 1248: if (network && (nettype == NET_SX25)) { ! 1249: sprintf(temp,", Link ID %d, LCN %d",linkid,lcn); conol(temp); ! 1250: } ! 1251: #endif /* SUNX25 */ ! 1252: if (speed >= 0L) { ! 1253: sprintf(temp,", speed %ld", speed); ! 1254: conoll(temp); ! 1255: } else conoll(""); ! 1256: sprintf(temp, ! 1257: "Terminal bytesize: %d, Command bytesize: %d, Parity: ", ! 1258: (cmask == 0177) ? 7 : 8, ! 1259: (cmdmsk == 0177) ? 7 : 8 ); ! 1260: conol(temp); ! 1261: ! 1262: switch (parity) { ! 1263: case 0: conoll("none"); break; ! 1264: case 'e': conoll("even"); break; ! 1265: case 'o': conoll("odd"); break; ! 1266: case 's': conoll("space"); break; ! 1267: case 'm': conoll("mark"); break; ! 1268: } ! 1269: sprintf(temp,"Terminal echo: %s", duplex ? "local" : "remote"); ! 1270: conoll(temp); ! 1271: if (seslog) { ! 1272: conol("Logging to: "); conoll(sesfil); ! 1273: } ! 1274: if (!network) shomdm(); ! 1275: return; ! 1276: ! 1277: case '?': /* Help */ ! 1278: c = hconne(); continue; ! 1279: ! 1280: case '0': /* Send a null */ ! 1281: c = '\0'; d = dopar((CHAR) c); ttoc((char) d); return; ! 1282: ! 1283: #ifndef NOPUSH ! 1284: case 'z': case '\032': /* Suspend */ ! 1285: stptrap(0); return; ! 1286: ! 1287: case '@': /* Start inferior command processor */ ! 1288: case '!': ! 1289: conres(); /* Put console back to normal */ ! 1290: zshcmd(""); /* Fork a shell. */ ! 1291: if (conbin((char)escape) < 0) { ! 1292: printf("Error resuming CONNECT session\n"); ! 1293: active = 0; ! 1294: } ! 1295: return; ! 1296: #endif /* NOPUSH */ ! 1297: ! 1298: case SP: /* Space, ignore */ ! 1299: return; ! 1300: ! 1301: default: /* Other */ ! 1302: if (c == CMDQ) { /* Backslash escape */ ! 1303: int x; ! 1304: kbp = kbuf; ! 1305: *kbp++ = c; ! 1306: while (((c = (congks(0) & cmdmsk)) != '\r') && (c != '\n')) ! 1307: *kbp++ = c; ! 1308: *kbp = NUL; kbp = kbuf; ! 1309: x = xxesc(&kbp); /* Interpret it */ ! 1310: if (x >= 0) { /* No key mapping here */ ! 1311: c = dopar((CHAR) x); ! 1312: ttoc((char) c); ! 1313: return; ! 1314: } else { /* Invalid backslash code. */ ! 1315: conoc(BEL); ! 1316: return; ! 1317: } ! 1318: } ! 1319: conoc(BEL); return; /* Invalid esc arg, beep */ ! 1320: } ! 1321: } ! 1322: } ! 1323: ! 1324: VOID ! 1325: #ifdef CK_ANSIC ! 1326: logchar(char c) ! 1327: #else ! 1328: logchar(c) char c; ! 1329: #endif /* CK_ANSIC */ ! 1330: /* logchar */ { /* Log character c to session log */ ! 1331: if (seslog) ! 1332: if ((sessft != 0) || ! 1333: (c != '\r' && ! 1334: c != '\0' && ! 1335: c != XON && ! 1336: c != XOFF)) ! 1337: if (zchout(ZSFILE,c) < 0) { ! 1338: conoll(""); ! 1339: conoll("ERROR WRITING SESSION LOG, LOG CLOSED!"); ! 1340: seslog = 0; ! 1341: } ! 1342: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.