|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
package require platform |
|
namespace eval ::platform::shell {} |
|
|
|
|
|
|
|
|
|
|
|
|
|
proc ::platform::shell::generic {shell} { |
|
|
|
|
|
CHECK $shell |
|
LOCATE base out |
|
|
|
set code {} |
|
|
|
|
|
lappend code {package forget platform} |
|
|
|
lappend code [list source $base] |
|
|
|
lappend code {puts [platform::generic]} |
|
|
|
lappend code {exit 0} |
|
|
|
set arch [RUN $shell [join $code \n]] |
|
|
|
if {$out} {file delete -force $base} |
|
return $arch |
|
} |
|
|
|
|
|
|
|
proc ::platform::shell::identify {shell} { |
|
|
|
|
|
CHECK $shell |
|
LOCATE base out |
|
|
|
set code {} |
|
|
|
|
|
lappend code {package forget platform} |
|
|
|
lappend code [list source $base] |
|
|
|
lappend code {puts [platform::identify]} |
|
|
|
lappend code {exit 0} |
|
|
|
set arch [RUN $shell [join $code \n]] |
|
|
|
if {$out} {file delete -force $base} |
|
return $arch |
|
} |
|
|
|
|
|
|
|
proc ::platform::shell::platform {shell} { |
|
|
|
|
|
CHECK $shell |
|
|
|
set code {} |
|
lappend code {puts $tcl_platform(platform)} |
|
lappend code {exit 0} |
|
|
|
return [RUN $shell [join $code \n]] |
|
} |
|
|
|
|
|
|
|
|
|
proc ::platform::shell::CHECK {shell} { |
|
if {![file exists $shell]} { |
|
return -code error "Shell \"$shell\" does not exist" |
|
} |
|
if {![file executable $shell]} { |
|
return -code error "Shell \"$shell\" is not executable (permissions)" |
|
} |
|
return |
|
} |
|
|
|
proc ::platform::shell::LOCATE {bv ov} { |
|
upvar 1 $bv base $ov out |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
set pl [package ifneeded platform [package require platform]] |
|
set base [lindex $pl end] |
|
|
|
set out 0 |
|
if {[lindex [file system $base]] ne "native"} { |
|
set temp [TEMP] |
|
file copy -force $base $temp |
|
set base $temp |
|
set out 1 |
|
} |
|
return |
|
} |
|
|
|
proc ::platform::shell::RUN {shell code} { |
|
set c [TEMP] |
|
set cc [open $c w] |
|
puts $cc $code |
|
close $cc |
|
|
|
set e [TEMP] |
|
|
|
set code [catch { |
|
exec $shell $c 2> $e |
|
} res] |
|
|
|
file delete $c |
|
|
|
if {$code} { |
|
append res \n[read [set chan [open $e r]]][close $chan] |
|
file delete $e |
|
return -code error "Shell \"$shell\" is not executable ($res)" |
|
} |
|
|
|
file delete $e |
|
return $res |
|
} |
|
|
|
proc ::platform::shell::TEMP {} { |
|
set prefix platform |
|
|
|
|
|
|
|
|
|
set tmpdir [DIR] |
|
|
|
set chars "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" |
|
set nrand_chars 10 |
|
set maxtries 10 |
|
set access [list RDWR CREAT EXCL TRUNC] |
|
set permission 0600 |
|
set channel "" |
|
set checked_dir_writable 0 |
|
set mypid [pid] |
|
for {set i 0} {$i < $maxtries} {incr i} { |
|
set newname $prefix |
|
for {set j 0} {$j < $nrand_chars} {incr j} { |
|
append newname [string index $chars \ |
|
[expr {int(rand()*62)}]] |
|
} |
|
set newname [file join $tmpdir $newname] |
|
if {[file exists $newname]} { |
|
after 1 |
|
} else { |
|
if {[catch {open $newname $access $permission} channel]} { |
|
if {!$checked_dir_writable} { |
|
set dirname [file dirname $newname] |
|
if {![file writable $dirname]} { |
|
return -code error "Directory $dirname is not writable" |
|
} |
|
set checked_dir_writable 1 |
|
} |
|
} else { |
|
|
|
close $channel |
|
return [file normalize $newname] |
|
} |
|
} |
|
} |
|
if {$channel ne ""} { |
|
return -code error "Failed to open a temporary file: $channel" |
|
} else { |
|
return -code error "Failed to find an unused temporary file name" |
|
} |
|
} |
|
|
|
proc ::platform::shell::DIR {} { |
|
|
|
|
|
|
|
global tcl_platform env |
|
|
|
set attempdirs [list] |
|
|
|
foreach tmp {TMPDIR TEMP TMP} { |
|
if { [info exists env($tmp)] } { |
|
lappend attempdirs $env($tmp) |
|
} |
|
} |
|
|
|
switch $tcl_platform(platform) { |
|
windows { |
|
lappend attempdirs "C:\\TEMP" "C:\\TMP" "\\TEMP" "\\TMP" |
|
} |
|
macintosh { |
|
set tmpdir $env(TRASH_FOLDER) |
|
} |
|
default { |
|
lappend attempdirs \ |
|
[file join / tmp] \ |
|
[file join / var tmp] \ |
|
[file join / usr tmp] |
|
} |
|
} |
|
|
|
lappend attempdirs [pwd] |
|
|
|
foreach tmp $attempdirs { |
|
if { [file isdirectory $tmp] && [file writable $tmp] } { |
|
return [file normalize $tmp] |
|
} |
|
} |
|
|
|
|
|
return -code error "Unable to determine a proper directory for temporary files" |
|
} |
|
|
|
|
|
|
|
|
|
package provide platform::shell 1.1.4 |
|
|