      function CALLFN(s)
*
*
*
*
*
*
*
*
*
      common /callfn/ read.fn
      common /callfn/ write.fn
      common /callfn/ server.handle
      common /callfn/ alarm.handle
      common /callfn/ read.s1a
      common /callfn/ read.s2a
      common /callfn/ read.s2b
      common /callfn/ write.s1a
      common /callfn/ write.s2a
      common /callfn/ write.s2b
      common /callfn/ alarm.s1
      common /callfn/ alarm.s2.0
      common /callfn/ alarm.s2.30

      $include ccall.bp ccall.common
      $catalog local

      if server.handle = 0 then

         open 'PLIP.CTRL' to ctrl.fd else stop 201,'PLIP.CTRL'
         read config from ctrl.fd , 'CONFIG' else stop 202,'CONFIG'
         rpc.addr = ''
         for i = 1 to dcount(config,@am) while rpc.addr = ''
            l = config<i>
            w1 = trim(field(l,'=',1))
            w2 = trim(field(l,'=',2))
            if w1 = 'RPC ADDR' then
               rpc.addr = w2
            end
         next i

         if rpc.addr = '' then
            display 'Cannot find RPC ADDR = line in PLIP.CTRL CONFIG'
            stop
         end

         call sock.connect(rpc.addr,'','',server.handle,err)
         if err <> '' then
            server.handle = 0
            stop 'error connecting to socket server - ' : err
         end

         read.fn  = ccall.getfn2('libc.so.6','read')
         write.fn = ccall.getfn2('libc.so.6','write')
         alarm.fn = ccall.getfn2('libc.so.6','alarm')

         read.s1a = cc$nul4

         read.s2a = CC$FN.PUSHVAL : int2bin(server.handle,4) : ~
                    CC$FN.PUSHOFF : cc$4 :                     ~
                    CC$FN.PUSHVAL

         read.s2b = CC$FN.CALLFN  : read.fn :   ~
                    CC$FN.RTN32   : cc$0 :      ~
                    CC$FN.EXIT

         write.s1a = cc$nul4

         write.s2a = CC$FN.PUSHVAL : int2bin(server.handle,4) : ~
                     CC$FN.PUSHOFF : cc$4 :                     ~
                     CC$FN.PUSHVAL

         write.s2b = CC$FN.CALLFN  : write.fn :  ~
                     CC$FN.RTN32   : cc$0 :      ~
                     CC$FN.EXIT

         alarm.s1  = cc$nul4

         alarm.s2.0  = CC$FN.PUSHVAL : int2bin(0,4) :  ~
                       CC$FN.CALLFN  : alarm.fn :      ~
                       CC$FN.RTN32   : CC$0 :          ~
                       CC$FN.EXIT

         alarm.s2.30 = CC$FN.PUSHVAL : int2bin(30,4) : ~
                       CC$FN.CALLFN  : alarm.fn :      ~
                       CC$FN.RTN32   : CC$0 :          ~
                       CC$FN.EXIT

         buf = ''
         call sock.read(server.handle,8,15000,15000,'',buf,err)
         if err <> '' then
            call csub.close(server.handle,'')
            server.handle = 0
            stop 'error receiving rpc connect string'
         end
      end

      *$*   dummy = ccall(alarm.s1,alarm.s2.30)

      cmd.len = len(s)

      t = oconv(cmd.len,'mcdx') 'r%4'
      send.str = t : t : s

      xx = iconv(cmd.len+8,'IL')

      s1 = write.s1a : send.str
      s2 = write.s2a : xx : write.s2b
      s = ccall(s1,s2)
      if s[1,4] <> xx then
         display 's1 = ' : bin2hex(s1)
         display 's2 = ' : bin2hex(s2)
         res = bin2int(s[1,4])
         call csub.close(server.handle,'')
         server.handle = 0
         display 'error calling csub.write res = ' : res
         stop
      end

      xx = iconv(cmd.len,'IL')

      s1 = read.s1a : str(CC$NUL,cmd.len)
      s2 = read.s2a : xx : read.s2b
      s = ccall(s1,s2)
      if s[1,4] <> xx then
         display 's1 = ' : bin2hex(s1)
         display 's2 = ' : bin2hex(s2)
         res = bin2int(s[1,4])
         call csub.close(server.handle,'')
         server.handle = 0
         display 'error calling csub.read res = ' : res
         stop
      end
      s = s[5,cmd.len]

      *$*   dummy = ccall(alarm.s1,alarm.s2.0)

      return(s)
   end
