⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcliocmd.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 3 页
字号:
    return TCL_OK;}/* *---------------------------------------------------------------------- * * TcpAcceptCallbacksDeleteProc -- * *	Assocdata cleanup routine called when an interpreter is being *	deleted to set the interp field of all the accept callback records *	registered with	the interpreter to NULL. This will prevent the *	interpreter from being used in the future to eval accept scripts. * * Results: *	None. * * Side effects: *	Deallocates memory and sets the interp field of all the accept *	callback records to NULL to prevent this interpreter from being *	used subsequently to eval accept scripts. * *---------------------------------------------------------------------- */	/* ARGSUSED */static voidTcpAcceptCallbacksDeleteProc(clientData, interp)    ClientData clientData;	/* Data which was passed when the assocdata                                 * was registered. */    Tcl_Interp *interp;		/* Interpreter being deleted - not used. */{    Tcl_HashTable *hTblPtr;    Tcl_HashEntry *hPtr;    Tcl_HashSearch hSearch;    AcceptCallback *acceptCallbackPtr;    hTblPtr = (Tcl_HashTable *) clientData;    for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch);             hPtr != (Tcl_HashEntry *) NULL;             hPtr = Tcl_NextHashEntry(&hSearch)) {        acceptCallbackPtr = (AcceptCallback *) Tcl_GetHashValue(hPtr);        acceptCallbackPtr->interp = (Tcl_Interp *) NULL;    }    Tcl_DeleteHashTable(hTblPtr);    ckfree((char *) hTblPtr);}/* *---------------------------------------------------------------------- * * RegisterTcpServerInterpCleanup -- * *	Registers an accept callback record to have its interp *	field set to NULL when the interpreter is deleted. * * Results: *	None. * * Side effects: *	When, in the future, the interpreter is deleted, the interp *	field of the accept callback data structure will be set to *	NULL. This will prevent attempts to eval the accept script *	in a deleted interpreter. * *---------------------------------------------------------------------- */static voidRegisterTcpServerInterpCleanup(interp, acceptCallbackPtr)    Tcl_Interp *interp;		/* Interpreter for which we want to be                                 * informed of deletion. */    AcceptCallback *acceptCallbackPtr;    				/* The accept callback record whose                                 * interp field we want set to NULL when                                 * the interpreter is deleted. */{    Tcl_HashTable *hTblPtr;	/* Hash table for accept callback                                 * records to smash when the interpreter                                 * will be deleted. */    Tcl_HashEntry *hPtr;	/* Entry for this record. */    int new;			/* Is the entry new? */    hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp,            "tclTCPAcceptCallbacks",            NULL);    if (hTblPtr == (Tcl_HashTable *) NULL) {        hTblPtr = (Tcl_HashTable *) ckalloc((unsigned) sizeof(Tcl_HashTable));        Tcl_InitHashTable(hTblPtr, TCL_ONE_WORD_KEYS);        (void) Tcl_SetAssocData(interp, "tclTCPAcceptCallbacks",                TcpAcceptCallbacksDeleteProc, (ClientData) hTblPtr);    }    hPtr = Tcl_CreateHashEntry(hTblPtr, (char *) acceptCallbackPtr, &new);    if (!new) {        panic("RegisterTcpServerCleanup: damaged accept record table");    }    Tcl_SetHashValue(hPtr, (ClientData) acceptCallbackPtr);}/* *---------------------------------------------------------------------- * * UnregisterTcpServerInterpCleanupProc -- * *	Unregister a previously registered accept callback record. The *	interp field of this record will no longer be set to NULL in *	the future when the interpreter is deleted. * * Results: *	None. * * Side effects: *	Prevents the interp field of the accept callback record from *	being set to NULL in the future when the interpreter is deleted. * *---------------------------------------------------------------------- */static voidUnregisterTcpServerInterpCleanupProc(interp, acceptCallbackPtr)    Tcl_Interp *interp;		/* Interpreter in which the accept callback                                 * record was registered. */    AcceptCallback *acceptCallbackPtr;    				/* The record for which to delete the                                 * registration. */{    Tcl_HashTable *hTblPtr;    Tcl_HashEntry *hPtr;    hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp,            "tclTCPAcceptCallbacks", NULL);    if (hTblPtr == (Tcl_HashTable *) NULL) {        return;    }    hPtr = Tcl_FindHashEntry(hTblPtr, (char *) acceptCallbackPtr);    if (hPtr == (Tcl_HashEntry *) NULL) {        return;    }    Tcl_DeleteHashEntry(hPtr);}/* *---------------------------------------------------------------------- * * AcceptCallbackProc -- * *	This callback is invoked by the TCP channel driver when it *	accepts a new connection from a client on a server socket. * * Results: *	None. * * Side effects: *	Whatever the script does. * *---------------------------------------------------------------------- */static voidAcceptCallbackProc(callbackData, chan, address, port)    ClientData callbackData;		/* The data stored when the callback                                         * was created in the call to                                         * Tcl_OpenTcpServer. */    Tcl_Channel chan;			/* Channel for the newly accepted                                         * connection. */    char *address;			/* Address of client that was                                         * accepted. */    int port;				/* Port of client that was accepted. */{    AcceptCallback *acceptCallbackPtr;    Tcl_Interp *interp;    char *script;    char portBuf[10];    int result;    acceptCallbackPtr = (AcceptCallback *) 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 != (Tcl_Interp *) NULL) {        script = acceptCallbackPtr->script;        interp = acceptCallbackPtr->interp;                Tcl_Preserve((ClientData) script);        Tcl_Preserve((ClientData) 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((Tcl_Interp *) NULL,  chan);                result = Tcl_VarEval(interp, script, " ", Tcl_GetChannelName(chan),                " ", address, " ", portBuf, (char *) NULL);        if (result != TCL_OK) {            Tcl_BackgroundError(interp);	    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((Tcl_Interp *) NULL, chan);                Tcl_Release((ClientData) interp);        Tcl_Release((ClientData) script);    } else {        /*         * The interpreter has been deleted, so there is no useful         * way to utilize the client socket - just close it.         */        Tcl_Close((Tcl_Interp *) NULL, chan);    }}/* *---------------------------------------------------------------------- * * TcpServerCloseProc -- * *	This callback is called when the TCP server channel for which it *	was registered is being closed. It informs the interpreter in *	which the accept script is evaluated (if that interpreter still *	exists) that this channel no longer needs to be informed if the *	interpreter is deleted. * * Results: *	None. * * Side effects: *	In the future, if the interpreter is deleted this channel will *	no longer be informed. * *---------------------------------------------------------------------- */static voidTcpServerCloseProc(callbackData)    ClientData callbackData;	/* The data passed in the call to                                 * Tcl_CreateCloseHandler. */{    AcceptCallback *acceptCallbackPtr;    				/* The actual data. */    acceptCallbackPtr = (AcceptCallback *) callbackData;    if (acceptCallbackPtr->interp != (Tcl_Interp *) NULL) {        UnregisterTcpServerInterpCleanupProc(acceptCallbackPtr->interp,                acceptCallbackPtr);    }    Tcl_EventuallyFree((ClientData) acceptCallbackPtr->script, TCL_DYNAMIC);    ckfree((char *) acceptCallbackPtr);}/* *---------------------------------------------------------------------- * * Tcl_SocketCmd -- * *	This procedure is invoked to process the "socket" Tcl command. *	See the user documentation for details on what it does. * * Results: *	A standard Tcl result. * * Side effects: *	Creates a socket based channel. * *---------------------------------------------------------------------- */intTcl_SocketCmd(notUsed, interp, argc, argv)    ClientData notUsed;			/* Not used. */    Tcl_Interp *interp;			/* Current interpreter. */    int argc;				/* Number of arguments. */    char **argv;			/* Argument strings. */{    int a, server, port;    char *arg, *copyScript, *host, *script;    char *myaddr = NULL;    int myport = 0;    int async = 0;    Tcl_Channel chan;    AcceptCallback *acceptCallbackPtr;        server = 0;    script = NULL;    if (TclHasSockets(interp) != TCL_OK) {	return TCL_ERROR;    }    for (a = 1; a < argc; a++) {        arg = argv[a];	if (arg[0] == '-') {	    if (strcmp(arg, "-server") == 0) {                if (async == 1) {                    Tcl_AppendResult(interp,                            "cannot set -async option for server sockets",                            (char *) NULL);                    return TCL_ERROR;                }		server = 1;		a++;		if (a >= argc) {		    Tcl_AppendResult(interp,			    "no argument given for -server option",                            (char *) NULL);		    return TCL_ERROR;		}                script = argv[a];            } else if (strcmp(arg, "-myaddr") == 0) {		a++;                if (a >= argc) {		    Tcl_AppendResult(interp,			    "no argument given for -myaddr option",                            (char *) NULL);		    return TCL_ERROR;		}                myaddr = argv[a];            } else if (strcmp(arg, "-myport") == 0) {		a++;                if (a >= argc) {		    Tcl_AppendResult(interp,			    "no argument given for -myport option",                            (char *) NULL);		    return TCL_ERROR;		}		if (TclSockGetPort(interp, argv[a], "tcp", &myport)                    != TCL_OK) {		    return TCL_ERROR;		}            } else if (strcmp(arg, "-async") == 0) {                if (server == 1) {                    Tcl_AppendResult(interp,                            "cannot set -async option for server sockets",                            (char *) NULL);                    return TCL_ERROR;                }                async = 1;	    } else {		Tcl_AppendResult(interp, "bad option \"", arg,                        "\", must be -async, -myaddr, -myport, or -server",                        (char *) NULL);		return TCL_ERROR;	    }	} else {	    break;	}    }    if (server) {        host = myaddr;		/* NULL implies INADDR_ANY */	if (myport != 0) {	    Tcl_AppendResult(interp, "Option -myport is not valid for servers",		    NULL);	    return TCL_ERROR;	}    } else if (a < argc) {	host = argv[a];	a++;    } else {wrongNumArgs:	Tcl_AppendResult(interp, "wrong # args: should be either:\n",		argv[0],                " ?-myaddr addr? ?-myport myport? ?-async? host port\n",		argv[0],                " -server command ?-myaddr addr? port",                (char *) NULL);        return TCL_ERROR;    }    if (a == argc-1) {	if (TclSockGetPort(interp, argv[a], "tcp", &port) != TCL_OK) {	    return TCL_ERROR;	}    } else {	goto wrongNumArgs;    }    if (server) {        acceptCallbackPtr = (AcceptCallback *) ckalloc((unsigned)                sizeof(AcceptCallback));        copyScript = ckalloc((unsigned) strlen(script) + 1);        strcpy(copyScript, script);        acceptCallbackPtr->script = copyScript;        acceptCallbackPtr->interp = interp;        chan = Tcl_OpenTcpServer(interp, port, host, AcceptCallbackProc,                (ClientData) acceptCallbackPtr);        if (chan == (Tcl_Channel) NULL) {            ckfree(copyScript);            ckfree((char *) acceptCallbackPtr);            return TCL_ERROR;        }        /*         * Register with the interpreter to let us know when the         * interpreter is deleted (by having the callback set the         * acceptCallbackPtr->interp field to NULL). This is to         * avoid trying to eval the script in a deleted interpreter.         */        RegisterTcpServerInterpCleanup(interp, acceptCallbackPtr);                /*         * Register a close callback. This callback will inform the         * interpreter (if it still exists) that this channel does not         * need to be informed when the interpreter is deleted.         */                Tcl_CreateCloseHandler(chan, TcpServerCloseProc,                (ClientData) acceptCallbackPtr);    } else {        chan = Tcl_OpenTcpClient(interp, port, host, myaddr, myport, async);        if (chan == (Tcl_Channel) NULL) {            return TCL_ERROR;        }    }    Tcl_RegisterChannel(interp, chan);                Tcl_AppendResult(interp, Tcl_GetChannelName(chan), (char *) NULL);        return TCL_OK;}/* *---------------------------------------------------------------------- * * Tcl_FcopyObjCmd -- * *	This procedure is invoked to process the "fcopy" Tcl command. *	See the user documentation for details on what it does. * * Results: *	A standard Tcl result. * * Side effects: *	Moves data between two channels and possibly sets up a *	background copy handler. * *---------------------------------------------------------------------- */intTcl_FcopyObjCmd(dummy, interp, objc, objv)    ClientData dummy;		/* Not used. */    Tcl_Interp *interp;		/* Current interpreter. */    int objc;			/* Number of arguments. */    Tcl_Obj *CONST objv[];	/* Argument objects. */{    Tcl_Channel inChan, outChan;    char *arg;    int mode, i;    int toRead;    Tcl_Obj *cmdPtr;    static char* switches[] = { "-size", "-command", NULL };    enum { FcopySize, FcopyCommand } index;    if ((objc < 3) || (objc > 7) || (objc == 4) || (objc == 6)) {	Tcl_WrongNumArgs(interp, 1, objv,		"input output ?-size size? ?-command callback?");	return TCL_ERROR;    }    /*     * Parse the channel arguments and verify that they are readable     * or writable, as appropriate.     */    arg = Tcl_GetStringFromObj(objv[1], NULL);    inChan = Tcl_GetChannel(interp, arg, &mode);    if (inChan == (Tcl_Channel) NULL) {	return TCL_ERROR;    }    if ((mode & TCL_READABLE) == 0) {	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "channel \"",		Tcl_GetStringFromObj(objv[1], NULL),                 "\" wasn't opened for reading", (char *) NULL);        return TCL_ERROR;    }    arg = Tcl_GetStringFromObj(objv[2], NULL);    outChan = Tcl_GetChannel(interp, arg, &mode);    if (outChan == (Tcl_Channel) NULL) {	return TCL_ERROR;    }    if ((mode & TCL_WRITABLE) == 0) {	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "channel \"",		Tcl_GetStringFromObj(objv[1], NULL),                 "\" wasn't opened for writing", (char *) NULL);        return TCL_ERROR;    }    toRead = -1;    cmdPtr = NULL;    for (i = 3; i < objc; i += 2) {	if (Tcl_GetIndexFromObj(interp, objv[i], switches, "switch", 0,		(int *) &index) != TCL_OK) {	    return TCL_ERROR;	}	switch (index) {	    case FcopySize:		if (Tcl_GetIntFromObj(interp, objv[i+1], &toRead) != TCL_OK) {		    return TCL_ERROR;		}		break;	    case FcopyCommand:		cmdPtr = objv[i+1];		break;	}    }    return TclCopyChannel(interp, inChan, outChan, toRead, cmdPtr);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -