5

proc f1 proc f2 および proc f3 を定義したとします。ここで、TCL インタープリターを作成し、proc f1 proc f2 および proc f3 のコードをそのインタープリターにソースし、f1、f2、および f3 以外のすべてのコマンドがそのインタープリター内にあるように制限します。どうすればそれができますか?

編集:

作成したインタープリター内で f1、f2、および f3 以外のコマンドが呼び出された場合、エラー メッセージが発行され、インタープリターでソース化されたコードが実行されます (同じインタープリターでソース化されたこの別のコードをソース化した後、 f1、f2、および f3 プロシージャを含むコード) を停止する必要があります。

4

2 に答える 2

9

それを完全に行うことはできません、ほとんどの目的に対して十分に類似したことを行うことができます。

通常、インタープリターでコマンド f1、f2、および f3 を作成してから、Tcl コマンドをまったく持たないサブインタープリターを作成し、そのサブインタープリターで公開したいコマンドをコマンドにエイリアスします。親で。

# First define f1-f3 in whatever way you want

# Now make the context; we'll use a safe interpreter for good measure...
set slave [interp create -safe]

# Scrub namespaces, then global vars, then commands
foreach ns [$slave eval namespace children ::] {
    $slave eval namespace delete $ns
}
foreach v [$slave eval info vars] {
    $slave eval unset $v
}
foreach cmd [$slave eval info commands] {
    # Note: we're hiding, not completely removing
    $slave hide $cmd
}

# Make the aliases for the things we want
foreach cmd {f1 f2 f3} {
    $slave alias $cmd $cmd
}

# And evaluate the untrusted script in it
catch {$slave invokehidden source $theScript}

# Finally, kill the untrusted interpreter
interp delete $slave
于 2012-05-08T16:59:44.207 に答える
2

これが簡単な解決策です。入力を 1 行ずつ読み取ります。最初のトークンが f1、f2、または f3 の場合は、コマンドを実行し、Control+を押すCか入力exitしてループを終了します。

proc f1 {args} { puts "f1:$args" }
proc f2 {args} { puts "f2:$args" }
proc f3 {args} { puts "f3:$args" }

while 1 {
    puts -nonewline ">"
    flush stdout
    gets stdin line
    set firstToken [lindex $line 0]
    if {[lsearch {f1 f2 f3 exit} $firstToken] != -1} {
        eval $line
    }
}

このソリューションにはいくつかの問題があります。

  1. Eval は危険と見なされます
  2. 編集機能はあまりありません。工夫して tclreadline パッケージを使用することをお勧めします。

これらの欠点にもかかわらず、ソリューションの実装は非常に簡単です。

于 2012-05-08T20:09:24.000 に答える