From: Toby Newman on 29 Mar 2010 10:57 I'm quite new to tcl and expect. I am using this expect script to connect to an sshd server: http://pastebin.com/EpG5jY3f It's failing when the password begins with a ". (I have to prepend the " with a backslash at the command prompt or bash trips over it). Examples: ../expectScript.sh pass\"word 127.0.0.1 tnewman This works, the " is in the middle of the password. ../expectScript.sh \"password 127.0.0.1 tnewman This doesn't work, the " is at the start of the password. Example output: Logging in using tnewman and {"FFFFFF}...spawn ssh tnewman(a)127.0.0.1 tnewman(a)127.0.0.1's password: Permission denied, please try again. How should I be escaping this " so that it is passed along correctly? My understanding was that anything shown in {} is passed straight through by tcl. -- -Toby Add the word afiduluminag to the subject to circumvent my email filters.
From: Donald Arseneau on 30 Mar 2010 04:46 On Mar 29, 7:57 am, Toby Newman <goo...(a)asktoby.com> wrote: set password [lrange $argv 0 0] set ip [lrange $argv 1 1] set username [lrange $argv 2 2] # " ` and \ in passwords interfere with bash when the command # is entered so have to be escaped with \. # Use TCL to strip those backslashes out. regsub -all {\\\"} $password "\"" password regsub -all {\\\`} $password "\`" password regsub -all {\\\\} $password "\\" password > It's failing when the password begins with a ". (I have to prepend the > " with a backslash at the command prompt or bash trips over it). > > Examples: > > ./expectScript.sh pass\"word 127.0.0.1 tnewman > This works, the " is in the middle of the password. > > ./expectScript.sh \"password 127.0.0.1 tnewman > This doesn't work, the " is at the start of the password. > > Example output: > Logging in using tnewman and {"FFFFFF}...spawn ssh tnew...(a)127.0.0.1 > tnew...(a)127.0.0.1's password: > Permission denied, please try again. > > How should I be escaping this " so that it is passed along correctly? > My understanding was that anything shown in {} is passed straight > through by tcl. It sounds like you are confusing bash quoting with Tcl quoting. Tcl's verbatim quoting with { } is Bash's verbatim quoting with ' '. Your problem is your extraction of the arguments from the argv list to produce one-element lists rather than just strings. Change the [lrange $argv n n] to [lindex $argv n] and get rid of the regsubs. Here is what is happening. Bash does its own processing of quotes and backslash-escapes before handing arguments to Tcl, so the backslash is not in any argument when Tcl/expect receives it! Your password argument is indeed pass"word or "password, saved in element 0 of the $argv list. There should be no need to remove any backslash (no regsub lines). However, by extracting sub-lists from $argv rather than simply the items themselves, you get into trouble. When you use these little lists as if they were the items themselves you get extra formatting characters inserted by Tcl, including the \ that you thought came from the original bash argument. For some reason, when the " is at the beginning, Tcl doesn't make it list-safe using \ anymore, but by putting { } around the whole argument. Either of these would behave the same if you went on to use the value as a list (both [lindex $password 0] or [join $password {}] give the proper password string), but you use the list as if it were the password itself. You can skip the details if they are confusing, but just remember to use list operations for lists and string commands for strings, and use [lindex] to extract list items but [lrange] to extract sub-lists. Another way to get the arguments, rather than lindex is lassign $argv password ip username which works in recent Tcl, or foreach {password ip username} $argv { break } a hackish solution that has worked for many years. Donald Arseneau
From: Toby Newman on 1 Apr 2010 09:00 On 2010-03-30, Donald Arseneau <asnd(a)triumf.ca> wrote: > On Mar 29, 7:57 am, Toby Newman <goo...(a)asktoby.com> wrote: > > set password [lrange $argv 0 0] > set ip [lrange $argv 1 1] > set username [lrange $argv 2 2] > > # " ` and \ in passwords interfere with bash when the command > # is entered so have to be escaped with \. > # Use TCL to strip those backslashes out. > regsub -all {\\\"} $password "\"" password > regsub -all {\\\`} $password "\`" password > regsub -all {\\\\} $password "\\" password > >> It's failing when the password begins with a ". (I have to prepend the >> " with a backslash at the command prompt or bash trips over it). >> >> Examples: >> >> ./expectScript.sh pass\"word 127.0.0.1 tnewman >> This works, the " is in the middle of the password. >> >> ./expectScript.sh \"password 127.0.0.1 tnewman >> This doesn't work, the " is at the start of the password. >> >> Example output: >> Logging in using tnewman and {"FFFFFF}...spawn ssh tnew...(a)127.0.0.1 >> tnew...(a)127.0.0.1's password: >> Permission denied, please try again. >> >> How should I be escaping this " so that it is passed along correctly? >> My understanding was that anything shown in {} is passed straight >> through by tcl. > > It sounds like you are confusing bash quoting with Tcl quoting. > Tcl's verbatim quoting with { } is Bash's verbatim quoting with ' '. > > Your problem is your extraction of the arguments from the argv list > to produce one-element lists rather than just strings. Change the > [lrange $argv n n] to [lindex $argv n] and get rid of the regsubs. > > Here is what is happening. > > Bash does its own processing of quotes and backslash-escapes before > handing arguments to Tcl, so the backslash is not in any argument > when Tcl/expect receives it! Your password argument is indeed > pass"word or "password, saved in element 0 of the $argv list. > There should be no need to remove any backslash (no regsub lines). > > However, by extracting sub-lists from $argv rather than simply > the items themselves, you get into trouble. When you use these > little lists as if they were the items themselves you get extra > formatting characters inserted by Tcl, including the \ that you > thought came from the original bash argument. For some reason, > when the " is at the beginning, Tcl doesn't make it list-safe using > \ anymore, but by putting { } around the whole argument. Either of > these would behave the same if you went on to use the value as > a list (both [lindex $password 0] or [join $password {}] give the > proper password string), but you use the list as if it were the > password itself. > > You can skip the details if they are confusing, but just remember > to use list operations for lists and string commands for strings, > and use [lindex] to extract list items but [lrange] to extract > sub-lists. > > Another way to get the arguments, rather than lindex is > > lassign $argv password ip username > > which works in recent Tcl, or > > foreach {password ip username} $argv { break } > > a hackish solution that has worked for many years. > > Donald Arseneau Thank you for that clear solution - you helped me solve my problem. -- -Toby Add the word afiduluminag to the subject to circumvent my email filters.
|
Pages: 1 Prev: linkstaterouting algorithm Next: This piece of code is correct (exec vs open)? |