Skip to content

Instantly share code, notes, and snippets.

@rphillips
Last active August 29, 2015 14:18
Show Gist options
  • Save rphillips/32c3b970d357e0885e08 to your computer and use it in GitHub Desktop.
Save rphillips/32c3b970d357e0885e08 to your computer and use it in GitHub Desktop.
Record Terminal
local bit = require('bit')
local ffi = require('ffi')
local S = require('syscall')
ffi.cdef[[
int execl(const char *path, const char *arg0, ...);
int login_tty(int fd);
]]
local STDIN_FILENO = 0
local STDOUT_FILENO = 1
local done = false
local fd = S.open("out.log", "WRONLY,CREAT", "RWU")
local mpty = S.posix_openpt("rdwr,noctty")
mpty:grantpt()
mpty:unlockpt()
local pts_name = mpty:ptsname()
local spty = S.open(pts_name, "rdwr,noctty")
local termios = spty:tcgetattr()
termios:makeraw()
termios.c_lflag = bit.band(termios.lflag, bit.bnot(S.c.LFLAG["ICANON,ISIG,IEXTEN"]))
S.signal('chld', function() done = true end)
local function write_output(mpty, spty)
ffi.C.close(STDIN_FILENO)
local size = 8096
local buffer = S.types.t.buffer(size)
while true do
local rv = S.read(mpty:getfd(), buffer, size)
if rv > 0 then
S.write(STDOUT_FILENO, buffer, rv)
S.write(fd, buffer, rv)
else
break
end
end
mpty:close()
S.close(fd)
end
local function start_shell(mpty, spty)
mpty:close()
ffi.C.login_tty(spty:getfd())
ffi.C.execl('/bin/sh', '-i')
assert(false, 'could not spawn shell')
end
local child = S.fork()
if child < 0 then
assert(false) -- fork failed
elseif child == 0 then
-- child
local subchild = S.fork()
if subchild < 0 then
assert(false) -- fork failed
elseif subchild == 0 then
write_output(mpty, spty)
else
start_shell(mpty, spty)
end
else
local size = 8096
local buffer = S.types.t.buffer(size)
while not done do
local rv = S.read(STDIN_FILENO, buffer, size)
if rv > 0 then
S.write(mpty:getfd(), buffer, rv)
else
break
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment