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(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