interp(3tcl)

NAME
interp - 建立和操縱 Tcl 解釋器

總覽 SYNOPSIS
interp option ?arg arg ...?

描述 DESCRIPTION

這個命令建立一個或多個新的 Tcl 解釋器，並使其與建立(它們的)解釋器在相同的應用中共存。建立解釋器的解釋器叫做主解釋器(master)而新解釋器叫做從解釋器(slave)。主解釋器可以建立任意數目的從解釋器，每個從解釋器也可以自己建立增添的從解釋器而成爲它們的主解釋器，這將導致解釋器的一個等級層次(hierarchy)。

每個解釋器相對其他解釋器是獨立的: 它有給命令、過程、和全局變量的自己的名字空間。一個主解釋器可以使用叫別名(alias)的機制建立它的從解釋器與它自身間的連接。別名是在一個從解釋器中的一個命令，調用它時，導致在它的主解釋器或其他從解釋器中調用一個命令。解釋器之間的唯一其他連接是通過環境變量(env 變量)，它通常被在這個應用中的所有解釋器共享。注意給文件的名字空間(比如由 open命令返回的名字)不在解釋器之間共享。提供顯式的命令來共享文件和把到打開文件的引用從一個解釋器轉換(transfer)到另一個。

interp命令還提供對安全(safe)解釋器的支持。一個安全解釋器是一個功能被嚴格限制了的從解釋器，這樣就可以執行不可信任的腳本而不用害怕它們毀壞其他解釋器或這個應用的環境。例如，安全解釋器不能訪問所有 IO 通道建立命令和子過程建立命令。 詳情參見下面的 SAFE INTERPRETERS (安全的解釋器) 章節。未從安全的解釋器中去除有危險的功能；但是，它們是隱藏的，所以只有可信任的解釋器可以獲得到它們的訪問。隱藏命令的詳細解釋請參見下面的 HIDDEN COMMANDS (隱藏命令) 章節。可以使用別名機制來在從解釋器和它的主解釋器之間進行受保護的通信(類似於一個內核調用)。別名機制工作的詳情參見下面的 ALIAS INVOCATION (別名調用)章節。

一個限定的(qualified)解釋器的名字是一個適當的 Tcl 列表，它包含在這個解釋器層次中它的祖先的一個子集，終結於以它的直接上級(immediate)主解釋器命名的字符串。解釋器名字是相對於在其中使用它的哪個解釋器的。例如，如果 a 是當前解釋器的一個從解釋器並且它有一個從解釋器 a1，它依次有一個從解釋器 a11，在a 中 a11 的限定的名字是列表 a1 a11。

下面描述的 interp命令接受限定的解釋器名字作爲參數；命令在其中求值的解釋器總是可以作爲 {}來引用(空列表或字符串)。注意除了通過別名之外，在一個從解釋器中不可能通過名字引用一個主(祖先)解釋器。還有，沒有通過它可以引用在應用中建立的第一個解釋器的全局名字。這兩種限制的目的都是爲了安全。

INTERP 命令 COMMAND

使用 interp 命令建立、刪除、和操縱從解釋器，並在解釋器之間共享或轉換通道。依賴於 option 參數，它可以有下列一些形式:

interp alias srcPath srcCmd
    返回一個 Tcl 列表，它的元素是與叫做 srcCmd的別名有關的 targetCmd 和 args(在建立別名時指定所有這些值；在從解釋器中實際的源命令如果被重命名的話可能與 srcCmd 不同)。

interp alias srcPath srcCmd {}
    刪除在從解釋器中用 srcPath 標識的給 srcCmd 的別名。srcCmd 引用在其下建立別名的名字；如果 源命令已經被重命名，則刪除重命名後的命令。

interp alias srcPath srcCmd targetPath targetCmd ?arg arg ...?
    這個命令在一個從解釋器和其他解釋器之間建立一個別名(關於在一個從解釋器和它的主解釋器之間建立別名請參見下面的 alias 從命令)。在這個命令中，兩個從解釋器可以在調用這個命令的解釋器底下的解釋器層次中的任何位置。SrcPath和 srcCmd 標識這個別名的來源。SrcPath 是一個 Tcl 列表，它的元素選擇一個特定的解釋器。例如，“a b”標識一個解釋器 b，它是解釋器 a 的一個從解釋器，a解釋器是調用(命令)的解釋器的一個從解釋器。一個空列表指定調用這個命令的解釋器。srcCmd給出一個新命令的名字，將在源解釋器中建立它。TargetPath和 targetCmd 指定一個目標解釋器和命令，和 arg 參數，如果有的話，給 targetCmd 指定增補的參數，它們在 srcCmd 調用中指定的所有參數的前面。TargetCmd在這個調用的時候可以被取消定義(undefine)了，或者它已經存在了；它不由這個命令來建立。別名安排在源解釋器中調用給定源命令的時候在目標解釋器中調用給定目標命令。詳情參見下面的 ALIAS INVOCATION (別名調用)章節。

interp aliases ?path?
    這個命令返回給在用 path 表示的解釋器中定義的別名的所有源命令的名字一個 Tcl 列表。

interp create ?-safe? ?--? ?path?
    建立用 path 標識的一個從解釋器和叫做從命令(slave command)的一個新命令。從命令的名字是 path的最後一個成員。在其中建立新的從解釋器和從命令的解釋器由從 path 中去除最後一個成員所獲得的路徑來標識。例如，如果 path 是 a b c 則一個新的從解釋器和叫做 c的從命令建立在用路徑 a b 標識的從解釋器中。可以使用從命令先下面描述的那樣操縱新解釋器。如果省略了 path， Tcl 建立 interpx 形式的一個唯一的名字，這裏的 x是一個整數，並用於解釋器和從命令。如果指定了 -safe開關(或者主解釋器是一個安全解釋器)，新的從解釋器將建立成功能有限的一個安全解釋器；否則從解釋器將包含 Tcl 內置命令和變量的全集。使用 -- 開關來標記開關的結束；如果路徑是象 -safe 這樣的一個特殊的值的時候需要這個開關。這個命令的結果是新解釋器的名字。一個從解釋器的名字在它的主解釋器的所有從解釋器中必須是唯一的；如果在這個主解釋器中用給定名字(標識)的一個從解釋器已經存在則發生一個錯誤。

interp delete ?path ...?
    刪除用可選的 path 參數給出的零個或多個解釋器，並且對於每個解釋器，它還刪除它的所有從解釋器。這個命令還刪除給每個被刪除的解釋器的從命令。對於每個 path 參數，如果叫這個名字的解釋器不存在，這個名字將引發一個錯誤。

interp eval path arg ?arg ...?
    這個命令用與 concat命令相同的方式串聯所有的 arg 參數，接着在用 path 標識的解釋器中把結果字符串作爲一個 Tcl 腳本來求值。把這個求值的結果(如果發生錯誤的話，包括象 errorInfo和 errorCode 變量這樣的錯誤信息)返回給調用(命令)的解釋器。

interp exists path
    如果在這個主解釋器中存在用 path 指定的從解釋器則返回 1，否則返回 0。如果省略了 path，使用調用(命令)的解釋器。

interp expose path hiddenName ?exposedCmdName?
    在用 path 表示(denote)的解釋器中，使隱藏的命令 hiddenName 暴露(expose)，最終把它帶回在一個新的exposedCmdName 名字之下(目前只接受沒有任何:: 的一個全局名字空間名字)。如果有目標名字的一個暴露的命令已經存在，這個命令失敗。隱藏命令的詳情參見下面的HIDDEN COMMANDS (隱藏命令)章節。

interp hide path exposedCmdName ?hiddenCmdName?
    在用 path 表示(denote)的解釋器中，使暴露的命令 exposedCmdName 隱藏，並把它重命名成隱藏命令 hiddenCmdName，如果未給出 hiddenCmdName 則保持相同的名字。如果有目標名字的一個隱藏的命令已經存在，這個命令失敗。目前 exposedCmdName 和 hiddenCmdName二者不能不能包含名字空間限定符，否則將引發一個錯誤。即使當前名字空間不是全局名字空間，仍在全局名字空間中查找要被 interp hide隱藏的命令。這防止從解釋器通過使當前的名字空間不同於全局名字空間(的方式)，來愚弄主解釋器去隱藏錯誤的命令。隱藏命令的詳情參見下面的HIDDEN COMMANDS (隱藏命令)章節。

interp hidden path
    返回在用 path 標識的解釋器中所有隱藏命令的名字的一個列表。

interp invokehidden path ?-global? hiddenCmdName ?arg ...?
    在由 path 表示的解釋器中用提供的參數調用隱藏命令 hiddenCmdName 。對參數不(進行)替換或求值。如果存在 -global 標誌，在目標解釋器的全局層次上調用隱藏命令；否則在當前的調用框架 (frame)上調用它並且可以訪問調用框架內部和外部的局部變量。隱藏命令的詳情請參見下面的HIDDEN COMMANDS (隱藏命令)章節。

interp issafe ?path?
    如果由 path 指定的解釋器是安全的則返回 1，否則返回 0。

interp marktrusted path
    標記用 path 標識的解釋器是可信任的。不暴露隱藏命令。這個命令只能在可信任的解釋器中調用。如果由 path標識的解釋器已經是可信任的，則這個命令沒有影響。

interp share srcPath channelId destPath
    在用 srcPath 標識的解釋器和用 destPath 標識的解釋器之間導致用 channelId標識的 IO 通道變成共享的。兩個解釋器在這個 IO通道上由相同的權限。兩個解釋器必須關閉它來關閉低層的 IO 通道；在銷燬一個解釋器的時候自動關閉在這個解釋器中可訪問的 IO 通道。

interp slaves ?path?
    返回與用 path 標識的解釋器相關的所有從解釋器的名字的一個 Tcl 列表。如果省略了 path，使用調用(命令)的解釋器。

interp target path alias
    返回描述給一個別名的目標解釋器的一個 Tcl 列表。用一個解釋器路徑和源命令名指定這個別名， 就象在上面的 interp alias 中那樣。目標解釋器的名字被返回爲相對於調用(命令)的解釋器的一個解釋器路徑。如果給這個別名的目標解釋器是調用(命令)的解釋器則返回一個空列表。如果給別名的目標解釋器不是調用(命令)的解釋器或是它的後代之一則生成一個錯誤。在調用這個命令的時候目標命令不是必須定義的。

interp transfer srcPath channelId destPath
    導致用 channelId 標識的 IO 通道，在用 destPath 標識的解釋器中變成可獲得的，而在用 srcPath 標識的解釋器中變成不可獲得的。

SLAVE 命令 COMMAND

對於每個用 interp 建立的從解釋器，在主解釋器中建立名字與這個新解釋器相同的一個新 Tcl 命令。可以使用這個命令調用在這個解釋器上的各種操作。它有下面的一般形式: slave command ?arg arg ...? Slave 是解釋器的名字，command 和 args確定這個命令的具體行爲。這個命令有效形式有:

slave aliases
    返回一個 Tcl 列表，它的元素是在 slave 中的所有別名的名字。返回的名字是建立別名時使用的 srcCmd 的值(如果它們已經被重命名，則它可以同這個命令的當前的名字不相同)。

slave alias srcCmd
    返回一個 Tcl 列表，它的元素是與叫做 srcCmd 的別名相關的 targetCmd 和 args(在建立這個別名的時候指定所有這些值；在從解釋器中的實際的源命令如果被重命令則可能與 srcCmd不同)。

slave alias srcCmd {}
    在從解釋器中刪除給 srcCmd 的別名。srcCmd 參照在其下建立別名的那個名字；如果源命令已經被重命名，則刪除重命名後的命令。

slave alias srcCmd targetCmd ?arg ..?
    建立一個別名，當在slave 中調用 srcCmd 的時候, 在主解釋器中調用 targetCmd 。把 arg 參數作爲補充的參數傳遞給 targetCmd ，這些參數在 srcCmd 的調用中傳遞的任何參數之前。詳情參見下面的ALIAS INVOCATION (別名調用)章節。

slave eval arg ?arg ..?
    這個命令用與 concat 命令相同的方式串聯所有的 arg 參數，接着在 slave 中把結果字符串作爲一個 Tcl 腳本來求值。把這個求值的結果(如果有錯誤發生，包括象 errorInfo 和 errorCode 變量這樣的錯誤信息)返回給調用(命令)的解釋器。

slave expose hiddenName ?exposedCmdName?
    這個命令暴露在 slave 的隱藏的命令 hiddenName，最終把它帶回在一個新的exposedCmdName 名字之下(目前只接受沒有任何:: 的一個全局名字空間名字)。如果有目標名字的一個暴露的命令已經存在，這個命令失敗。隱藏命令的詳情參見下面的HIDDEN COMMANDS (隱藏命令)章節。

slave hide exposedCmdName ?hiddenCmdName?
    這個命令隱藏在從解釋器中暴露的命令 exposedCmdName，並把它重命名成隱藏命令 hiddenCmdName，如果未給出hiddenCmdName 則保持相同的名字。如果有目標名字的一個隱藏的命令已經存在，這個命令失敗。目前 exposedCmdName和 hiddenCmdName二者不能不能包含名字空間限定符，否則將引發一個錯誤。即使當前名字空間不是全局名字空間，仍在全局名字空間中查找要被隱藏的命令。這防止從解釋器通過使當前的名字空間不同於全局名字空間(的方式)，來愚弄主解釋器去隱藏錯誤的命令。隱藏命令的詳情參見下面的HIDDEN COMMANDS (隱藏命令)章節。

slave hidden
    返回在 slave 中所有隱藏的名字的一個列表。

slave invokehidden ?-global hiddenName ?arg ..?
    這個命令在 slave 中用提供的參數調用隱藏的命令 hiddenName。對這些參數不進行求值或替換。如果給出了 -global標誌，則在這個從解釋器的全局層次上調用這個命令；否則在當前調用框架上調用它並可訪問這個調用框架內部或外部的局部變量。隱藏命令的詳情參見下面的HIDDEN COMMANDS (隱藏命令)章節。

slave issafe
    如果從解釋器是安全的則返回 1，否則返回 0。

slave marktrusted
    標記從解釋器爲可以信任的。只可以被可信任的解釋器調用。這個命令不暴露在這個從解釋器中的任何隱含命令。如果這個命令已經是可以信任的了，則這個命令沒有影響。

安全解釋器 SAFE INTERPRETERS

一個安全解釋器是一個功能受限制的解釋器，所以執行從最惡毒的敵人那裏來的任意腳本都是安全的而不用害怕這個腳本毀壞包圍它的(enclosing)應用或你的計算環境的其餘部分。要使一個解釋器安全，要從這個解釋器中刪除特定的命令和變量。例如，刪除在磁盤上建立文件的命令，和刪除exec命令，因爲它可通過子進程導致破壞。通過建立到主解釋器的別名，它小心的檢查它們的參數並提供對設施的一個安全子集的受限制的訪問，可以提供對這些設施的有限的訪問。例如，在一個特定的子目錄中允許文件建立，和允許對仔細選擇的和一個固定的程序的集合的子進程調用。

通過給 interp create 命令指定 -safe開關來建立一個安全的解釋器。進而，一個安全解釋器建立的任何從解釋器都是安全的。

建立的安全解釋器準確的有下列的內置的命令集:
after    append    array    binary
break    case    catch    clock
close    concat    continue    eof
error    eval    expr    fblocked
fcopy    fileevent    flush    for
foreach    format    gets    global
history    if    incr    info
interp    join    lappend    lindex
linsert    list    llength    lrange
lreplace    lsearch    lsort    namespace
package    pid    proc    puts
read    regexp    regsub    rename
return    scan    seek    set
split    string    subst    switch
tell    trace    unset    update
uplevel    upvar    variable    vwait
while interp create 建立一個安全解釋器時下列命令是隱藏的:
cd    exec    exit    fconfigure
file    glob    load    open
pwd    socket    source    vwait
以後這些命令可以作爲 Tcl 過程或別名來重新建立，或用 interp expose暴露出來。

除此之外，在一個安全解釋器中不存在 env變量，所以不能同其他解釋器共享環境變量。env 變量可能造成一次安全冒險，因爲用戶可能在某個環境變量中存儲敏感信息。例如，PGP 手冊建議在環境變量 PGPPASS 中存儲 PGP 私有密鑰。讓不可信任代碼可以在安全解釋器中訪問這個變量將招致一次安全冒險。

如果擴展被裝載到安全解釋器中，它們也可以限制它們自己功能來排除不安全的命令。對擴展的安全性的管理的討論參見Safe-Tcl 和 load Tcl 命令的手冊條目。

別名調用 ALIAS INVOCATION

精心的設計了別名機制，所以在安全的從解釋器中執行不可信任的腳本是安全的而別名的目標是一個可信任的主解釋器。最保證安全性的最重要的事情是確保從從解釋器傳遞到主解釋器的信息在主解釋器中永不被求值或替換；如果這種情況發生了，它將開啓在從解釋器中的某個邪惡的腳本來在主解釋器中調用任意函數，這將危及安全。

當從解釋器中調用一個別名的源(命令)的時候，在分析這個命令時進行常規的 Tcl 替換。在源解釋器中完成這些替換，就象對在這個解釋器中的調用的其他命令一樣。源命令的命令過程接受它的參數並把它們與給這個別名的 targetCmd和 args 融合起來建立一個新的參數數組。如果 srcCmd的字是``srcCmd arg1 arg2 ... argN''，則新的字集將是``targetCmd arg arg ... arg arg1 arg2 ... argN''。這裏的 targetCmd和 args 是在建立別名的時候提供的值。接着用 TargetCmd來在目標解釋器中定位(locate)一個命令過程，並且用新的參數集來調用這個命令過程。如果在目標解釋器中沒有叫做 targetCmd 的命令則發生一個錯誤。在這個字上不進行補充的替換:不通過常規的 Tcl 求值機制，直接調用目標命令過程。所以在每個字上精確的進行一次替換: 在分析建立這個別名的命令的時候替換 targetCmd 和 args，當在源解釋器中分析這個別名的源命令的時候替換 arg1 - argN。

在安全解釋器中給別名寫 targetCmds 的時候，給它的參數永遠不被求值或替換是非常重要的，因爲這將提供一種逃逸機制，使從解釋器可以執行在主解釋器中的任意代碼。這將危及系統的安全。

隱藏命令 HIDDEN COMMANDS

安全解釋器嚴重的限制了在其中執行的 Tcl 程序可獲得的功能。允許不可信任的 Tcl 程序訪問這些功能是不安全的，因爲它們可以在這個環境中被用於各種攻擊。但是，有時在安全解釋器的上下文中有使用危險的功能的合理需要。例如，有時一個程序必須 source 到解釋器中。另一個例子是 Tk，在這裏窗口被綁定到與一個特定解釋器關聯的窗口層次當中；一些潛在的危險函數，比如窗口管理，必須在這個解釋器上下文中的那些窗口上進行。

interp 命令提供了對這個問題的一種隱藏命令形式的解決方案。不是從安全解釋器中整個的刪除危險的命令，而是隱藏這些命令，所以它們變成對在這個解釋器中執行的 Tcl 腳本是不可獲得的。但是，這個安全解釋器的任何可信任的祖先可以使用 interp invoke，在這個安全解釋器的上下文中，調用這些隱藏命令。隱藏命令和暴露命令駐留在分開的名字空間中。在一個解釋器中可以定義叫相同名字的隱藏命令和暴露命令。

在別名調用期間，在主解釋器中調用的過程體中可以調用在從解釋器中的隱藏命令。例如，在一個從解釋器中可以給 source 建立一個別名。當在這個從解釋器中調用它的時候，調用在主解釋器中的一個過程來檢查這個操作是否是允許的(比如，是否允許這個從解釋器訪問的它要求source 的文件)。接着這個過程在從解釋器中調用隱藏的 source命令來實際裝載(source)這個文件的內容。注意在從解釋器中存在來着兩個叫 source 的命令: 別名和隱藏命令。

因爲一個主解釋器可以把調用一個隱藏命令作爲處理一個別名調用的一部分，必須非常小心的避免對通過別名調用傳遞來的任何參數進行求值。否則，惡意的從解釋器可以導致一個可信任的代表它們來執行危險的命令。這個主題的完整討論參見ALIAS INVOCATION (別名調用)章節。要避免這個問題，對 interp invokehidden的參數不要進行替換或求值。

不允許安全解釋器調用它自身中或它後代中的隱藏命令。這防止安全從解釋器訪問在自身中或它們的後代中的隱藏命令。

一個可信任的解釋器可以使用 interp expose和 interp hide 來操縱一個解釋器中的隱藏命令的集合。interp expose 命令把在用 path 標識的解釋器中一個隱藏命令移動到暴露命令的集合中，在這個過程中可能重命名這個命令。如果叫目標名字的一個暴露的命令已經存在，這個操作失敗。類似的，interp hide 把在這個解釋器中的一個暴露命令移動到隱藏命令的集合中。不允許安全解釋器在它自身中或它的後代中的隱藏命令和暴露命令的集合之間移動命令。

目前，隱藏命令的名字不能包含名字空間限定符，並且在你可以隱藏它之前必須首先把在一個名字空間中的命令重命令到全局名字空中。在全局名字空間中查找要被 interp hide 隱藏的命令。這防止從解釋器通過使當前的名字空間不同於全局名字空間(的方式)，來愚弄主解釋器去隱藏錯誤的命令。

感謝 CREDITS

這個機制基於由 Nathaniel Borenstein 和 Marshall Rose 實現的 Safe-Tcl 原型。

參見 SEE ALSO
load(n), safe(n), Tcl_CreateSlave(3)

關鍵字 KEYWORDS
alias, master interpreter, safe interpreter, slave interpreter

[中文版維護人]
寒蟬退士

[中文版最新更新]
2001/10/09

《中國 Linux 論壇 man 手冊頁翻譯計劃》:
http://cmpp.linuxforum.net

跋
本頁面中文版由中文 man 手冊頁計劃提供。
中文 man 手冊頁計劃：https://github.com/man-pages-zh/manpages-zh