*** orig/config/config.dist	Thu Mar 18 13:03:33 1993
--- config/config.dist	Thu Apr 14 10:23:25 1994
***************
*** 720,722 ****
--- 720,737 ----
  ##  How long to sleep between innwatch iterations.
  #### =()<INNWATCH_SLEEPTIME	@<INNWATCH_SLEEPTIME>@>()=
  INNWATCH_SLEEPTIME	600
+ 
+ ##
+ ##  13.  TCL Configuration
+ ##  Do you want TCL support?  Pick DO or DONT
+ #### =()<TCL_SUPPORT	@<TCL_SUPPORT>@>()=
+ TCL_SUPPORT		DO
+ ##  How do you get the TCL library?  Probably -ltcl -lm, blank if no TCL
+ #### =()<TCL_LIB	@<TCL_LIB>@>()=
+ TCL_LIB			-ltcl -lm
+ ##  TCL Startup File
+ #### =()<_PATH_TCL_STARTUP	@<_PATH_TCL_STARTUP>@>()=
+ _PATH_TCL_STARTUP	/news/startup.tcl
+ ##  TCL Filter File
+ #### =()<_PATH_TCL_FILTER	@<_PATH_TCL_FILTER>@>()=
+ _PATH_TCL_FILTER	/news/filter.tcl
*** orig/doc/ctlinnd.8	Thu Mar 18 13:03:35 1993
--- doc/ctlinnd.8	Tue May 31 17:51:31 1994
***************
*** 142,147 ****
--- 142,156 ----
  .I site
  from the server's list of active feeds.
  This command is forwarded; see below.
+ .\" =()<.if '@<TCL_SUPPORT>@'DO' \{\>()=
+ .if 'DO'DO' \{\
+ .TP
+ .BI filter " flag"
+ Enable or disable Tcl news filtering.
+ If
+ .I flag
+ starts with the letter ``y'' then filtering is enabled.  If it starts with
+ ``n'', then filtering is disabled.\}
  .TP
  .BI flush " site"
  Flush the buffer for the specified site.
***************
*** 304,309 ****
--- 313,332 ----
  files are reloaded; if it is the word ``overview.fmt'' then the
  .IR overview.fmt (5)
  file is reloaded.
+ .\" =()<.if '@<TCL_SUPPORT>@'DO' \{\>()=
+ .if 'DO'DO' \{\
+ If it is the word ``filter.tcl'' then the
+ .IR filter.tcl
+ file is reloaded.  If a TCL procedure named ``filter_before_reload'' exists,
+ it will be called prior to rereading
+ .IR filter.tcl.
+ If a TCL procedure named ``filter_after_reload'' exists, it will be called
+ after
+ .IR filter.tcl
+ has been reloaded.  Reloading the Tcl filter does not enable filtering if
+ it is disabled; use
+ .IR filter
+ to do this.\}
  The
  .I reason
  is reported to
***************
*** 312,317 ****
--- 335,345 ----
  .IR inn.conf (5)
  file; the server currently only uses the ``pathhost'' parameter, so this
  restriction should not be a problem.
+ .\" =()<.if '@<TCL_SUPPORT>@'DO' \{\>()=
+ .if 'DO'DO' \{\
+ The
+ .IR startup.tcl
+ file cannot be reloaded.\}
  .TP
  .BI renumber " group"
  Scan the spool directory for the specified newsgroup and update the
*** orig/frontends/ctlinnd.c	Fri Jan 29 08:43:32 1993
--- frontends/ctlinnd.c	Tue May 31 16:58:27 1994
***************
*** 42,47 ****
--- 42,51 ----
  	0,	SC_CHECKFILE,	FALSE	},
      {	"drop",		"site\t\t\tStop feeding site",
  	1,	SC_DROP,	FALSE		},
+ #if defined(DO_TCL)
+     {	"filter",		"flag\t\t\tEnable or disable Tcl filtering",
+ 	1,	SC_FILTER,	FALSE		},
+ #endif /* defined(DO_TCL) */
      {	"flush",	"site\t\t\tFlush feed for site*",
  	1,	SC_FLUSH,	FALSE	},
      {	"flushlogs",	"\t\t\tFlush log files",
*** orig/include/configdata.h	Thu Mar 18 13:04:11 1993
--- include/configdata.h	Tue May 31 17:51:36 1994
***************
*** 386,388 ****
--- 386,395 ----
  #define SUB_DEFAULT		FALSE
  #define SUB_NEGATE		'!'
  #define LOOPBACK_HOST		"127.0.0.1"
+ 
+ /*
+ **  13.  TCL Support
+ */
+ 
+     /* =()<#define @<TCL_SUPPORT>@_TCL>()= */
+ #define DO_TCL
*** orig/include/inndcomm.h	Fri Jan 29 08:51:13 1993
--- include/inndcomm.h	Tue May 31 16:59:14 1994
***************
*** 14,19 ****
--- 14,20 ----
  #define SC_CHANGEGROUP	'u'
  #define SC_CHECKFILE	'd'
  #define SC_DROP		'e'
+ #define SC_FILTER	'T'
  #define SC_FLUSH	'f'
  #define SC_FLUSHLOGS	'g'
  #define SC_GO		'h'
*** orig/include/paths.h	Thu Mar 18 13:04:18 1993
--- include/paths.h	Tue May 31 17:51:36 1994
***************
*** 166,168 ****
--- 166,178 ----
  #define _CONF_CONTENTTYPE	"mime-contenttype"
      /* Default encoding */
  #define _CONF_ENCODING		"mime-encoding"
+ 
+ /*
+ **  13.  TCL Support
+ */
+ 
+     /* =()<#define _PATH_TCL_STARTUP	"@<_PATH_TCL_STARTUP>@">()= */
+ #define _PATH_TCL_STARTUP	"/news/startup.tcl"
+ 
+     /* =()<#define _PATH_TCL_FILTER	"@<_PATH_TCL_FILTER>@">()= */
+ #define _PATH_TCL_FILTER	"/news/filter.tcl"
*** orig/innd/Makefile	Thu Mar 18 13:04:19 1993
--- innd/Makefile	Tue May 31 17:51:36 1994
***************
*** 32,45 ****
  LIBS	= 
  LIBNEWS	= ../libinn.a
  LINTLIB	= ../llib-linn.ln
  
  SOURCES	= \
  	art.c cc.c chan.c his.c icd.c innd.c lc.c nc.c newsfeeds.c ng.c \
! 	proc.c rc.c site.c
  
  OBJECTS	= \
  	art.o cc.o chan.o his.o icd.o innd.o lc.o nc.o newsfeeds.o ng.o \
! 	proc.o rc.o site.o
  
  ALL	= innd inndstart
  
--- 32,47 ----
  LIBS	= 
  LIBNEWS	= ../libinn.a
  LINTLIB	= ../llib-linn.ln
+ ## =()<TCL_LIB	= @<TCL_LIB>@>()=
+ TCL_LIB	= -ltcl -lm
  
  SOURCES	= \
  	art.c cc.c chan.c his.c icd.c innd.c lc.c nc.c newsfeeds.c ng.c \
! 	proc.c rc.c site.c tcl.c
  
  OBJECTS	= \
  	art.o cc.o chan.o his.o icd.o innd.o lc.o nc.o newsfeeds.o ng.o \
! 	proc.o rc.o site.o tcl.o
  
  ALL	= innd inndstart
  
***************
*** 56,62 ****
  	$(CTAGS) $(SOURCES) ../lib/*.c innd.h ../include/*.h
  
  innd:		$(P) $(OBJECTS) $(LIBNEWS)
! 	$(CC) $(LDFLAGS) -o $@ $(OBJECTS) $(LIBNEWS) $(LIBS)
  
  inndstart:	$(P) inndstart.o $(LIBNEWS)
  	$(CC) $(LDFLAGS) -o $@ inndstart.o $(LIBNEWS) $(LIBS)
--- 58,64 ----
  	$(CTAGS) $(SOURCES) ../lib/*.c innd.h ../include/*.h
  
  innd:		$(P) $(OBJECTS) $(LIBNEWS)
! 	$(CC) $(LDFLAGS) -o $@ $(OBJECTS) $(LIBNEWS) $(TCL_LIB) $(LIBS)
  
  inndstart:	$(P) inndstart.o $(LIBNEWS)
  	$(CC) $(LDFLAGS) -o $@ inndstart.o $(LIBNEWS) $(LIBS)
*** orig/innd/art.c	Thu Mar 18 13:04:21 1993
--- innd/art.c	Thu Apr 14 10:23:25 1994
***************
*** 1726,1731 ****
--- 1726,1768 ----
  	return buff;
      }
  
+ #if defined(DO_TCL)
+     if (TCLFilterActive) {
+ 	int code;
+ 	ARTHEADER *hp;
+ 
+ 	/* make info available to Tcl */
+ 
+ 	TCLCurrArticle = article;
+ 	TCLCurrData = &Data;
+ 	for (hp = ARTheaders; hp < ENDOF(ARTheaders); hp++) {
+ 	    if (hp->Found) {
+ 		Tcl_SetVar2(TCLInterpreter, "Headers", hp->Name,
+ 			    hp->Value, TCL_GLOBAL_ONLY);
+ 	    }
+ 	}
+ 	    
+ 	/* call filter */
+ 
+         code = Tcl_Eval(TCLInterpreter, "filter_news");
+         if (code == TCL_OK) {
+ 	    if (strcmp(TCLInterpreter->result, "accept") != 0) {
+ 	        (void)sprintf(buff, "%d %s", NNTP_REJECTIT_VAL, 
+ 			      TCLInterpreter->result);
+ 		syslog(L_NOTICE, "rejecting %s %s", HDR(_message_id), buff);
+ 		ARTlog(&Data, ART_REJECT, buff);
+ 		ARTreject(buff, article);
+ 		return buff;
+ 	    }
+ 	} else {
+ 	    /* the filter failed: complain and then turn off filtering */
+ 	    syslog(L_ERROR, "TCL proc filter_news failed: %s",
+ 		   TCLInterpreter->result);
+ 	    TCLfilter(FALSE);
+ 	}
+     }
+ #endif /* defined(DO_TCL) */
+ 
      /* Stash a copy of the Newsgroups header. */
      p = HDR(_newsgroups);
      i = strlen(p);
*** orig/innd/cc.c	Thu Mar 18 13:04:22 1993
--- innd/cc.c	Tue May 31 17:48:28 1994
***************
*** 55,60 ****
--- 55,63 ----
  STATIC STRING	CCtrace();
  STATIC STRING	CCxabort();
  STATIC STRING	CCxexec();
+ #if defined(DO_TCL)
+ STATIC STRING	CCfilter();
+ #endif /* defined(DO_TCL) */
  
  STATIC char		CCpath[] = _PATH_NEWSCONTROL;
  STATIC char		**CCargv;
***************
*** 75,80 ****
--- 78,84 ----
      {	SC_CHANGEGROUP,	2, CCchgroup	},
      {	SC_CHECKFILE,	0, CCcheckfile	},
      {	SC_DROP,	1, CCdrop	},
+     {	SC_FILTER,	1, CCfilter	},
      {	SC_FLUSH,	1, CCflush	},
      {	SC_FLUSHLOGS,	0, CCflushlogs	},
      {	SC_GO,		1, CCgo		},
***************
*** 445,450 ****
--- 449,480 ----
  }
  
  
+ #if defined(DO_TCL)
+ STATIC STRING
+ CCfilter(av)
+     char	*av[];
+ {
+     char	*p;
+ 
+     switch (av[0][0]) {
+     default:
+ 	return "1 Bad flag";
+     case 'y':
+ 	if (TCLFilterActive)
+ 	    return "1 tcl filter already enabled";
+ 	TCLfilter(TRUE);
+ 	break;
+     case 'n':
+ 	if (!TCLFilterActive)
+ 	    return "1 tcl filter already disabled";
+ 	TCLfilter(FALSE);
+ 	break;
+     }
+     return NULL;
+ }
+ #endif /* defined(DO_TCL) */
+ 
+ 
  /*
  **  Flush all sites or one site.
  */
***************
*** 651,656 ****
--- 681,695 ----
  	(void)sprintf(p, "disabled %s", NNRPReason);
  	p += strlen(p);
      }
+ 
+ #if defined(DO_TCL)
+     *p++ = '\n';
+     p += strlen(strcpy(p, "Tcl filtering "));
+     if (TCLFilterActive)
+ 	p += strlen(strcpy(p, "enabled"));
+     else
+ 	p += strlen(strcpy(p, "disabled"));
+ #endif /* defined(DO_TCL) */
  	
      i = strlen(buff);
      if (CCreply.Size <= i) {
***************
*** 1026,1031 ****
--- 1065,1073 ----
  	ICDsetup(TRUE);
  	if (!ARTreadschema())
  	    return BADSCHEMA;
+ #if defined(DO_TCL)
+ 	TCLreadfilter();
+ #endif /* defined(DO_TCL) */
  	p = "all";
      }
      else if (EQ(p, "active") || EQ(p, "newsfeeds")) {
***************
*** 1043,1048 ****
--- 1085,1095 ----
  	if (!ARTreadschema())
  	    return BADSCHEMA;
      }
+ #if defined(DO_TCL)
+     else if (EQ(p, "filter.tcl")) {
+ 	TCLreadfilter();
+     }
+ #endif /* defined(DO_TCL) */
      else
  	return "1 Unknown reload type";
  
*** orig/innd/icd.c	Fri Jan 29 08:51:25 1993
--- innd/icd.c	Thu Apr 14 10:23:25 1994
***************
*** 366,372 ****
  ICDwriteactive()
  {
  #if	defined(ACT_MMAP)
!     /* No-op. */
  
  #else
  
--- 366,375 ----
  ICDwriteactive()
  {
  #if	defined(ACT_MMAP)
! #ifdef __alpha
!     if (msync((caddr_t)ICDactpointer, (size_t)ICDactsize, MS_SYNC)<0)
! 	syslog(L_NOTICE, "%s cant msync %m", LogName);
! #endif /* __alpha */
  
  #else
  
*** orig/innd/innd.c	Thu Mar 18 13:04:25 1993
--- innd/innd.c	Thu Apr 14 10:23:25 1994
***************
*** 486,491 ****
--- 486,495 ----
      ICDclose();
      HISclose();
      ARTclose();
+ #if defined(DO_TCL)
+     TCLclose();
+ #endif /* defined(DO_TCL) */
+ 
      (void)sleep(1);
      /* PROCclose(TRUE); */
      if (unlink(PID) < 0 && errno != ENOENT)
***************
*** 879,884 ****
--- 883,892 ----
  	    syslog(L_ERROR, "%s cant chmod %s %m", LogName, PID);
  	}
      }
+ 
+ #if defined(DO_TCL)
+     TCLsetup();
+ #endif /* defined(DO_TCL) */
  
      /* And away we go... */
      if (ShouldRenumber) {
*** orig/innd/innd.h	Thu Mar 18 13:04:26 1993
--- innd/innd.h	Thu Apr 14 10:23:25 1994
***************
*** 41,47 ****
  #include "libinn.h"
  #include "clibrary.h"
  #include "macros.h"
! 
  
  #define NOSITE		-1
  
--- 41,51 ----
  #include "libinn.h"
  #include "clibrary.h"
  #include "macros.h"
! #if     defined(DO_TCL)
! #include <tcl.h>
! #undef EXTERN /* TCL defines EXTERN; this undef prevents error messages 
! 	         when we define it later */
! #endif  /* defined(DO_TCL) */
  
  #define NOSITE		-1
  
***************
*** 524,526 ****
--- 528,562 ----
  extern void		SITEprocdied();
  extern void		SITEsend();
  extern void		SITEwrite();
+ 
+ /*
+ **  TCL Globals
+ */
+ 
+ #if defined(DO_TCL)
+ extern Tcl_Interp      *TCLInterpreter;
+ extern BOOL            TCLFilterActive;
+ extern BUFFER          *TCLCurrArticle;
+ extern ARTDATA         *TCLCurrData;
+ #endif /* defined(DO_TCL) */
+ 
+ 
+ /*
+ **  TCL Functions
+ */
+ 
+ #if defined(DO_TCL)
+ extern void            TCLfilter();
+ extern void            TCLreadfilter();
+ extern void            TCLsetup();
+ extern void            TCLclose();
+ #endif /* defined(DO_TCL) */
+ 
+ 
+ #ifdef __alpha
+ typedef unsigned int u_int32_t;
+ typedef int int32_t;
+ #else
+ typedef unsigned long u_int32_t;
+ typedef long int32_t;
+ #endif
*** orig/innd/rc.c	Thu Mar 18 13:04:31 1993
--- innd/rc.c	Thu Apr 14 10:23:25 1994
***************
*** 295,301 ****
  	}
  
  	/* Was host specified as as dotted quad? */
! 	if ((rp->Address.s_addr = inet_addr(buff)) != (unsigned long)-1) {
  	    rp->Name = COPY(buff);
  	    rp->Password = COPY(pass);
  	    rp->Patterns = pats ? CommaSplit(COPY(pats)) : NULL;
--- 295,302 ----
  	}
  
  	/* Was host specified as as dotted quad? */
! 	if ((rp->Address.s_addr = inet_addr(buff)) != (u_int32_t)-1) {
! 	  syslog(LOG_NOTICE, "think it's a dotquad");
  	    rp->Name = COPY(buff);
  	    rp->Password = COPY(pass);
  	    rp->Patterns = pats ? CommaSplit(COPY(pats)) : NULL;
***************
*** 485,491 ****
      AmSlave = master != NULL;
      if (AmSlave) {
  	/* Dotted quad? */
! 	if ((a.s_addr = inet_addr(master)) != (unsigned long)-1) {
  	    RCnmaster = 1;
  	    RCmaster = NEW(INADDR, 1);
  	    COPYADDR(&RCmaster[0], &a);
--- 486,492 ----
      AmSlave = master != NULL;
      if (AmSlave) {
  	/* Dotted quad? */
! 	if ((a.s_addr = inet_addr(master)) != (u_int32_t)-1) {
  	    RCnmaster = 1;
  	    RCmaster = NEW(INADDR, 1);
  	    COPYADDR(&RCmaster[0], &a);
*** orig/innd/tcl.c	Tue May 31 17:52:38 1994
--- innd/tcl.c	Thu Apr 14 10:23:25 1994
***************
*** 0 ****
--- 1,196 ----
+ /*  $Revision$
+ **
+ **  Support for TCL things
+ **
+ **  By Bob Heiney, Network Systems Laboratory, Digital Equipment Corporation
+ */
+ 
+ #include "innd.h"
+ 
+ #if     defined(DO_TCL)
+ 
+ Tcl_Interp       *TCLInterpreter;
+ BOOL             TCLFilterActive;
+ BUFFER           *TCLCurrArticle;
+ ARTDATA          *TCLCurrData;
+ 
+ STATIC char      TCLSTARTUP[] = _PATH_TCL_STARTUP;
+ STATIC char      TCLFILTER[] = _PATH_TCL_FILTER;
+ 
+ 
+ void
+ TCLfilter(value)
+     BOOL value;
+ {
+     TCLFilterActive=value;
+ 
+     syslog(L_NOTICE, "%s tcl filtering %s", LogName,
+ 	   TCLFilterActive ? "enabled" : "disabled");
+ }
+ 
+ 
+ void
+ TCLreadfilter()
+ {
+     int code;
+     
+     /* do before reload callback */
+     code = Tcl_Eval(TCLInterpreter, "filter_before_reload");
+     if (code != TCL_OK) {
+ 	if (strcmp(TCLInterpreter->result,
+ 		   "invalid command name: \"filter_before_reload\"")!=0)
+ 	    syslog(L_ERROR, "%s Tcl filter_before_reload failed: %s",
+ 		   LogName, TCLInterpreter->result);
+     }
+ 
+     /* read the filter file */
+     code = Tcl_EvalFile(TCLInterpreter, TCLFILTER);
+     if (code != TCL_OK) {
+ 	syslog(L_ERROR, "%s cant evaluate Tcl filter file: %s", LogName,
+ 	       TCLInterpreter->result);
+ 	TCLfilter(FALSE);
+     }
+ 
+     /* do the after callback, discarding any errors */
+     code = Tcl_Eval(TCLInterpreter, "filter_after_reload");
+     if (code != TCL_OK) {
+ 	if (strcmp(TCLInterpreter->result,
+ 		   "invalid command name: \"filter_after_reload\"")!=0)
+ 	    syslog(L_ERROR, "%s Tcl filter_after_reload failed: %s",
+ 		   LogName, TCLInterpreter->result);
+     }
+ }
+ 
+ 
+ /* makeCheckSum
+  *
+  * Compute a checksum. This function does a one's-complement addition
+  * of a series of 32-bit words. "buflen" is in bytes, not words. This is 
+  * hard because the number of bits with which our machine can do arithmetic
+  * is the same as the size of the checksum being created, but our hardware
+  * is 2's-complement and C has no way to check for integer overflow.
+  *
+  * Note that the checksum is returned in network byte order and not host
+  * byte order; this makes it suitable for putting into packets and for
+  * comparing with what is found in packets.
+  */
+ 
+ static
+ u_int32_t
+ makechecksum(sumbuf, buflen)
+      u_char *sumbuf;
+      int buflen;
+ {
+     register u_char *buf = (u_char *)sumbuf;
+     register int32_t len = buflen;
+     register int32_t sum;
+     u_int32_t bwordl,bwordr,bword,suml,sumr;
+     int rmdr;
+     u_char tbuf[4];
+     u_char *ptbuf;
+ 
+     suml = 0; sumr = 0;
+ 
+     len = len/4;
+     rmdr = buflen - 4*len;
+ 
+     while (len-- > 0) {
+ 	bwordr = (buf[3] & 0xFF)
+ 	    + ((buf[2] & 0xFF) << 8);
+ 	bwordl = (buf[1] & 0xFF)
+ 	    + ((buf[0] & 0xFF) << 8);
+ 	bword = ( bwordl << 16) | bwordr;
+ 	bword = ntohl(bword);
+ 	bwordl = (bword >> 16) & 0xFFFF;
+ 	bwordr = bword & 0xFFFF;
+ 	sumr += bwordr;
+ 	if (sumr & ~0xFFFF) {
+ 	    sumr &= 0xFFFF;
+ 	    suml++;
+ 	}
+ 	suml += bwordl;
+ 	if (suml & ~0xFFFF) {
+ 	    suml &= 0xFFFF;
+ 	    sumr++;
+ 	}
+ 	buf += 4;
+     }
+     /* if buffer size was not an even multiple of 4 bytes,
+        we have work to do */
+     if (rmdr > 0) {
+ 	tbuf[3] = 0; tbuf[2] = 0; tbuf[1] = 0;
+ 	/* tbuf[0] will always be copied into, and tbuf[3] will
+ 	 * always be zero (else this would not be a remainder)
+ 	 */
+ 	ptbuf = tbuf;
+ 	while (rmdr--) *ptbuf++ = *buf++;
+ 	bwordr = (tbuf[3] & 0xFF)
+ 	    + ((tbuf[2] & 0xFF) << 8);
+ 	bwordl = (tbuf[1] & 0xFF)
+ 	    + ((tbuf[0] & 0xFF) << 8);
+ 	bword = ( bwordl << 16) | bwordr;
+ 	bword = ntohl(bword);
+ 	bwordl = (bword >> 16) & 0xFFFF;
+ 	bwordr = bword & 0xFFFF;
+ 	sumr += bwordr;
+ 	if (sumr & ~0xFFFF) {
+ 	    sumr &= 0xFFFF;
+ 	    suml++;
+ 	}
+ 	suml += bwordl;
+ 	if (suml & ~0xFFFF) {
+ 	    suml &= 0xFFFF;
+ 	    sumr++;
+ 	}
+     }
+     sum = htonl( (suml << 16) | sumr);
+     return (~sum);
+ }
+ 
+ 
+ int
+ TCLCksumArt(clientData, interp, argc, argv)
+      ClientData clientData;
+      Tcl_Interp *interp;
+      int argc;
+      char *argv[];
+ {
+     char buf[100];
+ 
+     sprintf(buf, "%08x",
+ 	    makechecksum(TCLCurrData->Body,
+ 			 &TCLCurrArticle->Data[TCLCurrArticle->Used] - 
+ 			 TCLCurrData->Body));
+     Tcl_SetResult(interp, buf, TCL_VOLATILE);
+     return TCL_OK;
+ }
+ 
+ 
+ void
+ TCLsetup()
+ {
+     int code;
+     
+     TCLInterpreter = Tcl_CreateInterp();
+     code = Tcl_EvalFile(TCLInterpreter, TCLSTARTUP);
+     if (code != TCL_OK) {
+ 	syslog(L_FATAL, "%s cant read Tcl startup file: %s", LogName,
+ 	       TCLInterpreter->result);
+ 	exit(1);
+     }
+ 
+     Tcl_CreateCommand(TCLInterpreter, "checksum_article", TCLCksumArt,
+ 		      NULL, NULL);
+ 
+     TCLfilter(TRUE);
+     TCLreadfilter();
+ }
+ 
+ 
+ void
+ TCLclose()
+ {
+ }
+ 
+ 
+ #endif /* defined(DO_TCL) */
