在 Tcl 中,如何防止变量的内容在传递给 exec 时被 shell 解释?
In Tcl, how do I prevent a variable's contents from being interpreted by the shell when passed to `exec`?
我正在维护一些旧代码,发现以下部分...
if {[catch {exec -- echo $html_email > $file} ret]} {
puts $ret
return 0
}
...由于 HTML 电子邮件的第一个字符为 <
、 即
而中断
couldn't read file "html>
<title>cama_Investigate 00000560554PONY1</title>
<style type="text/css">
...
...
...
被解释为 I/O 重定向运算符。以前这不是问题,因为我们开始发送一些 headers、 的电子邮件,例如
append html_email "Content-Type : text/html; charset=us-ascii\n"
append html_email "Content-Disposition: inline\n"
我将重写所有这些以使用 Tcl 的本机文件 I/O,所以这个问题主要是学术性的:What is the proper way to guard a variable's contents from being interpreted by the shell 当传递给 exec
?
我正在使用 Tcl 8.0.5 和 csh,但如果可能的话,我对一般答案很感兴趣。
Tcl 的 exec
很时髦,唉。它坚持将以 <
字符开头的参数解释为重定向。 (也有一些其他的,但你不太可能击中它们。)除了将数据写入临时文件并从中重定向之外,也没有好的通用解决方法。
set ctr 0
while 1 {
set filename /tmp/[pid].[incr ctr].txt
# POSIX-style flags; write-only, must create or generate error
if {[catch {open $filename {WRONLY CREAT EXCL}} f] == 0} break
}
puts $f $html_email
close $f
exec echo <$filename >$file
file delete $filename
这太复杂了!通过改变我们使用的程序,我们可以做得更好。如果我们不使用 echo
而使用 cat
,我们可以使用 exec
的 heredoc 语法:
exec cat <<$html_email >$file
因为在这种情况下,字符是通过管道直接传递的(Tcl 就是这样做的),所以出错的可能性要小得多。然而,仍然 愚蠢,因为 Tcl 完全能够直接写入文件,更便携,开销更少:
set f [open $file "w"]
puts $f $html_email
close $f
是的,这实际上是大大简化的版本,是对上面第一个示例的一般替换。让我们做一些简单的事情,这些事情显然是正确的,这样以后就不会那么令人惊讶了。
您可以间接调用预期的命令,通过 shell:
路由它
exec -- csh -c "echo '$html_email'" > $file
或
exec -- csh -c "exec echo '$html_email'" > $file
我正在维护一些旧代码,发现以下部分...
if {[catch {exec -- echo $html_email > $file} ret]} {
puts $ret
return 0
}
...由于 HTML 电子邮件的第一个字符为 <
、 即
couldn't read file "html>
<title>cama_Investigate 00000560554PONY1</title>
<style type="text/css">
...
...
...
被解释为 I/O 重定向运算符。以前这不是问题,因为我们开始发送一些 headers、 的电子邮件,例如
append html_email "Content-Type : text/html; charset=us-ascii\n"
append html_email "Content-Disposition: inline\n"
我将重写所有这些以使用 Tcl 的本机文件 I/O,所以这个问题主要是学术性的:What is the proper way to guard a variable's contents from being interpreted by the shell 当传递给 exec
?
我正在使用 Tcl 8.0.5 和 csh,但如果可能的话,我对一般答案很感兴趣。
Tcl 的 exec
很时髦,唉。它坚持将以 <
字符开头的参数解释为重定向。 (也有一些其他的,但你不太可能击中它们。)除了将数据写入临时文件并从中重定向之外,也没有好的通用解决方法。
set ctr 0
while 1 {
set filename /tmp/[pid].[incr ctr].txt
# POSIX-style flags; write-only, must create or generate error
if {[catch {open $filename {WRONLY CREAT EXCL}} f] == 0} break
}
puts $f $html_email
close $f
exec echo <$filename >$file
file delete $filename
这太复杂了!通过改变我们使用的程序,我们可以做得更好。如果我们不使用 echo
而使用 cat
,我们可以使用 exec
的 heredoc 语法:
exec cat <<$html_email >$file
因为在这种情况下,字符是通过管道直接传递的(Tcl 就是这样做的),所以出错的可能性要小得多。然而,仍然 愚蠢,因为 Tcl 完全能够直接写入文件,更便携,开销更少:
set f [open $file "w"]
puts $f $html_email
close $f
是的,这实际上是大大简化的版本,是对上面第一个示例的一般替换。让我们做一些简单的事情,这些事情显然是正确的,这样以后就不会那么令人惊讶了。
您可以间接调用预期的命令,通过 shell:
路由它exec -- csh -c "echo '$html_email'" > $file
或
exec -- csh -c "exec echo '$html_email'" > $file