ruby pty/expect help

A

Ara.T.Howard

i've been up for a really long time, so perhaps i'm missing something silly,
but this script 'seems' to work (all three dots are printed), but no id_rsa
file is made? do i have to signal the child to die or something? any other
useful debugging tips? it would be great if PTY could 'tee' it's output to
stdout for debugging

~/eg/ruby > cat ssh-keygen.rb
require 'pty'
require 'expect'

path = ARGV.shift || 'id_rsa'
File.unlink path rescue nil

PTY.spawn('ssh-keygen -t rsa') do |r,w,cid|
r.expect %r/^Enter.*:\s+/ do
print '.'
w.puts path
end
r.expect %r/^Enter.*:\s+/ do
print '.'
w.puts ''
end
r.expect %r/^Enter.*:\s+/ do
print '.'
w.puts ''
end

w.flush
w.close
puts
end


-a
--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
| URL :: http://www.ngdc.noaa.gov/stp/
| TRY :: for l in ruby perl;do $l -e "print \"\x3a\x2d\x29\x0a\"";done
===============================================================================
 
T

ts

A> i've been up for a really long time, so perhaps i'm missing something silly,
A> but this script 'seems' to work (all three dots are printed), but no id_rsa
A> file is made?

You must read its output

A> do i have to signal the child to die or something? any other
A> useful debugging tips?

$expect_verbose = true


Guy Decoux
 
A

Ara.T.Howard

A> i've been up for a really long time, so perhaps i'm missing something silly,
A> but this script 'seems' to work (all three dots are printed), but no id_rsa
A> file is made?

You must read its output

thanks guy - what exactly do you mean? there's only one thing to read, and
reading it seems the throw errors:

~/eg/ruby > cat ssh-keygen.rb
require 'pty'
require 'expect'
$VERBOSE=nil

path = ARGV.shift || 'id_rsa'
File.unlink path rescue nil

PTY.spawn 'ssh-keygen -t rsa' do |r,w,cid|
r.expect %r/^Enter.*:\s+/ do |line|
print line
w.puts path
end
r.expect %r/^Enter.*:\s+/ do |line|
print line
w.puts ''
end
r.expect %r/^Enter.*:\s+/ do |line|
print line
w.puts ''
end

r.read # ?? this raises Errno::EIO
w.flush
w.close
puts
end


~/eg/ruby > ruby ssh-keygen.rb
Generating public/private rsa key pair.
Enter file in which to save the key (/home/ahoward/.ssh/id_rsa): id_rsa
Enter passphrase (empty for no passphrase):
Enter same passphrase again: ssh-keygen.rb:22:in `read': Input/output error - /dev/pts/19 (Errno::EIO)
from ssh-keygen.rb:22
from ssh-keygen.rb:8:in `spawn'
from ssh-keygen.rb:8


without the read it generates the expected output, but no id_rsa file is
produced and no error is given... doesn't the call to IO.expect do the reading
anyhow? also, the example in ext/pty/example_expect.rb doesn't seem to do any
reading either?
A> do i have to signal the child to die or something? any other
A> useful debugging tips?

$expect_verbose = true


Guy Decoux

this is very helpful - and it was right in the example! ;-)


-a
--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
| URL :: http://www.ngdc.noaa.gov/stp/
| TRY :: for l in ruby perl;do $l -e "print \"\x3a\x2d\x29\x0a\"";done
===============================================================================
 
T

ts

A> without the read it generates the expected output, but no id_rsa file is
A> produced and no error is given... doesn't the call to IO.expect do the reading
A> anyhow? also, the example in ext/pty/example_expect.rb doesn't seem to do any
A> reading either?

Without the read it don't give an error and don't generate the id_rsa
files.

With the read it give an error and generate the id_rsa files, no ?

Then protect the read :)



Guy DEcoux
 
A

Ara.T.Howard

A> without the read it generates the expected output, but no id_rsa file is
A> produced and no error is given... doesn't the call to IO.expect do the reading
A> anyhow? also, the example in ext/pty/example_expect.rb doesn't seem to do any
A> reading either?

Without the read it don't give an error and don't generate the id_rsa
files.

With the read it give an error and generate the id_rsa files, no ?

Then protect the read :)
Guy DEcoux


guy-

you are a saint. why on earth would one be __required__ to do a read which
generates an error? and why don't the example scripts do this?

-a
--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
| URL :: http://www.ngdc.noaa.gov/stp/
| TRY :: for l in ruby perl;do $l -e "print \"\x3a\x2d\x29\x0a\"";done
===============================================================================
 
N

nobu.nokada

Hi,

At Thu, 15 Apr 2004 01:09:20 +0900,
Ara.T.Howard wrote in [ruby-talk:97152]:
~/eg/ruby > ruby ssh-keygen.rb
Generating public/private rsa key pair.
Enter file in which to save the key (/home/ahoward/.ssh/id_rsa): id_rsa
Enter passphrase (empty for no passphrase):
Enter same passphrase again: ssh-keygen.rb:22:in `read': Input/output error - /dev/pts/19 (Errno::EIO)
from ssh-keygen.rb:22
from ssh-keygen.rb:8:in `spawn'
from ssh-keygen.rb:8


without the read it generates the expected output, but no id_rsa file is
produced and no error is given... doesn't the call to IO.expect do the reading
anyhow? also, the example in ext/pty/example_expect.rb doesn't seem to do any
reading either?

Because the watchdog thread created by PTY.spawn signals the
main thread when child exits, and read(2) is interrupted. In
such case, however, I feel that IO#read should return already
read data, if exists.

BTW, you don't need PTY at all to generate ssh key
automatically.

$ rm -f id_rsa{,.pub}
$ ssh-keygen -t rsa -N "" -f id_rsa
Generating public/private rsa key pair.
Your identification has been saved in id_rsa.
Your public key has been saved in id_rsa.pub.
The key fingerprint is:
42:1f:bc:76:60:45:a1:2b:fd:cc:4c:a2:3a:0c:87:c6 (e-mail address removed)


Index: io.c
===================================================================
RCS file: /cvs/ruby/src/ruby/io.c,v
retrieving revision 1.271
diff -u -2 -p -r1.271 io.c
--- io.c 14 Apr 2004 04:06:25 -0000 1.271
+++ io.c 15 Apr 2004 01:18:27 -0000
@@ -953,10 +953,9 @@ rb_io_fread(ptr, len, f)
case EWOULDBLOCK:
#endif
- if (len - n >= 0) {
+ if (len > n) {
clearerr(f);
- return len - n;
}
}
- return 0;
+ if (len == n) return 0;
}
*ptr = '\0';
 
A

Ara.T.Howard

Hi,

At Thu, 15 Apr 2004 01:09:20 +0900,
Ara.T.Howard wrote in [ruby-talk:97152]:
~/eg/ruby > ruby ssh-keygen.rb
Generating public/private rsa key pair.
Enter file in which to save the key (/home/ahoward/.ssh/id_rsa): id_rsa
Enter passphrase (empty for no passphrase):
Enter same passphrase again: ssh-keygen.rb:22:in `read': Input/output error - /dev/pts/19 (Errno::EIO)
from ssh-keygen.rb:22
from ssh-keygen.rb:8:in `spawn'
from ssh-keygen.rb:8


without the read it generates the expected output, but no id_rsa file is
produced and no error is given... doesn't the call to IO.expect do the reading
anyhow? also, the example in ext/pty/example_expect.rb doesn't seem to do any
reading either?

Because the watchdog thread created by PTY.spawn signals the main thread
when child exits, and read(2) is interrupted. In such case, however, I feel
that IO#read should return already read data, if exists.


perhaps a handle on an object which can be 'closed' could be returned instead
of an array of Files, etc:

passphrase = gen_random_passphrase

pty = PTY.spawn 'ssh-keygen'

pty.stdin.puts 'id_rsa.pub'
pty.stdin.puts passphrase
pty.stdin.puts passphrase
pts.close # do the right thing

pty = PTY.spawn 'ssh-agent'

pty.stdin.write passphrase

...

BTW, you don't need PTY at all to generate ssh key
automatically.

see above - i want to pass it to ssh-agent. thanks though, didn't know
that...

-a
--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
| URL :: http://www.ngdc.noaa.gov/stp/
| TRY :: for l in ruby perl;do $l -e "print \"\x3a\x2d\x29\x0a\"";done
===============================================================================
 
N

nobu.nokada

Hi,

At Thu, 15 Apr 2004 12:09:12 +0900,
Ara.T.Howard wrote in [ruby-talk:97212]:
perhaps a handle on an object which can be 'closed' could be returned instead
of an array of Files, etc:

passphrase = gen_random_passphrase

pty = PTY.spawn 'ssh-keygen'

pty.stdin.puts 'id_rsa.pub'
pty.stdin.puts passphrase
pty.stdin.puts passphrase
pts.close # do the right thing

Yes, I've thought about same strategy for open3.
pty = PTY.spawn 'ssh-agent'

pty.stdin.write passphrase

...



see above - i want to pass it to ssh-agent. thanks though, didn't know
that...

ssh-agent doesn't read passphrase but prints some environment
variables and runs as a daemon, like as:

$ ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-FGmutb8164/agent.8164; export SSH_AUTH_SOCK;
SSH_AGENT_PID=8165; export SSH_AGENT_PID;
echo Agent pid 8165;

Therefore you should set those variables instead. e.g.,

`ssh-agent`.scan(/^(SSH_[A-Z_]+)=([^; ]*)/, &ENV.method:)[]=))

Then, you'll need to send passphrase to ssh-add. At this time,
you have 2 methods:

1) with pty.
PTY.spawn("ssh-add") do |r,w,pid|
r.expect %r/^Enter.*:\s+/ {w.puts passphrase}
end

2) without control terminal. Since ssh-add reads passphrase
from stdin when no ctty or X are available, you can:

IO.popen("-", "w") do |f|
if f
f.puts passphrase
else
ENV.delete("SSH_ASKPASS")
ENV.delete("DISPLAY")
Process.setsid
exec("ssh-add")
end
end

or, if setsid command is available and env command has -u option:

IO.popen("env -u SSH_ASKPASS -u DISPLAY setsid ssh-add", "w") do |f|
f.puts passphrase
end
 
A

Ara.T.Howard

Hi,

At Thu, 15 Apr 2004 12:09:12 +0900,
Ara.T.Howard wrote in [ruby-talk:97212]:
perhaps a handle on an object which can be 'closed' could be returned instead
of an array of Files, etc:

passphrase = gen_random_passphrase

pty = PTY.spawn 'ssh-keygen'

pty.stdin.puts 'id_rsa.pub'
pty.stdin.puts passphrase
pty.stdin.puts passphrase
pts.close # do the right thing

Yes, I've thought about same strategy for open3.


have you seen my session-2.1.6 package which wraps open3 in this way? it is
more specific but same idea...
ssh-agent doesn't read passphrase but prints some environment variables and
runs as a daemon, like as:

right, right... i've slept three hourse in the last 48... basically i'm just
trying to get around security ;-)
$ ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-FGmutb8164/agent.8164; export SSH_AUTH_SOCK;
SSH_AGENT_PID=8165; export SSH_AGENT_PID;
echo Agent pid 8165;

Therefore you should set those variables instead. e.g.,

`ssh-agent`.scan(/^(SSH_[A-Z_]+)=([^; ]*)/, &ENV.method:)[]=))

^
^
^

i learn something every day
i guess that makes it a
block - neat.


Then, you'll need to send passphrase to ssh-add. At this time,
you have 2 methods:

1) with pty.
PTY.spawn("ssh-add") do |r,w,pid|
r.expect %r/^Enter.*:\s+/ {w.puts passphrase}
end

2) without control terminal. Since ssh-add reads passphrase
from stdin when no ctty or X are available, you can:

IO.popen("-", "w") do |f|
if f
f.puts passphrase
else
ENV.delete("SSH_ASKPASS")
ENV.delete("DISPLAY")
Process.setsid
exec("ssh-add")
end
end

or, if setsid command is available and env command has -u option:

IO.popen("env -u SSH_ASKPASS -u DISPLAY setsid ssh-add", "w") do |f|
f.puts passphrase
end


-a
--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
| URL :: http://www.ngdc.noaa.gov/stp/
| TRY :: for l in ruby perl;do $l -e "print \"\x3a\x2d\x29\x0a\"";done
===============================================================================
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

how to expect eof with expect+pty 4
return value for PTY.spawn 0
idiot's guide to druby using ssh tunnels 4
pretty exceptions 0
parent of TrueClass, FalseClass 9
narray on windows? 1
Class::name 0
ruby advocacy 3

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top