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 (fdc@columbia.edu, FDCCU@CUVMA.BITNET),
   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 UNIX
 611:            "local UNIX system"
 612: #else
 613:            "local system"
 614: #endif /* UNIX */
 615:            );
 616:     }
 617:     printf("\n");
 618:     what = W_NOTHING;       /* So console modes are set right. */
 619: #ifndef NOCSETS
 620:     language = langsv;      /* Restore language */
 621: #endif /* NOCSETS */
 622:     parent_id = (PID_T) 0;      /* Clean up */
 623: #ifdef DYNAMIC
 624:     if (temp) free(temp);       /* Free allocated memory */
 625:     if (ibuf) free(ibuf);
 626:     if (obuf) free(obuf);
 627: #endif /* DYNAMIC */
 628:     return(1);
 629:     }
 630:     if (pid) {              /* Top fork reads, sends keystrokes */
 631:     what = W_CONNECT;       /* Keep track of what we're doing */
 632:     active = 1;
 633:     debug(F101,"CONNECT keyboard fork duplex","",duplex);
 634: 
 635:     /* Catch communication errors or mode changes in lower fork */
 636: 
 637:     if (setjmp(con_env) == 0) { /* Normal entry... */
 638:         sjval = 0;          /* Initialize setjmp return code. */
 639:         signal(SIGUSR1,conn_int);   /* Routine for child process exit. */
 640:         signal(SIGUSR2,mode_chg);   /* Routine for mode change. */
 641: #ifdef SUNX25
 642:         if (network && nettype == NET_SX25) {
 643:         obufl = 0;
 644:         bzero (x25obuf,sizeof(x25obuf)) ;
 645:         }
 646: #endif /* SUNX25 */
 647: 
 648: /*
 649:   Here is the big loop that gets characters from the keyboard and sends them
 650:   out the communication device.  There are two components to the communication
 651:   path: the connection from the keyboard to C-Kermit, and from C-Kermit to
 652:   the remote computer.  The treatment of the 8th bit of keyboard characters
 653:   is governed by SET COMMAND BYTESIZE (cmdmsk).  The treatment of the 8th bit
 654:   of characters sent to the remote is governed by SET TERMINAL BYTESIZE
 655:   (cmask).   This distinction was introduced in edit 5A(164).
 656: */
 657:         while (active) {
 658: #ifndef NOSETKEY
 659:         if (kmptr) {        /* Have current macro? */
 660:             debug(F100,"kmptr non NULL","",0);
 661:             if ((c = (CHAR) *kmptr++) == NUL) { /* Get char from it */
 662:             kmptr = NULL;   /* If no more chars,  */
 663:             debug(F100,"macro empty, continuing","",0);
 664:             continue;   /* reset pointer and continue */
 665:             }
 666:             debug(F000,"char from macro","",c);
 667:         } else          /* No macro... */
 668: #endif /* NOSETKEY */
 669:           c = congks(0);    /* Read from keyboard */
 670: 
 671:         debug(F111,"** KEYB",dbchr(c),c);
 672: 
 673:                 if (c == -1) {      /* If read() got an error... */
 674: #ifdef COMMENT
 675: /*
 676:  This seems to cause problems.  If read() returns -1, the signal has already
 677:  been delivered, and nothing will wake up the pause().
 678: */
 679:             pause();        /* Wait for transmitter to finish. */
 680: #else
 681: #ifdef A986
 682: /*
 683:   On Altos machines with Xenix 3.0, pressing DEL in connect mode brings us
 684:   here (reason unknown).  The console line discipline at this point has
 685:   intr = ^C.  The communications tty has intr = DEL but we get here after
 686:   pressing DEL on the keyboard, even when the remote system has been set not
 687:   to echo.  With A986 defined, we stay in the read loop and beep only if the
 688:   offending character is not DEL.
 689: */
 690:             if ((c & 127) != 127) conoc(BEL);
 691: #else
 692:             conoc(BEL);     /* Beep */
 693:             active = 0;     /* and terminate the read loop */
 694:             continue;
 695: #endif /* A986 */
 696: #endif /* COMMENT */
 697:         }
 698:         c &= cmdmsk;        /* Do any requested masking */
 699: #ifndef NOSETKEY
 700: /*
 701:   Note: kmptr is NULL if we got character c from the keyboard, and it is
 702:   not NULL if it came from a macro.  In the latter case, we must avoid
 703:   expanding it again.
 704: */
 705:         if (!kmptr && macrotab[c]) { /* Macro definition for c? */
 706:             kmptr = macrotab[c];     /* Yes, set up macro pointer */
 707:             continue;            /* and restart the loop, */
 708:         } else c = keymap[c];        /* else use single-char keymap */
 709: #endif /* NOSETKEY */
 710:         if (
 711: #ifndef NOSETKEY
 712:             !kmptr &&
 713: #endif /* NOSETKEY */
 714:             ((c & 0x7f) == escape)) { /* Escape character? */
 715:             debug(F000,"connect got escape","",c);
 716:             c = congks(0) & 0177; /* Got esc, get its arg */
 717:             /* No key mapping here */
 718:             doesc((char) c);    /* Now process it */
 719: 
 720:         } else {        /* It's not the escape character */
 721:             csave = c;      /* Save it before translation */
 722:                     /* for local echoing. */
 723: #ifndef NOCSETS
 724: #ifndef SKIPESC
 725:             /* Translate character sets */
 726:             if (sxo) c = (*sxo)(c); /* From local to intermediate. */
 727:             if (rxo) c = (*rxo)(c); /* From intermediate to remote. */
 728: #else
 729:             if (inesc == ES_NORMAL) { /* If not inside escape seq.. */
 730:             /* Translate character sets */
 731:             if (sxo) c = (*sxo)((char)c); /* Local-intermediate */
 732:             if (rxo) c = (*rxo)((char)c); /* Intermediate-remote */
 733:             }
 734:             if (skipesc) chkaes((char)c); /* Check escape seq status */
 735: #endif /* SKIPESC */
 736: #endif /* NOCSETS */
 737: /*
 738:  If Shift-In/Shift-Out is selected and we have a 7-bit connection,
 739:  handle shifting here.
 740: */
 741:             if (sosi) {          /* Shift-In/Out selected? */
 742:             if (cmask == 0177) { /* In 7-bit environment? */
 743:                 if (c & 0200) {          /* 8-bit character? */
 744:                 if (outshift == 0) { /* If not shifted, */
 745:                     ttoc(dopar(SO)); /* shift. */
 746:                     outshift = 1;
 747:                 }
 748:                 } else {
 749:                 if (outshift == 1) { /* 7-bit character */
 750:                     ttoc(dopar(SI)); /* If shifted, */
 751:                     outshift = 0;    /* unshift. */
 752:                 }
 753:                 }
 754:             }
 755:             if (c == SO) outshift = 1;   /* User typed SO */
 756:             if (c == SI) outshift = 0;   /* User typed SI */
 757:             }
 758:             c &= cmask;     /* Apply Kermit-to-host mask now. */
 759: #ifdef SUNX25
 760:                     if (network && nettype == NET_SX25) {
 761:                         if (padparms[PAD_ECHO]) {
 762:                             if (debses)
 763:                   conol(dbchr(c)) ;
 764:                             else
 765:                   if ((c != padparms[PAD_CHAR_DELETE_CHAR])   &&
 766:                   (c != padparms[PAD_BUFFER_DELETE_CHAR]) &&
 767:                   (c != padparms[PAD_BUFFER_DISPLAY_CHAR]))
 768:                                 conoc(c) ;
 769:                             if (seslog) logchar(c);
 770:                         }
 771:             if (c == CR && (padparms[PAD_LF_AFTER_CR] == 4 ||
 772:                     padparms[PAD_LF_AFTER_CR] == 5)) {
 773:                             if (debses)
 774:                   conol(dbchr(LF)) ;
 775:                             else
 776:                   conoc(LF) ;
 777:                             if (seslog) logchar(LF);
 778:                         }
 779:                         if (c == padparms[PAD_BREAK_CHARACTER])
 780:               breakact();
 781:                         else if (padparms[PAD_DATA_FORWARD_TIMEOUT]) {
 782:                             tosend = 1;
 783:                             x25obuf [obufl++] = c;
 784:                         } else if (((c == padparms[PAD_CHAR_DELETE_CHAR])  ||
 785:                     (c == padparms[PAD_BUFFER_DELETE_CHAR]) ||
 786:                     (c == padparms[PAD_BUFFER_DISPLAY_CHAR]))
 787:                    && (padparms[PAD_EDITING]))
 788:               if (c == padparms[PAD_CHAR_DELETE_CHAR])
 789:                 if (obufl > 0) {
 790:                 conol("\b \b"); obufl--;
 791:                 } else {}
 792:               else if (c == padparms[PAD_BUFFER_DELETE_CHAR]) {
 793:                   conol ("\r\nPAD Buffer Deleted\r\n");
 794:                   obufl = 0;
 795:               }
 796:               else if (c == padparms[PAD_BUFFER_DISPLAY_CHAR]) {
 797:                   conol("\r\n");
 798:                   conol(x25obuf);
 799:                   conol("\r\n");
 800:               } else {}
 801:                         else {
 802:                             x25obuf [obufl++] = c;
 803:                             if (obufl == MAXOX25) tosend = 1;
 804:                             else if (c == CR) tosend = 1;
 805:                         }
 806:                         if (tosend)
 807:               if (ttol(x25obuf,obufl) < 0) {
 808:                   perror ("\r\nCan't send characters");
 809:                   active = 0;
 810:               } else {
 811:                   bzero (x25obuf,sizeof(x25obuf));
 812:                   obufl = 0;
 813:                   tosend = 0;
 814:               } else {};
 815:                     } else {
 816: #endif /* SUNX25 */
 817: 
 818: /* If we have a CR, handle CR/CRLF mapping... */
 819: 
 820:             if (c == '\015') {
 821:             if (tnlm    /* TERMINAL NEWLINE ON */
 822: #ifdef TNCODE               /* And for TELNET... */
 823:             || (network && ttnproto == NP_TELNET)
 824: #endif /* TNCODE */
 825:             ) {
 826:                 ttoc(dopar('\015'));    /* Send CR */
 827:                 if (duplex) conoc('\015');  /* Maybe echo CR */
 828: #ifdef TNCODE
 829:                 if (network && !tn_nlm && ttnproto == NP_TELNET)
 830:                   c = '\0';     /* Stuff NUL */
 831:                 else
 832: #endif /* TNCODE */
 833:                   c = '\012';   /* Stuff LF */
 834:                 csave = c;
 835:             }
 836:             }           /* Now process the LF or NUL... */
 837: #ifdef TNCODE
 838: /* If user types the 0xff character (TELNET IAC), it must be doubled. */
 839:             else
 840:               if (c == IAC && network && ttnproto == NP_TELNET) {
 841:                     /* Send one copy now */
 842:             ttoc((char)IAC); /* and the other one just below. */
 843:             }
 844: #endif /* TNCODE */
 845: 
 846:             /* Send the character */
 847: 
 848:             if (ttoc((char)dopar((CHAR) c)) > -1) {
 849:                 if (duplex) {   /* If half duplex, must echo */
 850:                 if (debses)
 851:                   conol(dbchr(csave)); /* the original char */
 852:                 else               /* not the translated one */
 853:                   conoc((char)csave);
 854:                 if (seslog) { /* And maybe log it too */
 855:                 c2 = csave;
 856:                 if (sessft == 0 && csave == '\r')
 857:                   c2 = '\n';
 858:                 logchar((char)c2);
 859:                 }
 860:             }
 861:                     } else {
 862:             perror("\r\nCan't send character");
 863:             active = 0;
 864:             }
 865: #ifdef SUNX25
 866:         }
 867: #endif /* SUNX25 */
 868:         }
 869:         }
 870:     }               /* Come here on death of child */
 871:     debug(F100,"CONNECT killing port fork","",0);
 872:     kill(pid,9);            /* Done, kill inferior fork. */
 873:     wait((WAIT_T *)0);      /* Wait till gone. */
 874:     if (sjval == 1) {       /* Read error on comm device */
 875:         dohangup = 1;
 876: #ifdef NETCONN
 877:         if (network) {
 878:         ttclos(0);
 879: #ifdef SUNX25
 880:         if (nettype == NET_SX25) initpad();
 881: #endif /* SUNX25 */
 882:         }
 883: #endif /* NETCONN */
 884:     }
 885:     if (sjval == 2)         /* If it was a mode change, go back */
 886:       goto newfork;         /* and coordinate with other fork. */
 887:     conres();           /* Reset the console. */
 888:     if (quitnow) doexit(GOOD_EXIT,xitsta); /* Exit now if requested. */
 889:     if (dohangup > 0) {     /* If hangup requested, do that. */
 890: #ifndef NODIAL
 891:         if (dohangup > 1)       /* User asked for it */
 892:           if (mdmhup() < 1)     /* Maybe hang up via modem */
 893: #endif /* NODIAL */
 894:           tthang();         /* And make sure we don't hang up */
 895:         dohangup = 0;       /* again unless requested again. */
 896:     }
 897: #ifdef SUNX25
 898:     if (dox25clr) {         /* If X.25 clear requested */
 899:         x25clear();         /* do that. */
 900:         initpad();
 901:         dox25clr = 0;       /* But only once. */
 902:     }
 903: #endif /* SUNX25 */
 904:     if (!quiet)
 905:       printf("(Back at %s)", *myhost ? myhost : "local UNIX system");
 906:     printf("\n");
 907:     what = W_NOTHING;       /* So console modes set right. */
 908: #ifndef NOCSETS
 909:     language = langsv;      /* Restore language */
 910: #endif /* NOCSETS */
 911:     parent_id = (PID_T) 0;
 912: #ifdef DYNAMIC
 913:     if (temp) free(temp);       /* Free allocated memory */
 914:     if (ibuf) free(ibuf);
 915:     if (obuf) free(obuf);
 916: #endif /* DYNAMIC */
 917:     return(1);
 918: 
 919:     } else {                /* Inferior reads, prints port input */
 920: 
 921: #ifndef OXOS
 922:     if (priv_can()) {       /* Cancel all privs */
 923:         printf("?setuid error - fatal\n");
 924:         doexit(BAD_EXIT,-1);
 925:     }
 926: #endif /* OXOS */
 927:     signal(SIGINT, SIG_IGN);    /* In case these haven't been */
 928:     signal(SIGQUIT, SIG_IGN);   /* inherited from above... */
 929: 
 930:     inshift = outshift = 0;     /* Initial SO/SI shift state. */
 931:     sleep(1);           /* Wait for parent's handler setup.  */
 932:     ibp = ibuf;         /* Initialize input buffering */
 933:     ibc = 0;            /* And output buffering. */
 934:     obp = obuf;
 935:     obc = 0;
 936:     debug(F100,"CONNECT starting port fork","",0);
 937:     while (1) {         /* Fresh read, wait for a character. */
 938: #ifdef SUNX25
 939:         if (network && (nettype == NET_SX25)) {
 940:         bzero(x25ibuf,sizeof(x25ibuf)) ;
 941:         if ((ibufl = ttxin(MAXIX25,x25ibuf)) < 0) {
 942:             if (ibufl == -2) {  /* PAD parms changes */
 943:             write(padpipe[1],padparms,MAXPADPARMS);
 944:             kill(parent_id,SIGUSR2);
 945:             } else {
 946:             if (!quiet)
 947:               printf("\r\nCommunications disconnect ");
 948:             kill(parent_id,SIGUSR1);
 949:             }
 950:             pause();
 951:         }
 952:         if (debses) {       /* Debugging output */
 953:             p = x25ibuf ;
 954:                         while (ibufl--) { c = *p++; conol(dbchr(c)); }
 955:         } else {
 956:             if (sosi
 957: #ifndef NOCSETS
 958:             || tcsl != tcsr
 959: #endif /* NOCSETS */
 960:             ) { /* Character at a time */
 961:             for (i = 1; i < ibufl; i++) {
 962:                 c = x25ibuf[i] & cmask;
 963:                 if (sosi) { /* Handle SI/SO */
 964:                 if (c == SO) {
 965:                     inshift = 1;
 966:                     continue;
 967:                 } else if (c == SI) {
 968:                     inshift = 0;
 969:                     continue;
 970:                 }
 971:                 if (inshift)
 972:                   c |= 0200;
 973:                 }
 974: #ifndef NOCSETS
 975: #ifndef SKIPESC
 976:             /* Translate character sets */
 977:             if (sxo) c = (*sxo)(c); /* From local to intermediate. */
 978:             if (rxo) c = (*rxo)(c); /* From intermediate to remote. */
 979: 
 980: #else /* Skipping escape sequences... */
 981: 
 982:             if (inesc == ES_NORMAL) { /* If not inside escape seq.. */
 983:             /* Translate character sets */
 984:             if (sxo) c = (*sxo)(c); /* Local to intermediate. */
 985:             if (rxo) c = (*rxo)(c); /* Intermediate to remote. */
 986:             }
 987:             if (skipesc) chkaes(c); /* Check escape sequence status */
 988: #endif /* SKIPESC */
 989: #endif /* NOCSETS */
 990:                 c &= cmdmsk; /* Apply command mask. */
 991:                 conoc(c);    /* Output to screen */
 992:                 logchar(c);  /* and session log */
 993:             }
 994:             } else {         /* All at once */
 995:             for (i = 1; i < ibufl; i++)
 996:               x25ibuf[i] &= (cmask & cmdmsk);
 997:             conxo(ibufl,x25ibuf);
 998:             if (seslog) zsoutx(ZSFILE,x25ibuf,ibufl);
 999:             }
1000:         }
1001:         continue;
1002: 
1003:         } else {            /* Not X.25... */
1004: #endif /* SUNX25 */
1005: /*
1006:   Get the next communication line character from our internal buffer.
1007:   If the buffer is empty, refill it.
1008: */
1009:         c = ckcgetc(0);     /* Get next character */
1010:         /* debug(F101,"CONNECT c","",c); */
1011:         if (c < 0) {
1012:             if (!quiet) {   /* Failed... */
1013:             printf("\r\nCommunications disconnect ");
1014:             if ( c == -3
1015: #ifdef UTEK
1016: /* This happens on UTEK if there's no carrier */
1017:                 && errno != EWOULDBLOCK
1018: #endif /* UTEK */
1019:                 )
1020:               perror("\r\nCan't read character");
1021:             }
1022:             tthang();       /* Hang up the connection */
1023:             kill(parent_id,SIGUSR1); /* Notify parent */
1024:             for (;;) pause();   /* and wait to be killed */
1025:         }
1026:         debug(F111,"** PORT",dbchr(c),c);
1027: #ifdef TNCODE
1028:         /* Handle TELNET negotiations here */
1029:         if (c == IAC && network && ttnproto == NP_TELNET) {
1030:             ckcputf();      /* Dump output buffer */
1031:             if ((tx = tn_doop((CHAR)(c & 0xff),duplex,ckcgetc)) == 0) {
1032:             continue;
1033:             } else if (tx == -1) { /* I/O error */
1034:             if (!quiet)
1035:               printf("\r\nCommunications disconnect ");
1036:             kill(parent_id,SIGUSR1); /* Notify parent. */
1037:             for (;;) pause(); /* Wait to be killed. */
1038:             } else if ((tx == 1) && (!duplex)) { /* ECHO change */
1039:             kill(parent_id,SIGUSR2); /* Tell the parent fork */
1040:             duplex = 1;
1041:             } else if ((tx == 2) && (duplex)) { /* ECHO change */
1042:             kill(parent_id,SIGUSR2);
1043:             duplex = 0;
1044:             } else if (tx == 3) { /* Quoted IAC */
1045:             c = 255;
1046:             } else continue;    /* Negotiation OK, get next char. */
1047:         }
1048: #endif /* TNCODE */
1049:         if (debses) {       /* Output character to screen */
1050:             char *s;        /* Debugging display... */
1051:             s = dbchr(c);
1052:             while (*s)
1053:               ckcputc(*s++);
1054:         } else {        /* Regular display ... */
1055:             c &= cmask;     /* Apply Kermit-to-remote mask */
1056:             if (sosi) {     /* Handle SI/SO */
1057:             if (c == SO) {  /* Shift Out */
1058:                 inshift = 1;
1059:                 continue;
1060:             } else if (c == SI) { /* Shift In */
1061:                 inshift = 0;
1062:                 continue;
1063:             }
1064:             if (inshift) c |= 0200;
1065:             }
1066: #ifndef NOCSETS
1067: #ifndef SKIPESC
1068:             /* Translate character sets */
1069:             if (sxi) c = (*sxi)((CHAR)c);
1070:             if (rxi) c = (*rxi)((CHAR)c);
1071: #else
1072:             if (inesc == ES_NORMAL) {
1073:             /* Translate character sets */
1074:             if (sxi) c = (*sxi)((CHAR)c);
1075:             if (rxi) c = (*rxi)((CHAR)c);
1076:             }
1077:             /* Adjust escape sequence status */
1078:             if (skipesc) chkaes((char)c);
1079: #endif /* SKIPESC */
1080: #endif /* NOCSETS */
1081:             c &= cmdmsk;    /* Apply command mask. */
1082:             if (c == CR && tt_crd) { /* SET TERM CR-DISPLAY CRLF ? */
1083:             ckcputc(c);      /* Yes, output CR */
1084:             if (seslog) logchar((char)c);
1085:             c = LF;          /* and insert a linefeed */
1086:             }
1087:             ckcputc(c);     /* Output character to screen */
1088:             if (seslog) logchar((char)c); /* Do session log */
1089:         }
1090: #ifdef SUNX25
1091:         }
1092: #endif /* SUNX25 */
1093:     }
1094:     }
1095: }
1096: 
1097: 
1098: /*  H C O N N E  --  Give help message for connect.  */
1099: 
1100: int
1101: hconne() {
1102:     int c;
1103:     static char *hlpmsg[] = {
1104: "\r\n  ? for this message",
1105: "\r\n  0 (zero) to send a null",
1106: "\r\n  B to send a BREAK",
1107: #ifdef CK_LBRK
1108: "\r\n  L to send a Long BREAK",
1109: #endif /* CK_LBRK */
1110: #ifdef NETCONN
1111: "\r\n  I to send a network interrupt packet",
1112: #ifdef TCPSOCKET
1113: "\r\n  A to send Are You There?",
1114: #endif /* TCPSOCKET */
1115: #ifdef SUNX25
1116: "\r\n  R to reset X.25 virtual circuit",
1117: #endif /* SUNX25 */
1118: #endif /* NETCONN */
1119: "\r\n  H to hangup and close the connection",
1120: "\r\n  Q to hangup and quit Kermit",
1121: "\r\n  S for status",
1122: "\r\n  ! to push to local shell",
1123: "\r\n  Z to suspend",
1124: "\r\n  \\ backslash code:",
1125: "\r\n    \\nnn  decimal character code",
1126: "\r\n    \\Onnn octal character code",
1127: "\r\n    \\Xhh  hexadecimal character code",
1128: "\r\n    terminate with carriage return.",
1129: "\r\n Type the escape character again to send the escape character, or",
1130: "\r\n press the space-bar to resume the CONNECT command.\r\n\r\n",
1131: "" };
1132:     conol("\r\nPress C to return to ");
1133:     conol(*myhost ? myhost : "the C-Kermit prompt");
1134:     conol(", or:");
1135:     conola(hlpmsg);         /* Print the help message. */
1136:     conol("Command>");          /* Prompt for command. */
1137:     c = congks(0) & 0177;       /* Get character, strip any parity. */
1138:     /* No key mapping or translation here */
1139:     if (c != CMDQ)
1140:       conoll("");
1141:     return(c);              /* Return it. */
1142: }
1143: 
1144: 
1145: /*  D O E S C  --  Process an escape character argument  */
1146: 
1147: VOID
1148: #ifdef CK_ANSIC
1149: doesc(char c)
1150: #else
1151: doesc(c) char c;
1152: #endif /* CK_ANSIC */
1153: /* doesc */ {
1154:     CHAR d;
1155: 
1156:     while (1) {
1157:     if (c == escape) {      /* Send escape character */
1158:         d = dopar((CHAR) c); ttoc((char) d); return;
1159:         } else              /* Or else look it up below. */
1160:         if (isupper(c)) c = tolower(c);
1161: 
1162:     switch(c) {
1163: 
1164:     case 'c':           /* Escape back to prompt */
1165:     case '\03':
1166:         active = 0; conol("\r\n"); return;
1167: 
1168:     case 'b':           /* Send a BREAK signal */
1169:     case '\02':
1170:         ttsndb(); return;
1171: 
1172: #ifdef NETCONN
1173:     case 'i':           /* Send Interrupt */
1174:     case '\011':
1175: #ifdef TCPSOCKET
1176: #ifndef IP
1177: #define IP 244
1178: #endif /* IP */
1179:         if (network && ttnproto == NP_TELNET) { /* TELNET */
1180:         temp[0] = IAC;      /* I Am a Command */
1181:         temp[1] = IP;       /* Interrupt Process */
1182:         temp[2] = NUL;
1183:         ttol((CHAR *)temp,2);
1184:         } else
1185: #endif /* TCPSOCKET */
1186: #ifdef SUNX25
1187:             if (network && (nettype == NET_SX25)) { /* X.25 */
1188:         (VOID) x25intr(0);              /* X.25 interrupt packet */
1189:         conol("\r\n");
1190:         } else
1191: #endif /* SUNX25 */
1192:           conoc(BEL);
1193:         return;
1194: 
1195: #ifdef TCPSOCKET
1196:     case 'a':           /* "Are You There?" */
1197:     case '\01':
1198: #ifndef AYT
1199: #define AYT 246
1200: #endif /* AYT */
1201:         if (network && ttnproto == NP_TELNET) {
1202:         temp[0] = IAC;      /* I Am a Command */
1203:         temp[1] = AYT;      /* Are You There? */
1204:         temp[2] = NUL;
1205:         ttol((CHAR *)temp,2);
1206:         } else conoc(BEL);
1207:         return;
1208: #endif /* TCPSOCKET */
1209: #endif /* NETCONN */
1210: 
1211: #ifdef CK_LBRK
1212:     case 'l':           /* Send a Long BREAK signal */
1213:         ttsndlb(); return;
1214: #endif /* CK_LBRK */
1215: 
1216:     case 'h':           /* Hangup */
1217:     case '\010':
1218: #ifdef SUNX25
1219:             if (network && (nettype == NET_SX25)) dox25clr = 1;
1220:             else
1221: #endif /* SUNX25 */
1222:         dohangup = 2; active = 0; conol("\r\nHanging up "); return;
1223: 
1224: #ifdef SUNX25
1225:         case 'r':                       /* Reset the X.25 virtual circuit */
1226:         case '\022':
1227:             if (network && (nettype == NET_SX25)) (VOID) x25reset();
1228:             conol("\r\n"); return;
1229: #endif /* SUNX25 */
1230: 
1231:     case 'q':           /* Quit */
1232:         quitnow = 1; active = 0; conol("\r\n"); return;
1233: 
1234:     case 's':           /* Status */
1235:         sprintf(temp,
1236:             "\r\nConnected %s %s", network ? "to" : "through", ttname);
1237:         conol(temp);
1238: #ifdef SUNX25
1239:             if (network && (nettype == NET_SX25)) {
1240:                 sprintf(temp,", Link ID %d, LCN %d",linkid,lcn); conol(temp);
1241:         }
1242: #endif /* SUNX25 */
1243:         if (speed >= 0L) {
1244:         sprintf(temp,", speed %ld", speed);
1245:         conoll(temp);
1246:         } else conoll("");
1247:         sprintf(temp,
1248:             "Terminal bytesize: %d, Command bytesize: %d, Parity: ",
1249:             (cmask  == 0177) ? 7 : 8,
1250:             (cmdmsk == 0177) ? 7 : 8 );
1251:         conol(temp);
1252: 
1253:         switch (parity) {
1254:           case  0:  conoll("none");  break;
1255:           case 'e': conoll("even");  break;
1256:           case 'o': conoll("odd");   break;
1257:           case 's': conoll("space"); break;
1258:           case 'm': conoll("mark");  break;
1259:         }
1260:         sprintf(temp,"Terminal echo: %s", duplex ? "local" : "remote");
1261:         conoll(temp);
1262:         if (seslog) {
1263:         conol("Logging to: "); conoll(sesfil);
1264:             }
1265:         if (!network) shomdm();
1266:         return;
1267: 
1268:     case '?':           /* Help */
1269:         c = hconne(); continue;
1270: 
1271:     case '0':           /* Send a null */
1272:         c = '\0'; d = dopar((CHAR) c); ttoc((char) d); return;
1273: 
1274: #ifndef NOPUSH
1275:     case 'z': case '\032':      /* Suspend */
1276:         stptrap(0); return;
1277: 
1278:     case '@':           /* Start inferior command processor */
1279:     case '!':
1280:         conres();           /* Put console back to normal */
1281:         zshcmd("");         /* Fork a shell. */
1282:         if (conbin((char)escape) < 0) {
1283:         printf("Error resuming CONNECT session\n");
1284:         active = 0;
1285:         }
1286:         return;
1287: #endif /* NOPUSH */
1288: 
1289:     case SP:            /* Space, ignore */
1290:         return;
1291: 
1292:     default:            /* Other */
1293:         if (c == CMDQ) {        /* Backslash escape */
1294:         int x;
1295:         kbp = kbuf;
1296:         *kbp++ = c;
1297:         while (((c = (congks(0) & cmdmsk)) != '\r') && (c != '\n'))
1298:           *kbp++ = c;
1299:         *kbp = NUL; kbp = kbuf;
1300:         x = xxesc(&kbp);    /* Interpret it */
1301:         if (x >= 0) {       /* No key mapping here */
1302:             c = dopar((CHAR) x);
1303:             ttoc((char) c);
1304:             return;
1305:         } else {        /* Invalid backslash code. */
1306:             conoc(BEL);
1307:             return;
1308:         }
1309:         }
1310:         conoc(BEL); return;     /* Invalid esc arg, beep */
1311:         }
1312:     }
1313: }
1314: 
1315: VOID
1316: #ifdef CK_ANSIC
1317: logchar(char c)
1318: #else
1319: logchar(c) char c;
1320: #endif /* CK_ANSIC */
1321: /* logchar */ {         /* Log character c to session log */
1322:     if (seslog)
1323:       if ((sessft != 0) ||
1324:       (c != '\r' &&
1325:        c != '\0' &&
1326:        c != XON &&
1327:        c != XOFF))
1328:     if (zchout(ZSFILE,c) < 0) {
1329:         conoll("");
1330:         conoll("ERROR WRITING SESSION LOG, LOG CLOSED!");
1331:         seslog = 0;
1332:     }
1333: }

Defined functions

chkaes defined in line 229; used 3 times
ckcgetc defined in line 369; used 2 times
ckcputc defined in line 346; used 3 times
ckcputf defined in line 336; used 1 times
conn_int defined in line 299; used 1 times
doesc defined in line 1147; used 2 times
hconne defined in line 1100; used 2 times
logchar defined in line 1315; used 7 times
mode_chg defined in line 307; used 2 times

Defined variables

VOID defined in line 1147; never used
active defined in line 110; used 10 times
con_env defined in line 289; used 3 times
connv defined in line 1; used 1 times
dox25clr defined in line 115; used 4 times
ibc defined in line 86; used 11 times
ibp defined in line 85; used 7 times
ibuf defined in line 101; used 9 times
ibufl defined in line 111; used 7 times
kbp defined in line 82; used 6 times
kbuf defined in line 82; used 2 times
kmptr defined in line 67; used 6 times
langsv defined in line 139; used 3 times
lcn defined in line 114; used 2 times
linkid defined in line 114; used 2 times
obc defined in line 94; used 9 times
obp defined in line 93; used 4 times
obuf defined in line 101; used 12 times
obufl defined in line 112; used 9 times
p defined in line 107; used 2 times
padpipe defined in line 117; used 3 times
quitnow defined in line 72; used 2 times
skipesc defined in line 169; used 5 times
tcs defined in line 142; used 7 times
temp defined in line 101; used 29 times
tosend defined in line 113; used 5 times
x25ibuf defined in line 108; used 8 times
x25obuf defined in line 109; used 8 times

Defined macros

AYT defined in line 1199; used 2 times
ES_ESCSEQ defined in line 163; used 1 times
ES_GOTCSI defined in line 164; used 1 times
ES_GOTESC defined in line 162; used 3 times
ES_NORMAL defined in line 161; used 10 times
ES_STRING defined in line 165; used 2 times
ES_TERMIN defined in line 166; used 1 times
IBUFL defined in line 90; used 4 times
IP defined in line 1177; used 2 times
OBUFL defined in line 95; used 3 times
SIGUSR1 defined in line 49; used 7 times
SIGUSR2 defined in line 53; used 6 times
SKIPESC defined in line 156; used 5 times
TMPLEN defined in line 97; used 2 times
Last modified: 1992-11-24
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 8010
Valid CSS Valid XHTML 1.0 Strict