gluon-core: implement popen3() in gluon/util.lua
This commit is contained in:
parent
7e45878b4e
commit
95a9188607
@ -1,6 +1,8 @@
|
|||||||
local bit = require 'bit'
|
local bit = require 'bit'
|
||||||
|
local posix_fcntl = require 'posix.fcntl'
|
||||||
local posix_glob = require 'posix.glob'
|
local posix_glob = require 'posix.glob'
|
||||||
local posix_syslog = require 'posix.syslog'
|
local posix_syslog = require 'posix.syslog'
|
||||||
|
local posix_unistd = require 'posix.unistd'
|
||||||
local hash = require 'hash'
|
local hash = require 'hash'
|
||||||
local sysconfig = require 'gluon.sysconfig'
|
local sysconfig = require 'gluon.sysconfig'
|
||||||
local site = require 'gluon.site'
|
local site = require 'gluon.site'
|
||||||
@ -188,4 +190,73 @@ function M.log(message, verbose)
|
|||||||
posix_syslog.syslog(posix_syslog.LOG_INFO, message)
|
posix_syslog.syslog(posix_syslog.LOG_INFO, message)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
M.PipePolicies = {
|
||||||
|
DISCARD=-1,
|
||||||
|
INHERIT=0,
|
||||||
|
CREATE=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.popen3(policies, path, ...)
|
||||||
|
local pipes = {}
|
||||||
|
local intern = {}
|
||||||
|
local extern = {}
|
||||||
|
|
||||||
|
for fd, policy in pairs(policies) do
|
||||||
|
if M.PipePolicies.CREATE==policy then
|
||||||
|
pipes[fd]={posix_unistd.pipe()}
|
||||||
|
if posix_unistd.STDIN_FILENO==fd then
|
||||||
|
intern[fd]=pipes[fd][1]
|
||||||
|
extern[fd]=pipes[fd][2]
|
||||||
|
else
|
||||||
|
intern[fd]=pipes[fd][2]
|
||||||
|
extern[fd]=pipes[fd][1]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- intern: r0, w1, w2
|
||||||
|
-- extern: w0, r1, r2
|
||||||
|
|
||||||
|
local pid = posix_unistd.fork()
|
||||||
|
|
||||||
|
if pid < 0 then
|
||||||
|
return nil
|
||||||
|
elseif pid == 0 then
|
||||||
|
local null=-1;
|
||||||
|
if M.contains(policies, M.PipePolicies.DISCARD) then
|
||||||
|
-- only open, if there's anything to discard
|
||||||
|
null = posix_fcntl.open('/dev/null', posix_fcntl.O_WRONLY)
|
||||||
|
end
|
||||||
|
|
||||||
|
for fd, policy in pairs(policies) do
|
||||||
|
if M.PipePolicies.DISCARD==policy then
|
||||||
|
if posix_unistd.STDIN_FILENO~=fd then
|
||||||
|
posix_unistd.dup2(null, fd)
|
||||||
|
end
|
||||||
|
elseif M.PipePolicies.CREATE==policy then
|
||||||
|
-- only close these, if they exist
|
||||||
|
posix_unistd.close(extern[fd])
|
||||||
|
posix_unistd.dup2(intern[fd], fd)
|
||||||
|
-- close all the dups
|
||||||
|
posix_unistd.close(intern[fd])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- close potential null
|
||||||
|
if null > 2 then
|
||||||
|
posix_unistd.close(null)
|
||||||
|
end
|
||||||
|
|
||||||
|
posix_unistd.execp(path, ...)
|
||||||
|
posix_unistd._exit(127)
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, v in pairs(intern) do
|
||||||
|
posix_unistd.close(v)
|
||||||
|
end
|
||||||
|
|
||||||
|
return pid, extern
|
||||||
|
end
|
||||||
return M
|
return M
|
||||||
|
Loading…
Reference in New Issue
Block a user