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