Trystan_C_C

LAN Remote Shell

Nov 27th, 2012
115
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.90 KB | None | 0 0
  1. local tArgs = { ... } -- Capture arguments inputted at the top level shell.
  2. --[[
  3.         LAN Cable Remote Shell          PaymentOption
  4.                                         Black Wolf Server
  5.                                         27 November 2012
  6.                                        
  7.         This program allows for the connection of one
  8.         computer to another and redirecting terminal
  9.         output to the receving machine. Both the receiving
  10.         machine and transmitting machine will be able
  11.         to provide input to the transmitting machine
  12.         through this program.
  13.        
  14.         Remember, this program will NOT check if the connection is secure
  15.         or the receiver/transmitter is still running this program. It is
  16.         the responisibility of the user to be aware of this information.
  17.         Results of the aforementioned situation are unknown, so be careful.
  18. ]]--
  19.  
  20. --[[
  21. local shellThread = coroutine.create(function() shell.run("rom/programs/shell") end)
  22. coroutine.resume(shellThread)
  23. while true do
  24.         local event = {os.pullEvent()} -- Get an event from the system.
  25.         coroutine.resume(shellThread, unpack(event)) -- Resume the shell using the event that was given.
  26. end
  27. ]]--
  28.  
  29. local connection = {} -- This will be the connection table for the connection that
  30.                       -- is made to this particular computer.
  31. local session = {}    -- This will be the shell session that has been started
  32.                       -- over the starting shell that will capture and
  33.                       -- resend events to the receiving computer.
  34. local lanCable = nil  -- This will be the wrapped lan cable.
  35. local lanCableSide = nil -- This will be the side on which the lan cable exists.
  36. local receiving = false -- Whether or not this particular computer is receiving
  37.                         -- the terminal output or is transmitting it.
  38.  
  39.  
  40.  
  41. -- Parses the arguments passed from the top level shell. The proper useage
  42. -- of the program is printed if the arguments are in some way incorrect.
  43. -- Params : nil
  44. -- Returns: true or false - Depending on whehter or not the arguments were correct.
  45. function processArguments()
  46.         if #tArgs == 2 then
  47.                 if tArgs[1] == "transmit" or tArgs[1] == "receive" then
  48.                         if tArgs[1] == "receive" then
  49.                                 receiving = true
  50.                         end
  51.                        
  52.                         if tonumber(tArgs[2]) then
  53.                                 connection.id = tonumber(tArgs[2])
  54.                                 return true
  55.                         end
  56.                 end
  57.         end
  58.        
  59.         print("Useage: " .. fs.getName(shell.getRunningProgram()) .. " <transmit/receive> <connectionID>")
  60.         return false
  61. end
  62.                        
  63. -- Attempts to locate a lan cable on any side of this particular computer.
  64. -- This function will wrap the lan cable if one is found and return it, along
  65. -- with the side the cable was found on.
  66. -- Params : nil
  67. -- Returns: lanCable, lanCableSide - The wrapped lan cable and the side its on.
  68. function locateAndWrapLanCable()
  69.         local sides = rs.getSides()
  70.         for sideIndex, side in ipairs(sides) do
  71.                 if peripheral.getType(side) == "cable" then
  72.                         return peripheral.wrap(side), side
  73.                 end
  74.         end
  75.        
  76.         -- No lan cable found.
  77.         return nil, nil
  78. end
  79.  
  80. -- Sends an event over the lan cable to the transmitting computer.
  81. -- Params : id, event - The id of the transmitter and the event to be sent in
  82. --                      table format.
  83. -- Returns: nil
  84. function sendEventToTransmitter(id, event)
  85.         lanCable.send(id, textutils.serialize(event))
  86. end
  87.  
  88. -- Waits for a lan message forever, or until the given amount of time has
  89. -- elapsed.
  90. -- Params : time - The amount of time to be waited for, if any.
  91. -- Returns: id, message or nil, nil - The id of the sender of the message, and
  92. --                                    the message sent if any was found.
  93. function receiveOverLan(time)
  94.         -- Set up a listening timeout timer in the case that we
  95.         -- have been provided with a timeout.
  96.         if time then
  97.                 local listenTimeout = os.startTimer(time)
  98.         end
  99.        
  100.         while true do
  101.                 local event, id, message = os.pullEvent()
  102.                
  103.                 if event == "cable_message" then
  104.                         return id, message    
  105.                 elseif event == "timer" and id == listenTimeout then
  106.                         return nil, nil
  107.                 end
  108.         end
  109. end
  110.  
  111. -- Creates a new local shell session in a thread.
  112. -- Params : nil
  113. -- Returns: shellThread
  114. function newShellThread()
  115.         local shellThread = coroutine.create(function() shell.run("rom/programs/shell") end)
  116.         return shellThread
  117. end
  118.  
  119. -- Wraps all of the native terminal functions into new functionst that will
  120. -- transmit themselves over lan to the receiving computer in a serialized table.
  121. -- Params : nil
  122. -- Returns: wrappedTerminal - The new native terminal functions that redirect output.
  123. function wrapNativeTerminalFunctions()
  124.         local oldTerminal = {}
  125.         local wrappedTerminal = {}
  126.        
  127.         local function wrapFunction(functionName)
  128.                 return function( ... )
  129.                         lanCable.send(connection.id, textutils.serialize({functionName = functionName, params = { ... }}))
  130.                         return oldTerminal[functionName]( ... )
  131.                 end
  132.         end
  133.        
  134.         for functionName, functionObject in pairs(term.native) do
  135.                 oldTerminal[functionName] = functionObject
  136.         end
  137.        
  138.         for functionName, functionObject in pairs(term.native) do
  139.                 wrappedTerminal[functionName] = wrapFunction(functionName)
  140.         end
  141.        
  142.         return wrappedTerminal
  143. end
  144.  
  145. -- Transmits information from this particular computer to the receiving computer
  146. -- over lan in a serialized table. Also, this program handles the output on the
  147. -- terminal after the computer has wrapped the native terminal output to be
  148. -- sent over lan.
  149. -- Params : nil
  150. -- Returns: nil
  151. function transmitTerminalOutput()
  152.         -- Wrap all of the native terminal functions into a new table that
  153.         -- will transmit their information to the receiving machine. Then
  154.         -- redirect terminal output through aforementioned table.
  155.         local redirectedTerminal = wrapNativeTerminalFunctions()
  156.         term.redirect(redirectedTerminal)
  157.        
  158.         -- Create a new shell instance and resume it, all the while handling
  159.         -- messages passed from the receiving computer.
  160.         local shellThread = newShellThread()
  161.         coroutine.resume(shellThread)
  162.        
  163.         while true do
  164.                 -- Wait for an event and handle it accordingly. Use a table to
  165.                 -- capture all parameters returned by any event.
  166.                 local event = {os.pullEvent()}
  167.                
  168.                 -- If the event was a cable message, then go ahead and check
  169.                 -- to see if it was from the receiving machine. In the case
  170.                 -- that it is, then handle it like an event.
  171.                 if event[1] == "cable_message" and event[2] == connection.id then
  172.                         event = textutils.unserialize(event[3])
  173.                         -- The message should have been an event table. Swap
  174.                         -- the sent event for the current one and update the
  175.                         -- screen.
  176.                 end
  177.                
  178.                 -- Update the current shell thread with the event that was
  179.                 -- captured this iteration.
  180.                 coroutine.resume(shellThread, unpack(event))
  181.         end
  182. end
  183.  
  184. -- Receives terminal output from the transmitting machine and draws it to the
  185. -- screen. This function also handles local events and redirects them to the
  186. -- transmitting machine. However, rednet events are not redirected, nor are
  187. -- lan cable events to prevent confusion on the transmitter's side.
  188. -- Params : nil
  189. -- Returns: nil
  190. function receiveTerminalOutput()
  191.         -- Runs any function from the transmitting machine from within the
  192.         -- native terminal functions.
  193.         local function runTerminalFunction(functionTable)
  194.                 if term.native[functionTable.functionName] then
  195.                         return term.native[functionTable.functionName](unpack(functionTable.params))
  196.                 end
  197.         end
  198.        
  199.         -- Create a new shell instance and resume it, all the while handling
  200.         -- messages passed from the transmitting computer. Also, send
  201.         -- user interaction events that are passsed.
  202.         local shellThread = newShellThread()
  203.         coroutine.resume(shellThread)
  204.        
  205.         while true do
  206.                 -- Wait for an event and handle it accordingly. Use a table to
  207.                 -- capture all parameters returned by any event.
  208.                 local event = {os.pullEvent()}
  209.                
  210.                 -- Discard rednet events.
  211.                 if event[1] == "rednet_message" then
  212.                         event = {}
  213.                 else
  214.                         -- If the event was a cable message from the transmitting computer,
  215.                         -- then go ahead and attempt to process it as a function call.
  216.                         if event[1] == "cable_message" and event[2] == connection.id then
  217.                                 -- Get the function table from the message by
  218.                                 -- unserializing the message, then execute it.
  219.                                 local functionTable = textutils.unserialize(event[3])
  220.                                 runTerminalFunction(functionTable)
  221.                         -- Any other event can be serialized and sent to the
  222.                         -- transmitting machine.
  223.                         else
  224.                                 lanCable.send(connection.id, textutils.serialize(event))
  225.                         end
  226.                 end
  227.                
  228.                 -- Update the current shell thread with the event that was
  229.                 -- captured this iteration.
  230.                 -- coroutine.resume(shellThread, unpack(event))
  231.         end
  232. end
  233.  
  234. -- Proccess the given arguments to make sure the program has the necessary information
  235. -- to execute properly.
  236. if not processArguments() then
  237.         return
  238. end
  239. -- Attempt to locate and wrap any land cable that can be found.
  240. lanCable, lanCableSide = locateAndWrapLanCable()
  241. if not lanCable or not lanCableSide then
  242.         print("No lan cable found.")
  243.         return
  244. end
  245.  
  246. -- If we are not to be the receiving computer, then begin transmitting terminal
  247. -- output to the receiving computer and listen for events from the receiving computer.
  248. if not receiving then
  249.         transmitTerminalOutput()
  250. else
  251.         receiveTerminalOutput()
  252. end
Advertisement
Add Comment
Please, Sign In to add comment