! rsh program for (interim) Mouse

%option "-NonStandard-NoCheck-NoDiag-NoLine"

%constinteger rsh port = 514

%include "Moose:Mouse.Inc"
%include "INet:INet.Inc"

%include "INet:INetAddrs"

%externalpredicatespec FS lookup(%string(31) what, %integername value)

%constinteger CR = 13, LF = 10

{} %routine print INet address(%integer addr)
{}    write(addr >> 24 & 255, 0);  print symbol('.')
{}    write(addr >> 16 & 255, 0);  print symbol('.')
{}    write(addr >>  8 & 255, 0);  print symbol('.')
{}    write(addr       & 255, 0)
{} %end

%ownrecord(semaphore fm) RX semaphore = 0
%ownrecord(mailbox fm) RX mailbox = 0
%ownrecord(INet user request fm) RX request = 0

%ownrecord(semaphore fm) TX semaphore = 0
%ownrecord(mailbox fm) TX mailbox = 0
%ownrecord(INet user request fm) TX request = 0

%ownrecord(mailbox fm)%name INet mailbox

%owninteger unit = 0
%owninteger key = 0

%routine close
   %record(INet user request fm)%name reply
%end

%routine check(%integer status)
   %return %if status = 0
   newline
   %stop %if status = closing error
   printstring("rsh: ")
   %if closing error <= status <= dud op error %start
      printstring(INet errors(status))
   %else
      write(status, 0)
   %finish
   newline
   %stop %if key = 0;  ! Not connected yet
   TX request_unit = unit
   TX request_key = key
   TX request_code = TCP abort request
   send message(TX request, INet mailbox, nil)
   %stop
%end

%routine connect(%integer peer)
   %recordformat connect fm(%integer ra, rp, lp, mss)
   %record(connect fm) c
   %record(INet user request fm)%name reply
      key = addr(TX request)
      TX request_key = key
      TX request_code = TCP allocate unit request
      send message(TX request, INet mailbox, TX mailbox)
      reply == receive message(TX mailbox)
      check(reply_status)
      unit = reply_unit
      !! printstring("Allocated unit ");  write(unit, 0);  newline
      TX request_unit = unit
      TX request_key = key
      TX request_code = TCP claim priv request
      TX request_buffer == byteinteger(addr(c_lp))
      send message(TX request, INet mailbox, TX mailbox)
      reply == receive message(TX mailbox)
      check(reply_status)
      !! printstring("Allocated port ");  write(c_lp, 0);  newline
      c_ra = peer;  c_rp = rsh port
      c_mss = 480
      TX request_unit = unit
      TX request_key = key
      TX request_code = TCP open request
      TX request_buffer == byteinteger(addr(c))
      TX request_bytes = 16
      send message(TX request, INet mailbox, TX mailbox)
      reply == receive message(TX mailbox)
      check(reply_status)
      !! printstring("Connected");  newline
%end

%routine send info(%string(255) local, remote, command)
   %record(INet user request fm)%name reply
   %string(255) text
      text = to string(0) . local . to string(0) . remote . %c
             to string(0) . command . to string(0)
      TX request_unit = unit
      TX request_key = key
      TX request_code = TCP send request
      TX request_buffer == charno(text, 1)
      TX request_bytes = length(text)
      !! printstring("Text at ");  phex(addr(TX request_bytes));  newline
      send message(TX request, INet mailbox, TX mailbox)
      reply == receive message(TX mailbox)
      check(reply_status)
      !! printstring("Sent connect data");  newline
      !! printstring("Closing out...");  newline
      TX request_unit = unit
      TX request_key = key
      TX request_code = TCP close request
      send message(TX request, INet mailbox, TX mailbox)
      !! printstring("Sent request, awaiting reply");  newline
      reply == receive message(TX mailbox)
      !! printstring("Reply received: ")
      !! printstring(INet errors(reply_status));  newline
%end

%routine loop
   %bytearray RX buffer(1 : 2048)
   %record(INet user request fm)%name reply
   %integer i
      !! printstring("""Looping""");  newline
      RX request_unit = unit
      RX request_key = key
      RX request_timeout = 0
      RX request_code = TCP receive request
      RX request_buffer == RX buffer(1)
      send message(RX request, INet mailbox, RX mailbox)
      %cycle
         ! Data from the other end?
         reply == receive message(RX mailbox)
         check(reply_status)
         print symbol(RX buffer(i)) %for i = 1, 1, reply_bytes
         RX request_unit = unit
         RX request_key = key
         RX request_timeout = 0
         RX request_code = TCP receive request
         RX request_buffer == RX buffer(1)
         send message(RX request, INet mailbox, RX mailbox)
      %repeat
%end 


%begin
   %string(255) target, command
   %integer x
      %if FS lookup(INet mailbox name, x) %start
         INet mailbox == record(x)
      %else
         printstring("No INet mailbox");  newline
         %stop
      %finish
      target = CLI param
      %unless target -> target . (" ") . command %start
         printstring("Target/command unspecified");  newline
         %stop
      %else %if target = ""
         printstring("Target unspecified");  newline
         %stop
      %else %if command = ""
         printstring("Command unspecified");  newline
         %stop
      %finish
      x = INet name to address(target)
      %if x = 0 %start
         printstring(target);  printstring(" unknown")
         newline
         %stop
      %finish
      {} printstring(target);  printstring(" is at ")
      {} print INet address(x);  newline
      setup semaphore(RX semaphore)
      setup mailbox(RX mailbox, RX semaphore)
      setup message(RX request, size of(RX request))
      setup semaphore(TX semaphore)
      setup mailbox(TX mailbox, TX semaphore)
      setup message(TX request, size of(TX request))
      !! printstring("Saved terminal mode: ");  phex(saved terminal mode);  newline
      connect(x)
      send info("gdmr", "gdmr", command)
      loop
%end %of %program
