1.1.10 release

git-svn-id: svn://192.168.202.10@1 3d104415-ff17-0410-8863-d5cf3c621b8a
This commit is contained in:
root
2006-07-07 14:57:59 +00:00
commit 6ef43b97cf
706 changed files with 235239 additions and 0 deletions
+146
View File
@@ -0,0 +1,146 @@
#!/usr/bin/perl
### AST_VICI_conf.pl
###
### Copyright (C) 2006 Matt Florell <vicidial@gmail.com> LICENSE: GPLv2
###
### Customized Variables
$SIP_user = 'SIP/cc100'; # your phone id
$server_ip = '10.10.10.15'; # Asterisk server IP
$DB_server = '10.10.10.15'; # MySQL server IP
$DB_database = 'asterisk'; # MySQL database name
$DB_user = 'idcheck'; # MySQL user
$DB_pass = '1234'; # MySQL pass
$DB_port = '3306'; # MySQL connection port
### Constants
$record_channel='';
$filename='';
$recording_id='';
$US = '_';
$MT[0] = '';
return 1;
# this subroutine is to be used with the callerID function to customize the
# variables that are passed in the URL string and the way that they are passed,
# these are the variables you have to work with:
# $callerID_areacode
# $callerID_prefix
# $callerID_last4
# $callerID_Time
# $callerID_Channel
# $callerID_uniqueID
# $callerID_phone_ext
# $callerID_server_ip
# $callerID_extension
# $callerID_inbound_number
# $callerID_comment_a
# $callerID_comment_b
# $callerID_comment_c
# $callerID_comment_d
# $callerID_comment_e
sub create_callerID_local_query_string
{
$local_web_callerID_QUERY_STRING ='';
$local_web_callerID_QUERY_STRING.="?callerID_areacode=$callerID_areacode";
$local_web_callerID_QUERY_STRING.="&callerID_prefix=$callerID_prefix";
$local_web_callerID_QUERY_STRING.="&callerID_last4=$callerID_last4";
$local_web_callerID_QUERY_STRING.="&callerID_Time=$callerID_Time";
$local_web_callerID_QUERY_STRING.="&callerID_Channel=$callerID_Channel";
$local_web_callerID_QUERY_STRING.="&callerID_uniqueID=$callerID_uniqueID";
$local_web_callerID_QUERY_STRING.="&callerID_phone_ext=$callerID_phone_ext";
$local_web_callerID_QUERY_STRING.="&callerID_server_ip=$callerID_server_ip";
$local_web_callerID_QUERY_STRING.="&callerID_extension=$callerID_extension";
$local_web_callerID_QUERY_STRING.="&callerID_inbound_number=$callerID_inbound_number";
$local_web_callerID_QUERY_STRING.="&callerID_comment_a=$callerID_comment_a";
$local_web_callerID_QUERY_STRING.="&callerID_comment_b=$callerID_comment_b";
$local_web_callerID_QUERY_STRING.="&callerID_comment_c=$callerID_comment_c";
$local_web_callerID_QUERY_STRING.="&callerID_comment_d=$callerID_comment_d";
$local_web_callerID_QUERY_STRING.="&callerID_comment_e=$callerID_comment_e";
}
# $lead_id
# $vendor_id
# $list_id
# $phone_code
# $phone_number
# $title
# $first_name
# $middle_initial
# $last_name
# $address1
# $address2
# $address3
# $city
# $state
# $province
# $postal_code
# $country_code
# $gender
# $date_of_birth
# $alt_phone
# $email
# $security
# $comments
# $user
# $pass
# $fronter
# $closer
# $campaign
# $group
# $SQLdate
# $epoch
# $uniqueid
# $customer_zap_channel
# $server_ip
# $SIPexten
sub create_VICIDIAL_query_string
{
$VICIDIAL_web_QUERY_STRING ='';
$VICIDIAL_web_QUERY_STRING.="?lead_id=$lead_id";
$VICIDIAL_web_QUERY_STRING.="&vendor_id=$vendor_id";
$VICIDIAL_web_QUERY_STRING.="&list_id=$list_id";
$VICIDIAL_web_QUERY_STRING.="&phone_code=$phone_code";
$VICIDIAL_web_QUERY_STRING.="&phone_number=$phone_number";
$VICIDIAL_web_QUERY_STRING.="&title=$title";
$VICIDIAL_web_QUERY_STRING.="&first_name=$first_name";
$VICIDIAL_web_QUERY_STRING.="&middle_initial=$middle_initial";
$VICIDIAL_web_QUERY_STRING.="&last_name=$last_name";
$VICIDIAL_web_QUERY_STRING.="&address1=$address1";
$VICIDIAL_web_QUERY_STRING.="&address2=$address2";
$VICIDIAL_web_QUERY_STRING.="&address3=$address3";
$VICIDIAL_web_QUERY_STRING.="&city=$city";
$VICIDIAL_web_QUERY_STRING.="&state=$state";
$VICIDIAL_web_QUERY_STRING.="&province=$province";
$VICIDIAL_web_QUERY_STRING.="&postal_code=$postal_code";
$VICIDIAL_web_QUERY_STRING.="&country_code=$country_code";
$VICIDIAL_web_QUERY_STRING.="&gender=$gender";
$VICIDIAL_web_QUERY_STRING.="&date_of_birth=$date_of_birth";
$VICIDIAL_web_QUERY_STRING.="&alt_phone=$alt_phone";
$VICIDIAL_web_QUERY_STRING.="&email=$email";
$VICIDIAL_web_QUERY_STRING.="&security=$security";
$VICIDIAL_web_QUERY_STRING.="&comments=$comments";
$VICIDIAL_web_QUERY_STRING.="&user=$user";
$VICIDIAL_web_QUERY_STRING.="&pass=$userpass";
$VICIDIAL_web_QUERY_STRING.="&fronter=$fronter";
$VICIDIAL_web_QUERY_STRING.="&closer=$user";
$VICIDIAL_web_QUERY_STRING.="&campaign=$campaign";
$VICIDIAL_web_QUERY_STRING.="&group=$group";
$VICIDIAL_web_QUERY_STRING.="&channel_group=$channel_group";
$VICIDIAL_web_QUERY_STRING.="&SQLdate=$SQLdate";
$VICIDIAL_web_QUERY_STRING.="&epoch=$secX";
$VICIDIAL_web_QUERY_STRING.="&uniqueid=$uniqueid";
$VICIDIAL_web_QUERY_STRING.="&customer_zap_channel=$customer_zap_channel";
$VICIDIAL_web_QUERY_STRING.="&server_ip=$server_ip";
$VICIDIAL_web_QUERY_STRING.="&SIPexten=$SIPexten";
$VICIDIAL_web_QUERY_STRING.="&session_id=$session_id";
$VICIDIAL_web_QUERY_STRING.="&phone=$phone_number";
$VICIDIAL_web_QUERY_STRING.="&parked_by=$lead_id";
$VICIDIAL_web_QUERY_STRING =~ s/ /+/gi;
$VICIDIAL_web_QUERY_STRING =~ s/\`|\~|\:|\;|\#|\'|\"|\{|\}|\(|\)|\*|\^|\%|\$|\!|\%|\r|\t|\n//gi;
}
+146
View File
@@ -0,0 +1,146 @@
#!/usr/bin/perl
### AST_VICI_conf.pl
###
### Copyright (C) 2006 Matt Florell <vicidial@gmail.com> LICENSE: GPLv2
###
### Customized Variables
$SIP_user = 'SIP/cc100'; # your phone id
$server_ip = '10.10.10.15'; # Asterisk server IP
$DB_server = '10.10.10.15'; # MySQL server IP
$DB_database = 'asterisk'; # MySQL database name
$DB_user = 'idcheck'; # MySQL user
$DB_pass = '1234'; # MySQL pass
$DB_port = '3306'; # MySQL connection port
### Constants
$record_channel='';
$filename='';
$recording_id='';
$US = '_';
$MT[0] = '';
return 1;
# this subroutine is to be used with the callerID function to customize the
# variables that are passed in the URL string and the way that they are passed,
# these are the variables you have to work with:
# $callerID_areacode
# $callerID_prefix
# $callerID_last4
# $callerID_Time
# $callerID_Channel
# $callerID_uniqueID
# $callerID_phone_ext
# $callerID_server_ip
# $callerID_extension
# $callerID_inbound_number
# $callerID_comment_a
# $callerID_comment_b
# $callerID_comment_c
# $callerID_comment_d
# $callerID_comment_e
sub create_callerID_local_query_string
{
$local_web_callerID_QUERY_STRING ='';
$local_web_callerID_QUERY_STRING.="?callerID_areacode=$callerID_areacode";
$local_web_callerID_QUERY_STRING.="&callerID_prefix=$callerID_prefix";
$local_web_callerID_QUERY_STRING.="&callerID_last4=$callerID_last4";
$local_web_callerID_QUERY_STRING.="&callerID_Time=$callerID_Time";
$local_web_callerID_QUERY_STRING.="&callerID_Channel=$callerID_Channel";
$local_web_callerID_QUERY_STRING.="&callerID_uniqueID=$callerID_uniqueID";
$local_web_callerID_QUERY_STRING.="&callerID_phone_ext=$callerID_phone_ext";
$local_web_callerID_QUERY_STRING.="&callerID_server_ip=$callerID_server_ip";
$local_web_callerID_QUERY_STRING.="&callerID_extension=$callerID_extension";
$local_web_callerID_QUERY_STRING.="&callerID_inbound_number=$callerID_inbound_number";
$local_web_callerID_QUERY_STRING.="&callerID_comment_a=$callerID_comment_a";
$local_web_callerID_QUERY_STRING.="&callerID_comment_b=$callerID_comment_b";
$local_web_callerID_QUERY_STRING.="&callerID_comment_c=$callerID_comment_c";
$local_web_callerID_QUERY_STRING.="&callerID_comment_d=$callerID_comment_d";
$local_web_callerID_QUERY_STRING.="&callerID_comment_e=$callerID_comment_e";
}
# $lead_id
# $vendor_id
# $list_id
# $phone_code
# $phone_number
# $title
# $first_name
# $middle_initial
# $last_name
# $address1
# $address2
# $address3
# $city
# $state
# $province
# $postal_code
# $country_code
# $gender
# $date_of_birth
# $alt_phone
# $email
# $security
# $comments
# $user
# $pass
# $fronter
# $closer
# $campaign
# $group
# $SQLdate
# $epoch
# $uniqueid
# $customer_zap_channel
# $server_ip
# $SIPexten
sub create_VICIDIAL_query_string
{
$VICIDIAL_web_QUERY_STRING ='';
$VICIDIAL_web_QUERY_STRING.="?lead_id=$lead_id";
$VICIDIAL_web_QUERY_STRING.="&vendor_id=$vendor_id";
$VICIDIAL_web_QUERY_STRING.="&list_id=$list_id";
$VICIDIAL_web_QUERY_STRING.="&phone_code=$phone_code";
$VICIDIAL_web_QUERY_STRING.="&phone_number=$phone_number";
$VICIDIAL_web_QUERY_STRING.="&title=$title";
$VICIDIAL_web_QUERY_STRING.="&first_name=$first_name";
$VICIDIAL_web_QUERY_STRING.="&middle_initial=$middle_initial";
$VICIDIAL_web_QUERY_STRING.="&last_name=$last_name";
$VICIDIAL_web_QUERY_STRING.="&address1=$address1";
$VICIDIAL_web_QUERY_STRING.="&address2=$address2";
$VICIDIAL_web_QUERY_STRING.="&address3=$address3";
$VICIDIAL_web_QUERY_STRING.="&city=$city";
$VICIDIAL_web_QUERY_STRING.="&state=$state";
$VICIDIAL_web_QUERY_STRING.="&province=$province";
$VICIDIAL_web_QUERY_STRING.="&postal_code=$postal_code";
$VICIDIAL_web_QUERY_STRING.="&country_code=$country_code";
$VICIDIAL_web_QUERY_STRING.="&gender=$gender";
$VICIDIAL_web_QUERY_STRING.="&date_of_birth=$date_of_birth";
$VICIDIAL_web_QUERY_STRING.="&alt_phone=$alt_phone";
$VICIDIAL_web_QUERY_STRING.="&email=$email";
$VICIDIAL_web_QUERY_STRING.="&security=$security";
$VICIDIAL_web_QUERY_STRING.="&comments=$comments";
$VICIDIAL_web_QUERY_STRING.="&user=$user";
$VICIDIAL_web_QUERY_STRING.="&pass=$userpass";
$VICIDIAL_web_QUERY_STRING.="&fronter=$fronter";
$VICIDIAL_web_QUERY_STRING.="&closer=$user";
$VICIDIAL_web_QUERY_STRING.="&campaign=$campaign";
$VICIDIAL_web_QUERY_STRING.="&group=$group";
$VICIDIAL_web_QUERY_STRING.="&channel_group=$channel_group";
$VICIDIAL_web_QUERY_STRING.="&SQLdate=$SQLdate";
$VICIDIAL_web_QUERY_STRING.="&epoch=$secX";
$VICIDIAL_web_QUERY_STRING.="&uniqueid=$uniqueid";
$VICIDIAL_web_QUERY_STRING.="&customer_zap_channel=$customer_zap_channel";
$VICIDIAL_web_QUERY_STRING.="&server_ip=$server_ip";
$VICIDIAL_web_QUERY_STRING.="&SIPexten=$SIPexten";
$VICIDIAL_web_QUERY_STRING.="&session_id=$session_id";
$VICIDIAL_web_QUERY_STRING.="&phone=$phone_number";
$VICIDIAL_web_QUERY_STRING.="&parked_by=$lead_id";
$VICIDIAL_web_QUERY_STRING =~ s/ /+/gi;
$VICIDIAL_web_QUERY_STRING =~ s/\`|\~|\:|\;|\#|\'|\"|\{|\}|\(|\)|\*|\^|\%|\$|\!|\%|\r|\t|\n//gi;
}
+14
View File
@@ -0,0 +1,14 @@
ACT|0200|0399
NT|0800|0999
NSW|1000|2599
ACT|2600|2618
NSW|2619|2899
ACT|2900|2920
NSW|2921|2999
VIC|3000|3999
QLD|4000|4999
SA|5000|5999
WA|6000|6999
TAS|7000|7999
VIC|8000|8999
QLD|9000|9999
+20
View File
@@ -0,0 +1,20 @@
package Asterisk;
require 5.004;
$VERSION = '0.08';
sub version { $VERSION; }
sub new {
my ($class, %args) = @_;
my $self = {};
$self->{configfile} = undef;
$self->{config} = {};
bless $self, ref $class || $class;
return $self;
}
sub DESTROY { }
1;
+685
View File
@@ -0,0 +1,685 @@
package Asterisk::AGI;
require 5.004;
use Asterisk;
@ISA = ( 'Asterisk' );
=head1 NAME
Asterisk::AGI - Simple Asterisk Gateway Interface Class
=head1 SYNOPSIS
use Asterisk::AGI;
$AGI = new Asterisk::AGI;
# pull AGI variables into %input
%input = $AGI->ReadParse();
# say the number 1984
$AGI->say_number(1984);
=head1 DESCRIPTION
This module should make it easier to write scripts that interact with the
asterisk open source pbx via AGI (asterisk gateway interface)
=head1 AGI COMMANDS
=cut
sub new {
my ($class, %args) = @_;
my $self = {};
$self->{'callback'} = undef;
$self->{'status'} = undef;
$self->{'lastresponse'} = undef;
bless $self, ref $class || $class;
return $self;
}
sub ReadParse {
my ($self, $fh) = @_;
my %input = ();
$fh = \*STDIN if (!$fh);
while (<$fh>) {
chomp;
last unless length($_);
if (/^agi_(\w+)\:\s+(.*)$/) {
$input{$1} = $2;
}
}
if (defined($DEBUG)&&($DEBUG>0)) {
print STDERR "AGI Environment Dump:\n";
foreach $i (sort keys %input) {
print STDERR " -- $i = $input{$i}\n";
}
}
return %input;
}
sub setcallback {
my ($self, $function) = @_;
if (defined($function) && ref($function) eq 'CODE') {
$self->{'callback'} = $function;
}
}
sub callback {
my ($self, $result) = @_;
if (defined($self->{'callback'}) && ref($self->{'callback'}) eq 'CODE') {
&{$self->{'callback'}}($result);
}
}
sub execute {
my ($self, $command) = @_;
$self->_execcommand($command);
my $res = $self->_readresponse();
return $self->_checkresult($res);
}
sub _execcommand {
my ($self, $command, $fh) = @_;
$fh = \*STDOUT if (!$fh);
select ((select ($fh), $| = 1)[0]);
return -1 if (!defined($command));
return print $fh "$command\n";
}
sub _readresponse {
my ($self, $fh) = @_;
my $response = undef;
$fh = \*STDIN if (!$fh);
$response = <$fh> || return '200 result=-1 (noresponse)';
chomp($response);
return $response;
}
sub _checkresult {
my ($self, $response) = @_;
return undef if (!defined($response));
my $result = undef;
$self->_lastresponse($response);
if ($response =~ /^200/) {
if ($response =~ /result=(-?[\d*#]+)/) {
$result = $1;
}
} elsif ($response =~ /\(noresponse\)/) {
$self->_status('noresponse');
} else {
print STDERR "Unexpected result '$response'\n" if (defined($DEBUG) && $DEBUG);
}
print STDERR "_checkresult($response) = $result\n" if (defined($DEBUG) && $DEBUG>3);
return $result;
}
sub _status {
my ($self, $status) = @_;
if (defined($status)) {
$self->{'status'} = $status;
} else {
return $self->{'status'};
}
}
sub _lastresponse {
my ($self, $response) = @_;
if (defined($response)) {
$self->{'lastresponse'} = $response;
} else {
return $self->{'lastresponse'};
}
}
=over 4
=item $AGI->stream_file($filename, $digits)
Executes AGI Command "STREAM FILE $filename $digits"
This command instructs Asterisk to play the given sound file and listen for the given dtmf digits. The
fileextension must not be used in the filename because Asterisk will find the most appropriate file
type.
Example: $AGI->stream_file('demo-echotest', '0123');
Returns: -1 on error or hangup,
0 if playback completes without a digit being pressed,
or the ASCII numerical value of the digit if a digit was pressed
=cut
sub stream_file {
my ($self, $filename, $digits) = @_;
my $ret = 0;
$digits = '""' if (!defined($digits));
return -1 if (!defined($filename));
$ret = $self->execute("STREAM FILE $filename $digits");
$self->callback($ret) if ($ret == -1);
return $ret;
}
=item $AGI->send_text($text)
Executes AGI Command "SEND TEXT "$text"
Sends the given text on a channel. Most channels do not support the transmission of text.
Example: $AGI->send_text('You've got mail!');
Returns: -1 on error or hangup,
0 if the text was sent or if the channel does not support text transmission.
=cut
sub send_text {
my ($self, $text) = @_;
my $ret = 0;
return $ret if (!defined($text));
$ret = $self->execute("SEND TEXT \"$text\"");
$self->callback($ret) if ($ret == -1);
return $ret;
}
=item $AGI->send_image($image)
Executes AGI Command "SEND IMAGE $image
Sends the given image on a channel. Most channels do not support the transmission of images.
Example: $AGI->send_image('image.png');
Returns: -1 on error or hangup,
0 if the image was sent or if the channel does not support image transmission.
=cut
sub send_image {
my ($self, $image) = @_;
my $ret = 0;
return -1 if (!defined($image));
$ret = $self->execute("SEND IMAGE $image");
$self->callback($ret) if ($ret == -1);
return $ret;
}
=item $AGI->say_number($number, $digits)
Executes AGI Command "SAY NUMBER $number $digits"
Says the given $number, returning early if any of the $digits are received.
Example: $AGI->say_number('98765');
Returns: -1 on error or hangup,
0 if playback completes without a digit being pressed,
or the ASCII numerical value of the digit of one was pressed.
=cut
sub say_number {
my ($self, $number, $digits) = @_;
my $ret = 0;
$digits = '""' if (!defined($digits));
return -1 if (!defined($number));
$number =~ s/\D//g;
$ret = $self->execute("SAY NUMBER $number $digits");
$self->callback($ret) if ($ret == -1);
return $ret;
}
=item $AGI->say_digits($number, $digits)
Executes AGI Command "SAY DIGITS $number $digits"
Says the given digit string $number, returning early if any of the $digits are received.
Example: $AGI->say_digits('8675309');
Returns: -1 on error or hangup,
0 if playback completes without a digit being pressed,
or the ASCII numerical value of the digit of one was pressed.
=cut
sub say_digits {
my ($self, $number, $digits) = @_;
my $ret = 0;
$digits = '""' if (!defined($digits));
return -1 if (!defined($number));
$number =~ s/\D//g;
$ret = $self->execute("SAY DIGITS $number $digits");
$self->callback($ret) if ($ret == -1);
return $ret;
}
=item $AGI->answer()
Executes AGI Command "ANSWER"
Answers channel if not already in answer state
Example: $AGI->answer();
Returns: -1 on channel failure, or
0 if successful
=cut
sub answer {
my ($self) = @_;
my $ret = 0;
$ret = $self->execute('ANSWER');
$self->callback($ret) if ($ret == -1);
return $ret;
}
=item $AGI->get_data($filename, $timeout, $maxdigits)
Executes AGI Command "GET DATA $filename $timeout $maxdigits"
Streams $filename and returns when $maxdigits have been received or
when $timeout has been reached. Timeout is specified in ms
Example: $AGI->get_data('demo-welcome', 15000, 5);
=cut
sub get_data {
my ($self, $filename, $timeout, $maxdigits) = @_;
my $ret = undef;
return -1 if (!defined($filename));
$ret = $self->execute("GET DATA $filename $timeout $maxdigits");
$self->callback($ret) if ($ret == -1);
return $ret;
}
=item $AGI->set_callerid($number)
Executes AGI Command "SET CALLERID $number"
Changes the callerid of the current channel to <number>
Example: $AGI->set_callerid('9995551212');
Returns: Always returns 1
=cut
sub set_callerid {
my ($self, $number) = @_;
return if (!defined($number));
return $self->execute("SET CALLERID $number");
}
=item $AGI->set_context($context)
Executes AGI Command "SET CONTEXT $context"
Changes the context for continuation upon exiting the agi application
Example: $AGI->set_context('dialout');
Returns: Always returns 0
=cut
sub set_context {
my ($self, $context) = @_;
return -1 if (!defined($context));
return $self->execute("SET CONTEXT $context");
}
=item $AGI->set_extension($extension)
Executes AGI Command "SET EXTENSION $extension"
Changes the extension for continuation upon exiting the agi application
Example: $AGI->set_extension('7');
Returns: Always returns 0
=cut
sub set_extension {
my ($self, $extension) = @_;
return -1 if (!defined($extension));
return $self->execute("SET EXTENSION $extension");
}
=item $AGI->set_priority($priority)
Executes AGI Command "SET PRIORITY $priority"
Changes the priority for continuation upon exiting the agi application
Example: $AGI->set_priority(1);
Returns: Always returns 0
=cut
sub set_priority {
my ($self, $priority) = @_;
return -1 if (!defined($priority));
return $self->execute("SET PRIORITY $priority");
}
sub receive_char {
my ($self, $timeout) = @_;
my $ret = 0;
#wait forever if timeout is not set. is this the prefered default?
$timeout = 0 if (!defined($timeout));
$ret = $self->execute("RECEIVE CHAR $timeout");
$self->callback($ret) if ($ret == -1);
return $ret;
}
sub tdd_mode {
my ($self, $mode) = @_;
return 0 if (!defined($mode));
return $self->execute("TDD MODE $mode");
}
sub wait_for_digit {
my ($self, $timeout) = @_;
my $ret = 0;
$timeout = -1 if (!defined($timeout));
$ret = $self->execute("WAIT FOR DIGIT $timeout");
$self->callback($ret) if ($ret == -1);
return $ret;
}
sub record_file {
my ($self, $filename, $format, $digits, $timeout, $beep) = @_;
my $ret = 0;
return -1 if (!defined($filename));
$digits = '""' if (!defined($digits));
$ret = $self->execute("RECORD FILE $filename $format $digits $timeout");
$self->callback($ret) if ($ret == -1);
return $ret;
}
sub set_autohangup {
my ($self, $time) = @_;
$time = 0 if (!defined($time));
return $self->execute("SET AUTOHANGUP $time");
}
=item $AGI->hangup($channel)
Executes AGI Command "HANGUP $channel"
Hangs up the passed $channel, or the current channel if $channel is not passed.
It is left to the AGI script to exit properly, otherwise you could end up with zombies.
Example: $AGI->hangup();
Returns: Always returns 1
=cut
sub hangup {
my ($self, $channel) = @_;
if ($channel) {
return $self->execute("HANGUP $channel");
} else {
return $self->execute("HANGUP");
}
}
=item $AGI->exec($app, $options)
Executes AGI Command "EXEC $app $options"
The most powerful AGI command. Executes the given application passing the given options.
Example: $AGI->exec('Dial', 'Zap/g2/8005551212');
Returns: -2 on failure to find application, or
whatever the given application returns
=cut
sub exec {
my ($self, $app, $options) = @_;
return -1 if (!defined($app));
$options = '""' if (!defined($options));
return $self->execute("EXEC $app $options");
}
sub channel_status {
my ($self, $channel) = @_;
return $self->execute("CHANNEL STATUS $channel");
}
=item $AGI->set_variable($variable, $value)
Executes AGI Command "SET VARIABLE $variable $value"
Sets the channel variable <variablename> to <value>
Example: $AGI->set_variable('status', 'authorized');
Returns: Always returns 1
=cut
sub set_variable {
my ($self, $variable, $value) = @_;
return $self->execute("SET VARIABLE $variable $value");
}
=item $AGI->get_variable($variable)
Executes AGI Command "GET VARIABLE $variablename"
Gets the channel variable <variablename>
Example: $AGI->get_variable('status');
Returns: The value of the variable, or undef if variable does not exist
=cut
sub get_variable {
my ($self, $variable) = @_;
my $result = undef;
if ($self->execute("GET VARIABLE $variable")) {
my $tempresult = $self->_lastresponse();
if ($tempresult =~ /\((.*)\)/) {
$result = $1;
}
}
return $result;
}
=item $AGI->verbose($message, $level)
Executes AGI Command "VERBOSE $message $level"
Logs $message with verboselevel $level
Example: $AGI->verbose("System Crashed\n", 1);
Returns: Always returns 1
=cut
sub verbose {
my ($self, $message, $level) = @_;
return $self->execute("VERBOSE \"$message\" $level");
}
=item $AGI->database_get($family, $key)
Executes AGI Command "DATABASE GET $family $key"
Example: $var = $AGI->database_get('test', 'status');
Returns: The value of the variable, or undef if variable does not exist
=cut
sub database_get {
my ($self, $family, $key) = @_;
my $result = undef;
if ($self->execute("DATABASE GET $family $key")) {
my $tempresult = $self->_lastresponse();
if ($tempresult =~ /\((.*)\)/) {
$result = $1;
}
}
return $result;
}
=item $AGI->database_put($family, $key, $value)
Executes AGI Command "DATABASE PUT $family $key $value"
Set/modifes database entry <family>/<key> to <value>
Example: $AGI->database_put('test', 'status', 'authorized');
Returns: 1 on success, 0 otherwise
=cut
sub database_put {
my ($self, $family, $key, $value) = @_;
return $self->execute("DATABASE PUT $family $key $value");
}
=item $AGI->database_del($family, $key)
Executes AGI Command "DATABASE DEL $family $key"
Removes database entry <family>/<key>
Example: $AGI->database_del('test', 'status');
Returns: 1 on success, 0 otherwise
=cut
sub database_del {
my ($self, $family, $key) = @_;
return $self->execute("DATABASE DEL $family $key");
}
=item $AGI->database_deltree($family, $key)
Executes AGI Command "DATABASE DELTREE $family $key"
Deletes a family or specific keytree within a family in the Asterisk database
Example: $AGI->database_deltree('test', 'status');
Example: $AGI->database_deltree('test');
Returns: 1 on success, 0 otherwise
=cut
sub database_deltree {
my ($self, $family, $key) = @_;
return $self->execute("DATABASE DELTREE $family $key");
}
sub noop {
my ($self) = @_;
return $self->execute("NOOP");
}
sub set_music {
my ($self, $mode, $class) = @_;
return $self->execute("SET MUSIC $mode $class");
}
1;
__END__
=back
+412
View File
@@ -0,0 +1,412 @@
package Asterisk::Manager;
require 5.004;
use Asterisk;
use IO::Socket;
use Digest::MD5;
#use strict;
#use warnings;
=head1 NAME
Asterisk::Manager - Asterisk Manager Interface
=head1 SYNOPSIS
use Asterisk::Manager;
my $astman = new Asterisk::Manager;
$astman->user('username');
$astman->secret('test');
$astman->host('localhost');
$astman->connect || die "Could not connect to " . $astman->host . "!\n";
$astman->disconnect;
=head1 DESCRIPTION
This module provides a simple interface to the asterisk manager interface.
=cut
my $EOL = "\r\n";
my $BLANK = $EOL x 2;
my $VERSION = '0.01';
sub version { $VERSION; }
sub new {
my ($class, %args) = @_;
my $self = {};
$self->{_CONNFD} = undef;
$self->{_PROTOVERS} = undef;
$self->{_ERRORSTR} = undef;
$self->{_HOST} = 'localhost';
$self->{_PORT} = 5038;
$self->{_USER} = undef;
$self->{_SECRET} = undef;
$self->{_EVENTCB} = {};
$self->{_DEBUG} = 0;
$self->{_CONNECTED} = 0;
bless $self, ref $class || $class;
return $self;
}
sub DESTROY { }
sub user {
my ($self, $user) = @_;
if ($user) {
$self->{_USER} = $user;
}
return $self->{_USER};
}
sub secret {
my ($self, $secret) = @_;
if ($secret) {
$self->{_SECRET} = $secret;
}
return $self->{_SECRET};
}
sub host {
my ($self, $host) = @_;
if ($host) {
$self->{_HOST} = $host;
}
return $self->{_HOST};
}
sub port {
my ($self, $port) = @_;
if ($port) {
$self->{_PORT} = $port;
}
return $self->{_PORT};
}
sub connected {
my ($self, $connected) = @_;
if (defined($connected)) {
$self->{_CONNECTED} = $connected;
}
return $self->{_CONNECTED};
}
sub error {
my ($self, $error) = @_;
if ($error) {
$self->{_ERRORSTR} = $error;
}
return $self->{_ERRORSTR};
}
sub debug {
my ($self, $debug) = @_;
if ($debug) {
$self->{_DEBUG} = $debug;
}
return $self->{_DEBUG};
}
sub connfd {
my ($self, $connfd) = @_;
if ($connfd) {
$self->{_CONNFD} = $connfd;
}
return $self->{_CONNFD};
}
sub read_response {
my ($self, $connfd) = @_;
my @response;
if (!$connfd) {
$connfd = $self->connfd;
}
while (my $line = <$connfd>) {
last if ($line eq $EOL);
if (wantarray) {
$line =~ s/$EOL//g;
push(@response, $line) if $line;
} else {
$response[0] .= $line;
}
}
return wantarray ? @response : $response[0];
}
sub connect {
my ($self) = @_;
my $host = $self->host;
my $port = $self->port;
my $user = $self->user;
my $secret = $self->secret;
my %resp;
my $conn = new IO::Socket::INET( Proto => 'tcp',
PeerAddr => $host,
PeerPort => $port
);
if (!$conn) {
$self->error("Connection refused ($host:$port)\n");
return undef;
}
$conn->autoflush(1);
my $input = <$conn>;
$input =~ s/$EOL//g;
my ($manager, $version) = split('/', $input);
if ($manager !~ /Asterisk Call Manager/) {
return $self->error("Unknown Protocol\n");
}
$self->{_PROTOVERS} = $version;
$self->connfd($conn);
# check if the remote host supports MD5 Challenge authentication
my %authresp = $self->sendcommand( Action => 'Challenge',
AuthType => 'MD5'
);
if (($authresp{Response} eq 'Success')) {
# do md5 login
my $md5 = new Digest::MD5;
$md5->add($authresp{Challenge});
$md5->add($secret);
my $digest = $md5->hexdigest;
%resp = $self->sendcommand( Action => 'Login',
AuthType => 'MD5',
Username => $user,
Key => $digest
);
} else {
# do plain text login
%resp = $self->sendcommand( Action => 'Login',
Username => $user,
Secret => $secret
);
}
if ( ($resp{Response} ne 'Success') && ($resp{Message} ne 'Authentication accepted') ) {
$self->error("Authentication failed for user $user\n");
return undef;
}
$self->connected(1);
return $conn;
}
sub astman_h2s {
my ($self, %thash) = @_;
my $tstring = '';
foreach my $key (keys %thash) {
$tstring .= $key . ': ' . $thash{$key} . ${EOL};
}
return $tstring;
}
sub astman_s2h {
my ($self, $tstring) = @_;
my %thash;
foreach my $line (split(/$EOL/, $tstring)) {
if ($line =~ /(\w*):\s*(\w*)/) {
$thash{$1} = $2;
}
}
return %thash;
}
#$want is how you want the data returned
#$want = 0 (default) returns the results in a hash
#$want = 1 returns the results in a large string
#$want = 2 returns the results in an array
sub sendcommand {
my ($self, %command, $want) = @_;
if (!defined($want)) {
$want = 0;
}
my $conn = $self->connfd || return;
my $cstring = $self->astman_h2s(%command);
$conn->send("$cstring$EOL");
if ($want == 1) {
my $response = $self->read_response($conn);
return $response;
}
my @resp = $self->read_response($conn);
if ($want == 2) {
return @resp;
} else {
return map { split(': ', $_) } @resp;
}
}
sub setcallback {
my ($self, $event, $function) = @_;
if (defined($function) && ref($function) eq 'CODE') {
$self->{_EVENTCB}{$event} = $function;
}
}
sub eventcallback {
my ($self, %resp) = @_;
my $callback;
my $event = $resp{Event};
return if (!$event);
if (defined($self->{_EVENTCB}{$event})) {
$callback = $self->{_EVENTCB}{$event};
} elsif (defined($self->{_EVENTCB}{DEFAULT})) {
$callback = $self->{_EVENTCB}{DEFAULT};
} else {
return;
}
return &{$callback}(%resp);
}
sub eventloop {
my ($self) = @_;
while (1) {
$self->handleevent;
}
}
sub handleevent {
my ($self) = @_;
my %resp = map { split(': ', $_); } $self->read_response;
$self->eventcallback(%resp);
return %resp;
}
sub action {
my ($self, $command, $wanthash) = @_;
return if (!$command);
my $conn = $self->connfd || return;
print $conn "Action: $command" . $BLANK;
my @resp = $self->read_response($conn);
if ($wanthash) {
return map { split(': ', $_) } @resp;
} elsif (wantarray) {
return @resp;
} else {
return $resp[0];
}
}
sub command {
my ($self, $command) = @_;
return if (!$command);
return $self->sendcommand('Action' => 'Command',
'Command' => $command, 1 );
}
sub monitor {
my ($self, $channel, $file) = @_;
return if (!$channel);
return $self->sendcommand('Action' => 'Monitor',
'Channel' => $channel,
'File' => $file, 1 );
}
sub changemonitor {
my ($self, $channel, $file) = @_;
return if (!$channel);
return $self->sendcommand('Action' => 'ChangeMonitor',
'Channel' => $channel,
'File' => $file, 1 );
}
sub stopmonitor {
my ($self, $channel, $file) = @_;
return if (!$channel);
return $self->sendcommand('Action' => 'StopMonitor',
'Channel' => $channel,
'File' => $file, 1 );
}
sub disconnect {
my ($self) = @_;
my $conn = $self->connfd;
my %resp = $self->sendcommand('Action' => 'Logoff');
if ($resp{Response} eq 'Goodbye') {
$self->{_CONNFD} = undef;
$self->connected(0);
return 1;
}
return 0;
}
1;
+110
View File
@@ -0,0 +1,110 @@
package Asterisk::Outgoing;
=head1 NAME
Asterisk::Outgoing - Create outgoing call queue file
=head1 SYNOPSIS
use Asterisk::Outgoing;
my $out = new Asterisk::Outgoing;
$out->setvariable('Channel', 'Zap/1/');
$out->setvariable('MaxRetries', 0);
$out->setvariable('RetryTime', 60);
$out->setvariable('WaitTime', 60);
$out->setvariable('Application', 'Playback');
$out->setvariable('Data', 'beep');
$out->create_outgoing;
=cut
require 5.004;
use Fcntl ':flock';
use Asterisk;
@ISA = ('Asterisk');
$VERSION = '0.01';
sub new {
my ($class, %args) = @_;
my $self = {};
$self->{OUTDIR} = '/var/spool/asterisk/outgoing';
$self->{OUTTIME} = undef;
$self->{OUTVARS} = {};
$self->{ALLOWEDVARS} = [ 'channel', 'maxretries', 'retrytime', 'waittime', 'context', 'extension', 'priority', 'application', 'data', 'callerid' ];
bless $self, ref $class || $class;
return $self;
}
sub outdir {
my ($self, $dir) = @_;
if (defined($dir)) {
$self->{OUTDIR} = $dir;
}
return $self->{OUTDIR};
}
sub outtime {
my ($self, $time) = @_;
if (defined($time)) {
$self->{OUTTIME} = $time;
} elsif (!defined($self->{OUTTIME})) {
$self->{OUTTIME} = time();
}
return $self->{OUTTIME};
}
sub checkvariable {
my ($self, $var) = @_;
my $ret = 0;
foreach $allowed (@{$self->{ALLOWEDVARS}}) {
if ($allowed =~ /$var/i) {
$ret = 1;
}
}
return $ret;
}
sub setvariable {
my ($self, $var, $value) = @_;
if ($self->checkvariable($var)) {
$self->{OUTVARS}{$var} = $value;
}
}
sub create_outgoing {
my ($self) = @_;
my $time = $self->outtime();
my $outdir = $self->outdir();
my $filename = $outdir . '/' . $time . '.outgoing';
open(OUTFILE, ">$filename") || return 0;
flock(OUTFILE, LOCK_EX);
utime($time, $time, $filename);
foreach my $var (keys %{$self->{OUTVARS}}) {
print OUTFILE "$var: " . $self->{OUTVARS}{$var} . "\n";
}
flock(OUTFILE, LOCK_UN);
close(OUTFILE);
utime($time, $time, $filename);
return 1;
}
1;
+61
View File
@@ -0,0 +1,61 @@
package Asterisk::QCall;
require 5.004;
use Fcntl ':flock';
use Asterisk;
$VERSION = '0.01';
sub version { $VERSION; }
sub new {
my ($class, %args) = @_;
my $self = {};
$self->{QUEUEDIR} = '/var/spool/asterisk/qcall';
$self->{QUEUETIME} = undef;
bless $self, ref $class || $class;
return $self;
}
sub DESTROY { }
sub queuedir {
my ($self, $dir) = @_;
if (defined($dir)) {
$self->{QUEUEDIR} = $dir;
}
return $self->{QUEUEDIR};
}
sub queuetime {
my ($self, $time) = @_;
if (defined($time)) {
$self->{QUEUETIME} = $time;
} elsif (!defined($self->{QUEUETIME})) {
$self->{QUEUETIME} = time();
}
return $self->{QUEUETIME};
}
sub create_qcall {
my ($self, $dialstring, $callerid, $extension, $maxsecs, $identifier, $response) = @_;
my $time = $self->queuetime();
my $queuedir = $self->queuedir();
my $filename = $queuedir . '/' . $time . '.queue';
open(QFILE, ">$filename") || return 0;
flock(QFILE, LOCK_EX);
print QFILE "$dialstring $callerid $extension $maxsecs $identifier $response";
flock(QFILE, LOCK_UN);
close(QFILE);
my $ret = utime($time, $time, $filename);
return 1;
}
1;
+261
View File
@@ -0,0 +1,261 @@
package Asterisk::Voicemail;
require 5.004;
=head1 NAME
Asterisk::Voicemail - Stuff to deal with asterisk voicemail
=head1 SYNOPSIS
This is not completed yet
=head1 DESCRIPTION
description
=cut
use Asterisk;
@ISA = ( 'Asterisk' );
$VERSION = '0.01';
$DEBUG = 5;
sub version { $VERSION; }
sub new {
my ($class, %args) = @_;
my $self = {};
bless $self, ref $class || $class;
# while (my ($key,$value) = each %args) { $self->set($key,$value); }
return $self;
}
sub DESTROY { }
sub spooldirectory {
my ($self, $directory) = @_;
if (defined($directory)) {
$self->{'spooldirectory'} = $directory;
} else {
$self->{'spooldirectory'} = '/var/spool/asterisk/vm' if (!defined($self->{'spooldirectory'}));
}
return $self->{'spooldirectory'};
}
sub sounddirectory {
my ($self, $directory) = @_;
if (defined($directory)) {
$self->{'sounddirectory'} = $directory;
} else {
$self->{'sounddirectory'} = '/var/lib/asterisk/sounds' if (!defined($self->{'sounddirectory'}));
}
return $self->{'sounddirectory'};
}
sub serveremail {
my ($self, $email) = @_;
$self->{'serveremail'} = $email if (defined($email));
return $self->{'serveremail'};
}
sub format {
my ($self, @formats) = @_;
if (@formats) {
$self->{'formats'} = @formats;
}
return $self->{'formats'};
}
sub vmbox {
my ($self, $vmbox, $vmpass, $vmfn, $vmemail) = @_;
if (defined($vmbox) && (defined($vmpass) || defined($vmfn) || defined($vmemail)) ) {
$self->{'vmbox'}{$vmbox}{'pass'} = $vmpass if (defined($vmpass));
$self->{'vmbox'}{$vmbox}{'fn'} = $vmfn if (defined($vmfn));
$self->{'vmbox'}{$vmbox}{'email'} = $vmemail if (defined($vmemail));
} elsif (defined($vmbox)) {
return ($self->{'vmbox'}{$vmbox}{'pass'},
$self->{'vmbox'}{$vmbox}{'fn'},
$self->{'vmbox'}{$vmbox}{'email'} );
}
}
sub getfolders {
my ($self, $vmbox) = @_;
my @folders = ();
my $spool = $self->spooldirectory();
foreach $file (<$spool/$vmbox/*>) {
if ( -d $file ) {
$file =~ s/$spool\/$vmbox\///;
push(@folders, $file);
}
}
return @folders;
}
sub configfile {
my ($self, $configfile) = @_;
if (defined($configfile)) {
$self->{'configfile'} = $configfile;
} else {
$self->{'configfile'} = '/etc/asterisk/voicemail.conf' if (!defined($self->{'configfile'}));
}
return $self->{'configfile'};
}
sub readconfig {
my ($self) = @_;
my $context = '';
my $line = '';
my $configfile = $self->configfile();
open(CF, "<$configfile") || die "Error loading $configfile: $!\n";
while ($line = <CF>) {
chop($line);
$line =~ s/;.*$//;
$line =~ s/\s*$//;
if ($line =~ /^;/) {
next;
} elsif ($line =~ /^\s*$/) {
next;
} elsif ($line =~ /^\[(\w+)\]$/) {
$context = $1;
print STDERR "Context: $context\n" if ($DEBUG>3);
} elsif ($line =~ /^format\s*[=>]+\s*(.*)/) {
my $formats = $1;
$self->format(split(/|/, $formats));
} elsif ($line =~ /^serveremail\s*[=>]+\s*(.*)/) {
$self->serveremail($1);
} elsif ($line =~ /^(\d+)\s*[=>]+\s*(.*)/) {
my $vmbox = $1;
my $vmstr = $2;
my ($vmpass, $vmfn, $vmemail) = split(/,/, $vmstr);
print STDERR "VM BOX ($vmbox)\n" if ($DEBUG>3);
$self->vmbox($vmbox, $vmpass, $vmfn, $vmstr);
} else {
print STDERR "Unknown line: $line\n" if ($DEBUG);
}
}
close(CF);
}
sub appendsoundfile {
my ($self, $source, $dest) = @_;
open(IN, "<$source") || return 0;
open(OUT, ">>$dest") || return 0;
while (<IN>) {
print OUT $_;
}
close(IN);
close(OUT);
return 1;
}
sub validmailbox {
my ($self, $vmbox) = @_;
return 1 if ($self->vmbox($vmbox));
return 0;
}
sub msgcount {
my ($self, $vmbox, $folder) = @_;
my $count = 0;
return $count if (!defined($vmbox) || !defined($folder));
my $spool = $self->spooldirectory() . '/' . $vmbox . '/' . $folder;
if (opendir(DIR, $spool)) {
my @msgs = grep(/^msg.*\.txt$/, readdir(DIR));
$count = $#msgs+1;
closedir(DIR);
}
return $count;
}
sub msgcountstr {
my ($self, $vmbox, $folder) = @_;
my $count = $self->msgcount($vmbox, $folder);
if ($count > 1) {
return "$count messages";
} elsif ($count > 0) {
return "$count message";
} else {
return "no messages";
}
}
sub createdefaultmailbox {
my ($self, $vmbox) = @_;
my $spool = $self->spooldirectory();
my $sounddir = $self->sounddirectory();
my $vmdir = "$spool/$vmbox";
if ( -d $vmdir ) {
print STDERR "Directory already exists: $vmdir\n" if ($DEBUG);
} else {
mkdir($vmdir, 0755) || return 0;
mkdir("$vmdir/INBOX", 0755) || return 0;
}
$self->appendsoundfile("$sounddir/vm-theperson.gsm", "$vmdir/unavail.gsm");
$self->appendsoundfile("$sounddir/vm-theperson.gsm", "$vmdir/busy.gsm");
$self->appendsoundfile("$sounddir/vm-extension.gsm", "$vmdir/greet.gsm");
foreach $chr (split(//, $vmbox)) {
$self->appendsoundfile("$sounddir/digits/$chr.gsm", "$vmdir/unavail.gsm");
$self->appendsoundfile("$sounddir/digits/$chr.gsm", "$vmdir/busy.gsm");
$self->appendsoundfile("$sounddir/digits/$chr.gsm", "$vmdir/greet.gsm");
}
$self->appendsoundfile("$sounddir/vm-isunavail.gsm", "$vmdir/unavail.gsm");
$self->appendsoundfile("$sounddir/vm-isonphone.gsm", "$vmdir/busy.gsm");
return 1;
}
sub messages {
my ($self, $messages, $folder) = @_;
my $path = $self->spooldirectory() . '/' . $mailbox . '/' . $folder;
if (opendir(DIR, $path)) {
my @msgs = sort grep(/^msg....\.txt$/, readdir(DIR));
closedir(DIR);
return map { s/^msg(....)\.txt$/$1/; $_ } @msgs;
}
return ();
}
1;
File diff suppressed because it is too large Load Diff
+266
View File
@@ -0,0 +1,266 @@
package Net::HTTP;
# $Id: HTTP.pm,v 1.43 2002/12/26 09:13:53 gisle Exp $
use strict;
use vars qw($VERSION @ISA);
$VERSION = "1.00";
eval { require IO::Socket::INET } || require IO::Socket;
require Net::HTTP::Methods;
@ISA=qw(IO::Socket::INET Net::HTTP::Methods);
sub configure {
my($self, $cnf) = @_;
$self->http_configure($cnf);
}
sub http_connect {
my($self, $cnf) = @_;
$self->SUPER::configure($cnf);
}
1;
__END__
=head1 NAME
Net::HTTP - Low-level HTTP connection (client)
=head1 SYNOPSIS
use Net::HTTP;
my $s = Net::HTTP->new(Host => "www.perl.com) || die $@;
$s->write_request(GET => "/", 'User-Agent' => "Mozilla/5.0");
my($code, $mess, %h) = $s->read_response_headers;
while (1) {
my $buf;
my $n = $s->read_entity_body($buf, 1024);
die "read failed: $!" unless defined $n;
last unless $n;
print $buf;
}
=head1 DESCRIPTION
The C<Net::HTTP> class is a low-level HTTP client. An instance of the
C<Net::HTTP> class represents a connection to an HTTP server. The
HTTP protocol is described in RFC 2616. The C<Net::HTTP> class
support C<HTTP/1.0> and C<HTTP/1.1>.
C<Net::HTTP> is a sub-class of C<IO::Socket::INET>. You can mix the
methods described below with reading and writing from the socket
directly. This is not necessary a good idea, unless you know what you
are doing.
The following methods are provided (in addition to those of
C<IO::Socket::INET>):
=over
=item $s = Net::HTTP->new( %options )
The C<Net::HTTP> constructor method takes the same options as
C<IO::Socket::INET>'s as well as these:
Host: Initial host attribute value
KeepAlive: Initial keep_alive attribute value
SendTE: Initial send_te attribute_value
HTTPVersion: Initial http_version attribute value
PeerHTTPVersion: Initial peer_http_version attribute value
MaxLineLength: Initial max_line_length attribute value
MaxHeaderLines: Initial max_header_lines attribute value
The C<Host> option is also the default for C<IO::Socket::INET>'s
C<PeerAddr>. The C<PeerPort> defaults to 80 if not provided.
The C<Listen> option provided by C<IO::Socket::INET>'s constructor
method is not allowed.
If unable to connect to the given HTTP server then the constructor
returns C<undef> and $@ contains the reason. After a successful
connect, a C<Net:HTTP> object is returned.
=item $s->host
Get/set the default value of the C<Host> header to send. The $host
should not be set to an empty string (or C<undef>).
=item $s->keep_alive
Get/set the I<keep-alive> value. If this value is TRUE then the
request will be sent with headers indicating that the server should try
to keep the connection open so that multiple requests can be sent.
The actual headers set will depend on the value of the C<http_version>
and C<peer_http_version> attributes.
=item $s->send_te
Get/set the a value indicating if the request will be sent with a "TE"
header to indicate the transfer encodings that the server can chose to
use. If the C<Compress::Zlib> module is installed then this will
annouce that this client accept both the I<deflate> and I<gzip>
encodings.
=item $s->http_version
Get/set the HTTP version number that this client should announce.
This value can only be set to "1.0" or "1.1". The default is "1.1".
=item $s->peer_http_version
Get/set the protocol version number of our peer. This value will
initially be "1.0", but will be updated by a successful
read_response_headers() method call.
=item $s->max_line_length
Get/set a limit on the length of response line and response header
lines. The default is 4096. A value of 0 means no limit.
=item $s->max_header_length
Get/set a limit on the number of headers lines that a response can
have. The default is 128. A value of 0 means no limit.
=item $s->format_request($method, $uri, %headers, [$content])
Format a request message and return it as a string. If the headers do
not include a C<Host> header, then a header is inserted with the value
of the C<host> attribute. Headers like C<Connection> and
C<Keep-Alive> might also be added depending on the status of the
C<keep_alive> attribute.
If $content is given (and it is non-empty), then a C<Content-Length>
header is automatically added unless it was already present.
=item $s->write_request($method, $uri, %headers, [$content])
Format and send a request message. Arguments are the same as for
format_request(). Returns true if successful.
=item $s->format_chunk( $data )
Returns the string to be written for the given chunk of data.
=item $s->write_chunk($data)
Will write a new chunk of request entity body data. This method
should only be used if the C<Transfer-Encoding> header with a value of
C<chunked> was sent in the request. Note, writing zero-length data is
a no-op. Use the write_chunk_eof() method to signal end of entity
body data.
Returns true if successful.
=item $s->format_chunk_eof( %trailers )
Returns the string to be written for signaling EOF when a
C<Transfer-Encoding> of C<chunked> is used.
=item $s->write_chunk_eof( %trailers )
Will write eof marker for chunked data and optional trailers. Note
that trailers should not really be used unless is was signaled
with a C<Trailer> header.
Returns true if successful.
=item ($code, $mess, %headers) = $s->read_response_headers( %opts )
Read response headers from server and return it. The $code is the 3
digit HTTP status code (see L<HTTP::Status>) and $mess is the textual
message that came with it. Headers are then returned as key/value
pairs. Since key letter casing is not normalized and the same key can
even occur multiple times, assigning these values directly to a hash
is not wise. Only the $code is returned if this method is called in
scalar context.
As a side effect this method updates the 'peer_http_version'
attribute.
Options might be passed in as key/value pairs. There are currently
only two options supported; C<laxed> and C<junk_out>.
The C<laxed> option will make read_response_headers() more forgiving
towards servers that have not learned how to speak HTTP properly. The
C<laxed> option is a boolean flag, and is enabled by passing in a TRUE
value. The C<junk_out> option can be used to capture bad header lines
when C<laxed> is enabled. The value should be an array reference.
Bad header lines will be pushed onto the array.
The C<laxed> option must be specified in order to communicate with
pre-HTTP/1.0 servers that don't describe the response outcome or the
data they send back with a header block. For these servers
peer_http_version is set to "0.9" and this method returns (200,
"Assumed OK").
The method will raise an exception (die) if the server does not speak
proper HTTP or if the C<max_line_length> or C<max_header_length>
limits are reached. If the C<laxed> option is turned on and
C<max_line_length> and C<max_header_length> checks are turned off,
then no exception will be raised and this method will always
return a response code.
=item $n = $s->read_entity_body($buf, $size);
Reads chunks of the entity body content. Basically the same interface
as for read() and sysread(), but the buffer offset argument is not
supported yet. This method should only be called after a successful
read_response_headers() call.
The return value will be C<undef> on read errors, 0 on EOF, -1 if no data
could be returned this time, otherwise the number of bytes assgined
to $buf. The $buf set to "" when the return value is -1.
This method will raise exceptions (die) if the server does not speak
proper HTTP. This can only happen when reading chunked data.
=item %headers = $s->get_trailers
After read_entity_body() has returned 0 to indicate end of the entity
body, you might call this method to pick up any trailers.
=item $s->_rbuf
Get/set the read buffer content. The read_response_headers() and
read_entity_body() methods use an internal buffer which they will look
for data before they actually sysread more from the socket itself. If
they read too much, the remaining data will be left in this buffer.
=item $s->_rbuf_length
Returns the number of bytes in the read buffer. This should always be
the same as:
length($s->_rbuf)
but might be more efficient.
=back
=head1 SUBCLASSING
The read_response_headers() and read_entity_body() will invoke the
sysread() method when they need more data. Subclasses might want to
override this method to contol how reading takes place.
The object itself is a glob. Subclasses should avoid using hash key
names prefixed with C<http_> and C<io_>.
=head1 SEE ALSO
L<LWP>, L<IO::Socket::INET>, L<Net::HTTP::NB>
=head1 COPYRIGHT
Copyright 2001-2003 Gisle Aas.
This library is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
=cut
+520
View File
@@ -0,0 +1,520 @@
package Net::HTTP::Methods;
# $Id: Methods.pm,v 1.12 2002/12/26 09:13:55 gisle Exp $
require 5.005; # 4-arg substr
use strict;
use vars qw($VERSION);
$VERSION = "1.00";
my $CRLF = "\015\012"; # "\r\n" is not portable
sub new {
my($class, %cnf) = @_;
require Symbol;
my $self = bless Symbol::gensym(), $class;
return $self->http_configure(\%cnf);
}
sub http_configure {
my($self, $cnf) = @_;
die "Listen option not allowed" if $cnf->{Listen};
my $host = delete $cnf->{Host};
my $peer = $cnf->{PeerAddr} || $cnf->{PeerHost};
if ($host) {
$cnf->{PeerAddr} = $host unless $peer;
}
else {
$host = $peer;
$host =~ s/:.*//;
}
$cnf->{PeerPort} = $self->http_default_port unless $cnf->{PeerPort};
$cnf->{Proto} = 'tcp';
my $keep_alive = delete $cnf->{KeepAlive};
my $http_version = delete $cnf->{HTTPVersion};
$http_version = "1.1" unless defined $http_version;
my $peer_http_version = delete $cnf->{PeerHTTPVersion};
$peer_http_version = "1.0" unless defined $peer_http_version;
my $send_te = delete $cnf->{SendTE};
my $max_line_length = delete $cnf->{MaxLineLength};
$max_line_length = 4*1024 unless defined $max_line_length;
my $max_header_lines = delete $cnf->{MaxHeaderLines};
$max_header_lines = 128 unless defined $max_header_lines;
return undef unless $self->http_connect($cnf);
unless ($host =~ /:/) {
my $p = $self->peerport;
$host .= ":$p";
}
$self->host($host);
$self->keep_alive($keep_alive);
$self->send_te($send_te);
$self->http_version($http_version);
$self->peer_http_version($peer_http_version);
$self->max_line_length($max_line_length);
$self->max_header_lines($max_header_lines);
${*$self}{'http_buf'} = "";
return $self;
}
sub http_default_port {
80;
}
# set up property accessors
for my $method (qw(host keep_alive send_te max_line_length max_header_lines peer_http_version)) {
my $prop_name = "http_" . $method;
no strict 'refs';
*$method = sub {
my $self = shift;
my $old = ${*$self}{$prop_name};
${*$self}{$prop_name} = shift if @_;
return $old;
};
}
# we want this one to be a bit smarter
sub http_version {
my $self = shift;
my $old = ${*$self}{'http_version'};
if (@_) {
my $v = shift;
$v = "1.0" if $v eq "1"; # float
unless ($v eq "1.0" or $v eq "1.1") {
require Carp;
Carp::croak("Unsupported HTTP version '$v'");
}
${*$self}{'http_version'} = $v;
}
$old;
}
sub format_request {
my $self = shift;
my $method = shift;
my $uri = shift;
my $content = (@_ % 2) ? pop : "";
for ($method, $uri) {
require Carp;
Carp::croak("Bad method or uri") if /\s/ || !length;
}
push(@{${*$self}{'http_request_method'}}, $method);
my $ver = ${*$self}{'http_version'};
my $peer_ver = ${*$self}{'http_peer_http_version'} || "1.0";
my @h;
my @connection;
my %given = (host => 0, "content-length" => 0, "te" => 0);
while (@_) {
my($k, $v) = splice(@_, 0, 2);
my $lc_k = lc($k);
if ($lc_k eq "connection") {
push(@connection, split(/\s*,\s*/, $v));
next;
}
if (exists $given{$lc_k}) {
$given{$lc_k}++;
}
push(@h, "$k: $v");
}
if (length($content) && !$given{'content-length'}) {
push(@h, "Content-Length: " . length($content));
}
my @h2;
if ($given{te}) {
push(@connection, "TE") unless grep lc($_) eq "te", @connection;
}
elsif ($self->send_te && zlib_ok()) {
# gzip is less wanted since the Compress::Zlib interface for
# it does not really allow chunked decoding to take place easily.
push(@h2, "TE: deflate,gzip;q=0.3");
push(@connection, "TE");
}
unless (grep lc($_) eq "close", @connection) {
if ($self->keep_alive) {
if ($peer_ver eq "1.0") {
# from looking at Netscape's headers
push(@h2, "Keep-Alive: 300");
unshift(@connection, "Keep-Alive");
}
}
else {
push(@connection, "close") if $ver ge "1.1";
}
}
push(@h2, "Connection: " . join(", ", @connection)) if @connection;
push(@h2, "Host: ${*$self}{'http_host'}") unless $given{host};
return join($CRLF, "$method $uri HTTP/$ver", @h2, @h, "", $content);
}
sub write_request {
my $self = shift;
$self->print($self->format_request(@_));
}
sub format_chunk {
my $self = shift;
return $_[0] unless defined($_[0]) && length($_[0]);
return sprintf("%x", length($_[0])) . $CRLF . $_[0] . $CRLF;
}
sub write_chunk {
my $self = shift;
return 1 unless defined($_[0]) && length($_[0]);
$self->print(sprintf("%x", length($_[0])) . $CRLF . $_[0] . $CRLF);
}
sub format_chunk_eof {
my $self = shift;
my @h;
while (@_) {
push(@h, sprintf "%s: %s$CRLF", splice(@_, 0, 2));
}
return join("", "0$CRLF", @h, $CRLF);
}
sub write_chunk_eof {
my $self = shift;
$self->print($self->format_chunk_eof(@_));
}
sub my_read {
die if @_ > 3;
my $self = shift;
my $len = $_[1];
for (${*$self}{'http_buf'}) {
if (length) {
$_[0] = substr($_, 0, $len, "");
return length($_[0]);
}
else {
return $self->sysread($_[0], $len);
}
}
}
sub my_readline {
my $self = shift;
for (${*$self}{'http_buf'}) {
my $max_line_length = ${*$self}{'http_max_line_length'};
my $pos;
while (1) {
# find line ending
$pos = index($_, "\012");
last if $pos >= 0;
die "Line too long (limit is $max_line_length)"
if $max_line_length && length($_) > $max_line_length;
# need to read more data to find a line ending
my $n = $self->sysread($_, 1024, length);
if (!$n) {
return undef unless length;
return substr($_, 0, length, "");
}
}
die "Line too long ($pos; limit is $max_line_length)"
if $max_line_length && $pos > $max_line_length;
my $line = substr($_, 0, $pos+1, "");
$line =~ s/(\015?\012)\z// || die "Assert";
return wantarray ? ($line, $1) : $line;
}
}
sub _rbuf {
my $self = shift;
if (@_) {
for (${*$self}{'http_buf'}) {
my $old;
$old = $_ if defined wantarray;
$_ = shift;
return $old;
}
}
else {
return ${*$self}{'http_buf'};
}
}
sub _rbuf_length {
my $self = shift;
return length ${*$self}{'http_buf'};
}
sub _read_header_lines {
my $self = shift;
my $junk_out = shift;
my @headers;
my $line_count = 0;
my $max_header_lines = ${*$self}{'http_max_header_lines'};
while (my $line = my_readline($self)) {
if ($line =~ /^(\S+)\s*:\s*(.*)/s) {
push(@headers, $1, $2);
}
elsif (@headers && $line =~ s/^\s+//) {
$headers[-1] .= " " . $line;
}
elsif ($junk_out) {
push(@$junk_out, $line);
}
else {
die "Bad header: '$line'\n";
}
if ($max_header_lines) {
$line_count++;
if ($line_count >= $max_header_lines) {
die "Too many header lines (limit is $max_header_lines)";
}
}
}
return @headers;
}
sub read_response_headers {
my($self, %opt) = @_;
my $laxed = $opt{laxed};
my($status, $eol) = my_readline($self);
unless (defined $status) {
die "EOF instead of response status line" unless $laxed;
# assume HTTP/0.9
${*$self}{'http_peer_http_version'} = "0.9";
${*$self}{'http_status'} = "200";
return 200 unless wantarray;
return (200, "EOF");
}
my($peer_ver, $code, $message) = split(/\s+/, $status, 3);
if (!$peer_ver || $peer_ver !~ s,^HTTP/,, || $code !~ /^[1-5]\d\d$/) {
die "Bad response status line: '$status'" unless $laxed;
# assume HTTP/0.9
${*$self}{'http_peer_http_version'} = "0.9";
${*$self}{'http_status'} = "200";
substr(${*$self}{'http_buf'}, 0, 0) = $status . $eol;
return 200 unless wantarray;
return (200, "Assumed OK");
};
${*$self}{'http_peer_http_version'} = $peer_ver;
${*$self}{'http_status'} = $code;
my $junk_out;
if ($laxed) {
$junk_out = $opt{junk_out} || [];
}
my @headers = $self->_read_header_lines($junk_out);
# pick out headers that read_entity_body might need
my @te;
my $content_length;
for (my $i = 0; $i < @headers; $i += 2) {
my $h = lc($headers[$i]);
if ($h eq 'transfer-encoding') {
push(@te, $headers[$i+1]);
}
elsif ($h eq 'content-length') {
$content_length = $headers[$i+1];
}
}
${*$self}{'http_te'} = join(",", @te);
${*$self}{'http_content_length'} = $content_length;
${*$self}{'http_first_body'}++;
delete ${*$self}{'http_trailers'};
return $code unless wantarray;
return ($code, $message, @headers);
}
sub read_entity_body {
my $self = shift;
my $buf_ref = \$_[0];
my $size = $_[1];
die "Offset not supported yet" if $_[2];
my $chunked;
my $bytes;
if (${*$self}{'http_first_body'}) {
${*$self}{'http_first_body'} = 0;
delete ${*$self}{'http_chunked'};
delete ${*$self}{'http_bytes'};
my $method = shift(@{${*$self}{'http_request_method'}});
my $status = ${*$self}{'http_status'};
if ($method eq "HEAD" || $status =~ /^(?:1|[23]04)/) {
# these responses are always empty
$bytes = 0;
}
elsif (my $te = ${*$self}{'http_te'}) {
my @te = split(/\s*,\s*/, lc($te));
die "Chunked must be last Transfer-Encoding '$te'"
unless pop(@te) eq "chunked";
for (@te) {
if ($_ eq "deflate" && zlib_ok()) {
#require Compress::Zlib;
my $i = Compress::Zlib::inflateInit();
die "Can't make inflator" unless $i;
$_ = sub { scalar($i->inflate($_[0])) }
}
elsif ($_ eq "gzip" && zlib_ok()) {
#require Compress::Zlib;
my @buf;
$_ = sub {
push(@buf, $_[0]);
return Compress::Zlib::memGunzip(join("", @buf)) if $_[1];
return "";
};
}
elsif ($_ eq "identity") {
$_ = sub { $_[0] };
}
else {
die "Can't handle transfer encoding '$te'";
}
}
@te = reverse(@te);
${*$self}{'http_te2'} = @te ? \@te : "";
$chunked = -1;
}
elsif (defined(my $content_length = ${*$self}{'http_content_length'})) {
$bytes = $content_length;
}
else {
# XXX Multi-Part types are self delimiting, but RFC 2616 says we
# only has to deal with 'multipart/byteranges'
# Read until EOF
}
}
else {
$chunked = ${*$self}{'http_chunked'};
$bytes = ${*$self}{'http_bytes'};
}
if (defined $chunked) {
# The state encoded in $chunked is:
# $chunked == 0: read CRLF after chunk, then chunk header
# $chunked == -1: read chunk header
# $chunked > 0: bytes left in current chunk to read
if ($chunked <= 0) {
my $line = my_readline($self);
if ($chunked == 0) {
die "Missing newline after chunk data: '$line'" unless $line eq "";
$line = my_readline($self);
}
my $chunk_len = $line;
$chunk_len =~ s/;.*//; # ignore potential chunk parameters
unless ($chunk_len =~ /^([\da-fA-F]+)\s*$/) {
die "Bad chunk-size in HTTP response: $line";
}
$chunked = hex($1);
if ($chunked == 0) {
${*$self}{'http_trailers'} = [$self->_read_header_lines];
$$buf_ref = "";
my $n = 0;
if (my $transforms = delete ${*$self}{'http_te2'}) {
for (@$transforms) {
$$buf_ref = &$_($$buf_ref, 1);
}
$n = length($$buf_ref);
}
# in case somebody tries to read more, make sure we continue
# to return EOF
delete ${*$self}{'http_chunked'};
${*$self}{'http_bytes'} = 0;
return $n;
}
}
my $n = $chunked;
$n = $size if $size && $size < $n;
$n = my_read($self, $$buf_ref, $n);
return undef unless defined $n;
${*$self}{'http_chunked'} = $chunked - $n;
if ($n > 0) {
if (my $transforms = ${*$self}{'http_te2'}) {
for (@$transforms) {
$$buf_ref = &$_($$buf_ref, 0);
}
$n = length($$buf_ref);
$n = -1 if $n == 0;
}
}
return $n;
}
elsif (defined $bytes) {
unless ($bytes) {
$$buf_ref = "";
return 0;
}
my $n = $bytes;
$n = $size if $size && $size < $n;
$n = my_read($self, $$buf_ref, $n);
return undef unless defined $n;
${*$self}{'http_bytes'} = $bytes - $n;
return $n;
}
else {
# read until eof
$size ||= 8*1024;
return my_read($self, $$buf_ref, $size);
}
}
sub get_trailers {
my $self = shift;
@{${*$self}{'http_trailers'} || []};
}
BEGIN {
my $zlib_ok;
sub zlib_ok {
return $zlib_ok if defined $zlib_ok;
# Try to load Compress::Zlib.
local $@;
local $SIG{__DIE__};
$zlib_ok = 0;
eval {
require Compress::Zlib;
Compress::Zlib->VERSION(1.10);
$zlib_ok++;
};
return $zlib_ok;
}
} # BEGIN
1;
+106
View File
@@ -0,0 +1,106 @@
package Net::HTTP::NB;
# $Id: NB.pm,v 1.5 2001/08/28 03:03:42 gisle Exp $
use strict;
use vars qw($VERSION @ISA);
$VERSION = "0.02";
require Net::HTTP;
@ISA=qw(Net::HTTP);
sub sysread {
my $self = $_[0];
if (${*$self}{'httpnb_read_count'}++) {
${*$self}{'http_buf'} = ${*$self}{'httpnb_save'};
die "Multi-read\n";
}
my $buf;
my $offset = $_[3] || 0;
my $n = sysread($self, $_[1], $_[2], $offset);
${*$self}{'httpnb_save'} .= substr($_[1], $offset);
return $n;
}
sub read_response_headers {
my $self = shift;
${*$self}{'httpnb_read_count'} = 0;
${*$self}{'httpnb_save'} = ${*$self}{'http_buf'};
my @h = eval { $self->SUPER::read_response_headers(@_) };
if ($@) {
return if $@ eq "Multi-read\n";
die;
}
return @h;
}
sub read_entity_body {
my $self = shift;
${*$self}{'httpnb_read_count'} = 0;
${*$self}{'httpnb_save'} = ${*$self}{'http_buf'};
# XXX I'm not so sure this does the correct thing in case of
# transfer-encoding tranforms
my $n = eval { $self->SUPER::read_entity_body(@_); };
if ($@) {
$_[0] = "";
return -1;
}
return $n;
}
1;
__END__
=head1 NAME
Net::HTTP::NB - Non-blocking HTTP client
=head1 SYNOPSIS
use Net::HTTP::NB;
my $s = Net::HTTP::NB->new(Host => "www.perl.com) || die $@;
$s->write_request(GET => "/");
use IO::Select;
my $sel = IO::Select->new($s);
READ_HEADER: {
die "Header timeout" unless $sel->can_read(10);
my($code, $mess, %h) = $s->read_response_headers;
redo READ_HEADER unless $code;
}
while (1) {
die "Body timeout" unless $sel->can_read(10);
my $buf;
my $n = $s->read_entity_body($buf, 1024);
last unless $n;
print $buf;
}
=head1 DESCRIPTION
Same interface as C<Net::HTTP> but it will never try multiple reads
when the read_response_headers() or read_entity_body() methods are
invoked. This make it possible to multiplex multiple Net::HTTP::NB
using select without risk blocking.
If read_response_headers() did not see enough data to complete the
headers an empty list is returned.
If read_entity_body() did not see new entity data in its read
the value -1 is returned.
=head1 SEE ALSO
L<Net::HTTP>
=head1 COPYRIGHT
Copyright 2001 Gisle Aas.
This library is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
=cut
+55
View File
@@ -0,0 +1,55 @@
package Net::HTTPS;
# $Id: HTTPS.pm,v 1.3 2002/12/23 18:16:29 gisle Exp $
use strict;
use vars qw($VERSION $SSL_SOCKET_CLASS @ISA);
$VERSION = "1.00";
# Figure out which SSL implementation to use
if ($IO::Socket::SSL::VERSION) {
$SSL_SOCKET_CLASS = "IO::Socket::SSL"; # it was already loaded
}
else {
eval { require Net::SSL; }; # from Crypt-SSLeay
if ($@) {
my $old_errsv = $@;
eval {
require IO::Socket::SSL;
};
if ($@) {
$old_errsv =~ s/\s\(\@INC contains:.*\)/)/g;
die $old_errsv . $@;
}
$SSL_SOCKET_CLASS = "IO::Socket::SSL";
}
else {
$SSL_SOCKET_CLASS = "Net::SSL";
}
}
require Net::HTTP::Methods;
@ISA=($SSL_SOCKET_CLASS, 'Net::HTTP::Methods');
sub configure {
my($self, $cnf) = @_;
$self->http_configure($cnf);
}
sub http_connect {
my($self, $cnf) = @_;
$self->SUPER::configure($cnf);
}
sub http_default_port {
443;
}
# The underlying SSLeay classes fails to work if the socket is
# placed in non-blocking mode. This override of the blocking
# method makes sure it stays the way it was created.
sub blocking { } # noop
1;
File diff suppressed because it is too large Load Diff
+255
View File
@@ -0,0 +1,255 @@
package Net::SSH;
use strict;
use vars qw($VERSION @ISA @EXPORT_OK $ssh $equalspace $DEBUG @ssh_options);
use Exporter;
use IO::File;
use IPC::Open2;
use IPC::Open3;
@ISA = qw(Exporter);
@EXPORT_OK = qw( ssh issh ssh_cmd sshopen2 sshopen3 );
$VERSION = '0.07';
$DEBUG = 0;
$ssh = "ssh";
=head1 NAME
Net::SSH - Perl extension for secure shell
=head1 SYNOPSIS
use Net::SSH qw(ssh issh sshopen2 sshopen3);
ssh('user@hostname', $command);
issh('user@hostname', $command);
ssh_cmd('user@hostname', $command);
ssh_cmd( {
user => 'user',
host => 'host.name',
command => 'command',
args => [ '-arg1', '-arg2' ],
stdin_string => "string\n",
} );
sshopen2('user@hostname', $reader, $writer, $command);
sshopen3('user@hostname', $writer, $reader, $error, $command);
=head1 DESCRIPTION
Simple wrappers around ssh commands.
For an all-perl implementation that does not require the system B<ssh> command,
see L<Net::SSH::Perl> instead.
=head1 SUBROUTINES
=over 4
=item ssh [USER@]HOST, COMMAND [, ARGS ... ]
Calls ssh in batch mode.
=cut
sub ssh {
my($host, @command) = @_;
@ssh_options = &_ssh_options unless @ssh_options;
my @cmd = ($ssh, @ssh_options, $host, @command);
warn "[Net::SSH::ssh] executing ". join(' ', @cmd). "\n"
if $DEBUG;
system(@cmd);
}
=item issh [USER@]HOST, COMMAND [, ARGS ... ]
Prints the ssh command to be executed, waits for the user to confirm, and
(optionally) executes the command.
=cut
sub issh {
my($host, @command) = @_;
my @cmd = ($ssh, $host, @command);
print join(' ', @cmd), "\n";
if ( &_yesno ) {
system(@cmd);
}
}
=item ssh_cmd [USER@]HOST, COMMAND [, ARGS ... ]
=item ssh_cmd OPTIONS_HASHREF
Calls ssh in batch mode. Throws a fatal error if data occurs on the command's
STDERR. Returns any data from the command's STDOUT.
If using the hashref-style of passing arguments, possible keys are:
user (optional)
host (requried)
command (required)
args (optional, arrayref)
stdin_string (optional) - written to the command's STDIN
=cut
sub ssh_cmd {
my($host, $stdin_string, @command);
if ( ref($_[0]) ) {
my $opt = shift;
$host = $opt->{host};
$host = $opt->{user}. '@'. $host if exists $opt->{user};
@command = ( $opt->{command} );
push @command, @{ $opt->{args} } if exists $opt->{args};
$stdin_string = $opt->{stdin_string};
} else {
($host, @command) = @_;
undef $stdin_string;
}
my $reader = IO::File->new();
my $writer = IO::File->new();
my $error = IO::File->new();
sshopen3( $host, $writer, $reader, $error, @command ) or die $!;
print $writer $stdin_string if defined $stdin_string;
close $writer;
local $/ = undef;
my $output_stream = <$reader>;
my $error_stream = <$error>;
if ( length $error_stream ) {
die "[Net:SSH::ssh_cmd] STDERR $error_stream";
}
return $output_stream;
}
=item sshopen2 [USER@]HOST, READER, WRITER, COMMAND [, ARGS ... ]
Connects the supplied filehandles to the ssh process (in batch mode).
=cut
sub sshopen2 {
my($host, $reader, $writer, @command) = @_;
@ssh_options = &_ssh_options unless @ssh_options;
open2($reader, $writer, $ssh, @ssh_options, $host, @command);
}
=item sshopen3 HOST, WRITER, READER, ERROR, COMMAND [, ARGS ... ]
Connects the supplied filehandles to the ssh process (in batch mode).
=cut
sub sshopen3 {
my($host, $writer, $reader, $error, @command) = @_;
@ssh_options = &_ssh_options unless @ssh_options;
open3($writer, $reader, $error, $ssh, @ssh_options, $host, @command);
}
sub _yesno {
print "Proceed [y/N]:";
my $x = scalar(<STDIN>);
$x =~ /^y/i;
}
sub _ssh_options {
my $reader = IO::File->new();
my $writer = IO::File->new();
my $error = IO::File->new();
open3($writer, $reader, $error, $ssh, '-V');
my $ssh_version = <$error>;
chomp($ssh_version);
if ( $ssh_version =~ /.*OpenSSH[-|_](\w+)\./ && $1 == 1 ) {
$equalspace = " ";
} else {
$equalspace = "=";
}
my @options = ( '-o', 'BatchMode'.$equalspace.'yes' );
if ( $ssh_version =~ /.*OpenSSH[-|_](\w+)\./ && $1 > 1 ) {
unshift @options, '-T';
}
@options;
}
=back
=head1 EXAMPLE
use Net::SSH qw(sshopen2);
use strict;
my $user = "username";
my $host = "hostname";
my $cmd = "command";
sshopen2("$user\@$host", *READER, *WRITER, "$cmd") || die "ssh: $!";
while (<READER>) {
chomp();
print "$_\n";
}
close(READER);
close(WRITER);
=head1 FREQUENTLY ASKED QUESTIONS
Q: How do you supply a password to connect with ssh within a perl script
using the Net::SSH module?
A: You don't. Use RSA or DSA keys. See the ssh-keygen(1) manpage.
Q: My script is "leaking" ssh processes.
A: See L<perlfaq8/"How do I avoid zombies on a Unix system">, L<IPC::Open2>,
L<IPC::Open3> and L<perlfunc/waitpid>.
=head1 AUTHORS
Ivan Kohler <ivan-netssh_pod@420.am>
John Harrison <japh@in-ta.net> contributed an example for the documentation.
Martin Langhoff <martin@cwa.co.nz> contributed the ssh_cmd command, and
Jeff Finucane <jeff@cmh.net> updated it and took care of the 0.04 release.
Anthony Awtrey <tony@awtrey.com> contributed a fix for those still using
OpenSSH v1.
=head1 COPYRIGHT
Copyright (c) 2002 Ivan Kohler.
Copyright (c) 2002 Freeside Internet Services, LLC
All rights reserved.
This program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.
=head1 BUGS
Not OO.
Look at IPC::Session (also fsh)
=head1 SEE ALSO
For an all-perl implementation that does not require the system B<ssh> command,
see L<Net::SSH::Perl> instead.
ssh-keygen(1), ssh(1), L<IO::File>, L<IPC::Open2>, L<IPC::Open3>
=cut
1;
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+359
View File
@@ -0,0 +1,359 @@
package Time::HiRes;
use strict;
use vars qw($VERSION $XS_VERSION @ISA @EXPORT @EXPORT_OK $AUTOLOAD);
require Exporter;
require DynaLoader;
@ISA = qw(Exporter DynaLoader);
@EXPORT = qw( );
@EXPORT_OK = qw (usleep sleep ualarm alarm gettimeofday time tv_interval
getitimer setitimer
ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF ITIMER_REALPROF
d_usleep d_ualarm d_gettimeofday d_getitimer d_setitimer
d_nanosleep);
$VERSION = '1.59';
$XS_VERSION = $VERSION;
$VERSION = eval $VERSION;
sub AUTOLOAD {
my $constname;
($constname = $AUTOLOAD) =~ s/.*:://;
die "&Time::HiRes::constant not defined" if $constname eq 'constant';
my ($error, $val) = constant($constname);
if ($error) { die $error; }
{
no strict 'refs';
*$AUTOLOAD = sub { $val };
}
goto &$AUTOLOAD;
}
bootstrap Time::HiRes;
# Preloaded methods go here.
sub tv_interval {
# probably could have been done in C
my ($a, $b) = @_;
$b = [gettimeofday()] unless defined($b);
(${$b}[0] - ${$a}[0]) + ((${$b}[1] - ${$a}[1]) / 1_000_000);
}
# Autoload methods go after =cut, and are processed by the autosplit program.
1;
__END__
=head1 NAME
Time::HiRes - High resolution alarm, sleep, gettimeofday, interval timers
=head1 SYNOPSIS
use Time::HiRes qw( usleep ualarm gettimeofday tv_interval );
usleep ($microseconds);
ualarm ($microseconds);
ualarm ($microseconds, $interval_microseconds);
$t0 = [gettimeofday];
($seconds, $microseconds) = gettimeofday;
$elapsed = tv_interval ( $t0, [$seconds, $microseconds]);
$elapsed = tv_interval ( $t0, [gettimeofday]);
$elapsed = tv_interval ( $t0 );
use Time::HiRes qw ( time alarm sleep );
$now_fractions = time;
sleep ($floating_seconds);
alarm ($floating_seconds);
alarm ($floating_seconds, $floating_interval);
use Time::HiRes qw( setitimer getitimer
ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF ITIMER_REALPROF );
setitimer ($which, $floating_seconds, $floating_interval );
getitimer ($which);
=head1 DESCRIPTION
The C<Time::HiRes> module implements a Perl interface to the C<usleep>,
C<ualarm>, C<gettimeofday>, and C<setitimer>/C<getitimer> system calls, in other
words, high resolution time and timers. See the L</EXAMPLES> section below
and the test scripts for usage; see your system documentation for the
description of the underlying C<nanosleep> or C<usleep>, C<ualarm>,
C<gettimeofday>, and C<setitimer>/C<getitimer> calls.
If your system lacks C<gettimeofday()> or an emulation of it you don't
get C<gettimeofday()> or the one-argument form of C<tv_interval()>. If your system lacks all of
C<nanosleep()>, C<usleep()>, and C<select()>, you don't get
C<Time::HiRes::usleep()> or C<Time::HiRes::sleep()>. If your system lacks both
C<ualarm()> and C<setitimer()> you don't get
C<Time::HiRes::ualarm()> or C<Time::HiRes::alarm()>.
If you try to import an unimplemented function in the C<use> statement
it will fail at compile time.
If your subsecond sleeping is implemented with C<nanosleep()> instead of
C<usleep()>, you can mix subsecond sleeping with signals since
C<nanosleep()> does not use signals. This, however is unportable, and you
should first check for the truth value of C<&Time::HiRes::d_nanosleep> to
see whether you have nanosleep, and then carefully read your
C<nanosleep()> C API documentation for any peculiarities. (There is no
separate interface to call C<nanosleep()>; just use C<Time::HiRes::sleep()>
or C<Time::HiRes::usleep()> with small enough values.)
Unless using C<nanosleep> for mixing sleeping with signals, give
some thought to whether Perl is the tool you should be using for work
requiring nanosecond accuracies.
The following functions can be imported from this module.
No functions are exported by default.
=over 4
=item gettimeofday ()
In array context returns a two-element array with the seconds and
microseconds since the epoch. In scalar context returns floating
seconds like C<Time::HiRes::time()> (see below).
=item usleep ( $useconds )
Sleeps for the number of microseconds specified. Returns the number
of microseconds actually slept. Can sleep for more than one second,
unlike the C<usleep> system call. See also C<Time::HiRes::sleep()> below.
=item ualarm ( $useconds [, $interval_useconds ] )
Issues a C<ualarm> call; the C<$interval_useconds> is optional and
will be zero if unspecified, resulting in C<alarm>-like behaviour.
=item tv_interval
tv_interval ( $ref_to_gettimeofday [, $ref_to_later_gettimeofday] )
Returns the floating seconds between the two times, which should have
been returned by C<gettimeofday()>. If the second argument is omitted,
then the current time is used.
=item time ()
Returns a floating seconds since the epoch. This function can be
imported, resulting in a nice drop-in replacement for the C<time>
provided with core Perl; see the L</EXAMPLES> below.
B<NOTE 1>: This higher resolution timer can return values either less
or more than the core C<time()>, depending on whether your platform
rounds the higher resolution timer values up, down, or to the nearest second
to get the core C<time()>, but naturally the difference should be never
more than half a second.
B<NOTE 2>: Since Sunday, September 9th, 2001 at 01:46:40 AM GMT, when
the C<time()> seconds since epoch rolled over to 1_000_000_000, the
default floating point format of Perl and the seconds since epoch have
conspired to produce an apparent bug: if you print the value of
C<Time::HiRes::time()> you seem to be getting only five decimals, not six
as promised (microseconds). Not to worry, the microseconds are there
(assuming your platform supports such granularity in first place).
What is going on is that the default floating point format of Perl
only outputs 15 digits. In this case that means ten digits before the
decimal separator and five after. To see the microseconds you can use
either C<printf>/C<sprintf> with C<"%.6f">, or the C<gettimeofday()> function in
list context, which will give you the seconds and microseconds as two
separate values.
=item sleep ( $floating_seconds )
Sleeps for the specified amount of seconds. Returns the number of
seconds actually slept (a floating point value). This function can be
imported, resulting in a nice drop-in replacement for the C<sleep>
provided with perl, see the L</EXAMPLES> below.
=item alarm ( $floating_seconds [, $interval_floating_seconds ] )
The C<SIGALRM> signal is sent after the specified number of seconds.
Implemented using C<ualarm()>. The C<$interval_floating_seconds> argument
is optional and will be zero if unspecified, resulting in C<alarm()>-like
behaviour. This function can be imported, resulting in a nice drop-in
replacement for the C<alarm> provided with perl, see the L</EXAMPLES> below.
B<NOTE 1>: With some operating system and Perl release combinations
C<SIGALRM> restarts C<select()>, instead of interuping it.
This means that an C<alarm()> followed by a C<select()>
may together take the sum of the times specified for the the
C<alarm()> and the C<select()>, not just the time of the C<alarm()>.
=item setitimer ( $which, $floating_seconds [, $interval_floating_seconds ] )
Start up an interval timer: after a certain time, a signal arrives,
and more signals may keep arriving at certain intervals. To disable a
timer, use C<$floating_seconds> of zero. If the C<$interval_floating_seconds>
is set to zero (or unspecified), the timer is disabled B<after> the
next delivered signal.
Use of interval timers may interfere with C<alarm()>, C<sleep()>,
and C<usleep()>. In standard-speak the "interaction is unspecified",
which means that I<anything> may happen: it may work, it may not.
In scalar context, the remaining time in the timer is returned.
In list context, both the remaining time and the interval are returned.
There are usually three or four interval timers available: the C<$which>
can be C<ITIMER_REAL>, C<ITIMER_VIRTUAL>, C<ITIMER_PROF>, or C<ITIMER_REALPROF>.
Note that which ones are available depends: true UNIX platforms usually
have the first three, but (for example) Win32 and Cygwin have only
C<ITIMER_REAL>, and only Solaris seems to have C<ITIMER_REALPROF> (which is
used to profile multithreaded programs).
C<ITIMER_REAL> results in C<alarm()>-like behavior. Time is counted in
I<real time>; that is, wallclock time. C<SIGALRM> is delivered when
the timer expires.
C<ITIMER_VIRTUAL> counts time in (process) I<virtual time>; that is, only
when the process is running. In multiprocessor/user/CPU systems this
may be more or less than real or wallclock time. (This time is also
known as the I<user time>.) C<SIGVTALRM> is delivered when the timer expires.
C<ITIMER_PROF> counts time when either the process virtual time or when
the operating system is running on behalf of the process (such as I/O).
(This time is also known as the I<system time>.) (The sum of user
time and system time is known as the I<CPU time>.) C<SIGPROF> is
delivered when the timer expires. C<SIGPROF> can interrupt system calls.
The semantics of interval timers for multithreaded programs are
system-specific, and some systems may support additional interval
timers. See your C<setitimer()> documentation.
=item getitimer ( $which )
Return the remaining time in the interval timer specified by C<$which>.
In scalar context, the remaining time is returned.
In list context, both the remaining time and the interval are returned.
The interval is always what you put in using C<setitimer()>.
=back
=head1 EXAMPLES
use Time::HiRes qw(usleep ualarm gettimeofday tv_interval);
$microseconds = 750_000;
usleep $microseconds;
# signal alarm in 2.5s & every .1s thereafter
ualarm 2_500_000, 100_000;
# get seconds and microseconds since the epoch
($s, $usec) = gettimeofday;
# measure elapsed time
# (could also do by subtracting 2 gettimeofday return values)
$t0 = [gettimeofday];
# do bunch of stuff here
$t1 = [gettimeofday];
# do more stuff here
$t0_t1 = tv_interval $t0, $t1;
$elapsed = tv_interval ($t0, [gettimeofday]);
$elapsed = tv_interval ($t0); # equivalent code
#
# replacements for time, alarm and sleep that know about
# floating seconds
#
use Time::HiRes;
$now_fractions = Time::HiRes::time;
Time::HiRes::sleep (2.5);
Time::HiRes::alarm (10.6666666);
use Time::HiRes qw ( time alarm sleep );
$now_fractions = time;
sleep (2.5);
alarm (10.6666666);
# Arm an interval timer to go off first at 10 seconds and
# after that every 2.5 seconds, in process virtual time
use Time::HiRes qw ( setitimer ITIMER_VIRTUAL time );
$SIG{VTALRM} = sub { print time, "\n" };
setitimer(ITIMER_VIRTUAL, 10, 2.5);
=head1 C API
In addition to the perl API described above, a C API is available for
extension writers. The following C functions are available in the
modglobal hash:
name C prototype
--------------- ----------------------
Time::NVtime double (*)()
Time::U2time void (*)(UV ret[2])
Both functions return equivalent information (like C<gettimeofday>)
but with different representations. The names C<NVtime> and C<U2time>
were selected mainly because they are operating system independent.
(C<gettimeofday> is Unix-centric, though some platforms like VMS have
emulations for it.)
Here is an example of using C<NVtime> from C:
double (*myNVtime)();
SV **svp = hv_fetch(PL_modglobal, "Time::NVtime", 12, 0);
if (!svp) croak("Time::HiRes is required");
if (!SvIOK(*svp)) croak("Time::NVtime isn't a function pointer");
myNVtime = INT2PTR(double(*)(), SvIV(*svp));
printf("The current time is: %f\n", (*myNVtime)());
=head1 DIAGNOSTICS
=head2 negative time not invented yet
You tried to use a negative time argument.
=head2 internal error: useconds < 0 (unsigned ... signed ...)
Something went horribly wrong-- the number of microseconds that cannot
become negative just became negative. Maybe your compiler is broken?
=head1 CAVEATS
Notice that the core C<time()> maybe rounding rather than truncating.
What this means is that the core C<time()> may be reporting the time
as one second later than C<gettimeofday()> and C<Time::HiRes::time()>.
Adjusting the system clock (either manually or by services like ntp)
may cause problems, especially for long running programs that assume
a monotonously increasing time (note that all platforms do not adjust
time as gracefully as UNIX ntp does). For example in Win32 (and derived
platforms like Cygwin and MinGW) the Time::HiRes::time() may temporarily
drift off from the system clock (and the original time()) by up to 0.5
seconds. Time::HiRes will notice this eventually and recalibrate.
=head1 AUTHORS
D. Wegscheid <wegscd@whirlpool.com>
R. Schertler <roderick@argon.org>
J. Hietaniemi <jhi@iki.fi>
G. Aas <gisle@aas.no>
=head1 COPYRIGHT AND LICENSE
Copyright (c) 1996-2002 Douglas E. Wegscheid. All rights reserved.
Copyright (c) 2002,2003,2004 Jarkko Hietaniemi. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=cut
+369
View File
@@ -0,0 +1,369 @@
package Time::HiRes;
use strict;
use vars qw($VERSION $XS_VERSION @ISA @EXPORT @EXPORT_OK $AUTOLOAD);
require Exporter;
require DynaLoader;
@ISA = qw(Exporter DynaLoader);
@EXPORT = qw( );
@EXPORT_OK = qw (usleep sleep ualarm alarm gettimeofday time tv_interval
getitimer setitimer
ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF ITIMER_REALPROF
d_usleep d_ualarm d_gettimeofday d_getitimer d_setitimer
d_nanosleep);
$VERSION = '1.65';
$XS_VERSION = $VERSION;
$VERSION = eval $VERSION;
sub AUTOLOAD {
my $constname;
($constname = $AUTOLOAD) =~ s/.*:://;
die "&Time::HiRes::constant not defined" if $constname eq 'constant';
my ($error, $val) = constant($constname);
if ($error) { die $error; }
{
no strict 'refs';
*$AUTOLOAD = sub { $val };
}
goto &$AUTOLOAD;
}
bootstrap Time::HiRes;
# Preloaded methods go here.
sub tv_interval {
# probably could have been done in C
my ($a, $b) = @_;
$b = [gettimeofday()] unless defined($b);
(${$b}[0] - ${$a}[0]) + ((${$b}[1] - ${$a}[1]) / 1_000_000);
}
# Autoload methods go after =cut, and are processed by the autosplit program.
1;
__END__
=head1 NAME
Time::HiRes - High resolution alarm, sleep, gettimeofday, interval timers
=head1 SYNOPSIS
use Time::HiRes qw( usleep ualarm gettimeofday tv_interval );
usleep ($microseconds);
ualarm ($microseconds);
ualarm ($microseconds, $interval_microseconds);
$t0 = [gettimeofday];
($seconds, $microseconds) = gettimeofday;
$elapsed = tv_interval ( $t0, [$seconds, $microseconds]);
$elapsed = tv_interval ( $t0, [gettimeofday]);
$elapsed = tv_interval ( $t0 );
use Time::HiRes qw ( time alarm sleep );
$now_fractions = time;
sleep ($floating_seconds);
alarm ($floating_seconds);
alarm ($floating_seconds, $floating_interval);
use Time::HiRes qw( setitimer getitimer
ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF ITIMER_REALPROF );
setitimer ($which, $floating_seconds, $floating_interval );
getitimer ($which);
=head1 DESCRIPTION
The C<Time::HiRes> module implements a Perl interface to the
C<usleep>, C<ualarm>, C<gettimeofday>, and C<setitimer>/C<getitimer>
system calls, in other words, high resolution time and timers. See the
L</EXAMPLES> section below and the test scripts for usage; see your
system documentation for the description of the underlying
C<nanosleep> or C<usleep>, C<ualarm>, C<gettimeofday>, and
C<setitimer>/C<getitimer> calls.
If your system lacks C<gettimeofday()> or an emulation of it you don't
get C<gettimeofday()> or the one-argument form of C<tv_interval()>.
If your system lacks all of C<nanosleep()>, C<usleep()>, and
C<select()>, you don't get C<Time::HiRes::usleep()> or
C<Time::HiRes::sleep()>. If your system lacks both C<ualarm()> and
C<setitimer()> you don't get C<Time::HiRes::ualarm()> or
C<Time::HiRes::alarm()>.
If you try to import an unimplemented function in the C<use> statement
it will fail at compile time.
If your subsecond sleeping is implemented with C<nanosleep()> instead
of C<usleep()>, you can mix subsecond sleeping with signals since
C<nanosleep()> does not use signals. This, however, is not portable,
and you should first check for the truth value of
C<&Time::HiRes::d_nanosleep> to see whether you have nanosleep, and
then carefully read your C<nanosleep()> C API documentation for any
peculiarities. (There is no separate interface to call
C<nanosleep()>; just use C<Time::HiRes::sleep()> or
C<Time::HiRes::usleep()> with small enough values.)
Unless using C<nanosleep> for mixing sleeping with signals, give
some thought to whether Perl is the tool you should be using for
work requiring nanosecond accuracies.
The following functions can be imported from this module.
No functions are exported by default.
=over 4
=item gettimeofday ()
In array context returns a two-element array with the seconds and
microseconds since the epoch. In scalar context returns floating
seconds like C<Time::HiRes::time()> (see below).
=item usleep ( $useconds )
Sleeps for the number of microseconds specified. Returns the number
of microseconds actually slept. Can sleep for more than one second,
unlike the C<usleep> system call. See also C<Time::HiRes::sleep()> below.
=item ualarm ( $useconds [, $interval_useconds ] )
Issues a C<ualarm> call; the C<$interval_useconds> is optional and
will be zero if unspecified, resulting in C<alarm>-like behaviour.
Note that the interaction between alarms and sleeps are unspecified.
=item tv_interval
tv_interval ( $ref_to_gettimeofday [, $ref_to_later_gettimeofday] )
Returns the floating seconds between the two times, which should have
been returned by C<gettimeofday()>. If the second argument is omitted,
then the current time is used.
=item time ()
Returns a floating seconds since the epoch. This function can be
imported, resulting in a nice drop-in replacement for the C<time>
provided with core Perl; see the L</EXAMPLES> below.
B<NOTE 1>: This higher resolution timer can return values either less
or more than the core C<time()>, depending on whether your platform
rounds the higher resolution timer values up, down, or to the nearest second
to get the core C<time()>, but naturally the difference should be never
more than half a second.
B<NOTE 2>: Since Sunday, September 9th, 2001 at 01:46:40 AM GMT, when
the C<time()> seconds since epoch rolled over to 1_000_000_000, the
default floating point format of Perl and the seconds since epoch have
conspired to produce an apparent bug: if you print the value of
C<Time::HiRes::time()> you seem to be getting only five decimals, not
six as promised (microseconds). Not to worry, the microseconds are
there (assuming your platform supports such granularity in the first
place). What is going on is that the default floating point format of
Perl only outputs 15 digits. In this case that means ten digits
before the decimal separator and five after. To see the microseconds
you can use either C<printf>/C<sprintf> with C<"%.6f">, or the
C<gettimeofday()> function in list context, which will give you the
seconds and microseconds as two separate values.
=item sleep ( $floating_seconds )
Sleeps for the specified amount of seconds. Returns the number of
seconds actually slept (a floating point value). This function can
be imported, resulting in a nice drop-in replacement for the C<sleep>
provided with perl, see the L</EXAMPLES> below.
Note that the interaction between alarms and sleeps are unspecified.
=item alarm ( $floating_seconds [, $interval_floating_seconds ] )
The C<SIGALRM> signal is sent after the specified number of seconds.
Implemented using C<ualarm()>. The C<$interval_floating_seconds> argument
is optional and will be zero if unspecified, resulting in C<alarm()>-like
behaviour. This function can be imported, resulting in a nice drop-in
replacement for the C<alarm> provided with perl, see the L</EXAMPLES> below.
B<NOTE 1>: With some combinations of operating systems and Perl
releases C<SIGALRM> restarts C<select()>, instead of interrupting it.
This means that an C<alarm()> followed by a C<select()> may together
take the sum of the times specified for the the C<alarm()> and the
C<select()>, not just the time of the C<alarm()>.
Note that the interaction between alarms and sleeps are unspecified.
=item setitimer ( $which, $floating_seconds [, $interval_floating_seconds ] )
Start up an interval timer: after a certain time, a signal arrives,
and more signals may keep arriving at certain intervals. To disable
an "itimer", use C<$floating_seconds> of zero. If the
C<$interval_floating_seconds> is set to zero (or unspecified), the
timer is disabled B<after> the next delivered signal.
Use of interval timers may interfere with C<alarm()>, C<sleep()>,
and C<usleep()>. In standard-speak the "interaction is unspecified",
which means that I<anything> may happen: it may work, it may not.
In scalar context, the remaining time in the timer is returned.
In list context, both the remaining time and the interval are returned.
There are usually three or four interval timers available: the
C<$which> can be C<ITIMER_REAL>, C<ITIMER_VIRTUAL>, C<ITIMER_PROF>, or
C<ITIMER_REALPROF>. Note that which ones are available depends: true
UNIX platforms usually have the first three, but (for example) Win32
and Cygwin have only C<ITIMER_REAL>, and only Solaris seems to have
C<ITIMER_REALPROF> (which is used to profile multithreaded programs).
C<ITIMER_REAL> results in C<alarm()>-like behavior. Time is counted in
I<real time>; that is, wallclock time. C<SIGALRM> is delivered when
the timer expires.
C<ITIMER_VIRTUAL> counts time in (process) I<virtual time>; that is,
only when the process is running. In multiprocessor/user/CPU systems
this may be more or less than real or wallclock time. (This time is
also known as the I<user time>.) C<SIGVTALRM> is delivered when the
timer expires.
C<ITIMER_PROF> counts time when either the process virtual time or when
the operating system is running on behalf of the process (such as I/O).
(This time is also known as the I<system time>.) (The sum of user
time and system time is known as the I<CPU time>.) C<SIGPROF> is
delivered when the timer expires. C<SIGPROF> can interrupt system calls.
The semantics of interval timers for multithreaded programs are
system-specific, and some systems may support additional interval
timers. See your C<setitimer()> documentation.
=item getitimer ( $which )
Return the remaining time in the interval timer specified by C<$which>.
In scalar context, the remaining time is returned.
In list context, both the remaining time and the interval are returned.
The interval is always what you put in using C<setitimer()>.
=back
=head1 EXAMPLES
use Time::HiRes qw(usleep ualarm gettimeofday tv_interval);
$microseconds = 750_000;
usleep $microseconds;
# signal alarm in 2.5s & every .1s thereafter
ualarm 2_500_000, 100_000;
# get seconds and microseconds since the epoch
($s, $usec) = gettimeofday;
# measure elapsed time
# (could also do by subtracting 2 gettimeofday return values)
$t0 = [gettimeofday];
# do bunch of stuff here
$t1 = [gettimeofday];
# do more stuff here
$t0_t1 = tv_interval $t0, $t1;
$elapsed = tv_interval ($t0, [gettimeofday]);
$elapsed = tv_interval ($t0); # equivalent code
#
# replacements for time, alarm and sleep that know about
# floating seconds
#
use Time::HiRes;
$now_fractions = Time::HiRes::time;
Time::HiRes::sleep (2.5);
Time::HiRes::alarm (10.6666666);
use Time::HiRes qw ( time alarm sleep );
$now_fractions = time;
sleep (2.5);
alarm (10.6666666);
# Arm an interval timer to go off first at 10 seconds and
# after that every 2.5 seconds, in process virtual time
use Time::HiRes qw ( setitimer ITIMER_VIRTUAL time );
$SIG{VTALRM} = sub { print time, "\n" };
setitimer(ITIMER_VIRTUAL, 10, 2.5);
=head1 C API
In addition to the perl API described above, a C API is available for
extension writers. The following C functions are available in the
modglobal hash:
name C prototype
--------------- ----------------------
Time::NVtime double (*)()
Time::U2time void (*)(UV ret[2])
Both functions return equivalent information (like C<gettimeofday>)
but with different representations. The names C<NVtime> and C<U2time>
were selected mainly because they are operating system independent.
(C<gettimeofday> is Unix-centric, though some platforms like VMS have
emulations for it.)
Here is an example of using C<NVtime> from C:
double (*myNVtime)();
SV **svp = hv_fetch(PL_modglobal, "Time::NVtime", 12, 0);
if (!svp) croak("Time::HiRes is required");
if (!SvIOK(*svp)) croak("Time::NVtime isn't a function pointer");
myNVtime = INT2PTR(double(*)(), SvIV(*svp));
printf("The current time is: %f\n", (*myNVtime)());
=head1 DIAGNOSTICS
=head2 negative time not invented yet
You tried to use a negative time argument.
=head2 internal error: useconds < 0 (unsigned ... signed ...)
Something went horribly wrong-- the number of microseconds that cannot
become negative just became negative. Maybe your compiler is broken?
=head1 CAVEATS
Notice that the core C<time()> maybe rounding rather than truncating.
What this means is that the core C<time()> may be reporting the time
as one second later than C<gettimeofday()> and C<Time::HiRes::time()>.
Adjusting the system clock (either manually or by services like ntp)
may cause problems, especially for long running programs that assume
a monotonously increasing time (note that all platforms do not adjust
time as gracefully as UNIX ntp does). For example in Win32 (and derived
platforms like Cygwin and MinGW) the Time::HiRes::time() may temporarily
drift off from the system clock (and the original time()) by up to 0.5
seconds. Time::HiRes will notice this eventually and recalibrate.
=head1 AUTHORS
D. Wegscheid <wegscd@whirlpool.com>
R. Schertler <roderick@argon.org>
J. Hietaniemi <jhi@iki.fi>
G. Aas <gisle@aas.no>
=head1 COPYRIGHT AND LICENSE
Copyright (c) 1996-2002 Douglas E. Wegscheid. All rights reserved.
Copyright (c) 2002,2003,2004 Jarkko Hietaniemi. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=cut
+351
View File
@@ -0,0 +1,351 @@
package Time::HiRes;
use strict;
use vars qw($VERSION $XS_VERSION @ISA @EXPORT @EXPORT_OK $AUTOLOAD);
require Exporter;
require DynaLoader;
@ISA = qw(Exporter DynaLoader);
@EXPORT = qw( );
@EXPORT_OK = qw (usleep sleep ualarm alarm gettimeofday time tv_interval
getitimer setitimer
ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF ITIMER_REALPROF
d_usleep d_ualarm d_gettimeofday d_getitimer d_setitimer
d_nanosleep);
$VERSION = '1.55';
$XS_VERSION = $VERSION;
$VERSION = eval $VERSION;
sub AUTOLOAD {
my $constname;
($constname = $AUTOLOAD) =~ s/.*:://;
die "&Time::HiRes::constant not defined" if $constname eq 'constant';
my ($error, $val) = constant($constname);
if ($error) { die $error; }
{
no strict 'refs';
*$AUTOLOAD = sub { $val };
}
goto &$AUTOLOAD;
}
bootstrap Time::HiRes;
# Preloaded methods go here.
sub tv_interval {
# probably could have been done in C
my ($a, $b) = @_;
$b = [gettimeofday()] unless defined($b);
(${$b}[0] - ${$a}[0]) + ((${$b}[1] - ${$a}[1]) / 1_000_000);
}
# Autoload methods go after =cut, and are processed by the autosplit program.
1;
__END__
=head1 NAME
Time::HiRes - High resolution alarm, sleep, gettimeofday, interval timers
=head1 SYNOPSIS
use Time::HiRes qw( usleep ualarm gettimeofday tv_interval );
usleep ($microseconds);
ualarm ($microseconds);
ualarm ($microseconds, $interval_microseconds);
$t0 = [gettimeofday];
($seconds, $microseconds) = gettimeofday;
$elapsed = tv_interval ( $t0, [$seconds, $microseconds]);
$elapsed = tv_interval ( $t0, [gettimeofday]);
$elapsed = tv_interval ( $t0 );
use Time::HiRes qw ( time alarm sleep );
$now_fractions = time;
sleep ($floating_seconds);
alarm ($floating_seconds);
alarm ($floating_seconds, $floating_interval);
use Time::HiRes qw( setitimer getitimer
ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF ITIMER_REALPROF );
setitimer ($which, $floating_seconds, $floating_interval );
getitimer ($which);
=head1 DESCRIPTION
The C<Time::HiRes> module implements a Perl interface to the C<usleep>,
C<ualarm>, C<gettimeofday>, and C<setitimer>/C<getitimer> system calls, in other
words, high resolution time and timers. See the L</EXAMPLES> section below
and the test scripts for usage; see your system documentation for the
description of the underlying C<nanosleep> or C<usleep>, C<ualarm>,
C<gettimeofday>, and C<setitimer>/C<getitimer> calls.
If your system lacks C<gettimeofday()> or an emulation of it you don't
get C<gettimeofday()> or the one-argument form of C<tv_interval()>. If your system lacks all of
C<nanosleep()>, C<usleep()>, and C<select()>, you don't get
C<Time::HiRes::usleep()> or C<Time::HiRes::sleep()>. If your system lacks both
C<ualarm()> and C<setitimer()> you don't get
C<Time::HiRes::ualarm()> or C<Time::HiRes::alarm()>.
If you try to import an unimplemented function in the C<use> statement
it will fail at compile time.
If your subsecond sleeping is implemented with C<nanosleep()> instead of
C<usleep()>, you can mix subsecond sleeping with signals since
C<nanosleep()> does not use signals. This, however is unportable, and you
should first check for the truth value of C<&Time::HiRes::d_nanosleep> to
see whether you have nanosleep, and then carefully read your
C<nanosleep()> C API documentation for any peculiarities. (There is no
separate interface to call C<nanosleep()>; just use C<Time::HiRes::sleep()>
or C<Time::HiRes::usleep()> with small enough values.)
Unless using C<nanosleep> for mixing sleeping with signals, give
some thought to whether Perl is the tool you should be using for work
requiring nanosecond accuracies.
The following functions can be imported from this module.
No functions are exported by default.
=over 4
=item gettimeofday ()
In array context returns a two-element array with the seconds and
microseconds since the epoch. In scalar context returns floating
seconds like C<Time::HiRes::time()> (see below).
=item usleep ( $useconds )
Sleeps for the number of microseconds specified. Returns the number
of microseconds actually slept. Can sleep for more than one second,
unlike the C<usleep> system call. See also C<Time::HiRes::sleep()> below.
=item ualarm ( $useconds [, $interval_useconds ] )
Issues a C<ualarm> call; the C<$interval_useconds> is optional and
will be zero if unspecified, resulting in C<alarm>-like behaviour.
=item tv_interval
tv_interval ( $ref_to_gettimeofday [, $ref_to_later_gettimeofday] )
Returns the floating seconds between the two times, which should have
been returned by C<gettimeofday()>. If the second argument is omitted,
then the current time is used.
=item time ()
Returns a floating seconds since the epoch. This function can be
imported, resulting in a nice drop-in replacement for the C<time>
provided with core Perl; see the L</EXAMPLES> below.
B<NOTE 1>: This higher resolution timer can return values either less
or more than the core C<time()>, depending on whether your platform
rounds the higher resolution timer values up, down, or to the nearest second
to get the core C<time()>, but naturally the difference should be never
more than half a second.
B<NOTE 2>: Since Sunday, September 9th, 2001 at 01:46:40 AM GMT, when
the C<time()> seconds since epoch rolled over to 1_000_000_000, the
default floating point format of Perl and the seconds since epoch have
conspired to produce an apparent bug: if you print the value of
C<Time::HiRes::time()> you seem to be getting only five decimals, not six
as promised (microseconds). Not to worry, the microseconds are there
(assuming your platform supports such granularity in first place).
What is going on is that the default floating point format of Perl
only outputs 15 digits. In this case that means ten digits before the
decimal separator and five after. To see the microseconds you can use
either C<printf>/C<sprintf> with C<"%.6f">, or the C<gettimeofday()> function in
list context, which will give you the seconds and microseconds as two
separate values.
=item sleep ( $floating_seconds )
Sleeps for the specified amount of seconds. Returns the number of
seconds actually slept (a floating point value). This function can be
imported, resulting in a nice drop-in replacement for the C<sleep>
provided with perl, see the L</EXAMPLES> below.
=item alarm ( $floating_seconds [, $interval_floating_seconds ] )
The C<SIGALRM> signal is sent after the specified number of seconds.
Implemented using C<ualarm()>. The C<$interval_floating_seconds> argument
is optional and will be zero if unspecified, resulting in C<alarm()>-like
behaviour. This function can be imported, resulting in a nice drop-in
replacement for the C<alarm> provided with perl, see the L</EXAMPLES> below.
B<NOTE 1>: With some operating system and Perl release combinations
C<SIGALRM> restarts C<select()>, instead of interuping it.
This means that an C<alarm()> followed by a C<select()>
may together take the sum of the times specified for the the
C<alarm()> and the C<select()>, not just the time of the C<alarm()>.
=item setitimer ( $which, $floating_seconds [, $interval_floating_seconds ] )
Start up an interval timer: after a certain time, a signal arrives,
and more signals may keep arriving at certain intervals. To disable a
timer, use C<$floating_seconds> of zero. If the C<$interval_floating_seconds>
is set to zero (or unspecified), the timer is disabled B<after> the
next delivered signal.
Use of interval timers may interfere with C<alarm()>, C<sleep()>,
and C<usleep()>. In standard-speak the "interaction is unspecified",
which means that I<anything> may happen: it may work, it may not.
In scalar context, the remaining time in the timer is returned.
In list context, both the remaining time and the interval are returned.
There are usually three or four interval timers available: the C<$which>
can be C<ITIMER_REAL>, C<ITIMER_VIRTUAL>, C<ITIMER_PROF>, or C<ITIMER_REALPROF>.
Note that which ones are available depends: true UNIX platforms usually
have the first three, but (for example) Win32 and Cygwin have only
C<ITIMER_REAL>, and only Solaris seems to have C<ITIMER_REALPROF> (which is
used to profile multithreaded programs).
C<ITIMER_REAL> results in C<alarm()>-like behavior. Time is counted in
I<real time>; that is, wallclock time. C<SIGALRM> is delivered when
the timer expires.
C<ITIMER_VIRTUAL> counts time in (process) I<virtual time>; that is, only
when the process is running. In multiprocessor/user/CPU systems this
may be more or less than real or wallclock time. (This time is also
known as the I<user time>.) C<SIGVTALRM> is delivered when the timer expires.
C<ITIMER_PROF> counts time when either the process virtual time or when
the operating system is running on behalf of the process (such as I/O).
(This time is also known as the I<system time>.) (The sum of user
time and system time is known as the I<CPU time>.) C<SIGPROF> is
delivered when the timer expires. C<SIGPROF> can interrupt system calls.
The semantics of interval timers for multithreaded programs are
system-specific, and some systems may support additional interval
timers. See your C<setitimer()> documentation.
=item getitimer ( $which )
Return the remaining time in the interval timer specified by C<$which>.
In scalar context, the remaining time is returned.
In list context, both the remaining time and the interval are returned.
The interval is always what you put in using C<setitimer()>.
=back
=head1 EXAMPLES
use Time::HiRes qw(usleep ualarm gettimeofday tv_interval);
$microseconds = 750_000;
usleep $microseconds;
# signal alarm in 2.5s & every .1s thereafter
ualarm 2_500_000, 100_000;
# get seconds and microseconds since the epoch
($s, $usec) = gettimeofday;
# measure elapsed time
# (could also do by subtracting 2 gettimeofday return values)
$t0 = [gettimeofday];
# do bunch of stuff here
$t1 = [gettimeofday];
# do more stuff here
$t0_t1 = tv_interval $t0, $t1;
$elapsed = tv_interval ($t0, [gettimeofday]);
$elapsed = tv_interval ($t0); # equivalent code
#
# replacements for time, alarm and sleep that know about
# floating seconds
#
use Time::HiRes;
$now_fractions = Time::HiRes::time;
Time::HiRes::sleep (2.5);
Time::HiRes::alarm (10.6666666);
use Time::HiRes qw ( time alarm sleep );
$now_fractions = time;
sleep (2.5);
alarm (10.6666666);
# Arm an interval timer to go off first at 10 seconds and
# after that every 2.5 seconds, in process virtual time
use Time::HiRes qw ( setitimer ITIMER_VIRTUAL time );
$SIG{VTALRM} = sub { print time, "\n" };
setitimer(ITIMER_VIRTUAL, 10, 2.5);
=head1 C API
In addition to the perl API described above, a C API is available for
extension writers. The following C functions are available in the
modglobal hash:
name C prototype
--------------- ----------------------
Time::NVtime double (*)()
Time::U2time void (*)(UV ret[2])
Both functions return equivalent information (like C<gettimeofday>)
but with different representations. The names C<NVtime> and C<U2time>
were selected mainly because they are operating system independent.
(C<gettimeofday> is Unix-centric, though some platforms like VMS have
emulations for it.)
Here is an example of using C<NVtime> from C:
double (*myNVtime)();
SV **svp = hv_fetch(PL_modglobal, "Time::NVtime", 12, 0);
if (!svp) croak("Time::HiRes is required");
if (!SvIOK(*svp)) croak("Time::NVtime isn't a function pointer");
myNVtime = INT2PTR(double(*)(), SvIV(*svp));
printf("The current time is: %f\n", (*myNVtime)());
=head1 DIAGNOSTICS
=head2 negative time not invented yet
You tried to use a negative time argument.
=head2 internal error: useconds < 0 (unsigned ... signed ...)
Something went horribly wrong-- the number of microseconds that cannot
become negative just became negative. Maybe your compiler is broken?
=head1 CAVEATS
Notice that the core C<time()> maybe rounding rather than truncating.
What this means is that the core C<time()> may be reporting the time as one second
later than C<gettimeofday()> and C<Time::HiRes::time()>.
=head1 AUTHORS
D. Wegscheid <wegscd@whirlpool.com>
R. Schertler <roderick@argon.org>
J. Hietaniemi <jhi@iki.fi>
G. Aas <gisle@aas.no>
=head1 COPYRIGHT AND LICENSE
Copyright (c) 1996-2002 Douglas E. Wegscheid. All rights reserved.
Copyright (c) 2002,2003,2004 Jarkko Hietaniemi. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=cut
+289
View File
@@ -0,0 +1,289 @@
package Time::Local;
require Exporter;
use Carp;
use Config;
use strict;
use integer;
use vars qw( $VERSION @ISA @EXPORT @EXPORT_OK );
$VERSION = '1.07';
@ISA = qw( Exporter );
@EXPORT = qw( timegm timelocal );
@EXPORT_OK = qw( timegm_nocheck timelocal_nocheck );
my @MonthDays = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
# Determine breakpoint for rolling century
my $ThisYear = (localtime())[5];
my $Breakpoint = ($ThisYear + 50) % 100;
my $NextCentury = $ThisYear - $ThisYear % 100;
$NextCentury += 100 if $Breakpoint < 50;
my $Century = $NextCentury - 100;
my $SecOff = 0;
my (%Options, %Cheat);
my $MaxInt = ((1<<(8 * $Config{intsize} - 2))-1)*2 + 1;
my $MaxDay = int(($MaxInt-43200)/86400)-1;
# Determine the EPOC day for this machine
my $Epoc = 0;
if ($^O eq 'vos') {
# work around posix-977 -- VOS doesn't handle dates in
# the range 1970-1980.
$Epoc = _daygm((0, 0, 0, 1, 0, 70, 4, 0));
}
elsif ($^O eq 'MacOS') {
no integer;
$MaxDay *=2 if $^O eq 'MacOS'; # time_t unsigned ... quick hack?
# MacOS time() is seconds since 1 Jan 1904, localtime
# so we need to calculate an offset to apply later
$Epoc = 693901;
$SecOff = timelocal(localtime(0)) - timelocal(gmtime(0));
$Epoc += _daygm(gmtime(0));
}
else {
$Epoc = _daygm(gmtime(0));
}
%Cheat=(); # clear the cache as epoc has changed
sub _daygm {
$_[3] + ($Cheat{pack("ss",@_[4,5])} ||= do {
my $month = ($_[4] + 10) % 12;
my $year = $_[5] + 1900 - $month/10;
365*$year + $year/4 - $year/100 + $year/400 + ($month*306 + 5)/10 - $Epoc
});
}
sub _timegm {
my $sec = $SecOff + $_[0] + 60 * $_[1] + 3600 * $_[2];
no integer;
$sec + 86400 * &_daygm;
}
sub timegm {
my ($sec,$min,$hour,$mday,$month,$year) = @_;
if ($year >= 1000) {
$year -= 1900;
}
elsif ($year < 100 and $year >= 0) {
$year += ($year > $Breakpoint) ? $Century : $NextCentury;
}
unless ($Options{no_range_check}) {
if (abs($year) >= 0x7fff) {
$year += 1900;
croak "Cannot handle date ($sec, $min, $hour, $mday, $month, $year)";
}
croak "Month '$month' out of range 0..11" if $month > 11 or $month < 0;
my $md = $MonthDays[$month];
++$md unless $month != 1 or $year % 4 or !($year % 400);
croak "Day '$mday' out of range 1..$md" if $mday > $md or $mday < 1;
croak "Hour '$hour' out of range 0..23" if $hour > 23 or $hour < 0;
croak "Minute '$min' out of range 0..59" if $min > 59 or $min < 0;
croak "Second '$sec' out of range 0..59" if $sec > 59 or $sec < 0;
}
my $days = _daygm(undef, undef, undef, $mday, $month, $year);
unless ($Options{no_range_check} or abs($days) < $MaxDay) {
$year += 1900;
croak "Cannot handle date ($sec, $min, $hour, $mday, $month, $year)";
}
$sec += $SecOff + 60*$min + 3600*$hour;
no integer;
$sec + 86400*$days;
}
sub timegm_nocheck {
local $Options{no_range_check} = 1;
&timegm;
}
sub timelocal {
no integer;
my $ref_t = &timegm;
my $loc_t = _timegm(localtime($ref_t));
# Is there a timezone offset from GMT or are we done
my $zone_off = $ref_t - $loc_t
or return $loc_t;
# Adjust for timezone
$loc_t = $ref_t + $zone_off;
# Are we close to a DST change or are we done
my $dst_off = $ref_t - _timegm(localtime($loc_t))
or return $loc_t;
# Adjust for DST change
$loc_t += $dst_off;
# for a negative offset from GMT, and if the original date
# was a non-extent gap in a forward DST jump, we should
# now have the wrong answer - undo the DST adjust;
return $loc_t if $zone_off <= 0;
my ($s,$m,$h) = localtime($loc_t);
$loc_t -= $dst_off if $s != $_[0] || $m != $_[1] || $h != $_[2];
$loc_t;
}
sub timelocal_nocheck {
local $Options{no_range_check} = 1;
&timelocal;
}
1;
__END__
=head1 NAME
Time::Local - efficiently compute time from local and GMT time
=head1 SYNOPSIS
$time = timelocal($sec,$min,$hour,$mday,$mon,$year);
$time = timegm($sec,$min,$hour,$mday,$mon,$year);
=head1 DESCRIPTION
These routines are the inverse of built-in perl functions localtime()
and gmtime(). They accept a date as a six-element array, and return
the corresponding time(2) value in seconds since the system epoch
(Midnight, January 1, 1970 UTC on Unix, for example). This value can
be positive or negative, though POSIX only requires support for
positive values, so dates before the system's epoch may not work on
all operating systems.
It is worth drawing particular attention to the expected ranges for
the values provided. The value for the day of the month is the actual day
(ie 1..31), while the month is the number of months since January (0..11).
This is consistent with the values returned from localtime() and gmtime().
The timelocal() and timegm() functions perform range checking on the
input $sec, $min, $hour, $mday, and $mon values by default. If you'd
rather they didn't, you can explicitly import the timelocal_nocheck()
and timegm_nocheck() functions.
use Time::Local 'timelocal_nocheck';
{
# The 365th day of 1999
print scalar localtime timelocal_nocheck 0,0,0,365,0,99;
# The twenty thousandth day since 1970
print scalar localtime timelocal_nocheck 0,0,0,20000,0,70;
# And even the 10,000,000th second since 1999!
print scalar localtime timelocal_nocheck 10000000,0,0,1,0,99;
}
Your mileage may vary when trying these with minutes and hours,
and it doesn't work at all for months.
Strictly speaking, the year should also be specified in a form consistent
with localtime(), i.e. the offset from 1900.
In order to make the interpretation of the year easier for humans,
however, who are more accustomed to seeing years as two-digit or four-digit
values, the following conventions are followed:
=over 4
=item *
Years greater than 999 are interpreted as being the actual year,
rather than the offset from 1900. Thus, 1963 would indicate the year
Martin Luther King won the Nobel prize, not the year 2863.
=item *
Years in the range 100..999 are interpreted as offset from 1900,
so that 112 indicates 2012. This rule also applies to years less than zero
(but see note below regarding date range).
=item *
Years in the range 0..99 are interpreted as shorthand for years in the
rolling "current century," defined as 50 years on either side of the current
year. Thus, today, in 1999, 0 would refer to 2000, and 45 to 2045,
but 55 would refer to 1955. Twenty years from now, 55 would instead refer
to 2055. This is messy, but matches the way people currently think about
two digit dates. Whenever possible, use an absolute four digit year instead.
=back
The scheme above allows interpretation of a wide range of dates, particularly
if 4-digit years are used.
Please note, however, that the range of dates that can be actually be handled
depends on the size of an integer (time_t) on a given platform.
Currently, this is 32 bits for most systems, yielding an approximate range
from Dec 1901 to Jan 2038.
Both timelocal() and timegm() croak if given dates outside the supported
range.
=head1 IMPLEMENTATION
These routines are quite efficient and yet are always guaranteed to agree
with localtime() and gmtime(). We manage this by caching the start times
of any months we've seen before. If we know the start time of the month,
we can always calculate any time within the month. The start times
are calculated using a mathematical formula. Unlike other algorithms
that do multiple calls to gmtime().
timelocal() is implemented using the same cache. We just assume that we're
translating a GMT time, and then fudge it when we're done for the timezone
and daylight savings arguments. Note that the timezone is evaluated for
each date because countries occasionally change their official timezones.
Assuming that localtime() corrects for these changes, this routine will
also be correct.
=head1 BUGS
The whole scheme for interpreting two-digit years can be considered a bug.
The proclivity to croak() is probably a bug.
=head1 SUPPORT
Support for this module is provided via the perl5-porters@perl.org
email list. See http://lists.perl.org/ for more details.
Please submit bugs using the RT system at bugs.perl.org, the perlbug
script, or as a last resort, to the perl5-porters@perl.org list.
=head1 AUTHOR
This module is based on a Perl 4 library, timelocal.pl, that was
included with Perl 4.036, and was most likely written by Tom
Christiansen.
The current version was written by Graham Barr.
It is now being maintained separately from the Perl core by Dave
Rolsky, <autarch@urth.org>.
=cut
@@ -0,0 +1,351 @@
package Time::HiRes;
use strict;
use vars qw($VERSION $XS_VERSION @ISA @EXPORT @EXPORT_OK $AUTOLOAD);
require Exporter;
require DynaLoader;
@ISA = qw(Exporter DynaLoader);
@EXPORT = qw( );
@EXPORT_OK = qw (usleep sleep ualarm alarm gettimeofday time tv_interval
getitimer setitimer
ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF ITIMER_REALPROF
d_usleep d_ualarm d_gettimeofday d_getitimer d_setitimer
d_nanosleep);
$VERSION = '1.55';
$XS_VERSION = $VERSION;
$VERSION = eval $VERSION;
sub AUTOLOAD {
my $constname;
($constname = $AUTOLOAD) =~ s/.*:://;
die "&Time::HiRes::constant not defined" if $constname eq 'constant';
my ($error, $val) = constant($constname);
if ($error) { die $error; }
{
no strict 'refs';
*$AUTOLOAD = sub { $val };
}
goto &$AUTOLOAD;
}
bootstrap Time::HiRes;
# Preloaded methods go here.
sub tv_interval {
# probably could have been done in C
my ($a, $b) = @_;
$b = [gettimeofday()] unless defined($b);
(${$b}[0] - ${$a}[0]) + ((${$b}[1] - ${$a}[1]) / 1_000_000);
}
# Autoload methods go after =cut, and are processed by the autosplit program.
1;
__END__
=head1 NAME
Time::HiRes - High resolution alarm, sleep, gettimeofday, interval timers
=head1 SYNOPSIS
use Time::HiRes qw( usleep ualarm gettimeofday tv_interval );
usleep ($microseconds);
ualarm ($microseconds);
ualarm ($microseconds, $interval_microseconds);
$t0 = [gettimeofday];
($seconds, $microseconds) = gettimeofday;
$elapsed = tv_interval ( $t0, [$seconds, $microseconds]);
$elapsed = tv_interval ( $t0, [gettimeofday]);
$elapsed = tv_interval ( $t0 );
use Time::HiRes qw ( time alarm sleep );
$now_fractions = time;
sleep ($floating_seconds);
alarm ($floating_seconds);
alarm ($floating_seconds, $floating_interval);
use Time::HiRes qw( setitimer getitimer
ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF ITIMER_REALPROF );
setitimer ($which, $floating_seconds, $floating_interval );
getitimer ($which);
=head1 DESCRIPTION
The C<Time::HiRes> module implements a Perl interface to the C<usleep>,
C<ualarm>, C<gettimeofday>, and C<setitimer>/C<getitimer> system calls, in other
words, high resolution time and timers. See the L</EXAMPLES> section below
and the test scripts for usage; see your system documentation for the
description of the underlying C<nanosleep> or C<usleep>, C<ualarm>,
C<gettimeofday>, and C<setitimer>/C<getitimer> calls.
If your system lacks C<gettimeofday()> or an emulation of it you don't
get C<gettimeofday()> or the one-argument form of C<tv_interval()>. If your system lacks all of
C<nanosleep()>, C<usleep()>, and C<select()>, you don't get
C<Time::HiRes::usleep()> or C<Time::HiRes::sleep()>. If your system lacks both
C<ualarm()> and C<setitimer()> you don't get
C<Time::HiRes::ualarm()> or C<Time::HiRes::alarm()>.
If you try to import an unimplemented function in the C<use> statement
it will fail at compile time.
If your subsecond sleeping is implemented with C<nanosleep()> instead of
C<usleep()>, you can mix subsecond sleeping with signals since
C<nanosleep()> does not use signals. This, however is unportable, and you
should first check for the truth value of C<&Time::HiRes::d_nanosleep> to
see whether you have nanosleep, and then carefully read your
C<nanosleep()> C API documentation for any peculiarities. (There is no
separate interface to call C<nanosleep()>; just use C<Time::HiRes::sleep()>
or C<Time::HiRes::usleep()> with small enough values.)
Unless using C<nanosleep> for mixing sleeping with signals, give
some thought to whether Perl is the tool you should be using for work
requiring nanosecond accuracies.
The following functions can be imported from this module.
No functions are exported by default.
=over 4
=item gettimeofday ()
In array context returns a two-element array with the seconds and
microseconds since the epoch. In scalar context returns floating
seconds like C<Time::HiRes::time()> (see below).
=item usleep ( $useconds )
Sleeps for the number of microseconds specified. Returns the number
of microseconds actually slept. Can sleep for more than one second,
unlike the C<usleep> system call. See also C<Time::HiRes::sleep()> below.
=item ualarm ( $useconds [, $interval_useconds ] )
Issues a C<ualarm> call; the C<$interval_useconds> is optional and
will be zero if unspecified, resulting in C<alarm>-like behaviour.
=item tv_interval
tv_interval ( $ref_to_gettimeofday [, $ref_to_later_gettimeofday] )
Returns the floating seconds between the two times, which should have
been returned by C<gettimeofday()>. If the second argument is omitted,
then the current time is used.
=item time ()
Returns a floating seconds since the epoch. This function can be
imported, resulting in a nice drop-in replacement for the C<time>
provided with core Perl; see the L</EXAMPLES> below.
B<NOTE 1>: This higher resolution timer can return values either less
or more than the core C<time()>, depending on whether your platform
rounds the higher resolution timer values up, down, or to the nearest second
to get the core C<time()>, but naturally the difference should be never
more than half a second.
B<NOTE 2>: Since Sunday, September 9th, 2001 at 01:46:40 AM GMT, when
the C<time()> seconds since epoch rolled over to 1_000_000_000, the
default floating point format of Perl and the seconds since epoch have
conspired to produce an apparent bug: if you print the value of
C<Time::HiRes::time()> you seem to be getting only five decimals, not six
as promised (microseconds). Not to worry, the microseconds are there
(assuming your platform supports such granularity in first place).
What is going on is that the default floating point format of Perl
only outputs 15 digits. In this case that means ten digits before the
decimal separator and five after. To see the microseconds you can use
either C<printf>/C<sprintf> with C<"%.6f">, or the C<gettimeofday()> function in
list context, which will give you the seconds and microseconds as two
separate values.
=item sleep ( $floating_seconds )
Sleeps for the specified amount of seconds. Returns the number of
seconds actually slept (a floating point value). This function can be
imported, resulting in a nice drop-in replacement for the C<sleep>
provided with perl, see the L</EXAMPLES> below.
=item alarm ( $floating_seconds [, $interval_floating_seconds ] )
The C<SIGALRM> signal is sent after the specified number of seconds.
Implemented using C<ualarm()>. The C<$interval_floating_seconds> argument
is optional and will be zero if unspecified, resulting in C<alarm()>-like
behaviour. This function can be imported, resulting in a nice drop-in
replacement for the C<alarm> provided with perl, see the L</EXAMPLES> below.
B<NOTE 1>: With some operating system and Perl release combinations
C<SIGALRM> restarts C<select()>, instead of interuping it.
This means that an C<alarm()> followed by a C<select()>
may together take the sum of the times specified for the the
C<alarm()> and the C<select()>, not just the time of the C<alarm()>.
=item setitimer ( $which, $floating_seconds [, $interval_floating_seconds ] )
Start up an interval timer: after a certain time, a signal arrives,
and more signals may keep arriving at certain intervals. To disable a
timer, use C<$floating_seconds> of zero. If the C<$interval_floating_seconds>
is set to zero (or unspecified), the timer is disabled B<after> the
next delivered signal.
Use of interval timers may interfere with C<alarm()>, C<sleep()>,
and C<usleep()>. In standard-speak the "interaction is unspecified",
which means that I<anything> may happen: it may work, it may not.
In scalar context, the remaining time in the timer is returned.
In list context, both the remaining time and the interval are returned.
There are usually three or four interval timers available: the C<$which>
can be C<ITIMER_REAL>, C<ITIMER_VIRTUAL>, C<ITIMER_PROF>, or C<ITIMER_REALPROF>.
Note that which ones are available depends: true UNIX platforms usually
have the first three, but (for example) Win32 and Cygwin have only
C<ITIMER_REAL>, and only Solaris seems to have C<ITIMER_REALPROF> (which is
used to profile multithreaded programs).
C<ITIMER_REAL> results in C<alarm()>-like behavior. Time is counted in
I<real time>; that is, wallclock time. C<SIGALRM> is delivered when
the timer expires.
C<ITIMER_VIRTUAL> counts time in (process) I<virtual time>; that is, only
when the process is running. In multiprocessor/user/CPU systems this
may be more or less than real or wallclock time. (This time is also
known as the I<user time>.) C<SIGVTALRM> is delivered when the timer expires.
C<ITIMER_PROF> counts time when either the process virtual time or when
the operating system is running on behalf of the process (such as I/O).
(This time is also known as the I<system time>.) (The sum of user
time and system time is known as the I<CPU time>.) C<SIGPROF> is
delivered when the timer expires. C<SIGPROF> can interrupt system calls.
The semantics of interval timers for multithreaded programs are
system-specific, and some systems may support additional interval
timers. See your C<setitimer()> documentation.
=item getitimer ( $which )
Return the remaining time in the interval timer specified by C<$which>.
In scalar context, the remaining time is returned.
In list context, both the remaining time and the interval are returned.
The interval is always what you put in using C<setitimer()>.
=back
=head1 EXAMPLES
use Time::HiRes qw(usleep ualarm gettimeofday tv_interval);
$microseconds = 750_000;
usleep $microseconds;
# signal alarm in 2.5s & every .1s thereafter
ualarm 2_500_000, 100_000;
# get seconds and microseconds since the epoch
($s, $usec) = gettimeofday;
# measure elapsed time
# (could also do by subtracting 2 gettimeofday return values)
$t0 = [gettimeofday];
# do bunch of stuff here
$t1 = [gettimeofday];
# do more stuff here
$t0_t1 = tv_interval $t0, $t1;
$elapsed = tv_interval ($t0, [gettimeofday]);
$elapsed = tv_interval ($t0); # equivalent code
#
# replacements for time, alarm and sleep that know about
# floating seconds
#
use Time::HiRes;
$now_fractions = Time::HiRes::time;
Time::HiRes::sleep (2.5);
Time::HiRes::alarm (10.6666666);
use Time::HiRes qw ( time alarm sleep );
$now_fractions = time;
sleep (2.5);
alarm (10.6666666);
# Arm an interval timer to go off first at 10 seconds and
# after that every 2.5 seconds, in process virtual time
use Time::HiRes qw ( setitimer ITIMER_VIRTUAL time );
$SIG{VTALRM} = sub { print time, "\n" };
setitimer(ITIMER_VIRTUAL, 10, 2.5);
=head1 C API
In addition to the perl API described above, a C API is available for
extension writers. The following C functions are available in the
modglobal hash:
name C prototype
--------------- ----------------------
Time::NVtime double (*)()
Time::U2time void (*)(UV ret[2])
Both functions return equivalent information (like C<gettimeofday>)
but with different representations. The names C<NVtime> and C<U2time>
were selected mainly because they are operating system independent.
(C<gettimeofday> is Unix-centric, though some platforms like VMS have
emulations for it.)
Here is an example of using C<NVtime> from C:
double (*myNVtime)();
SV **svp = hv_fetch(PL_modglobal, "Time::NVtime", 12, 0);
if (!svp) croak("Time::HiRes is required");
if (!SvIOK(*svp)) croak("Time::NVtime isn't a function pointer");
myNVtime = INT2PTR(double(*)(), SvIV(*svp));
printf("The current time is: %f\n", (*myNVtime)());
=head1 DIAGNOSTICS
=head2 negative time not invented yet
You tried to use a negative time argument.
=head2 internal error: useconds < 0 (unsigned ... signed ...)
Something went horribly wrong-- the number of microseconds that cannot
become negative just became negative. Maybe your compiler is broken?
=head1 CAVEATS
Notice that the core C<time()> maybe rounding rather than truncating.
What this means is that the core C<time()> may be reporting the time as one second
later than C<gettimeofday()> and C<Time::HiRes::time()>.
=head1 AUTHORS
D. Wegscheid <wegscd@whirlpool.com>
R. Schertler <roderick@argon.org>
J. Hietaniemi <jhi@iki.fi>
G. Aas <gisle@aas.no>
=head1 COPYRIGHT AND LICENSE
Copyright (c) 1996-2002 Douglas E. Wegscheid. All rights reserved.
Copyright (c) 2002,2003,2004 Jarkko Hietaniemi. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=cut
@@ -0,0 +1,359 @@
package Time::HiRes;
use strict;
use vars qw($VERSION $XS_VERSION @ISA @EXPORT @EXPORT_OK $AUTOLOAD);
require Exporter;
require DynaLoader;
@ISA = qw(Exporter DynaLoader);
@EXPORT = qw( );
@EXPORT_OK = qw (usleep sleep ualarm alarm gettimeofday time tv_interval
getitimer setitimer
ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF ITIMER_REALPROF
d_usleep d_ualarm d_gettimeofday d_getitimer d_setitimer
d_nanosleep);
$VERSION = '1.59';
$XS_VERSION = $VERSION;
$VERSION = eval $VERSION;
sub AUTOLOAD {
my $constname;
($constname = $AUTOLOAD) =~ s/.*:://;
die "&Time::HiRes::constant not defined" if $constname eq 'constant';
my ($error, $val) = constant($constname);
if ($error) { die $error; }
{
no strict 'refs';
*$AUTOLOAD = sub { $val };
}
goto &$AUTOLOAD;
}
bootstrap Time::HiRes;
# Preloaded methods go here.
sub tv_interval {
# probably could have been done in C
my ($a, $b) = @_;
$b = [gettimeofday()] unless defined($b);
(${$b}[0] - ${$a}[0]) + ((${$b}[1] - ${$a}[1]) / 1_000_000);
}
# Autoload methods go after =cut, and are processed by the autosplit program.
1;
__END__
=head1 NAME
Time::HiRes - High resolution alarm, sleep, gettimeofday, interval timers
=head1 SYNOPSIS
use Time::HiRes qw( usleep ualarm gettimeofday tv_interval );
usleep ($microseconds);
ualarm ($microseconds);
ualarm ($microseconds, $interval_microseconds);
$t0 = [gettimeofday];
($seconds, $microseconds) = gettimeofday;
$elapsed = tv_interval ( $t0, [$seconds, $microseconds]);
$elapsed = tv_interval ( $t0, [gettimeofday]);
$elapsed = tv_interval ( $t0 );
use Time::HiRes qw ( time alarm sleep );
$now_fractions = time;
sleep ($floating_seconds);
alarm ($floating_seconds);
alarm ($floating_seconds, $floating_interval);
use Time::HiRes qw( setitimer getitimer
ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF ITIMER_REALPROF );
setitimer ($which, $floating_seconds, $floating_interval );
getitimer ($which);
=head1 DESCRIPTION
The C<Time::HiRes> module implements a Perl interface to the C<usleep>,
C<ualarm>, C<gettimeofday>, and C<setitimer>/C<getitimer> system calls, in other
words, high resolution time and timers. See the L</EXAMPLES> section below
and the test scripts for usage; see your system documentation for the
description of the underlying C<nanosleep> or C<usleep>, C<ualarm>,
C<gettimeofday>, and C<setitimer>/C<getitimer> calls.
If your system lacks C<gettimeofday()> or an emulation of it you don't
get C<gettimeofday()> or the one-argument form of C<tv_interval()>. If your system lacks all of
C<nanosleep()>, C<usleep()>, and C<select()>, you don't get
C<Time::HiRes::usleep()> or C<Time::HiRes::sleep()>. If your system lacks both
C<ualarm()> and C<setitimer()> you don't get
C<Time::HiRes::ualarm()> or C<Time::HiRes::alarm()>.
If you try to import an unimplemented function in the C<use> statement
it will fail at compile time.
If your subsecond sleeping is implemented with C<nanosleep()> instead of
C<usleep()>, you can mix subsecond sleeping with signals since
C<nanosleep()> does not use signals. This, however is unportable, and you
should first check for the truth value of C<&Time::HiRes::d_nanosleep> to
see whether you have nanosleep, and then carefully read your
C<nanosleep()> C API documentation for any peculiarities. (There is no
separate interface to call C<nanosleep()>; just use C<Time::HiRes::sleep()>
or C<Time::HiRes::usleep()> with small enough values.)
Unless using C<nanosleep> for mixing sleeping with signals, give
some thought to whether Perl is the tool you should be using for work
requiring nanosecond accuracies.
The following functions can be imported from this module.
No functions are exported by default.
=over 4
=item gettimeofday ()
In array context returns a two-element array with the seconds and
microseconds since the epoch. In scalar context returns floating
seconds like C<Time::HiRes::time()> (see below).
=item usleep ( $useconds )
Sleeps for the number of microseconds specified. Returns the number
of microseconds actually slept. Can sleep for more than one second,
unlike the C<usleep> system call. See also C<Time::HiRes::sleep()> below.
=item ualarm ( $useconds [, $interval_useconds ] )
Issues a C<ualarm> call; the C<$interval_useconds> is optional and
will be zero if unspecified, resulting in C<alarm>-like behaviour.
=item tv_interval
tv_interval ( $ref_to_gettimeofday [, $ref_to_later_gettimeofday] )
Returns the floating seconds between the two times, which should have
been returned by C<gettimeofday()>. If the second argument is omitted,
then the current time is used.
=item time ()
Returns a floating seconds since the epoch. This function can be
imported, resulting in a nice drop-in replacement for the C<time>
provided with core Perl; see the L</EXAMPLES> below.
B<NOTE 1>: This higher resolution timer can return values either less
or more than the core C<time()>, depending on whether your platform
rounds the higher resolution timer values up, down, or to the nearest second
to get the core C<time()>, but naturally the difference should be never
more than half a second.
B<NOTE 2>: Since Sunday, September 9th, 2001 at 01:46:40 AM GMT, when
the C<time()> seconds since epoch rolled over to 1_000_000_000, the
default floating point format of Perl and the seconds since epoch have
conspired to produce an apparent bug: if you print the value of
C<Time::HiRes::time()> you seem to be getting only five decimals, not six
as promised (microseconds). Not to worry, the microseconds are there
(assuming your platform supports such granularity in first place).
What is going on is that the default floating point format of Perl
only outputs 15 digits. In this case that means ten digits before the
decimal separator and five after. To see the microseconds you can use
either C<printf>/C<sprintf> with C<"%.6f">, or the C<gettimeofday()> function in
list context, which will give you the seconds and microseconds as two
separate values.
=item sleep ( $floating_seconds )
Sleeps for the specified amount of seconds. Returns the number of
seconds actually slept (a floating point value). This function can be
imported, resulting in a nice drop-in replacement for the C<sleep>
provided with perl, see the L</EXAMPLES> below.
=item alarm ( $floating_seconds [, $interval_floating_seconds ] )
The C<SIGALRM> signal is sent after the specified number of seconds.
Implemented using C<ualarm()>. The C<$interval_floating_seconds> argument
is optional and will be zero if unspecified, resulting in C<alarm()>-like
behaviour. This function can be imported, resulting in a nice drop-in
replacement for the C<alarm> provided with perl, see the L</EXAMPLES> below.
B<NOTE 1>: With some operating system and Perl release combinations
C<SIGALRM> restarts C<select()>, instead of interuping it.
This means that an C<alarm()> followed by a C<select()>
may together take the sum of the times specified for the the
C<alarm()> and the C<select()>, not just the time of the C<alarm()>.
=item setitimer ( $which, $floating_seconds [, $interval_floating_seconds ] )
Start up an interval timer: after a certain time, a signal arrives,
and more signals may keep arriving at certain intervals. To disable a
timer, use C<$floating_seconds> of zero. If the C<$interval_floating_seconds>
is set to zero (or unspecified), the timer is disabled B<after> the
next delivered signal.
Use of interval timers may interfere with C<alarm()>, C<sleep()>,
and C<usleep()>. In standard-speak the "interaction is unspecified",
which means that I<anything> may happen: it may work, it may not.
In scalar context, the remaining time in the timer is returned.
In list context, both the remaining time and the interval are returned.
There are usually three or four interval timers available: the C<$which>
can be C<ITIMER_REAL>, C<ITIMER_VIRTUAL>, C<ITIMER_PROF>, or C<ITIMER_REALPROF>.
Note that which ones are available depends: true UNIX platforms usually
have the first three, but (for example) Win32 and Cygwin have only
C<ITIMER_REAL>, and only Solaris seems to have C<ITIMER_REALPROF> (which is
used to profile multithreaded programs).
C<ITIMER_REAL> results in C<alarm()>-like behavior. Time is counted in
I<real time>; that is, wallclock time. C<SIGALRM> is delivered when
the timer expires.
C<ITIMER_VIRTUAL> counts time in (process) I<virtual time>; that is, only
when the process is running. In multiprocessor/user/CPU systems this
may be more or less than real or wallclock time. (This time is also
known as the I<user time>.) C<SIGVTALRM> is delivered when the timer expires.
C<ITIMER_PROF> counts time when either the process virtual time or when
the operating system is running on behalf of the process (such as I/O).
(This time is also known as the I<system time>.) (The sum of user
time and system time is known as the I<CPU time>.) C<SIGPROF> is
delivered when the timer expires. C<SIGPROF> can interrupt system calls.
The semantics of interval timers for multithreaded programs are
system-specific, and some systems may support additional interval
timers. See your C<setitimer()> documentation.
=item getitimer ( $which )
Return the remaining time in the interval timer specified by C<$which>.
In scalar context, the remaining time is returned.
In list context, both the remaining time and the interval are returned.
The interval is always what you put in using C<setitimer()>.
=back
=head1 EXAMPLES
use Time::HiRes qw(usleep ualarm gettimeofday tv_interval);
$microseconds = 750_000;
usleep $microseconds;
# signal alarm in 2.5s & every .1s thereafter
ualarm 2_500_000, 100_000;
# get seconds and microseconds since the epoch
($s, $usec) = gettimeofday;
# measure elapsed time
# (could also do by subtracting 2 gettimeofday return values)
$t0 = [gettimeofday];
# do bunch of stuff here
$t1 = [gettimeofday];
# do more stuff here
$t0_t1 = tv_interval $t0, $t1;
$elapsed = tv_interval ($t0, [gettimeofday]);
$elapsed = tv_interval ($t0); # equivalent code
#
# replacements for time, alarm and sleep that know about
# floating seconds
#
use Time::HiRes;
$now_fractions = Time::HiRes::time;
Time::HiRes::sleep (2.5);
Time::HiRes::alarm (10.6666666);
use Time::HiRes qw ( time alarm sleep );
$now_fractions = time;
sleep (2.5);
alarm (10.6666666);
# Arm an interval timer to go off first at 10 seconds and
# after that every 2.5 seconds, in process virtual time
use Time::HiRes qw ( setitimer ITIMER_VIRTUAL time );
$SIG{VTALRM} = sub { print time, "\n" };
setitimer(ITIMER_VIRTUAL, 10, 2.5);
=head1 C API
In addition to the perl API described above, a C API is available for
extension writers. The following C functions are available in the
modglobal hash:
name C prototype
--------------- ----------------------
Time::NVtime double (*)()
Time::U2time void (*)(UV ret[2])
Both functions return equivalent information (like C<gettimeofday>)
but with different representations. The names C<NVtime> and C<U2time>
were selected mainly because they are operating system independent.
(C<gettimeofday> is Unix-centric, though some platforms like VMS have
emulations for it.)
Here is an example of using C<NVtime> from C:
double (*myNVtime)();
SV **svp = hv_fetch(PL_modglobal, "Time::NVtime", 12, 0);
if (!svp) croak("Time::HiRes is required");
if (!SvIOK(*svp)) croak("Time::NVtime isn't a function pointer");
myNVtime = INT2PTR(double(*)(), SvIV(*svp));
printf("The current time is: %f\n", (*myNVtime)());
=head1 DIAGNOSTICS
=head2 negative time not invented yet
You tried to use a negative time argument.
=head2 internal error: useconds < 0 (unsigned ... signed ...)
Something went horribly wrong-- the number of microseconds that cannot
become negative just became negative. Maybe your compiler is broken?
=head1 CAVEATS
Notice that the core C<time()> maybe rounding rather than truncating.
What this means is that the core C<time()> may be reporting the time
as one second later than C<gettimeofday()> and C<Time::HiRes::time()>.
Adjusting the system clock (either manually or by services like ntp)
may cause problems, especially for long running programs that assume
a monotonously increasing time (note that all platforms do not adjust
time as gracefully as UNIX ntp does). For example in Win32 (and derived
platforms like Cygwin and MinGW) the Time::HiRes::time() may temporarily
drift off from the system clock (and the original time()) by up to 0.5
seconds. Time::HiRes will notice this eventually and recalibrate.
=head1 AUTHORS
D. Wegscheid <wegscd@whirlpool.com>
R. Schertler <roderick@argon.org>
J. Hietaniemi <jhi@iki.fi>
G. Aas <gisle@aas.no>
=head1 COPYRIGHT AND LICENSE
Copyright (c) 1996-2002 Douglas E. Wegscheid. All rights reserved.
Copyright (c) 2002,2003,2004 Jarkko Hietaniemi. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=cut
@@ -0,0 +1,369 @@
package Time::HiRes;
use strict;
use vars qw($VERSION $XS_VERSION @ISA @EXPORT @EXPORT_OK $AUTOLOAD);
require Exporter;
require DynaLoader;
@ISA = qw(Exporter DynaLoader);
@EXPORT = qw( );
@EXPORT_OK = qw (usleep sleep ualarm alarm gettimeofday time tv_interval
getitimer setitimer
ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF ITIMER_REALPROF
d_usleep d_ualarm d_gettimeofday d_getitimer d_setitimer
d_nanosleep);
$VERSION = '1.65';
$XS_VERSION = $VERSION;
$VERSION = eval $VERSION;
sub AUTOLOAD {
my $constname;
($constname = $AUTOLOAD) =~ s/.*:://;
die "&Time::HiRes::constant not defined" if $constname eq 'constant';
my ($error, $val) = constant($constname);
if ($error) { die $error; }
{
no strict 'refs';
*$AUTOLOAD = sub { $val };
}
goto &$AUTOLOAD;
}
bootstrap Time::HiRes;
# Preloaded methods go here.
sub tv_interval {
# probably could have been done in C
my ($a, $b) = @_;
$b = [gettimeofday()] unless defined($b);
(${$b}[0] - ${$a}[0]) + ((${$b}[1] - ${$a}[1]) / 1_000_000);
}
# Autoload methods go after =cut, and are processed by the autosplit program.
1;
__END__
=head1 NAME
Time::HiRes - High resolution alarm, sleep, gettimeofday, interval timers
=head1 SYNOPSIS
use Time::HiRes qw( usleep ualarm gettimeofday tv_interval );
usleep ($microseconds);
ualarm ($microseconds);
ualarm ($microseconds, $interval_microseconds);
$t0 = [gettimeofday];
($seconds, $microseconds) = gettimeofday;
$elapsed = tv_interval ( $t0, [$seconds, $microseconds]);
$elapsed = tv_interval ( $t0, [gettimeofday]);
$elapsed = tv_interval ( $t0 );
use Time::HiRes qw ( time alarm sleep );
$now_fractions = time;
sleep ($floating_seconds);
alarm ($floating_seconds);
alarm ($floating_seconds, $floating_interval);
use Time::HiRes qw( setitimer getitimer
ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF ITIMER_REALPROF );
setitimer ($which, $floating_seconds, $floating_interval );
getitimer ($which);
=head1 DESCRIPTION
The C<Time::HiRes> module implements a Perl interface to the
C<usleep>, C<ualarm>, C<gettimeofday>, and C<setitimer>/C<getitimer>
system calls, in other words, high resolution time and timers. See the
L</EXAMPLES> section below and the test scripts for usage; see your
system documentation for the description of the underlying
C<nanosleep> or C<usleep>, C<ualarm>, C<gettimeofday>, and
C<setitimer>/C<getitimer> calls.
If your system lacks C<gettimeofday()> or an emulation of it you don't
get C<gettimeofday()> or the one-argument form of C<tv_interval()>.
If your system lacks all of C<nanosleep()>, C<usleep()>, and
C<select()>, you don't get C<Time::HiRes::usleep()> or
C<Time::HiRes::sleep()>. If your system lacks both C<ualarm()> and
C<setitimer()> you don't get C<Time::HiRes::ualarm()> or
C<Time::HiRes::alarm()>.
If you try to import an unimplemented function in the C<use> statement
it will fail at compile time.
If your subsecond sleeping is implemented with C<nanosleep()> instead
of C<usleep()>, you can mix subsecond sleeping with signals since
C<nanosleep()> does not use signals. This, however, is not portable,
and you should first check for the truth value of
C<&Time::HiRes::d_nanosleep> to see whether you have nanosleep, and
then carefully read your C<nanosleep()> C API documentation for any
peculiarities. (There is no separate interface to call
C<nanosleep()>; just use C<Time::HiRes::sleep()> or
C<Time::HiRes::usleep()> with small enough values.)
Unless using C<nanosleep> for mixing sleeping with signals, give
some thought to whether Perl is the tool you should be using for
work requiring nanosecond accuracies.
The following functions can be imported from this module.
No functions are exported by default.
=over 4
=item gettimeofday ()
In array context returns a two-element array with the seconds and
microseconds since the epoch. In scalar context returns floating
seconds like C<Time::HiRes::time()> (see below).
=item usleep ( $useconds )
Sleeps for the number of microseconds specified. Returns the number
of microseconds actually slept. Can sleep for more than one second,
unlike the C<usleep> system call. See also C<Time::HiRes::sleep()> below.
=item ualarm ( $useconds [, $interval_useconds ] )
Issues a C<ualarm> call; the C<$interval_useconds> is optional and
will be zero if unspecified, resulting in C<alarm>-like behaviour.
Note that the interaction between alarms and sleeps are unspecified.
=item tv_interval
tv_interval ( $ref_to_gettimeofday [, $ref_to_later_gettimeofday] )
Returns the floating seconds between the two times, which should have
been returned by C<gettimeofday()>. If the second argument is omitted,
then the current time is used.
=item time ()
Returns a floating seconds since the epoch. This function can be
imported, resulting in a nice drop-in replacement for the C<time>
provided with core Perl; see the L</EXAMPLES> below.
B<NOTE 1>: This higher resolution timer can return values either less
or more than the core C<time()>, depending on whether your platform
rounds the higher resolution timer values up, down, or to the nearest second
to get the core C<time()>, but naturally the difference should be never
more than half a second.
B<NOTE 2>: Since Sunday, September 9th, 2001 at 01:46:40 AM GMT, when
the C<time()> seconds since epoch rolled over to 1_000_000_000, the
default floating point format of Perl and the seconds since epoch have
conspired to produce an apparent bug: if you print the value of
C<Time::HiRes::time()> you seem to be getting only five decimals, not
six as promised (microseconds). Not to worry, the microseconds are
there (assuming your platform supports such granularity in the first
place). What is going on is that the default floating point format of
Perl only outputs 15 digits. In this case that means ten digits
before the decimal separator and five after. To see the microseconds
you can use either C<printf>/C<sprintf> with C<"%.6f">, or the
C<gettimeofday()> function in list context, which will give you the
seconds and microseconds as two separate values.
=item sleep ( $floating_seconds )
Sleeps for the specified amount of seconds. Returns the number of
seconds actually slept (a floating point value). This function can
be imported, resulting in a nice drop-in replacement for the C<sleep>
provided with perl, see the L</EXAMPLES> below.
Note that the interaction between alarms and sleeps are unspecified.
=item alarm ( $floating_seconds [, $interval_floating_seconds ] )
The C<SIGALRM> signal is sent after the specified number of seconds.
Implemented using C<ualarm()>. The C<$interval_floating_seconds> argument
is optional and will be zero if unspecified, resulting in C<alarm()>-like
behaviour. This function can be imported, resulting in a nice drop-in
replacement for the C<alarm> provided with perl, see the L</EXAMPLES> below.
B<NOTE 1>: With some combinations of operating systems and Perl
releases C<SIGALRM> restarts C<select()>, instead of interrupting it.
This means that an C<alarm()> followed by a C<select()> may together
take the sum of the times specified for the the C<alarm()> and the
C<select()>, not just the time of the C<alarm()>.
Note that the interaction between alarms and sleeps are unspecified.
=item setitimer ( $which, $floating_seconds [, $interval_floating_seconds ] )
Start up an interval timer: after a certain time, a signal arrives,
and more signals may keep arriving at certain intervals. To disable
an "itimer", use C<$floating_seconds> of zero. If the
C<$interval_floating_seconds> is set to zero (or unspecified), the
timer is disabled B<after> the next delivered signal.
Use of interval timers may interfere with C<alarm()>, C<sleep()>,
and C<usleep()>. In standard-speak the "interaction is unspecified",
which means that I<anything> may happen: it may work, it may not.
In scalar context, the remaining time in the timer is returned.
In list context, both the remaining time and the interval are returned.
There are usually three or four interval timers available: the
C<$which> can be C<ITIMER_REAL>, C<ITIMER_VIRTUAL>, C<ITIMER_PROF>, or
C<ITIMER_REALPROF>. Note that which ones are available depends: true
UNIX platforms usually have the first three, but (for example) Win32
and Cygwin have only C<ITIMER_REAL>, and only Solaris seems to have
C<ITIMER_REALPROF> (which is used to profile multithreaded programs).
C<ITIMER_REAL> results in C<alarm()>-like behavior. Time is counted in
I<real time>; that is, wallclock time. C<SIGALRM> is delivered when
the timer expires.
C<ITIMER_VIRTUAL> counts time in (process) I<virtual time>; that is,
only when the process is running. In multiprocessor/user/CPU systems
this may be more or less than real or wallclock time. (This time is
also known as the I<user time>.) C<SIGVTALRM> is delivered when the
timer expires.
C<ITIMER_PROF> counts time when either the process virtual time or when
the operating system is running on behalf of the process (such as I/O).
(This time is also known as the I<system time>.) (The sum of user
time and system time is known as the I<CPU time>.) C<SIGPROF> is
delivered when the timer expires. C<SIGPROF> can interrupt system calls.
The semantics of interval timers for multithreaded programs are
system-specific, and some systems may support additional interval
timers. See your C<setitimer()> documentation.
=item getitimer ( $which )
Return the remaining time in the interval timer specified by C<$which>.
In scalar context, the remaining time is returned.
In list context, both the remaining time and the interval are returned.
The interval is always what you put in using C<setitimer()>.
=back
=head1 EXAMPLES
use Time::HiRes qw(usleep ualarm gettimeofday tv_interval);
$microseconds = 750_000;
usleep $microseconds;
# signal alarm in 2.5s & every .1s thereafter
ualarm 2_500_000, 100_000;
# get seconds and microseconds since the epoch
($s, $usec) = gettimeofday;
# measure elapsed time
# (could also do by subtracting 2 gettimeofday return values)
$t0 = [gettimeofday];
# do bunch of stuff here
$t1 = [gettimeofday];
# do more stuff here
$t0_t1 = tv_interval $t0, $t1;
$elapsed = tv_interval ($t0, [gettimeofday]);
$elapsed = tv_interval ($t0); # equivalent code
#
# replacements for time, alarm and sleep that know about
# floating seconds
#
use Time::HiRes;
$now_fractions = Time::HiRes::time;
Time::HiRes::sleep (2.5);
Time::HiRes::alarm (10.6666666);
use Time::HiRes qw ( time alarm sleep );
$now_fractions = time;
sleep (2.5);
alarm (10.6666666);
# Arm an interval timer to go off first at 10 seconds and
# after that every 2.5 seconds, in process virtual time
use Time::HiRes qw ( setitimer ITIMER_VIRTUAL time );
$SIG{VTALRM} = sub { print time, "\n" };
setitimer(ITIMER_VIRTUAL, 10, 2.5);
=head1 C API
In addition to the perl API described above, a C API is available for
extension writers. The following C functions are available in the
modglobal hash:
name C prototype
--------------- ----------------------
Time::NVtime double (*)()
Time::U2time void (*)(UV ret[2])
Both functions return equivalent information (like C<gettimeofday>)
but with different representations. The names C<NVtime> and C<U2time>
were selected mainly because they are operating system independent.
(C<gettimeofday> is Unix-centric, though some platforms like VMS have
emulations for it.)
Here is an example of using C<NVtime> from C:
double (*myNVtime)();
SV **svp = hv_fetch(PL_modglobal, "Time::NVtime", 12, 0);
if (!svp) croak("Time::HiRes is required");
if (!SvIOK(*svp)) croak("Time::NVtime isn't a function pointer");
myNVtime = INT2PTR(double(*)(), SvIV(*svp));
printf("The current time is: %f\n", (*myNVtime)());
=head1 DIAGNOSTICS
=head2 negative time not invented yet
You tried to use a negative time argument.
=head2 internal error: useconds < 0 (unsigned ... signed ...)
Something went horribly wrong-- the number of microseconds that cannot
become negative just became negative. Maybe your compiler is broken?
=head1 CAVEATS
Notice that the core C<time()> maybe rounding rather than truncating.
What this means is that the core C<time()> may be reporting the time
as one second later than C<gettimeofday()> and C<Time::HiRes::time()>.
Adjusting the system clock (either manually or by services like ntp)
may cause problems, especially for long running programs that assume
a monotonously increasing time (note that all platforms do not adjust
time as gracefully as UNIX ntp does). For example in Win32 (and derived
platforms like Cygwin and MinGW) the Time::HiRes::time() may temporarily
drift off from the system clock (and the original time()) by up to 0.5
seconds. Time::HiRes will notice this eventually and recalibrate.
=head1 AUTHORS
D. Wegscheid <wegscd@whirlpool.com>
R. Schertler <roderick@argon.org>
J. Hietaniemi <jhi@iki.fi>
G. Aas <gisle@aas.no>
=head1 COPYRIGHT AND LICENSE
Copyright (c) 1996-2002 Douglas E. Wegscheid. All rights reserved.
Copyright (c) 2002,2003,2004 Jarkko Hietaniemi. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=cut
@@ -0,0 +1,359 @@
package Time::HiRes;
use strict;
use vars qw($VERSION $XS_VERSION @ISA @EXPORT @EXPORT_OK $AUTOLOAD);
require Exporter;
require DynaLoader;
@ISA = qw(Exporter DynaLoader);
@EXPORT = qw( );
@EXPORT_OK = qw (usleep sleep ualarm alarm gettimeofday time tv_interval
getitimer setitimer
ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF ITIMER_REALPROF
d_usleep d_ualarm d_gettimeofday d_getitimer d_setitimer
d_nanosleep);
$VERSION = '1.59';
$XS_VERSION = $VERSION;
$VERSION = eval $VERSION;
sub AUTOLOAD {
my $constname;
($constname = $AUTOLOAD) =~ s/.*:://;
die "&Time::HiRes::constant not defined" if $constname eq 'constant';
my ($error, $val) = constant($constname);
if ($error) { die $error; }
{
no strict 'refs';
*$AUTOLOAD = sub { $val };
}
goto &$AUTOLOAD;
}
bootstrap Time::HiRes;
# Preloaded methods go here.
sub tv_interval {
# probably could have been done in C
my ($a, $b) = @_;
$b = [gettimeofday()] unless defined($b);
(${$b}[0] - ${$a}[0]) + ((${$b}[1] - ${$a}[1]) / 1_000_000);
}
# Autoload methods go after =cut, and are processed by the autosplit program.
1;
__END__
=head1 NAME
Time::HiRes - High resolution alarm, sleep, gettimeofday, interval timers
=head1 SYNOPSIS
use Time::HiRes qw( usleep ualarm gettimeofday tv_interval );
usleep ($microseconds);
ualarm ($microseconds);
ualarm ($microseconds, $interval_microseconds);
$t0 = [gettimeofday];
($seconds, $microseconds) = gettimeofday;
$elapsed = tv_interval ( $t0, [$seconds, $microseconds]);
$elapsed = tv_interval ( $t0, [gettimeofday]);
$elapsed = tv_interval ( $t0 );
use Time::HiRes qw ( time alarm sleep );
$now_fractions = time;
sleep ($floating_seconds);
alarm ($floating_seconds);
alarm ($floating_seconds, $floating_interval);
use Time::HiRes qw( setitimer getitimer
ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF ITIMER_REALPROF );
setitimer ($which, $floating_seconds, $floating_interval );
getitimer ($which);
=head1 DESCRIPTION
The C<Time::HiRes> module implements a Perl interface to the C<usleep>,
C<ualarm>, C<gettimeofday>, and C<setitimer>/C<getitimer> system calls, in other
words, high resolution time and timers. See the L</EXAMPLES> section below
and the test scripts for usage; see your system documentation for the
description of the underlying C<nanosleep> or C<usleep>, C<ualarm>,
C<gettimeofday>, and C<setitimer>/C<getitimer> calls.
If your system lacks C<gettimeofday()> or an emulation of it you don't
get C<gettimeofday()> or the one-argument form of C<tv_interval()>. If your system lacks all of
C<nanosleep()>, C<usleep()>, and C<select()>, you don't get
C<Time::HiRes::usleep()> or C<Time::HiRes::sleep()>. If your system lacks both
C<ualarm()> and C<setitimer()> you don't get
C<Time::HiRes::ualarm()> or C<Time::HiRes::alarm()>.
If you try to import an unimplemented function in the C<use> statement
it will fail at compile time.
If your subsecond sleeping is implemented with C<nanosleep()> instead of
C<usleep()>, you can mix subsecond sleeping with signals since
C<nanosleep()> does not use signals. This, however is unportable, and you
should first check for the truth value of C<&Time::HiRes::d_nanosleep> to
see whether you have nanosleep, and then carefully read your
C<nanosleep()> C API documentation for any peculiarities. (There is no
separate interface to call C<nanosleep()>; just use C<Time::HiRes::sleep()>
or C<Time::HiRes::usleep()> with small enough values.)
Unless using C<nanosleep> for mixing sleeping with signals, give
some thought to whether Perl is the tool you should be using for work
requiring nanosecond accuracies.
The following functions can be imported from this module.
No functions are exported by default.
=over 4
=item gettimeofday ()
In array context returns a two-element array with the seconds and
microseconds since the epoch. In scalar context returns floating
seconds like C<Time::HiRes::time()> (see below).
=item usleep ( $useconds )
Sleeps for the number of microseconds specified. Returns the number
of microseconds actually slept. Can sleep for more than one second,
unlike the C<usleep> system call. See also C<Time::HiRes::sleep()> below.
=item ualarm ( $useconds [, $interval_useconds ] )
Issues a C<ualarm> call; the C<$interval_useconds> is optional and
will be zero if unspecified, resulting in C<alarm>-like behaviour.
=item tv_interval
tv_interval ( $ref_to_gettimeofday [, $ref_to_later_gettimeofday] )
Returns the floating seconds between the two times, which should have
been returned by C<gettimeofday()>. If the second argument is omitted,
then the current time is used.
=item time ()
Returns a floating seconds since the epoch. This function can be
imported, resulting in a nice drop-in replacement for the C<time>
provided with core Perl; see the L</EXAMPLES> below.
B<NOTE 1>: This higher resolution timer can return values either less
or more than the core C<time()>, depending on whether your platform
rounds the higher resolution timer values up, down, or to the nearest second
to get the core C<time()>, but naturally the difference should be never
more than half a second.
B<NOTE 2>: Since Sunday, September 9th, 2001 at 01:46:40 AM GMT, when
the C<time()> seconds since epoch rolled over to 1_000_000_000, the
default floating point format of Perl and the seconds since epoch have
conspired to produce an apparent bug: if you print the value of
C<Time::HiRes::time()> you seem to be getting only five decimals, not six
as promised (microseconds). Not to worry, the microseconds are there
(assuming your platform supports such granularity in first place).
What is going on is that the default floating point format of Perl
only outputs 15 digits. In this case that means ten digits before the
decimal separator and five after. To see the microseconds you can use
either C<printf>/C<sprintf> with C<"%.6f">, or the C<gettimeofday()> function in
list context, which will give you the seconds and microseconds as two
separate values.
=item sleep ( $floating_seconds )
Sleeps for the specified amount of seconds. Returns the number of
seconds actually slept (a floating point value). This function can be
imported, resulting in a nice drop-in replacement for the C<sleep>
provided with perl, see the L</EXAMPLES> below.
=item alarm ( $floating_seconds [, $interval_floating_seconds ] )
The C<SIGALRM> signal is sent after the specified number of seconds.
Implemented using C<ualarm()>. The C<$interval_floating_seconds> argument
is optional and will be zero if unspecified, resulting in C<alarm()>-like
behaviour. This function can be imported, resulting in a nice drop-in
replacement for the C<alarm> provided with perl, see the L</EXAMPLES> below.
B<NOTE 1>: With some operating system and Perl release combinations
C<SIGALRM> restarts C<select()>, instead of interuping it.
This means that an C<alarm()> followed by a C<select()>
may together take the sum of the times specified for the the
C<alarm()> and the C<select()>, not just the time of the C<alarm()>.
=item setitimer ( $which, $floating_seconds [, $interval_floating_seconds ] )
Start up an interval timer: after a certain time, a signal arrives,
and more signals may keep arriving at certain intervals. To disable a
timer, use C<$floating_seconds> of zero. If the C<$interval_floating_seconds>
is set to zero (or unspecified), the timer is disabled B<after> the
next delivered signal.
Use of interval timers may interfere with C<alarm()>, C<sleep()>,
and C<usleep()>. In standard-speak the "interaction is unspecified",
which means that I<anything> may happen: it may work, it may not.
In scalar context, the remaining time in the timer is returned.
In list context, both the remaining time and the interval are returned.
There are usually three or four interval timers available: the C<$which>
can be C<ITIMER_REAL>, C<ITIMER_VIRTUAL>, C<ITIMER_PROF>, or C<ITIMER_REALPROF>.
Note that which ones are available depends: true UNIX platforms usually
have the first three, but (for example) Win32 and Cygwin have only
C<ITIMER_REAL>, and only Solaris seems to have C<ITIMER_REALPROF> (which is
used to profile multithreaded programs).
C<ITIMER_REAL> results in C<alarm()>-like behavior. Time is counted in
I<real time>; that is, wallclock time. C<SIGALRM> is delivered when
the timer expires.
C<ITIMER_VIRTUAL> counts time in (process) I<virtual time>; that is, only
when the process is running. In multiprocessor/user/CPU systems this
may be more or less than real or wallclock time. (This time is also
known as the I<user time>.) C<SIGVTALRM> is delivered when the timer expires.
C<ITIMER_PROF> counts time when either the process virtual time or when
the operating system is running on behalf of the process (such as I/O).
(This time is also known as the I<system time>.) (The sum of user
time and system time is known as the I<CPU time>.) C<SIGPROF> is
delivered when the timer expires. C<SIGPROF> can interrupt system calls.
The semantics of interval timers for multithreaded programs are
system-specific, and some systems may support additional interval
timers. See your C<setitimer()> documentation.
=item getitimer ( $which )
Return the remaining time in the interval timer specified by C<$which>.
In scalar context, the remaining time is returned.
In list context, both the remaining time and the interval are returned.
The interval is always what you put in using C<setitimer()>.
=back
=head1 EXAMPLES
use Time::HiRes qw(usleep ualarm gettimeofday tv_interval);
$microseconds = 750_000;
usleep $microseconds;
# signal alarm in 2.5s & every .1s thereafter
ualarm 2_500_000, 100_000;
# get seconds and microseconds since the epoch
($s, $usec) = gettimeofday;
# measure elapsed time
# (could also do by subtracting 2 gettimeofday return values)
$t0 = [gettimeofday];
# do bunch of stuff here
$t1 = [gettimeofday];
# do more stuff here
$t0_t1 = tv_interval $t0, $t1;
$elapsed = tv_interval ($t0, [gettimeofday]);
$elapsed = tv_interval ($t0); # equivalent code
#
# replacements for time, alarm and sleep that know about
# floating seconds
#
use Time::HiRes;
$now_fractions = Time::HiRes::time;
Time::HiRes::sleep (2.5);
Time::HiRes::alarm (10.6666666);
use Time::HiRes qw ( time alarm sleep );
$now_fractions = time;
sleep (2.5);
alarm (10.6666666);
# Arm an interval timer to go off first at 10 seconds and
# after that every 2.5 seconds, in process virtual time
use Time::HiRes qw ( setitimer ITIMER_VIRTUAL time );
$SIG{VTALRM} = sub { print time, "\n" };
setitimer(ITIMER_VIRTUAL, 10, 2.5);
=head1 C API
In addition to the perl API described above, a C API is available for
extension writers. The following C functions are available in the
modglobal hash:
name C prototype
--------------- ----------------------
Time::NVtime double (*)()
Time::U2time void (*)(UV ret[2])
Both functions return equivalent information (like C<gettimeofday>)
but with different representations. The names C<NVtime> and C<U2time>
were selected mainly because they are operating system independent.
(C<gettimeofday> is Unix-centric, though some platforms like VMS have
emulations for it.)
Here is an example of using C<NVtime> from C:
double (*myNVtime)();
SV **svp = hv_fetch(PL_modglobal, "Time::NVtime", 12, 0);
if (!svp) croak("Time::HiRes is required");
if (!SvIOK(*svp)) croak("Time::NVtime isn't a function pointer");
myNVtime = INT2PTR(double(*)(), SvIV(*svp));
printf("The current time is: %f\n", (*myNVtime)());
=head1 DIAGNOSTICS
=head2 negative time not invented yet
You tried to use a negative time argument.
=head2 internal error: useconds < 0 (unsigned ... signed ...)
Something went horribly wrong-- the number of microseconds that cannot
become negative just became negative. Maybe your compiler is broken?
=head1 CAVEATS
Notice that the core C<time()> maybe rounding rather than truncating.
What this means is that the core C<time()> may be reporting the time
as one second later than C<gettimeofday()> and C<Time::HiRes::time()>.
Adjusting the system clock (either manually or by services like ntp)
may cause problems, especially for long running programs that assume
a monotonously increasing time (note that all platforms do not adjust
time as gracefully as UNIX ntp does). For example in Win32 (and derived
platforms like Cygwin and MinGW) the Time::HiRes::time() may temporarily
drift off from the system clock (and the original time()) by up to 0.5
seconds. Time::HiRes will notice this eventually and recalibrate.
=head1 AUTHORS
D. Wegscheid <wegscd@whirlpool.com>
R. Schertler <roderick@argon.org>
J. Hietaniemi <jhi@iki.fi>
G. Aas <gisle@aas.no>
=head1 COPYRIGHT AND LICENSE
Copyright (c) 1996-2002 Douglas E. Wegscheid. All rights reserved.
Copyright (c) 2002,2003,2004 Jarkko Hietaniemi. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=cut
+90
View File
@@ -0,0 +1,90 @@
package Time::gmtime;
use strict;
use 5.006_001;
use Time::tm;
our(@ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS, $VERSION);
BEGIN {
use Exporter ();
@ISA = qw(Exporter Time::tm);
@EXPORT = qw(gmtime gmctime);
@EXPORT_OK = qw(
$tm_sec $tm_min $tm_hour $tm_mday
$tm_mon $tm_year $tm_wday $tm_yday
$tm_isdst
);
%EXPORT_TAGS = ( FIELDS => [ @EXPORT_OK, @EXPORT ] );
$VERSION = 1.02;
}
use vars @EXPORT_OK;
sub populate (@) {
return unless @_;
my $tmob = Time::tm->new();
@$tmob = (
$tm_sec, $tm_min, $tm_hour, $tm_mday,
$tm_mon, $tm_year, $tm_wday, $tm_yday,
$tm_isdst )
= @_;
return $tmob;
}
sub gmtime (;$) { populate CORE::gmtime(@_ ? shift : time)}
sub gmctime (;$) { scalar CORE::gmtime(@_ ? shift : time)}
1;
__END__
=head1 NAME
Time::gmtime - by-name interface to Perl's built-in gmtime() function
=head1 SYNOPSIS
use Time::gmtime;
$gm = gmtime();
printf "The day in Greenwich is %s\n",
(qw(Sun Mon Tue Wed Thu Fri Sat Sun))[ gm->wday() ];
use Time::gmtime w(:FIELDS;
printf "The day in Greenwich is %s\n",
(qw(Sun Mon Tue Wed Thu Fri Sat Sun))[ gm_wday() ];
$now = gmctime();
use Time::gmtime;
use File::stat;
$date_string = gmctime(stat($file)->mtime);
=head1 DESCRIPTION
This module's default exports override the core gmtime() function,
replacing it with a version that returns "Time::tm" objects.
This object has methods that return the similarly named structure field
name from the C's tm structure from F<time.h>; namely sec, min, hour,
mday, mon, year, wday, yday, and isdst.
You may also import all the structure fields directly into your namespace
as regular variables using the :FIELDS import tag. (Note that this
still overrides your core functions.) Access these fields as variables
named with a preceding C<tm_> in front their method names. Thus,
C<$tm_obj-E<gt>mday()> corresponds to $tm_mday if you import the fields.
The gmctime() function provides a way of getting at the
scalar sense of the original CORE::gmtime() function.
To access this functionality without the core overrides,
pass the C<use> an empty import list, and then access
function functions with their full qualified names.
On the other hand, the built-ins are still available
via the C<CORE::> pseudo-package.
=head1 NOTE
While this class is currently implemented using the Class::Struct
module to build a struct-like class, you shouldn't rely upon this.
=head1 AUTHOR
Tom Christiansen
+86
View File
@@ -0,0 +1,86 @@
package Time::localtime;
use strict;
use 5.006_001;
use Time::tm;
our(@ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS, $VERSION);
BEGIN {
use Exporter ();
@ISA = qw(Exporter Time::tm);
@EXPORT = qw(localtime ctime);
@EXPORT_OK = qw(
$tm_sec $tm_min $tm_hour $tm_mday
$tm_mon $tm_year $tm_wday $tm_yday
$tm_isdst
);
%EXPORT_TAGS = ( FIELDS => [ @EXPORT_OK, @EXPORT ] );
$VERSION = 1.02;
}
use vars @EXPORT_OK;
sub populate (@) {
return unless @_;
my $tmob = Time::tm->new();
@$tmob = (
$tm_sec, $tm_min, $tm_hour, $tm_mday,
$tm_mon, $tm_year, $tm_wday, $tm_yday,
$tm_isdst )
= @_;
return $tmob;
}
sub localtime (;$) { populate CORE::localtime(@_ ? shift : time)}
sub ctime (;$) { scalar CORE::localtime(@_ ? shift : time) }
1;
__END__
=head1 NAME
Time::localtime - by-name interface to Perl's built-in localtime() function
=head1 SYNOPSIS
use Time::localtime;
printf "Year is %d\n", localtime->year() + 1900;
$now = ctime();
use Time::localtime;
use File::stat;
$date_string = ctime(stat($file)->mtime);
=head1 DESCRIPTION
This module's default exports override the core localtime() function,
replacing it with a version that returns "Time::tm" objects.
This object has methods that return the similarly named structure field
name from the C's tm structure from F<time.h>; namely sec, min, hour,
mday, mon, year, wday, yday, and isdst.
You may also import all the structure fields directly into your namespace
as regular variables using the :FIELDS import tag. (Note that this still
overrides your core functions.) Access these fields as
variables named with a preceding C<tm_> in front their method names.
Thus, C<$tm_obj-E<gt>mday()> corresponds to $tm_mday if you import
the fields.
The ctime() function provides a way of getting at the
scalar sense of the original CORE::localtime() function.
To access this functionality without the core overrides,
pass the C<use> an empty import list, and then access
function functions with their full qualified names.
On the other hand, the built-ins are still available
via the C<CORE::> pseudo-package.
=head1 NOTE
While this class is currently implemented using the Class::Struct
module to build a struct-like class, you shouldn't rely upon this.
=head1 AUTHOR
Tom Christiansen
+33
View File
@@ -0,0 +1,33 @@
package Time::tm;
use strict;
our $VERSION = '1.00';
use Class::Struct qw(struct);
struct('Time::tm' => [
map { $_ => '$' } qw{ sec min hour mday mon year wday yday isdst }
]);
1;
__END__
=head1 NAME
Time::tm - internal object used by Time::gmtime and Time::localtime
=head1 SYNOPSIS
Don't use this module directly.
=head1 DESCRIPTION
This module is used internally as a base class by Time::localtime And
Time::gmtime functions. It creates a Time::tm struct object which is
addressable just like's C's tm structure from F<time.h>; namely with sec,
min, hour, mday, mon, year, wday, yday, and isdst.
This class is an internal interface only.
=head1 AUTHOR
Tom Christiansen
+51
View File
@@ -0,0 +1,51 @@
MA|01000|02799
RI|02800|02999
NH|03000|03899
ME|03900|04999
VT|05000|05999
CT|06000|06999
NJ|07000|08999
NY|10000|14999
PA|15000|19699
DE|19700|19999
DC|20000|20599
MD|20600|21999
VA|22000|24699
WV|24700|26999
NC|27000|28999
SC|29000|29999
GA|30000|31999
FL|32000|34999
AL|35000|36999
TN|37000|38599
MS|38600|39999
KY|40000|42999
OH|43000|45999
IN|46000|47999
MI|48000|49999
IA|50000|52999
WI|53000|54999
MN|55000|56999
SD|57000|57999
ND|58000|58999
MT|59000|59999
IL|60000|62999
MO|63000|65999
KS|66000|67999
NE|68000|69999
LA|70000|71599
AR|71600|72999
OK|73000|74999
TX|75000|79999
CO|80000|81999
WY|82000|83199
ID|83200|83999
UT|84000|84999
AZ|85000|86999
NM|87000|88899
NV|88900|89999
CA|90000|96699
HI|96700|96999
OR|97000|97999
WA|98000|99499
AK|99500|99999
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 520 B