This code was written and posted by davem at the PHP docs site, socket functions. Have not yet run it, but looks good to me and WebProfessor thinks so as well. UAYOR - but I'll be posting my experience with this sort of thing as I go.
<?php
/*
PHP forked daemon
Standalone PHP binary must be compiled with --enable-sockets and --enable-pcntl
Dave M. -2002
Online Services USA
*/
function sig_handler($signo) {
switch($signo) {
case SIGTERM:
// handle shutdown tasks
exit;
break;
case SIGHUP:
// handle restart tasks
break;
case SIGUSR1:
print "Caught SIGUSR1...\n";
break;
case SIGCHLD:
while( pcntl_waitpid(-1,$status,WNOHANG)>0 ) {
}
break;
case SIGINT:
exit;
default:
// not implemented yet...
break;
}
}
function interact($sock) {
// Custom code goes here... e.g: socket_read() socket_write()...
}
function become_daemon() {
$child = pcntl_fork();
if($child) {
exit; // kill parent
}
posix_setsid(); // become session leader
chdir("/");
umask(0); // clear umask
return posix_getpid();
}
function open_pid_file($file) {
if(file_exists($file)) {
$fp = fopen($file,"r");
$pid = fgets($fp,1024);
fclose($fp);
if(posix_kill($pid,0)) {
print "Server already running with PID: $pid\n";
exit;
}
print "Removing PID file for defunct server process $pid\n";
if(!unlink($file)) {
print "Cannot unlink PID file $file\n";
exit;
}
}
if($fp = fopen($file,"w")) {
return $fp;
} else {
print "Unable to open PID file $file for writing...\n";
exit;
}
}
function change_identity($uid,$gid) {
global $pid_file;
if(!posix_setgid($gid)) {
print "Unable to setgid to $gid!\n";
unlink($pid_file);
exit;
}
if(!posix_setuid($uid)) {
print "Unable to setuid to $uid!\n";
unlink($pid_file);
exit;
}
}
error_reporting (4);
set_time_limit (0);
ob_implicit_flush ();
$pid_file = '/tmp/php_daemon.pid';
$underpriv_uid = '99'; // uid 99 == user nobody, at least on my system.
$underpriv_gid = '99';
$port = 10000;
$address = 0; // 0 binds to all addresses, may not work on fbsd
$quit = 0;
pcntl_signal(SIGCHLD, "sig_handler");
pcntl_signal(SIGTERM, "sig_handler");
pcntl_signal(SIGINT, "sig_handler");
$fh = open_pid_file($pid_file);
if (($sock = socket_create (AF_INET, SOCK_STREAM, 0)) < 0) {
print "socket_create() failed: reason: " . socket_strerror ($sock) . "\n";
}
if (($ret = socket_bind ($sock, $address, $port)) < 0) {
print "socket_bind() failed: reason: " . socket_strerror ($ret) . "\n";
}
if (($ret = socket_listen ($sock, 0)) < 0) {
print "socket_listen() failed: reason: " . socket_strerror ($ret) . "\n";
}
change_identity($underpriv_uid,$underpriv_gid);
print "Server ready. Waiting for connections.....\n";
$pid = become_daemon();
fputs($fh,$pid);
fclose($fh);
while(!$quit) {
if (($connection = socket_accept($sock)) < 0) {
next;
}
if( ($child = pcntl_fork()) == -1 ) {
print "Could not fork!!\n";
print "Dying...\n";
$quit++;
}
elseif($child == 0) {
socket_close($sock);
interact($connection);
exit;
}
socket_close($connection);
}
if(posix_getpid() == $pid) {
unlink($pid_file);
}
?>