#!/usr/bin/perl # By Simon Tatham require 5.002; use Socket; use FileHandle; $verbose=1, shift @ARGV if $ARGV[0] eq "-v"; die "usage: nntpid messageid\n" if !defined $ARGV[0]; $mid = $ARGV[0]; $mid =~ s/^$//; $mid = "<$mid>"; $ns=$ENV{'NNTPSERVER'}; if (!defined $ns or !length $ns) { $ns = `cat /etc/nntpserver`; chomp($ns); } $port = (getservbyname("nntp", "tcp"))[2]; $ns = inet_aton($ns); $proto = getprotobyname("tcp"); $paddr = sockaddr_in($port, $ns); socket(S,PF_INET,SOCK_STREAM,$proto) or die "socket: $!"; connect(S,$paddr) or die "connect: $!"; S->autoflush(1); &getline; $code =~ /^2\d\d/ or die "no initial greeting from server\n"; &docmd("MODE READER"); # some servers require a GROUP before an ARTICLE command &docmd("GROUP misc.misc"); &docmd("ARTICLE $mid"); while (1) { &getline; s/[\r\n]//g; last if /^\.$/; s/^\.//; print STDOUT "$_\n"; } &docmd("QUIT"); close S; sub putline { my ($line) = @_; print STDERR ">>> $line\n" if $verbose; print S "$line\r\n"; } sub getline { $_ = ; s/[\r\n]*$//s; $code = substr($_,0,3); print STDERR "<<< $_\n" if $verbose; } sub docmd { my ($cmd) = @_; while (1) { &putline($cmd); &getline; if ($code eq "480") { &auth; } else { last; } } $code =~ /^2\d\d/ or die "failed on `$cmd':\n$_\n"; } sub auth { # Authentication. if ($ENV{"NNTPAUTH"}) { $auth = $ENV{"NNTPAUTH"}; &putline("AUTHINFO GENERIC $auth"); pipe AUTHSTDIN, TOAUTH or die "unable to create pipes"; pipe FROMAUTH, AUTHSTDOUT or die "unable to create pipes"; $pid = fork; if (!defined $pid) { die "unable to fork for authentication helper"; } elsif ($pid == 0) { # we are child $ENV{"NNTP_AUTH_FDS"} = "0.1"; open STDIN, "<&AUTHSTDIN"; open STDOUT, ">&AUTHSTDOUT"; close S; exec $auth; } # we are parent close AUTHSTDIN; close AUTHSTDOUT; autoflush TOAUTH 1; &getline; print TOAUTH "$_\n"; while () { s/[\r\n]*$//s; &putline($_); &getline; print TOAUTH "$_\n"; } die "failed authentication\n" unless $? == 0; } }