TCL中的每条语句是解释执行的,但有时候我们需要对要执行的语句做一些安全性的检测。tcl中有个一很方便的命令能在当前解释器中创建一个访问受限的嵌套的(子)解释器来执行危险语句。
创建一个名为slave的解释器:interp create -safe slave
子解释器中再创建一个孙解释器:interp eval foo { interp create bar }
此命令的形式为:interp eval slave cmd args ...
在slave中执行cmd并返回其执行结果
or,
interp create {foo bar2}
这些创建的解释器本身就可以做为一个命令来执行,eg
slave eval {set a 5}
interp eval slave {set a 5}
使用 -safe可以创建一个原始的安全解释器,但使用safe Base可以创建一个方便的安全解释器,例如,使用safe Base创建的解释器中包含exit命令,但该命令已经被改写成删除该解释器了。
当创建了一个安全解释器(-safe)后,这个新创建的解释器中的某些命令是被隐藏的,也就是说,对这些隐藏命令的调用是受它的父亲控制的。
在父亲中调用子解释器中的隐藏命令的方法:interp invokehidden slave source filename
这些被隐藏的命令是:cd exec exit file glob load open pwd socket source
之所以这样设置我觉得是安全方面的原因,假设你要执行一个未经过验证的script,并且这个script中有个exit语句,这样当在子解释器中执行了exit后,整个程序就退出了,这就要求子解释器不能直接执行这些有风险的语句。
例如:当在安全的解释器中直接执行open这个隐藏命令时,
interp eval slave open 1 "r" 返回错误:invalid command name "open"
关于隐藏命令的相关调用如下:
interp expose slave cmd | 设置slave中应藏的命令cmd为非隐藏 |
interp hide slave cmd | 设置slave中的命令cmd设置为隐藏 |
interp hidden slave | 返回slave中所有的隐藏命令 |
interp invokehidden slave cmd | 在当前解释器空间中调用slave中隐藏命令cmd |
Command Aliases:Command Aliases(命令别名)是在一个解释器中的命令,并且此命令可以在其他解释器中被调用。
创建命令别名的方法: interp alias slave cmd1 target cmd2 arg1 arg2 ...
在解释器slave中创建cmd1这个命令别名,从而当slave中的cmd1被调用的时候,解释器target中的cmd2就被调用。
eg, interp alias slave exit {} interp delete slave
{}表示当前解释器空间,在slave中创建一个命令命令别名exit,当在slave中调用exit时,就在当前解释空间中调用interp delete slave来删除slave解释器。
解释器间的I/O,传递(transfer) 与 共享(share)
- I/O通道的名字在每个解释器中都是相同的。解释器操作共享的I/O通道需要相应的权限,而操作传递进来的I/O通道则默认具有调用者的权限
- I/O中的seek偏移在每个解释器中都是共享的,也就是说,当两个或者多个解释器操作同一个共享的I/O通道通道时,由于seek偏移是共享存在的,所以这些解释器可能会获得不同的结果。
- 每个I/O通道都有一个引用计数,来标识I/O通道的使用情况。与Windows中的Handle系统类似,但有一点不同,当一个父解释器传递一个I/O通道时,该I/O通道的引用计数并不改变,而共享一个I/O通道时,该I/O通道的引用计数加1。
interp share interp1 chanName interp2
在interp1与interp2中共享一个I/O通道(chanName)
interp transfer interp1 chanName interp2