define (efn=1) define (sy=2) define (rem=3) define (error=4) define (null=0) # "0 ^@ define (soh=1) # "1 ^A define (stx=2) # "2 ^B define (eot=4) # "4 ^D define (enq=5) # "5 ^E define (ack=6) # "6 ^F define (bel=7) # "7 ^G define (bs=8) # "10 ^H define (lf=10) # "12 ^J define (cr=13) # "15 ^M define (so=14) # "16 ^N define (dle=16) # "20 ^P define (dc4=20) # "24 ^T define (syn=22) # "26 ^V define (space=32) # "40 = ' ' define (zero=48) # "60 = '0' define (nine=57) # "71 = '9' define (colon=58) # "72 = ':' define (slash=47) # "57 = '/' define (oct040=32) # "40 define (oct077=63) # "77 define (oct100=64) # "100 define (oct137=95) # "137 define (oct177=127) # "177 define (oct200=128) # "200 define (oct237=159) # "237 define (oct377=255) # "377 define (oct400=256) # "400 define (transmissionlength=255) define (responselength=10) define (maxrecordsize=512) define (numeric=testn) define (linsiz=40) define (translength=trlen) define (fnamelengthhigh=fnhigh) define (fnamelengthlow=fnlow) define (recordlengthhigh=rchigh) define (recordlengthlow=rclow) define (recordlength=rclen) define (encodelength=codlen) define (decodelength=lencod) define (ttwlbf=256) # io.wlb, "400 define (ttrnef=528) # io.rne, "1020 # XMT - mainline section of the transmit program, Cadnet V. 3.0 # # This program will transmit files with fixed or variable length records # from one rsx system to another. It uses any terminal in the device # table which it can attach to, and is connected to the remote PDP-11 # running 'RECEIV', Cadnet V 3.0 . # program xmt byte record (maxrecordsize), out (28), in (28) byte oswt (10), iswt (10) logical*1 numeric # a function logical*1 image integer*2 iarray (18) byte tsknam (6) common /task/ tsknam integer*2 rsplen byte respon (responselength), transm (responselength) data idot /3r.../ data image /.false./ # Retrieve the task name and save it for use in error messages. call gettsk (iarray, ids) # get task name in radix 50 if (iarray (1) == idot) iarray (1) = 0 # eliminate leading '...' if (iarray (2) == idot) iarray (2) = 0 # trailing '...' call r50asc (6, iarray, tsknam) # convert to ascii do i = 1, 6 # eliminate blanks if (tsknam (i) == space) tsknam (i) = null # Attach the devices used by Cadnet call assign (1, 'TI:') # mcr command line lun call assign (sy, 'SY0:') # output lun call assign (sy) # close the unit call assign (error, 'TI:') # error message lun call ttatt (0, rem, istat) # attach to term if (istat != 0) # attach error { write (error, 2060) tsknam 2060 format (x, 6a1, ' -- Cannot Attach Communication Device.') call exst (4) } # Process command lines until there are no more. repeat { # Retrieve and process command line call getlin (line, len, ids, 'XMT') # retrieve command line call outfil (out, lenout, oswt, nswto) # get output file name call infil (in, lenin, iswt, nswti) # get input file name #type *, 'nswti, iswt', nswti, iswt # Process /im switch, if present if ((nswti > 0) & (iswt (1) == 'I') \ (iswt (2) == 'M')) { # fixed length records image = .true. if (iswt (3) == colon) { # compute the record length (fixed length) i = 4 while (numeric (iswt (i+1))) i = i + 1 decode (i - 3, 9, iswt (4)) nsize #type *, 'i, iswt, nsize', i, iswt, nsize if (nsize > maxrecordsize) { # record size too large write (error, 2040) tsknam 2040 format(x,6a1,' -- Record Size Too Large.') next } } else # use default record length nsize = 128 } else # varible length records { image = .false. nsize = 0 } # Open the input file call ope (lenin, in, ids) if (ids < 0) { write (error, 2000) tsknam 2000 format (x, 6a1, ' -- Open failure on input file') call close (sy) next } # Initialize communication with remote. call init (out, lenout, nsize, ids) if (ids < 0) # init error - do next command line next # Send file a record at a time repeat { # read a record from the file, deal with errors call readf (record, reclen, ids) if (ids < 0) # read error on input file { write (rem, 2050) soh # abort communication write (error, 2030) tsknam call close (sy) break } if (ids > 0) { # eof on input file # Terminate communication, do next command record transm (1) = eot call sendln (transm, 1, respon, rsplen) if ((rsplen != 1) \ (respon (1) != eot)) # Communication terminated abruptly write (error, 2020) tsknam break } # write a record from the file, deal with errors call trans (record, reclen, ids) if (ids < 0) break # if failure, do next command line } } %9 format (i ) 2020 format (x, 6a1, ' -- Communication did not end properly. File may be corrupted.') 2030 format (x, 6a1, ' -- Input file open error.') 2050 format (x, 10a1) end # INIT - Initialization routine for Cadnet V 3.0. Transmit the name of the # file to be created on the remote, the length of the filename and the # record length of the file (0 for variable record length). # # Calling Sequence: # call init (fname, len, nsize, ids) # # Where: # fname - name of output file # len - length of fname # nsize - record length for output file (0 => variable length) # ids - status code. = 0 => all ok # < 0 => error # # Note: # The format of an init sequence (transmitted string/response string) is: # # [filename length] [record length] [file name] # [transmission length] # subroutine init (fname, len, nsize, ids) byte fname (28) integer*2 len, nsize, ids integer*2 rsplen, size byte transm (transmissionlength) byte respon (responselength) integer*2 translength integer*2 fnamelengthhigh, fnamelengthlow integer*2 recordlengthhigh, recordlengthlow byte tsknam (6) common /task/ tsknam # Build the init sequence and send it to the remote. call encodelength (len, fnamelengthhigh, fnamelengthlow) call encodelength (nsize, recordlengthhigh, recordlengthlow) transm (1) = ack transm (2) = fnamelengthhigh transm (3) = fnamelengthlow transm (4) = recordlengthhigh transm (5) = recordlengthlow do i = 1, len transm (i+5) = fname (i) # Wait for response from remote, decode it, and check for an illegal response. call sendln (transm, len+5, respon, rsplen) call decodelength (translength, respon (1), respon (2)) if ((rsplen != 2) \ (translength != len + 5)) { # illegal response string: incorrect length write (rem, 2000) soh # send abort character write (error, 2030) tsknam call close (sy) ids = -1 # error status code return } # Legal response ids = 0 # clear status code return 2000 format (x, 100a1) 2030 format (x, 6a1, ' -- Communication initialization error.') end # TRANS - Transmit a record of the file to the remote. Cadnet V. 3.0. # # Calling Sequence: # call trans (record, reclen, ids) # # Where: # record - the record of data to be transmitted # reclen - length of record # ids - status code # # Note: # In the following notes, the string transmitted to the remote is listed # first, followed by the response string sent by the remote back to XMT. # # The format of a data line representing a logical record of length 0 is: # # [transmission length] [logical record length] # # The format of a data line not holding the end of the logical record is: # [data subsequences] # [transmission length] # # The format of a data line holding the end of the logical record is: # [data subsequences] # [transmission length] [logical record length] # subroutine trans (record, reclen, ids) byte record (maxrecordsize) integer*2 reclen, ids byte transm (transmissionlength), respon (responselength) integer*2 char, rsplen integer*2 translength, recordlength byte tsknam (6) common /task/ tsknam # Encode and send the record to the remote. if (reclen == 0) { # zero length logical record # Wait for and decode response string from remote. transm (1) = stx call sendln (transm, 1, respon, rsplen) call decodelength (translength, respon (1), respon (2)) call decodelength (recordlength, respon (3), respon (4)) if ((rsplen != 4) \ (translength != 1) \ (recordlength != reclen)) { # Illegal response from remote. type *, 'translength, recordlength, respon', translength, recordlength, respon ids = -1 write (error, 101) write (rem, 100) soh # send abort character return } } else { # non-zero length logical record i = 1 # i next position in record # Send the record to the remote as data line(s). while (i <= reclen) { # Build the data line to be sent to the remote j = 1 # j next position in transm (transmit line) while (j <= linsiz-1 & i <= reclen) { # Generate the subsequence for record (i) char = record (i) & oct377 if ((char >= null) & (char < space)) { # Control character # Send ' ' transm (j) = enq transm (j + 1) = record (i) \ oct100 j = j + 2 } else if ((char >= space) & (char < oct177)) { # Printing character # Send '' transm (j) = record (i) j = j + 1 } else if (char == oct177) { # Delete character # Send '' transm (j) = dc4 j = j + 1 } else if ((char >= oct200) & (char <= oct237)) { # Negative character (lower values) # Send ' ' transm (j) = bs transm (j + 1) = (record (i) & oct177) \ oct100 j = j + 2 } else if ((char > oct237) & (char < oct377)) { # Negative character (higher values) # Send ' ' transm (j) = bel transm (j + 1) = record (i) & oct177 j = j + 2 } else if (char == oct377) { # Delete character (w/ bit 7 set) # Send '' transm (j) = syn j = j + 1 } else { # Logic error: unrecognized character write (error, 103) record (i) write (rem, 100) soh # send abort character call exst (4) } i = i + 1 } # while (j <= linsiz-1 & i <= reclen) # Send the data line to the remote, check response if (i <= reclen) { # Not end of logical record: append transm (j) = so j = j + 1 call sendln (transm, j-1, respon, rsplen) call decodelength (translength, respon (1), respon (2)) if ((rsplen != 2) \ (translength != j-1)) { # Illegal response from remote. ids = - 1 write (error, 101) write (rem, 100) soh # send abort character return } } else { # End of logical record: append transm (j) = dle j = j + 1 call sendln (transm, j-1, respon, rsplen) call decodelength (translength, respon (1), respon (2)) call decodelength (recordlength, respon (3), respon(4)) if ((rsplen != 4) \ (translength != j-1) \ (recordlength != reclen)) { # Illegal response from remote. ids = -1 write (error, 101) write (rem, 100) soh # send abort character return } } } # while (i <= reclen) } # else clause of if (reclen == 0) return 100 format (x, 251a1) 101 format (' Remote not receiving properly, aborting communication') 103 format (' Unrecognized character in subroutine TRANS:', i5) end # SENDLN - read a data line from the remote computer. # for receive task, CADNET V 3.0 # # Calling Sequence: # call sendln (transm, translength, respon, rsplen) # # Where: # transm - string to be transmitted to the remote # translength - number of characters to be transmitted # respon - string containing all the characters in the response line # rsplen - length of response line. # # subroutine sendln (transm, translength, respon, rsplen) byte transm (transmissionlength) integer*2 translength byte respon (responselength) integer*2 rsplen define (wrtefn=2) define (redefn=3) integer*2 outlen integer*2 redios (2), redpar (6), reddsw integer*2 wrtios (2), wrtpar (6), wrtdsw logical*1 wrtbyt, redbyt equivalence (wrtbyt, wrtios (1)), (redbyt, redios (1)) include [100,3]ttcomm byte tsknam (6) common /task/ tsknam # Prepare for the write and read i/o's transm (translength + 1) = cr outlen = translength + 1 call getadr (iaddr, transm) wrtpar (1) = iaddr wrtpar (2) = outlen wrtpar (3) = 0 call getadr (iaddr, respon) redpar (1) = iaddr redpar (2) = responselength # type *, 'sending ', translength, 'chars:' # type 98, (transm (i), i = 1, translength) # 98 format (20o4) # Issue the write and read call qio (ttwlbf, rem, wrtefn, , wrtios, wrtpar, wrtdsw) call wtqio (ttrnef, rem, redefn, , redios, redpar, reddsw) # Check for errors if (wrtdsw == 1 & reddsw == 1 & wrtbyt == 1 & redbyt == 1) # all ok { rsplen = redios (2) # type 99, rsplen, (respon (i), i = 1, rsplen) # 99 format (' received ', i4, ' chars:', 50o4) if (respon (1) == null) { # strip off from start do i = 1, rsplen-1 respon (i) = respon (i + 1) rsplen = rsplen - 1 } return } else if (wrtdsw != 1 \ reddsw != 1) # directive error { write (error, 1) tsknam write (rem, 3) soh call exst (4) } else if (wrtbyt != 1 \ redbyt != 1) # i/o error { write (error, 2) tsknam write (rem, 3) soh call exst (4) } 1 format (' ', 6a1, ' - Directive error in sendln. Aborting receive task.') 2 format (' ', 6a1, ' - I/O error in sendln. Aborting receive task.') 3 format (x, a1) end # ENCODELENGTH - encode a length (integer, 0 <= length <= 4095) into 2 ASCII # characters. # # Calling Sequence: # call encodelength (i, hibyte, lobyte) # # Where: # i - value to be encoded # hibyte - high-order 2 octal digits of i, plus offset of octal 40. # lobyte - low-order 2 octal digits of i, plus offset of octal 40. # subroutine encodelength (i, hibyte, lobyte) integer*2 i byte hibyte, lobyte byte tsknam (6) common /task/ tsknam # Check for input value out of range if ((i < 0) \ (i > 4095)) { type 1, tsknam, i write (rem, 2) soh # send abort character call exst (4) } # Encode value hibyte = (i / oct100) + oct040 lobyte = (i & oct077) + oct040 1 format (' ', 6a1, ' - Logic error in subroutine ENCODELENGTH. I = ', i10) 2 format (' ', a1) return end # DECODELENGTH - decode a length (integer, 0 <= length <= 4095) from 2 ASCII # characters. # # Calling Sequence: # call decodelength (i, hibyte, lobyte) # # Where: # i - value to be derived from ASCII input # hibyte - high-order 2 octal digits of i, plus offset of octal 40. # lobyte - low-order 2 octal digits of i, plus offset of octal 40. # subroutine decodelength (i, hibyte, lobyte) integer*2 i byte hibyte, lobyte byte tsknam (6) common /task/ tsknam integer*2 j, k # Check for illegal input values if ((hibyte < oct040) \ (hibyte > oct137) \ (lobyte < oct040) \ (lobyte > oct137)) { type 1, tsknam, hibyte, lobyte write (rem, 2) soh # send abort character call exst (4) } # Decode value j = hibyte - oct040 k = lobyte - oct040 i = j * oct100 + k 1 format (' ', 6a1, ' - Logic error in subroutine DECODELENGTH. I = ', 2i10) 2 format (' ', a1) return end