Skip to content
Snippets Groups Projects
Commit e410a9c2 authored by aiyion.prime's avatar aiyion.prime Committed by Matthias Schiffer
Browse files

gluon-core: implement popen3() in gluon/util.lua

[Matthias Schiffer: simplify close_fds() helper and use in child process]
parent 14236ed8
No related branches found
No related tags found
No related merge requests found
local bit = require 'bit'
local posix_fcntl = require 'posix.fcntl'
local posix_glob = require 'posix.glob'
local posix_syslog = require 'posix.syslog'
local posix_unistd = require 'posix.unistd'
local hash = require 'hash'
local sysconfig = require 'gluon.sysconfig'
local site = require 'gluon.site'
......@@ -193,4 +195,76 @@ function M.log(message, verbose)
posix_syslog.syslog(posix_syslog.LOG_INFO, message)
end
local function close_fds(fds)
for _, fd in pairs(fds) do
posix_unistd.close(fd)
end
end
M.subprocess = {}
M.subprocess.DEVNULL = -1
M.subprocess.PIPE = 1
-- Execute a program found using command PATH search, like the shell.
-- Return the pid, as well as the I/O streams as pipes or nil on error.
function M.subprocess.popen(path, argt, options)
argt = argt or {}
local childfds = {}
local parentfds = {}
local stdiostreams = {stdin = 0, stdout = 1, stderr = 2}
for iostream in pairs(stdiostreams) do
if options[iostream] == M.subprocess.PIPE then
local piper, pipew = posix_unistd.pipe()
if iostream == "stdin" then
childfds[iostream] = piper
parentfds[iostream] = pipew
else
childfds[iostream] = pipew
parentfds[iostream] = piper
end
end
end
-- childfds: r0, w1, w2
-- parentfds: w0, r1, r2
local pid, errmsg, errnum = posix_unistd.fork()
if pid == nil then
close_fds(parentfds)
close_fds(childfds)
return nil, errmsg, errnum
elseif pid == 0 then
local null = -1
if M.contains(options, M.subprocess.DEVNULL) then
-- only open if there's anything to discard
null = posix_fcntl.open('/dev/null', posix_fcntl.O_RDWR)
end
for iostream, fd in pairs(stdiostreams) do
local option = options[iostream]
if option == M.subprocess.DEVNULL then
posix_unistd.dup2(null, fd)
elseif option == M.subprocess.PIPE then
posix_unistd.dup2(childfds[iostream], fd)
end
end
close_fds(childfds)
close_fds(parentfds)
-- close potential null
if null > 2 then
posix_unistd.close(null)
end
posix_unistd.execp(path, argt)
posix_unistd._exit(127)
end
close_fds(childfds)
return pid, parentfds
end
return M
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment