#!/usr/bin/perl

# 引数１に実行したいホストのIPアドレス
# 引数２に実行したいユーザ名（例: postmaster)
# 引数３に実行したいユーザのパスワード
# 引数４に実行したいCLIコマンド

use strict;
use Socket;
use FileHandle;

my ($con_host, $con_port);
my ($ip, $sockaddr);
my ($arg, $buf, $ret, $len);
my ($user, $password,$cli_cmd);
my ($errCode,$idCounter,@responses,$debug);
my ($snd_cmd,$rin,$rcv,$ret_code);
my ($chr01,$chr02);
my ($timeout);

#################  postmaster の設定 ###############
# $user = 'postmaster';
# $password = 'abcdefg';

#################  接続先の設定 ####################
# $con_host = '172.20.100.100';
$con_port = 106;
$timeout = 30;

my ($debug);

#$debug = "YES";
$debug = "NO";

($arg) = @ARGV;

$con_host=$ARGV[0];
$user=$ARGV[1];
$password=$ARGV[2];
$cli_cmd=$ARGV[3];


# ソケットの生成
$ip = inet_aton($con_host) || die "host($con_host) not found.\n";
$sockaddr = pack_sockaddr_in($con_port, $ip);
socket(SOCKET, PF_INET, SOCK_STREAM, 0) || die "socket error.\n";


# ソケットの接続
connect(SOCKET, $sockaddr) || die "connect $con_host $con_port error.\n";
autoflush SOCKET (1);

#タイムアウト処理
$rin = '';
vec($rin,fileno(SOCKET),1) = 1;
select($rin, undef, undef, $timeout) or die "Request timeout.\n";

# 接続時の受信
recv(SOCKET,$rcv,1000,0);
if ( $debug eq "YES" ){ printf "Recv:%s\n",$rcv; }
$ret_code=substr($rcv, 0, 3);
if ($ret_code eq "200") {

}else{
	close(SOCKET);
	die "PWD READY ERROR.\n";
}


# ユーザ名送信
$snd_cmd="USER $user\0";
if ( $debug eq "YES" ){ printf "Send:%s\n",$snd_cmd; }
send(SOCKET,$snd_cmd,0);

#タイムアウト処理
$rin = '';
vec($rin,fileno(SOCKET),1) = 1;
select($rin, undef, undef, $timeout) or die "Request timeout.\n";

#受信
recv(SOCKET,$rcv,1000,0);
if ( $debug eq "YES" ){ printf "Recv:%s\n",$rcv; }

$ret_code=substr($rcv, 0, 3);
if ($ret_code eq "300") {

}else{
	close(SOCKET);
	die "USER send ERROR.\n";
}


# パスワード送信
$snd_cmd="PASS $password\0";
if ( $debug eq "YES" ){ printf "Send:%s\n",$snd_cmd; }
send(SOCKET,$snd_cmd,0);

#タイムアウト処理
$rin = '';
vec($rin,fileno(SOCKET),1) = 1;
select($rin, undef, undef, $timeout) or die "Request timeout.\n";

#受信
recv(SOCKET,$rcv,1000,0);
if ( $debug eq "YES" ){ printf "Recv:%s\n",$rcv; }

$ret_code=substr($rcv, 0, 3);
if ($ret_code eq "200") {

}else{
	close(SOCKET);
	die "USER or PASS ERROR.\n";
}


# コマンド送信
$snd_cmd="$cli_cmd\0";
if ( $debug eq "YES" ){ printf "Send:%s\n",$snd_cmd; }
send(SOCKET,$snd_cmd,0);

#タイムアウト処理
$rin = '';
vec($rin,fileno(SOCKET),1) = 1;
select($rin, undef, undef, $timeout) or die "Request timeout.\n";

# 出足の5文字受信
recv(SOCKET,$rcv,5,0);
if ( $debug eq "YES" ){ printf "Recv:%s\n",$rcv; }

$ret_code=substr($rcv, 0, 5);
if ($ret_code eq "200 O") {

	# 200 OKで完結する場合

	#タイムアウト処理
	$rin = '';
	vec($rin,fileno(SOCKET),1) = 1;
	select($rin, undef, undef, $timeout) or die "Request timeout.\n";

	#受信
	recv(SOCKET,$rcv,1000,0);
	if ( $debug eq "YES" ){ printf "Recv:%s\n",$rcv; }

	$ret_code=substr($rcv, 0, 1);
	if ($ret_code eq "K") {
		printf "200 OK\n";
	}else{
		close(SOCKET);
		die "USER or PASS ERROR.\n";
	}

}elsif ($ret_code eq "200 d") {

	# data followがある場合

	for (;;) {
		#タイムアウト処理
		$rin = '';
		vec($rin,fileno(SOCKET),1) = 1;
		select($rin, undef, undef, $timeout) or die "Request timeout.\n";

		# この行の改行までスキップ
		recv(SOCKET,$rcv,1,0);
		if ( $rcv eq "\n" ){
			last;
		}
	}

	$chr01="";
	$chr02="";
	for(;;) {

		#タイムアウト処理
		$rin = '';
		vec($rin,fileno(SOCKET),1) = 1;
		select($rin, undef, undef, $timeout) or die "Request timeout.\n";


		recv(SOCKET,$rcv,1,0);
		printf "%s",$rcv;
		$chr01=$chr02;
		$chr02=substr($rcv, 0, 1);
		if ( $chr01 eq "\r" ){
			if ( $chr02 eq "\n" ){
				last;
			}
		}
	}
}else{
	close(SOCKET);
	die "COMMAND ERROR.\n";
}



# QUIT送信
$snd_cmd="QUIT\0";
if ( $debug eq "YES" ){ printf "Send:%s\n",$snd_cmd; }
send(SOCKET,$snd_cmd,0);

#タイムアウト処理
$rin = '';
vec($rin,fileno(SOCKET),1) = 1;
select($rin, undef, undef, $timeout) or die "Request timeout.\n";

#受信
recv(SOCKET,$rcv,1000,0);
if ( $debug eq "YES" ){ printf "Recv:%s\n",$rcv; }

$ret_code=substr($rcv, 0, 3);
if ($ret_code eq "200") {

}else{
	close(SOCKET);
	die "QUIT ERROR.\n";
}




close(SOCKET);
exit;





