+-+-+-+ Beginning of part 23 +-+-+-+
XAdd`009/Host=LT2006`009/Type=X
XAdd`009/Host=LT2007`009/Type=X
XAdd`009/Host=LT2008`009/Type=X
XAdd`009/Host=LT2009`009/Type=X
XAdd`009/Host=LT2010`009/Type=X
XAdd`009/Host=LT2011`009/Type=X
XAdd`009/Host=LT2012`009/Type=X
XAdd`009/Host=LT2013`009/Type=X
XAdd`009/Host=LATALL`009/Type=X    /Link=ALL
XExit
X$ NoRebuild:
X$!
$ GOSUB UNPACK_FILE

$ FILE_IS = "TCPFINGER.FOR"
$ CHECKSUM_IS = 944478027
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X`009Integer Function TCP_Finger(Host,Comm,Finger_out_routine)
X
Xc  Outgoing finger for EUNICE TCP/IP
Xc  P. Lucas, CMU,  16-OCT-1984
Xc  This code borrows heavily form examples taken from Joe Sventek's primer
Xc`009on how to do this stuff.
Xc
X        include 'INETSYM.INC'
X`009External`009Fing_Nonode, Fing_NoNet
X
X        integer*4 bufsiz, sd,  errlen
X`009integer*4 btrim
X        integer*2 sys$assign, sys$qiow
X        logical*4 inet_gethost
X        character*80 buffer
X`009logical*1 bytbuf(1024)
X`009character*132 tempcom, tempcom1
X`009Character`009Network*20,`009Get_Network*20
X`009character*(*)host,comm
X        integer*2 iosb(4), s
X        logical*4 error
X        integer*2 swab
X        character errbuf*256
X`009external  finger_out_routine
X`009external  Fing_Complete, Fing_Abort
Xc
Xc       FORTRAN equivalent of sockaddr_in
Xc
X        integer*2 i2buf(8)
X        logical*1 l1buf(16)
X`009Character`009Flush /255/
X
X        equivalence (i2buf(1), l1buf(1))
Xc  Default return status
X`009TCP_Finger = %Loc(Fing_Complete)
X`009call inet_lower(host)`009`009!we need lower case host name
X
Xc   must terminate with cr/lf
X`009if (comm(1:6).eq.'FINGER') then
X`009  lll=index(comm,' ')
X`009  if ((lll.ne.0).and.(lll+1.le.len(comm))) then
X`009    tempcom1=comm(lll+1:)
X`009  else
X`009    tempcom1=' '
X`009  endif
X`009else
X`009  tempcom1=comm
X`009endif
X`009lll=btrim(tempcom1)
X`009if(lll.eq.1 .and. tempcom1(1:1) .le. ' ') then
X`009`009tempcom = char(13)//char(10)
X`009else
X`009`009tempcom=tempcom1(1:lll)//char(13)//char(10)
X`009endif
Xc
Xc
Xc       assign channel to device and create socket
Xc
X        s = sys$assign('INET0:', sd,,)
X        if (error(s, 1, errbuf, errlen)) then
X`009`009TCP_Finger = %Loc(Fing_NoNet)`009`009!No TCP available
X`009`009return
X        endif
X        s = sys$qiow(%val(0), %val(sd), %val(IO$_SOCKET), %ref(iosb),
X     1            ,, %val(AF_INET), %val(SOCK_STREAM),,,,)
X        if (error(s, iosb(1), errbuf, errlen)) then
X          call finger_out_routine(errbuf(1:errlen))
X`009  TCP_Finger = %loc(fing_abort)
X`009  return
X        endif
Xc
Xc       fill in destination port and host address.  inet_gethost locates
Xc       the entry for the specified host in the file ETC:HOSTS.
Xc       and returns the internet address in the correct order
Xc
X        i2buf(1) = AF_INET
X        i2buf(2) = swab(79)
X        if (.not. inet_gethost(host(1:btrim(host)), l1buf(5))) then
X`009  TCP_Finger = %Loc(Fing_NoNode)
X`009  return
X        endif
Xc
Xc       connect to server
Xc
X        s = sys$qiow(%val(0), %val(sd), %val(IO$_CONNECT), %ref(iosb),
X     1            ,, %ref(l1buf), %val(16),,,,)
X        if (error(s, iosb(1), errbuf, errlen)) then
X`009  Call Finger_Out_Routine
X     1`009`009(': link failed]'// char(13)//char(10))
X          call finger_out_routine(errbuf(1:errlen))
X`009  TCP_Finger = %loc(fing_abort)
X`009  return
X        endif
Xc  Get network name
X`009Network = Get_Network('T')
X`009if (network .eq. '?')network = 'ARPA'`009!default to arpa
Xc  Finish message
X`009Call Finger_Out_Routine('.'//Network(:Btrim(Network))//']'
X     1`009`009//char(13)//char(10))
X
Xc
Xc   send the request
X          s = sys$qiow(%val(0), %val(sd), %val(IO$_SEND), %ref(iosb),,,
X     1              %ref(tempcom), %val(btrim(tempcom)),,,,)
X          if (error(s, iosb(1), errbuf, errlen)) then
X            call finger_out_routine(errbuf(1:errlen))
X`009    TCP_Finger = %loc(fing_abort)
X`009    return
X          endif
Xc       read on socket until 0 length read - seems to imply
Xc       that the partner has exited
Xc
X2        s = sys$qiow(%val(0), %val(sd), %val(IO$_RECEIVE), %ref(iosb),
X     1            ,, %ref(bytbuf), %val(1024),,,,)
X        if (error(s, iosb(1), errbuf, errlen)) then
X          call finger_out_routine(errbuf(1:errlen))
X`009  TCP_Finger = %loc(fing_abort)
X`009  return
X        endif
X        if (iosb(2) .eq. 0) goto 222
X`009nl = iosb(2)/80
X`009do ii = 1,nl
X`009`009call bytetostr(bytbuf((ii-1)*80+1),80,buffer)
X`009`009call finger_out_routine(buffer)
X`009enddo
X`009ilen=iosb(2)-nl*80
X`009if(ilen .gt. 0)then
X`009`009call bytetostr(bytbuf(nl*80+1),ilen,buffer)
X`009`009call finger_out_routine(buffer(1:ilen))
X`009endif
X`009goto 2
Xc
X222`009call sys$dassgn(%val(sd))
X`009return
X        end
Xc
Xc
Xc
Xc
Xc   Find host in etc:hosts and return inet address - GETHOST.INC
X
X        logical function inet_gethost(host, adrbuf)
X
X        character*(*) host
X        logical*1 adrbuf(4)
X        integer*4 lun, hostlen, n, i, adrlen, m, j, k
X        integer*4 lib$get_lun, inet_getword
X        character buffer*256, address*40, nicknm*40
X
X        integer*4 i4
X        logical*1 l1
X
X        equivalence (l1,i4)
X
X        if (.not. lib$get_lun(lun)) then
X          inet_gethost = .false.
X          return
X        endif
X        open (unit=lun, file='TWG$ETC:[000000]HOSTS.', type='OLD',`032
X     1     READONLY, err=10)
X        hostlen = len(host)
X1       continue
X        read (lun, 100, end=11) n, buffer
X100     format(q, (a))
X        if (buffer(1:1) .eq. '#') goto 1        ! have a comment
X        i = index(buffer(1:n), '#')
X        if (i .gt. 0) then
X          n = i
X        endif
X        do 4 i = 1, n
X          k = ichar(buffer(i:i))
X          if (k .eq. 9) then
X            buffer(i:i) = ' '           ! replace tabs by blanks
X          endif
X4       continue
X        i = 1
X        adrlen = inet_getword(buffer(1:n), i, address)
X        adrlen = adrlen + 1
X        address(adrlen:adrlen) = '.'
X2       continue
X        m = inet_getword(buffer(1:n), i, nicknm)
X        if (m .le. 0) goto 1
X        if (m .ne. hostlen) goto 2
X        if (nicknm(1:m) .ne. host(1:m)) goto 2
X        close(unit = lun)
X        call lib$free_lun(lun)
X        i = 1
X        do 3 j = 1, 4
X          k = i + index(address(i:adrlen), '.') - 2
X          call ots$cvt_ti_l(address(i:k), i4)
X          adrbuf(j) = l1
X          i = k + 2
X3       continue
X        inet_gethost = .true.
X        return
X11      close (unit = lun)
X10      call lib$free_lun(lun)
X        inet_gethost = .false.
X        return
X        end
X
X
Xc    Swap bytes in short integer - SWAB.INC
X
X        integer*2 function swab(short)
X
X        integer*2 short, result
X        logical*1 bytes(2), temp
X
X        equivalence (result, bytes(1))
X
X        result = short
X        temp = bytes(1)
X        bytes(1) = bytes(2)
X        bytes(2) = temp
X        swab = result
X
X        return
X        end
X
X
X
Xc   Translate error into printable string - ERROR.INC
X
X      logical function error(first, second, errbuf, errlen)
X
X      integer*2 first, second
X      character*(*) errbuf
X      integer*4 errlen
X      integer*2 err
X
X      errlen = 0
X      if (first .and. second) then
X         error = .false.
X         return
X      endif
X      if (.not. first) then
X        err = first
X      else
X        err = second
X      endif
X      if ((err .and. '8000'x) .eq. '8000'x) then
X        call eunice_error(err, errbuf, errlen)
X      else
X        call sys$getmsg(%val(err), %ref(errlen), errbuf, %val(15),)
X      endif
X      error = .true.
X      return
X
X      end
X
Xc   Fetch next word from buffer - GETWORD.INC
X
X      integer*4 function inet_getword(buf, i, out)
X
X      character*(*) buf, out
X      integer*4 i, n, j
X
X      n = len(buf)
X1     continue
X        if (i .gt. n) then
X          goto 2
X        elseif (buf(i:i) .ne. ' ') then
X          goto 2
X        else
X          i = i + 1
X        endif
X        goto 1
X2     continue
X      j = 1
X3     continue
X        if (i .gt. n) then
X          goto 4
X        elseif (buf(i:i) .eq. ' ') then
X          goto 4
X        else
X          out(j:j) = buf(i:i)
X          j = j + 1
X          i = i + 1
X        endif
X        goto 3
X4     continue
X
X      inet_getword = j - 1
X
X      return
X      end
X
X
X
Xc  Translate Eunice error number into printable string - EUNICEERR.INC
X
X      subroutine eunice_error(error, errbuf, errlen)
X
X      integer*2 error
X      character*(*) errbuf, temp*100
X      integer*4 i, errlen
X
X      i = error .and. '7fff'x
X      i = i / 8
X      if (i .le. 0 .or. i .gt. 65) then
X         temp = 'EUNKNOWN, Unknown Eunice error'
X      else
X         goto (1,2,3,4,5,6,7,8,9,10,
X     1         11,12,13,14,15,16,17,18,19,20,
X     2         21,22,23,24,25,26,27,28,29,30,
X     3         31,32,33,34,35,36,37,38,39,40,
X     4         41,42,43,44,45,46,47,48,49,50,
X     5         51,52,53,54,55,56,57,58,59,60,
X     6         61,62,63,64,65), i
X1        temp =`032
X     1   'EPERM, Not owner'
X         goto 100
X2        temp =`032
X     1   'ENOENT, No such file or directory'
X         goto 100
X3        temp =`032
X     1   'ESRCH, No such process'
X         goto 100
X4        temp =`032
X     1   'EINTR, Interrupted system call'
X         goto 100
X5        temp =`032
X     1   'EIO, I/O error'
X         goto 100
X6        temp =`032
X     1   'ENXIO, No such device or address'
X         goto 100
X7        temp =`032
X     1   'E2BIG, Arg list too long'
X         goto 100
X8        temp =`032
X     1   'ENOEXEC, Exec format error'
X         goto 100
X9        temp =`032
X     1   'EBADF, Bad file number'
X         goto 100
X10       temp =`032
X     1   'ECHILD, No children'
X         goto 100
X11       temp =`032
X     1   'EAGAIN, No more processes'
X         goto 100
X12       temp =`032
X     1   'ENOMEM, Not enough core'
X         goto 100
X13       temp =`032
X     1   'EACCES, Permission denied'
X         goto 100
X14       temp =`032
X     1   'EFAULT, Bad address'
X         goto 100
X15       temp =`032
X     1   'ENOTBLK, Block device required'
X         goto 100
X16       temp =`032
X     1   'EBUSY, Mount device busy'
X         goto 100
X17       temp =`032
X     1   'EEXIST, File exists'
X         goto 100
X18       temp =`032
X     1   'EXDEV, Cross-device link'
X         goto 100
X19       temp =`032
X     1   'ENODEV, No such device'
X         goto 100
X20       temp =`032
X     1   'ENOTDIR, Not a directory'
X         goto 100
X21       temp =`032
X     1   'EISDIR, Is a directory'
X         goto 100
X22       temp =`032
X     1   'EINVAL, Invalid argument'
X         goto 100
X23       temp =`032
X     1   'ENFILE, File table overflow'
X         goto 100
X24       temp =`032
X     1   'EMFILE, Too many open files'
X         goto 100
X25       temp =`032
X     1   'ENOTTY, Not a typewriter'
X         goto 100
X26       temp =`032
X     1   'ETXTBSY, Text file busy'
X         goto 100
X27       temp =`032
X     1   'EFBIG, File too large'
X         goto 100
X28       temp =`032
X     1   'ENOSPC, No space left on device'
X         goto 100
X29       temp =`032
X     1   'ESPIPE, Illegal seek'
X         goto 100
X30       temp =`032
X     1   'EROFS, Read-only file system'
X         goto 100
X31       temp =`032
X     1   'EMLINK, Too many links'
X         goto 100
X32       temp =`032
X     1   'EPIPE, Broken pipe'
X         goto 100
X33       temp =`032
X     1   'EDOM, Argument too large'
X         goto 100
X34       temp =`032
X     1   'ERANGE, Result too large'
X         goto 100
X35       temp =`032
X     1   'EWOULDBLOCK, Operation would block'
X         goto 100
X36       temp =`032
X     1   'EINPROGRESS, Operation now in progress'
X         goto 100
X37       temp =`032
X     1   'EALREADY, Operation already in progress'
X         goto 100
X38       temp =`032
X     1   'ENOTSOCK, Socket operation on non-socket'
X         goto 100
X39       temp =`032
X     1   'EDESTADDRREQ, Destination address required'
X         goto 100
X40       temp =`032
X     1   'EMSGSIZE, Message too long'
X         goto 100
X41       temp =`032
X     1   'EPROTOTYPE, Protocol wrong type for socket'
X         goto 100
X42       temp =`032
X     1   'ENOPROTOOPT, Protocol not available'
X         goto 100
X43       temp =`032
X     1   'EPROTONOSUPPORT, Protocol not supported'
X         goto 100
X44       temp =`032
X     1   'ESOCKTNOSUPPORT, Socket type not supported'
X         goto 100
X45       temp =`032
X     1   'EOPNOTSUPP, Operation not supported on socket'
X         goto 100
X46       temp =`032
X     1   'EPFNOSUPPORT, Protocol family not supported'
X         goto 100
X47       temp =`032
X     1   'EAFNOSUPPORT, Address family not supported by protocol family'
X         goto 100
X48       temp =`032
X     1   'EADDRINUSE, Address already in use'
X         goto 100
X49       temp =`032
X     1   'EADDRNOTAVAIL, Cannot assign requested address'
X         goto 100
X50       temp =`032
X     1   'ENETDOWN, Network is down'
X         goto 100
X51       temp =`032
X     1   'ENETUNREACH, Network is unreachable'
X         goto 100
X52       temp =`032
X     1   'ENETRESET, Network dropped connection on reset'
X         goto 100
X53       temp =`032
X     1   'ECONNABORTED, Software caused connection abort'
X         goto 100
X54       temp =`032
X     1   'ECONNRESET, Connection reset by peer'
X         goto 100
X55       temp =`032
X     1   'ENOBUFS, No buffer space available'
X         goto 100
X56       temp =`032
X     1   'EISCONN, Socket is already connected'
X         goto 100
X57       temp =`032
X     1   'ENOTCONN, Socket is not connected'
X         goto 100
X58       temp =`032
X     1   'ESHUTDOWN, Cannot send after socket shutdown'
X         goto 100
X59       temp =`032
X     1   'ETOOMANYREFS, Too many references: cannot splice'
X         goto 100
X60       temp =`032
X     1   'ETIMEDOUT, Connection timed out'
X         goto 100
X61       temp =`032
X     1   'ECONNREFUSED, Connection refused'
X         goto 100
X62       temp =`032
X     1   'ELOOP, Too many levels of symbolic links'
X         goto 100
X63       temp =`032
X     1   'ENAMETOOLONG, File name too long'
X         goto 100
X64       temp =`032
X     1   'EHOSTDOWN, Host is down'
X         goto 100
X65       temp =`032
X     1   'EHOSTUNREACH, No route to host'
X         goto 100
X      endif
X100   continue
X      errbuf = 'Eunice-E-' // temp
X      errlen = len(errbuf)
X      do while (errlen .gt. 0)
X         if (errbuf(errlen:errlen) .ne. ' ') then
X            goto 101
X         endif
X         errlen = errlen - 1
X      enddo
X101   continue
X
X      return
X      end
Xc  Fold character string to lower case - LOWER.INC
X
X        subroutine inet_lower(buf)
X
X        character*(*) buf
X        integer n, i, biga, bigz, diff, x
X
X        n = len(buf)
X        i = 1
X        biga = ichar('A')
X        bigz = ichar('Z')
X        diff = ichar('a') - biga
X        do while (i .le. n)
X          x = ichar(buf(i:i))
X          if (x .ge. biga .and. x .le. bigz) then
X            buf(i:i) = char(x+diff)
X          endif
X          i = i + 1
X        enddo
X
X        return
X        end
X`009subroutine bytetostr (bytary, max,string)
X`009byte bytary(max)
X`009integer max
X`009character*(*) string
X`009i = 1
X`009do while (i .le. max .and. bytary(i) .ne. 0)
-+-+-+-+-+ End of part 23 +-+-+-+-+-
