[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: io.popen: reading both stdout AND stderr
 
- From: Philipp Janda <siffiejoe@...>
 
- Date: Thu, 15 Aug 2013 17:01:57 +0200
 
Hi!
Am 15.08.2013 15:57 schröbte Lorenzo Donati:
[...]
BTW. If Lua team doesn't deem it useful enough to enhance popen in this
sense, IMO this should be added at least to lfs
On a related note, although a robust workhorse, I find lfs a bit
lacking. I'd really like it to be a little more feature complete.
Maybe you are looking at the wrong library. What about lua-apr[1][2] 
(also available as a rock[3])?
  [1]:  https://github.com/xolox/lua-apr/
  [2]:  http://peterodding.com/code/lua/apr/
  [3]:  http://luarocks.org/repositories/rocks/#lua-apr
lua-apr is still for Lua 5.1 only, but I have a quick-and-dirty patch 
for Lua 5.2 support, if you are interested ...
Features I miss from lfs (which should be easy to bind to already
existing APIs in the host OS):
* mkdir cannot create directories recursively ( mkdir "a/b/c" gives an
error if "a" doesn't exist, whereas I'd like to have a flag to tell it
"do make all the intermediate dirs")
    apr.dir_make_recursive(path [, permissions]) → status
* File copy operations.
    apr.file_copy(source, target [, permissions]) → status
    apr.file_append(source, target [, permissions]) → status
    apr.file_link(source, target) → status
* Pathname existance checking and
canonalization/normalization/resolution (e.g. lfs.exists
"/foo/bar/a/b/../../c" would return "/foo/bar/c" if this file exists, or
nil otherwise)
    apr.filepath_root(path [, option, ...]) → root, path
    apr.filepath_parent(path [, option, ...]) → parent, filename
    apr.filepath_name(path [, split]) → filename [, extension]
    apr.filepath_merge(root, path [, option, ...]) → merged
etc...
* lfs.dir iterator should not return ".." and "." as directories.
Especially ".." is dangerous when building recursive functions on top of
lfs.dir: you could by mistake recurse upwards (I'm always wrapping
lfs.dir to remove ".." and ".", but this inconvenient and error prone -
I don't know you, but I never used lfs.dir output directly). At least
this behaviour should be documented.
Other operations that are not strictly file-system operations, but IMO
too much connected to them:
* lfs.setenv (to pair os.getenv)
    apr.env_set(name, value) → status
    apr.env_delete(name) → status
* lfs.popen (as said above)
* lfs.execute  having a richer API than os.execute (e.g. see wxWidgets
wxExecute) and allowing sync/async execution
    apr.proc_create(program) → process
    apr.proc_detach(daemonize) → status
    process:user_set(username [, password]) → status
    process:cmdtype_set(type) → status
    process:dir_set(path) → status
    process:io_set(stdin, stdout, stderr) → status
    process:exec([args]) → status
    process:wait(how) → done [, why, code]
    process:kill(how) → status
etc....
Regarding your enhanced popen, this is as far as I got:
    local apr = require( "apr" )
    local proc = assert( apr.proc_create( "./xxx.sh" ) )
    assert( proc:cmdtype_set( "program" ) )
    assert( proc:io_set( 'none', 'parent-block', 'parent-block' ) )
    assert( proc:exec{} )
    local out = proc:out_get()
    local err = proc:err_get()
    print( out:read() )
    print( err:read() )
    local done, why, code = assert( proc:wait( true ) )
    if why == "exit" then
      print( "exit status:", code )
    else
      print( "killed by signal:", code )
    end
The problem (which lfs would face as well) is multiplexing the io of 
stdout and stderr so that no process is blocked and no output lost ...
I acknowledge that many of the above can be built on top of lfs, but
sometimes it is tricky and anyway not as efficient as wrapping existing
OS APIs.
Cheers.
-- Lorenzo
Philipp