#!/usr/bin/perl  --
######################################################################
# sslproxyadm
# SSLproxy process administration command.
#
# Copyright (C) 2008  NTT COMWARE Corporation.
#
# 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 of the
# License, 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, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA
######################################################################
use strict;
use warnings;

# logger test flag.
our $LOGGER_DEBUG = 0;

# sslproxyadm define value.
our $OK = 0;
our $NG = 1;
our $ON = 1;
our $OFF = 0;
our $SSLPROXY_PATH = "/usr/sbin/";
our $SSLPROXY = "sslproxy";
our $LOGGER_SECTION_KEY = "logger";
our $TARGET_SECTION_KEY = "target_.*";
our $LOGROTATE_CMD = "/usr/sbin/logrotate";
our $LOGROTATE_CONF_FILE = "/etc/logrotate.d/sslproxy";
our $LOGROTATE_STAT_FILE = "/var/lib/logrotate.status";

# sslproxyadm default parameter value.
our $CMD_OPT = "unknown";
our $CONFIG_FILE = "/etc/l7vs/sslproxy/sslproxyadm.cf";
our $LOG_FILE = "/var/log/l7vs/sslproxy/sslproxyadm.log";
our $LOG_LEVEL = "warn";

# Set library path.
$ENV{LD_LIBRARY_PATH} = "/usr/local/lib/";

# sslproxyadm global data table
our %sslproxyadm_data = ();
our %target_data = ();
our %process_data = ();

# main code.
	# Start main routine.
	&do_main;

	# Here is not executed. However, it exists for safety. 
	&do_exit($NG);
# main code end.

#!
# sslproxyadm command main routine.
#
# command argment check and command execution.
#
sub do_main
{
	#--------- DEBUG LOG ---------#
	my $argc = @ARGV;
	&print_log("file", "DEBUG", "common", "10050001", 
		   "in_function : do_main : ".
		   "argc = $argc, ".
		   "argv = @ARGV");
	#------- DEBUG LOG END -------#

	my $result = $NG;

	# Check command argment count.
	if (@ARGV == 2) {
		$CONFIG_FILE = $ARGV[1];
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "common", "10050002", 
			   "Command arg count is normal.");
		#------- DEBUG LOG END -------#
	} elsif (@ARGV == 1) {
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "common", "10050003", 
			   "Command arg count is normal. Use default config file.");
		#------- DEBUG LOG END -------#
	} else {
		&print_log("fcerr", "ERROR", "common", "40050001", 
			   "Command arg count is abnormal.");
		&usage;
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "common", "10050004", 
			   "out_function : do_main : Check argment NG");
		#------- DEBUG LOG END -------#
		&do_exit($NG);
	}
	$CMD_OPT = $ARGV[0];
	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "common", "10050005", 
		   "function : do_main : Check argment OK");
	#------- DEBUG LOG END -------#

	# Read sslproxyadm configration file.
	($result) = &read_adm_config;
	if ($result == $NG) {
		&print_log("fcerr", "ERROR", "common", "40050002", 
			   "Config file read error. file = $CONFIG_FILE");
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "common", "10050006", 
			   "out_function : do_main : read_adm_config NG");
		#------- DEBUG LOG END -------#
		&do_exit($NG);
	}
	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "common", "10050007", 
		   "function : do_main : read_adm_config OK");
	#------- DEBUG LOG END -------#

	# Set logger configuration.
	($result) = &set_log;
	if ($result == $NG) {
		&print_log("fcerr", "ERROR", "common", "40050003", 
			   "Logger setting error.");
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "common", "10050008", 
			   "out_function : do_main : set_log NG");
		#------- DEBUG LOG END -------#
		&do_exit($NG);
	}
	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "common", "10050009", 
		   "function : do_main : set_log OK");
	#------- DEBUG LOG END -------#

	# Check command option.
	if ($CMD_OPT ne "start" &&
	    $CMD_OPT ne "stop" &&
	    $CMD_OPT ne "restart" &&
	    $CMD_OPT ne "reload" &&
	    $CMD_OPT ne "check" &&
	    $CMD_OPT ne "status" &&
	    $CMD_OPT ne "config") { 
		&print_log("fcerr", "ERROR", "common", "40050004", 
			   "Invalid command. command = $CMD_OPT");
		&usage;
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "common", "10050010", 
			   "out_function : do_main : Check command NG");
		#------- DEBUG LOG END -------#
		&do_exit($NG);
	}
	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "common", "10050011", 
		   "function : do_main : Check command OK");
	#------- DEBUG LOG END -------#

	# Check target configration file.
	($result) = &check_target_config;
	if ($result == $NG) {
		&print_log("fcerr", "ERROR", "common", "40050005", 
			   "Check target config file error.");
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "common", "10050012", 
			   "out_function : do_main : check_target_config NG");
		#------- DEBUG LOG END -------#
		&do_exit($NG);
	}
	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "common", "10050013", 
		   "function : do_main : check_target_config OK");
	#------- DEBUG LOG END -------#

	# Check target configration file format command execution.
	if ($CMD_OPT eq "config") {
		($result) = &do_config;
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "common", "10050014", 
			   "function : do_main : Command execute END. command = $CMD_OPT");
		#------- DEBUG LOG END -------#
		if ($result == $NG) {
			&print_log("fcerr", "ERROR", "common", "40050006", 
				   "Command execute error. command = $CMD_OPT");
			#--------- DEBUG LOG ---------#
			&print_log("file", "DEBUG", "common", "10050015", 
				   "out_function : do_main : Command execute NG");
			#------- DEBUG LOG END -------#
			&do_exit($NG);
		}
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "common", "10050016", 
			   "out_function : do_main : Command execute OK. command = $CMD_OPT");
		#------- DEBUG LOG END -------#
		&do_exit($OK);
	}

	# Get sslproxy process status.
	($result) = &get_process_status;
	if ($result == $NG) {
		&print_log("fcerr", "ERROR", "common", "40050007", 
			   "Get process status error.");
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "common", "10050017", 
			   "out_function : do_main : get_process_status NG");
		#------- DEBUG LOG END -------#
		&do_exit($NG);
	}
	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "common", "10050018", 
		   "function : do_main : get_process_status OK");
	#------- DEBUG LOG END -------#

	# Command execution.
	if ($CMD_OPT eq "start") {
		($result) = &do_start;
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "common", "10050019", 
			   "function : do_main : Command execute END. command = $CMD_OPT");
		#------- DEBUG LOG END -------#
	} elsif ($CMD_OPT eq "stop") {
		($result) = &do_stop;
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "common", "10050020", 
			   "function : do_main : Command execute END. command = $CMD_OPT");
		#------- DEBUG LOG END -------#
	} elsif ($CMD_OPT eq "restart") {
		($result) = &do_restart;
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "common", "10050021", 
			   "function : do_main : Command execute END. command = $CMD_OPT");
		#------- DEBUG LOG END -------#
	} elsif ($CMD_OPT eq "reload") {
		($result) = &do_reload;
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "common", "10050022", 
			   "function : do_main : Command execute END. command = $CMD_OPT");
		#------- DEBUG LOG END -------#
	} elsif ($CMD_OPT eq "check") {
		($result) = &do_check;
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "common", "10050023", 
			   "function : do_main : Command execute END. command = $CMD_OPT");
		#------- DEBUG LOG END -------#
	} elsif ($CMD_OPT eq "status") {
		($result) = &do_status;
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "common", "10050024", 
			   "function : do_main : Command execute END. command = $CMD_OPT");
		#------- DEBUG LOG END -------#
	} else {
		# Here is not executed. However, it exists for safety. 
		&print_log("fcerr", "ERROR", "common", "40050008", 
			   "Invalid command. command = $CMD_OPT");
		&usage;
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "common", "10050025", 
			   "out_function : do_main : Check command NG");
		#------- DEBUG LOG END -------#
		&do_exit($NG);
	}
	if ($result == $NG) {
		&print_log("fcerr", "ERROR", "common", "40050009", 
			   "Command execute error. command = $CMD_OPT");
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "common", "10050026", 
			   "out_function : do_main : Command execute NG");
		#------- DEBUG LOG END -------#
		&do_exit($NG);
	}
	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "common", "10050027", 
		   "out_function : do_main : Command execute OK. command = $CMD_OPT");
	#------- DEBUG LOG END -------#
	&do_exit($OK)
}

#!
# Read sslproxyadm configration file.
#
# @retval	OK/NG	read result
#
sub read_adm_config
{
	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "config", "10030001", 
		   "in_function : read_adm_config");
	#------- DEBUG LOG END -------#
	my $result = $NG;

	%sslproxyadm_data = ();
	($result) = &read_config($CONFIG_FILE, "adm");
	if ($result == $NG) {
		&print_log("file", "ERROR", "config", "40030001", 
			   "Read sslproxyadm configration file error. file = $CONFIG_FILE");
	}

	# for debug.
	#&print_table_data(%sslproxyadm_data);

	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "config", "10030002", 
		   "out_function : read_adm_config : result = $result");
	#------- DEBUG LOG END -------#
	return ($result);
}

#!
# Check target configration files. exist or not.
#
# @retval	OK/NG	check result
#
sub check_target_config
{
	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "config", "10030003", 
		   "in_function : check_target_config");
	#------- DEBUG LOG END -------#
	my $result = $NG;

	# Search target configration file.
	foreach my $section (sort keys(%sslproxyadm_data)) {
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "config", "10030004", 
			   "Search section. ".
			   "section = $section");
		#------- DEBUG LOG END -------#
		my $target_conf_file = "";
		# Check target section.
		next if ($section !~ /^$TARGET_SECTION_KEY$/);
		# Get target configration file name.
		$target_conf_file = $sslproxyadm_data{$section}{"conf_file"};
		# Open target configration file for exist check.
		if(!open(CONFIG, "<$target_conf_file")) {
			&print_log("file", "ERROR", "config", "40030002", 
				   "Cannot open target config file. file = $target_conf_file");
			$result = $NG;
			last;
		}
		close(CONFIG);
		$result = $OK;
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "config", "10030005", 
			   "Target config file open OK. ".
			   "target_conf_file = $target_conf_file");
		#------- DEBUG LOG END -------#
	}

	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "config", "10030006", 
		   "out_function : check_target_config : ".
		   "result = $result");
	#------- DEBUG LOG END -------#
	return ($result);
}

#!
# Read specified configration file.
#
# @param[in]	conf_file	configration file
# @param[in]	conf_kind	configration file kind(adm or target)
# @retval	OK/NG		read result
#
sub read_config
{
	# Argment.
	my ($conf_file, $conf_kind) = (@_);
	my $result = $OK;
	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "config", "10030007", 
		   "in_function : read_config : ".
		   "conf_file = $conf_file ".
		   "conf_kind = $conf_kind");
	#------- DEBUG LOG END -------#

	# Check config file kind. "adm" or "target"
	if ($conf_kind ne "adm" && $conf_kind ne "target") {
		&print_log("file", "ERROR", "config", "40030003", 
			   "Invalid config file kind. kind = $conf_kind");
		$result = $NG;
	# Open config file.
	} elsif(!open(CONFIG, "<$conf_file")) {
		&print_log("file", "ERROR", "config", "40030004", 
			   "Cannot open config file. file = $conf_file");
		$result = $NG;
	} else {
		# Read data and Set to data table.
		my $line_data = "";
		my $section_flag = $OFF;
		my $now_section = "";
		my $now_line = 0;
		my $sec_key;
		# Set section keyword.
		if ($conf_kind eq "adm") {
			$sec_key = $TARGET_SECTION_KEY;
		} elsif ($conf_kind eq "target") {
			$sec_key = $SSLPROXY;
		}
		while ($line_data = <CONFIG>) {
			# Read one line data.
			$now_line++;
			# Skip Null line and comment line.
			next if ($line_data =~ /^\s*$|^\s*#/);
			# Cut space, tab, \n.
			$line_data =~ s/\s|\t|\n//g;
			#--------- DEBUG LOG ---------#
			&print_log("file", "DEBUG", "config", "10030008", 
				   "Read line data [$now_line] = $line_data");
			#------- DEBUG LOG END -------#

			# Check section line. (include [logger] [$sec_key])
			if ($line_data =~ 
			    /^\[$LOGGER_SECTION_KEY\]$|^\[$sec_key\]$/) {
				# Check start of first section.
				$section_flag = $ON;
				# Cut [ and ].
				$line_data =~ s/\[|\]//g;
				# Check duplication of section name. "adm" or "target"
				if ($conf_kind eq "adm") {
					while (my ($section_name, $section_data) = each (%sslproxyadm_data)) {
						#--------- DEBUG LOG ---------#
						&print_log("file", "DEBUG", "config", "10030009", 
							   "Check section name. ".
							   "read line = $line_data, ".
							   "saved data = $section_name");
						#------- DEBUG LOG END -------#
						if ($line_data eq $section_name) {
							&print_log("file", "ERROR", "config", "40030005", 
								   "Section name is duplicated. ".
								   "section = $section_name Line:$now_line");
							$result = $NG;
							last;
						}
					}
				} elsif ($conf_kind eq "target") {
					while (my ($section_name, $section_data) = each (%target_data)) {
						#--------- DEBUG LOG ---------#
						&print_log("file", "DEBUG", "config", "10030010", 
							   "Check section name. ".
							   "read line = $line_data, ".
							   "saved data = $section_name");
						#------- DEBUG LOG END -------#
						if ($line_data eq $section_name) {
							&print_log("file", "ERROR", "config", "40030006", 
								   "Section name is duplicated. ".
								   "section = $section_name Line:$now_line");
							$result = $NG;
							last;
						}
					}
				}
				if ($result == $NG) {
					#--------- DEBUG LOG ---------#
					&print_log("file", "DEBUG", "config", "10030011", 
						   "Check section name NG.");
					#------- DEBUG LOG END -------#
					last;
				}
				$now_section = $line_data;
				#--------- DEBUG LOG ---------#
				&print_log("file", "DEBUG", "config", "10030012", 
					   "New section found. section = $now_section");
				#------- DEBUG LOG END -------#
				next;
			}

			# Check parameter line. (include "=")
			if ($line_data =~ /=/) {
				# Out of section.
				if ($section_flag == $OFF) {
					&print_log("file", "ERROR", "config", "40030007", 
						   "Ivalid parameter line.  ".
						   "Out of section. Line:$now_line");
					$result = $NG;
					last;
				}
				# Split by "=" delimiter to key and value.
				my @param = split /=/, $line_data, 2;
				# Check key is "".
				if ($param[0] eq "") {
					&print_log("file", "ERROR", "config", "40030008", 
						   "Ivalid parameter line.  ".
						   "Parameter key is NULL. Line:$now_line");
					$result = $NG;
					last;
				}
				# Cut char value's ".
				$param[1] =~ s/"//g;
				# Parameter data set to data table. "adm" or "target"
				if ($conf_kind eq "adm") {
					$sslproxyadm_data{$now_section}{$param[0]} = $param[1];
				} elsif ($conf_kind eq "target") {
					$target_data{$now_section}{$param[0]} = $param[1];
				}
				#--------- DEBUG LOG ---------#
				&print_log("file", "DEBUG", "config", "10030013", 
					   "Parameter set. ".
					   "section = $now_section, ".
					   "key = $param[0], ".
					   "value = $param[1]");
				#------- DEBUG LOG END -------#
				next;
			}

			# Ivalid line. 
			&print_log("file", "ERROR", "config", "40030009", 
				   "Ivalid parameter line.  ".
				   "Unknown line. Line:$now_line");
			$result = $NG;
			last;
		}
		close(CONFIG);
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "config", "10030014", 
			   "Config file read and Set data END.");
		#------- DEBUG LOG END -------#

		# Check read and data set result.
		# $result is OK? section is exist?
		if ($result == $OK) {
			# Check section count. "adm" or "target"
			my $logger_section_count = 0;
			my $section_count = 0;
			if ($conf_kind eq "adm") {
				foreach my $adm_section (sort keys(%sslproxyadm_data)) {
					if ($adm_section =~ /^$LOGGER_SECTION_KEY$/) {
						$logger_section_count++;
					}
					if ($adm_section =~ /^$sec_key$/) {
						$section_count++;
					}
				}
			} elsif ($conf_kind eq "target") {
				foreach my $target_section (sort keys(%target_data)) {
					if ($target_section =~ /^$LOGGER_SECTION_KEY$/) {
						$logger_section_count++;
					}
					if ($target_section =~ /^$sec_key$/) {
						$section_count++;
					}
				}
			}
			if ($logger_section_count == 0) {
				&print_log("file", "ERROR", "config", "40030010", 
					   "[logger] section nothing in config file. ".
					   "file = $conf_file");
				$result = $NG;
			} elsif ($section_count == 0) {
				&print_log("file", "ERROR", "config", "40030011", 
					   "[$sec_key] section nothing in config file. ".
					   "file = $conf_file");
				$result = $NG;
			} else {
				#--------- DEBUG LOG ---------#
				&print_log("file", "DEBUG", "config", "10030015", 
					   "Read and data set result OK.");
				#------- DEBUG LOG END -------#
			}
		}
	}

	# for debug.
	#&print_table_data(%sslproxyadm_data);
	#&print_table_data(%target_data);

	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "config", "10030016", 
		   "out_function : read_config : result = $result");
	#------- DEBUG LOG END -------#
	return ($result);
}

#!
# Get sslproxy process status.
#
# Collect sslproxy process info and Check status.
# and Judge sslproxy process status.
#
# @retval	OK/NG	get result
#
sub get_process_status
{
	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "status", "10020001", 
		   "in_function : get_process_status");
	#------- DEBUG LOG END -------#

	my $result = $OK;

	# Collect SSLproxy process information.
	($result) = &collect_process_info;
	if ($result == $NG) {
		&print_log("file", "ERROR", "status", "40020001", 
			   "Collect sslproxy process info error.");
	} else {
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "status", "10020002", 
			   "Check sslproxy process start.");
		#------- DEBUG LOG END -------#
		foreach my $conf_target (sort keys(%sslproxyadm_data)) {
			# Get target id from sslproxyadm_data
			# Check target section. (other is skip)
			next if ($conf_target !~ /^$TARGET_SECTION_KEY$/);

			# Check list for sslproxy process status.
			# is_start		Starting or Stopped
			# cmp_config		match or not
			# start_info		file exist or not
			# cmp_start_info	match or not
			my $is_start = $NG;
			my $cmp_config = $NG;
			my $start_info = $NG;
			my $cmp_start_info = $NG;
			# proc_status		judge result
			my $proc_status = $NG;

			# Check is_start. Exist target id in process_data or not.
			#--------- DEBUG LOG ---------#
			&print_log("file", "DEBUG", "status", "10020003", 
				   "Check is_start. target = $conf_target");
			#------- DEBUG LOG END -------#
			foreach my $proc_target (sort keys(%process_data)) {
				#--------- DEBUG LOG ---------#
				&print_log("file", "DEBUG", "status", "10020004", 
					   "Check process = $proc_target");
				#------- DEBUG LOG END -------#
				if ($proc_target eq $conf_target) {
					#--------- DEBUG LOG ---------#
					&print_log("file", "DEBUG", "status", "10020005", 
						   "$proc_target is Starting.");
					#------- DEBUG LOG END -------#
					$is_start = $OK;
					# save pid.
					$sslproxyadm_data{$proc_target}{"pid"} = 
						$process_data{$proc_target}{"pid"};
					# Set known sslproxy process flag.
					# (Not set process is unknown sslproxy process)
					$process_data{$proc_target}{"known"} = $ON;
					last;
				}
			}
			$sslproxyadm_data{$conf_target}{"is_start"} = $is_start;

			# Check cmp_config. Compare target conf file name.
			# (Starting process only)
			if ($is_start == $OK) {
				#--------- DEBUG LOG ---------#
				&print_log("file", "DEBUG", "status", "10020006", 
					   "Check cmp_config. target = $conf_target");
				#------- DEBUG LOG END -------#
				if ($sslproxyadm_data{$conf_target}{"conf_file"} eq 
				    $process_data{$conf_target}{"conf_file"}) {
					#--------- DEBUG LOG ---------#
					&print_log("file", "DEBUG", "status", "10020007", 
						   "Config file matched.");
					#------- DEBUG LOG END -------#
					$cmp_config = $OK;
				}
				$sslproxyadm_data{$conf_target}{"cmp_config"} = $cmp_config;
			}

			# Check start_info. Try open start_info file for exist check.
			# start_info file name = target_conf_file + "." + target_id
			my $start_info_file = $sslproxyadm_data{$conf_target}{"conf_file"}.
					      ".".
					      $conf_target;
			#--------- DEBUG LOG ---------#
			&print_log("file", "DEBUG", "status", "10020008", 
				   "Check start_info. file = $start_info_file");
			#------- DEBUG LOG END -------#
			if (open(STARTFILE, "<$start_info_file")) {
				#--------- DEBUG LOG ---------#
				&print_log("file", "DEBUG", "status", "10020009", 
					   "Start info file existed.");
				#------- DEBUG LOG END -------#
				$start_info = $OK;
				close(STARTFILE);
			}
			$sslproxyadm_data{$conf_target}{"start_info"} = $start_info;

			# Check cmp_start_info. Compare start_info file and conf file.
			# (start_info OK only)
			if ($start_info == $OK) {
				#--------- DEBUG LOG ---------#
				&print_log("file", "DEBUG", "status", "10020010", 
					   "Check cmp_start_info. target = $conf_target");
				#------- DEBUG LOG END -------#
				# Open diff command output.
				my $diff_cmd = "/usr/bin/diff $start_info_file ".
					       $sslproxyadm_data{$conf_target}{"conf_file"}.
					       " |";
				if (open(DIFFDATA, $diff_cmd)) {
					#--------- DEBUG LOG ---------#
					&print_log("file", "DEBUG", "status", "10020011", 
						   "Get diff command output.");
					#------- DEBUG LOG END -------#
					my @diff_data = <DIFFDATA>;
					my $diff_cnt = @diff_data;
					# Check diff output size. 0 is matched.
					if ($diff_cnt == 0) {
						#--------- DEBUG LOG ---------#
						&print_log("file", "DEBUG", "status", "10020012", 
							   "Start info file matched.");
						#------- DEBUG LOG END -------#
						$cmp_start_info = $OK;
					}
					close(DIFFDATA);
				}
				$sslproxyadm_data{$conf_target}{"cmp_start_info"} = $cmp_start_info;
			}

			# Judge sslproxy process status. Check normal start/stop state.
			#--------- DEBUG LOG ---------#
			&print_log("file", "DEBUG", "status", "10020013", 
				   "Judge sslproxy process status by check result. ".
				   "target = $conf_target");
			#------- DEBUG LOG END -------#
			if (($is_start == $OK && 
			    $cmp_config == $OK && 
			    $start_info == $OK && 
			    $cmp_start_info == $OK) ||
			    ($is_start == $NG && 
			    $start_info == $NG)) {
				#--------- DEBUG LOG ---------#
				&print_log("file", "DEBUG", "status", "10020014", 
					   "Result sslproxy process status is OK. ".
					   "Normal Starting or Stopped.");
				#------- DEBUG LOG END -------#
				$proc_status = $OK;
			}
			$sslproxyadm_data{$conf_target}{"proc_status"} = $proc_status;

			# now_start flag initialize.
			$sslproxyadm_data{$conf_target}{"now_start"} = $OFF;
		}
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "status", "10020015", 
			   "Check and Judge sslproxy process status END.");
		#------- DEBUG LOG END -------#

		# for debug.
		#&print_table_data(%process_data);
		#&print_table_data(%sslproxyadm_data);
	}

	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "status", "10020016", 
		   "out_function : get_process_status : result = $result");
	#------- DEBUG LOG END -------#
	return ($result);
}

#!
# Collect sslproxy process information.
#
# @retval	OK/NG	collect result
#
sub collect_process_info
{
	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "status", "10020017", 
		   "in_function : collect_process_info");
	#------- DEBUG LOG END -------#

	my $result = $OK;

	# Collect sslproxy process information from ps command output.
	# Set to process_data.
	%process_data = ();
	my $ps_cmd = "/bin/ps -C $SSLPROXY -o pid=,cmd= |";
	if(!open(PROCESS, $ps_cmd)) {
		&print_log("file", "ERROR", "status", "40020002", 
			   "Cannot open ps command output.");
		$result = $NG;
	} else {
		# Read ps command data and Set to data table.
		my $line_data = "";
		while ($line_data = <PROCESS>) {
			# Read one line data. (one process)
			# Cut \n.
			$line_data =~ s/^\s*|\n$//g;
			#--------- DEBUG LOG ---------#
			&print_log("file", "DEBUG", "status", "10020018", 
				   "Read one process line data = $line_data");
			#------- DEBUG LOG END -------#

			# Split @param by " " delimiter.
			# $param[0] -> pid
			# $param[1] -> cmd (ex. "./sslproxy")
			# $param[2] -> target id
			# $param[3] -> target config file
			my @param = split /\s/, $line_data, 4;
			# Parameter data set to data table.
			$process_data{$param[2]}{"pid"} = $param[0];
			$process_data{$param[2]}{"conf_file"} = $param[3];
			$process_data{$param[2]}{"known"} = $OFF;
			#--------- DEBUG LOG ---------#
			&print_log("file", "DEBUG", "status", "10020019", 
				   "Parameter set. ".
				   "target_id = $param[2], ".
				   "pid = $param[0], ".
				   "conf_file = $param[3]");
			#------- DEBUG LOG END -------#
		}
		close(PROCESS);
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "status", "10020020", 
			   "Process info read and Set data END.");
		#------- DEBUG LOG END -------#

		# Check process count.
		my $proc_count = keys(%process_data);
		if ($proc_count == 0) {
			&print_log("file", "INFO", "status", "20020001", 
				   "Executing SSLproxy process is nothing.");
		}

		# for debug.
		#&print_table_data(%process_data);
	}

	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "status", "10020021", 
		   "out_function : collect_process_info : result = $result");
	#------- DEBUG LOG END -------#
	return ($result);
}

#!
# Update sslproxy process status.
# Set Starting <-> Stopped status.
#
# @param[in]	target_id	target id
# @param[in]	flag		update kind flag
# @retval	OK/NG	update result
#
sub update_process_status
{
	# Argment.
	# flag ig ON(Starting) or OFF(Stopped).
	my ($target_id, $flag) = (@_);
	my $result = $NG;
	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "status", "10020022", 
		   "in_function : update_process_status : ".
		   "target_id = $target_id, ".
		   "flag = $flag");
	#------- DEBUG LOG END -------#

	# Create or Delete start information file.
	($result) = &manage_start_info($target_id, $flag);
	if ($result == $OK) {
		# Set start status. (is_start)
		if ($flag == $ON) {
			$sslproxyadm_data{$target_id}{"is_start"} = $OK;
			#--------- DEBUG LOG ---------#
			&print_log("file", "DEBUG", "status", "10020023", 
				   "Set is_start \"OK\". ".
				   "target_id = $target_id");
			#------- DEBUG LOG END -------#
		} else {
			$sslproxyadm_data{$target_id}{"is_start"} = $NG;
			#--------- DEBUG LOG ---------#
			&print_log("file", "DEBUG", "status", "10020024", 
				   "Set is_start \"NG\". ".
				   "target_id = $target_id");
			#------- DEBUG LOG END -------#
		}
		# Set started flag. (now_start)
		$sslproxyadm_data{$target_id}{"now_start"} = $flag;
	}

	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "status", "10020025", 
		   "out_function : update_process_status : result = $result");
	#------- DEBUG LOG END -------#
	return ($result);
}

#!
# Manage start information.
# Create and Delete start information file.
#
# @param[in]	target_id	target id
# @param[in]	flag		manage kind flag
# @retval	OK/NG	manage result
#
sub manage_start_info
{
	# Argment.
	# flag ig ON(Starting) or OFF(Stopped).
	my ($target_id, $flag) = (@_);
	my $result = $NG;
	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "status", "10020026", 
		   "in_function : manage_start_info : ".
		   "target_id = $target_id, ".
		   "flag = $flag");
	#------- DEBUG LOG END -------#

	# start_info file name = target_conf_file + "." + target_id
	my $config_file = $sslproxyadm_data{$target_id}{"conf_file"};
	my $start_info_file = $config_file.".".$target_id;

	if ($flag == $ON) {
		# Copy conf file to start information file.
		my $cp_cmd = "/bin/cp -a $config_file $start_info_file";
		($result) = system($cp_cmd);
		if ($result != $OK) {
			&print_log("file", "ERROR", "status", "40020003", 
				   "Copy command execute error. : $!");
			$result = $NG;
		}
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "status", "10020027", 
			   "Copy start information file END. ".
			   "config_file = $config_file, ".
			   "start_info_file = $start_info_file");
		#------- DEBUG LOG END -------#
	} elsif ($flag == $OFF) {
		# Delete start information file.
		my $rm_cmd = "/bin/rm -f $start_info_file";
		($result) = system($rm_cmd);
		if ($result != $OK) {
			&print_log("file", "ERROR", "status", "40020004", 
				   "Remove command execute error. : $!");
			$result = $NG;
		}
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "status", "10020028", 
			   "Delete start information file END. ".
			   "config_file = $config_file, ".
			   "start_info_file = $start_info_file");
		#------- DEBUG LOG END -------#
	}

	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "status", "10020029", 
		   "out_function : manage_start_info : result = $result");
	#------- DEBUG LOG END -------#
	return ($result);
}

#!
# Start sslproxy process.
#
# @retval	OK/NG	start result
#
sub do_start
{
	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "control", "10010001", 
		   "in_function : do_start");
	#------- DEBUG LOG END -------#

	my $result = $NG;
	my $start_cnt = 0;

	# Search start target in sslproxyadm_data.
	foreach my $target (sort keys(%sslproxyadm_data)) {
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "control", "10010002", 
			   "Search start target. ".
			   "target = $target");
		#------- DEBUG LOG END -------#
		# Check target section. (other is skip)
		next if ($target !~ /^$TARGET_SECTION_KEY$/);

		# Start executing, when target status Stopped.
		if ($sslproxyadm_data{$target}{"is_start"} == $NG) {
			$start_cnt++;
			# Start one target process.
			($result) = &start_process($target);
			if ($result == $NG) {
				&print_log("file", "ERROR", "control", "40010001", 
					   "Start process error. ".
					   "target = $target");
				last;
			}
			#--------- DEBUG LOG ---------#
			&print_log("file", "DEBUG", "control", "10010003", 
				   "Start target END. ".
				   "target = $target");
			#------- DEBUG LOG END -------#
		} else {
			&print_log("file", "WARN", "control", "30010001", 
				   "Process already starting. ".
				   "target = $target");
		}
	}

	# Check start target count.
	if ($start_cnt == 0) {
		&print_log("file", "WARN", "control", "30010002", 
			   "Target process not found for start.");
	# When process start failed, already Starting process will be Stopped.
	} elsif ($result == $NG) {
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "control", "10010004", 
			   "Start recover target.");
		#------- DEBUG LOG END -------#

		# Search recover target in sslproxyadm_data.
		foreach my $recover_target (sort keys(%sslproxyadm_data)) {
			#--------- DEBUG LOG ---------#
			&print_log("file", "DEBUG", "control", "10010005", 
				   "Search recover target. ".
				   "recover_target = $recover_target");
			#------- DEBUG LOG END -------#
			# Check target section. (other is skip)
			next if ($recover_target !~ /^$TARGET_SECTION_KEY$/);

			# "now_start" flag is "ON" is Stopped. 
			if ($sslproxyadm_data{$recover_target}{"now_start"} == $ON) {
				my $recover_result = $NG;
				# Recover(stop) one target process.
				($recover_result) = &stop_process($recover_target);
				if ($recover_result == $NG) {
					&print_log("file", "ERROR", "control", "40010002", 
						   "Recover process error. ".
						   "recover_target = $recover_target");
				}
				#--------- DEBUG LOG ---------#
				&print_log("file", "DEBUG", "control", "10010006", 
					   "Recover target END. ".
					   "recover_target = $recover_target");
				#------- DEBUG LOG END -------#
			}
		}
	}

	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "control", "10010007", 
		   "out_function : do_start : result = $result");
	#------- DEBUG LOG END -------#
	return ($result);
}

#!
# Stop sslproxy process.
#
# @retval	OK/NG	start result
#
sub do_stop
{
	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "control", "10010008", 
		   "in_function : do_stop");
	#------- DEBUG LOG END -------#

	my $result = $NG;
	my $stop_cnt = 0;

	# Search stop target in sslproxyadm_data.
	foreach my $target (sort keys(%sslproxyadm_data)) {
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "control", "10010009", 
			   "Search stop target. ".
			   "target = $target");
		#------- DEBUG LOG END -------#
		# Check target section. (other is skip)
		next if ($target !~ /^$TARGET_SECTION_KEY$/);

		# Stop executing, when target status Starting.
		if ($sslproxyadm_data{$target}{"is_start"} == $OK) {
			$stop_cnt++;
			# Stop one target process.
			($result) = &stop_process($target);
			if ($result == $NG) {
				&print_log("file", "ERROR", "control", "40010003", 
					   "Stop process error. ".
					   "target = $target");
				last;
			}
			#--------- DEBUG LOG ---------#
			&print_log("file", "DEBUG", "control", "10010010", 
				   "Stop target END. ".
				   "target = $target");
			#------- DEBUG LOG END -------#
		} else {
			&print_log("file", "WARN", "control", "30010003", 
				   "Process already stopped. ".
				   "target = $target");
		}
	}

	# Check stop target count.
	if ($stop_cnt == 0) {
		&print_log("file", "WARN", "control", "30010004", 
			   "Target process not found for stop.");
	}

	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "control", "10010011", 
		   "out_function : do_stop : result = $result");
	#------- DEBUG LOG END -------#
	return ($result);
}

#!
# Restart sslproxy process.
#
# @retval	OK/NG	start result
#
sub do_restart
{
	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "control", "10010012", 
		   "in_function : do_restart");
	#------- DEBUG LOG END -------#

	my $result = $NG;
	my $stop_cnt = 0;
	my $start_cnt = 0;

	# Search restart target in sslproxyadm_data.
	foreach my $target (sort keys(%sslproxyadm_data)) {
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "control", "10010013", 
			   "Search restart target. ".
			   "target = $target");
		#------- DEBUG LOG END -------#
		# Check target section. (other is skip)
		next if ($target !~ /^$TARGET_SECTION_KEY$/);

		# Stop executing for restart, when target status Starting.
		if ($sslproxyadm_data{$target}{"is_start"} == $OK) {
			$stop_cnt++;
			# Stop one target process.
			($result) = &stop_process($target);
			if ($result == $NG) {
				&print_log("file", "ERROR", "control", "40010004", 
					   "Stop process for restart error. ".
					   "target = $target");
				last;
			}
			#--------- DEBUG LOG ---------#
			&print_log("file", "DEBUG", "control", "10010014", 
				   "Stop target for restart END. ".
				   "target = $target");
			#------- DEBUG LOG END -------#
		} else {
			&print_log("file", "WARN", "control", "30010005", 
				   "Process already stopped for restart. ".
				   "target = $target");
		}

		# Start executing for restart, when target status Stopped.
		if ($sslproxyadm_data{$target}{"is_start"} == $NG) {
			$start_cnt++;
			# Start one target process.
			($result) = &start_process($target);
			if ($result == $NG) {
				&print_log("file", "ERROR", "control", "40010005", 
					   "Start process for restart error. ".
					   "target = $target");
				last;
			}
			#--------- DEBUG LOG ---------#
			&print_log("file", "DEBUG", "control", "10010015", 
				   "Start target for restart END. ".
				   "target = $target");
			#------- DEBUG LOG END -------#
		} else {
			&print_log("file", "WARN", "control", "30010006", 
				   "Process already starting for restart. ".
				   "target = $target");
		}
	}

	# Check stop target for restart count.
	if ($stop_cnt == 0) {
		&print_log("file", "WARN", "control", "30010007", 
			   "Target process not found for stop (restart).");
	}

	# Check start target for restart count.
	if ($start_cnt == 0) {
		&print_log("file", "WARN", "control", "30010008", 
			   "Target process not found for start (restart).");
	# When process start for restart failed, already Starting process will be Stopped.
	} elsif ($result == $NG) {
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "control", "10010016", 
			   "Start recover target for restart.");
		#------- DEBUG LOG END -------#

		# Search recover target in sslproxyadm_data.
		foreach my $recover_target (sort keys(%sslproxyadm_data)) {
			#--------- DEBUG LOG ---------#
			&print_log("file", "DEBUG", "control", "10010017", 
				   "Search recover target for restart. ".
				   "recover_target = $recover_target");
			#------- DEBUG LOG END -------#
			# Check target section. (other is skip)
			next if ($recover_target !~ /^$TARGET_SECTION_KEY$/);

			# "now_start" flag is "ON" is Stopped. 
			if ($sslproxyadm_data{$recover_target}{"now_start"} == $ON) {
				my $recover_result = $NG;
				# Recover(stop) one target process.
				($recover_result) = &stop_process($recover_target);
				if ($recover_result == $NG) {
					&print_log("file", "ERROR", "control", "40010006", 
						   "Recover process  for restart error. ".
						   "recover_target = $recover_target");
				}
				#--------- DEBUG LOG ---------#
				&print_log("file", "DEBUG", "control", "10010018", 
					   "Recover target  for restart END. ".
					   "recover_target = $recover_target");
				#------- DEBUG LOG END -------#
			}
		}
	}

	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "control", "10010019", 
		   "out_function : do_restart : result = $result");
	#------- DEBUG LOG END -------#
	return ($result);
}

#!
# Reload sslproxy process.
#
# @retval	OK/NG	start result
#
sub do_reload
{
	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "control", "10010020", 
		   "in_function : do_reload");
	#------- DEBUG LOG END -------#

	my $result = $NG;
	my $stop_cnt = 0;
	my $start_cnt = 0;

	# Search reload target in sslproxyadm_data.
	foreach my $target (sort keys(%sslproxyadm_data)) {
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "control", "10010021", 
			   "Search reload target. ".
			   "target = $target");
		#------- DEBUG LOG END -------#
		# Check target section. (other is skip)
		next if ($target !~ /^$TARGET_SECTION_KEY$/);

		# Stop executing for reload, when target status Starting
		# and process status Abnormal(NG).
		if ($sslproxyadm_data{$target}{"is_start"} == $OK) {
			if ($sslproxyadm_data{$target}{"proc_status"} != $OK) {
				$stop_cnt++;
				# Stop one target process.
				($result) = &stop_process($target);
				if ($result == $NG) {
					&print_log("file", "ERROR", "control", "40010007", 
						   "Stop process for reload error. ".
						   "target = $target");
					last;
				}
				#--------- DEBUG LOG ---------#
				&print_log("file", "DEBUG", "control", "10010022", 
					   "Stop target for reload END. ".
					   "target = $target");
				#------- DEBUG LOG END -------#
			} else {
				#--------- DEBUG LOG ---------#
				&print_log("file", "DEBUG", "control", "10010023", 
					   "Process normal starting for reload. ".
					   "target = $target");
				#------- DEBUG LOG END -------#
			}
		} else {
			&print_log("file", "WARN", "control", "30010009", 
				   "Process already stopped for reload. ".
				   "target = $target");
		}

		# Start executing for reload, when target status Stopped.
		if ($sslproxyadm_data{$target}{"is_start"} == $NG) {
			$start_cnt++;
			# Start one target process.
			($result) = &start_process($target);
			if ($result == $NG) {
				&print_log("file", "ERROR", "control", "40010008", 
					   "Start process for reload error. ".
					   "target = $target");
				last;
			}
			#--------- DEBUG LOG ---------#
			&print_log("file", "DEBUG", "control", "10010024", 
				   "Start target for reload END. ".
				   "target = $target");
			#------- DEBUG LOG END -------#
		} else {
			&print_log("file", "WARN", "control", "30010010", 
				   "Process already starting for reload. ".
				   "target = $target");
		}
	}

	# Check stop target for reload count.
	if ($stop_cnt == 0) {
		&print_log("file", "WARN", "control", "30010011", 
			   "Target process not found for stop (reload).");
	}

	# Check start target for reload count.
	if ($start_cnt == 0) {
		&print_log("file", "WARN", "control", "30010012", 
			   "Target process not found for start (reload).");
	# When process start for reload failed, already Starting process will be Stopped.
	} elsif ($result == $NG) {
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "control", "10010025", 
			   "Start recover target for reload.");
		#------- DEBUG LOG END -------#

		# Search recover target in sslproxyadm_data.
		foreach my $recover_target (sort keys(%sslproxyadm_data)) {
			#--------- DEBUG LOG ---------#
			&print_log("file", "DEBUG", "control", "10010026", 
				   "Search recover target for reload. ".
				   "recover_target = $recover_target");
			#------- DEBUG LOG END -------#
			# Check target section. (other is skip)
			next if ($recover_target !~ /^$TARGET_SECTION_KEY$/);

			# "now_start" flag is "ON" is Stopped. 
			if ($sslproxyadm_data{$recover_target}{"now_start"} == $ON) {
				my $recover_result = $NG;
				# Recover(stop) one target process.
				($recover_result) = &stop_process($recover_target);
				if ($recover_result == $NG) {
					&print_log("file", "ERROR", "control", "40010009", 
						   "Recover process  for reload error. ".
						   "recover_target = $recover_target");
				}
				#--------- DEBUG LOG ---------#
				&print_log("file", "DEBUG", "control", "10010027", 
					   "Recover target  for reload END. ".
					   "recover_target = $recover_target");
				#------- DEBUG LOG END -------#
			}
		}
	}

	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "control", "10010028", 
		   "out_function : do_reload : result = $result");
	#------- DEBUG LOG END -------#
	return ($result);
}

#!
# Check all target is normal Starting.
#
# @retval	OK/NG	check result
#
sub do_check
{
	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "status", "10020030", 
		   "in_function : do_check");
	#------- DEBUG LOG END -------#

	my $result = $OK;

	# Check all target in sslproxyadm_data.
	foreach my $target (sort keys(%sslproxyadm_data)) {
		# Get target id from sslproxyadm_data
		# Check target section. (other is skip)
		next if ($target !~ /^$TARGET_SECTION_KEY$/);
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "status", "10020031", 
			   "Check target = $target");
		#------- DEBUG LOG END -------#

		# Check proc_status is OK and prosess is Starting.
		if ($sslproxyadm_data{$target}{"proc_status"} != $OK ||
		    $sslproxyadm_data{$target}{"is_start"} != $OK) {
			&print_log("file", "WARN", "status", "30020001", 
				   "Check NG. Found NG target. target = $target");
			$result = $NG;
			last;
		}
	}

	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "status", "10020032", 
		   "out_function : do_check : result = $result");
	#------- DEBUG LOG END -------#
	return ($result);
}

#!
# Print all status.
# Logger, Target, Process.
#
# @retval	OK/NG	print result (always OK)
#
sub do_status
{
	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "status", "10020033", 
		   "in_function : do_status");
	#------- DEBUG LOG END -------#

	my $result = $OK;

	print STDOUT "----- Print SSLproxyadm status start -----\n";

	# Print common information.
	print STDOUT "[ Common Data ]\n";
	print STDOUT "Common config file	: $CONFIG_FILE\n";
	print STDOUT "Output log file		: $LOG_FILE\n";
	print STDOUT "Output log level	: $LOG_LEVEL\n";
	print STDOUT "Log rotate config file	: $LOGROTATE_CONF_FILE\n";
	print STDOUT "Log rotate status file	: $LOGROTATE_STAT_FILE\n";
	print STDOUT "\n";

	# Print all target information in sslproxyadm_data.
	print STDOUT "[ Target Data ]\n";
	my $target_data_count = keys(%sslproxyadm_data);
	if ($target_data_count == 0) {
		print STDOUT "	Target nothing.\n";
	} else {
		foreach my $target (sort keys(%sslproxyadm_data)) {
			# Get target id from sslproxyadm_data
			# Check target section. (other is skip)
			next if ($target !~ /^$TARGET_SECTION_KEY$/);

			print STDOUT "TargetID : $target\n";
			print STDOUT "	Config file	: " . 
				     $sslproxyadm_data{$target}{"conf_file"} . 
				     "\n";

			if ($sslproxyadm_data{$target}{"proc_status"} == $OK) {
				print STDOUT "	Process status 	: Normal.\n";
			} else {
				print STDOUT "	Process status 	: Abnormal.\n";
			}

			if ($sslproxyadm_data{$target}{"is_start"} == $OK) {
				print STDOUT "	Execute status 	: Starting. " . 
					     "PID = " . 
					     $sslproxyadm_data{$target}{"pid"} . 
					     "\n";
			} else {
				print STDOUT "	Execute status 	: Stopped.\n";
			}

			if ($sslproxyadm_data{$target}{"proc_status"} == $NG) {
				print STDOUT "	Status detail 	: \n";
				if ($sslproxyadm_data{$target}{"is_start"} == $OK) {
					if ($sslproxyadm_data{$target}{"cmp_config"} == $NG) {
						print STDOUT "			".
						": Different configuration file is used now.\n";
					}
					if ($sslproxyadm_data{$target}{"start_info"} == $NG) {
						print STDOUT "			".
						": Start information file nothing. (Manual start?)\n";
					} else {
						print STDOUT "			".
						": Start information file exist. (Change config?)\n";
						if ($sslproxyadm_data{$target}{"cmp_start_info"} == $NG) {
							print STDOUT "			".
							": Start information file is Different. \n";
						}
					}
				} else {
					if ($sslproxyadm_data{$target}{"start_info"} == $OK) {
						print STDOUT "			".
						": Start information file exist. (Change config or Manual stop?)\n";
						if ($sslproxyadm_data{$target}{"cmp_start_info"} == $NG) {
							print STDOUT "			".
							": Start information file is Different. \n";
						}
					}
				}
			}
		}
	}
	print STDOUT "\n";

	# Print unknown process information in process_data.
	print STDOUT "[ Unknown SSLproxy process ]\n";
	my $process_data_count = keys(%process_data);
	if ($process_data_count == 0) {
		print STDOUT "	Process nothing.\n";
	} else {
		foreach my $proc_target (sort keys(%process_data)) {
			if ($process_data{$proc_target}{"known"} != $ON) {
				print STDOUT "TargetID : $proc_target\n";
				print STDOUT "	Config file	: " . 
					     $process_data{$proc_target}{"conf_file"} . 
					     "\n";
				print STDOUT "	PID		: " . 
					     $process_data{$proc_target}{"pid"} . 
					     "\n";
			}
		}
	}

	print STDOUT "----- Print SSLproxyadm status end   -----\n";

	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "status", "10020034", 
		   "out_function : do_status : result = $result");
	#------- DEBUG LOG END -------#
	return ($result);
}

#!
# Check target configuration file format.
#
# @retval	OK/NG	check result
#
sub do_config
{
	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "config", "10030017", 
		   "in_function : do_config");
	#------- DEBUG LOG END -------#

	my $result = $NG;

	# Search target configration file.
	foreach my $section (sort keys(%sslproxyadm_data)) {
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "config", "10030018", 
			   "Search section. ".
			   "section = $section");
		#------- DEBUG LOG END -------#
		my $target_conf_file = "";
		# Check target section.
		next if ($section !~ /^$TARGET_SECTION_KEY$/);
		# Get target configration file name.
		$target_conf_file = $sslproxyadm_data{$section}{"conf_file"};
		# Read target configration file for format check.
		%target_data = ();
		($result) = &read_config($target_conf_file, "target");
		if ($result == $NG) {
			&print_log("file", "ERROR", "config", "40030012", 
				   "Target config file format error. ".
				   "file = $target_conf_file");
			last;
		}
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "config", "10030019", 
			   "Target config file format OK. ".
			   "target_conf_file = $target_conf_file");
		#------- DEBUG LOG END -------#

		# for debug.
		#&print_table_data(%target_data);
	}

	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "config", "10030020", 
		   "out_function : do_config : ".
		   "result = $result");
	#------- DEBUG LOG END -------#
	return ($result);
}

#!
# Start specified sslproxy process.
# Start process and Create start information and Update process status.
#
# @param[in]	target_id	target id
# @retval	OK/NG	start result
#
sub start_process
{
	# Argment.
	my ($target_id) = (@_);
	my $result = $NG;
	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "control", "10010029", 
		   "in_function : start_process : ".
		   "target_id = $target_id");
	#------- DEBUG LOG END -------#

	my $config_file = $sslproxyadm_data{$target_id}{"conf_file"};

	# Check sslproxy command file. Try open for exist check.
	if (open(TEMP, "<$SSLPROXY_PATH$SSLPROXY")) {
		close(TEMP);
		# Execute sslproxy start command.
		# /usr/sbin/sslproxy target_id config_file
		my $cmd_result = system("$SSLPROXY_PATH$SSLPROXY $target_id $config_file");
		# Check command result.
		if ($cmd_result != 0) {
			&print_log("file", "ERROR", "control", "40010010", 
				   "sslproxy command execution error.");
		} else {
			# Check Starting sslproxy exist or not.
			# Open ps command output.
			my $ps_cmd = "/bin/ps -C $SSLPROXY -o pid=,cmd= |";
			if (!open(PROCESS, $ps_cmd)) {
				&print_log("file", "ERROR", "control", "40010011", 
					   "Cannot open ps command output.");
			} else {
				# Read ps command data.
				my $line_data = "";
				while ($line_data = <PROCESS>) {
					# Read one line data. (one process)
					# Cut \n.
					$line_data =~ s/^\s*|\n$//g;
					#--------- DEBUG LOG ---------#
					&print_log("file", "DEBUG", "control", "10010030", 
						   "Read one process line data = $line_data");
					#------- DEBUG LOG END -------#

					# Split @param by " " delimiter.
					# $param[0] -> pid
					# $param[1] -> cmd (ex. "./sslproxy")
					# $param[2] -> target id
					# $param[3] -> target config file
					my @param = split /\s/, $line_data, 4;
					# Check target_id exist or not.
					if ($param[2] eq $target_id) {
						# Target process found. Save pid.
						$sslproxyadm_data{$target_id}{"pid"} = $param[0];
						$result = $OK;
						#--------- DEBUG LOG ---------#
						&print_log("file", "DEBUG", "control", "10010031", 
							   "Starting target process found.");
						#------- DEBUG LOG END -------#
						last;
					}
				}
				close(PROCESS);
			}
		}
	} else {
		&print_log("file", "ERROR", "control", "40010012", 
			   "SSLproxy command file not exist.");
	}

	if ($result == $NG) {
		&print_log("file", "ERROR", "control", "40010013", 
			   "Start target process error. ".
			   "target_id = $target_id");
	} else {
		# Set and update process status. (Starting)
		($result) = &update_process_status($target_id, $ON);
		if ($result == $NG) {
			&print_log("file", "ERROR", "control", "40010014", 
				   "Update target process status (Starting) error. ".
				   "target_id = $target_id");
			&stop_process($target_id);
		}
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "control", "10010032", 
			   "Update target process status (Starting) END.");
		#------- DEBUG LOG END -------#
	}

	if ($result == $OK) {
		&print_log("file", "INFO", "control", "20010001", 
			   "SSLproxy process start OK. ".
			   "target_id = $target_id");
	}

	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "control", "10010033", 
		   "out_function : start_process : ".
		   "result = $result");
	#------- DEBUG LOG END -------#
	return ($result);
}

#!
# Stop specified sslproxy process.
# Stop process and Delete start information and Update process status.
#
# @param[in]	target_id	target id
# @retval	OK/NG	start result
#
sub stop_process
{
	# Argment.
	my ($target_id) = (@_);
	my $result = $NG;
	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "control", "10010034", 
		   "in_function : stop_process : ".
		   "target_id = $target_id");
	#------- DEBUG LOG END -------#

	my $pid = $sslproxyadm_data{$target_id}{"pid"};

	# Execute sslproxy stop command.
	# /bin/kill sslproxy_pid
	system("/bin/kill $pid");

	# Check Stopped sslproxy exist or not.
	# Open grep command output.
	my $grep_cmd = "/bin/ps -C $SSLPROXY -o args --no-headers | ".
		       "/bin/cut -d\" \" -f2 | ".
		       "/bin/grep $target_id |";
	if (!open(GREPDATA, $grep_cmd)) {
		&print_log("file", "ERROR", "control", "40010015", 
			   "Cannot open shell command output.");
	} else {
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "control", "10010035", 
			   "Get grep command output.");
		#------- DEBUG LOG END -------#
		my @grep_data = <GREPDATA>;
		my $grep_cnt = @grep_data;
		# Check grep output size. 0 is target process not found.
		if ($grep_cnt == 0) {
			#--------- DEBUG LOG ---------#
			&print_log("file", "DEBUG", "control", "10010036", 
				   "Stopped target process not found (stop OK).");
			#------- DEBUG LOG END -------#
			$result = $OK;
		}
		close(GREPDATA);
	}

	if ($result == $NG) {
		&print_log("file", "ERROR", "control", "40010016", 
			   "Stop target process error. ".
			   "target_id = $target_id");
	} else {
		# Set and update process status. (Stopped)
		($result) = &update_process_status($target_id, $OFF);
		if ($result == $NG) {
			&print_log("file", "ERROR", "control", "40010017", 
				   "Update target process status (Stopped) error. ".
				   "target_id = $target_id");
		}
		#--------- DEBUG LOG ---------#
		&print_log("file", "DEBUG", "control", "10010037", 
			   "Update target process status (Stopped) END.");
		#------- DEBUG LOG END -------#
	}

	if ($result == $OK) {
		&print_log("file", "INFO", "control", "20010002", 
			   "SSLproxy process stop OK. ".
			   "target_id = $target_id");
	}

	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "control", "10010038", 
		   "out_function : stop_process : ".
		   "result = $result");
	#------- DEBUG LOG END -------#
	return ($result);
}

#!
# Set logger.
# Set logfile/loglevel and Execute logrotate.
#
# @retval	OK/NG	check result
#
sub set_log
{
	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "logger", "10040001", 
		   "in_function : set_log");
	#------- DEBUG LOG END -------#
	my $result = $OK;

	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "logger", "10040002", 
		   "Config before value. ".
		   "LOG_LEVEL = $LOG_LEVEL, ".
		   "LOG_FILE = $LOG_FILE");
	#------- DEBUG LOG END -------#

	# Get loglevel from logger configuration.
	my $loglevel = $sslproxyadm_data{$LOGGER_SECTION_KEY}{"log_level"};
	if ($loglevel eq "") {
		&print_log("file", "WARN", "logger", "30040001", 
			   "Log level not found in config. ".
			   "Use default log level. ".
			   "level = $LOG_LEVEL");
		$loglevel = $LOG_LEVEL;
	} else {
		# Check config log level range.
		if ($loglevel ne "debug" &&
		    $loglevel ne "info"  &&
		    $loglevel ne "warn"  &&
		    $loglevel ne "error" &&
		    $loglevel ne "fatal") {
			&print_log("file", "ERROR", "logger", "40040001", 
				   "Invalid config log level. ".
				   "level = $loglevel");
			$result = $NG;
		} else {
			#--------- DEBUG LOG ---------#
			&print_log("file", "DEBUG", "logger", "10040003", 
				   "Config log level is $loglevel.");
			#------- DEBUG LOG END -------#
		}
	}

	# Get logfile from logger configuration.
	my $logfile = $sslproxyadm_data{$LOGGER_SECTION_KEY}{"log_filename"};
	if ($result == $OK) {
		if ($logfile eq "") {
			&print_log("file", "WARN", "logger", "30040002", 
				   "Log file not found in config. ".
				   "Use default log file. ".
				   "file = $LOG_FILE");
			$logfile = $LOG_FILE;
		} else {
			# Check log file. Try open.
			if(!open(LOGFILE, ">>$logfile")) {
				&print_log("file", "ERROR", "logger", "40040002", 
					   "Cannot open config log file. ".
					   "file = $logfile");
				$result = $NG;
			} else {
				close(LOGFILE);
				if ($logfile ne $LOG_FILE) {
					&print_log("file", "WARN", "logger", "30040003", 
						   "Log file is chaged. ".
						   "$LOGROTATE_CONF_FILE file ".
						   "should also change for log rotate.");
				} else {
					#--------- DEBUG LOG ---------#
					&print_log("file", "DEBUG", "logger", "10040004", 
						   "Log file is still default.");
					#------- DEBUG LOG END -------#
				}
			}
		}
	}

	# Execute logrotate command.
	if ($result == $OK) {
		($result) = system("$LOGROTATE_CMD $LOGROTATE_CONF_FILE");
		if ($result != $OK) {
			&print_log("file", "ERROR", "logger", "40040003", 
				   "Logrotate execute error. : $!");
			$result = $NG;
			#--------- DEBUG LOG ---------#
			&print_log("file", "DEBUG", "logger", "10040005", 
				   "Not change logger setteing.");
			#------- DEBUG LOG END -------#
		} else {
			# Change logger setteing.
			$LOG_LEVEL = $loglevel;
			$LOG_FILE = $logfile;
			#--------- DEBUG LOG ---------#
			&print_log("file", "DEBUG", "logger", "10040006", 
				   "Change logger setteing. ".
				   "level = $LOG_LEVEL, ".
				   "file = $LOG_FILE");
			#------- DEBUG LOG END -------#
		}
	}

	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "logger", "10040007", 
		   "out_function : set_log : ".
		   "result = $result");
	#------- DEBUG LOG END -------#
	return ($result);
}

#!
# Output log message to console or log file.
#
# output device string	-> cout/cerr/file/fcout/fcerr
# log level string	-> DEBUG/INFO/WARN/ERROR/FATAL (1-5)
# log category string	-> control/status/config/logger/common (1-5)
# 			   (sslproxyadm_xxxxx)
# message number	-> level_numberX + category_numberXXX + XXXX
# 			   (SLAXXXXXXXX)
#
# @param[in]	outdev		output device
# @param[in]	level		message log level
# @param[in]	category	log category
# @param[in]	msgid		message number
# @param[in]	msg		message string
#
sub print_log
{
	# Argment.
	my ($outdev, $level, $category, $msgid, $msg) = (@_);
	my $result = $NG;
	#--------- DEBUG LOG ---------#
	if ($LOGGER_DEBUG) {
		print STDOUT "in_function : print_log : ".
			     "outdev = $outdev, ".
			     "level = $level, ".
			     "category = $category, ".
			     "msgid = $msgid, ".
			     "msg = $msg\n";
	}
	#------- DEBUG LOG END -------#

	# Check message and output log level.
	($result) =&check_log_level($level);
	if ($result == $OK) {
		# Check log category range.
		if ($category ne "control" &&
		    $category ne "status" &&
		    $category ne "config" &&
		    $category ne "logger" &&
		    $category ne "common") {
			print STDERR "Print log error : Invalid log category.\n";
		# Check log output device range.
		} elsif ($outdev ne "cout" &&
		    $outdev ne "cerr" &&
		    $outdev ne "file" &&
		    $outdev ne "fcout" &&
		    $outdev ne "fcerr") {
			print STDERR "Print log error : Invalid log output device.\n";
		} else {
			# Print to console.
			if ($outdev eq "cout" || $outdev eq "fcout") {
				print STDOUT "$msg\n";
			} elsif ($outdev eq "cerr" || $outdev eq "fcerr") {
				print STDERR "$msg\n";
			}
			# Print to lof file.
			if ($outdev eq "file" || $outdev eq "fcout" || $outdev eq "fcerr") {
				if(!open(LOGFILE, ">>$LOG_FILE")) {
					print STDERR "Cannot open log file.\n";
				} else {
					my $now_date = localtime();
					print LOGFILE "$now_date ".
						      "[$level] ".
						      "sslproxyadm_$category ".
						      "SLA$msgid ".
						      "$msg\n";
					close(LOGFILE);
				}
			}
		}
	}

	#--------- DEBUG LOG ---------#
	if ($LOGGER_DEBUG) {
		print STDOUT "out_function : print_log\n";
	}
	#------- DEBUG LOG END -------#
}

#!
# Check message and output log level.
#
# @param[in]	level	message log level
# @retval	OK/NG	check result
#
sub check_log_level
{
	# Argment.
	my ($level) = (@_);
	my $result = $NG;
	#--------- DEBUG LOG ---------#
	if ($LOGGER_DEBUG) {
		print STDOUT "in_function : check_log_level : level = $level\n";
	}
	#------- DEBUG LOG END -------#

	# Check message log level range.
	if ($level ne "DEBUG" &&
	    $level ne "INFO"  &&
	    $level ne "WARN"  &&
	    $level ne "ERROR" &&
	    $level ne "FATAL") {
		print STDERR "Print log error : Invalid message log level.\n";
	# Check output log level.
	} elsif ($LOG_LEVEL eq "debug") {
		$result = $OK;
		#--------- DEBUG LOG ---------#
		if ($LOGGER_DEBUG) {
			print STDOUT "Logout level OK. out[$LOG_LEVEL] msg[$level]\n";
		}
		#------- DEBUG LOG END -------#
	} elsif ($LOG_LEVEL eq "info") {
		if ($level eq "INFO"  ||
		    $level eq "WARN"  ||
		    $level eq "ERROR" ||
		    $level eq "FATAL") {
			$result = $OK;
			#--------- DEBUG LOG ---------#
			if ($LOGGER_DEBUG) {
				print STDOUT "Logout level OK. out[$LOG_LEVEL] msg[$level]\n";
			}
			#------- DEBUG LOG END -------#
		} else {
			#--------- DEBUG LOG ---------#
			if ($LOGGER_DEBUG) {
				print STDOUT "Logout level NG. out[$LOG_LEVEL] msg[$level]\n";
			}
			#------- DEBUG LOG END -------#
		}
	} elsif ($LOG_LEVEL eq "warn") {
		if ($level eq "WARN"  ||
		    $level eq "ERROR" ||
		    $level eq "FATAL") {
			$result = $OK;
			#--------- DEBUG LOG ---------#
			if ($LOGGER_DEBUG) {
				print STDOUT "Logout level OK. out[$LOG_LEVEL] msg[$level]\n";
			}
			#------- DEBUG LOG END -------#
		} else {
			#--------- DEBUG LOG ---------#
			if ($LOGGER_DEBUG) {
				print STDOUT "Logout level NG. out[$LOG_LEVEL] msg[$level]\n";
			}
			#------- DEBUG LOG END -------#
		}
	} elsif ($LOG_LEVEL eq "error") {
		if ($level eq "ERROR"  ||
		    $level eq "FATAL") {
			$result = $OK;
			#--------- DEBUG LOG ---------#
			if ($LOGGER_DEBUG) {
				print STDOUT "Logout level OK. out[$LOG_LEVEL] msg[$level]\n";
			}
			#------- DEBUG LOG END -------#
		} else {
			#--------- DEBUG LOG ---------#
			if ($LOGGER_DEBUG) {
				print STDOUT "Logout level NG. out[$LOG_LEVEL] msg[$level]\n";
			}
			#------- DEBUG LOG END -------#
		}
	} elsif ($LOG_LEVEL eq "fatal") {
		if ($level eq "FATAL") {
			$result = $OK;
			#--------- DEBUG LOG ---------#
			if ($LOGGER_DEBUG) {
				print STDOUT "Logout level OK. out[$LOG_LEVEL] msg[$level]\n";
			}
			#------- DEBUG LOG END -------#
		} else {
			#--------- DEBUG LOG ---------#
			if ($LOGGER_DEBUG) {
				print STDOUT "Logout level NG. out[$LOG_LEVEL] msg[$level]\n";
			}
			#------- DEBUG LOG END -------#
		}
	} else {
		print STDERR "Print log error : Invalid output log level.\n";
	}

	#--------- DEBUG LOG ---------#
	if ($LOGGER_DEBUG) {
		print STDOUT "out_function : check_log_level : result = $result\n";
	}
	#------- DEBUG LOG END -------#
	return ($result);
}

#!
# Show command usage.
#
sub usage
{
	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "common", "10050028", 
		   "in_function : usage");
	#------- DEBUG LOG END -------#

	print STDERR "\nUsage : sslproxyadm ".
		     "\{start|stop|restart|reload|check|status|config\} ".
		     "[config_file_name]\n".
		     "  start		Start SSLproxy process.\n".
		     "  stop		Stop SSLproxy process.\n".
		     "  restart	Restart SSLproxy process.\n".
		     "  reload	Re-configure SSLproxy process.\n".
		     "  check		Check SSLproxy process status.\n".
		     "  status	Print SSLproxy process status.\n".
		     "  config	Check SSLproxy configration file.\n\n";

	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "common", "10050029", 
		   "out_function : usage");
	#------- DEBUG LOG END -------#
}

#!
# Exit sslproxyadm command.
#
# @param[in]	result	command result
#
sub do_exit
{
	# Argment.
	my ($result) = (@_);
	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "common", "10050030", 
		   "in_function : do_exit : result = $result");
	#------- DEBUG LOG END -------#

	if ($result == $OK) {
		&print_log("fcout", "INFO", "common", "20050001", 
			   "SSLproxyadm command ($CMD_OPT) is successful.");
	} elsif ($result == $NG) {
		&print_log("fcerr", "INFO", "common", "20050002", 
			   "SSLproxyadm command ($CMD_OPT) is failure.");
	}

	#--------- DEBUG LOG ---------#
	&print_log("file", "DEBUG", "common", "10050031", 
		   "out_function : do_exit");
	#------- DEBUG LOG END -------#
	exit($result);
}

#!
# Print specified table data to STDOUT for debug.
#
# @param[in]	table_data	command result
#
sub print_table_data
{
	my (%table_data) = (@_);
	print STDOUT "\n*** Print table data ***\n";
	my $section_count = keys(%table_data);
	print STDOUT "Section count[$section_count]\n";
	while (my ($section_name, $section_data) = each (%table_data)) {
		my $key_count = keys(%$section_data);
		print STDOUT "	[$section_name] section. Key count[$key_count]\n";
		while (my ($key, $value) = each (%$section_data)) {
			print STDOUT "		Key[$key] Value[$value]\n";
		}
	}
	print STDOUT "\n";
}
