C
C	VAXNET.FOR
C
C	This program is used to communicate with a remote CPU over
C	an asynchronous interface line.
C
C	Written by R. Lipsett at INTERMETRICS on April 23, 1979
C
C	Rewritten by:
C	Robin Miller at Project Software & Development, Inc. 1981
C
	INCLUDE 'COM.INC'

	EXTERNAL WRITELT, WRITERT, RESET_WORLD
	LOGICAL BACKUP
	INTEGER*4 EXIT_BLOCK(4)
	CHARACTER*50 LOCAL_DEVICE, LOGICAL_DEVICE, REMOTE_DEVICE
C
C	Character strings for questions, help, etc.
C
	CHARACTER*(*) TITLE, INFOQ, INFOH, PORTQ, PORTH, LOGQ, LOGH
	PARAMETER (TITLE = SS//
	1 'VAXNET Version 3.0 -- Asynchronous Communications Program'
	1 //SS)
	PARAMETER (INFOQ = 'Do you want Help information displayed (No) ? ')
	PARAMETER (INFOH = SS//
	1 'This program is used to transfer file(s) between two computers'
	1 //SS//'over an asynchronous communications line.  '
	1 //DS//'Default answers are in parentheses; i.e., (_TTE1:)'
	1 //SS//'Typing the ESCape key displays HELP for a question.'
	1 //SS//'To exit, do one of the following:'
	1 //DS//'1.  If communicating with the remote, type CTRL/Y to'
	1 //SS//'    get to command level.  Then type EXIT or CTRL/Z.'
	1 //DS//'2.  In response to any VAXNET question, type CTRL/Z.'
	1 //DS)
	PARAMETER (PORTQ = 
	1 'Enter the port being used for the remote (_TTE1:): ')
	PARAMETER (PORTH = SS//
	1 'The port used for the remote can be one of the following:'
	1 //DS//'1.  One of the modem ports on the VAX,'
	1 //SS//'                 or'
	1 //SS//'2.  A port patched to another computer in-house.  The'
	1 //SS//'    synchronous null modem patch cable must be used.'
	1 //DS)
	PARAMETER (LOGQ =
	1 'Write the output from the remote to a log file (No) ? ')
	PARAMETER (LOGH = SS//
	1 'The next question requests whether to write the output'
	1 //SS//'from the remote to a log file on the VAX.  If you answer'
	1 //SS//'Yes, the output from the remote will be written to both'
	1 //SS//'the terminal and the log file.'
	1 //DS)
C
C	VAXNET program starts here.
C
	TYPE *, TITLE
C
C	Set the default local read function to Passall/Noecho.
C
	FUNCTION = (IO$_TTYREADALL + IO$M_NOECHO)
C
C	Set up an exit handler.
C
	EXIT_BLOCK(2) = %LOC(RESET_WORLD)
	EXIT_BLOCK(3) = 1
	EXIT_BLOCK(4) = %LOC(LOCAL_STATUS)
	STATUS = SYS$DCLEXH(EXIT_BLOCK)	! Set up exit handler.
	CALL CHECK_STATUS('VAXNET(DCLEXH)',STATUS)
	REMOTE = .FALSE.		! Presume local terminal,
	HANGUP = .FALSE.		!  and no modem hangup.
	LOGFILE = .FALSE.		! Default to no log file.
	DEBUG_MODE = .FALSE.		! Disable debug mode.

	STATUS = SYS$TRNLOG('SYS$INPUT',I,LOCAL_DEVICE,,,)
	CALL CHECK_STATUS('VAXNET(TRNLOG)',STATUS)
C
C	Note in the following that I contains the true length, and remember
C	that TRNLOG puts a stupid 4-byte header on the translations of
C	SYS$INPUT/OUTPUT specifically.
C
	STATUS = SYS$ASSIGN(LOCAL_DEVICE(5:I),LOCAL_CHANNEL,,)
	CALL CHECK_STATUS('VAXNET(TT)',STATUS)
C
C	Ask if Help information wanted.
C
25	CALL PROMPT_USER(INFOQ,LBUFFER,10)
	IF (TERMINATOR .EQ. ESCAPE .OR. LBUFFER(1) .EQ. 'Y') THEN
		CALL WRITE_USER(INFOH)
	ENDIF
C
C	Ask if user wants output from remote to go to log file.
C
50	CALL PROMPT_USER(LOGQ,LBUFFER,10)
	IF (LBUFFER(1) .EQ. '!') GO TO 25
	IF (TERMINATOR .NE. ESCAPE .AND. LBUFFER(1) .NE. 'Y') GO TO 100
	IF (TERMINATOR .EQ. ESCAPE) THEN
		CALL WRITE_USER(LOGH)
		GO TO 50
	ENDIF
	IF (.NOT. LOGFILE) CALL ENABLE_LOGFILE
C
C	Ask for VAXNET remote port.
C
100	CALL PROMPT_USER(PORTQ,%REF(LOGICAL_DEVICE),50)
	IF (LOGICAL_DEVICE(1:1) .EQ. '!') GO TO 50
	IF (TERMINATOR .EQ. ESCAPE) THEN
		CALL WRITE_USER(PORTH)
		GO TO 100
	ENDIF
	IF (LBYTE_COUNT .EQ. 0) THEN
		LOGICAL_DEVICE = '_TTE1:'
		LBYTE_COUNT = LEN(LOGICAL_DEVICE)
	ENDIF
C
C	Assign channel to remote terminal.
C
	STATUS = SYS$ALLOC(LOGICAL_DEVICE(1:LBYTE_COUNT),
	1			SIZE,REMOTE_DEVICE,)
	IF (STATUS .NE. SS$_DEVALRALLOC)
	1	CALL CHECK_STATUS('VAXNET(ALLOC)',STATUS)
	STATUS = SYS$ASSIGN(REMOTE_DEVICE(1:SIZE),REMOTE_CHANNEL,,)
	CALL CHECK_STATUS('VAXNET(ASSIGN)',STATUS)
	CALL SETUP_TERMINALS(BACKUP)	! Set up terminal characteristics.
	IF (BACKUP) THEN
		STATUS = SYS$DASSGN(%VAL(REMOTE_CHANNEL))
		CALL CHECK_STATUS('VAXNET(DASSGN)',STATUS)
		STATUS = SYS$DALLOC(REMOTE_DEVICE(1:SIZE),)
		IF (STATUS .NE. SS$_NOPRIV)
	1		CALL CHECK_STATUS('VAXNET(DALLOC)',STATUS)
		GO TO 100
	ENDIF
C
C	Set process priority and swap mode.
C
C	The following two system services will fail without the PSWAPM
C	privilege for $SETSWM, and the ALTPRI privilege for $SETPRI.
C	On a busy system, VAXNET will need to be installed with these
C	privileges to avoid problems.
C
500	STATUS = SYS$SETSWM(%VAL(1)) 	! No swapping.
	PRIORITY = 7			! Priority of 7.
	STATUS = SYS$SETPRI(,,%VAL(PRIORITY),) ! And go set it.
C
C	Disable Control/C traps.
C
	LOCAL_STATUS = SYS$QIOW(,%VAL(LOCAL_CHANNEL),
	1	%VAL(IO$_SETMODE + IO$M_CTRLCAST),,,,,,,,,)
	CALL CHECK_STATUS('VAXNET(SETMODE)',LOCAL_STATUS)
	XMITTER_BUSY = .FALSE.		! Set transmitter not busy.
	CONTROLC_TYPED = .FALSE.	! No ^C seen yet.
	CALL SET_CONTROLC_AST		! Enable Control/C AST'S
C
C	Main Loop.
C
C	Read from the remote terminal port.
C
1000	REMOTE_STATUS = SYS$QIOW(,%VAL(REMOTE_CHANNEL),
	1	%VAL(IO$_SENSEMODE + IO$M_TYPEAHDCNT),
	1	RIOSB,,,TYPEAHEAD_COUNT,,,,,)
	CALL CHECK_STATUS('VAXNET(SENSEMODE)',REMOTE_STATUS)
	NBYTES = TYPEAHEAD_COUNT(1)	! Get typeahead count.
	IF (NBYTES .EQ. 0) THEN
		NBYTES = 1		! Read one byte.
		GO TO 1050		! Loop till byte count.
	ENDIF
	IF (READ_ONE) GO TO 1050	! Read NBYTES.

	IF (OBYTES .EQ. NBYTES .OR.
	1	NBYTES .GT. TYPEAHEAD_SIZE-10) GO TO 1050
	CALL WAITABIT('00.01')		! Wait 1 clock tick.
	OBYTES = NBYTES			! Save byte count.
	GO TO 1000			! Get typeahead count again.

1050	OBYTES = 0			! Reset for next time.
	RECEIVER_BUSY = .TRUE.		! Show receiver is busy.
	REMOTE_STATUS = SYS$QIO(,%VAL(REMOTE_CHANNEL),
	1	%VAL(IO$_TTYREADALL + IO$M_NOECHO),
	1	RIOSB,WRITELT,,TBUFFER,%VAL(NBYTES),,NOTERM,,)
	CALL CHECK_STATUS('VAXNET(TTYREADALL)',REMOTE_STATUS)

1100	IF (CONTROLC_TYPED) CALL GET_COMMAND ! If ^C, get VAXNET command.
	IF (.NOT. XMITTER_BUSY) GO TO 1200  ! BR if transmitter is done.
	IF (.NOT. RECEIVER_BUSY) GO TO 1000 ! BR if receiver is done.
	STATUS = SYS$HIBER()		! Wait till something happens.
	GO TO 1100

1200	XMITTER_BUSY = .TRUE.		! Show transmitter is busy.
C
C	Read from the local terminal.
C
C	All control characters are sent to the remote except for
C	Control/Y which is used to escape to the VAXNET command
C	question.  The main reason this method was chosen, was
C	to allow control characters and escape sequences to be
C	sent to the remote for various programs (i.e., EDT).
C
	LOCAL_STATUS = SYS$QIO(,%VAL(LOCAL_CHANNEL),
	1	%VAL(FUNCTION),
	1	LIOSB,WRITERT,,LBUFFER,%VAL(1),,NOTERM,,)
	CALL CHECK_STATUS('VAXNET(FUNCTION)',LOCAL_STATUS)
	GO TO 1100
	END
	SUBROUTINE WRITELT
C
C	AST routine to write to local terminal (TT).
C
	INCLUDE 'COM.INC/NOLIST'
	EXTERNAL WAKE_UP

	RECEIVER_BUSY = .FALSE. 	! Set receiver not busy.
	STATUS_CODE = RIOSB(1)		! Get status code.
	NBYTES = RIOSB(2)		! Get the byte count.
	IF (STATUS_CODE .EQ. SS$_ABORT) THEN
		CALL WAKE_UP		! Wakeup the hibernate,
		RETURN			!  and return.
	ENDIF
	CALL CHECK_STATUS('WRITELT',STATUS_CODE)
	IF (.NOT. LOGFILE) GO TO 510
C
C	Copy characters read from remote to receive buffer and
C	write it to disk if full.
C
	DO 100 I = 1,NBYTES
	RINDEX = RINDEX+1
	RBUFFER(RINDEX) = TBUFFER(I) .AND. "177
	IF (RINDEX .EQ. BUFFER_SIZE) THEN
		CALL WRITE_LOGFILE(RBUFFER,RINDEX)
		RINDEX = 0
	ENDIF
100	CONTINUE
C
C	Echo character(s) from remote at local terminal.
C
510	LOCAL_STATUS = SYS$QIO(,%VAL(LOCAL_CHANNEL),
	1	%VAL(IO$_WRITELBLK + IO$M_NOFORMAT),
	1	XIOSB,WAKE_UP,,TBUFFER,%VAL(NBYTES),,,,)
	CALL CHECK_STATUS('WRITELT',LOCAL_STATUS)
	RETURN
	END
	SUBROUTINE WRITERT
C
C	AST routine to write to remote terminal.
C
	INCLUDE 'COM.INC/NOLIST'
	EXTERNAL WAKE_UP

	XMITTER_BUSY = .FALSE.		! Set transmitter not busy.
	STATUS_CODE  = LIOSB(1)		! Get status code.
	IF (STATUS_CODE .EQ. SS$_ABORT) THEN
		CALL WAKE_UP		! Wakeup the hibernate,
		RETURN			!  and return.	
	ENDIF
	CALL CHECK_STATUS('WRITERT',STATUS_CODE)
C
C 	Now that local read does a Read Pass All, we must check for
C	Control/Y in the buffer to escape to VAXNET command prompt.
C
	IF (LBUFFER(1) .EQ. CONTROL_Y) THEN
		CALL WRITE_LOGFILE(RBUFFER,RINDEX) ! Write log file.
		RINDEX = 0		! Initialize index.
		CALL CONTROLC_AST 	! Process like ^C AST.
		RETURN			! And return.
	ENDIF
C
C	If doing local echoing, all incoming characters from the local
C	terminal are stored in RBUFFER so they will be written to the
C	logfile.  This simulates echoing from the remote.
C
	IF (LOCAL_ECHO) THEN
		RINDEX = RINDEX + 1
		RBUFFER(RINDEX) = LBUFFER(1) .AND. "177
		IF (RINDEX .EQ. BUFFER_SIZE) THEN
			CALL WRITE_LOGFILE(RBUFFER,RINDEX)
			RINDEX = 0
		ENDIF
	ENDIF
C
C	Write to remote terminal.
C
100	REMOTE_STATUS = SYS$QIO(,%VAL(REMOTE_CHANNEL),
	1	%VAL(IO$_WRITELBLK + IO$M_NOFORMAT),
	1	XIOSB,WAKE_UP,,LBUFFER,%VAL(1),,,,)
	CALL CHECK_STATUS('WRITERT',REMOTE_STATUS)
	RETURN
	END
	SUBROUTINE GET_COMMAND
C
C	Get VAXNET Command.
C
	INCLUDE 'COM.INC/NOLIST'

	CHARACTER*25 COMMAND
	CHARACTER*(*) VAXNETQ, VAXNETH, BAD_COMMAND
	PARAMETER (VAXNETQ = DS//'Vaxnet> ')
	PARAMETER (VAXNETH = SS//
	1 'Valid Commands are:'
	1 //DS//'  BAUD  - changes the baud rate of the remote port,'
	1 //SS//'  DUMP  - dumps a file to the remote without using SNDRCV,'
	1 //SS//'  EXIT  - exits from VAXNET,'
	1 //SS//'  GET   - transfers a file to the VAX from the remote,'
	1 //SS//'  LOG   - enables output to a log file,'
	1 //SS//'  NOLOG - disables output to the log file,'
	1 //SS//'  SEND  - transfers a file from the VAX to the remote,'
	1 //SS//'  $cmd  - executes a DCL command.'
	1 //DS//'Type the RETURN key to exit from command level.'
	1 //SS)
	PARAMETER (BAD_COMMAND = SS//
	1 '*** Invalid Command ***'//SS//BELL)
C
C	Request VAXNET command.
C
50	CALL PROMPT_USER(VAXNETQ,%REF(COMMAND),LEN(COMMAND))
	IF (TERMINATOR .EQ. ESCAPE) THEN
100		CALL WRITE_USER(VAXNETH)
		GO TO 50
	ENDIF
	IF (LBYTE_COUNT .EQ. 0) GO TO 200
	DUMP_MODE = .FALSE.
C
C	Dispatch to command processing routines.
C
	IF	(COMMAND(1:1) .EQ. 'B') THEN	! Change the baud rate.
		CALL SET_BAUDRATE
	ELSEIF	(COMMAND(1:5) .EQ. 'DEBUG') THEN ! Enable debug mode.
		DEBUG_MODE = .TRUE.
	ELSEIF	(COMMAND(1:1) .EQ. 'D') THEN	! Dumps a file to the remote.
		FLOW = OUT
		DUMP_MODE = .TRUE.
		CALL GETSEND
	ELSEIF	(COMMAND(1:4) .EQ. 'ECHO') THEN ! Enable local echoing.
		FUNCTION = IO$_TTYREADALL
		LOCAL_ECHO = .TRUE.
	ELSEIF	(COMMAND(1:1) .EQ. 'E') THEN	! Exit from Vaxnet.
		CALL FINISH
	ELSEIF	(COMMAND(1:1) .EQ. 'G') THEN	! Get a file from the remote.
		FLOW = IN
		CALL GETSEND
	ELSEIF	(COMMAND(1:1) .EQ. 'H') THEN	! Request for Help.
		GO TO 100
	ELSEIF	(COMMAND(1:1) .EQ. 'L') THEN	! Open a log file.
		CALL ENABLE_LOGFILE
	ELSEIF	(COMMAND(1:1) .EQ. 'N') THEN	! Disable the log file.
		CALL WRITE_LOGFILE(RBUFFER,RINDEX)
		RINDEX = 0
		IF (LOGFILE) CLOSE (UNIT=LOG_UNIT)
		LOGFILE = .FALSE.
	ELSEIF	(COMMAND(1:3) .EQ. 'ONE') THEN	! Enable one character reads.
		READ_ONE = .TRUE.
	ELSEIF	(COMMAND(1:1) .EQ. 'S') THEN	! Send a file to the remote.
		FLOW = OUT
		CALL GETSEND
	ELSEIF	(COMMAND(1:1) .EQ. '$') THEN	! Do a DCL command.
		CALL DO_DCL_COMMAND(COMMAND,LBYTE_COUNT)
		GO TO 50
	ELSE					! Something else (ERROR).
		CALL WRITE_USER(BAD_COMMAND)
		GO TO 100			! Tell user valid commands.
	ENDIF
	GO TO 200

	ENTRY REENABLE
C
C	Reenable everything.
C
200	CALL SET_CONTROLC_AST		! Enable Control/C AST
	CONTROLC_TYPED = .FALSE.	! Turn off GET
	RETURN
	END
	SUBROUTINE CHECK_STATUS(FACILITY_NAME,STATUS_CODE)
C
C	Subroutine to check status from a System Service.
C
C	Inputs:
C		FACILITY_NAME - Subroutine name.
C		STATUS_CODE - Status code.
C
	INCLUDE 'COM.INC/NOLIST'
	CHARACTER*(*) FACILITY_NAME, ERROR_MESSAGE

	PARAMETER (ERROR_MESSAGE = SS//
	1 '*** VAXNET Terminated with ERROR ***'//BELL//SS)
	CHARACTER*80 MESSAGE
	INTEGER*4 STATUS_CODE

	IF (STATUS_CODE .EQ. SS$_NORMAL) RETURN
	IF (LOGFILE) CALL WRITE_LOGFILE(RBUFFER,RINDEX)
C
C	Report error message to the terminal.
C
C	Set flags for GETMSG for:
C		- Include text of message.
C		- Include message identifier.
C		- Include severity indicator.
C		- Do not include facility name.
C
	FLAGS = "7			! Set up flags.
	CALL SYS$GETMSG(%VAL(STATUS_CODE),MSGLEN,MESSAGE,%VAL(FLAGS),)
	CALL WRITE_USER(SS//'%'//FACILITY_NAME//'-'//
	1		MESSAGE(2:MSGLEN)//SS)
	IF (STATUS_CODE .EQ. SS$_HANGUP) RETURN
	CALL WRITE_USER(ERROR_MESSAGE)
	IF (LOGFILE) CLOSE (UNIT=LOG_UNIT)	! Close the logfile.
	CALL SYS$EXIT(%VAL(SS$_NORMAL))		! And exit with status.
	END
	SUBROUTINE SET_CONTROLC_AST
C
C	Routine to enable Control/C AST's.
C
	INCLUDE 'COM.INC/NOLIST'
	EXTERNAL CONTROLC_AST

	LOCAL_STATUS = SYS$QIOW(,%VAL(LOCAL_CHANNEL),
	1	%VAL(IO$_SETMODE + IO$M_CTRLCAST),,,,
	1	CONTROLC_AST,,,,,)
	CALL CHECK_STATUS('SET_CONTROLC_AST',LOCAL_STATUS)
	RETURN
	END
	SUBROUTINE CONTROLC_AST
C
C	Control/C Trap Handler
C
	INCLUDE 'COM.INC/NOLIST'

C
C	Turn off all reads outstanding.
C
	RECEIVER_BUSY = .FALSE.		! Set receiver not busy.
	XMITTER_BUSY = .FALSE.		! Set transmitter not busy.
	LOCAL_STATUS = SYS$CANCEL(%VAL(LOCAL_CHANNEL))
	CALL CHECK_STATUS('CONTROLC_AST(LOCAL)',LOCAL_STATUS)
	REMOTE_STATUS = SYS$CANCEL(%VAL(REMOTE_CHANNEL))
	CALL CHECK_STATUS('CONTROLC_AST(REMOTE)',REMOTE_STATUS)

	IF (IN_A_COMMAND) THEN		! If in a command,
		IN_A_COMMAND = .FALSE.	! Turn off command flag and return.
	ELSE
		CONTROLC_TYPED = .TRUE.	! Show Control/C was typed.
		CALL WAKE_UP		! Wake up hibernate state.
	ENDIF
	RETURN
	END
	SUBROUTINE WAKE_UP
C
C	Subroutine to wake up hibernate state.
C
	IMPLICIT INTEGER*4 (A-Z)

	STATUS = SYS$CANWAK(,)		! Cancel wakeups.
	CALL CHECK_STATUS('WAKE_UP(CANWAK)',STATUS)
	STATUS = SYS$BINTIM('0 00:00:00.01',DELTA)
	CALL CHECK_STATUS('WAKE_UP(BINTIM)',STATUS)
	STATUS = SYS$SCHDWK(,,DELTA,,)	! Schedule wakeup.
	CALL CHECK_STATUS('WAKE_UP(SCHDWK)',STATUS)
	RETURN
	END
	SUBROUTINE RESET_WORLD
C
C	Exit handler.
C
	CALL SYS$SETSWM(%VAL(0)) 	! Reenable swapping.
	CALL SYS$SETPRI(,,%VAL(4),) 	! Lower priority.
	RETURN
	END
	SUBROUTINE ENABLE_LOGFILE
C
C	Character string for questions and log file name.
C
	INCLUDE 'COM.INC/NOLIST'

	CHARACTER*(*) OPENQ, OPENH, LOGQ, LOGH
	CHARACTER*50 LOGNAME
	PARAMETER (OPENQ = 
	1 'The log file is already open, open a new file (Yes) ? ')
	PARAMETER (OPENH = SS//
	1 'Since the log file is already open, you can either create'
	1 //SS//'a new log file by answering Yes, or use the current log'
	1 //SS//'file by typing No.'//DS)
	PARAMETER (LOGQ = 'Enter the name of the log file (VAXNET.LOG): ')
	PARAMETER (LOGH = SS//
	1 'The next question requests the name of the file on the VAX'
	1 //SS//'to write the output from the remote system to.'
	1 //DS)
C
C	See if log file is already open.  If it is, ask if new file desired.
C
	IF (.NOT. LOGFILE) GO TO 200
100	CALL PROMPT_USER(OPENQ,LBUFFER,10)
	IF (LBUFFER(1) .EQ. '!') RETURN
	IF (TERMINATOR .EQ. ESCAPE) THEN
		CALL WRITE_USER(OPENH)
		GO TO 100
	ENDIF
	IF (LBYTE_COUNT .EQ. 0 .OR. LBUFFER(1) .EQ. 'Y') THEN
		CALL WRITE_LOGFILE(RBUFFER,RINDEX)
		RINDEX = 0
		CLOSE (UNIT=LOG_UNIT)
		LOGFILE = .FALSE.
	ELSE
		RETURN
	ENDIF
	
C
C	Ask for log file name.
C
200	CALL PROMPT_USER(LOGQ,%REF(LOGNAME),50)
	IF (LOGNAME(1:1) .EQ. '!') RETURN
	IF (TERMINATOR .EQ. ESCAPE) THEN
		CALL WRITE_USER(LOGH)
		GO TO 200
	ENDIF
	IF (LBYTE_COUNT .EQ. 0) THEN
		LOGNAME = 'VAXNET.LOG'
		LBYTE_COUNT = 10
	ENDIF
	OPEN (UNIT=LOG_UNIT, TYPE='NEW', NAME=LOGNAME(1:LBYTE_COUNT),
	1	FORM='FORMATTED', RECORDTYPE='VARIABLE',
	1	RECORDSIZE=BUFFER_SIZE, CARRIAGECONTROL='NONE',
	1	ORGANIZATION='SEQUENTIAL', BUFFERCOUNT=2)
	LOGFILE = .TRUE.
	RETURN
	END
	SUBROUTINE WRITE_LOGFILE(BUFFER,NBYTES)
C
C	Write the contents of a buffer to the log file.
C
	INCLUDE 'COM.INC/NOLIST'
	LOGICAL*1 BUFFER(1)

	IF (LOGFILE) THEN
		WRITE (2,100) (BUFFER(I),I=1,NBYTES)
100		FORMAT(<NBYTES>A1)
	ENDIF
	RETURN
	END
	SUBROUTINE SETUP_TERMINALS(BACKUP)
C
C	Sets up the terminal characteristics for both the local
C	terminal and the remote terminal.
C
	INCLUDE 'COM.INC/NOLIST'
	INCLUDE 'TTDEF.FOR/NOLIST'
	LOGICAL BACKUP
	INTEGER*4 LOCAL_CHAR(2), REMOTE_CHAR(2)
	INTEGER*4 SET_LOCAL(2), SET_REMOTE(2)
	CHARACTER*10 REMOTE_BAUD, SYSTEM_TYPE
	CHARACTER*(*) BAUDQ, BAUDH, TYPEQ, TYPEH
	PARAMETER (BAUDQ =
	1 'Enter the baud rate for the remote port (9600): ')
	PARAMETER (BAUDH = SS//
	1 'The list of valid baud rates are:'
	1 //DS//'50, 75, 110, 134, 150, 300, 600, 1200, 1800,'
	1 //SS//'2000, 2400, 3600, 4800, 7200, or 9600.'
	1 //DS//'If you are communicating over a modem, the baud rate'
	1 //SS//'will be either 300 or 1200 baud.'
	1 //DS)
	PARAMETER (TYPEQ =
	1 'Enter the system type of the remote (DEC): ')
	PARAMETER (TYPEH = SS//
	1 'This question determines the method used by VAXNET to'
	1 //SS//'communicate with the remote.  The system types are:'
	1 //DS//'  APPLE, DEC, IBM, UNIX, and XXDP.'
	1 //DS)
C
C	Get system type of remote.
C
	BACKUP = .FALSE.
100	CALL PROMPT_USER(TYPEQ,%REF(SYSTEM_TYPE),LEN(SYSTEM_TYPE))
	IF (SYSTEM_TYPE(1:1) .EQ. '!') THEN
		BACKUP = .TRUE.
		RETURN
	ENDIF
	IF (TERMINATOR .EQ. ESCAPE) THEN
125		CALL WRITE_USER(TYPEH)
		GOTO 100
	ENDIF
	IF (LBYTE_COUNT .EQ. 0) SYSTEM_TYPE = 'DEC'
	IF     (SYSTEM_TYPE(1:5) .EQ. 'APPLE') THEN
		READ_ONE = .TRUE.
		LOCAL_ECHO = .FALSE.
	ELSEIF (SYSTEM_TYPE(1:3) .EQ. 'DEC') THEN
		READ_ONE = .FALSE.
		LOCAL_ECHO = .FALSE.
	ELSEIF (SYSTEM_TYPE(1:3) .EQ. 'IBM') THEN
		READ_ONE = .TRUE.
		LOCAL_ECHO = .TRUE.
		FUNCTION = IO$_TTYREADALL
	ELSEIF (SYSTEM_TYPE(1:4) .EQ. 'UNIX') THEN
		READ_ONE = .TRUE.
		LOCAL_ECHO = .FALSE.
	ELSEIF (SYSTEM_TYPE(1:4) .EQ. 'XXDP') THEN
		READ_ONE = .TRUE.
		LOCAL_ECHO = .FALSE.
	ELSE
		GO TO 125
	ENDIF
	GO TO 200

	ENTRY SET_BAUDRATE
C
C	Get and set the baud rate for the remote.
C
200	CALL PROMPT_USER(BAUDQ,%REF(REMOTE_BAUD),LEN(REMOTE_BAUD))
	IF (REMOTE_BAUD(1:1) .EQ. '!') GO TO 100
	IF (TERMINATOR .EQ. ESCAPE) THEN
225		CALL WRITE_USER(BAUDH)
		GOTO 200
	ENDIF
C
C	The HANGUP flag is set according to the baud rate instead of
C	the REMOTE attribute of the terminal since VMS doesn't set the
C	REMOTE characteristic until it detects the carrier signal
C	changing from off to on.  This is OK if the modem connection
C	is made before VAXNET is started but is unacceptable if
C	o  VAXNET is started before modem connection,
C	o  the modem does not assert carrier (we have 1 modem with CD
C	   tyied high which makes the modem look like a LOCAL terminal),
C	o  or if communicating with a local computer (our synchronous
C	   null modem patch cable causes the carrier signal to be asserted).
C
	HANGUP = .TRUE.
	IF (LBYTE_COUNT .EQ. 0) REMOTE_BAUD = '9600'
	IF     (REMOTE_BAUD(1:2) .EQ. '50') THEN
		BAUD_RATE = TT$C_BAUD_50
	ELSEIF (REMOTE_BAUD(1:2) .EQ. '75') THEN
		BAUD_RATE = TT$C_BAUD_75
	ELSEIF (REMOTE_BAUD(1:3) .EQ. '110') THEN
		BAUD_RATE = TT$C_BAUD_110
	ELSEIF (REMOTE_BAUD(1:3) .EQ. '134') THEN
		BAUD_RATE = TT$C_BAUD_134
	ELSEIF (REMOTE_BAUD(1:3) .EQ. '150') THEN
		BAUD_RATE = TT$C_BAUD_150
	ELSEIF (REMOTE_BAUD(1:3) .EQ. '300') THEN
		BAUD_RATE = TT$C_BAUD_300
	ELSEIF (REMOTE_BAUD(1:3) .EQ. '600') THEN
		BAUD_RATE = TT$C_BAUD_600
	ELSEIF (REMOTE_BAUD(1:4) .EQ. '1200') THEN
		BAUD_RATE = TT$C_BAUD_1200
	ELSEIF (REMOTE_BAUD(1:4) .EQ. '1800') THEN
		BAUD_RATE = TT$C_BAUD_1800
	ELSEIF (REMOTE_BAUD(1:4) .EQ. '2000') THEN
		BAUD_RATE = TT$C_BAUD_2000
	ELSEIF (REMOTE_BAUD(1:4) .EQ. '2400') THEN
		BAUD_RATE = TT$C_BAUD_2400
	ELSEIF (REMOTE_BAUD(1:4) .EQ. '3600') THEN
		BAUD_RATE = TT$C_BAUD_3600
	ELSEIF (REMOTE_BAUD(1:4) .EQ. '4800') THEN
		HANGUP = .FALSE.
		BAUD_RATE = TT$C_BAUD_4800
	ELSEIF (REMOTE_BAUD(1:4) .EQ. '7200') THEN
		HANGUP = .FALSE.
		BAUD_RATE = TT$C_BAUD_7200
	ELSEIF (REMOTE_BAUD(1:4) .EQ. '9600') THEN
		HANGUP = .FALSE.
		BAUD_RATE = TT$C_BAUD_9600
	ELSEIF (REMOTE_BAUD(1:5) .EQ. '19200') THEN
		HANGUP = .FALSE.
		BAUD_RATE = TT$C_BAUD_19200
	ELSE
		GO TO 225
	ENDIF
C
C	Get local terminal characteristics.
C
	LOCAL_STATUS = SYS$QIOW(,%VAL(LOCAL_CHANNEL),
	1	%VAL(IO$_SENSEMODE),LIOSB,,,LOCAL_CHAR,,,,,)
	CALL CHECK_STATUS('SETUP_TERMINALS',LOCAL_STATUS)

	SET_LOCAL(1) = LOCAL_CHAR(1)
	SET_LOCAL(2) = LOCAL_CHAR(2)
	CALL LIB$INSV(0,TT$V_HALFDUP,1,SET_LOCAL(2))
C
C	Set local terminal to full duplex.
C
	LOCAL_STATUS = SYS$QIOW(,%VAL(LOCAL_CHANNEL),
	1	%VAL(IO$_SETMODE),LIOSB,,,SET_LOCAL,,,,,)
	CALL CHECK_STATUS('SETUP_TERMINALS',LOCAL_STATUS)
C
C	Get remote terminal characteristics.
C
	REMOTE_STATUS = SYS$QIOW(,%VAL(REMOTE_CHANNEL),
	1	%VAL(IO$_SENSEMODE),RIOSB,,,REMOTE_CHAR,,,,,)
	CALL CHECK_STATUS('SETUP_TERMINALS',REMOTE_STATUS)

	IF ((REMOTE_CHAR(2) .AND. TT$M_REMOTE) .NE. 0)
	1	REMOTE = .TRUE.			! Flag remote.
	SET_REMOTE(1) = REMOTE_CHAR(1)
	SET_REMOTE(2) = REMOTE_CHAR(2)
	SET_CHAR =	TT$M_HOSTSYNC + TT$M_LOWER +
	1		TT$M_MECHFORM + TT$M_MECHTAB +
	1		TT$M_NOBRDCST + TT$M_NOECHO +
	1		TT$M_PASSALL + TT$M_EIGHTBIT +
	1		TT$M_SCOPE + TT$M_TTSYNC

	CALL LIB$INSV(DT$_VT100,8,8,SET_REMOTE(1))
	CALL LIB$INSV(511,16,16,SET_REMOTE(1))
	CALL LIB$INSV(SET_CHAR,0,(TT$V_HALFDUP+1),SET_REMOTE(2))

C
C	Set remote terminal to:
C
C	/VT100, WIDTH=511, PAGE=same,
C	SPEED=(user_specified), CRFILL=0, LFFILL=0, NOPARITY
C	PASSALL, NOECHO, TYPEAHEAD, NOESCAPE, HOSTSYNC, TTYSYNC,
C	LOWERCASE, TAB, NOWRAP, SCOPE, REMOTE, NOHOLDCREEN,
C	EIGHTBIT, NOBROADCAST, NOREADSYNC, FORM, FULLDUP
C
	REMOTE_STATUS = SYS$QIOW(,%VAL(REMOTE_CHANNEL),
	1	%VAL(IO$_SETMODE),RIOSB,,,SET_REMOTE,,%VAL(BAUD_RATE),,,)
	CALL CHECK_STATUS('SETUP_TERMINALS',REMOTE_STATUS)

	RETURN
	END
	SUBROUTINE PROMPT_USER(PROMPT,BUFFER,BUFSIZE)
C
C	Prompt local terminal and wait for response.  The prompt and
C	the response are also written to the log file if open.
C
C	Inputs:
C		PROMPT - Address of character string descriptor.
C		BUFFER - Address to store characters read.
C		BUFSIZE - Maximum number of bytes to read.
C
C	Outputs:
C		LBYTE_COUNT = Number of bytes read.
C		TERMINATOR  = Terminating character.
C		Calls FINISH if Control/Z typed.
C
	INCLUDE 'COM.INC/NOLIST'
	CHARACTER*(*) PROMPT, MESSAGE
	LOGICAL*1 BUFFER(1)

	LENGTH = LEN(PROMPT)
	BUFFER(1) = 0
	CALL WRITE_LOGFILE(%REF(PROMPT),LENGTH)
100	LOCAL_STATUS = SYS$QIOW(,%VAL(LOCAL_CHANNEL),
	1	%VAL(IO$_READPROMPT + IO$M_CVTLOW),
	1	LIOSB,,,BUFFER,%VAL(BUFSIZE),,,
	1	%REF(PROMPT),%VAL(LENGTH))
200	CALL CHECK_STATUS('PROMPT_USER',LOCAL_STATUS)
	LBYTE_COUNT	= LIOSB(2)	! Save the bytecount.
	TERMINATOR	= LIOSB(3)	! Save the terminator.
C
C	Since the VMS terminal driver only echos newline when a
C	carriage return is typed, the following code will echo a
C	newline for all other terminators as well as format the
C	buffer to be written to the log file.
C
	IF (TERMINATOR .EQ. CR) THEN
		BUFFER(LBYTE_COUNT+2) = LF
	ELSE
		BUFFER(LBYTE_COUNT+1) = CR
		BUFFER(LBYTE_COUNT+2) = LF
		TYPE *, NULL
	ENDIF
	CALL WRITE_LOGFILE(BUFFER,(LBYTE_COUNT+2))
	IF (TERMINATOR .EQ. EOF) CALL FINISH
C
C	If the user types either CTRL/C or CTRL/Y, the abort status
C	is returned to make it simple to detect canceled reads.
C
	IF     (LIOSB(1) .EQ. SS$_CONTROLC) THEN
		LIOSB(1) = SS$_ABORT
		IN_A_COMMAND = .FALSE.
	ELSEIF (LIOSB(1) .EQ. SS$_CONTROLY) THEN
		LIOSB(1) = SS$_ABORT
		IN_A_COMMAND = .FALSE.
	ENDIF
	RETURN

	ENTRY WRITE_USER(MESSAGE)
C
C	Write a buffer to the user and the log file if open.
C
	LENGTH = LEN(MESSAGE)
	CALL WRITE_LOGFILE(%REF(MESSAGE),LENGTH)
	LOCAL_STATUS = SYS$QIOW(,%VAL(LOCAL_CHANNEL),
	1	%VAL(IO$_WRITELBLK + IO$M_NOFORMAT),
	1	LIOSB,,,%REF(MESSAGE),%VAL(LENGTH),,,,)
	CALL CHECK_STATUS('WRITE_USER',LOCAL_STATUS)
	RETURN
	END
	SUBROUTINE DO_DCL_COMMAND(BUFFER,NBYTES)
C
C	Subroutine to execute a DCL command.
C
	IMPLICIT INTEGER*4 (A-Z)
	CHARACTER*(*) BUFFER, STOP_MSG
	PARAMETER (STOP_MSG = '$ STOP ''F$PROCESS()')

	STATUS = LIB$EXECUTE_CLI(BUFFER(1:NBYTES),STOP_MSG)
	RETURN
	END
	SUBROUTINE FINISH
C
C	Writes receive buffer to logfile and prints exit message.
C
	INCLUDE 'COM.INC/NOLIST'

	CHARACTER*(*) DONE_MESSAGE, HANGUPQ, HANGUP_MESSAGE
	PARAMETER (DONE_MESSAGE = SS//
	1 '*** Normal VAXNET Termination ***'//SS)
	PARAMETER (HANGUPQ =
	1 'Do you want the modem hung up (No) ? ')
	PARAMETER (HANGUP_MESSAGE = SS//
	1 '*** Don''t forget to hangup the modem !!! ***'
	1 //BELL//SS)

	IF (REMOTE .AND. HANGUP) THEN
100		CALL PROMPT_USER(HANGUPQ,LBUFFER,10)
		IF (TERMINATOR .EQ. ESCAPE) GO TO 100
		IF (LBUFFER(1) .EQ. 'Y')	! Hangup the modem.
	1		REMOTE_STATUS = SYS$QIOW(,%VAL(REMOTE_CHANNEL),
	1				%VAL(IO$_SETMODE + IO$M_HANGUP),
	1				RIOSB,,,,,,,,)
	ELSE
		IF (HANGUP) CALL WRITE_USER(HANGUP_MESSAGE)
	ENDIF
	CALL WRITE_USER(DONE_MESSAGE)		! Type the done message.
	IF (LOGFILE) CLOSE (UNIT=LOG_UNIT)	! Close the logfile.
	CALL SYS$EXIT(%VAL(SS$_NORMAL))		! And exit.
	END
