Annotation of coherent/e/bin/ckermit/ckucon.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.