Where does this \r\n come from when I redirect STDOUT to a PTY in Perl?
Asked Answered
S

2

5

With the following code:

use strict;
use warnings;
use utf8;

use IO::Pty;
use Data::Dump qw(pp);

my $pty = IO::Pty->new;
open *STDOUT, '>&', $pty->slave;

if ( my $pid = open *STDOUT, '|-' ) {
  # parent
  my $str = "foo\n";
  print {*STDERR} "parent [1]: ", pp($str), "\n";
  print {*STDOUT} $str;
  my $line = <$pty>;
  print {*STDERR} "parent [2]: ", pp($line), "\n";
} else {
  # child
  while (<>) {
    print {*STDERR} "child [1]: ", pp($_), "\n";
    s/foo/bar/;
    print {*STDERR} "child [2]: ", pp($_), "\n";
    print $_;
  } ## end while (<>)
  exit;
} ## end else [ if ( my $pid = open *STDOUT...)]

The output I get is:

parent [1]: "foo\n"
child [1]: "foo\n"
child [2]: "bar\n"
parent [2]: "bar\r\n"

But on the last line I expected to receive "bar\n". Also, I'm running Perl under Linux, so shouldn't this LF to CRLF nonsense be a non-issue?

Servomechanism answered 3/3, 2023 at 18:56 Comment(0)
C
6

\r and \n are "control characters". What are "control characters" controlling? A typewriter. Well, it used to.

TTYs pre-date computers, going back to telegraphs. TTY stands for teletype; literally a typewriter that types the output. As it was a typewriter, it needed to be told to slide (return) the print head (carriage) back to the first column of the page, and then advance the paper to the next line. \r\n.

Now that's baked into the tty protocol. Even though technology has moved on, it's still acting like it's talking to a typewriter.

See also Why in the output of script (1) the newline is CR + LF (dos-style)?

Corticosterone answered 3/3, 2023 at 19:18 Comment(0)
S
6

As indicated by the user Schwern, the problem was caused by the TTY itself. I solved it by using the raw mode on the TTY.

$pty->slave->set_raw();
$pty->set_raw();
Servomechanism answered 3/3, 2023 at 19:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.