Orion09

CC-SSH Agent

Mar 24th, 2026 (edited)
19
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.77 KB | None | 0 0
  1. -- ============================================================
  2. -- cct_agent.lua - Network agent for CC:T Remote
  3. --
  4. -- Run this on every computer EXCEPT the gateway.
  5. -- The gateway (running cct_remote daemon) will discover
  6. -- this computer via rednet and proxy commands to it.
  7. --
  8. -- Requirements: a modem on any side (wired or wireless)
  9. -- Usage: cct_agent (or put in startup file)
  10. -- ============================================================
  11.  
  12. local REDNET_PROTOCOL = "cct_remote"
  13.  
  14. -- ── Colour helpers ──────────────────────────────────────────
  15.  
  16. local function colour(c)
  17. if not term.isColour() then return end
  18. term.setTextColour(c)
  19. end
  20. local function reset() colour(colours.white) end
  21. local function printC(c, ...)
  22. colour(c) ; print(...) ; reset()
  23. end
  24.  
  25. -- ── Output capture ──────────────────────────────────────────
  26.  
  27. local function captureOutput(fn)
  28. local lines = {}
  29. local curLine = ""
  30.  
  31. local fakeTerm = {}
  32. for k, v in pairs(term.current()) do fakeTerm[k] = v end
  33.  
  34. fakeTerm.write = function(text)
  35. curLine = curLine .. tostring(text)
  36. end
  37.  
  38. fakeTerm.blit = function(text)
  39. curLine = curLine .. tostring(text)
  40. end
  41.  
  42. fakeTerm.setCursorPos = function(x, y)
  43. if curLine ~= "" then
  44. lines[#lines + 1] = curLine
  45. curLine = ""
  46. end
  47. end
  48.  
  49. fakeTerm.scroll = function()
  50. if curLine ~= "" then
  51. lines[#lines + 1] = curLine
  52. curLine = ""
  53. end
  54. end
  55.  
  56. fakeTerm.clear = function() end
  57. fakeTerm.clearLine = function() end
  58. fakeTerm.setTextColour = function() end
  59. fakeTerm.setTextColor = function() end
  60. fakeTerm.setBackgroundColour = function() end
  61. fakeTerm.setBackgroundColor = function() end
  62.  
  63. local prev = term.redirect(fakeTerm)
  64. local ok, err = pcall(fn)
  65. term.redirect(prev)
  66.  
  67. if curLine ~= "" then lines[#lines + 1] = curLine end
  68.  
  69. return ok, table.concat(lines, "\n"), tostring(err)
  70. end
  71.  
  72. -- ── Modem open ──────────────────────────────────────────────
  73.  
  74. local function openModem()
  75. local sides = { "top","bottom","left","right","front","back" }
  76. for _, side in ipairs(sides) do
  77. if peripheral.getType(side) == "modem" then
  78. rednet.open(side)
  79. return side
  80. end
  81. end
  82. for _, name in ipairs(peripheral.getNames()) do
  83. if peripheral.getType(name) == "modem" then
  84. rednet.open(name)
  85. return name
  86. end
  87. end
  88. return nil
  89. end
  90.  
  91. -- ── Run a command, return ok + output ───────────────────────
  92.  
  93. local function runCommand(code)
  94. local fn = load(code, "remote", "t", _ENV)
  95. if fn then
  96. local ok, out, err = captureOutput(fn)
  97. return ok, ok and (out ~= "" and out or "OK") or err
  98. else
  99. local ok, out, err = captureOutput(function()
  100. if not shell.run(code) then error("shell.run failed") end
  101. end)
  102. return ok, ok and (out ~= "" and out or "OK") or err
  103. end
  104. end
  105.  
  106. -- ── Main ────────────────────────────────────────────────────
  107.  
  108. local modemSide = openModem()
  109. if not modemSide then
  110. printError("No modem found. Attach a modem and restart.")
  111. return
  112. end
  113.  
  114. local myId = os.getComputerID()
  115. local myLabel = os.getComputerLabel() or ("Agent " .. myId)
  116.  
  117. printC(colours.yellow, "=== CC:T Agent ===")
  118. printC(colours.lime, "ID: " .. myId)
  119. printC(colours.lime, "Label: " .. myLabel)
  120. printC(colours.lime, "Modem: " .. modemSide)
  121. printC(colours.yellow, "Waiting for gateway... (Ctrl+T to stop)")
  122.  
  123. -- Announce ourselves so gateways already running pick us up
  124. rednet.broadcast({ type = "hello", label = myLabel }, REDNET_PROTOCOL)
  125.  
  126. while true do
  127. local senderId, msg, protocol = rednet.receive(REDNET_PROTOCOL)
  128.  
  129. if type(msg) ~= "table" then goto continue end
  130.  
  131. -- Gateway is pinging to discover agents
  132. if msg.type == "ping" then
  133. rednet.send(senderId, { type = "pong", label = myLabel }, REDNET_PROTOCOL)
  134. printC(colours.cyan, "Ping from gateway " .. senderId)
  135.  
  136. -- Gateway is sending a command to run
  137. elseif msg.type == "run" and msg.code then
  138. printC(colours.yellow, "CMD from " .. senderId .. ": " .. msg.code)
  139. local ok, data = runCommand(msg.code)
  140.  
  141. rednet.send(senderId, {
  142. type = "response",
  143. msgId = msg.msgId or "",
  144. ok = ok,
  145. data = data,
  146. }, REDNET_PROTOCOL)
  147.  
  148. printC(ok and colours.lime or colours.red,
  149. (ok and "[ok] " or "[err] ") .. data)
  150. end
  151.  
  152. ::continue::
  153. end
Advertisement
Add Comment
Please, Sign In to add comment