Updated 2010-05-17 21:21:56 by AMG

MJ: We can extend the Tcl chan command to have a new subcommand chan mode that returns a list of the access modes of a file handle (r for readable, w for writable) with the small extension below.

To register the new subcommand in the namespace ensemble the ensemble map needs to be updated.

examples edit

% package require chanmode
% chan mode stderr
% chan mode stdin
% set f [open c:/temp.txt w+]
% chan mode $f
r w

pkgIndex.tcl edit

package ifneeded chanmode 0.1 \
    [list source [file join [file dirname [info script]] chanmode.tcl]]

chanmode.tcl edit

load [file dirname [info script]]/chanmode0.1[info sharedlibextension]
set map [namespace ensemble configure ::chan -map]
dict set map mode ::chanmode::mode
namespace ensemble configure ::chan -map $map

chanmode.c edit

#include <tcl.h>
#include <stdio.h>

   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 get the mode from. */
   const char *channelId;  /* Name of channel to get the mode from. */
   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) {
       Tcl_AppendElement(interp, "r");

   if (mode & TCL_WRITABLE) {
       Tcl_AppendElement(interp, "w");

   return TCL_OK;

Chanmode_Init(Tcl_Interp *interp)
   if (Tcl_InitStubs(interp, "8.5", 0) == 0) {
      return TCL_ERROR;
   Tcl_CreateObjCommand(interp, "chanmode::mode", Chanmode_ModeObjCmd,
                        NULL, NULL);
   Tcl_PkgProvide(interp, "chanmode", "0.1");
   return TCL_OK;