# Policy parameters: # directory is the location for the files # maxfile is the number of files allowed in the directory # maxsize is the max size for any single file. array set tempfile { maxfile 4 maxsize 65536 directory ./ } # tempfile(directory) is computed dynamically based on # the source of the script proc Tempfile_PolicyInit { slave } { global tempfile interp alias $slaveopen {} TempfileOpenAlias $slave$tempfile(directory) $tempfile(maxfile) "1.tcl" interp eval p open interp alias $slave puts {} TempfilePutsAlias $slave tempfile(maxsize) $tempfile(channels,$slave) interp alias $slaveexit {} TempfileExitAlias $slave } proc TempfileOpenAlias { slave dir maxfile name { m w } { p 0777 } } { global tempfile # remove sneaky characters regsub -all {|/:} [file tail $name] {} real set real [file join$dir$real] # Limit the number of files set files [ glob-nocomplain [file join$dir*] ] set N [ llength $files ] if { ( $N>=$maxfile ) && ( [ lsearch -exact $files$real ] <0 ) } { error "permission denied" } if [ catch { open$real$m$p } out ] { return-code error "$name: permission denied" } lappend tempfile(channels,$slave) $out interp share {} $out$slave return$out } proc TempfileExitAlias { slave } { global tempfile interp delete$slave if [info exists tempfile(channels,$slave)] { foreach out $tempfile(channels,$slave) { catch { close$out } } unset tempfile(channels,$slave) } } # See also the puts alias in Example 24–4 on page 389 proc TempfilePutsAlias { slave max chan args } { # max is the file size limit, in bytes # chan is the I/O channel # args is either a single string argument, # or the -nonewline flag plus the string. if { [ llength $args ] >2} { error "invalid arguments" } if { [ llength $args ] ==2 } { if { ![ string match -n* [ lindex $args0 ] ] } { error "invalid arguments" } set str [ lindex $args1 ] } else { set str [ lindex $args0 ]n } set size [ expr [ tell$chan ] + [ string length$str ] ] if { $size>$max } { error "File size exceeded" } else { puts -nonewline $chan$str } } safe::interpCreate p Tempfile_PolicyInit p interp eval p puts 1234
array set tempfile { maxfile 4 maxsize 65536 directory ./ } proc Tempfile_PolicyInit { slave } { global tempfile interp alias $slaveopen {} TempfileOpenAlias $slave$tempfile(directory) $tempfile(maxfile) "1.tcl" interp eval p open interp hide $slavetell interp alias $slavetell {} TempfileTellAlias $slave$tempfile(channels,$slave) interp hide $slave puts interp alias $slave puts {} TempfilePutsAlias $slave$tempfile(maxsize) $tempfile(channels,$slave) # interp alias $slave exit {} TempfileExitAlias $slave } proc TempfileOpenAlias { slave dir maxfile name { m w } { p 0777 } } { global tempfile # remove sneaky characters regsub -all {|/:} [ file tail $name ] {} real set real [ file join$dir$real ] # Limit the number of files set files [ glob-nocomplain [ file join$dir* ] ] set N [ llength $files ] if { ( $N>=$maxfile ) && ( [ lsearch -exact $files$real ] <0 ) } { error "permission denied" } if [ catch { interp invokehidden $slaveopen$real$m$p } out ] { return-code error "$name: permission denied" } lappend tempfile(channels,$slave) $out return$out } proc TempfileTellAlias { slave chan } { return [ interp invokehidden $slavetell$chan ] } proc TempfilePutsAlias { slave max chan args } { if { [ llength $args ] >2 } { error "invalid arguments" } if { [ llength $args ] ==2 } { if { ![ string match -n* [ lindex $args0 ] ] } { error "invalid arguments" } set string [lindex $args1] } else { set string [lindex $args0]n } set size [ interp invokehidden $slavetell$chan ] incr size [ string length$string ] if { $size>$max } { error "File size exceeded" } else { interp invokehidden $slave puts -nonewline $chan$string } } proc TempfileExitAlias { slave } { global tempfile interp delete$slave if [info exists tempfile(channels,$slave)] { foreach out $tempfile(channels,$slave) { catch { close$out } } unset tempfile(channels,$slave) } } safe::interpCreate p Tempfile_PolicyInit p
本例子通过在子解释器中调用隐藏的命令来实现I/O
Example 3.
# SafeAfter_PolicyInit creates a child witha safe after command proc SafeAfter_PolicyInit { slave max } { # max limits the number of outstanding after events global after interp alias $slave after {} SafeAfterAlias $slave$max interp alias $slaveexit {} SafeAfterExitAlias $slave # This is used to generate after IDs for the slave. set after(id,$slave) 0 } # SafeAfterAlias is an alias for after. It disallows after with only a time argument and no command. proc SafeAfterAlias { slave max args } { global after set argc [ llength $args ] if { $argc==0 } { error "Usage: after option args" } switch -- [ lindex $args0 ] { cancel { # A naive implementation would just eval after cancel $args but something dangerous could be hiding in args. set myid [ lindex $args1 ] if { [ info exists after(id,$slave,$myid) ] } { set id $after(id,$slave,$myid) unset after(id,$slave,$myid) after cancel $id } return"" } default { if { $argc==1 } { error "Usage: after time command args..." } if { [ llength [ array names after id,$slave,* ] ] >=$max } { error "Too many after events" } # Maintain concat semantics set command [concat [ lrange $args1 end ] ] # Compute our own id to pass the callback.
# after(id,$slave)=0
set myid after#[ incr after(id,$slave) ] set id [ after [ lindex $args0 ] [ list SafeAfterCallback $slave$myid$command ] ] set after(id,$slave,$myid) $id return$myid } } } # SafeAfterCallback is the after callback in the master. # It evaluates its command in the safe interpreter. proc SafeAfterCallback { slave myid cmd } { global after unset after(id,$slave,$myid) if [ catch { interp eval$slave$cmd } err ] { catch { interp eval$slave bgerror $error } puts $error } } # SafeAfterExitAlias is an alias for exit that does cleanup. proc SafeAfterExitAlias { slave } { global after foreach id [ array names after id,$slave,* ] { after cancel $after($id) unset after($id) } interp delete$slave } safe::interpCreate p SafeAfter_PolicyInit p 4
下面贴上几个关于safe policy的例子Example 1.# Policy parameters:# directory is the location for the files# maxfile is the number of files allowed in the directory# maxsize is the max size for any single