lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


You're assuming that the command is on the path. This doesn't work for shell builtins, or for things using windows' AppPaths feature to avoid contaminating PATH for one single program

On 28 Dec 2013 10:33, "Sean Conner" <sean@conman.org> wrote:
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 ... )