Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
#!/usr/bin/perl
use strict;
use English qw/ $POSTMATCH /;
use FileHandle;
use File::Basename qw/ basename /;
use POSIX qw/ SEEK_END EAGAIN /;
use Sys::Syslog qw/ openlog syslog closelog /;
# バージョン番号
my $VERSION = sprintf( '0.%d.%02d', q$Revision: 1.7 $ =~ /(\d+)\.(\d+)/ );
my $BASENAME = &basename( $0, ".perl" );
=head1 NAME
safeconnect - ondemand 接続を行う PPP リンク上で安全に接続する
=head1 SYNOPSIS
safeconnect [OPTIONS] HOST PORT
=head1 DESCRIPTION
ondemand 接続を行う PPP リンク上で安全に通信を開始するための
connect(1) のラッパースクリプト.指定されたオプション,接続先ホスト名
およびポート番号は,最終的には全て connect によって処理される.
pppd(8) に I オプションを指定して,ondemand 接続を行うように設
定している場合,ppp インタフェースの IP アドレス は起動時に設定済みで
ある.そのため,ISP によって動的に IP アドレスが割り当てられる場合,
PPP 接続の確立時にインターフェースの IP アドレスが変化し,既存の接続が
破壊されることがある.
この問題を避けるため,このスクリプトは以下の手順で接続を行う.
=over 4
=item (1)
connect を使って指定されたサーバに最初の接続を行う.
=item (2)
既に PPP 接続が確立している場合は接続に成功する.
確立していなかった場合は dialup が始まるので,その間に connect を強制
終了させ,F を監視して接続が確立されるのを待つ.
=item (3)
実際に connect を実行して,指定されたサーバに接続する.
=back
=cut
# 実際に実行する connect コマンドのパス
my $PROG = "/usr/bin/connect";
# pppd の接続記録が保存されているファイル
my $LOGFILE = "/var/log/messages";
# 接続記録の末尾 $SIZE byte だけを調べる対象とする
my $SIZE = 4096;
# 最初に接続状態の確認のために実行される connect コマンドの接続待ち時間
my $TIMEOUT = 20;
# 接続記録を syslog に記録する場合の属性
my $FACILITY = "daemon";
# デバッグオプションが指定されているか?
my $DEBUG = grep( $_ eq "-d", @ARGV );
# 本体
if( $FACILITY and ! $DEBUG ){
&openlog( $BASENAME, 'pid', $FACILITY );
&syslog( "info", join( ' ', $PROG, @ARGV ) );
&closelog();
}
&watch() unless &check();
&debug( "2nd connect" );
&start();
# connect を実行して,ネットワーク接続が利用可能な状態か検査する関数
sub check {
&debug( "check()" );
# 子プロセスを fork する
for( my $i; $i < 5; $i++ ){
if( my $pid = fork ){
# 親プロセス側の処理
local $SIG{ALRM} = sub { die "SIGALRM is received\n"; };
eval {
alarm $TIMEOUT;
waitpid( $pid, 0 );
alarm 0;
};
if( $@ =~ /SIGALRM is received/ ){
# timeout した場合は,必ず子プロセスを終了させておく必
# 要がある.
&debug( "Timeout occured" );
kill 9, $pid;
return 0;
} else {
&debug( "Connection succeeded" );
return 1;
}
} elsif( defined $pid ){
# 子プロセス側の処理
STDIN->close;
&debug( "1st connect" );
if( $DEBUG ){
&start();
} else {
my $null = new FileHandle( "/dev/null", "w" );
if( $null ){
STDOUT->fdopen( $null, "w" );
STDERR->fdopen( $null, "w" );
&start();
}
}
exit 0; # Not reach.
} elsif( $! == &EAGAIN ){
sleep 5;
next;
} else {
die "Can't fork $PROG: $!\n";
}
}
die "Can't fork $PROG: retry conter exceeded\n";
}
# $LOGFILE を監視して,pppd が接続を確立するまで待機する関数
sub watch {
&debug( "watch()" );
my( $fh, $data, $pid );
while( $fh = new FileHandle( $LOGFILE, "r" ) ){
$fh->seek( -$SIZE, &SEEK_END );
$fh->read( $data, $SIZE );
$fh->close;
while( $data =~ /\spppd\[(\d+)\]: Starting link/m ){
$pid = $1;
$data = $POSTMATCH;
}
last if $data =~ /\spppd\[$pid\]: Local IP address changed to/m;
sleep 5;
}
}
# 実際に connect を実行する関数
sub start {
&debug( "start()" );
exec( $PROG, @ARGV );
}
sub debug {
if( $DEBUG ){
STDERR->print( "DEBUG: ", sprintf( shift @_, @_ ), "\n" );
STDERR->flush;
}
}
=head1 SEE ALSO
connect(1) または http://www.imasy.or.jp/~gotoh/ssh/connect.html
=head1 AUTHOR
=over 4
=item TSUCHIYA Masatoshi
=back
=head1 COPYRIGHT
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, you can either send email to this
program's maintainer or write to: The Free Software Foundation,
Inc.; 59 Temple Place, Suite 330; Boston, MA 02111-1307, USA.
Last Update: $Date: 2002/11/30 14:10:21 $
=cut