Fossil SCM

Add 'tclIsSafe' and 'tclMakeSafe' commands to the Tcl integration subsystem.

mistachkin 2015-07-11 23:13 trunk
Commit 501f35e50a8bdc0e36188beb560f4d6c9348bb0a
+101 -8
--- src/th_tcl.c
+++ src/th_tcl.c
@@ -439,12 +439,12 @@
439439
440440
/*
441441
** TH1 command: tclEval arg ?arg ...?
442442
**
443443
** Evaluates the Tcl script and returns its result verbatim. If a Tcl script
444
-** error is generated, it will be transformed into a TH1 script error. A Tcl
445
-** interpreter will be created automatically if it has not been already.
444
+** error is generated, it will be transformed into a TH1 script error. The
445
+** Tcl interpreter will be created automatically if it has not been already.
446446
*/
447447
static int tclEval_command(
448448
Th_Interp *interp,
449449
void *ctx,
450450
int argc,
@@ -498,11 +498,12 @@
498498
/*
499499
** TH1 command: tclExpr arg ?arg ...?
500500
**
501501
** Evaluates the Tcl expression and returns its result verbatim. If a Tcl
502502
** script error is generated, it will be transformed into a TH1 script error.
503
-** A Tcl interpreter will be created automatically if it has not been already.
503
+** The Tcl interpreter will be created automatically if it has not been
504
+** already.
504505
*/
505506
static int tclExpr_command(
506507
Th_Interp *interp,
507508
void *ctx,
508509
int argc,
@@ -563,12 +564,12 @@
563564
564565
/*
565566
** TH1 command: tclInvoke command ?arg ...?
566567
**
567568
** Invokes the Tcl command using the supplied arguments. No additional
568
-** substitutions are performed on the arguments. A Tcl interpreter will
569
-** be created automatically if it has not been already.
569
+** substitutions are performed on the arguments. The Tcl interpreter
570
+** will be created automatically if it has not been already.
570571
*/
571572
static int tclInvoke_command(
572573
Th_Interp *interp,
573574
void *ctx,
574575
int argc,
@@ -633,10 +634,100 @@
633634
Tcl_Release((ClientData)tclInterp);
634635
rc = notifyPreOrPostEval(1, interp, ctx, argc, argv, argl,
635636
getTh1ReturnCode(rc));
636637
return rc;
637638
}
639
+
640
+/*
641
+** TH1 command: tclIsSafe
642
+**
643
+** Returns non-zero if the Tcl interpreter is "safe". The Tcl interpreter
644
+** will be created automatically if it has not been already.
645
+*/
646
+static int tclIsSafe_command(
647
+ Th_Interp *interp,
648
+ void *ctx,
649
+ int argc,
650
+ const char **argv,
651
+ int *argl
652
+){
653
+ Tcl_Interp *tclInterp;
654
+
655
+ if( createTclInterp(interp, ctx)!=TH_OK ){
656
+ return TH_ERROR;
657
+ }
658
+ if( argc!=1 ){
659
+ return Th_WrongNumArgs(interp, "tclIsSafe");
660
+ }
661
+ tclInterp = GET_CTX_TCL_INTERP(ctx);
662
+ if( !tclInterp || Tcl_InterpDeleted(tclInterp) ){
663
+ Th_ErrorMessage(interp, "invalid Tcl interpreter", (const char *)"", 0);
664
+ return TH_ERROR;
665
+ }
666
+ Th_SetResultInt(interp, Tcl_IsSafe(tclInterp));
667
+ return TH_OK;
668
+}
669
+
670
+/*
671
+** TH1 command: tclMakeSafe
672
+**
673
+** Forces the Tcl interpreter into "safe" mode by removing all "unsafe"
674
+** commands and variables. This operation cannot be undone. The Tcl
675
+** interpreter will remain "safe" until the process terminates.
676
+*/
677
+static int tclMakeSafe_command(
678
+ Th_Interp *interp,
679
+ void *ctx,
680
+ int argc,
681
+ const char **argv,
682
+ int *argl
683
+){
684
+ static int registerChans = 1;
685
+ Tcl_Interp *tclInterp;
686
+ int rc = TH_OK;
687
+
688
+ if( createTclInterp(interp, ctx)!=TH_OK ){
689
+ return TH_ERROR;
690
+ }
691
+ if( argc!=1 ){
692
+ return Th_WrongNumArgs(interp, "tclMakeSafe");
693
+ }
694
+ tclInterp = GET_CTX_TCL_INTERP(ctx);
695
+ if( !tclInterp || Tcl_InterpDeleted(tclInterp) ){
696
+ Th_ErrorMessage(interp, "invalid Tcl interpreter", (const char *)"", 0);
697
+ return TH_ERROR;
698
+ }
699
+ if( Tcl_IsSafe(tclInterp) ){
700
+ Th_ErrorMessage(interp,
701
+ "Tcl interpreter is already 'safe'", (const char *)"", 0);
702
+ return TH_ERROR;
703
+ }
704
+ if( registerChans ){
705
+ /*
706
+ ** HACK: Prevent the call to Tcl_MakeSafe() from actually closing the
707
+ ** standard channels instead of simply unregistering them from
708
+ ** the Tcl interpreter. This should only need to be done once
709
+ ** per thread (process?).
710
+ */
711
+ registerChans = 0;
712
+ Tcl_RegisterChannel(NULL, Tcl_GetStdChannel(TCL_STDIN));
713
+ Tcl_RegisterChannel(NULL, Tcl_GetStdChannel(TCL_STDOUT));
714
+ Tcl_RegisterChannel(NULL, Tcl_GetStdChannel(TCL_STDERR));
715
+ }
716
+ Tcl_Preserve((ClientData)tclInterp);
717
+ if( Tcl_MakeSafe(tclInterp)!=TCL_OK ){
718
+ int nResult;
719
+ const char *zResult = getTclResult(tclInterp, &nResult);
720
+ Th_ErrorMessage(interp,
721
+ "could not make Tcl interpreter 'safe':", zResult, nResult);
722
+ rc = TH_ERROR;
723
+ }else{
724
+ Th_SetResult(interp, 0, 0);
725
+ }
726
+ Tcl_Release((ClientData)tclInterp);
727
+ return rc;
728
+}
638729
639730
/*
640731
** Tcl command: th1Eval arg
641732
**
642733
** Evaluates the TH1 script and returns its result verbatim. If a TH1 script
@@ -709,13 +800,15 @@
709800
static struct _Command {
710801
const char *zName;
711802
Th_CommandProc xProc;
712803
void *pContext;
713804
} aCommand[] = {
714
- {"tclEval", tclEval_command, 0},
715
- {"tclExpr", tclExpr_command, 0},
716
- {"tclInvoke", tclInvoke_command, 0},
805
+ {"tclEval", tclEval_command, 0},
806
+ {"tclExpr", tclExpr_command, 0},
807
+ {"tclInvoke", tclInvoke_command, 0},
808
+ {"tclIsSafe", tclIsSafe_command, 0},
809
+ {"tclMakeSafe", tclMakeSafe_command, 0},
717810
{0, 0, 0}
718811
};
719812
720813
/*
721814
** Called if the Tcl interpreter is deleted. Removes the Tcl integration
722815
--- src/th_tcl.c
+++ src/th_tcl.c
@@ -439,12 +439,12 @@
439
440 /*
441 ** TH1 command: tclEval arg ?arg ...?
442 **
443 ** Evaluates the Tcl script and returns its result verbatim. If a Tcl script
444 ** error is generated, it will be transformed into a TH1 script error. A Tcl
445 ** interpreter will be created automatically if it has not been already.
446 */
447 static int tclEval_command(
448 Th_Interp *interp,
449 void *ctx,
450 int argc,
@@ -498,11 +498,12 @@
498 /*
499 ** TH1 command: tclExpr arg ?arg ...?
500 **
501 ** Evaluates the Tcl expression and returns its result verbatim. If a Tcl
502 ** script error is generated, it will be transformed into a TH1 script error.
503 ** A Tcl interpreter will be created automatically if it has not been already.
 
504 */
505 static int tclExpr_command(
506 Th_Interp *interp,
507 void *ctx,
508 int argc,
@@ -563,12 +564,12 @@
563
564 /*
565 ** TH1 command: tclInvoke command ?arg ...?
566 **
567 ** Invokes the Tcl command using the supplied arguments. No additional
568 ** substitutions are performed on the arguments. A Tcl interpreter will
569 ** be created automatically if it has not been already.
570 */
571 static int tclInvoke_command(
572 Th_Interp *interp,
573 void *ctx,
574 int argc,
@@ -633,10 +634,100 @@
633 Tcl_Release((ClientData)tclInterp);
634 rc = notifyPreOrPostEval(1, interp, ctx, argc, argv, argl,
635 getTh1ReturnCode(rc));
636 return rc;
637 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
638
639 /*
640 ** Tcl command: th1Eval arg
641 **
642 ** Evaluates the TH1 script and returns its result verbatim. If a TH1 script
@@ -709,13 +800,15 @@
709 static struct _Command {
710 const char *zName;
711 Th_CommandProc xProc;
712 void *pContext;
713 } aCommand[] = {
714 {"tclEval", tclEval_command, 0},
715 {"tclExpr", tclExpr_command, 0},
716 {"tclInvoke", tclInvoke_command, 0},
 
 
717 {0, 0, 0}
718 };
719
720 /*
721 ** Called if the Tcl interpreter is deleted. Removes the Tcl integration
722
--- src/th_tcl.c
+++ src/th_tcl.c
@@ -439,12 +439,12 @@
439
440 /*
441 ** TH1 command: tclEval arg ?arg ...?
442 **
443 ** Evaluates the Tcl script and returns its result verbatim. If a Tcl script
444 ** error is generated, it will be transformed into a TH1 script error. The
445 ** Tcl interpreter will be created automatically if it has not been already.
446 */
447 static int tclEval_command(
448 Th_Interp *interp,
449 void *ctx,
450 int argc,
@@ -498,11 +498,12 @@
498 /*
499 ** TH1 command: tclExpr arg ?arg ...?
500 **
501 ** Evaluates the Tcl expression and returns its result verbatim. If a Tcl
502 ** script error is generated, it will be transformed into a TH1 script error.
503 ** The Tcl interpreter will be created automatically if it has not been
504 ** already.
505 */
506 static int tclExpr_command(
507 Th_Interp *interp,
508 void *ctx,
509 int argc,
@@ -563,12 +564,12 @@
564
565 /*
566 ** TH1 command: tclInvoke command ?arg ...?
567 **
568 ** Invokes the Tcl command using the supplied arguments. No additional
569 ** substitutions are performed on the arguments. The Tcl interpreter
570 ** will be created automatically if it has not been already.
571 */
572 static int tclInvoke_command(
573 Th_Interp *interp,
574 void *ctx,
575 int argc,
@@ -633,10 +634,100 @@
634 Tcl_Release((ClientData)tclInterp);
635 rc = notifyPreOrPostEval(1, interp, ctx, argc, argv, argl,
636 getTh1ReturnCode(rc));
637 return rc;
638 }
639
640 /*
641 ** TH1 command: tclIsSafe
642 **
643 ** Returns non-zero if the Tcl interpreter is "safe". The Tcl interpreter
644 ** will be created automatically if it has not been already.
645 */
646 static int tclIsSafe_command(
647 Th_Interp *interp,
648 void *ctx,
649 int argc,
650 const char **argv,
651 int *argl
652 ){
653 Tcl_Interp *tclInterp;
654
655 if( createTclInterp(interp, ctx)!=TH_OK ){
656 return TH_ERROR;
657 }
658 if( argc!=1 ){
659 return Th_WrongNumArgs(interp, "tclIsSafe");
660 }
661 tclInterp = GET_CTX_TCL_INTERP(ctx);
662 if( !tclInterp || Tcl_InterpDeleted(tclInterp) ){
663 Th_ErrorMessage(interp, "invalid Tcl interpreter", (const char *)"", 0);
664 return TH_ERROR;
665 }
666 Th_SetResultInt(interp, Tcl_IsSafe(tclInterp));
667 return TH_OK;
668 }
669
670 /*
671 ** TH1 command: tclMakeSafe
672 **
673 ** Forces the Tcl interpreter into "safe" mode by removing all "unsafe"
674 ** commands and variables. This operation cannot be undone. The Tcl
675 ** interpreter will remain "safe" until the process terminates.
676 */
677 static int tclMakeSafe_command(
678 Th_Interp *interp,
679 void *ctx,
680 int argc,
681 const char **argv,
682 int *argl
683 ){
684 static int registerChans = 1;
685 Tcl_Interp *tclInterp;
686 int rc = TH_OK;
687
688 if( createTclInterp(interp, ctx)!=TH_OK ){
689 return TH_ERROR;
690 }
691 if( argc!=1 ){
692 return Th_WrongNumArgs(interp, "tclMakeSafe");
693 }
694 tclInterp = GET_CTX_TCL_INTERP(ctx);
695 if( !tclInterp || Tcl_InterpDeleted(tclInterp) ){
696 Th_ErrorMessage(interp, "invalid Tcl interpreter", (const char *)"", 0);
697 return TH_ERROR;
698 }
699 if( Tcl_IsSafe(tclInterp) ){
700 Th_ErrorMessage(interp,
701 "Tcl interpreter is already 'safe'", (const char *)"", 0);
702 return TH_ERROR;
703 }
704 if( registerChans ){
705 /*
706 ** HACK: Prevent the call to Tcl_MakeSafe() from actually closing the
707 ** standard channels instead of simply unregistering them from
708 ** the Tcl interpreter. This should only need to be done once
709 ** per thread (process?).
710 */
711 registerChans = 0;
712 Tcl_RegisterChannel(NULL, Tcl_GetStdChannel(TCL_STDIN));
713 Tcl_RegisterChannel(NULL, Tcl_GetStdChannel(TCL_STDOUT));
714 Tcl_RegisterChannel(NULL, Tcl_GetStdChannel(TCL_STDERR));
715 }
716 Tcl_Preserve((ClientData)tclInterp);
717 if( Tcl_MakeSafe(tclInterp)!=TCL_OK ){
718 int nResult;
719 const char *zResult = getTclResult(tclInterp, &nResult);
720 Th_ErrorMessage(interp,
721 "could not make Tcl interpreter 'safe':", zResult, nResult);
722 rc = TH_ERROR;
723 }else{
724 Th_SetResult(interp, 0, 0);
725 }
726 Tcl_Release((ClientData)tclInterp);
727 return rc;
728 }
729
730 /*
731 ** Tcl command: th1Eval arg
732 **
733 ** Evaluates the TH1 script and returns its result verbatim. If a TH1 script
@@ -709,13 +800,15 @@
800 static struct _Command {
801 const char *zName;
802 Th_CommandProc xProc;
803 void *pContext;
804 } aCommand[] = {
805 {"tclEval", tclEval_command, 0},
806 {"tclExpr", tclExpr_command, 0},
807 {"tclInvoke", tclInvoke_command, 0},
808 {"tclIsSafe", tclIsSafe_command, 0},
809 {"tclMakeSafe", tclMakeSafe_command, 0},
810 {0, 0, 0}
811 };
812
813 /*
814 ** Called if the Tcl interpreter is deleted. Removes the Tcl integration
815
--- test/th1-tcl.test
+++ test/th1-tcl.test
@@ -123,5 +123,47 @@
123123
[file nativename [file join $dir th1-tcl9.txt]]
124124
125125
test th1-tcl-9 {[string trim $RESULT] eq [list [file tail $fossilexe] 3 \
126126
[list test-th-render --open-config [file nativename [file join $dir \
127127
th1-tcl9.txt]]]]}
128
+
129
+###############################################################################
130
+
131
+fossil test-th-eval "tclMakeSafe a"
132
+test th1-tcl-10 {[normalize_result] eq \
133
+{TH_ERROR: wrong # args: should be "tclMakeSafe"}}
134
+
135
+###############################################################################
136
+
137
+fossil test-th-eval "list \[tclIsSafe\] \[tclMakeSafe\] \[tclIsSafe\]"
138
+test th1-tcl-11 {[normalize_result] eq {0 {} 1}}
139
+
140
+###############################################################################
141
+
142
+fossil test-th-eval "tclMakeSafe; tclMakeSafe"
143
+test th1-tcl-12 {[normalize_result] eq \
144
+{TH_ERROR: Tcl interpreter is already 'safe'}}
145
+
146
+###############################################################################
147
+
148
+fossil test-th-eval "tclEval pwd; tclMakeSafe; tclEval pwd"
149
+test th1-tcl-13 {[normalize_result] eq {TH_ERROR: invalid command name "pwd"}}
150
+
151
+###############################################################################
152
+
153
+fossil test-th-eval "tclMakeSafe; tclExpr {0 + \[string length \[pwd\]\]}"
154
+test th1-tcl-14 {[normalize_result] eq {TH_ERROR: invalid command name "pwd"}}
155
+
156
+###############################################################################
157
+
158
+fossil test-th-eval "tclInvoke pwd; tclMakeSafe; tclInvoke pwd"
159
+test th1-tcl-15 {[normalize_result] eq {TH_ERROR: Tcl command not found: pwd}}
160
+
161
+###############################################################################
162
+
163
+fossil test-th-eval "tclMakeSafe; tclEval set x 2"
164
+test th1-tcl-16 {[normalize_result] eq {2}}
165
+
166
+###############################################################################
167
+
168
+fossil test-th-eval "tclMakeSafe; tclEval set x 2; tclEval info vars x"
169
+test th1-tcl-17 {[normalize_result] eq {x}}
128170
--- test/th1-tcl.test
+++ test/th1-tcl.test
@@ -123,5 +123,47 @@
123 [file nativename [file join $dir th1-tcl9.txt]]
124
125 test th1-tcl-9 {[string trim $RESULT] eq [list [file tail $fossilexe] 3 \
126 [list test-th-render --open-config [file nativename [file join $dir \
127 th1-tcl9.txt]]]]}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
--- test/th1-tcl.test
+++ test/th1-tcl.test
@@ -123,5 +123,47 @@
123 [file nativename [file join $dir th1-tcl9.txt]]
124
125 test th1-tcl-9 {[string trim $RESULT] eq [list [file tail $fossilexe] 3 \
126 [list test-th-render --open-config [file nativename [file join $dir \
127 th1-tcl9.txt]]]]}
128
129 ###############################################################################
130
131 fossil test-th-eval "tclMakeSafe a"
132 test th1-tcl-10 {[normalize_result] eq \
133 {TH_ERROR: wrong # args: should be "tclMakeSafe"}}
134
135 ###############################################################################
136
137 fossil test-th-eval "list \[tclIsSafe\] \[tclMakeSafe\] \[tclIsSafe\]"
138 test th1-tcl-11 {[normalize_result] eq {0 {} 1}}
139
140 ###############################################################################
141
142 fossil test-th-eval "tclMakeSafe; tclMakeSafe"
143 test th1-tcl-12 {[normalize_result] eq \
144 {TH_ERROR: Tcl interpreter is already 'safe'}}
145
146 ###############################################################################
147
148 fossil test-th-eval "tclEval pwd; tclMakeSafe; tclEval pwd"
149 test th1-tcl-13 {[normalize_result] eq {TH_ERROR: invalid command name "pwd"}}
150
151 ###############################################################################
152
153 fossil test-th-eval "tclMakeSafe; tclExpr {0 + \[string length \[pwd\]\]}"
154 test th1-tcl-14 {[normalize_result] eq {TH_ERROR: invalid command name "pwd"}}
155
156 ###############################################################################
157
158 fossil test-th-eval "tclInvoke pwd; tclMakeSafe; tclInvoke pwd"
159 test th1-tcl-15 {[normalize_result] eq {TH_ERROR: Tcl command not found: pwd}}
160
161 ###############################################################################
162
163 fossil test-th-eval "tclMakeSafe; tclEval set x 2"
164 test th1-tcl-16 {[normalize_result] eq {2}}
165
166 ###############################################################################
167
168 fossil test-th-eval "tclMakeSafe; tclEval set x 2; tclEval info vars x"
169 test th1-tcl-17 {[normalize_result] eq {x}}
170
+31 -6
--- www/th1.md
+++ www/th1.md
@@ -154,10 +154,12 @@
154154
* styleHeader
155155
* styleFooter
156156
* tclEval
157157
* tclExpr
158158
* tclInvoke
159
+ * tclIsSafe
160
+ * tclMakeSafe
159161
* tclReady
160162
* trace
161163
* stime
162164
* utime
163165
* wiki
@@ -473,34 +475,57 @@
473475
**This command requires the Tcl integration feature.**
474476
475477
* tclEval arg ?arg ...?
476478
477479
Evaluates the Tcl script and returns its result verbatim. If a Tcl script
478
-error is generated, it will be transformed into a TH1 script error. A Tcl
479
-interpreter will be created automatically if it has not been already.
480
+error is generated, it will be transformed into a TH1 script error. The
481
+Tcl interpreter will be created automatically if it has not been already.
480482
481483
<a name="tclExpr"></a>TH1 tclExpr Command
482484
-----------------------------------------
483485
484486
**This command requires the Tcl integration feature.**
485487
486488
* tclExpr arg ?arg ...?
487489
488490
Evaluates the Tcl expression and returns its result verbatim. If a Tcl
489
-script error is generated, it will be transformed into a TH1 script error.
490
-A Tcl interpreter will be created automatically if it has not been already.
491
+script error is generated, it will be transformed into a TH1 script
492
+error. The Tcl interpreter will be created automatically if it has not
493
+been already.
491494
492495
<a name="tclInvoke"></a>TH1 tclInvoke Command
493496
---------------------------------------------
494497
495498
**This command requires the Tcl integration feature.**
496499
497500
* tclInvoke command ?arg ...?
498501
499502
Invokes the Tcl command using the supplied arguments. No additional
500
-substitutions are performed on the arguments. A Tcl interpreter will
501
-be created automatically if it has not been already.
503
+substitutions are performed on the arguments. The Tcl interpreter
504
+will be created automatically if it has not been already.
505
+
506
+<a name="tclIsSafe"></a>TH1 tclIsSafe Command
507
+---------------------------------------------
508
+
509
+**This command requires the Tcl integration feature.**
510
+
511
+ * tclIsSafe
512
+
513
+Returns non-zero if the Tcl interpreter is "safe". The Tcl interpreter
514
+will be created automatically if it has not been already.
515
+
516
+<a name="tclMakeSafe"></a>TH1 tclMakeSafe Command
517
+---------------------------------------------
518
+
519
+**This command requires the Tcl integration feature.**
520
+
521
+ * tclMakeSafe
522
+
523
+Forces the Tcl interpreter into "safe" mode by removing all "unsafe"
524
+commands and variables. This operation cannot be undone. The Tcl
525
+interpreter will remain "safe" until the process terminates. The Tcl
526
+interpreter will be created automatically if it has not been already.
502527
503528
<a name="tclReady"></a>TH1 tclReady Command
504529
-------------------------------------------
505530
506531
* tclReady
507532
--- www/th1.md
+++ www/th1.md
@@ -154,10 +154,12 @@
154 * styleHeader
155 * styleFooter
156 * tclEval
157 * tclExpr
158 * tclInvoke
 
 
159 * tclReady
160 * trace
161 * stime
162 * utime
163 * wiki
@@ -473,34 +475,57 @@
473 **This command requires the Tcl integration feature.**
474
475 * tclEval arg ?arg ...?
476
477 Evaluates the Tcl script and returns its result verbatim. If a Tcl script
478 error is generated, it will be transformed into a TH1 script error. A Tcl
479 interpreter will be created automatically if it has not been already.
480
481 <a name="tclExpr"></a>TH1 tclExpr Command
482 -----------------------------------------
483
484 **This command requires the Tcl integration feature.**
485
486 * tclExpr arg ?arg ...?
487
488 Evaluates the Tcl expression and returns its result verbatim. If a Tcl
489 script error is generated, it will be transformed into a TH1 script error.
490 A Tcl interpreter will be created automatically if it has not been already.
 
491
492 <a name="tclInvoke"></a>TH1 tclInvoke Command
493 ---------------------------------------------
494
495 **This command requires the Tcl integration feature.**
496
497 * tclInvoke command ?arg ...?
498
499 Invokes the Tcl command using the supplied arguments. No additional
500 substitutions are performed on the arguments. A Tcl interpreter will
501 be created automatically if it has not been already.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
502
503 <a name="tclReady"></a>TH1 tclReady Command
504 -------------------------------------------
505
506 * tclReady
507
--- www/th1.md
+++ www/th1.md
@@ -154,10 +154,12 @@
154 * styleHeader
155 * styleFooter
156 * tclEval
157 * tclExpr
158 * tclInvoke
159 * tclIsSafe
160 * tclMakeSafe
161 * tclReady
162 * trace
163 * stime
164 * utime
165 * wiki
@@ -473,34 +475,57 @@
475 **This command requires the Tcl integration feature.**
476
477 * tclEval arg ?arg ...?
478
479 Evaluates the Tcl script and returns its result verbatim. If a Tcl script
480 error is generated, it will be transformed into a TH1 script error. The
481 Tcl interpreter will be created automatically if it has not been already.
482
483 <a name="tclExpr"></a>TH1 tclExpr Command
484 -----------------------------------------
485
486 **This command requires the Tcl integration feature.**
487
488 * tclExpr arg ?arg ...?
489
490 Evaluates the Tcl expression and returns its result verbatim. If a Tcl
491 script error is generated, it will be transformed into a TH1 script
492 error. The Tcl interpreter will be created automatically if it has not
493 been already.
494
495 <a name="tclInvoke"></a>TH1 tclInvoke Command
496 ---------------------------------------------
497
498 **This command requires the Tcl integration feature.**
499
500 * tclInvoke command ?arg ...?
501
502 Invokes the Tcl command using the supplied arguments. No additional
503 substitutions are performed on the arguments. The Tcl interpreter
504 will be created automatically if it has not been already.
505
506 <a name="tclIsSafe"></a>TH1 tclIsSafe Command
507 ---------------------------------------------
508
509 **This command requires the Tcl integration feature.**
510
511 * tclIsSafe
512
513 Returns non-zero if the Tcl interpreter is "safe". The Tcl interpreter
514 will be created automatically if it has not been already.
515
516 <a name="tclMakeSafe"></a>TH1 tclMakeSafe Command
517 ---------------------------------------------
518
519 **This command requires the Tcl integration feature.**
520
521 * tclMakeSafe
522
523 Forces the Tcl interpreter into "safe" mode by removing all "unsafe"
524 commands and variables. This operation cannot be undone. The Tcl
525 interpreter will remain "safe" until the process terminates. The Tcl
526 interpreter will be created automatically if it has not been already.
527
528 <a name="tclReady"></a>TH1 tclReady Command
529 -------------------------------------------
530
531 * tclReady
532

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button