function RunTool ($name, $params, $method='passthru', $extra=false) {
	global $CmdLineTool;
	if (!array_key_exists($name, $CmdLineTool)) 
		return false;
	$tool = &$CmdLineTool[$name];

	// set environment variables
	if (isset($tool['env'])) {
		$envvars = new Attributes($tool['env']);
		$envvars = $envvars->getAttribs();
		foreach ($envars as $var=>$val)
			putenv("$var=$val");
	}
	// get parameters
	$params = new Attributes($params);
	$varpattern = '(?<!\\\\)\$(\w+)';
	$p = preg_replace("/$varpattern/e", "(\$a=\$params->getAttrib('$1'))===false ? '$$1' : \$a", $tool['param']);
	$p = preg_replace("/\\{[^}]*?{$varpattern}[^}]*\\}/", '', $p); // remove {...$var...}
	$p = preg_replace("/\{([^}]*)\}/", '$1', $p);                  // remove braces from {...}
	$p = preg_replace("/$varpattern/", '', $p);                    // remove undefined $var
	$p = preg_replace("/\s+/", ' ', $p);
	$params = trim($p);
	//SHOW("$tool[path] $params");
	switch ($method) {
		case 'pipe': {
			$stdin = $extra;
			$ret = pipe_execute("$tool[path] $params", $stdin);
			break;
		}
		case 'pipe-callback': {
			$p = popen("$tool[path] $params", "r");
			if ($p) {
				while (!feof($p)) {
					$line = trim(fgets($p));
					call_user_func($extra, $line);
				}
				$ret = pclose($p);
			}
			else
				$ret = false;
			break;
		}
		case 'exec': {
			exec("$tool[path] $params", $ret);
			break;
		}
		default:
			passthru("$tool[path] $params");
	}

	// unset environmet variables
	if (is_array($envvars)) 
		foreach ($envvars as $var=>$val)
			putenv("$var="); 
	return $ret;
}
	function mimeTypeByFile () {
		if ($this->exists()) {
			$ret = pipe_execute("file -i -b -n ".$this->path());
			return $ret;
		}
		return false;
	}