Emulating execvp - Is There a Better Way To Do This?
I'm currently wrapping a command line tool (espeak
) with Tcl/Tk, and I have figured this out so far:
load ./extensions/system.so
package require Tk
package require Tclx
set chid 0
proc kill {id} {
exec kill -9 $id
}
proc speak {} {
global chid
set chid [fork]
if {$chid == 0} {
execvp espeak [.text get 1.0 end]
}
}
proc silent {} {
global chid
kill $chid
}
Where system.so is an extension I hacked together to be able to use execvp
:
#include <tcl.h>
#include <tclExtend.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
static int
execvp_command(ClientData cdata, Tcl_Interp *interp, int argc, const char* argv[])
{
if (argc == 1)
{
interp->result = "execvp command ?args ...?";
return TCL_ERROR;
}
execvp(argv[1], argv + 1);
return TCL_OK;
}
int System_Init(Tcl_Interp* interp)
{
if (Tcl_InitStubs(interp, "8.1", 0) == NULL)
return TCL_ERROR;
Tcl_CreateCommand(interp, "execvp", execvp_command, NULL, NULL);
Tcl_PkgProvide(interp, "syste开发者_如何学编程m", "1.0");
return TCL_OK;
}
The reason I need execvp
is because a subprocess created by exec
(Tcl) seems to keep going when the process dies (I can confirm this by ^C
'ing out of the GUI), whereas if I use execvp
, espeak
dies properly.
Thus, all I really need out of this script is to be able to start a subprocess and kill it on demand.
Is there another library that can do this properly, like Expect?
Tcl uses execvp
internally (really; I've just checked the source) so the difference lies elsewhere. That elsewhere will be in signals; the subprocess created by the exec
command (and other things that use the same underlying engine) will have the majority of signals forced to use the default signal handlers, but since the only signal it sets to non-default is SIGPIPE, I wonder what else is going on.
That said, the definitive extension for working with this sort of thing is TclX. That gives you access to all the low-level POSIX functionality that you've been using partially. (Expect may also be able to do it.)
精彩评论