[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: io.popen of unknown program succeeds
- From: Sean Conner <sean@...>
- Date: Sat, 28 Dec 2013 05:29:54 -0500
It was thus said that the Great Dirk Laurie once stated:
> 2013/12/28 Philipp Janda <siffiejoe@gmx.net>:
>
> > But you can find out (in Lua 5.2) by calling the `close` method on the
> > returned file pointer:
> >
> > > print( io.popen( "no_such_program" ):close() )
> > sh: 1: no_such_program: not found
> > nil exit 127
> > > print( io.popen( "false" ):close() )
> > nil exit 1
> > > print( io.popen( "true" ):close() )
> > true exit 0
>
> So one could use this instead of io.popen?
>
> function popen(prog,mode)
> local cond,msg,code = io.popen(prog,mode):close()
> if code==127 then error("'"..prog.."' not found") end
> return io.popen(prog,mode)
> end
No, much better to check for the existance of the program first:
function popen(program,mode)
local function exists(name)
local function check(file)
local f = io.open(file,"r")
if f ~= nil then
f:close()
return true
else
return false
end
end
-- -------------------------------------------------------------------
-- if given a relative or absolute path, just check the name. No need
-- to adapt this code for Windows---it'll work as is, as Windows will
-- also support '/' for directory separators, and it also supports '.'
-- for the current directory.
-- -------------------------------------------------------------------
if name:match("^%./") or name:match("^/") then
return check(name)
end
-- -------------------------------------------------------------------
-- now check the PATH. If PATH isn't defined, just use an empty string
-- to avoid some messy logic otherwise.
-- -------------------------------------------------------------------
local path = os.getenv("PATH") or ""
for segment in path:gmatch("([^:]+):?") do
local file = segment .. "/" .. name
if check(file) then
return true
end
end
return false
end
local file = program:match("^(%S+)")
if not exists(file) then
error('"' .. program .. '" not found')
end
return io.popen(program,mode)
end
But this fails to check if the resulting file is executable (although, if
it's in the PATH, it probably is), and program names with embedded spaces
are problematic. Perhaps if you gave popen() three parameters, the first
being the program, the second being the rest of the command line, and the
final one being the mode would work around the space problem ...
-spc (It's always the little details ... )