Annotation of coherent/e/bin/cku179/ckucon.c, revision 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.