Is it possible to force `expect` to `puts` a string of nulls without a newline?

56 Views Asked by At

Consider the following script, which I'll call PrintNull.tcl.

puts -nonewline "\0\0\0\0"

If I run this script with tclsh, it outputs the four null characters as expected:

tclsh PrintNull.tcl  | xxd
00000000: 0000 0000          

If I run this script with expect, it outputs nothing:

expect -f PrintNull.tcl  | xxd
# No output at all

Curiously, if I modify the script slightly and remove the -nonewline, both tclsh and expect behave the same way, but now they both have an extra newline character:

expect -f PrintNull.tcl  | xxd
00000000: 0000 0000 0a                             .....
tclsh PrintNull.tcl  | xxd
00000000: 0000 0000 0a                             .....

What is causing this behavior, and is it possible to force expect to behave like tcl when processing puts?

2

There are 2 best solutions below

0
pynexj On BEST ANSWER

Explicitly flushing stdout can solve the issue:

$ expect -c 'puts -nonewline "\0\0\0\0" ' | xxd
$ expect -c 'puts -nonewline "\0\0\0\0"; flush stdout' | xxd
00000000: 0000 0000                                ....

Based on the observation stdout is line-buffered for both Tcl and Expect but seems like Expect does not flush stdout before exiting.

NOTE: The issue is not specific for NULL chars. For example expect -c 'puts -nonewline foobar' can also reproduce the issue.

1
merlin2011 On

I did more experiments, and I found that both send and send_user seem to work fine for printing nulls in expect.

#!/usr/bin/expect

send "\0\0\0\0"
send_user "\0\0\0\0"

Output:

./PrintNull2.exp  | xxd
00000000: 0000 0000 0000 0000                      ........

I'm still interested in any answers that explain why expect's version of puts appears to be broken though.