From e998de4642143666eb6b42caed658d2a73ac7c60 Mon Sep 17 00:00:00 2001 From: minotaur01 Date: Tue, 30 Aug 2016 10:27:21 -0400 Subject: [PATCH] TFTP Service 1.0.7 (#1877) * TFTP Service v1.0.7 Fixed linux and windows run as service issues Fixed linux systemd service self install issues Modified windows service self install process * Revert "TFTP Service v1.0.7" This reverts commit 4418ca7a116f39da205478ed0a41402cb257da2f. * TFTP Service v1.0.7 Fixed linux and windows run as service issues Fixed linux systemd service self install issues Modified windows service self install process --- app/tftp/resources/systemd.service.template | 21 +- app/tftp/resources/tftpservice.class.php | 8 +- app/tftp/tftpservice.php | 251 +++++++++++++++----- 3 files changed, 212 insertions(+), 68 deletions(-) diff --git a/app/tftp/resources/systemd.service.template b/app/tftp/resources/systemd.service.template index ebe6459958..d207be0ac4 100644 --- a/app/tftp/resources/systemd.service.template +++ b/app/tftp/resources/systemd.service.template @@ -1,19 +1,26 @@ [Unit] -Description={$name} +Description={$fullname} After=syslog.target network.target {$database} Requires={$database} [Service] -User=www-data -Group=www-data -WorkingDirectory={$scriptfolder} Type=simple +PIDFile=/run/{$shortname}.pid +WorkingDirectory={$scriptfolder} StandardOutput=null StandardError=syslog -ExecStart=/usr/bin/php {$scriptname} +ExecStart=/usr/bin/php {$scriptpath} +ExecStop=/bin/kill $MAINPID PrivateTmp=true -InaccessibleDirectories=/home /root /boot /opt /mnt /media /etc /usr -ReadOnlyDirectories= +InaccessibleDirectories=/home /root /boot /opt /mnt /media +ReadOnlyDirectories=/etc /usr + +;Permissions +User=root +Group=daemon + +;Limits +LimitCORE=1 [Install] WantedBy=multi-user.target \ No newline at end of file diff --git a/app/tftp/resources/tftpservice.class.php b/app/tftp/resources/tftpservice.class.php index 9e5f925172..0aaa27f758 100644 --- a/app/tftp/resources/tftpservice.class.php +++ b/app/tftp/resources/tftpservice.class.php @@ -30,7 +30,8 @@ require_once 'tftpserver.class.php'; class tftpservice extends TFTPServer { - private $_debug=true; + private $_headless=true; + private $_debug=false; private $_dbtype; private $_dbhost; private $_dbport; @@ -42,6 +43,7 @@ class tftpservice extends TFTPServer function __construct($server_url, $config) { parent::__construct($server_url); + if (isset($config['headless'])) $this->_headless=$config['headless']; if (isset($config['debug'])) $this->_debug=$config['debug']; if (isset($config['db_type'])) $this->_dbtype=$config['db_type']; if (isset($config['db_host'])) $this->_dbhost=$config['db_host']; @@ -57,12 +59,14 @@ class tftpservice extends TFTPServer } private function log($client, $level, $message) { - if($level!='D'||$this->_debug) + if(!$this->_headless && ($level!='D' || $this->_debug)) { echo date("H:i:s") . " " . $level . " " . $client . " " . $message . "\n"; + } + } public function get($client, $filepath, $mode) diff --git a/app/tftp/tftpservice.php b/app/tftp/tftpservice.php index aef50f03f9..bdd4013fa5 100644 --- a/app/tftp/tftpservice.php +++ b/app/tftp/tftpservice.php @@ -46,44 +46,59 @@ function Service_Install() // check if we found the executable binary if (file_exists(PHP_BINARY)) { - exec('sc create '.$appname.' type=own binPath="'.PHP_BINARY.' '.$_SERVER["SCRIPT_FILENAME"].'" DisplayName="'.$appdesc.'" start=auto'); - die($appdesc.' was successfully installed.\n'); + win32_create_service( Array( + 'service' => $appname, + 'display' => $appdesc, + 'params' => __FILE__ . " --Service", + 'path' => PHP_BINARY + )); + + //exec('sc create '.$appname.' type=own binPath="'.PHP_BINARY.' '.$_SERVER["SCRIPT_FILENAME"].'" DisplayName="'.$appdesc.'" start=auto'); + die($appdesc." was successfully installed.\n"); } else { - die($appdesc.' could not be installed because the php executable was not found.\n'); + die($appdesc." could not be installed because the php executable was not found.\n"); } } else { - require_once __DIR__.'/../../resources/config.php'; + // load required files + require_once __DIR__.'/../../resources/config.php'; //required for database type // read template file - $template=file_get_contents('resources/systemd.service.template'); + $template=file_get_contents(dirname(__FILE__).'/resources/systemd.service.template'); - // service name - $template=str_replace('\{\$name\}',$appdesc,$template); + // service short name + $template=str_replace('{$shortname}',$appname,$template); + // service full name + $template=str_replace('{$fullname}',$appdesc,$template); // service dependencies - switch ($dbtype) { + switch ($db_type) { case 'pgsql': - $template=str_replace('\{\$database\}','postgresql.service',$template); + $template=str_replace('{$database}','postgresql.service',$template); break; case 'mysql': - $template=str_replace('\{\$database\}','mariadb.service',$template); + $template=str_replace('{$database}','mariadb.service',$template); break; default: - $template=str_replace('\{\$database\}','',$template); + $template=str_replace('{$database}','',$template); break; } + // script path + $template=str_replace('{$scriptpath}',__FILE__,$template); // script folder - $template=str_replace('\{\$scriptfolder\}',dirname(__FILE__),$template); - // script name - $template=str_replace('\{\$scriptname\}',basename(__FILE__),$template); + $template=str_replace('{$scriptfolder}',dirname(__FILE__),$template); + // script filename + $template=str_replace('{$scriptfilename}',basename(__FILE__),$template); // write service file - file_put_contents('/lib/systemd/system/'.$appname.'.service'); + file_put_contents('/lib/systemd/system/'.$appname.'.service', $template); + // reload systemd and enable service + exec('systemctl daemon-reload'); + exec('systemctl enable '.$appname); - die($appdesc.' was successfully installed.\n'); + die($appdesc." was successfully installed.\n"); } } @@ -95,34 +110,28 @@ function Service_Uninstall() // uninstall for specific os if (strpos(PHP_OS,"WIN") !== false) { - exec('sc delete "'.$appname.'"'); - die($appdesc.' was successfully uninstalled.\n'); + win32_delete_service($appname); + //exec('sc delete "'.$appname.'"'); + die($appdesc." was successfully uninstalled.\n"); } else { + // stop service and disable in systemd + exec('systemctl stop '.$appname); + exec('systemctl disable '.$appname); + // delete systemd service file unlink('/lib/systemd/system/'.$appname.'.service'); - die($appdesc.' was successfully uninstalled.\n'); + die($appdesc." was successfully uninstalled.\n"); } } -function Run() +function Service_Run() { global $appname; global $appdesc; global $pid; global $pidfile; - global $tftpservice_address; - global $tftpservice_port; - global $tftpservice_fileslocation; - - // required for php 4.3.0 - /* - declare(ticks = 1); - - function _process_term() { exit(0);} - function _process_output($buffer) { } - */ - + // check for existing process if (file_exists($pidfile)) { $pid = file_get_contents($pidfile); @@ -132,37 +141,37 @@ function Run() exec('tasklist -NH -FO TABLE -FI "PID eq '.$pid.'" 2>NUL', $data); foreach($data as $line) { - if (strpos($line,$pid) !== false) die($appdesc.' already running with process id '.$pid); + if (strpos($line,$pid) !== false) die($appdesc." already running with process id ".$pid); } + + Service_Windows_Run(); } else { - if (file_exists('/proc/'.$pid)) die($appdesc.' already running with process id'.$pid); + if (file_exists('/proc/'.$pid)) die($appdesc." already running with process id".$pid); + + Service_Linux_Run(); } } } - /* - // fork process - $pid = pcntl_fork(); - if ($pid < 0) - die("fusionpbx-tftpservice process fork failed\n"); - else if ($pid) // parent - die("fusionpbx-tftpservice process fork failed\n"); +} - posix_setsid(); - pcntl_signal(SIGTERM, "_process_term"); - pcntl_signal(SIGHUP, SIG_IGN); - // redirect normal output to null function - ob_start("_process_output"); - */ +function Service_Linux_Run() +{ + global $appname; + global $appdesc; + global $pid; + global $pidfile; + global $tftpservice_address; + global $tftpservice_port; + global $tftpservice_fileslocation; // write pid file file_put_contents($pidfile, getmypid()); // load required files require_once __DIR__.'/../../resources/config.php'; - require_once 'resources/tftpservice.class.php'; require_once 'resources/dbhelper.php'; // get service settings from database @@ -189,21 +198,145 @@ function Run() // destroy data unset($s); + // load required files + require_once 'resources/tftpservice.class.php'; + // start service - $server = new tftpservice("udp://$tftpservice_address:$tftpservice_port", array('db_type'=>$db_type,'db_host'=>$db_host, "db_port"=>$db_port, "db_name"=>$db_name, "db_username"=>$db_username, "db_password"=>$db_password, "files_location"=>$tftpservice_fileslocation)); - echo $appdesc.' has started.'; + $server = new tftpservice("udp://$tftpservice_address:$tftpservice_port", array("headless"=>true, "db_type"=>$db_type, "db_host"=>$db_host, "db_port"=>$db_port, "db_name"=>$db_name, "db_username"=>$db_username, "db_password"=>$db_password, "files_location"=>$tftpservice_fileslocation)); if(!$server->loop($error, $user)) die("$error\n"); - echo $appdesc.' has stopped.'; } -// Install System Service +function Service_Windows_Run() +{ + global $appname; + global $appdesc; + global $pid; + global $pidfile; + global $tftpservice_address; + global $tftpservice_port; + global $tftpservice_fileslocation; + + // write pid file + file_put_contents($pidfile, getmypid()); + + // load required files + require_once __DIR__.'/../../resources/config.php'; + require_once 'resources/dbhelper.php'; + + // get service settings from database + // connect to database + $db = database::connect($db_type,$db_host,$db_port,$db_name,$db_username,$db_password); + // get settings + $s = database::get_table($db,'v_default_settings',array('default_setting_subcategory','default_setting_value'),array('default_setting_subcategory','LIKE','tftp_service_%')); + // set local variables + foreach ($s as $i) { + switch ($i[0]) { + case 'tftp_service_address': + $tftpservice_address=$i[1]; + break; + case 'tftp_service_port': + $tftpservice_port=$i[1]; + break; + case 'tftp_service_fileslocation': + $tftpservice_fileslocation=$i[1]; + break; + } + } + // disconnect from database + unset($db); + // destroy data + unset($s); + + // load required files + require_once 'resources/tftpservice.class.php'; + + // start service + $server = new tftpservice("udp://$tftpservice_address:$tftpservice_port", array("headless"=>true, "db_type"=>$db_type, "db_host"=>$db_host, "db_port"=>$db_port, "db_name"=>$db_name, "db_username"=>$db_username, "db_password"=>$db_password, "files_location"=>$tftpservice_fileslocation)); + // signal running to service controller + win32_start_service_ctrl_dispatcher($appname); + win32_set_service_status(WIN32_SERVICE_RUNNING); + // execute run loop + if(!$server->loop($error, $user)) die("$error\n"); + // signal stopped to service controller + win32_set_service_status(WIN32_SERVICE_STOPPED); +} + +function Run() +{ + global $appname; + global $appdesc; + global $pid; + global $pidfile; + global $tftpservice_address; + global $tftpservice_port; + global $tftpservice_fileslocation; + + // check for existing process + if (file_exists($pidfile)) { + $pid = file_get_contents($pidfile); + if (is_numeric($pid)) { + if (strpos(PHP_OS,"WIN") !== false) + { + exec('tasklist -NH -FO TABLE -FI "PID eq '.$pid.'" 2>NUL', $data); + foreach($data as $line) + { + if (strpos($line,$pid) !== false) die($appdesc." already running with process id ".$pid); + } + } + else + { + if (file_exists('/proc/'.$pid)) die($appdesc." already running with process id".$pid); + } + } + } + + // write pid file + file_put_contents($pidfile, getmypid()); + + // load required files + require_once __DIR__.'/../../resources/config.php'; + require_once 'resources/dbhelper.php'; + + // get service settings from database + // connect to database + $db = database::connect($db_type,$db_host,$db_port,$db_name,$db_username,$db_password); + // get settings + $s = database::get_table($db,'v_default_settings',array('default_setting_subcategory','default_setting_value'),array('default_setting_subcategory','LIKE','tftp_service_%')); + // set local variables + foreach ($s as $i) { + switch ($i[0]) { + case 'tftp_service_address': + $tftpservice_address=$i[1]; + break; + case 'tftp_service_port': + $tftpservice_port=$i[1]; + break; + case 'tftp_service_fileslocation': + $tftpservice_fileslocation=$i[1]; + break; + } + } + // disconnect from database + unset($db); + // destroy data + unset($s); + + // load required files + require_once 'resources/tftpservice.class.php'; + + // start service + $server = new tftpservice("udp://$tftpservice_address:$tftpservice_port", array('db_type'=>$db_type,'db_host'=>$db_host, "db_port"=>$db_port, "db_name"=>$db_name, "db_username"=>$db_username, "db_password"=>$db_password, "files_location"=>$tftpservice_fileslocation)); + echo $appdesc." has started.\n"; + if(!$server->loop($error, $user)) die("$error\n"); + echo $appdesc." has stopped.\n"; +} + if(isset($_SERVER["argv"][1])&&$_SERVER["argv"][1]=="--InstallService") - Service_Install(); -// Uninstall System Service + Service_Install(); // Install System Service elseif(isset($_SERVER["argv"][1])&&$_SERVER["argv"][1]=="--UninstallService") - Service_Uninstall(); -// Run Service -else Run(); - - + Service_Uninstall(); // Uninstall System Service +elseif(isset($_SERVER["argv"][1])&&$_SERVER["argv"][1]=="--Service") + Service_Run(); // Run as a Service +else + Run(); // Run ?>