Pty: I/O buffer problems?

Once upon a time, Hal was coding at 3 in the morning.

There was too much blood in his caffeine stream.

He wrote a little program to open a pty to an interactive program –
ftp, in the case shown below.

He noticed that when he sent a command, it was echoed back, even if he
set noecho on the tty. He decided not to worry about this.

But then he noticed that characters were being retrieved over and over,
as though the buffer were not being emptied or something.

Then he got tired of posting in second person.

So anyway: I open ftp via PTY, and I send it an “open” command. (I
picked that one randomly.) I watch the characters I get back, and I
write them out as a “dumped” (readable) string.

Of course, I do a break to kill the program after a few seconds, as
there is no clean way to terminate this little piece of code. The
’ensure’ clause closes my files.

Here’s what I get in “mylog” (excuse any linewrap):

got: "\r\rftp> \rftp> "
got: "\rftp> o\rftp> o\rftp> op\rftp> op\rftp> ope\rftp> ope\rftp>
open\rftp> open\r\n(to) "

Notice the weird way the “open” is built up a char at a time.

Code is shown below.

What is going on here???

Thanks for any help…

Hal

require ‘pty’

def converse(input,logfile)
log = File.open(logfile,“w”)
dlog = File.open(“debug.log”,“w”)
STDOUT.sync = true
loop do
waiting = ""
while select([input],nil,nil,0)
ch = input.sysread(1)
# STDOUT.putc(ch)
waiting << ch
dlog.puts "w #{ch.dump}“
end
log.puts(“got: #{waiting.dump}”) if waiting!=”"
end
ensure
log.close
dlog.close
end

PTY.spawn("/usr/bin/ftp") do |rd,wr,pid|
begin
wr.puts "open"
converse(rd,“mylog”)
rescue PTY::ChildExited
end
end

Hal,

I’m guessing here, but I think you should read all data from the port
before calling select() again.

Dave

···

On Thu, 27 May 2004 17:26:52 +0900, Hal Fulton hal9000@hypermetrics.com wrote:

Once upon a time, Hal was coding at 3 in the morning.

There was too much blood in his caffeine stream.

He wrote a little program to open a pty to an interactive program –
ftp, in the case shown below.

He noticed that when he sent a command, it was echoed back, even if he
set noecho on the tty. He decided not to worry about this.

But then he noticed that characters were being retrieved over and over,
as though the buffer were not being emptied or something.

Then he got tired of posting in second person.

So anyway: I open ftp via PTY, and I send it an “open” command. (I
picked that one randomly.) I watch the characters I get back, and I
write them out as a “dumped” (readable) string.

Of course, I do a break to kill the program after a few seconds, as
there is no clean way to terminate this little piece of code. The
‘ensure’ clause closes my files.

Here’s what I get in “mylog” (excuse any linewrap):

got: "\r\rftp> \rftp> "
got: "\rftp> o\rftp> o\rftp> op\rftp> op\rftp> ope\rftp> ope\rftp>
open\rftp> open\r\n(to) "

Notice the weird way the “open” is built up a char at a time.

Code is shown below.

What is going on here???

Thanks for any help…

Hal

require ‘pty’

def converse(input,logfile)
log = File.open(logfile,“w”)
dlog = File.open(“debug.log”,“w”)
STDOUT.sync = true
loop do
waiting = “”
while select([input],nil,nil,0)
ch = input.sysread(1)
# STDOUT.putc(ch)
waiting << ch
dlog.puts “w #{ch.dump}”
end
log.puts(“got: #{waiting.dump}”) if waiting!=“”
end
ensure
log.close
dlog.close
end

PTY.spawn(“/usr/bin/ftp”) do |rd,wr,pid|
begin
wr.puts “open”
converse(rd,“mylog”)
rescue PTY::ChildExited
end
end

David L Hawley wrote:

Hal,

I’m guessing here, but I think you should read all data from the port
before calling select() again.

That makes sense I suppose, but how do I know when there is no more?
I don’t want to block.

And anyway: I thought when I read a single character, it would
definitely be removed from the buffer. It seems not?

I tried getc first, then sysread(1).

Hal

···

Dave

On Thu, 27 May 2004 17:26:52 +0900, Hal Fulton > hal9000@hypermetrics.com wrote:

Once upon a time, Hal was coding at 3 in the morning.

There was too much blood in his caffeine stream.

He wrote a little program to open a pty to an interactive program –
ftp, in the case shown below.

He noticed that when he sent a command, it was echoed back, even if he
set noecho on the tty. He decided not to worry about this.

But then he noticed that characters were being retrieved over and over,
as though the buffer were not being emptied or something.

Then he got tired of posting in second person.

So anyway: I open ftp via PTY, and I send it an “open” command. (I
picked that one randomly.) I watch the characters I get back, and I
write them out as a “dumped” (readable) string.

Of course, I do a break to kill the program after a few seconds, as
there is no clean way to terminate this little piece of code. The
‘ensure’ clause closes my files.

Here’s what I get in “mylog” (excuse any linewrap):

got: "\r\rftp> \rftp> "
got: "\rftp> o\rftp> o\rftp> op\rftp> op\rftp> ope\rftp> ope\rftp>
open\rftp> open\r\n(to) "

Notice the weird way the “open” is built up a char at a time.

Code is shown below.

What is going on here???

Thanks for any help…

Hal

require ‘pty’

def converse(input,logfile)
log = File.open(logfile,“w”)
dlog = File.open(“debug.log”,“w”)
STDOUT.sync = true
loop do
waiting = “”
while select([input],nil,nil,0)
ch = input.sysread(1)
# STDOUT.putc(ch)
waiting << ch
dlog.puts “w #{ch.dump}”
end
log.puts(“got: #{waiting.dump}”) if waiting!=“”
end
ensure
log.close
dlog.close
end

PTY.spawn(“/usr/bin/ftp”) do |rd,wr,pid|
begin
wr.puts “open”
converse(rd,“mylog”)
rescue PTY::ChildExited
end
end