MJ - With the use of namespace ensembles to create newer Tcl core commands (e.g. chan) it's very straightforward to extend core commands with you own functionallity. One way is to change the Tcl core as described in chan mode a better way that allows to achieve this is to write an extension adding the functionallity. For instance we can extend the Tcl chan command to have a new subcommand chan mode that returns a list of the mode of a file handle (r for readable, w for writeable) with the following small extension.
pkgIndex.tcl
package ifneeded chanmode 0.1 \ [list source [file dirname [info script]]/chanmode.tcl]
chanmode.tcl
load [file dirname [info script]]/chanmode0.1.dll set map [namespace ensemble configure ::chan -map] dict set map mode ::chanmode::mode namespace ensemble configure ::chan -map $map
chanmode.c
#include <tcl.h> #include <stdio.h> int Chanmode_ModeObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Channel chan; /* The channel to puts on. */ const char *channelId; /* Name of channel for puts. */ int mode; /* Mode in which channel is opened. */ if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "channelId"); return TCL_ERROR; } channelId = Tcl_GetString(objv[1]); chan = Tcl_GetChannel(interp, channelId, &mode); if (chan == (Tcl_Channel) NULL) { return TCL_ERROR; } if ((mode & TCL_READABLE) != 0) { Tcl_AppendElement(interp, "r"); } if ((mode & TCL_WRITABLE) != 0) { Tcl_AppendElement(interp, "w"); } return TCL_OK; } int DLLEXPORT Chanmode_Init(Tcl_Interp *interp) { if (Tcl_InitStubs(interp, "8.5", 0) == 0L) { return TCL_ERROR; } Tcl_CreateObjCommand(interp, "chanmode::mode", Chanmode_ModeObjCmd, NULL, NULL); Tcl_PkgProvide(interp, "chanmode", "0.1"); return TCL_OK; }