|
Packit |
437b5e |
--[[
|
|
Packit |
437b5e |
POSIX library for Lua 5.1, 5.2 & 5.3.
|
|
Packit |
437b5e |
(c) Gary V. Vaughan <gary@vaughan.pe>, 2013-2015
|
|
Packit |
437b5e |
(c) Reuben Thomas <rrt@sc3d.org> 2010-2015
|
|
Packit |
437b5e |
(c) Natanael Copa <natanael.copa@gmail.com> 2008-2010
|
|
Packit |
437b5e |
]]
|
|
Packit |
437b5e |
--[[--
|
|
Packit |
437b5e |
Lua POSIX bindings.
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
In addition to the convenience functions documented in this module, all
|
|
Packit |
437b5e |
APIs from submodules are copied into the return table for convenience and
|
|
Packit |
437b5e |
backwards compatibility.
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
@module posix
|
|
Packit |
437b5e |
]]
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
local bit = require "bit32"
|
|
Packit |
437b5e |
local M = {}
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
-- For backwards compatibility, copy all table entries into M namespace.
|
|
Packit |
437b5e |
for _, sub in ipairs {
|
|
Packit |
437b5e |
"ctype", "dirent", "errno", "fcntl", "fnmatch", "getopt", "glob", "grp",
|
|
Packit |
437b5e |
"libgen", "poll", "pwd", "sched", "signal", "stdio", "stdlib", "sys.msg",
|
|
Packit |
437b5e |
"sys.resource", "sys.socket", "sys.stat", "sys.statvfs", "sys.time",
|
|
Packit |
437b5e |
"sys.times", "sys.utsname", "sys.wait", "syslog", "termio", "time",
|
|
Packit |
437b5e |
"unistd", "utime"
|
|
Packit |
437b5e |
} do
|
|
Packit |
437b5e |
local t = require ("posix." .. sub)
|
|
Packit |
437b5e |
for k, v in pairs (t) do
|
|
Packit |
437b5e |
if k ~= "version" then
|
|
Packit |
437b5e |
assert(M[k] == nil, "posix namespace clash: " .. sub .. "." .. k)
|
|
Packit |
437b5e |
M[k] = v
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
-- Inject deprecated APIs (overwriting submodules) for backwards compatibility.
|
|
Packit |
437b5e |
for k, v in pairs (require "posix.deprecated") do
|
|
Packit |
437b5e |
M[k] = v
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
for k, v in pairs (require "posix.compat") do
|
|
Packit |
437b5e |
M[k] = v
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
M.version = "posix for " .. _VERSION .. " / luaposix 33.3.1"
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
local argerror, argtypeerror, checkstring, checktable, toomanyargerror =
|
|
Packit |
437b5e |
M.argerror, M.argtypeerror, M.checkstring, M.checktable, M.toomanyargerror
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
-- Code extracted from lua-stdlib with minimal modifications
|
|
Packit |
437b5e |
local list = {
|
|
Packit |
437b5e |
sub = function (l, from, to)
|
|
Packit |
437b5e |
local r = {}
|
|
Packit |
437b5e |
local len = #l
|
|
Packit |
437b5e |
from = from or 1
|
|
Packit |
437b5e |
to = to or len
|
|
Packit |
437b5e |
if from < 0 then
|
|
Packit |
437b5e |
from = from + len + 1
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
if to < 0 then
|
|
Packit |
437b5e |
to = to + len + 1
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
for i = from, to do
|
|
Packit |
437b5e |
table.insert (r, l[i])
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
return r
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
}
|
|
Packit |
437b5e |
-- end of stdlib code
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
--- Check permissions like @{posix.unistd.access}, but for euid.
|
|
Packit |
437b5e |
-- Based on the glibc function of the same name. Does not always check
|
|
Packit |
437b5e |
-- for read-only file system, text busy, etc., and does not work with
|
|
Packit |
437b5e |
-- ACLs &c.
|
|
Packit |
437b5e |
-- @function euidaccess
|
|
Packit |
437b5e |
-- @string file file to check
|
|
Packit |
437b5e |
-- @string mode checks to perform (as for access)
|
|
Packit |
437b5e |
-- @return 0 if access allowed; nil otherwise (and errno is set)
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
local access, set_errno, stat = M.access, M.set_errno, M.stat
|
|
Packit |
437b5e |
local getegid, geteuid, getgid, getuid =
|
|
Packit |
437b5e |
M.getegid, M.geteuid, M.getgid, M.getuid
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
local function euidaccess (file, mode)
|
|
Packit |
437b5e |
local euid, egid = geteuid (), getegid ()
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
if getuid () == euid and getgid () == egid then
|
|
Packit |
437b5e |
-- If we are not set-uid or set-gid, access does the same.
|
|
Packit |
437b5e |
return access (file, mode)
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
local stats = stat (file)
|
|
Packit |
437b5e |
if not stats then
|
|
Packit |
437b5e |
return
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
-- The super-user can read and write any file, and execute any file
|
|
Packit |
437b5e |
-- that anyone can execute.
|
|
Packit |
437b5e |
if euid == 0 and ((not string.match (mode, "x")) or
|
|
Packit |
437b5e |
string.match (stats.st_mode, "x")) then
|
|
Packit |
437b5e |
return 0
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
-- Convert to simple list of modes.
|
|
Packit |
437b5e |
mode = string.gsub (mode, "[^rwx]", "")
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
if mode == "" then
|
|
Packit |
437b5e |
return 0 -- The file exists.
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
-- Get the modes we need.
|
|
Packit |
437b5e |
local granted = stats.st_mode:sub (1, 3)
|
|
Packit |
437b5e |
if euid == stats.st_uid then
|
|
Packit |
437b5e |
granted = stats.st_mode:sub (7, 9)
|
|
Packit |
437b5e |
elseif egid == stats.st_gid or set.new (posix.getgroups ()):member (stats.st_gid) then
|
|
Packit |
437b5e |
granted = stats.st_mode:sub (4, 6)
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
granted = string.gsub (granted, "[^rwx]", "")
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
if string.gsub ("[^" .. granted .. "]", mode) == "" then
|
|
Packit |
437b5e |
return 0
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
set_errno (EACCESS)
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
if _DEBUG ~= false then
|
|
Packit |
437b5e |
M.euidaccess = function (...)
|
|
Packit |
437b5e |
local argt = {...}
|
|
Packit |
437b5e |
checkstring ("euidaccess", 1, argt[1])
|
|
Packit |
437b5e |
checkstring ("euidaccess", 2, argt[2])
|
|
Packit |
437b5e |
if #argt > 2 then toomanyargerror ("euidaccess", 2, #argt) end
|
|
Packit |
437b5e |
return euidaccess (...)
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
else
|
|
Packit |
437b5e |
M.euidaccess = euidaccess
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
--- Open a pseudo-terminal.
|
|
Packit |
437b5e |
-- Based on the glibc function of the same name.
|
|
Packit |
437b5e |
-- @fixme add support for term and win arguments
|
|
Packit |
437b5e |
-- @treturn[1] int master file descriptor
|
|
Packit |
437b5e |
-- @treturn[1] int slave file descriptor
|
|
Packit |
437b5e |
-- @treturn[1] string slave file name
|
|
Packit |
437b5e |
-- @return[2] nil
|
|
Packit |
437b5e |
-- @treturn[2] string error message
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
local bit = require "bit32"
|
|
Packit |
437b5e |
local fcntl = require "posix.fcntl"
|
|
Packit |
437b5e |
local stdlib = require "posix.stdlib"
|
|
Packit |
437b5e |
local unistd = require "posix.unistd"
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
local bor = bit.bor
|
|
Packit |
437b5e |
local open, O_RDWR, O_NOCTTY = fcntl.open, fcntl.O_RDWR, fcntl.O_NOCTTY
|
|
Packit |
437b5e |
local grantpt, openpt, ptsname, unlockpt =
|
|
Packit |
437b5e |
stdlib.grantpt, stdlib.openpt, stdlib.ptsname, stdlib.unlockpt
|
|
Packit |
437b5e |
local close = unistd.close
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
local function openpty (term, win)
|
|
Packit |
437b5e |
local ok, errmsg, master, slave, slave_name
|
|
Packit |
437b5e |
master, errmsg = openpt (bor (O_RDWR, O_NOCTTY))
|
|
Packit |
437b5e |
if master then
|
|
Packit |
437b5e |
ok, errmsg = grantpt (master)
|
|
Packit |
437b5e |
if ok then
|
|
Packit |
437b5e |
ok, errmsg = unlockpt (master)
|
|
Packit |
437b5e |
if ok then
|
|
Packit |
437b5e |
slave_name, errmsg = ptsname (master)
|
|
Packit |
437b5e |
if slave_name then
|
|
Packit |
437b5e |
slave, errmsg = open (slave_name, bor (O_RDWR, O_NOCTTY))
|
|
Packit |
437b5e |
if slave then
|
|
Packit |
437b5e |
return master, slave, slave_name
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
close (master)
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
return nil, errmsg
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
if _DEBUG ~= false then
|
|
Packit |
437b5e |
M.openpty = function (...)
|
|
Packit |
437b5e |
local argt = {...}
|
|
Packit |
437b5e |
if #argt > 0 then toomanyargerror ("openpty", 0, #argt) end
|
|
Packit |
437b5e |
return openpty (...)
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
else
|
|
Packit |
437b5e |
M.openpty = openpty
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
--- Exec a command or Lua function.
|
|
Packit |
437b5e |
-- @function execx
|
|
Packit |
437b5e |
-- @param task, a table of arguments to `P.execp` or a Lua function, which
|
|
Packit |
437b5e |
-- should read from standard input, write to standard output, and return
|
|
Packit |
437b5e |
-- an exit code
|
|
Packit |
437b5e |
-- @param ... positional arguments to the function
|
|
Packit |
437b5e |
-- @treturn nil on error (normally does not return)
|
|
Packit |
437b5e |
-- @treturn string error message
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
local unpack = table.unpack or unpack -- 5.3 compatibility
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
local errno, execp, _exit =
|
|
Packit |
437b5e |
M.errno, M.execp, M._exit
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
function execx (task, ...)
|
|
Packit |
437b5e |
if type (task) == "table" then
|
|
Packit |
437b5e |
execp (unpack (task))
|
|
Packit |
437b5e |
-- Only get here if there's an error; kill the fork
|
|
Packit |
437b5e |
local _, n = errno ()
|
|
Packit |
437b5e |
_exit (n)
|
|
Packit |
437b5e |
else
|
|
Packit |
437b5e |
_exit (task (...) or 0)
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
if _DEBUG ~= false then
|
|
Packit |
437b5e |
M.execx = function (task, ...)
|
|
Packit |
437b5e |
local argt, typetask = {task, ...}, type (task)
|
|
Packit |
437b5e |
if typetask ~= "table" and typetask ~= "function" then
|
|
Packit |
437b5e |
argtypeerror ("execx", 1, "table or function", task)
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
return execx (task, ...)
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
else
|
|
Packit |
437b5e |
M.execx = execx
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
--- Run a command or function in a sub-process using `P.execx`.
|
|
Packit |
437b5e |
-- @function spawn
|
|
Packit |
437b5e |
-- @param task, as for `P.execx`.
|
|
Packit |
437b5e |
-- @tparam string ... as for `P.execx`
|
|
Packit |
437b5e |
-- @return values as for `P.wait`
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
local unpack = table.unpack or unpack -- 5.3 compatibility
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
local fork, wait =
|
|
Packit |
437b5e |
M.fork, M.wait
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
local function spawn (task, ...)
|
|
Packit |
437b5e |
local pid, err = fork ()
|
|
Packit |
437b5e |
if pid == nil then
|
|
Packit |
437b5e |
return pid, err
|
|
Packit |
437b5e |
elseif pid == 0 then
|
|
Packit |
437b5e |
execx (task, ...)
|
|
Packit |
437b5e |
else
|
|
Packit |
437b5e |
local _, reason, status = wait (pid)
|
|
Packit |
437b5e |
return status, reason -- If wait failed, status is nil & reason is error
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
if _DEBUG ~= false then
|
|
Packit |
437b5e |
M.spawn = function (task, ...)
|
|
Packit |
437b5e |
local argt, typetask = {task, ...}, type (task)
|
|
Packit |
437b5e |
if typetask ~= "table" and typetask ~= "function" then
|
|
Packit |
437b5e |
argtypeerror ("spawn", 1, "table or function", task)
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
return spawn (task, ...)
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
else
|
|
Packit |
437b5e |
M.spawn = spawn
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
local close, dup2, fork, pipe, wait, _exit =
|
|
Packit |
437b5e |
M.close, M.dup2, M.fork, M.pipe, M.wait, M._exit
|
|
Packit |
437b5e |
local STDIN_FILENO, STDOUT_FILENO = M.STDIN_FILENO, M.STDOUT_FILENO
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
--- Close a pipeline opened with popen or popen_pipeline.
|
|
Packit |
437b5e |
-- @function pclose
|
|
Packit |
437b5e |
-- @tparam table pfd pipeline object
|
|
Packit |
437b5e |
-- @return values as for `P.wait`, for the last (or only) stage of the pipeline
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
local function pclose (pfd)
|
|
Packit |
437b5e |
close (pfd.fd)
|
|
Packit |
437b5e |
for i = 1, #pfd.pids - 1 do
|
|
Packit |
437b5e |
wait (pfd.pids[i])
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
local _, reason, status = wait (pfd.pids[#pfd.pids])
|
|
Packit |
437b5e |
return reason, status
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
if _DEBUG ~= false then
|
|
Packit |
437b5e |
M.pclose = function (...)
|
|
Packit |
437b5e |
local argt = {...}
|
|
Packit |
437b5e |
checktable ("pclose", 1, argt[1])
|
|
Packit |
437b5e |
if #argt > 2 then toomanyargerror ("pclose", 1, #argt) end
|
|
Packit |
437b5e |
return pclose (...)
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
else
|
|
Packit |
437b5e |
M.pclose = pclose
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
local function move_fd (from_fd, to_fd)
|
|
Packit |
437b5e |
if from_fd ~= to_fd then
|
|
Packit |
437b5e |
if not dup2 (from_fd, to_fd) then
|
|
Packit |
437b5e |
error "error dup2-ing"
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
close (from_fd)
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
--- Run a commands or Lua function in a sub-process.
|
|
Packit |
437b5e |
-- @function popen
|
|
Packit |
437b5e |
-- @tparam task, as for @{execx}
|
|
Packit |
437b5e |
-- @tparam string mode `"r"` for read or `"w"` for write
|
|
Packit |
437b5e |
-- @func[opt] pipe_fn function returning a paired read and
|
|
Packit |
437b5e |
-- write file descriptor (*default* @{posix.unistd.pipe})
|
|
Packit |
437b5e |
-- @treturn pfd pipeline object
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
local function popen (task, mode, pipe_fn)
|
|
Packit |
437b5e |
local read_fd, write_fd = (pipe_fn or pipe) ()
|
|
Packit |
437b5e |
if not read_fd then
|
|
Packit |
437b5e |
error "error opening pipe"
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
local parent_fd, child_fd, in_fd, out_fd
|
|
Packit |
437b5e |
if mode == "r" then
|
|
Packit |
437b5e |
parent_fd, child_fd, in_fd, out_fd = read_fd, write_fd, STDIN_FILENO, STDOUT_FILENO
|
|
Packit |
437b5e |
elseif mode == "w" then
|
|
Packit |
437b5e |
parent_fd, child_fd, in_fd, out_fd = write_fd, read_fd, STDOUT_FILENO, STDIN_FILENO
|
|
Packit |
437b5e |
else
|
|
Packit |
437b5e |
error "invalid mode"
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
local pid = fork ()
|
|
Packit |
437b5e |
if pid == nil then
|
|
Packit |
437b5e |
error "error forking"
|
|
Packit |
437b5e |
elseif pid == 0 then -- child process
|
|
Packit |
437b5e |
move_fd (child_fd, out_fd)
|
|
Packit |
437b5e |
close (parent_fd)
|
|
Packit |
437b5e |
_exit (execx (task, child_fd, in_fd, out_fd))
|
|
Packit |
437b5e |
end -- parent process
|
|
Packit |
437b5e |
close (child_fd)
|
|
Packit |
437b5e |
return {pids = {pid}, fd = parent_fd}
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
if _DEBUG ~= false then
|
|
Packit |
437b5e |
M.popen = function (task, ...)
|
|
Packit |
437b5e |
local argt, typetask = {task, ...}, type (task)
|
|
Packit |
437b5e |
if typetask ~= "table" and typetask ~= "function" then
|
|
Packit |
437b5e |
argtypeerror ("popen", 1, "table or function", task)
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
checkstring ("popen", 2, argt[2])
|
|
Packit |
437b5e |
if argt[3] ~= nil and type (argt[3]) ~= "function" then
|
|
Packit |
437b5e |
argtypeerror ("popen", 3, "function or nil", argt[3])
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
if #argt > 3 then toomanyargerror ("popen", 3, #argt) end
|
|
Packit |
437b5e |
return popen (task, ...)
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
else
|
|
Packit |
437b5e |
M.popen = popen
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
--- Perform a series of commands and Lua functions as a pipeline.
|
|
Packit |
437b5e |
-- @function popen_pipeline
|
|
Packit |
437b5e |
-- @tparam table t tasks for @{execx}
|
|
Packit |
437b5e |
-- @tparam string mode `"r"` for read or `"w"` for write
|
|
Packit |
437b5e |
-- @func[opt] pipe_fn function returning a paired read and
|
|
Packit |
437b5e |
-- write file descriptor (*default* @{posix.unistd.pipe})
|
|
Packit |
437b5e |
-- @treturn pfd pipeline object
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
local close, _exit = M.close, M._exit
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
local function popen_pipeline (tasks, mode, pipe_fn)
|
|
Packit |
437b5e |
local first, from, to, inc = 1, 2, #tasks, 1
|
|
Packit |
437b5e |
if mode == "w" then
|
|
Packit |
437b5e |
first, from, to, inc = #tasks, #tasks - 1, 1, -1
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
local pfd = popen (tasks[first], mode, pipe_fn)
|
|
Packit |
437b5e |
for i = from, to, inc do
|
|
Packit |
437b5e |
local pfd_next = popen (function (fd, in_fd, out_fd)
|
|
Packit |
437b5e |
move_fd (pfd.fd, in_fd)
|
|
Packit |
437b5e |
_exit (execx (tasks[i]))
|
|
Packit |
437b5e |
end,
|
|
Packit |
437b5e |
mode,
|
|
Packit |
437b5e |
pipe_fn)
|
|
Packit |
437b5e |
close (pfd.fd)
|
|
Packit |
437b5e |
pfd.fd = pfd_next.fd
|
|
Packit |
437b5e |
table.insert (pfd.pids, pfd_next.pids[1])
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
return pfd
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
if _DEBUG ~= false then
|
|
Packit |
437b5e |
M.popen_pipeline = function (...)
|
|
Packit |
437b5e |
local argt = {...}
|
|
Packit |
437b5e |
checktable ("popen_pipeline", 1, argt[1])
|
|
Packit |
437b5e |
checkstring ("popen_pipeline", 2, argt[2])
|
|
Packit |
437b5e |
if argt[3] ~= nil and type (argt[3]) ~= "function" then
|
|
Packit |
437b5e |
argtypeerror ("popen_pipeline", 3, "function or nil", argt[3])
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
if #argt > 3 then toomanyargerror ("popen_pipeline", 3, #argt) end
|
|
Packit |
437b5e |
return popen_pipeline (...)
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
else
|
|
Packit |
437b5e |
M.popen_pipeline = popen_pipeline
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
--- Add one gettimeofday() returned timeval to another.
|
|
Packit |
437b5e |
-- @function timeradd
|
|
Packit |
437b5e |
-- @param x a timeval
|
|
Packit |
437b5e |
-- @param y another timeval
|
|
Packit |
437b5e |
-- @return x + y, adjusted for usec overflow
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
local function timeradd (x, y)
|
|
Packit |
437b5e |
local sec, usec = 0, 0
|
|
Packit |
437b5e |
if x.sec then sec = sec + x.sec end
|
|
Packit |
437b5e |
if y.sec then sec = sec + y.sec end
|
|
Packit |
437b5e |
if x.usec then usec = usec + x.usec end
|
|
Packit |
437b5e |
if y.usec then usec = usec + y.usec end
|
|
Packit |
437b5e |
if usec > 1000000 then
|
|
Packit |
437b5e |
sec = sec + 1
|
|
Packit |
437b5e |
usec = usec - 1000000
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
return { sec = sec, usec = usec }
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
if _DEBUG ~= false then
|
|
Packit |
437b5e |
M.timeradd = function (...)
|
|
Packit |
437b5e |
local argt = {...}
|
|
Packit |
437b5e |
checktable ("timeradd", 1, argt[1])
|
|
Packit |
437b5e |
checktable ("timeradd", 2, argt[2])
|
|
Packit |
437b5e |
if #argt > 2 then toomanyargerror ("timeradd", 2, #argt) end
|
|
Packit |
437b5e |
return timeradd (...)
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
--- Compare one gettimeofday() returned timeval with another
|
|
Packit |
437b5e |
-- @function timercmp
|
|
Packit |
437b5e |
-- @param x a timeval
|
|
Packit |
437b5e |
-- @param y another timeval
|
|
Packit |
437b5e |
-- @return 0 if x and y are equal, >0 if x is newer, <0 if y is newer
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
local function timercmp (x, y)
|
|
Packit |
437b5e |
local x = { sec = x.sec or 0, usec = x.usec or 0 }
|
|
Packit |
437b5e |
local y = { sec = y.sec or 0, usec = y.usec or 0 }
|
|
Packit |
437b5e |
if x.sec ~= y.sec then
|
|
Packit |
437b5e |
return x.sec - y.sec
|
|
Packit |
437b5e |
else
|
|
Packit |
437b5e |
return x.usec - y.usec
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
if _DEBUG ~= false then
|
|
Packit |
437b5e |
M.timercmp = function (...)
|
|
Packit |
437b5e |
local argt = {...}
|
|
Packit |
437b5e |
checktable ("timercmp", 1, argt[1])
|
|
Packit |
437b5e |
checktable ("timercmp", 2, argt[2])
|
|
Packit |
437b5e |
if #argt > 2 then toomanyargerror ("timercmp", 2, #argt) end
|
|
Packit |
437b5e |
return timercmp (...)
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
--- Subtract one gettimeofday() returned timeval from another.
|
|
Packit |
437b5e |
-- @function timersub
|
|
Packit |
437b5e |
-- @param x a timeval
|
|
Packit |
437b5e |
-- @param y another timeval
|
|
Packit |
437b5e |
-- @return x - y, adjusted for usec underflow
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
local function timersub (x,y)
|
|
Packit |
437b5e |
local sec, usec = 0, 0
|
|
Packit |
437b5e |
if x.sec then sec = x.sec end
|
|
Packit |
437b5e |
if y.sec then sec = sec - y.sec end
|
|
Packit |
437b5e |
if x.usec then usec = x.usec end
|
|
Packit |
437b5e |
if y.usec then usec = usec - y.usec end
|
|
Packit |
437b5e |
if usec < 0 then
|
|
Packit |
437b5e |
sec = sec - 1
|
|
Packit |
437b5e |
usec = usec + 1000000
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
return { sec = sec, usec = usec }
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
if _DEBUG ~= false then
|
|
Packit |
437b5e |
M.timersub = function (...)
|
|
Packit |
437b5e |
local argt = {...}
|
|
Packit |
437b5e |
checktable ("timersub", 1, argt[1])
|
|
Packit |
437b5e |
checktable ("timersub", 2, argt[2])
|
|
Packit |
437b5e |
if #argt > 2 then toomanyargerror ("timersub", 2, #argt) end
|
|
Packit |
437b5e |
return timersub (...)
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
end
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
return M
|