For Programmers: Free Programming Magazines  


Home > Archive > Tcl > May 2004 > exec problems









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author exec problems
Murrgon

2004-05-17, 12:36 pm

I am trying to use TCL to work with CVS and I am having some
problems using exec to get this working. The first thing I
want to do is login to CVS, which requires the user to type
in their password. This is what I have:

set strCmdLine "$strCVSExe -d $CVSROOT -x login"
eval exec $strCmdLine

I have also tried the more direct approach:

exec $strCVSExe -d $CVSROOT -x login

This doesn't acheive what I want though. First off, CVS
doesn't print any message about loggin in, even though it
is waiting for the password. Once you type the password
in and press ENTER, the CVS login message appears, along
with the password (in '*' format) and then the script
quits.

How do I get this to work properly?
Thanks

Murrgon

Michael Schlenker

2004-05-17, 1:39 pm

Murrgon wrote:

> I am trying to use TCL to work with CVS and I am having some
> problems using exec to get this working. The first thing I
> want to do is login to CVS, which requires the user to type
> in their password. This is what I have:
>
> set strCmdLine "$strCVSExe -d $CVSROOT -x login"
> eval exec $strCmdLine
>
> I have also tried the more direct approach:
>
> exec $strCVSExe -d $CVSROOT -x login
>
> This doesn't acheive what I want though. First off, CVS
> doesn't print any message about loggin in, even though it
> is waiting for the password. Once you type the password
> in and press ENTER, the CVS login message appears, along
> with the password (in '*' format) and then the script
> quits.
>
> How do I get this to work properly?


If your on unix, use expect, it was made for this kind of jobs.

Otherwise you probably want to use a pipe with open and some fileevents
instead of exec for this task.

Michael


Cameron Laird

2004-05-17, 1:39 pm

In article <Lr4qc.3503$325.459855@news20.bellglobal.com>,
Murrgon <murrgon@hotmail.com> wrote:
>I am trying to use TCL to work with CVS and I am having some
>problems using exec to get this working. The first thing I
>want to do is login to CVS, which requires the user to type
>in their password. This is what I have:
>
>set strCmdLine "$strCVSExe -d $CVSROOT -x login"
>eval exec $strCmdLine
>
>I have also tried the more direct approach:
>
>exec $strCVSExe -d $CVSROOT -x login
>
>This doesn't acheive what I want though. First off, CVS
>doesn't print any message about loggin in, even though it
>is waiting for the password. Once you type the password
>in and press ENTER, the CVS login message appears, along
>with the password (in '*' format) and then the script
>quits.
>
>How do I get this to work properly?

Murrgon

2004-05-17, 2:34 pm

Cameron Laird wrote:
> There are a LOT of answers to this question, none
> of them nearly as simple as one would hope. Are
> you familiar with Expect? What happens when you
> type
> expect
> at you command shell prompt?


Well, first off I am running tclsh on a Win2k platform
to do this. I tried typing in 'expect' as you suggested,
but it just came up with an "invalid command name" error.

I am pretty new to TCL and I have not used Expect at all.
This may turn out to be more difficult than I originally
anticipated.

Michael Schlenker

2004-05-17, 2:34 pm

Murrgon wrote:
> Cameron Laird wrote:
>
>
>
> Well, first off I am running tclsh on a Win2k platform
> to do this. I tried typing in 'expect' as you suggested,
> but it just came up with an "invalid command name" error.
>

Thats the usual problem on win32. There is a commercial expect there,
but probably you don't need it, its mostly a convenience.

> I am pretty new to TCL and I have not used Expect at all.
> This may turn out to be more difficult than I originally
> anticipated.
>

Actually Tcl is quite good at what you want, especially with expect
available, but in general the problem isn't super trivial.

Perhaps you should take a look at tkCVS to get a hint how it is done
correctly:
http://wiki.tcl.tk/tkcvs

Michael




Murrgon

2004-05-18, 11:33 am

Michael Schlenker wrote:
> Actually Tcl is quite good at what you want, especially with expect
> available, but in general the problem isn't super trivial.
>
> Perhaps you should take a look at tkCVS to get a hint how it is done
> correctly:
> http://wiki.tcl.tk/tkcvs


Well, I took a look at tkcvs and I'd have to say that it is
fairly elaborate. It was difficult to track down exactly
where they were running the cvs commands but I found this
section in the exec.tcl source file:

set procout [open "| $command 2>@$procerr" r]
set procid [pid $procout]

fileevent $procout readable [list \
[namespace current]::out_handler $viewer $filter]
flush $procerr
fileevent $procerr readable [list [namespace current]::err_handler]

vwait [namespace current]::ExecDone

If I understand this correctly (and I'm not sure that I do), they
are using 'open' to exectute the CVS command and using 'fileevent'
to watch for and handle the output from the command. This seems
way more complicated than it needs to be. I may end up switching
to Python if this ends up being more trouble than it's worth.

Murrgon

Michael Schlenker

2004-05-18, 12:36 pm

Murrgon wrote:
> Michael Schlenker wrote:
>
>
>
> Well, I took a look at tkcvs and I'd have to say that it is
> fairly elaborate. It was difficult to track down exactly
> where they were running the cvs commands but I found this
> section in the exec.tcl source file:
>
> set procout [open "| $command 2>@$procerr" r]
> set procid [pid $procout]
>
> fileevent $procout readable [list \
> [namespace current]::out_handler $viewer $filter]
> flush $procerr
> fileevent $procerr readable [list [namespace current]::err_handler]
>
> vwait [namespace current]::ExecDone
>
> If I understand this correctly (and I'm not sure that I do), they
> are using 'open' to exectute the CVS command and using 'fileevent'
> to watch for and handle the output from the command. This seems
> way more complicated than it needs to be.

This is a typical pipe setup for tcl (rather complex looking due to the
[namespace] and [list] quoting they do).

If you just want to exec a cvs command like cvs update and do not need
to have a user enter data interactivly to the program this is total
overkill. The big benefit of this is that you can display data as it
gets output by cvs and do not experience hangs of your GUI, not only
when the whole command has finished. And you would in principle be able
to feed input into the command. (not done in the above setting, so you
may have found the typical cvs invocation, but not the login.)

Could be that you simply want bgexec from the BLT package.

> I may end up switching
> to Python if this ends up being more trouble than it's worth.

How does using Python make this any easier (unless you know Python well
already and do not know Tcl)?

Michael

Murrgon

2004-05-18, 1:32 pm

Michael Schlenker wrote:
> This is a typical pipe setup for tcl (rather complex looking due to the
> [namespace] and [list] quoting they do).
>
> If you just want to exec a cvs command like cvs update and do not need
> to have a user enter data interactivly to the program this is total
> overkill. The big benefit of this is that you can display data as it
> gets output by cvs and do not experience hangs of your GUI, not only
> when the whole command has finished. And you would in principle be able
> to feed input into the command. (not done in the above setting, so you
> may have found the typical cvs invocation, but not the login.)
>
> Could be that you simply want bgexec from the BLT package.


Well as it turns out, I managed to get it to work satisfactorly
using the stuff described here: http://wiki.tcl.tk/1039

Here is what I did:

set cmdLine [list $strCVSExe -d $CVSROOT -x login]

# Login to CVS
puts "Logging in to $CVSROOT"
puts "Please enter your password:"
catch { eval exec $cmdLine } cmdResult

I had to add my own prompt, but that wasn't to big of a problem.
The key to the problem ended up being creating the command line
arguments as a list and not a string.

>
> How does using Python make this any easier (unless you know Python well
> already and do not know Tcl)?


Python provides a specific system() call (like in C) as well as many
of the other spawn() type functions which would make this more
straightforward.

Thanks for the help

Bruce Hartweg

2004-05-18, 2:33 pm



Murrgon wrote:
> Michael Schlenker wrote:
>
>
>
> Well as it turns out, I managed to get it to work satisfactorly
> using the stuff described here: http://wiki.tcl.tk/1039
>
> Here is what I did:
>
> set cmdLine [list $strCVSExe -d $CVSROOT -x login]
>
> # Login to CVS
> puts "Logging in to $CVSROOT"
> puts "Please enter your password:"
> catch { eval exec $cmdLine } cmdResult
>
> I had to add my own prompt, but that wasn't to big of a problem.
> The key to the problem ended up being creating the command line
> arguments as a list and not a string.
>
>
>
> Python provides a specific system() call (like in C) as well as many
> of the other spawn() type functions which would make this more
> straightforward.
>


exec is like system, so I don't know if it is any harder/easier than
this is.

a couple of more items, if using list instead of a srting for your
command made a difference, then eithe strCVSExe ot CVSROOT (or both)
must contain a space.

your direct execution of exec would work in that case, which you
said worked, but didn;t provide you any feedback (as is understandable
as the exec command *returns* the output if not redirected). To
get that feedback - just add a redirect arg (or args to get error as well)

exec $strCVSExe -d $CVSROOT -x login >@ stdout 2>@ stderr

and you shoud see the output on your console.

But, the catch is still a good idea to handle error conditions.
to save the extar eval, I usually inlude the exec in the comdline
and pass it direct to eval

set cmd [list exec $strCVSExe -d $CVSROOT -x login]
lappend cmd >@ stdout
lappend cmd 2>@ stderr
lappend cmd <@ stdin

catch $cmd result

Bruce



Roland Roberts

2004-05-18, 2:33 pm

-----BEGIN PGP SIGNED MESSAGE-----
[color=darkred]

[...]

Murrgon> Here is what I did:

Murrgon> set cmdLine [list $strCVSExe -d $CVSROOT -x login]

Murrgon> # Login to CVS
Murrgon> puts "Logging in to $CVSROOT"
Murrgon> puts "Please enter your password:"
Murrgon> catch { eval exec $cmdLine } cmdResult

Murrgon> I had to add my own prompt, but that wasn't to big of a problem.
Murrgon> The key to the problem ended up being creating the command line
Murrgon> arguments as a list and not a string.
[color=darkred]
[color=darkred]

Murrgon> Python provides a specific system() call (like in C) as
Murrgon> well as many of the other spawn() type functions which
Murrgon> would make this more straightforward.

You need to realize that what tkcvs is doing and your solution are
radically different even though they both get the job done. For your
purposes, you don't care, but keep in mind what tkcvs is doing because
eventually, if you stick with Tcl, you *will* want do use that idiom.

In your solution, you stop *everything* while the exec is running. In
tkcvs, if, say, you are doing a check-out of a tree that has a few
hundred files and takes 10 minutes, the GUI is still 100% responsive
during that time. The Perl/Python equivalent is more like opening a
pipe and setting up a select while also handling other events/actions.
The tkcvs solution is the typical way to handle subprocess commands in
a GUI where you don't want the GUI to freeze while the command runs.
And God forbid that the subprocess command hangs in the exec; if that
happens, the exec hangs your whole application....

regards,

roland
- --
PGP Key ID: 66 BC 3B CD
Roland B. Roberts, PhD RL Enterprises
roland@rlenter.com 6818 Madeline Court
roland@astrofoto.org Brooklyn, NY 11220

-----BEGIN PGP SIGNATURE-----
Version: 2.6.3ia
Charset: noconv
Comment: Processed by Mailcrypt 3.5.4, an Emacs/PGP interface

iQCVAwUBQKpL1+oW38lmvDvNAQEZRwP/SUOIly0uTRqqPLsu2LKpj4Prn8VELgO+
KGUCn/6i7OVxsNnu6+McAx5F/OLaD74lxAagvRA56JG2lVGsTOBjJ/QM76KfcGvF
N4Gzrz1dMIjm87inaRXPPadgn+FNaPw3KxSFkbwF
IdQh0p2oyYnb4+tASpgH0XE3
+w95zQb0dgs=
=KSY+
-----END PGP SIGNATURE-----
Murrgon

2004-05-18, 6:32 pm

Roland Roberts wrote:
> You need to realize that what tkcvs is doing and your solution are
> radically different even though they both get the job done. For your
> purposes, you don't care, but keep in mind what tkcvs is doing because
> eventually, if you stick with Tcl, you *will* want do use that idiom.
>
> In your solution, you stop *everything* while the exec is running. In
> tkcvs, if, say, you are doing a check-out of a tree that has a few
> hundred files and takes 10 minutes, the GUI is still 100% responsive
> during that time. The Perl/Python equivalent is more like opening a
> pipe and setting up a select while also handling other events/actions.
> The tkcvs solution is the typical way to handle subprocess commands in
> a GUI where you don't want the GUI to freeze while the command runs.
> And God forbid that the subprocess command hangs in the exec; if that
> happens, the exec hangs your whole application....


In my solution, I *want* to stop everything while exec is running.
I am not running any GUI using TK, just a simple script run from
tclsh. So when I ask it to log in to CVS, I want it to stop and
ask the user to type in their password, not continue to run and
fail because there is no valid CVS session active.

Murrgon

2004-05-18, 6:32 pm

Bruce Hartweg wrote:
> exec is like system, so I don't know if it is any harder/easier than
> this is.
>
> a couple of more items, if using list instead of a srting for your
> command made a difference, then eithe strCVSExe ot CVSROOT (or both)
> must contain a space.


Actually they don't. The problem was not that exec wasn't running
the proper command, but more that when it finished, the script would
exit. What fixed that was probably the use of the 'catch'.

David Gravereaux

2004-05-18, 7:32 pm

Murrgon <murrgon@hotmail.com> wrote:

>Roland Roberts wrote:
>
>In my solution, I *want* to stop everything while exec is running.
>I am not running any GUI using TK, just a simple script run from
>tclsh. So when I ask it to log in to CVS, I want it to stop and
>ask the user to type in their password, not continue to run and
>fail because there is no valid CVS session active.


You CAN use pipes: http://wiki.tcl.tk/3846

See the third code sample for how to interact on CVS to enter a
passphrase.
--
David Gravereaux <davygrvy@pobox.com>
[species: human; planet: earth,milkyway(western spiral arm),alpha sector]
Ralf Fassel

2004-05-19, 4:31 am

* Murrgon <murrgon@hotmail.com>
| I am not running any GUI using TK, just a simple script run from
| tclsh. So when I ask it to log in to CVS, I want it to stop and ask
| the user to type in their password, not continue to run and fail
| because there is no valid CVS session active.

Then exec with redirected output is your solution. Usually exec
returns the output of the command but you don't need this here.

`catch' it though, as the command might fail (this might be different
from perl or python were you may have to check the exit status
explicitely).

if {[catch {exec cvs ... >@stdout 2>@stderr} errmsg]} {
# cvs command failed, further details in errmsg, ::errorCode and
# ::errorInfo
...
}

R'
Murrgon

2004-05-19, 10:38 am

David Gravereaux wrote:
> You CAN use pipes: http://wiki.tcl.tk/3846
>
> See the third code sample for how to interact on CVS to enter a
> passphrase.


That was useful. Thanks.

Roland Roberts

2004-05-20, 6:32 pm

-----BEGIN PGP SIGNED MESSAGE-----
[color=darkred]

Murrgon> In my solution, I *want* to stop everything while exec is running.
Murrgon> I am not running any GUI using TK, just a simple script run from
Murrgon> tclsh. So when I ask it to log in to CVS, I want it to stop and
Murrgon> ask the user to type in their password, not continue to run and
Murrgon> fail because there is no valid CVS session active.

You could also use Expect and [interact]. Note expect is *still* Tcl,
so apart from the user interaction part and the process control part,
you don't have to think about it being expect.

regards,

roland
- --
PGP Key ID: 66 BC 3B CD
Roland B. Roberts, PhD RL Enterprises
roland@rlenter.com 6818 Madeline Court
roland@astrofoto.org Brooklyn, NY 11220

-----BEGIN PGP SIGNATURE-----
Version: 2.6.3ia
Charset: noconv
Comment: Processed by Mailcrypt 3.5.4, an Emacs/PGP interface

iQCVAwUBQK0pNuoW38lmvDvNAQH9VAQAs9jtJC72
YTbCtsNc3msVuLKTqqvApzPR
C+hu5+s0RJIHLOvUFGDO4/ W7Z+rQqXMjWfNuc6BLXeT5htkBAR5YTFZ7SwmxRC
9r
In3l8vFf1jTRKQizBg1ozsh+k/NhxdP6Y5h6+TE+U/3mb48Uh6rpDoxeeYYvWgOF
aapSiM794MI=
=pFYC
-----END PGP SIGNATURE-----
Donal K. Fellows

2004-05-24, 10:40 am

Murrgon wrote:
> In my solution, I *want* to stop everything while exec is running.
> I am not running any GUI using TK, just a simple script run from
> tclsh. So when I ask it to log in to CVS, I want it to stop and
> ask the user to type in their password, not continue to run and
> fail because there is no valid CVS session active.


Ah, in that case you probably want to redirect stdin.

set cmd "cvs update" ;# Add your favourite options! :^)
eval exec $cmd <@stdin >@stdout 2>@stderr

If you're using CVS in a terminal in a GUI, the SSH_ASKPASS environment
variable might be useful. Encouraging people to set up a proper ssh key
agent is best though; saves a lot of typing on their part.

Donal.

Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com