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

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

unix.superglobalmegacorp.com

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