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:
C	Robin Miller at Project Software & Development, Inc. 1981
C
	INCLUDE 'COM.INC/LIST'
	INCLUDE 'TTDEF.FOR/NOLIST'

	EXTERNAL RESET_WORLD

	INTEGER*4 EXIT_BLOCK(4)
C
C	Character strings for questions, help, etc.
C
	CHARACTER*(*) INFOQ, LOGQ, DIALUP_MESSAGE
	CHARACTER*32 DUMMY

	PARAMETER (INFOQ = 'Do you want Help information displayed (No) ? ')
	PARAMETER (LOGQ =
	1 'Write the output from the remote to a log file (No) ? ')
	PARAMETER (DIALUP_MESSAGE = SS//
	1 '*** If using a dialup modem, call the remote system now. ***'
	1 //SS)
C
C	VAXNET program starts here.
C
	CALL WRITE_VERSION()
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)
C
C	Allocate some event flags for QIO's.
C
	CALL GET_EFN(LEFN_IN)		! Local input event flag.
	CALL GET_EFN(LEFN_OUT)		! Local output event flag.
	CALL GET_EFN(REFN_IN)		! Remote input event flag.
	CALL GET_EFN(REFN_OUT)		! Remote output event flag.
C
C	Initialize vaerious flags and counts.
C
	MODEM = .FALSE.			! Presume not a modem.
	REMOTE = .FALSE.		! Presume local terminal,
	HANGUP = .TRUE.			! Hangup modem on exit.
	LOGFILE = .FALSE.		! Default to no log file.
	DEBUG_MODE = .FALSE.		! Disable debug output.
	DUMP_MODE = .FALSE.		! Disable dump mode.
	ECHO_DUMP = .TRUE.		! Echo records dumped to remote.
	EXITING = .FALSE.		! We're not exiting yet.
	HIBERNATING = .FALSE.		! Show we're not hibernating.
	EXIT_ON_ERROR = .TRUE.		! Exit on TRNLOG/ASSIGN.
	MODEM_ONLINE = .FALSE.		! Autodial modem is offline.
	NEED_TO_DEAS = .FALSE.		! Don't have remote port yet.
	TIMEOUT_COUNT = 10		! Initialize timeout count.
	TYPEAHEAD_SIZE = 78-38		!	and typeahead size.
	LOCAL_ASTS = 0			! Initialize the local
	REMOTE_ASTS = 0			!  and remote AST counts.
	STARTUP = .TRUE.		! Show we're in startup code.
C
C	In batch mode, we must read and write to a disk file so
C	the normal QIO's can't be used.
C
	CALL GET_JPI()			! Get our job information.
	IF (BATCH_MODE) THEN
		OPEN (UNIT=IN_UNIT, TYPE='UNKNOWN', NAME='SYS$COMMAND',
	1		FORM='FORMATTED', RECORDTYPE='VARIABLE',
	1		RECORDSIZE=IN_SIZE, CARRIAGECONTROL='NONE',
	1		ORGANIZATION='SEQUENTIAL')

	OPEN (UNIT=OUT_UNIT, TYPE='UNKNOWN', NAME='SYS$OUTPUT',
	1		FORM='FORMATTED', RECORDTYPE='VARIABLE',
	1		RECORDSIZE=OUT_SIZE, CARRIAGECONTROL='NONE',
	1		ORGANIZATION='SEQUENTIAL', BUFFERCOUNT=2)

		GO TO 15		! Skip channel assignment.
	ENDIF
C
C	If not in batch mode, translate SYS$COMMAND, and assign a
C	channel for QIO's.
C
	I = 11				! Size of SYS$COMMAND
	LOCAL_DEVICE = 'SYS$COMMAND'
10	STATUS = SYS$TRNLOG(LOCAL_DEVICE(1:I),I,LOCAL_DEVICE,,,)
	IF (STATUS .NE. SS$_NOTRAN) GO TO 10
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.  This header only exists if the
C	first byte starts with an escape character.
C
	LOCAL_SIZE = I			! Copy size of local device.
	IF (LOCAL_DEVICE(1:1) .EQ. CHAR(27)) THEN
		S = 5			! Point past header.
	ELSE
		S = 1			! Use entire string.
	ENDIF
	STATUS = SYS$ASSIGN(LOCAL_DEVICE(S:LOCAL_SIZE),LCHAN_IN,,)
	IF (.NOT. STATUS) THEN
		CALL LIB$SIGNAL(%VAL(STATUS))
		CALL SYS$EXIT(%VAL(STATUS))
	ENDIF
	STATUS = SYS$ASSIGN(LOCAL_DEVICE(S:LOCAL_SIZE),LCHAN_OUT,,)
C
C	Ask if Help information wanted.
C
15	IF (GET_SYMBOL('VAXNET_INTRO',DUMMY,DUMMY_SIZE)) THEN
		GO TO 30
	ENDIF
25	CALL PROMPT_USER(INFOQ,%REF(DUMMY),LEN(DUMMY))
30	IF (WANTS_HELP .OR. DUMMY(1:1) .EQ. 'Y') THEN
		CALL GET_HELP('INTRO')
	ENDIF
C
C	Ask if user wants output from remote to go to log file.
C
	IF (GET_SYMBOL('VAXNET_LOG',DUMMY,DUMMY_SIZE)) THEN
		GO TO 60
	ENDIF
50	CALL PROMPT_USER(LOGQ,%REF(DUMMY),LEN(DUMMY))
	IF (BACKUP) GO TO 25
	IF (WANTS_HELP) THEN
		CALL GET_HELP('LOG')	! Get help on logging.
		GO TO 50
	ENDIF
C
C	Request a VAXNET log file name.
C
60	IF (DUMMY(1:1) .NE. 'Y') GO TO 75
	IF (.NOT. LOGFILE) THEN
		CALL ENABLE_LOGFILE()	! Go enable a logfile.
	ENDIF
C
C	Request the remote system type.
C
75	CALL SETUP_SYSTEM()		! Set up the system type.
	IF (BACKUP) GO TO 50
C
C	Request the interrupt character.
C
85	CALL SETUP_INTERRUPT()		! Set up the interrupt character.
	IF (BACKUP) GO TO 75
C
C	Request the remote port to use.
C
100	CALL GET_PORT()			! Get the remote port.
	IF (BACKUP) GO TO 85
C
C	Request the remote baud rate.
C
125	CALL SETUP_BAUDRATE		! Setup the remote baud rate.
	IF (BACKUP) THEN
		CALL DEAL_PORT()	! Deallocate the remote port.
		GO TO 100		! And request the port again.
	ENDIF
C
C	If the remote port is setup MODEM, get the modem type.
C
200	IF (MODEM) THEN
		CALL GET_MODEM_TYPE()	! Get autodial modem type.
		IF (BACKUP) GO TO 125
	ENDIF
C
C	If using an autodial modem, get phone number.
C
	IF (AUTODIAL) THEN
		CALL GET_PHONE_NUMBER()	! Get the phone number to dial.
		IF (BACKUP) GO TO 200
	ENDIF
C
C	If symbols answered all or some of the questions, display
C	a status report so the user knows what the answers were.
C
	IF (SYMBOL_COUNT .GT. 0) THEN
		CALL SHOW_STATUS()	! Display a status report.
	ENDIF
C
C	Disable Control/C traps.
C
	IF (.NOT. BATCH_MODE) THEN
		LOCAL_STATUS = SYS$QIOW(,%VAL(LCHAN_IN),
	1		%VAL(IO$_SETMODE + IO$M_CTRLCAST),,,,,,,,,)
		CALL CHECK_STATUS('VAXNET(SETMODE)',LOCAL_STATUS)
		CALL REENABLE()		! Enable CTRL/C's.
	ENDIF
C
C	If the user has the PSWAPM privilege, we will disable swapping.
C	Swapping must be disabled if VAXNET is getting hung in hibernate
C	or an MWAIT state if SDA is to examine its process header.
C
	CALL SYS$SETSWM(%VAL(1))	! Disable process swapping.
C
C	If using an autodial modem, dial the phone number.
C
	IF (AUTODIAL) THEN
		CALL DIAL_MODEM()	! Dial the phone number.
	ENDIF
C
C	Special modem code.
C
	IF (CROSS_FILE) THEN
		IF (AUTODIAL) THEN
			IF (MODEM_ONLINE) THEN
				CALL WAIT_CROSSFILE()
			ENDIF
		ELSE
			CALL WAIT_CROSSFILE()
		ENDIF
	ELSEIF (MODEM) THEN
		IF (.NOT. AUTODIAL) THEN
			IF (BAUD_RATE .LE. TT$C_BAUD_1200) THEN
				CALL WRITE_USER(DIALUP_MESSAGE)
			ENDIF
		ENDIF
	ENDIF
C
C	Attempt automatic login.
C
	IF (AUTODIAL .AND. MODEM_ONLINE) THEN
		IF (.NOT. AUTO_LOGIN()) THEN
			IF (BATCH_MODE) CALL FINISH()
		ENDIF	
	ENDIF
	STARTUP = .FALSE.		! Done with startup code.
C
C	If the symbol TYPEAHEAD_SIZE is defined, we'll change the
C	default typeahead size used during remote reads.  This is
C	the value we allow the typeahead buffer to fill to before
C	issuing our read function.
C
	IF (GET_SYMBOL('TYPEAHEAD_SIZE',DUMMY,SIZE)) THEN
		CALL CVT_DTB(DUMMY(1:SIZE),TYPEAHEAD_SIZE)
	ENDIF
C
C	If batch mode, we never enter the interactive loop.
C
	IF (BATCH_MODE) THEN
		IF (AUTODIAL .AND. MODEM_ONLINE) THEN
			CALL GET_COMMAND() ! Get a VAXNET command.
		ENDIF
		CALL FINISH()		! Exit if we return.
	ENDIF

	IF (CONTROLC_TYPED) THEN
		CALL GET_COMMAND()	! Go request a command.
	ENDIF
C
C	Main Loop.
C
C	After the local and remote reads are enabled, all we do is
C	hibernate.  All further processing is done at AST level.
C
C	We get woken up for two reasons.  We get woken up when the
C	user types the interrupt character, and also when a remote
C	read completes.
C
1000	INTERRUPT_TYPED = .FALSE.	! Show interrupt not typed.
	CALL SETUP_LOCAL(.TRUE.)	! Setup local for interactive.
	CALL LOCAL_READ()		! Enable the transmitter.
	CALL REMOTE_READ()		! Enable The receiver.

1100	IF (INTERRUPT_TYPED) THEN
	    CALL SETUP_LOCAL(.FALSE.)	! We're leaving interactive mode.
	    CALL GET_COMMAND()		! Go request a command.
	    GO TO 1000			! Get the reads started again.
	ELSE
	    IF (.NOT. RECEIVER_BUSY) THEN
		CALL REMOTE_READ()	! Startup another remote read.
	    ENDIF
	ENDIF
	HIBERNATING = .TRUE.		! Show we are hibernating.
	STATUS = SYS$HIBER()		! Wait till something happens.
	GO TO 1100			! Go see who woke us up.
	END
