2016-07-27 21 views
2

Ich Aufrechterhaltung einige alte Code und festgestellt, dass das folgende Stück ...Wie verhindere ich in Tcl, dass der Inhalt einer Variablen von der Shell interpretiert wird, wenn sie an exec übergeben wird?

if {[catch {exec -- echo $html_email > $file} ret]} { 
    puts $ret 
    return 0 
} 

... bricht aufgrund der ersten Zeichen einer HTML-E-Mail < ist, dh

couldn't read file "html> 
    <title>cama_Investigate 00000560554PONY1</title> 
    <style type="text/css"> 
    ... 
    ... 
    ... 

, die als E/A-Umleitungsoperator interpretiert wird. Zuvor war dies kein Problem, da wir die E-Mails mit einigen Headern, z. B. , z.

append html_email "Content-Type  : text/html; charset=us-ascii\n" 
append html_email "Content-Disposition: inline\n" 

Ich werde alles neu zu schreiben, diese Tcl nativen Datei zu verwenden, I/O, so ist diese Frage vor allem akademisch: Was ist der richtige Weg ist von dem Inhalt einer Variable schützen von der Shell interpretiert wurde, wenn übergeben zu exec?

Ich benutze Tcl 8.0.5 und Csh, aber ich bin interessiert an einer allgemeinen Antwort, wenn möglich.

Antwort

2

Tcl exec ist funky, leider. Es besteht darauf, ein Argument zu interpretieren, das mit einem < Zeichen als Umleitung beginnt. (Es gibt auch ein paar andere, aber Sie treffen sie etwas weniger wahrscheinlich.) Es gibt keine gute allgemeine Problemumgehung, außer dass Sie die Daten in eine temporäre Datei schreiben und von dort weiterleiten.

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 

Das ist furchtbar kompliziert! Wir können viel besser machen, indem wir das Programm ändern, das wir verwenden. Wenn stattdessen echo verwenden wir cat verwenden, können wir exec ‚s heredoc Syntax:

exec cat <<$html_email >$file 

Da in diesem Fall die Zeichen werden direkt über eine Pipeline übergeben (das ist, wie Tcl dies der Fall ist) gibt es weit weniger schief gehen. Doch es ist noch dumm da Tcl durchaus in der Lage, direkt auf Dateien zu schreiben, mehr portabel und mit weniger Aufwand:

set f [open $file "w"] 
puts $f $html_email 
close $f 

Ja, das ist eigentlich eine enorm vereinfachte Version des allgemeinen Ersatzes von dem ersten Beispiel über. Lassen Sie uns die einfachen Dinge tun, die viel offensichtlicher sind, denn dann gibt es in Zukunft weniger Überraschungen.

+0

A 'tun ... while' Schleife angebracht wäre, außer Tcl sie nicht haben nativ. Ein expliziter "Break" vereinfacht das. –

0

Sie können den beabsichtigten Befehl indirekt aufrufen, es durch ein Shell-Routing:

exec -- csh -c "echo '$html_email'" > $file 

oder

exec -- csh -c "exec echo '$html_email'" > $file 
+0

Diese sind sehr zerbrechlich, da sie nicht mit Zeichen umgehen (mehr als mäßig wahrscheinlich in HTML auftauchen), ohne zusätzliche Verarbeitung. –