rem: Tcl_Channel chan;
add: Tcl_Channel chan = NULL;
context: NsTclChanObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]){    NsInterp *itPtr = arg;    NsServer *servPtr = itPtr->servPtr;    Tcl_Channel chan;    int new;    Tcl_HashEntry *hPtr;    Tcl_HashSearch search;    static CONST char *opts[] = {	"cleanup", "list", "share", "register", "unregister", NULL    };    enum {	CCleanupIdx, CListIdx, CShareIdx, CRegisterIdx, CUnregisterIdx    } opt;    if (objc < 2) {        Tcl_WrongNumArgs(interp, 1, objv, "command ?args?");	return TCL_ERROR;    }    if (Tcl_GetIndexFromObj(interp, objv[1], opts, "option", 0,			    (int *) &opt) != TCL_OK) {	return TCL_ERROR;    }    switch (opt) {    case CShareIdx:	if (objc != 4) {            Tcl_WrongNumArgs(interp, 1, objv, "share name channel");	    return TCL_ERROR;	}	chan = Tcl_GetChannel(interp, Tcl_GetString(objv[2]), NULL);	if (chan == NULL) {	    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "no such channel: ", 		    Tcl_GetString(objv[2]), NULL);	    return TCL_ERROR;	}    	Ns_MutexLock(&servPtr->chans.lock);	hPtr = Tcl_CreateHashEntry(&servPtr->chans.table, Tcl_GetString(objv[3]), &new);    	if (new) {	    Tcl_RegisterChannel(NULL, chan);            Tcl_SetHashValue(hPtr, chan);    	}    	Ns_MutexUnlock(&servPtr->chans.lock);	if (!new) {	    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "share already in use: ", 		    Tcl_GetString(objv[3]), NULL);	    return TCL_ERROR;	}	hPtr = Tcl_CreateHashEntry(&itPtr->chans, Tcl_GetString(objv[3]), &new);	Tcl_SetHashValue(hPtr, chan);	break;    case CRegisterIdx:	if (objc != 3) {	    Tcl_WrongNumArgs(interp, 1, objv, "register name");	    return TCL_ERROR;	}    	Ns_MutexLock(&servPtr->chans.lock);    	hPtr = Tcl_FindHashEntry(&servPtr->chans.table, Tcl_GetString(objv[2]));	if (hPtr != NULL) {	    chan = Tcl_GetHashValue(hPtr);	    Tcl_RegisterChannel(interp, chan);	    Tcl_SetResult(interp, (char *) Tcl_GetChannelName(chan), TCL_VOLATILE);	}    	Ns_MutexUnlock(&servPtr->chans.lock);	if (hPtr == NULL) {	    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "no such shared channel: ",		    Tcl_GetString(objv[3]), NULL);	    return TCL_ERROR;	}	hPtr = Tcl_CreateHashEntry(&itPtr->chans, Tcl_GetString(objv[2]), &new);	Tcl_SetHashValue(hPtr, chan);	break;    case CUnregisterIdx:	if (objc != 3) {            Tcl_WrongNumArgs(interp, 1, objv, "unregister name");	    return TCL_ERROR;	}	hPtr = Tcl_FindHashEntry(&itPtr->chans, Tcl_GetString(objv[2]));	if (hPtr == NULL) {	    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "no such registered channel: ",		    Tcl_GetString(objv[3]), NULL);	    return TCL_ERROR;	}	chan = Tcl_GetHashValue(hPtr);	Tcl_DeleteHashEntry(hPtr);    	Ns_MutexLock(&servPtr->chans.lock);	Tcl_UnregisterChannel(interp, chan);    	Ns_MutexUnlock(&servPtr->chans.lock);	break;    case CListIdx:	hPtr = Tcl_FirstHashEntry(&itPtr->chans, &search);	while (hPtr != NULL) {	    Tcl_AppendElement(interp, Tcl_GetHashKey(&itPtr->chans, hPtr));	    hPtr = Tcl_NextHashEntry(&search);	}	break;    case CCleanupIdx:	if (itPtr->chans.numEntries > 0) {	    Ns_MutexLock(&servPtr->chans.lock);	    hPtr = Tcl_FirstHashEntry(&itPtr->chans, &search);	    while (hPtr != NULL) {	        chan = Tcl_GetHashValue(hPtr);		Tcl_UnregisterChannel(interp, chan);	    	hPtr = Tcl_NextHashEntry(&search);	    }	    Ns_MutexUnlock(&servPtr->chans.lock);	}    }    return TCL_OK;}