#!/usr/bin/perl
#
# chkconfig: 345 99 01
# description: Starts and stops the SPLX daemons used to provide SPLX services.
#
# /etc/init.d/splxcore
#
### BEGIN INIT INFO
# Provides: splxcore
# Required-Start:
# X-UnitedLinux-Should-Start:
# Required-Stop:
# X-UnitedLinux-Should-Stop:
# Default-Start: 3 4 5
# Default-Stop:
# Short-Description: ServerProtect for Linux core
# Description: Starts and stops the SPLX core daemons used to provide SPLX core services.
### END INIT INFO

use utf8;

use Sys::Syslog qw(:DEFAULT setlogsock);
use POSIX qw(strftime);

# define variables

$uid=$<;

$debuglevel=0;
$MODULE_NAME="splx_service";

#$tmi_cfg_file="/opt/TrendMicro/TMI/TMI.cfg";

$ld_so_conf_file="/etc/ld.so.conf";

$product_root="/opt/TrendMicro/SProtectLinux";

$splx_log_file="$product_root/SPLX.tmp/splx.log";

$tmsplx_xml_file="$product_root/tmsplx.xml";

$ARCH=`uname -m`;
chomp($ARCH);


#print $ARCH;

# define commands

if ( -e "/sbin/pidof" ) {
	$pidof="/sbin/pidof";
} elsif ( -e "/bin/pidof") {
	$pidof="/bin/pidof";
} elsif ( -e "/usr/bin/pidof") {
	$pidof="/usr/bin/pidof";
} elsif ( -e "/usr/sbin/pidof") {
	$pidof="/usr/sbin/pidof";
} elsif ( -e "/usr/local/bin/pidof") {
	$pidof="/usr/local/bin/pidof";
} elsif ( -e "/usr/local/sbin/pidof") {
	$pidof="/usr/local/sbin/pidof";
} else {
}
$ldconfig="/sbin/ldconfig";

$insmod="/sbin/insmod";

$rmmod="/sbin/rmmod";

$mknod="/bin/mknod";

$ps="/bin/ps";

# reads debug level from configuration file

open TMSPLX_XML, "< $tmsplx_xml_file";
while (<TMSPLX_XML>) {
	if (/(Name=\"UserDebugLevel\"\sValue=\"\d\")/) {
		@list=split / /, $1;
		foreach $token (@list) {
			if ($token=~/Value/) {
				@sublist=split /=/, $token;
				$debuglevel=eval $sublist[1];
			}
		}
	}
}
close TMSPLX_XML;

# write logs if DEBUG is defined
my $log_file_is_open = 0;	#FALSE
sub open_log{
	if (open LOG_FILE, ">> /var/log/messages") {
        binmode(LOG_FILE, ":utf8");
		$log_file_is_open = 1;	#TRUE
	}
}

sub write_log{
	my $message=$_[0];

	if ($log_file_is_open) {
		$now_string = strftime "%b %e %H:%M:%S", localtime;
		($hostname, @alias, $ad, $len, @addrs) = gethostbyname('localhost');
		print LOG_FILE $now_string . " " . $hostname . " " . $MODULE_NAME . ": " . $message . "\n";
	}

	return 1;	
}

sub close_log{
	if ($log_file_is_open) {
		close(LOG_FILE);
	}
	return 1;
}

# check if this script is run by root

if (defined($uid) && ($uid!=0)) {
	write_log "error: ServerProtect for Linux must be run by root.";
	print "splxcore must be launched by a root user. Login as root and try again.\n";
	exit 1;
}
# set colors for displaying results

$bootup=$ENV{"BOOTUP"};
$res_col=60;

if (!defined($bootup)) {
	$bootup="color";
}

sub move_to_colon{
	($bootup eq "color") && (print "\033[${res_col}G");
	return 1;
}

sub set_success_color{
	($bootup eq "color") && (print "\033[1;32m");
	return 1;
}

sub set_failure_color{
	($bootup eq "color") && (print "\033[1;31m");
	return 1;
}

sub set_normal_color{
	($bootup eq "color") && (print "\033[0;39m");
	return 1;
}

sub info_success {
    if ( -e "/etc/init.d/functions") {    
        system ("export CONSOLETYPE=vt && . /etc/init.d/functions && \$SETCOLOR_SUCCESS && echo -ne \"" . $_[0] . "\" && \$SETCOLOR_NORMAL");
    }
    else
    {
        set_success_color;
        print $_[0];
        set_normal_color;
    }
}

sub info_failure {
    if ( -e "/etc/init.d/functions") {    
        system ("export CONSOLETYPE=vt && . /etc/init.d/functions && \$SETCOLOR_FAILURE && echo -ne \"" . $_[0] . "\" && \$SETCOLOR_NORMAL");
    }
    else
    {
        set_failure_color;
        print $_[0];
        set_normal_color;
    }
}

# echo success or failure
sub echo_success {
    if (( -e "/etc/init.d/functions") && ($bootup eq "color")){    
        system ("export CONSOLETYPE=vt && . /etc/init.d/functions && \$MOVE_TO_COL && echo -n \"[  \" && \$SETCOLOR_SUCCESS && echo -n \"OK\" && \$SETCOLOR_NORMAL && echo -ne \"  ]\\r\"");
        print "\n"
    }
    else
    {
        ($bootup eq "color") && (&move_to_colon);
        print "[  ";
        
        ($bootup eq "color") && (&set_success_color);
        print "OK";
        
        ($bootup eq "color") && (&set_normal_color);
        print "  ]\n";
        
    }
}

sub echo_failure {
    if ((-e "/etc/init.d/functions") && ($bootup eq "color")){
        system ("export CONSOLETYPE=vt && . /etc/init.d/functions && \$MOVE_TO_COL && echo -n \"[\" && \$SETCOLOR_FAILURE && echo -n \"FAILED\" && \$SETCOLOR_NORMAL && echo -ne \"]\\r\"");
        print "\n";
    }
    else
    {
        ($bootup eq "color") && (&move_to_colon);
        print "[";
        
        ($bootup eq "color") && (&set_failure_color);
        print "FAILED";
        
        ($bootup eq "color") && (&set_normal_color);
        print "]\n";
    }
}

sub echo_notavaliable{
    if ((-e "/etc/init.d/functions") && ($bootup eq "color")){
        system ("export CONSOLETYPE=vt && . /etc/init.d/functions && \$MOVE_TO_COL && echo -n \"[Not available]\" && echo -ne \"]\\r\"");
        print "\n";
    }
    else
    {

        ($bootup eq "color") && (&move_to_colon);
        print "[";
        
        print "Not available";
        
        print "]\n";
    }
}

# check status of a program

sub is_running{
	my %property=(
		"running" => 0,
		"pid" => ""
	);
	my $program=$_[0];
	my @pid_list;
	my $pid;
	SWITCH:{
		# splxmod
		($program eq "splxmod") && do {
			open MODULES, "< /proc/modules";
			while (<MODULES>) {
				if (/splxmod/) {
					$property{'running'}=1;
				}
			}
			close MODULES;
			return %property;
			last SWITCH;
		};

		# default
		open PID_OF, "$pidof $program |" or return %property;
		while (<PID_OF>) {
			@pid_list=split /\s/, $_;
		}
		close PID_OF;
		foreach $pid (@pid_list) {
			if (kill 0, $pid) {
				if ($property{"pid"} eq "") {
					$property{"pid"}=$pid;
				} else {
					$property{"pid"}.=" $pid";
				}
			}
		}
		if ($property{"pid"} ne "") {
			$property{"running"}=1;
			return %property;
		} else {
			$property{"running"}=0;
			return %property;
		}
	}
}

# show status of programs

sub show_status{
	my $program=$_[0];
	my $running=0;
	my %property=(
		"running" => 0,
		"pid" => ""
	);

 	SWITCH:{
		($program eq "splxmod") && do {
			%property = is_running "splxmod";
			if ($property{"running"}==1) {
				print "$program module is running...\n";
				return 0;
			}
			if ( -e "/var/lock/subsys/splxmod") {
				print "The splxmod module has been loaded successfully, but is not running.\n";
				return 1;
			} else {
				if (! open OS_RELEASE, "< /proc/sys/kernel/osrelease") {
					write_log "ERROR: Cannot open /proc/sys/kernel/osrelease.";
				}
				while (<OS_RELEASE>) {
					chomp($_);
					$kernel_version=$_;
				}
				close OS_RELEASE;


				print "$program module is stopped\n";
				if(-e "$product_root/SPLX.module/splxmod-$kernel_version.$ARCH.o")
				{
					return 1;
				}else
				{
					return 0;
				}
			}
			last SWITCH;
		};
		($program eq "entity") && do {
			%property = is_running "entity";
			if ($property{"running"}==1) {
				print "$program (pid ".$property{"pid"}.") is running...\n";
				return 0;
			}
			if (-e "/var/run/entity.pid") {
				open PID_FILE, "< /var/run/entity.pid";
				while (<PID_FILE>) {
					chomp;
					if ($_ ne "") {
						print "The $program is dead, but the pid file still exists. The pid file path is '/var/run/entity.pid'.\n";
						return 1;
					}
					close PID_FILE;
				}
			}
			if ( -e "/var/lock/subsys/entity") {
				print "The $program is dead, but the subsys is locked. The subsys path is '/var/lock/subsys/entity'.\n";
				return 1;
			} else {
				print "$program is stopped\n";
				return 1;
			}
			last SWITCH;
		};
	
		($program eq "vsapiapp") && do {
			%property = is_running $program;
			if ($property{"running"}==1) {
				print "$program (pid ".$property{"pid"}.") is running...\n";
				return 0;
			}

			if (! open OS_RELEASE, "< /proc/sys/kernel/osrelease") {
				write_log "ERROR: Cannot open /proc/sys/kernel/osrelease.";
			}
			while (<OS_RELEASE>) {
				chomp($_);
				$kernel_version=$_;
			}
			close OS_RELEASE;

			if(-e "$product_root/SPLX.module/splxmod-$kernel_version.$ARCH.o")
			{
				if (-e "/var/run/$program.pid")
				{
					open PID_FILE, "< /var/run/$program.pid";
					while (<PID_FILE>) {
						print "$program is dead, but the pid file still exists. The pid file path is '/var/run/vsapiapp.pid'.\n";
						close PID_FILE;
						return 1;
					}
				}
				if (-e "/var/lock/subsys/$program")
				{
					print "$program is dead, but the subsys is locked. The subsys path is '/var/lock/subsys/vsapiapp'.\n";
					return 1;
				} else {
					print "$program is stopped\n";
					return 1;
				}
			}else
			{
				print "$program is stopped\n";
				return 0;
			}
		};
		%property = is_running $program;
		if ($property{"running"}==1) {
			print "$program (pid ".$property{"pid"}.") is running...\n";
			return 0;
		}
		if (-e "/var/run/$program.pid") {
			open PID_FILE, "< /var/run/$program.pid";
			while (<PID_FILE>) {
				print "$program dead but pid file exists\n";
				close PID_FILE;
				return 1;
			}
		}
		if (-e "/var/lock/subsys/$program") {
			print "$program dead but subsys locked\n";
			return 1;
		} else {
			print "$program is stopped\n";
			return 1;
		}
	}
}

# update library paths for execution

sub update_library_path{
	my $first=0;
	my $reload=0;
	open LD_SO_CONF_FILE, "< $ld_so_conf_file";
	while (<LD_SO_CONF_FILE>) {
		if (/$product_root\/SPLX.lib/) {
			$first=1;
		}
	}
	close LD_SO_CONF_FILE;
	open LD_SO_CONF_FILE, ">> $ld_so_conf_file";
	if ($first==0) {
		print LD_SO_CONF_FILE "$product_root/SPLX.lib\n";
		$reload=1;
	}
	close LD_SO_CONF_FILE;
	if ($reload==1) {
		system "$ldconfig";
	}

	my $ld_library_path=$ENV{'LD_LIBRARY_PATH'};
	if (defined($ld_library_path)) {
		if (!($ld_library_path=~/"$product_root\/SPLX.lib"/)) {
			if (length($ld_library_path)==0) {
				$ld_library_path="$product_root/SPLX.lib";
			} else {
				$ld_library_path="$ld_library_path:$product_root/SPLX.lib";
			}
		}
	}
	
	# Set LD_LIBRARY_PATH and build links for Agent libraries.
	$ENV{'LD_LIBRARY_PATH'} = "$product_root/SPLX.lib/agent";
	system "ldconfig -n $product_root/SPLX.lib/agent";

	return 1;
}

# kill process

sub kill_proc{
	my $program=$_[0];
	my @pid_list;
	my $i;
	my $return_value=0;
	open PID_OF, "$pidof $program |" or return 0;
	while (<PID_OF>) {
		@pid_list=split /\s/, $_;
	}
	close PID_OF;
	$i= scalar(@pid_list)-1;
	if ($i<0) {
		$return_value=1;
	} 
#       midified to fix the internal case #TT155623 
    else{
		$count=$i;
		while($count>=0){
			
			open PPID_OF, "$ps -eo pid,ppid | grep $pid_list[ $count ] |" or return 0;
			my $line;
			while(<PPID_OF>){
			$line++;
			}
			close PPID_OF;
			if($line>1){
			last;
			}
			$count--;
		}
		if($count<0){
			$count=$i;
		}	
		my $pid=$pid_list[ $count ];
                $return_value+=kill 15, $pid;
        }
 #  modified end
	if ($return_value) {
		return 1;
	} else {
		return 0;
	}
}

# touch file

sub touch{
	my $filename=$_[0];
	if (-e $_[0]) {
		open TEMP, $filename;
		close TEMP;
	} else {
		open TEMP, "> $filename";
		close TEMP;
	}
}

# main program

if ($debuglevel!=0) {
	open_log;
}
SWITCH:{
	(!defined($ARGV[0])) && do{
		print "Invalid usage of splxcore command.\n";
		print "Valid syntax is: '$0 {start|stop|restart|status}'.\n";
		print "Enter the correct splxcore command and try again.\n";
		exit 1;
	};
	($ARGV[0] eq "stop") && do {
		my $STOP_Entity=0;
		my $STOP_vsapiapp=0;
		my $STOP_splxmod=0;
		my $no_Entity=0;
		my $no_vsapiapp=0;
		my $no_splxmod=0;

		#print "Shutting down ServerProtect for Linux:\n";
		#write_log "Shutting down ServerProtect for Linux: ";
		# stop manual/schedule scan
		# shutdown manual scan if needed
		%property=is_running "splx_manual_scan";
		if ($property{"running"}) {
			system "$product_root/SPLX.vsapiapp/splxmain -n > /dev/null 2>&1";
		}

		# shutdown scheduled scan if needed

		# changed to handle case  #TT146013  by errik
		%property=is_running "splx_schedule_s";
		# end
		if ($property{"running"}) {
			system "$product_root/SPLX.vsapiapp/splxmain -t > /dev/null 2>&1";
		}
	
		# shutdown vsapiapp
		print "Shutting down vsapiapp";
		write_log "step: shutting down vsapiapp service.";
		%property=is_running "vsapiapp";
		if ($property{"running"}) {
			$return_value=system "$product_root/SPLX.vsapiapp/splxmain -a > /dev/null 2>&1";
                        $return_value=system "$pidof vsapiapp > /dev/null";
                        if ($return_value==0) {
                                $return_value=system "/usr/bin/killall -s 9 vsapiapp 2>&1 > /dev/null";
                        } else {
                                $return_value=0;
                        }
                        if ($return_value==0) {
                                unlink "/var/lock/subsys/vsapiapp";
                                write_log "success: vsapiapp service stopped normally.";
                                echo_success;
                                $STOP_vsapiapp=0;
                        } else {
                                write_log "error: vsapiapp service stopped with errors.";
                                echo_failure;
                                $STOP_vsapiapp=1;
                        }
                        #sleep 5;
		} else {
			unlink "/var/lock/subsys/vsapiapp";
			write_log "info: vsapiapp service not running.";
			echo_failure;
			$STOP_vsapiapp=0;
			$no_vsapiapp=1;
		}

		# unload module
		print "Unloading splx kernel module:";
		write_log "step: unloading splx kernel module.";
		%property=is_running "splxmod";
		if ($property{'running'}==0) {
			unlink "/var/lock/subsys/splxmod";
			unlink "/dev/splxdev";
			write_log "info: splx kernel module not loaded.";
			echo_failure;
			$STOP_splxmod=0;
			$no_splxmod=1;
		} else {
			$i=0;
			while ($property{"running"} && $i<600) {
				$return_value=system "$rmmod splxmod > /dev/null 2>&1";
				if ($return_value==1) {
					write_log "Unable to unload splx kernel module. ServerProtect will attempt to unload splx kernel module.";
				}
				sleep 1;
				%property=is_running "splxmod";
				$i=$i+1;
			}
			if($property{"running"}){
				write_log "error: Some errors were found while unloading splx kernel module.";
				echo_failure;
				$STOP_splxmod=1;
			}else{
				unlink "/var/lock/subsys/splxmod";
				unlink "/dev/splxdev";
				write_log "success: splx kernel module unloaded.";
				echo_success;
				$STOP_splxmod=0;
			}
		}

		# stop entity
		print "Shutting down entity: ";
		write_log "step: shutting down entity.";
		%property=is_running "entity";
		if ($property{"running"}==0) {
			unlink "/var/lock/subsys/entity";
			write_log "info: entity service not running.";
			echo_failure;
			$STOP_Entity=0;
			$no_Entity=1;
		} else {
			$i=0;
			while ($property{"running"} && $i<15){
				if(! kill_proc "entity"){
					write_log "Unable to stop entity. ServerProtect will attempt to stop the entity.";
				}
				sleep 1;
				%property=is_running "entity";
				$i=$i+1;
			}
			if($property{"running"}){
				write_log "warning: Some errors were found while stopping entity. Forcefully terminating it.";
				system "killall -9 entity";
			}
			unlink "/var/lock/subsys/entity";
			write_log "success: entity service stopped.";
			echo_success;
			$STOP_Entity=0;
		}

		# disable jobs of crontab
        # *****************************************
        unlink("/etc/cron.d/splxbif");
        # *****************************************
		system "$product_root/SPLX.vsapiapp/splxmain -b > /dev/null 2>&1";

		$STOP=$STOP_Entity+$STOP_vsapiapp+$STOP_splxmod;
		$no_core=$no_Entity+$no_vsapiapp+$no_splxmod;
		if ($STOP==0) {
			if ($no_core==3)
			{
				info_failure("ServerProtect for Linux core not running.\n");
				unlink "/var/lock/subsys/splxcore";
				write_log "ServerProtect for Linux core not running.";
				exit 2;
			}
			
			info_success("ServerProtect for Linux core stopped normally.\n");
			unlink "/var/lock/subsys/splxcore";
			write_log "ServerProtect for Linux core stopped.";
			exit 0;
		} else {
			info_failure("splxcore stopped with errors. Please contact Trend Micro support.\n");
			write_log "ServerProtect for Linux core stopped with errors.";
			exit 1;
		}

		last SWITCH;
	};
	($ARGV[0] eq "start") && do {
		my $START_Entity=0;
		my $START_vsapiapp=0;
		my $START_splxmod=0;
		#print "Starting ServerProtect for Linux core: \n";
		#write_log "Starting ServerProtect for Linux core:";
		# remove temporary files left by vsapiapp
		$one = '$1';
		$dollar = '$';
		$awk_regex1 = "'/^V[0-9A-V][0-9A-V][0-9A-V][0-9A-V][0-9A-V][[:print:]][[:print:]][[:print:]][[:print:]][[:print:]][[:print:]]$dollar/ {print $one}'";
		system "cd $product_root/SPLX.tmp/; rm  -f `ls | awk $awk_regex1` ";
		$awk_regex2 = "'/^VS[0-9A-V][0-9A-V][0-9A-V][0-9A-V][0-9A-V][0-9A-V].[0-9A-V][0-9A-V][0-9A-V]$dollar/ {print $one}'";
		system "cd $product_root/SPLX.tmp/; rm  -f `ls | awk $awk_regex2 ` ";


		# check if splxcore is running
		#%property=is_running "entity";
		#if ($property{"running"}) {
		#  set_success_color;
		#  print "ServerProtect for Linux core running.\n";
		#  set_normal_color;
		#  write_log "error: ServerProtect for Linux core running. Entity is still running.";
		#  exit 1;
		#}

		# update library path
		update_library_path;

		# check if tmsplx.xml exists
		if (! -e $tmsplx_xml_file) {
			write_log "error: file $tmsplx_xml_file not exist.";
			echo_failure;
			print "ServerProtect for Linux core started with errors.\n";
			print "Some errors were found while starting splxcore. See the system log for error description. The default system log file path is /var/log/messages.\n";
			write_log "ServerProtect for Linux core started with errors.";
			exit 1;
		}

		# co-work with ISVW, IMSS, IWSS
		system "$product_root/SPLX.util/splxcomp -i > /dev/null 2>&1";


		# for check expire
		$expire_value=system "$product_root/SPLX.vsapiapp/entity -E > /dev/null 2>&1";
		$expire_value >>= 8;

		# start Entity
		print "Starting Entity: ";
		write_log "step: starting Entity service.";
		$return_value=0;
		%property=is_running "entity";
		if (!$property{"running"})
		{

			chdir "$product_root";

			if ($debuglevel!=0) {
				$return_value=system "$product_root/SPLX.vsapiapp/entity -D > $product_root/SPLX.tmp/entity.log 2>&1 &";
			} else {
				$return_value=system "$product_root/SPLX.vsapiapp/entity -D > /dev/null 2>&1 &";
			}
		}
		if ($return_value==0) {
			write_log "step: entity service started.";
			echo_success;
			touch "/var/lock/subsys/entity";
		} else {
			write_log "error: entity service can't be started.";
			echo_failure;
			print "Unable to start the entity. Please contact Trend Micro support.\n";
			write_log "Entity service started with errors.";
			$START_Entity=1;
		}

		# check if splx kernel module exist and make a symbolic link
		if (! open OS_RELEASE, "< /proc/sys/kernel/osrelease") {
			write_log "ERROR: Cannot open /proc/sys/kernel/osrelease.";
		}
		while (<OS_RELEASE>) {
			chomp($_);
			$kernel_version=$_;
		}
		close OS_RELEASE;

		if (-e "$product_root/SPLX.module/splxmod-$kernel_version.$ARCH.o") {
			unlink "$product_root/SPLX.module/splxmod.ko";
			unlink "$product_root/SPLX.module/splxmod.o";
			symlink "$product_root/SPLX.module/splxmod-$kernel_version.$ARCH.o", "$product_root/SPLX.module/splxmod.o";
			symlink "$product_root/SPLX.module/splxmod.o", "$product_root/SPLX.module/splxmod.ko";
		} else {
			write_log "ERROR: No valid KHM present. Failed to find [$product_root/SPLX.module/splxmod-$kernel_version.$ARCH.o]";
		}

		if ( $expire_value == 0 ) {

			# installs splx kernel module
			print "Loading splx kernel module: ";
			write_log "step: loading splx kernel module.";

			$splxmod_addr="0";
			if (! open SYS_MAP, "< /boot/System.map-$kernel_version") {
				write_log "ERROR: Cannot open /boot/System.map-$kernel_version.";
			}
			while (<SYS_MAP>) {
				chomp($_);
				if ($_=~/ sys_call_table/) {
					@tk_list=split / /, $_;
					if ($tk_list[2] eq "sys_call_table") {
						$splxmod_addr=$tk_list[0];
						last;
					}
				}
			}
			close SYS_MAP;


			$splxmod_execve_addr="0";
			$find_doexecve_address=0;
			if (! open SYS_MAP, "< /boot/System.map-$kernel_version") {
				write_log "ERROR: Cannot open /boot/System.map-$kernel_version.";
			}
			while (<SYS_MAP>) {
				chomp($_);
				if ($_=~/ do_execve/) {
					@tk_list=split / /, $_;
					if ($tk_list[2] eq "do_execve") {
						$splxmod_execve_addr=$tk_list[0];
						$find_doexecve_address=1;
						last;
					}
				}
			}
			close SYS_MAP;
			
			if ($find_doexecve_address == 0){
				if (! open SYS_MAP, "< /boot/System.map-$kernel_version") {
					write_log "ERROR: Cannot open /boot/System.map-$kernel_version.";
				}
				while (<SYS_MAP>) {
					chomp($_);
					if ($_=~/ kernel_execve/) {
						@tk_list=split / /, $_;
						if ($tk_list[2] eq "kernel_execve") {
							$splxmod_execve_addr=$tk_list[0];
							last;
						}
					}
				}
				close SYS_MAP;
			}

			if ($ARCH eq "x86_64"){
				$splxmod_ret_addr="0";
				if (! open SYS_MAP, "< /boot/System.map-$kernel_version") {
					write_log "ERROR: Cannot open /boot/System.map-$kernel_version.";
				}
				while (<SYS_MAP>) {
					chomp($_);
					if ($_=~/ int_ret_from_sys_call/) {
						@tk_list=split / /, $_;
						if ($tk_list[2] eq "int_ret_from_sys_call") {
							$splxmod_ret_addr=$tk_list[0];
							last;
						}
					}
				}
				close SYS_MAP;							
				
				$splxmod_ia32_addr="0";
				if (! open SYS_MAP, "< /boot/System.map-$kernel_version") {
					write_log "ERROR: Cannot open /boot/System.map-$kernel_version.";
				}
				while (<SYS_MAP>) {
					chomp($_);
					if ($_=~/ ia32_sys_call_table/) {
						@tk_list=split / /, $_;
						if ($tk_list[2] eq "ia32_sys_call_table") {
							$splxmod_ia32_addr=$tk_list[0];
							last;
						}
					}
				}
				close SYS_MAP;
				
				$splxmod_compat_do_execve_addr="0";
				if (! open SYS_MAP, "< /boot/System.map-$kernel_version") {
					write_log "ERROR: Cannot open /boot/System.map-$kernel_version.";
				}
				while (<SYS_MAP>) {
					chomp($_);
					if ($_=~/ compat_do_execve/) {
						@tk_list=split / /, $_;
						if ($tk_list[2] eq "compat_do_execve") {
							$splxmod_compat_do_execve_addr=$tk_list[0];
							last;
						}
					}
				}
				close SYS_MAP;														
			}

			%property=is_running "splxmod";
			$return_value=0;
			if (!$property{"running"})
			{
				if (! -e "/var/lock/subsys/splxmod" && -e "$product_root/SPLX.module/splxmod-$kernel_version.$ARCH.o") {
					if ($ARCH eq "x86_64"){
						$Insmod_Command = "$insmod $product_root/SPLX.module/splxmod.o splxmod_debug=0 splxmod_addr=0x$splxmod_addr splxmod_execve_addr=0x$splxmod_execve_addr splxmod_ret_addr=0x$splxmod_ret_addr splxmod_ia32_addr=0x$splxmod_ia32_addr splxmod_compat_do_execve_addr=0x$splxmod_compat_do_execve_addr";						
						}
						else 
						{
	                                         $Insmod_Command = "$insmod $product_root/SPLX.module/splxmod.o splxmod_debug=0 splxmod_addr=0x$splxmod_addr splxmod_execve_addr=0x$splxmod_execve_addr";
						}
#						print "\n";
#					        print $Insmod_Command;
#					        print "\n";
						$return_value=system "$Insmod_Command >/dev/null 2>&1";
						if ($return_value==0) {
							write_log "success: splx kernel module loaded.";
							echo_success;
							touch "/var/lock/subsys/splxmod";
						} else {
							write_log "error: executing [$Insmod_Command] failed";
							write_log "error: splx kernel module can't be loaded.";
							echo_failure;
							print "Unable to load Kernel module. Please contact Trend Micro support.\n";
							write_log "Kernel module can't be loaded.";
							$START_splxmod=1;
						}
				} elsif(! -e "$product_root/SPLX.module/splxmod-$kernel_version.$ARCH.o") {
	    	     			echo_notavaliable;
	                                print "\nError:   Kernel Hook Module (KHM) for this Linux kernel version is not\navailable. Check if the KHM for your  Linux kernel version is released\non the Trend Micro website at   \"http://downloadcenter.trendmicro.com/\nindex.php?prodid=20\".  Or, follow the instructions in the INSTALL file\nin \"/opt/TrendMicro/SProtectLinux/SPLX.module/src/module\" to build the\nKHM for your Linux kernel version.\n\n";
	         			write_log "Kernel module can't be loaded.";

	      		} else {
					write_log "error: /var/lock/subsys/splxmod present. KHM already loaded?";
				}
			}else
			{
				write_log "success: splx kernel module loaded.";
				echo_success;
			}

			# generate the splx device file
			if ( system("/sbin/lsmod | grep splxmod > /dev/null 2>&1") == 0) {
				write_log "step: creating device file.";
				if (-e "/dev/splxdev") {
					unlink "/dev/splxdev";
				}
				if (! open DEVICES, "/proc/devices") {
					write_log "ERROR: Cannot open /proc/devices.";
				}
				while (<DEVICES>) {
					if (/splxdev/) {
						($device_number)=split /\s/, $_,0;
					}
				}
				close DEVICES;

				if (defined($device_number)) {
					$return_value=system "$mknod --mode=640 /dev/splxdev c $device_number 0 > /dev/null 2>&1";
				} else {
					write_log "error: no such device. Make sure KHM has been loaded successfully.";
					if( -e "$product_root/SPLX.module/splxmod-$kernel_version.$ARCH.o")
					{
						$START_splxmod=1;
					}
				}

				if (defined($return_value)&&($return_value==0)) {
					write_log "success: device file created.";
				} else {
					write_log "error: device file can't be created.";
					print "Unable to create device file. Please contact Trend Micro support.\n";
					write_log "Device file can't be created.";
					if(-e "$product_root/SPLX.module/splxmod-$kernel_version.$ARCH.o" )
					{
						$START_splxmod=1;
					}
				}
			}

			# start vsapiapp
			print "Starting vsapiapp: ";
			write_log "step: starting vsapiapp service.";
			$check_pattern=0;
			chdir "$product_root/SPLX.vsapiapp";
			$check_pattern=system "./virus_type_finder > /dev/null 2>&1";
			if($check_pattern==0)
			{
				$return_value=0;
				%property=is_running "vsapiapp";
				if (!$property{"running"})
				{
					chdir "$product_root/SPLX.vsapiapp";
					$return_value=system "./splxmain -e -D > /dev/null 2>&1";
				}
				if ($return_value==0) {
					write_log "step: vsapiapp service started.";
					echo_success;
					touch "/var/lock/subsys/vsapiapp";
				} else {
					write_log "error: vsapiapp service can't be started.";
					echo_failure;
					print "Unable to start the Scan Engine (Vsapiapp) service. Please contact Trend Micro support.\n";
					write_log "Vsapiapp service can't be started.";
					$START_vsapiapp=1;
				}
			}
			else
			{
				write_log "error: vsapiapp service can't be started.";
				echo_failure;
				print "Real-time scan was unable to load the scan engine or pattern files. The scan engine or pattern files may be missing or corrupted. Please click \"Update Now\" in the Summary screen to download the latest components.\n";
				write_log "Vsapiapp service can't be started.";
				$START_vsapiapp=1;
			}
		} else {
			print "Loading splx kernel module: ";
			echo_failure;
			print "Starting vsapiapp: ";
			echo_failure;
    	
			write_log "Please make sure the product has been activated. KHM splxmod.o will not be loaded."
		}
		
		# enable jobs of crontab
        # add splxbif in /etc/cron.d/splxbif
        ########################################
        $BIF_schedule_command="30 2 * * 0 root /opt/TrendMicro/SProtectLinux/SPLX.util/TMBIF >/dev/null 2>&1\n";
        open(SPLXBIF, ">/etc/cron.d/splxbif");
        print SPLXBIF $BIF_schedule_command;
        close(SPLXBIF);
        ########################################
		system "$product_root/SPLX.vsapiapp/splxmain -c > /dev/null 2>&1";

		$START=$START_Entity+$START_vsapiapp+$START_splxmod;
		if ($START==0) {
			touch "/var/lock/subsys/splxcore";
			info_success("ServerProtect for Linux core started.\n");
			write_log "ServerProtect for Linux core started.";
		} else {
			info_failure( "Some errors were found while starting splxcore. See the system log for error description. The default system log file path is /var/log/messages.\n");
			write_log "ServerProtect for Linux core started with errors.";
			exit 1;
		}

		last SWITCH;
	};
		
	($ARGV[0] eq "restart") && do {
		system "$0 stop";
		system "$0 start";
		last SWITCH;
	};
	($ARGV[0] eq "status") && do {
		my $STATUS_Entity=0;
		my $STATUS_vsapiapp=0;
		my $STATUA_splxmod=0;
		$STATUA_splxmod=show_status "splxmod";
		$STATUS_vsapiapp=show_status "vsapiapp";
		$STATUS_Entity=show_status "entity";
		$STATUS=$STATUS_Entity+$STATUS_vsapiapp+$STATUS_splxmod;
		if ($STATUS==0) {
			exit 0;
		} else {
			exit 1;
		}
		last SWITCH;
	};
    print "Invalid usage of splxcore command.\n";
    print "Valid syntax is: '$0 {start|stop|restart|status}'.\n";
    print "Enter the correct splxcore command and try again.\n";
}

if ($debuglevel!=0) {
	close_log;
}

exit 0;
