DEV Community

Yuki Kimoto
Yuki Kimoto

Posted on • Edited on

How to download cpanm in the portable way that supports Perl 5.8.1

How to download cpanm in the portable way that supports Perl 5.8.1.

On Linux/UNIX, Mac, Windows/PowerShell

perl -0777 -Mstrict -Mwarnings -MIO::Socket::INET -e 'my $socket = IO::Socket::INET->new(  Proto => qq(tcp),  PeerAddr => qq(cpanmin.us),  PeerPort => 80,) or die $!;print $socket join qq(\r\n),  qq(GET / HTTP/1.1),  qq(Connection:close),  qq(Host:cpanmin.us),  qq(\r\n);my $res = <$socket>;$res =~ m(^HTTP/1\.1 200 OK\r\n) or die $res;$res =~ s/.*?\r\n\r\n//s;open my $out, qq(>), qq(cpanm) or die $!;print $out $res'
Enter fullscreen mode Exit fullscreen mode

On Windows/Command Prompt:

perl -0777 -Mstrict -Mwarnings -MIO::Socket::INET -e "my $socket = IO::Socket::INET->new(  Proto => qq(tcp),  PeerAddr => qq(cpanmin.us),  PeerPort => 80,) or die $!;print $socket join qq(\r\n),  qq(GET / HTTP/1.1),  qq(Connection:close),  qq(Host:cpanmin.us),  qq(\r\n);my $res = <$socket>;$res =~ m(^HTTP/1\.1 200 OK\r\n) or die $res;$res =~ s/.*?\r\n\r\n//s;open my $out, qq(>), qq(cpanm) or die $!;print $out $res"
Enter fullscreen mode Exit fullscreen mode

The answer is using IO::Socket::INET.

If Perl is 5.14+, Perl has a HTTP client called HTTP::Tiny.

Examples on Github Action

The example to donwload cpanm on Github Action.

https://github.com/yuki-kimoto/SPVM/blob/build/.github/workflows/linux-ubuntu-latest-32bit.yml

Note for Beginners

cpanm is a tool to download Perl modules from CPAN. CAPN have many module distributions that are uploaded by Perl users.

Before Fixed(Old content)

On Linux/UNIX, Mac, Windows/PowerShell

perl -Mstrict -Mwarnings -MIO::Socket::INET -e 'my $socket = IO::Socket::INET->new(PeerAddr => qq(cpanmin.us), PeerPort => 80, Proto=> qq(tcp));print $socket qq(GET / HTTP/1.0\r\nHost:cpanmin.us\r\n\r\n);binmode STDOUT;print <$socket>;' | perl -p -0777 -e 'BEGIN { binmode STDOUT;binmode STDIN  } s/.*?\r\n\r\n//s' > cpanm

Enter fullscreen mode Exit fullscreen mode

On Windows/Command Prompt:

perl -Mstrict -Mwarnings -MIO::Socket::INET -e "my $socket = IO::Socket::INET->new(PeerAddr => qq(cpanmin.us), PeerPort => 80, Proto=> qq(tcp));print $socket qq(GET / HTTP/1.0\r\nHost:cpanmin.us\r\n\r\n);binmode STDOUT;print <$socket>;" | perl -p -0777 -e "BEGIN { binmode STDOUT;binmode STDIN  } s/.*?\r\n\r\n//s" > cpanm

Enter fullscreen mode Exit fullscreen mode

Top comments (5)

Collapse
 
ap profile image
Aristotle Pagaltzis • Edited

Why two whole perl separate processes?

Also I forgot last time that strictly speaking using the Host header under HTTP/1.0 is wrong so you should say HTTP/1.1. However then the server will keep the connection open for more requests so you also need Connection: close.

You are missing at least a minimum of error checking as well. The code should at least check that the response was a 200 OK. And it should not create the file if there was an error.

perl -0777 -Mstrict -Mwarnings -MIO::Socket::INET -e '
my $socket = IO::Socket::INET->new(
  Proto => qq(tcp),
  PeerAddr => qq(cpanmin.us),
  PeerPort => 80,
) or die $!;
print $socket join qq(\r\n),
  qq(GET / HTTP/1.1),
  qq(Connection: close),
  qq(Host: cpanmin.us),
  qq(\r\n);
my $res = <$socket>;
$res =~ m(^HTTP/1\.1 200 OK\r\n) or die $res;
$res =~ s/.*?\r\n\r\n//s;
open my $out, qq(>), qq(cpanm) or die $!;
print $out $res'
Enter fullscreen mode Exit fullscreen mode
Collapse
 
yukikimoto profile image
Yuki Kimoto

Why two whole perl separate processes?

I don't really have the reason.

Your oneliner is better. I will use your oneliner after testing it in SPVM.

Collapse
 
yukikimoto profile image
Yuki Kimoto

I fixed the article.

Thread Thread
 
ap profile image
Aristotle Pagaltzis

I updated my code as well. I noticed that the combined HTTP status match and header removal regexp was very subtly wrong (even if it will probably never matter in practice). When I tried to fix it, it made the regexp way too tricky. So I split it in two matches instead.

Thread Thread
 
yukikimoto profile image
Yuki Kimoto

Thanks. I fixed this article again.