#!/usr/bin/php getMessage()); } if (0 < count($options[0])) { foreach ($options[0] as $option) { $option_switch = $option[0]; $option_value = $option[1]; switch ($option_switch) { // config file case 'c': case '--config': $GLOBALS['btds']['config_file'] = $option_value; // help default: case 'h': case '?': case '--help': // no action - default break; // list devices case 'l': case '--list': $GLOBALS['btds']['action'] = 'list'; break; // add device case 'a': case '--add': $GLOBALS['btds']['action'] = 'add'; $add_name = $option_value; $add_address = $options[1][0]; break; // remove device case 'r': case '--remove': $GLOBALS['btds']['action'] = 'remove'; $remove_device = $option_value; break; // foreground case 'f': case '--foreground': $GLOBALS['btds']['action'] = 'foreground'; break; // daemon case 'd': case '--daemon': $GLOBALS['btds']['action'] = 'daemon'; break; } // end switch option } // end foreach option } // end if options // parse config file $GLOBALS['btds']['config'] = parse_config_file($GLOBALS['btds']['config_file']); // determine hostname $GLOBALS['btds']['hostname'] = get_hostname(); // connect to db db_connect(); // perform proper action switch ($GLOBALS['btds']['action']) { // help default: Usage(); break; // list devices case 'list': list_devices(); break; // add device case 'add': add_device($add_name, $add_address); break; // remove device case 'remove': remove_device($remove_device); break; // foreground case 'foreground': $GLOBALS['btds']['devices'] = get_devices(); monitor_devices( $GLOBALS['btds']['hostname'], $GLOBALS['btds']['devices']); break; // daemon case 'daemon': daemonize(); db_connect(); $GLOBALS['btds']['devices'] = get_devices(); monitor_devices( $GLOBALS['btds']['hostname'], $GLOBALS['btds']['devices']); break; } // end switch option /** FUNCTIONS **/ function Usage($message = '', $exit_code = EXIT_STATUS_USAGE) { $error_message = null; if (!empty($message)) { $error_message = rtrim($message)."\n\n"; } // end if message $usage_message =<<< END == {$GLOBALS['btds']['progname']} v{$GLOBALS['btds']['version']} == {$_SERVER['argv'][0]} [-h|-?|--help] [-c|--config ] [-l|--list] [-a|--add
] [-r|--remove |
] [-f|--foreground] [-d|--daemon] END; fwrite(STDOUT, $error_message); fwrite(STDOUT, $usage_message); exit($exit_code); } // end function Usage() function parse_config_file($config_file) { if (!file_exists($config_file)) { Usage("Config File '$config_file' doesn't exist", EXIT_STATUS_CONFIG_ERROR); } // end if no file return simplexml_load_file($config_file); } // end function parse_config_file() function db_connect() { $GLOBALS['btds']['db_conn'] = mysql_connect( $GLOBALS['btds']['config']->db->hostname, $GLOBALS['btds']['config']->db->username, $GLOBALS['btds']['config']->db->password, true) or die ("DBERROR: Couldn't connect to server - ".mysql_error()); mysql_select_db( $GLOBALS['btds']['config']->db->database, $GLOBALS['btds']['db_conn']) or die ("DBERROR: Couldn't select database - ".mysql_error()); return $GLOBALS['btds']['db_conn']; } // end function db_connect() /** * Quotes and escapes the specified value * * @param string $value * @return string */ function db_quote($value) { $needs_quoted = !is_int($value); $value = mysql_real_escape_string($value, $GLOBALS['btds']['db_conn']); if ($needs_quoted) { $value = '\'' . $value . '\''; } // end if needs quoted return $value; } // end function db_quote() function get_hostname() { return preg_replace('/^(\w+)\..*$/', '$1', $_ENV['HOSTNAME']); } // end function get_hostname() function address2int($address) { $return_val = null; // remove colons from address // 00:0F:DE:8B:58:8A => 000FDE8B588A $address = str_replace(':', '', $address); // validate address if (12 != strlen($address)) { return $return_val; } // end if not 12 characters $return_val = hexdec($address); return $return_val; } // end function address2int() function int2address($address) { $return_val = null; $address = (double) $address; if (!is_numeric($address) && 0 > $address) { return $return_val; } // end if not number or negative // convert the integer address to hex string $return_val = dechex($address); // make the string 12 characters $return_val = str_pad($return_val, 12, '0', STR_PAD_LEFT); // uppercase the hex $return_val = strtoupper($return_val); // insert the colons $return_val = preg_replace('/^(..)(..)(..)(..)(..)(..)$/', '$1:$2:$3:$4:$5:$6', $return_val); return $return_val; } // end function int2address() function get_devices() { $return_array = array(); $device_query = "SELECT `name`, `address` FROM `btdev_list`"; $result = mysql_query($device_query, $GLOBALS['btds']['db_conn']) or die ("DBERROR: Couldn't perform query - ".mysql_error()); while ($row = mysql_fetch_array($result)) { $return_array[$row['name']] = int2address($row['address']); } // end while rows return $return_array; } // end function get_devices() function list_devices() { $device_array = get_devices(); if (0 == count($device_array)) { fwrite(STDOUT, "No Devices\n"); } // end if no devices foreach ($device_array as $device_name => $device_address) { fwrite(STDOUT, $device_name . ' ' . $device_address . "\n"); } // end foreach device } // end function list_devices() function add_device($add_name, $add_address) { // validate name if (0 > strlen($add_name)) { Usage("Name must be set ($add_name)"); } // end if no name $add_address_int = address2int($add_address); if (!is_numeric($add_address_int) || 0 > $add_address_int) { Usage("Address must be set ($add_address)"); } // end if not numeric address $add_query = 'REPLACE INTO `btdev_list` ' . 'SET `name` = \'' . mysql_real_escape_string($add_name) . '\', ' . '`address` = \'' . $add_address_int . '\''; fwrite(STDOUT, "Adding '$add_name' with address '$add_address'\n"); mysql_query($add_query, $GLOBALS['btds']['db_conn']) or die ("DBERROR: Couldn't perform query - ".mysql_error()); } // end function add_device( function remove_device($device) { $remove_type = 'name'; // check if $device is a name or an address $device_as_address = address2int($device); if (is_numeric($device_as_address) && 0 < $device_as_address) { $remove_type = 'address'; $device = $device_as_address; } // end if device address // remove the proper device $remove_query = 'DELETE FROM `btdev_list` ' . 'WHERE `' . $remove_type . '` = \'' . mysql_real_escape_string($device) . '\''; mysql_query($remove_query, $GLOBALS['btds']['db_conn']) or die ("DBERROR: Couldn't perform query - ".mysql_error()); } // end function remove_device() /** * Daemonizes script */ function daemonize() { if (pcntl_fork()) { exit(EXIT_STATUS_NORMAL); } posix_setsid(); chdir('/'); umask(0); fclose(STDIN); fclose(STDOUT); fclose(STDERR); // STDIN = fopen('/dev/null'); // STDOUT = fopen('/dev/null'); // STDERR = fopen('/dev/null'); } // end function daemonize() /** * Monitors the various devices status * * @param string $hostname local host name * @param array $device_list */ function monitor_devices($hostname, $device_list) { // loop forver while (true) { foreach ($device_list as $device_name => $device_address) { # fwrite(STDOUT, "Checking $device_name ($device_address)\n"); $device_status = poll_device($device_address); # fwrite(STDOUT, " Device status: " . ($device_status ? 'seen' : 'not seen') . "\n"); // log device status log_device_seen($hostname, $device_name); } //end foreach device sleep(DEVICE_WAIT_TIME); } // end never end } // end function monitor_devices() /** * checks if the device can be seen * * @param string $device_address * @return boolean whether device could be seen */ function poll_device($device_address) { $return_val = false; // check if the device can be seen $hcitool = escapeshellcmd($GLOBALS['btds']['config']->hcitool); $device_address = escapeshellarg($device_address); $device_check_cmd = "$hcitool name $device_address"; $device_name = `$device_check_cmd 2> /dev/null`; if (!empty($device_name)) { $return_val = true; } // end if device name return $return_val; } // end function poll_device() /** * Logs that the specified device was seen * * @param string $hostname * @param string $device_name */ function log_device_seen($hostname, $device_name) { $query = 'REPLACE INTO `btdev_status` SET ' . '`dev_name` = ' . db_quote($device_name) . ', ' . '`host` = ' . db_quote($hostname) . ', ' . '`last_seen` = NOW()'; mysql_query($query, $GLOBALS['btds']['db_conn']) or die ("DBERROR: Couldn't perform query - ".mysql_error()); } // end function log_device_status()