%(
****************************************************************
Copyright (c) 1992, Carnegie Mellon University
All Rights Reserved
Permission is hereby granted to use, copy, modify, and
distribute this software provided that the above copyright
notice appears in all copies and that any distribution be for
noncommercial purposes.
Carnegie Mellon University disclaims all warranties with regard
to this software. In no event shall Carnegie Mellon University
be liable for any special, indirect, or consequential damages
or any damages whatsoever resulting from loss of use, data, or
profits arising out of or in connection with the use or
performance of this software.
****************************************************************
)%
%TITLE 'TCP_TELNET_MISC - TELNET Virtual Terminal service support routines'
%(
Facility:
TCP_TELNET - Run incoming TELNET service under TCP (RFC 854)
Abstract:
A collection of routines which support the TELNET module.
Includes option-specific code, etc...
Author:
1.0 02-Feb-1989 Bruce R. Miller CMU Network Development
Module Modification History:
1.1 13-Nov-1991 John M. Clement (JC) Rice University
Added many terminal types and fixed the WINDOW_SIZE and TERMINAL_TYPE
setting routines. Also removed all calls to SIGNAL
Calls to SIGNAL are forbidded if we run under IPACP.
The Terminal name is now parsed by preceding it by "*"
and doing a wild search. This allows syntax as VT240 or DEC-VT240
Indeed even 240 will be understood.
Set_DEVDEP added to turn on/off 8-bit, PASSALL
When Terminal type is received only ask for new one if current one
is different from last one or after 6 tries.
Fixed a problem in Timing_mark_ON Referred to REMOPTS instead of
LCLOPTS (JC)
)%
MODULE TELNET_MISC(IDENT='1.0',LANGUAGE(BLISS32),
ADDRESSING_MODE(EXTERNAL=LONG_RELATIVE,
NONEXTERNAL=LONG_RELATIVE),
LIST(REQUIRE,ASSEMBLY,OBJECT,BINARY),
OPTIMIZE,OPTLEVEL=3,ZIP)=
BEGIN
LIBRARY 'SYS$LIBRARY:LIB'; ! JC
!LIBRARY 'SYS$LIBRARY:STARLET';
LIBRARY 'CMUIP_SRC:[CENTRAL]NETXPORT'; ! BLISS common definitions
LIBRARY 'TELNET'; ! TELNET protocol definitions
LIBRARY 'TCPMacros'; ! Local (tcp) Macro defintions.
!++
! This macro describes the terminal translation table entries.
!--
! Modified by J .Clement JC
! Changed table structure to include the Device dependent terminal
! This has been modified to include all known DEC terminal types.
! Characteristics.
$FIELD TTAB$FIELDS =
SET
TTab$L_NAME = [$ADDRESS],
TTab$W_TYPE = [$BYTES(4)],
TTab$L_DEVDEP = [$BYTES(4)],
TTab$L_DEVDEP2 = [$BYTES(4)]
TES;
LITERAL
TTab$K_Size = $Field_Set_Size,
TTab$K_Table_Size = 39;
MACRO
TTab$Entry = BLOCK[TTab$K_Size] FIELD(TTAB$FIELDS)%;
OWN
Term_Table : VECTOR[(TTab$K_Size+1)*TTab$K_Table_Size, LONG]
PRESET (
[0] = TTab$K_Table_Size,
[1] = TTab$K_Size,
[1*TTAB$K_Size+0] = %ASCID'UNKNOWN',
[1*TTab$K_Size+1] = TT$_UNKNOWN,
[1*TTab$K_Size+2] = 0,
[1*TTab$K_Size+3] = 0,
[2*TTAB$K_Size+0] = %ASCID'DEC-FT1',
[2*TTab$K_Size+1] = TT$_FT1,
[2*TTab$K_Size+2] = 0,
[2*TTab$K_Size+3] = 0,
[3*TTAB$K_Size+0] = %ASCID'DEC-FT2',
[3*TTab$K_Size+1] = TT$_FT2,
[3*TTab$K_Size+2] = 0,
[3*TTab$K_Size+3] = 0,
[4*TTAB$K_Size+0] = %ASCID'DEC-FT3',
[4*TTab$K_Size+1] = TT$_FT3,
[4*TTab$K_Size+2] = 0,
[4*TTab$K_Size+3] = 0,
[5*TTAB$K_Size+0] = %ASCID'DEC-FT4',
[5*TTab$K_Size+1] = TT$_FT4,
[5*TTab$K_Size+2] = 0,
[5*TTab$K_Size+3] = 0,
[6*TTAB$K_Size+0] = %ASCID'DEC-FT5',
[6*TTab$K_Size+1] = TT$_FT5,
[6*TTab$K_Size+2] = 0,
[6*TTab$K_Size+3] = 0,
[7*TTAB$K_Size+0] = %ASCID'DEC-FT6',
[7*TTab$K_Size+1] = TT$_FT6,
[7*TTab$K_Size+2] = 0,
[7*TTab$K_Size+3] = 0,
[8*TTAB$K_Size+0] = %ASCID'DEC-FT7',
[8*TTab$K_Size+1] = TT$_FT7,
[8*TTab$K_Size+2] = 0,
[8*TTab$K_Size+3] = 0,
[9*TTAB$K_Size+0] = %ASCID'DEC-FT8',
[9*TTab$K_Size+1] = TT$_FT8,
[9*TTab$K_Size+2] = 0,
[9*TTab$K_Size+3] = 0,
[10*TTAB$K_Size+0] = %ASCID'DEC-TQ_BTS', ! ????
[10*TTab$K_Size+1] = TT$_TQ_BTS,
[10*TTab$K_Size+2] = 0,
[10*TTab$K_Size+3] = 0,
[11*TTAB$K_Size+0] = %ASCID'DEC-VT05',
[11*TTab$K_Size+1] = TT$_VT05,
[11*TTab$K_Size+2] = 0
+TT$M_MECHTAB
+TT$M_WRAP
+TT$M_LFFILL
+TT$M_SCOPE,
[11*TTab$K_Size+3] = 0,
[12*TTAB$K_Size+0] = %ASCID'DEC-VK100',
[12*TTab$K_Size+1] = TT$_VK100,
[12*TTab$K_Size+2] = 0
+TT$M_LOWER
+TT$M_MECHTAB
+TT$M_WRAP
+TT$M_SCOPE,
[12*TTab$K_Size+3] = 0
+TT2$M_ANSICRT
+TT2$M_AVO
+TT2$M_DECCRT,
[13*TTAB$K_Size+0] = %ASCID'TEK',
[13*TTab$K_Size+1] = TT$_TEK401X,
[13*TTab$K_Size+2] = 0
+TT$M_LOWER
+TT$M_MECHTAB
+TT$M_MECHFORM,
[13*TTab$K_Size+3] = 0,
[14*TTAB$K_Size+0] = %ASCID'DEC-LAX',
[14*TTab$K_Size+1] = TT$_LAX,
[14*TTab$K_Size+2] = 0
+TT$M_LOWER
+TT$M_MECHTAB
+TT$M_WRAP
+TT$M_MECHFORM,
[14*TTab$K_Size+3] = 0,
[15*TTAB$K_Size+0] = %ASCID'DEC-LA34',
[15*TTab$K_Size+1] = TT$_LA34,
[15*TTab$K_Size+2] = 0
+TT$M_LOWER
+TT$M_WRAP
+TT$M_MECHFORM,
[15*TTab$K_Size+3] = 0,
[16*TTAB$K_Size+0] = %ASCID'DEC-LA36',
[16*TTab$K_Size+1] = TT$_LA36,
[16*TTab$K_Size+2] = 0
+TT$M_LOWER
+TT$M_WRAP,
[16*TTab$K_Size+3] = 0,
[17*TTAB$K_Size+0] = %ASCID'DEC-LA38',
[17*TTab$K_Size+1] = TT$_LA38,
[17*TTab$K_Size+2] = 0
+TT$M_LOWER
+TT$M_WRAP
+TT$M_MECHFORM,
[17*TTab$K_Size+3] = 0,
[18*TTAB$K_Size+0] = %ASCID'DEC-VT5X',
[18*TTab$K_Size+1] = TT$_VT5X,
[18*TTab$K_Size+2] = 0
+TT$M_LOWER
+TT$M_MECHTAB
+TT$M_WRAP
+TT$M_SCOPE,
[18*TTab$K_Size+3] = 0,
[19*TTAB$K_Size+0] = %ASCID'DEC-VT50',
[19*TTab$K_Size+1] = TT$_VT5X,
[19*TTab$K_Size+2] = 0
+TT$M_LOWER
+TT$M_MECHTAB
+TT$M_WRAP
+TT$M_SCOPE,
[19*TTab$K_Size+3] = 0,
[20*TTAB$K_Size+0] = %ASCID'DEC-VT52',
[20*TTab$K_Size+1] = TT$_VT52,
[20*TTab$K_Size+2] = 0
+TT$M_LOWER
+TT$M_MECHTAB
+TT$M_WRAP
+TT$M_SCOPE,
[20*TTab$K_Size+3] = 0,
[21*TTAB$K_Size+0] = %ASCID'DEC-VT55',
[21*TTab$K_Size+1] = TT$_VT55,
[21*TTab$K_Size+2] = 0
+TT$M_LOWER
+TT$M_MECHTAB
+TT$M_WRAP
+TT$M_SCOPE,
[21*TTab$K_Size+3] = 0,
[22*TTAB$K_Size+0] = %ASCID'DEC-VT80',
[22*TTab$K_Size+1] = TT$_VT80,
[22*TTab$K_Size+2] = 0
+TT$M_LOWER
+TT$M_MECHTAB
+TT$M_WRAP
+TT$M_SCOPE,
[22*TTab$K_Size+3] = 0
+TT2$M_ANSICRT
!!!Optional +TT2$M_AVO
+TT2$M_DECCRT,
[23*TTAB$K_Size+0] = %ASCID'DEC-VT100',
[23*TTab$K_Size+1] = TT$_VT100,
[23*TTab$K_Size+2] = 0
+TT$M_LOWER
+TT$M_MECHTAB
+TT$M_WRAP
+TT$M_SCOPE,
[23*TTab$K_Size+3] = 0
+TT2$M_ANSICRT
!!!Optional +TT2$M_AVO
+TT2$M_DECCRT,
[24*TTAB$K_Size+0] = %ASCID'DEC-VT101',
[24*TTab$K_Size+1] = TT$_VT101,
[24*TTab$K_Size+2] = 0
+TT$M_LOWER
+TT$M_MECHTAB
+TT$M_WRAP
+TT$M_SCOPE,
[24*TTab$K_Size+3] = 0
+TT2$M_ANSICRT
+TT2$M_DECCRT,
[25*TTAB$K_Size+0] = %ASCID'DEC-VT102',
[25*TTab$K_Size+1] = TT$_VT102,
[25*TTab$K_Size+2] = 0
+TT$M_LOWER
+TT$M_MECHTAB
+TT$M_WRAP
+TT$M_SCOPE,
[25*TTab$K_Size+3] = 0
+TT2$M_PRINTER
+TT2$M_ANSICRT
+TT2$M_AVO
+TT2$M_EDIT
+TT2$M_DECCRT,
[26*TTAB$K_Size+0] = %ASCID'DEC-VT105',
[26*TTab$K_Size+1] = TT$_VT105,
[26*TTab$K_Size+2] = 0
+TT$M_LOWER
+TT$M_MECHTAB
+TT$M_WRAP
+TT$M_SCOPE,
[26*TTab$K_Size+3] = 0
+TT2$M_ANSICRT
!!!Optional +TT2$M_AVO
+TT2$M_EDIT
+TT2$M_DECCRT,
[27*TTAB$K_Size+0] = %ASCID'DEC-VT125',
[27*TTab$K_Size+1] = TT$_VT125,
[27*TTab$K_Size+2] = 0
+TT$M_LOWER
+TT$M_MECHTAB
+TT$M_WRAP
+TT$M_SCOPE,
[27*TTab$K_Size+3] = 0
+TT2$M_SIXEL
+TT2$M_PRINTER
+TT2$M_APP_KEYPAD
+TT2$M_ANSICRT
+TT2$M_REGIS
+TT2$M_AVO
+TT2$M_DECCRT,
[28*TTAB$K_Size+0] = %ASCID'DEC-VT131',
[28*TTab$K_Size+1] = TT$_VT131,
[28*TTab$K_Size+2] = 0
+TT$M_LOWER
+TT$M_MECHTAB
+TT$M_WRAP
+TT$M_SCOPE,
[28*TTab$K_Size+3] = 0
+TT2$M_ANSICRT
+TT2$M_BLOCK
+TT2$M_AVO
+TT2$M_EDIT
+TT2$M_DECCRT,
[29*TTAB$K_Size+0] = %ASCID'DEC-VT132',
[29*TTab$K_Size+1] = TT$_VT132,
[29*TTab$K_Size+2] = 0
+TT$M_LOWER
+TT$M_MECHTAB
+TT$M_WRAP
+TT$M_SCOPE,
[29*TTab$K_Size+3] = 0
+TT2$M_ANSICRT
+TT2$M_BLOCK
+TT2$M_AVO
+TT2$M_EDIT
+TT2$M_DECCRT,
[30*TTAB$K_Size+0] = %ASCID'DEC-VT132',
[30*TTab$K_Size+1] = TT$_VT132,
[30*TTab$K_Size+2] = 0
+TT$M_LOWER
+TT$M_MECHTAB
+TT$M_WRAP
+TT$M_SCOPE,
[30*TTab$K_Size+3] = 0
+TT2$M_ANSICRT
+TT2$M_BLOCK
+TT2$M_AVO
+TT2$M_EDIT
+TT2$M_DECCRT,
[31*TTAB$K_Size+0] = %ASCID'DEC-VT173',
[31*TTab$K_Size+1] = TT$_VT173,
[31*TTab$K_Size+2] = 0
+TT$M_LOWER
+TT$M_MECHTAB
+TT$M_WRAP
+TT$M_SCOPE,
[31*TTab$K_Size+3] = 0
+TT2$M_BLOCK
+TT2$M_AVO
+TT2$M_EDIT,
[32*TTAB$K_Size+0] = %ASCID'DECPRO',
[32*TTab$K_Size+1] = TT$_Pro_Series,
[32*TTab$K_Size+2] = 0
+TT$M_LOWER
+TT$M_MECHTAB
+TT$M_WRAP
+TT$M_SCOPE,
[32*TTab$K_Size+3] = 0
+TT2$M_PRINTER
+TT2$M_ANSICRT
+TT2$M_AVO
+TT2$M_EDIT
+TT2$M_DECCRT,
[33*TTAB$K_Size+0] = %ASCID'DEC-VT200',
[33*TTab$K_Size+1] = TT$_VT200_Series,
[33*TTab$K_Size+2] = 0
+TT$M_LOWER
+TT$M_MECHTAB
+TT$M_WRAP
+TT$M_SCOPE,
[33*TTab$K_Size+3] = 0
+TT2$M_ANSICRT
+TT2$M_AVO
+TT2$M_EDIT
+TT2$M_DECCRT
+TT2$M_DECCRT2,
[34*TTAB$K_Size+0] = %ASCID'DEC-VT220',
[34*TTab$K_Size+1] = TT$_VT200_Series,
[34*TTab$K_Size+2] = 0
+TT$M_LOWER
+TT$M_MECHTAB
+TT$M_WRAP
+TT$M_SCOPE,
[34*TTab$K_Size+3] = 0
+TT2$M_ANSICRT
+TT2$M_AVO
+TT2$M_EDIT
+TT2$M_DECCRT
+TT2$M_DECCRT2,
[35*TTAB$K_Size+0] = %ASCID'DEC-VT240',
[35*TTab$K_Size+1] = TT$_VT200_Series,
[35*TTab$K_Size+2] = 0
+TT$M_LOWER
+TT$M_MECHTAB
+TT$M_WRAP
+TT$M_SCOPE,
[35*TTab$K_Size+3] = 0
+TT2$M_REGIS
+TT2$M_SIXEL
+TT2$M_ANSICRT
+TT2$M_AVO
+TT2$M_EDIT
+TT2$M_DECCRT
+TT2$M_DECCRT2,
[36*TTAB$K_Size+0] = %ASCID'DEC-VT300',
[36*TTab$K_Size+1] = TT$_VT300_Series,
[36*TTab$K_Size+2] = 0
+TT$M_LOWER
+TT$M_MECHTAB
+TT$M_WRAP
+TT$M_SCOPE,
[36*TTab$K_Size+3] = 0
+TT2$M_PRINTER
+TT2$M_ANSICRT
+TT2$M_AVO
+TT2$M_EDIT
+TT2$M_DECCRT
+TT2$M_DECCRT2
+TT2$M_DECCRT3,
[37*TTAB$K_Size+0] = %ASCID'DEC-VT320',
[37*TTab$K_Size+1] = TT$_VT300_Series,
[37*TTab$K_Size+2] = 0
+TT$M_LOWER
+TT$M_MECHTAB
+TT$M_WRAP
+TT$M_SCOPE,
[37*TTab$K_Size+3] = 0
+TT2$M_PRINTER
+TT2$M_ANSICRT
+TT2$M_AVO
+TT2$M_EDIT
+TT2$M_DECCRT
+TT2$M_DECCRT2
+TT2$M_DECCRT3,
[38*TTAB$K_Size+0] = %ASCID'DEC-VT340',
[38*TTab$K_Size+1] = TT$_VT300_Series,
[38*TTab$K_Size+2] = 0
+TT2$M_REGIS
+TT2$M_SIXEL
+TT$M_LOWER
+TT$M_MECHTAB
+TT$M_WRAP
+TT$M_SCOPE,
[38*TTab$K_Size+3] = 0
+TT2$M_PRINTER
+TT2$M_ANSICRT
+TT2$M_AVO
+TT2$M_EDIT
+TT2$M_DECCRT
+TT2$M_DECCRT2
+TT2$M_DECCRT3,
[39*TTAB$K_Size+0] = %ASCID'DEC-VT400',
[39*TTab$K_Size+1] = TT$_VT400_Series,
[39*TTab$K_Size+2] = 0
+TT$M_LOWER
+TT$M_MECHTAB
+TT$M_WRAP
+TT$M_SCOPE,
[39*TTab$K_Size+3] = 0
+TT2$M_ANSICRT
+TT2$M_AVO
+TT2$M_EDIT
+TT2$M_DECCRT
+TT2$M_DECCRT2
+TT2$M_DECCRT3
+TT2$M_DECCRT4
);
GLOBAL ROUTINE Print (Control_string, P1)=
BEGIN
EXTERNAL ROUTINE
Send_2_Operator;
LOCAL
Out_Buffer : VECTOR[256, BYTE],
Out_Desc : BLOCK[8, BYTE],
Status;
Out_Desc[DSC$B_CLASS] = DSC$K_CLASS_Z;
Out_Desc[DSC$B_DTYPE] = DSC$K_DTYPE_Z;
Out_Desc[DSC$W_LENGTH] = %ALLOCATION (Out_Buffer);
Out_Desc[DSC$A_POINTER] = Out_Buffer;
Status = $FAOL (
CTRSTR = .Control_String,
OUTLEN = Out_Desc[DSC$W_LENGTH],
OUTBUF = Out_Desc,
PRMLST = P1);
IF NOT .Status THEN RETURN .Status;
Send_2_Operator(Out_Desc)
END;
GLOBAL ROUTINE Line_Changed_AST (Parm) : NOVALUE =
!--
! Functional Description:
!
! Called whenever the TW's characteristics are changed by the child proc
!--
BEGIN
EXTERNAL ROUTINE
TVT_SEND_SUBOP;
LOCAL
PTY_Char : $BBLOCK [QCB$K_Size],
io_stats : BLOCK[8,BYTE],
data : initial(1),
RC : LONG;
BIND
TVT = Parm : REF TVT$BLOCK,
Old_Chars = TVT[TVT$TTYDEPEND] : $BBLOCK,
Charistics = PTY_Char [QCB$L_Charistics] : $BBLOCK,
Extend_Char = PTY_Char [QCB$L_EXTEND_CHAR] : $BBLOCK; ! JC
! Make sure the TVT is still valid
IF .TVT[TVT$CANCEL] THEN
RETURN;
RC = $QIOW (
CHAN = .TVT[TVT$PTY_CHN],
FUNC = IO$_SENSEMODE,
IOSB = io_stats,
P1 = PTY_Char,
P2 = QCB$K_Size);
IF NOT .RC THEN
BEGIN
XLOG$FAO(LOG$TELERR
,'!%T Set_LINE_Change_AST: SENSEMODE status=!UL!/',0,.RC);
END
ELSE IF NOT .io_stats[0,0,16,0] THEN
BEGIN
XLOG$FAO(LOG$TELERR
,'!%T Set_LINE_Change_AST: SENSEMODE status=!UL!/'
,0,.io_stats[0,0,16,0]);
END
ELSE
BEGIN
IF .Charistics[TT$V_TTSYNC] NEQ .Old_Chars[TT$V_TTSYNC] THEN
TVT_SEND_SUBOP(.TVT,Telnet$K_Toggle_Flow_Control,
%REF(IF (.Charistics[TT$V_TTSYNC])
THEN Option$K_Tog_Flow_Cntl_ON
ELSE Option$K_Tog_Flow_Cntl_OFF),
1);
Old_Chars = .Charistics;
TVT[TVT$TTYDEPEND2] = .Extend_Char;
END;
RC = $QIOW (
CHAN = .TVT[TVT$PTY_CHN],
FUNC = IO$_SETMODE,
IOSB = io_stats,
P1 = Line_Changed_AST,
P2 = .TVT,
P3 = 0,
P4 = 3);
IF NOT .RC THEN
BEGIN
XLOG$FAO(LOG$TELERR
,'!%T Set_LINE_Change_AST: SETMODE status=!UL!/',0,.RC);
END
ELSE IF NOT .io_stats[0,0,16,0] THEN
BEGIN
XLOG$FAO(LOG$TELERR
,'!%T Set_LINE_Change_AST: SETMODE status=!UL!/'
,0,.io_stats[0,0,16,0]);
END;
END;
GLOBAL ROUTINE IS_CNTRLT_GOOD (TVT) =
!--
! Functional Description:
!
! Returns 1 if process will respond to ^T with status information.
!
! Right now it checks to see if the term is in Pasthru/ALL or TTSYNC
! mode which usually means I'm in EMACS, the only thing I know of
! Also TELNET !!!!!!!
! that eats ^T's.
!--
BEGIN
MAP
TVT : REF TVT$BLOCK;
LOCAL
RC,
io_stats : BLOCK[8,BYTE],
PTY_Char : $BBLOCK [QCB$K_Size],
Status : LONG;
BIND
Charistics = PTY_Char [QCB$L_Charistics] : $BBLOCK,
Extend_Char = PTY_Char [QCB$L_EXTEND_CHAR] : $BBLOCK;
RC = $QIOW (
CHAN = .TVT[TVT$PTY_CHN],
FUNC = IO$_SENSEMODE,
IOSB = io_stats,
P1 = PTY_Char,
P2 = QCB$K_Size);
NOT (
(.Charistics[TT$V_TTSYNC] EQL 0) OR
(.Charistics[TT$V_PASSALL] EQL 1) OR
(.Extend_Char[TT2$V_PASTHRU] EQL 1)
)
END;
GLOBAL ROUTINE Timing_Mark_On(TVT) : NOVALUE =
!--
! Functional Description:
!
! The TM option has been turned on. Turn it right back off.
! In the future we shouldn't respond until we think the process
! has, um, well, processed all of the data before the TM.
!++
BEGIN
MAP
TVT : REF TVT$BLOCK;
BIND
LCLOPTS = TVT[TVT$LCLOPTS] : OPT$LIST;
LCLOPTS[Telnet$K_Timing_Mark,OPT$STATE] = OPT$STATE_OFF;
END;
GLOBAL ROUTINE Set_PTY_Window_Size (TVT, pag, width) : NOVALUE =
!--
! Functional Description:
!
! Set the terminal mode to reflect the new size.
!--
BEGIN
MAP
TVT : REF TVT$BLOCK;
BIND
pty_chan = TVT[TVT$PTY_CHN],
PTY_Char = TVT[TVT$TTY_CHAR] : $BBLOCK,
Charistics = PTY_Char [QCB$L_Charistics] : $BBLOCK,
Extend_Char = PTY_Char [QCB$L_EXTEND_CHAR] : $BBLOCK;
LOCAL
io_stats : $BBLOCK [8],
Status : LONG;
Status = $QIOW (
CHAN = .PTY_CHAN,
FUNC = IO$_SENSEMODE,
IOSB = io_stats,
P1 = PTY_Char,
P2 = QCB$K_Size);
IF NOT .Status THEN
BEGIN
XLOG$FAO(LOG$TELERR
,'!%T Set_PTY_Window_size: SENSEMODE status=!UL!/',0,.status);
END
ELSE IF NOT .io_stats[0,0,16,0] THEN
BEGIN
XLOG$FAO(LOG$TELERR
,'!%T Set_PTY_Window_size: SENSEMODE status=!UL!/'
,0,.io_stats[0,0,16,0]);
END
ELSE
BEGIN
IF .Width GTR 0 THEN
PTY_Char[QCB$W_PAGE_WIDTH] = .width;
IF .Pag GTR -1 THEN
PTY_Char[QCB$B_PAGE_LENGTH] = .pag;
Status = $QIOW (
CHAN = .PTY_Chan,
FUNC = IO$_SETMODE,
IOSB = io_stats,
P1 = PTY_Char,
P2 = QCB$K_Size);
IF NOT .Status THEN
BEGIN
XLOG$FAO(LOG$TELERR
,'!%T Set_PTY_Window_size: SETMODE status=!UL!/',0,.status);
END
ELSE IF NOT .io_stats[0,0,16,0] THEN
BEGIN
XLOG$FAO(LOG$TELERR
,'!%T Set_PTY_Window_size: SETMODE status=!UL!/',
0,.io_stats[0,0,16,0]);
END
END;
SS$_NORMAL
END;
GLOBAL ROUTINE Window_Size_Sub (TVT) : NOVALUE =
!++
! Functional Description:
!
! We've received new window size information.
!--
BEGIN
MAP
TVT : REF TVT$BLOCK;
LOCAL
Width,
Length;
IF .TVT[TVT$SUB_CNT] LSS 4 THEN RETURN;
Width = 255 * CH$RCHAR_A(TVT[TVT$SUB_PTR]);
Width = .Width + CH$RCHAR_A(TVT[TVT$SUB_PTR]);
Length = 255 * CH$RCHAR_A(TVT[TVT$SUB_PTR]);
Length = .Length + CH$RCHAR_A(TVT[TVT$SUB_PTR]);
IF (.Width EQL 0) OR (.Length EQL 0) THEN RETURN(SS$_NORMAL);
Set_PTY_Window_Size(.TVT, .Length, .Width);
SS$_NORMAL
END;
GLOBAL ROUTINE Set_PTY_Term_Type (TVT, type, devdep) : NOVALUE =
!--
! Functional Description:
!
! Set the terminal mode to reflect the new size.
!--
! Rewritten by JC to make it work
!
BEGIN
EXTERNAL ROUTINE
SET_DEVDEP;
MAP
devdep : REF VECTOR[2];
MAP
TVT : REF TVT$BLOCK;
BIND
pty_chan = TVT[TVT$PTY_CHN],
tty_chan = TVT[TVT$TTY_CHN],
PTY_Char = TVT[TVT$TTY_CHAR] : $BBLOCK,
Charistics = PTY_Char [QCB$L_Charistics] : $BBLOCK,
Extend_Char = PTY_Char [QCB$L_EXTEND_CHAR] : $BBLOCK,
LCLOPTS = TVT[TVT$LCLOPTS] : OPT$LIST,
State_Echo = LCLOPTS[Telnet$K_Echo,Opt$State],
State_Binary = LCLOPTS[Telnet$K_Binary,Opt$State],
State_Eightbit = LCLOPTS[Telnet$K_Extended_ASCII,Opt$State];
LOCAL
io_stats : $BBLOCK [8],
Status : LONG;
Status = $QIOW (
CHAN = .PTY_CHAN,
FUNC = IO$_SENSEMODE,
IOSB = io_stats,
P1 = PTY_Char,
P2 = QCB$K_Size);
IF NOT .Status THEN
BEGIN
XLOG$FAO(LOG$TELERR
,'!%T Set_PTY_Term_Type: SENSEMODE status=!UL!/',0,.status);
END
ELSE IF NOT .io_stats[0,0,16,0] THEN
BEGIN
XLOG$FAO(LOG$TELERR
,'!%T Set_PTY_Term_Type: SENSEMODE status=!UL!/'
,0,.io_stats[0,0,16,0]);
END
ELSE
BEGIN
PTY_Char[QCB$B_TYPE] = .type;
!
! Set the new terminal characteristics JC
!
PTY_Char[QCB$L_CHARISTICS] = (.PTY_Char[QCB$L_CHARISTICS] AND
(NOT ( TT$M_LOWER
OR TT$M_EIGHTBIT
OR TT$M_MECHFORM
OR TT$M_MECHTAB
OR TT$M_WRAP
OR TT$M_SCOPE)))
OR .devdep[0];
PTY_Char[QCB$L_EXTEND_CHAR]= (.PTY_Char[QCB$L_EXTEND_CHAR] AND
(NOT ( TT2$M_PRINTER
OR TT2$M_REGIS
OR TT2$M_SIXEL
!!!JC OR TT2$M_PASTHRU
OR TT2$M_ANSICRT
OR TT2$M_BLOCK
OR TT2$M_AVO
OR TT2$M_EDIT
OR TT2$M_DECCRT
OR TT2$M_DECCRT2
OR TT2$M_DECCRT3)))
OR .devdep[1];
Charistics [TT$V_EIGHTBIT] = .State_Binary OR .State_Eightbit;
Status = $QIOW (
CHAN = .PTY_Chan,
FUNC = IO$_SETMODE,
IOSB = io_stats,
P1 = PTY_Char,
P2 = QCB$K_Size);
IF NOT .Status THEN
BEGIN
XLOG$FAO(LOG$TELERR
,'!%T Set_PTY_Term_Type: SETMODE status=!UL!/',
0,.status);
END
ELSE IF NOT .io_stats[0,0,16,0] THEN
BEGIN
XLOG$FAO(LOG$TELERR
,'!%T Set_PTY_Term_Type: SETMODE status=!UL!/',
0,.io_stats[0,0,16,0]);
END;
TVT[TVT$TTSET] = 1; ! Set TTSET flag
SET_DEVDEP(.TVT);
END;
SS$_NORMAL
END;
GLOBAL ROUTINE Terminal_Type_On (TVT) : NOVALUE =
!++
! Functional Description:
!
! We've agreed to talk about terminal types.
!--
BEGIN
EXTERNAL ROUTINE
TVT_SEND_SUBOP;
MAP
TVT : REF TVT$BLOCK;
! Ask for the terminal type.
TVT_SEND_SUBOP(.TVT,Telnet$K_Terminal_Type,
%REF(Option$K_Terminal_Type_Send), 1);
END;
GLOBAL ROUTINE Window_Size_On (TVT) : NOVALUE =
!++
! Functional Description:
!
! We've agreed to talk about terminal types.
!--
! Added by JC
BEGIN
EXTERNAL ROUTINE
TVT_SEND_SUBOP;
MAP
TVT : REF TVT$BLOCK;
! Ask for the terminal type.
TVT_SEND_SUBOP(.TVT,Telnet$K_Window_Size,
%REF(Option$K_Terminal_Type_Send), 1);
END;
ROUTINE Lookup_terminal(Term_Desc, Devdep) =
!++
! Functional Description:
!
! Search the terminal name list to find a string that matches
! term_desc. If none found, return -1,
! Otherwise return(SS$_NORMAL) and set .Type_id = term type number.
!--
BEGIN
MAP
Devdep : REF VECTOR[2],
Term_Desc : REF Block[8,BYTE];
EXTERNAL ROUTINE
STR$UPCASE : BLISS ADDRESSING_MODE(GENERAL),
STR$TRIM : BLISS ADDRESSING_MODE(GENERAL),
STR$MATCH_WILD : BLISS ADDRESSING_MODE(GENERAL),
STR$CASE_BLIND_COMPARE : BLISS ADDRESSING_MODE(GENERAL);
LOCAL
Buffer : VECTOR[32, BYTE],
TYPDSC : BLOCK[8,BYTE],
i,
Status;
!
! Setup buffer to hold input string
!
Buffer[1]='*';
TYPDSC[DSC$W_LENGTH] = %ALLOCATION(Buffer)-2;
TYPDSC[DSC$B_DTYPE] = DSC$K_DTYPE_T;
TYPDSC[DSC$B_CLASS] = DSC$K_CLASS_S;
TYPDSC[DSC$A_POINTER] = Buffer+2;
!
! Get the string and trim off blanks
! Then Make it upper case
!
Status = STR$TRIM(TYPDSC,.Term_Desc,TYPDSC[DSC$W_LENGTH]);
Status = STR$UPCASE(TYPDSC,TYPDSC);
TYPDSC[DSC$A_POINTER] = Buffer+1;
!
! Now add the * to the string for a wild match
!
TYPDSC[DSC$W_LENGTH] = .TYPDSC[DSC$W_LENGTH] +1;
Buffer[0] = .TERM_DESC[DSC$W_LENGTH]+1;
INCR i FROM 1 TO .Term_Table[0] DO
BEGIN
!!! Status = STR$CASE_BLIND_COMPARE(
!
! Make a wild match
!
Status = STR$MATCH_WILD(
.Term_Table[.Term_Table[1]*.i+0],
TYPDSC);
IF (.Status AND 1) EQL 1 THEN
BEGIN
devdep[0] = .Term_Table[.Term_Table[1]*.i+2];
devdep[1] = .Term_Table[.Term_Table[1]*.i+3];
RETURN(.Term_Table[.Term_Table[1]*.i+1]);
END;
END;
-1
END;
GLOBAL ROUTINE Terminal_Type_Sub (TVT) : NOVALUE =
BEGIN
EXTERNAL
LIB$_UNRKEY,
LIB$_AMBKEY;
EXTERNAL ROUTINE
STR$COPY_DX : BLISS ADDRESSING_MODE(GENERAL),
STR$CASE_BLIND_COMPARE : BLISS ADDRESSING_MODE(GENERAL),
TVT_SEND_SUBOP;
MAP
TVT : REF TVT$BLOCK;
BIND
LCLOPTS = TVT[TVT$LCLOPTS] : OPT$LIST,
REMOPTS = TVT[TVT$REMOPTS] : OPT$LIST,
OPTBLK = (
REMOPTS[Telnet$K_Terminal_type,OPT$BASE]) : OPT$BLOCK;
LOCAL
Type_id : INITIAL(%X'FFFF'),
devdep : VECTOR[2],
Status,
OLDTYPDSC : BLOCK[DSC$K_Z_BLN,BYTE],
TYPDSC : BLOCK[DSC$K_Z_BLN,BYTE];
CH$RCHAR_A(TVT[TVT$SUB_PTR]);
TYPDSC[DSC$W_LENGTH] = .TVT[TVT$SUB_CNT] - 1; ! current string
TYPDSC[DSC$A_POINTER] = .TVT[TVT$SUB_PTR];
TYPDSC[DSC$B_DTYPE] = DSC$K_DTYPE_T;
TYPDSC[DSC$B_CLASS] = DSC$K_CLASS_S;
!!! OLDTYPDSC[DSC$W_LENGTH] = %ALLOCATION( TVT[TVT$TERMINAL_TYPE]);
OLDTYPDSC[DSC$W_LENGTH] = 16; ! Saved terminal type
OLDTYPDSC[DSC$A_POINTER] = TVT[TVT$TERMINAL_TYPE];
OLDTYPDSC[DSC$B_DTYPE] = DSC$K_DTYPE_T;
OLDTYPDSC[DSC$B_CLASS] = DSC$K_CLASS_S;
TVT[TVT$SUB_PTR] = TVT[TVT$SUB_BUF];
TVT[TVT$SUB_CNT] = 0;
Type_ID = Lookup_terminal(TYPDSC,devdep); ! Get terminal type
IF .Type_ID GTR 0 THEN ! Is it OK ?
BEGIN
!
! Setup the device dependent bits
!
Set_PTY_Term_Type(.TVT,.type_id,devdep);
END
ELSE IF STR$CASE_BLIND_COMPARE(OLDTYPDSC,TYPDSC) ! Not same ?
AND (.TVT[TVT$KILL_TERMINAL_TYPE] LEQU 6) ! Not 6 tries ?
AND (.Type_ID NEQ 0)
THEN BEGIN
TVT_SEND_SUBOP(.TVT,Telnet$K_Terminal_Type,
%REF(Option$K_Terminal_Type_Send), 1);
!!! OPTBLK[OPT$PREFER] = OPT$DONT_CARE;
END;
TVT[TVT$KILL_TERMINAL_TYPE] = .TVT[TVT$KILL_TERMINAL_TYPE]+1;
Status = STR$COPY_DX(OLDTYPDSC,TYPDSC);
SS$_NORMAL
END;
GLOBAL ROUTINE Set_DEVDEP_DONE(TVT) : NOVALUE =
BEGIN
MAP
TVT : REF TVT$BLOCK;
BIND
tty_chan = TVT[TVT$TTY_CHN];
LOCAL
Status;
XLOG$FAO(LOG$TELNEG,'!%T Set_DEVDEP_Done:!/',0);
if .tty_chan EQL 0 then RETURN(SS$_Normal);
Status = $DASSGN (CHAN = .tty_chan);
IF NOT .Status THEN
XLOG$FAO(LOG$TELERR
,'!%T Set_DEVDEP_Done: DASSGN status=!UL!/',0,.status);
tty_chan = 0;
ss$_normal
END;
GLOBAL ROUTINE Set_DEVDEP(TVT) : NOVALUE =
!--
! Functional Description:
!
! Set the terminal device dependent characteristics
! Added by JC
!--
BEGIN
LOCAL
Telnet_Passall,
Changed,
IO_Stats : BLOCK[8,BYTE],
Unit_Number,
devstr : VECTOR[20,BYTE],
devnam : $BBLOCK[DSC$K_S_BLN] PRESET (
[DSC$W_LENGTH] = %ALLOCATION(devstr),
[DSC$B_DTYPE] = DSC$K_DTYPE_Z,
[DSC$B_CLASS] = DSC$K_CLASS_Z,
[DSC$A_POINTER] = devstr),
ptystr : VECTOR[20,BYTE],
ptynam : $BBLOCK[DSC$K_S_BLN] PRESET (
[DSC$W_LENGTH] = %ALLOCATION(ptystr),
[DSC$B_DTYPE] = DSC$K_DTYPE_Z,
[DSC$B_CLASS] = DSC$K_CLASS_Z,
[DSC$A_POINTER] = ptystr),
Item_List : $ITMLST_DECL (Items = 3),
Status : LONG;
MAP
TVT : REF TVT$BLOCK;
BIND
pty_chan = TVT[TVT$PTY_CHN],
tty_chan = TVT[TVT$TTY_CHN],
PTY_Char = TVT[TVT$TTY_CHAR] : $BBLOCK,
Charistics = PTY_Char [QCB$L_Charistics] : $BBLOCK,
Extend_Char = PTY_Char [QCB$L_EXTEND_CHAR] : $BBLOCK,
LCLOPTS = TVT[TVT$LCLOPTS] : OPT$LIST,
Echo_opt = LCLOPTS[Telnet$K_Echo,OPT$BASE] : OPT$BLOCK,
State_Echo = LCLOPTS[Telnet$K_Echo,Opt$State],
State_Binary = LCLOPTS[Telnet$K_Binary,Opt$State],
State_Eightbit = LCLOPTS[Telnet$K_Extended_ASCII,Opt$State];
!
! If user is not yet setup we must exit to prevent conflicts.
!
IF .TVT[TVT$DO_PID] THEN RETURN(0);
Status = $QIOW (
CHAN = .pty_chan,
FUNC = IO$_SENSEMODE,
IOSB = io_stats,
P1 = PTY_char,
P2 = QCB$K_Size);
IF NOT .Status
THEN BEGIN
XLOG$FAO(LOG$TELERR
,'!%T Set_DEVDEP: SENSEMODE PTY status=!UL!/',0,.status);
END
ELSE IF NOT .io_stats[0,0,16,0]
THEN BEGIN
XLOG$FAO(LOG$TELERR
,'!%T Set_DEVDEP: SENSEMODE PTY status=!UL!/'
,0,.io_stats[0,0,16,0]);
END
ELSE BEGIN
XLOG$FAO(LOG$TELNEG
,'!%T Set_DEVDEP: Before Class=!UB Type=!UB Char:x!XL x!XL Size=!UW !UB!/',0
,.PTY_Char[QCB$B_Class]
,.PTY_Char[QCB$B_Type]
,(.PTY_Char[QCB$L_CHARISTICS] AND %X'FFFFFF')
,.PTY_Char[QCB$L_EXTEND_CHAR]
,.PTY_Char[QCB$W_PAGE_WIDTH]
,.PTY_Char[QCB$B_PAGE_LENGTH]);
Telnet_passall = $TRNLOG(
LOGNAM=%ASCID'TELNET_PASSALL', ! JC
RSLLEN=ptynam[DSC$W_LENGTH], ! JC
RSLBUF=ptynam); ! JC
Changed = 0;
Changed = .TVT[TVT$TTSET];
if .Telnet_Passall EQL 1 THEN
Changed = .Changed OR
(.Charistics [TT$V_PASSALL] XOR .State_Binary);
IF NOT .Echo_OPT[OPT$CURRENT] ! Echo being negotiated ??
THEN BEGIN
Changed = .Changed OR
(.Charistics [TT$V_NOECHO] XOR (NOT .State_Echo));
Charistics [TT$V_NOECHO] = 1 AND (NOT .State_Echo);
END;
XLOG$FAO(LOG$TELNEG
,'!%T Set_DEVDEP: Changed=x!XL!/',0
,.Changed);
If NOT (.Changed OR
(.Charistics[TT$V_EIGHTBIT] XOR
(.State_Binary OR .State_Eightbit)))
THEN RETURN(SS$_NORMAL); ! No changes to be made
Charistics [TT$V_EIGHTBIT] = .State_Binary OR .State_Eightbit;
if .Telnet_Passall EQL 1 THEN
Charistics [TT$V_PASSALL] = .State_Binary;
TVT[TVT$TTYDEPEND] = .PTY_Char[QCB$L_CHARISTICS];
TVT[TVT$TTYDEPEND2] = .PTY_Char[QCB$L_EXTEND_CHAR];
XLOG$FAO(LOG$TELNEG
,'!%T Set_DEVDEP: After Class=!UB Type=!UB Char:x!XL x!XL Size=!UW !UB!/',0
,.PTY_Char[QCB$B_Class]
,.PTY_Char[QCB$B_Type]
,(.PTY_Char[QCB$L_CHARISTICS] AND %X'FFFFFF')
,.PTY_Char[QCB$L_EXTEND_CHAR]
,.PTY_Char[QCB$W_PAGE_WIDTH]
,.PTY_Char[QCB$B_PAGE_LENGTH]);
Status = $QIOW (
CHAN = .pty_chan,
FUNC = IO$_SETMODE,
IOSB = io_stats,
P1 = PTY_char,
P2 = QCB$K_Size);
IF NOT .Status
THEN BEGIN
XLOG$FAO(LOG$TELERR
,'!%T Set_DEVDEP: SETMODE PTY status=!UL!/',0,.status);
END
ELSE IF NOT .io_stats[0,0,16,0]
THEN BEGIN
XLOG$FAO(LOG$TELERR
,'!%T Set_DEVDEP: SETMODE PTY status=!UL!/',
0,.io_stats[0,0,16,0]);
END
END;
TVT[TVT$TTSET] = .Changed;
IF NOT .Changed THEN RETURN(SS$_Normal);
!
! If we changed some vital stuff, change it through front end.
! JC
!
IF .tty_chan NEQ 0 THEN RETURN(SS$_Normal); ! Front end in use ?
!
! We find the correct terminal by:
! 1. Get unit number
! 2. Get Front end device name
! 3. Concatonate name and number
! 4. Then attach to it.
devnam[DSC$A_POINTER] = TVT[TVT$TTY_DEVSTR];
$ITMLST_INIT (ITMLST = Item_List,
(ITMCOD = DVI$_UNIT, BUFADR = Unit_Number));
Status = $GETDVIW (ITMLST = Item_List
,CHAN=.PTY_chan); ! Get unit
!!!JC XLOG$FAO(LOG$TELNEG
!!!JC ,'!%T Set_DEVDEP: Unit_Number=x!XL!/',0
!!!JC ,.Unit_Number);
ptynam[DSC$W_LENGTH] = %ALLOCATION(ptystr);
Status = $TRNLOG(
LOGNAM=%ASCID'INET$PTY_TERM', ! JC
RSLLEN=ptynam[DSC$W_LENGTH], ! JC
RSLBUF=ptynam); ! JC
Status = .Status EQL SS$_NORMAL;
IF .Status THEN
Status = $FAO(%ASCID'_!ASA!UL:',devnam,devnam,ptynam,.Unit_Number);
IF .Status THEN
Status = $GETDVIW (ITMLST = Item_List, DEVNAM = devnam);
!!!JC xlog$fao(LOG$TELNEG
!!!JC ,'!%T Set_DEVDEP: TTY_TERM == "!AS"'
!!!JC ,0,devnam); ! Concatonate
Status = $ASSIGN( DEVNAM=devnam
,CHAN=tty_chan); ! Open new channel
IF NOT .Status ! No channel ?
THEN BEGIN
tty_chan = 0;
XLOG$FAO(LOG$TELERR
,'!%T Set_DEVDEP: ASSIGN status=!UL!/',0,.status);
END
ELSE BEGIN
Status = $QIO (
CHAN = .tty_chan,
FUNC = IO$_SETMODE,
ASTADR = Set_DEVDEP_done,
ASTPRM = .TVT,
P1 = PTY_char,
P2 = QCB$K_Size); ! Set front end
IF NOT .Status
THEN BEGIN
XLOG$FAO(LOG$TELERR
,'!%T Set_DEVDEP: SETMODE TTY status=!UL!/',0,.status);
Status = $DASSGN (CHAN = .tty_chan);
tty_chan = 0;
END;
END;
TVT[TVT$TTSET] = 0; ! True if characteristics changed
!!!JC XLOG$FAO(LOG$TELNEG
!!!JC ,'!%T Set_DEVDEP: tty_chan=!UL!/',0,.tty_chan);
!!!JC XLOG$FAO(LOG$TELNEG
!!!JC ,'!%T Set_DEVDEP: pty_chan=!UL!/',0,.PTY_chan);
SS$_NORMAL
END;
GLOBAL ROUTINE LineMode_Sub (TVT) : NOVALUE =
BEGIN
MAP
TVT : REF TVT$BLOCK;
LOCAL
b1,b2;
! Do we have enough data
IF .TVT[TVT$SUB_CNT] LSS 2 THEN RETURN;
! What kind of sub-option is it?
b1 = CH$RCHAR_A(TVT[TVT$SUB_PTR]);
!++
! What kind of suboption is it?
!--
%( IF .b1 EQL Option$K_LineMode_Mode THEN
Linemode_SubOp_Mode (CH$RCHAR_A(TVT[TVT$SUB_PTR]))
ELSE IF .b1 EQL Option$K_LineMode_SLC THEN
Linemode_SubOp_SLC (.TVT[TVT$SUB_PTR], .TVT[TVT$SUB_CNT]-1)
ELSE
BEGIN
b2 = CH$RCHAR_A(TVT[TVT$SUB_PTR]);
IF .b2 EQL Option$K_LineMode_Forwardmask THEN
Linemode_SubOp_Forwardmask(.b1,
.TVT[TVT$SUB_PTR],.TVT[TVT$SUB_CNT]-2)
END
)%
SS$_NORMAL
END;
%(
ROUTINE Linemode_SubOp_Mode ( Mask ) =
BEGIN
EXTERNAL ROUTINE
Send_TCP_SubOption;
LOCAL
New_Mask : BYTE,
Mode_EDIT,Mode_TRAPSIG,
SubOption_Data : $BBLOCK[2],
SubOption_Desc : $BBLOCK [DSC$K_S_BLN] PRESET (
[DSC$W_LENGTH] = %ALLOCATION(SubOption_Data),
[DSC$B_DTYPE] = DSC$K_DTYPE_T,
[DSC$B_CLASS] = DSC$K_CLASS_D,
[DSC$A_POINTER] = SubOption_Data);
! If the ACK bit is set, don't do anything.
IF .Mask