diff options
Diffstat (limited to 'lib/Net')
| -rw-r--r-- | lib/Net/IMAP/InterIMAP.pm | 59 | 
1 files changed, 52 insertions, 7 deletions
| diff --git a/lib/Net/IMAP/InterIMAP.pm b/lib/Net/IMAP/InterIMAP.pm index 26cfbbd..97756f4 100644 --- a/lib/Net/IMAP/InterIMAP.pm +++ b/lib/Net/IMAP/InterIMAP.pm @@ -24,6 +24,7 @@ use Config::Tiny ();  use IO::Select ();  use List::Util 'first';  use Socket 'SO_KEEPALIVE'; +use POSIX ':signal_h';  use Exporter 'import';  BEGIN { @@ -225,10 +226,33 @@ sub new($%) {      $self->{_STATE} = '';      if ($self->{type} eq 'tunnel') { -        require 'IPC/Open2.pm';          my $command = $self->{command} // $self->fail("Missing tunnel command"); -        my $pid = IPC::Open2::open2(@$self{qw/STDOUT STDIN/}, $command) -            or $self->panic("Can't fork: $!"); + +        pipe $self->{STDOUT}, my $wd or $self->panic("Can't pipe: $!"); +        pipe my $rd, $self->{STDIN}  or $self->panic("Can't pipe: $!"); + +        my $pid = fork // $self->panic("Can't fork: $!"); + +        unless ($pid) { +            # children +            foreach (\*STDIN, \*STDOUT, $self->{STDIN}, $self->{STDOUT}) { +                close $_ or $self->panic("Can't close: $!"); +            } +            open STDIN,  '<&', $rd or $self->panic("Can't dup: $!"); +            open STDOUT, '>&', $wd or $self->panic("Can't dup: $!"); + +            my $sigset = POSIX::SigSet::->new(SIGINT); +            my $oldsigset = POSIX::SigSet::->new(); + +            sigprocmask(SIG_BLOCK, $sigset, $oldsigset) // $self->panic("Can't block SIGINT: $!"); + +            exec $command or $self->panic("Can't exec: $!"); +        } + +        # parent +        foreach ($rd, $wd) { +            close $_ or $self->panic("Can't close: $!"); +        }      }      else {          my %args = (Proto => 'tcp', Blocking => 1); @@ -287,8 +311,8 @@ sub new($%) {      # are considered.      $self->{_MODIFIED} = {}; -    if (defined $self->{'logger-fd'} and $self->{'logger-fd'}->fileno != fileno STDERR) { -        require 'POSIX.pm'; +    if (defined $self->{'logger-fd'} and defined $self->{'logger-fd'}->fileno +            and $self->{'logger-fd'}->fileno != fileno STDERR) {          require 'Time/HiRes.pm';      } @@ -400,7 +424,8 @@ sub DESTROY($) {  sub log($@) {      my $self = shift;      return unless @_; -    $self->logger(@_) if defined $self->{'logger-fd'} and $self->{'logger-fd'}->fileno != fileno STDERR; +    $self->logger(@_) if defined $self->{'logger-fd'} and defined $self->{'logger-fd'}->fileno +        and $self->{'logger-fd'}->fileno != fileno STDERR;      my $prefix = defined $self->{name} ? $self->{name} : '';      $prefix .= "($self->{_SELECTED})" if $self->{_STATE} eq 'SELECTED';      print STDERR $prefix, ': ', @_, "\n"; @@ -409,7 +434,8 @@ sub logger($@) {      my $self = shift;      return unless @_ and defined $self->{'logger-fd'};      my $prefix = ''; -    if ($self->{'logger-fd'}->fileno != fileno STDERR) { +    if (defined $self->{'logger-fd'}->fileno and defined $self->{'logger-fd'}->fileno +            and $self->{'logger-fd'}->fileno != fileno STDERR) {          my ($s, $us) = Time::HiRes::gettimeofday();          $prefix = POSIX::strftime("%b %e %H:%M:%S", localtime($s)).".$us ";      } @@ -500,6 +526,25 @@ sub examine($$;$$) {  } +# $self->unselect() +#   Issue an UNSELECT command (cf. RFC 3691). Upon success, change the +#   state to AUTH. +sub unselect($) { +    my $self = shift; + +    $self->_send('UNSELECT'); + +    $self->{_STATE} = 'AUTH'; +    delete $self->{_SELECTED}; + +    # it is safe to wipe cached VANISHED responses or FLAG updates, +    # because interesting stuff must have made the mailbox dirty so +    # we'll get back to it +    $self->{_VANISHED} = []; +    $self->{_MODIFIED} = {}; +} + +  # $self->logout()  #   Issue a LOGOUT command.  Change the state to LOGOUT.  sub logout($) { | 
