我在我的C应用程序中嵌入了Tcl解释器。我想将C应用程序作为telnet服务器运行,并且执行从telnet客户端发送的Tcl命令。
我写了一个示例代码,如Tcl_SocketObjCmd()
。
问题:如何将telnet通道连接到Tcl解释器,然后执行从telnet客户端发送的Tcl命令?
似乎是为了在Tcl_MainEx()
中实现tclMain.c
的功能。
但现在我不知道如何将Telnet服务器通道连接到Tcl解释器。
typedef struct AcceptCallback
{
char *script;
Tcl_Interp *interp;
} AcceptCallback;
int
main(int argc, char **argv)
{
Tcl_Interp *interp;
interp = Tcl_CreateInterp();
if (NULL == interp)
{
return 1;
}
if (Tcl_Init(interp) == TCL_ERROR)
{
return 1;
}
telnet_server_init(interp, 8888, "192.168.1.100");
while (true)
{
sleep(100);
}
return 0
}
int
telnet_server_init(
Tcl_Interp *interp,
int port,
char *host)
{
char *script = "";
Tcl_Channel chan;
AcceptCallback *acceptCallbackPtr = ckalloc(sizeof(AcceptCallback));
unsigned len = strlen(script) + 1;
char *copyScript = ckalloc(len);
memcpy(copyScript, script, len);
acceptCallbackPtr->script = copyScript;
acceptCallbackPtr->interp = interp;
chan = Tcl_OpenTcpServer(interp, port, host, AcceptCallbackProc, acceptCallbackPtr);
if (chan == NULL)
{
ckfree(copyScript);
ckfree(acceptCallbackPtr);
return TCL_ERROR;
}
RegisterTcpServerInterpCleanup(interp, acceptCallbackPtr);
Tcl_CreateCloseHandler(chan, TcpServerCloseProc, acceptCallbackPtr);
return TCL_OK;
}
static void
AcceptCallbackProc(
ClientData callbackData,
Tcl_Channel chan,
char *address,
int port)
{
AcceptCallback *acceptCallbackPtr = callbackData;
/*
* Check if the callback is still valid; the interpreter may have gone
* away, this is signalled by setting the interp field of the callback
* data to NULL.
*/
if (acceptCallbackPtr->interp != NULL) {
char portBuf[TCL_INTEGER_SPACE];
char *script = acceptCallbackPtr->script;
Tcl_Interp *interp = acceptCallbackPtr->interp;
int result;
Tcl_Preserve(script);
Tcl_Preserve(interp);
TclFormatInt(portBuf, port);
Tcl_RegisterChannel(interp, chan);
/*
* Artificially bump the refcount to protect the channel from being
* deleted while the script is being evaluated.
*/
Tcl_RegisterChannel(NULL, chan);
result = Tcl_VarEval(interp, script, " ", Tcl_GetChannelName(chan),
" ", address, " ", portBuf, NULL);
if (result != TCL_OK) {
Tcl_BackgroundException(interp, result);
Tcl_UnregisterChannel(interp, chan);
}
/*
* Decrement the artificially bumped refcount. After this it is not
* safe anymore to use "chan", because it may now be deleted.
*/
Tcl_UnregisterChannel(NULL, chan);
Tcl_Release(interp);
Tcl_Release(script);
} else {
/*
* The interpreter has been deleted, so there is no useful way to use
* the client socket - just close it.
*/
Tcl_Close(NULL, chan);
}
}