package
forks::signals; #hide from PAUSE
$VERSION = 0.26;
use strict;
use warnings;
use Carp ();
use vars qw($sig %usersig);
use List::MoreUtils;
my $tied;
my %sig_undefined_map;
my %sig_defined_map;
sub import {
shift;
unless ($sig) {
%usersig = %SIG;
$sig = \%SIG;
*SIG = {};
$tied = tie %SIG, __PACKAGE__;
}
if ((my $idx = List::MoreUtils::firstidx(
sub { $_ eq 'ifdef' }, @_)) >= 0) {
if (ref $_[$idx+1] eq 'HASH') {
my (undef, $opts) = splice(@_, $idx, 2);
%sig_defined_map = map { $_ => $opts->{$_} }
map(defined $opts->{$_} && $opts->{$_} ne ''
? $_ : (), keys %{$opts});
_STORE($_, $usersig{$_})
foreach map(defined $usersig{$_} && $usersig{$_} ne ''
? $_ : (), keys %sig_defined_map);
} else {
splice(@_, $idx, 1);
%sig_defined_map = ();
}
}
if ((my $idx = List::MoreUtils::firstidx(
sub { $_ eq 'ifndef' }, @_)) >= 0) {
if (ref $_[$idx+1] eq 'HASH') {
my (undef, $opts) = splice(@_, $idx, 2);
%sig_undefined_map = map { $_ => $opts->{$_} }
map(defined $opts->{$_} && $opts->{$_} ne ''
? $_ : (), keys %{$opts});
_STORE($_, (defined $usersig{$_} ? $usersig{$_} : undef))
foreach map(!defined $usersig{$_} || $usersig{$_} eq ''
? $_ : (), keys %sig_undefined_map);
} else {
splice(@_, $idx, 1);
%sig_undefined_map = ();
}
}
return $tied;
}
sub _STORE {
my $k = shift;
my $s = shift;
if (!defined($s) || $s eq '' || $s eq 'DEFAULT') {
if (grep(/^$k$/, keys %sig_undefined_map)) {
$sig->{$k} = $sig_undefined_map{$k};
} else {
delete( $sig->{$k} );
}
} elsif ($s eq 'IGNORE') {
$sig->{$k} = 'IGNORE';
} else {
$sig->{$k} = ref($s) eq 'CODE'
? grep(/^$k$/, keys %sig_defined_map)
? sub { $sig_defined_map{$k}->(@_); $s->(@_) }
: $s
: grep(/^$k$/, keys %sig_defined_map)
? sub { $sig_defined_map{$k}->(@_); $s; }
: $s;
}
}
sub CLONE {}
sub TIEHASH { bless({}, shift) }
sub STORE {
$usersig{$_[1]} = $_[2];
_STORE($_[1], $_[2]);
}
sub FETCH { $sig->{$_[1]} }
sub FIRSTKEY { my $a = scalar keys %{$sig}; each %{$sig} }
sub NEXTKEY { each %{$sig} }
sub EXISTS { exists $sig->{$_[1]} }
sub DELETE { _STORE($_[1], undef) }
sub CLEAR {
$_[0]->DELETE($_) while ($_) = each %{$sig};
return;
}
sub SCALAR { scalar %{$sig} }
1;
__END__
=head1 NAME
forks::signals - signal management for forks
=head1 DESCRIPTION
This module is only intended for internal use by L<forks>.
=head1 CREDITS
Implementation inspired by Cory Johns' L<libalarm/Alarm::_TieSIG>.
=head1 AUTHOR
Eric Rybski <rybskej@yahoo.com>. Please send all module inquries to me.
=head1 COPYRIGHT
Copyright (c)
2005-2007 Eric Rybski <rybskej@yahoo.com>.
All rights reserved. This program is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.
=head1 SEE ALSO
L<forks>
=cut
syntax highlighted by Code2HTML, v. 0.9.1