-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Reproduction steps: 1. Run "script -t 2>timing". 2. When the prompt comes up, hit return. 3. New prompt. Wait several seconds, then type "true" and hit return. 4. Repeat (3) as desired, then exit scripted shell. 5. Run "scriptreplay timing". You'll find on the replay that, rather than waiting several seconds between the prompt and true, the wait will actually occur after the first "t" of true. - -= explanation =- One way of looking at this is that this functionality was broken by the reimplementation in C. Another position, at least as equally viable, is that script/scriptreplay was never really quite working right in the first place. The source of the issue is that the C scriptreplay is expecting script to behave in a common-sense way, as it is documented to do, when in fact it has never behaved in such a way. If you look carefully at the dooutput() function in script.c, you'll see that the following pseudocode sums up the situation, as far as timing goes: oldtime = now() // via time() do: newtime = now() // via gettimeofday() bytes_read = do_nonblocking_read() fprintf(timingfile, "%f %d\n", newtime - oldtime, bytes_read) print read-block to output while (read was successful) You'll notice, perhaps, that both newtime and oldtime will have been sampled before the first actual read, which would normally yield a value very close to zero; but it can actually be as great as a second, due to the fact that oldtime was stored with time() and newtime was taken from gettimeofday(). It's not until the next iteration of the loop that the time taken to do a read has factored in any way, into the calculation of a delay in the timing file. The Perl-based scriptreplay had code like this (only a comment was removed): my $block; my $oldblock=''; while (<TIMING>) { my ($delay, $blocksize)=split ' ', $_, 2; if ($delay / $divisor > 0.0001) { select(undef, undef, undef, $delay / $divisor - 0.0001); } read(TYPESCRIPT, $block, $blocksize) or die "read failure on typescript: $!"; print $oldblock; $oldblock=$block; } Note that two delay lines are read, and executed, before a single byte has been written to the terminal. This makes sense since the first delay value is in actuality a completely spurious number (less than 1). scriptreplay.pl just read the number of bytes it was supposed to, but held off on printing it out until the next delay. The current C-based scriptreplay program doesn't do this, but does what anyone would otherwise assume it should: read a delay and number of bytes, do the delay, and read/write the number of bytes. - -= what can be done =- - From a Correctness POV, the right way to deal with this is to fix script.c, not scriptreplay.c. The simple act of moving the newtime calculation to below the read, rather than before it (and, perhaps, calculating oldtime using gettimeofday, so we don't introduce a spurious ~half-second delay) will have things working better than they ever did, and result in a much more straightforward way to process the timing file (i.e., the way scriptreplay does it now). - From a Pragmatism POV, though, there's the fact that, if we simply kludge scriptreplay.c to behave as the original did, then the timing files from all versions of script, new and old, will work with the current scriptreplay. If we fix script.c instead, then everyone has to be careful not to mix versions of script. - -= ouch, my head =- The reason I ran into this, is I'm currently nearing completion on a program to break down typescripts into human-readable form. The program is GNU Teseq, and a preview version can be had from http://micah.cowan.name/projects/teseq/ (note to archive-readers: that link won't be good for long; if you can't find it there, look around at http://www.gnu.org/software/teseq/ (which isn't up yet at the time of this writing)). It takes input like: ^[[1mHi^[[m there, world^H^H^H^H^Hearth And spits out something like: : Esc [ 1 m & SGR: SELECT GRAPHIC RENDITION " Set bold text. |Hi| : Esc [ 0 m & SGR: SELECT GRAPHIC RENDITION " Clear graphic rendition to defaults. | there, world| . BS/^H BS/^H BS/^H BS/^H BS/^H |earth|. I just added support for timing files, so that you could include the timing information, make edits (whatever's needed to debug a pesky terminal issue), and the timings would all still be in the correct place. These timings are inserted into the output as "delay lines", e.g.: @ 3.14159 <--- seconds to wait Teseq currently behaves similar to scriptreplay.pl: skips over the first (timestamp) line, processes _two_ timing-file lines, then processes the number of bytes from the first of those lines. Where it gets... interesting... is that there's a companion program, reseq, which can turn this format back into a script-style typescript-and-timings-file. In order to do that, it actually has to read up to the _third_ delay line, before it can write a single byte out to the timings file, since the seconds field for the first two lines of the timing file will come from the first two delay lines of the Teseq file; but the number-of-bytes field for the first line of the timing file can't be determined until we see how many bytes follow them, up to the next (third) delay line. Ick! That may be a good case for the fix-script.c POV; but OTOH even if you fix that I'm still going to have to support all the folks with less than spanking-new versions of script. That means my choices are: (1) just yell at them to get a version of script that works, or (2) include an option to handle outputs from buggy versions of script. In the case of (1), my code will be significantly cleaner, but I'll probably have mild support headaches to look forward to. . If I had to choose, fixing script is the solution that appeals to me most; but given that it's been like that for forever, and people may be depending on its current idiosyncracies somewhere, and fixing it could confuse people who try to share typescripts, it's not insane to consider just "breaking" scriptreplay properly instead. ;) - -- Micah J. Cowan Programmer, musician, typesetting enthusiast, gamer. GNU Maintainer: wget, screen, teseq http://micah.cowan.name/ -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFIjb4f7M8hyUobTrERAk7LAJ95uJFk63LaEuqzhhhNKWUgvJj9vgCeO6g6 L9Iazqf7QexvfJG6k/c8kIo= =u5Fi -----END PGP SIGNATURE----- -- To unsubscribe from this list: send the line "unsubscribe util-linux-ng" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html