3 * PEAR, the PHP Extension and Application Repository
5 * Command line interface
11 * @author Stig Bakken <ssb@php.net>
12 * @author Tomas V.V.Cox <cox@idecnet.com>
13 * @copyright 1997-2009 The Authors
14 * @license http://opensource.org/licenses/bsd-license.php New BSD License
15 * @link http://pear.php.net/package/PEAR
19 if (!defined('PEAR_RUNTYPE')) {
20 // this is defined in peclcmd.php as 'pecl'
21 define('PEAR_RUNTYPE', 'pear');
23 define('PEAR_IGNORE_BACKTRACE', 1);
27 //the space is needed for windows include paths with trailing backslash
28 // http://pear.php.net/bugs/bug.php?id=19482
29 if ('@include_path@ ' != '@'.'include_path'.'@ ') {
30 ini_set('include_path', trim('@include_path@ '). PATH_SEPARATOR . get_include_path());
33 // this is a raw, uninstalled pear, either a cvs checkout, or php distro
36 @ini_set('allow_url_fopen', true);
38 ob_implicit_flush(true);
39 @ini_set('track_errors', true);
40 @ini_set('html_errors', false);
41 $_PEAR_PHPDIR = '#$%^&*';
42 set_error_handler('error_handler');
44 $pear_package_version = "@pear_version@";
46 require_once 'PEAR.php';
47 require_once 'PEAR/Frontend.php';
48 require_once 'PEAR/Config.php';
49 require_once 'PEAR/Command.php';
50 require_once 'Console/Getopt.php';
53 PEAR_Command::setFrontendType('CLI');
54 $all_commands = PEAR_Command::getCommands();
56 // remove this next part when we stop supporting that crap-ass PHP 4.2
57 if (!isset($_SERVER['argv']) && !isset($argv) && !isset($HTTP_SERVER_VARS['argv'])) {
58 echo 'ERROR: either use the CLI php executable, ' .
59 'or set register_argc_argv=On in php.ini';
63 $argv = Console_Getopt::readPHPArgv();
64 // fix CGI sapi oddity - the -- in pear.bat/pear is not removed
65 if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
67 $argv = array_values($argv);
69 $progname = PEAR_RUNTYPE;
71 $options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
72 if (PEAR::isError($options)) {
79 if ($progname == 'gpear' || $progname == 'pear-gtk') {
82 foreach ($opts as $opt) {
89 $pear_user_config = '';
90 $pear_system_config = '';
91 $store_user_config = false;
92 $store_system_config = false;
95 foreach ($opts as $opt) {
98 $pear_user_config = $opt[1];
101 $pear_system_config = $opt[1];
106 PEAR_Command::setFrontendType($fetype);
107 $ui = &PEAR_Command::getFrontendObject();
108 $config = &PEAR_Config::singleton($pear_user_config, $pear_system_config);
110 if (PEAR::isError($config)) {
112 if ($pear_user_config !== false) {
113 $_file .= $pear_user_config;
115 if ($pear_system_config !== false) {
116 $_file .= '/' . $pear_system_config;
119 $_file = 'The default config file';
121 $config->getMessage();
122 $ui->outputData("ERROR: $_file is not a valid config file or is corrupted.");
123 // We stop, we have no idea where we are :)
127 // this is used in the error handler to retrieve a relative path
128 $_PEAR_PHPDIR = $config->get('php_dir');
129 $ui->setConfig($config);
130 PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));
132 $verbose = $config->get("verbose");
136 if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) {
138 foreach ($opts as $opt) {
139 if ($opt[0] == 'd' || $opt[0] == 'D') {
140 // the user knows what they are doing, and are setting config values
145 // no prior runs, try to install PEAR
146 $parent = dirname(__FILE__);
147 if (strpos($parent, 'scripts')) {
148 $grandparent = dirname($parent);
149 $packagexml = $grandparent . DIRECTORY_SEPARATOR . 'package2.xml';
150 $pearbase = $grandparent;
152 $packagexml = $parent . DIRECTORY_SEPARATOR . 'package2.xml';
155 if (file_exists($packagexml)) {
160 $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php');
161 $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data');
162 $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs');
163 $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests');
166 $pearbase . DIRECTORY_SEPARATOR . 'extensions'
168 $config->set('bin_dir', $pearbase);
169 $config->mergeConfigFile($pearbase . 'pear.ini', false);
171 $config->set('auto_discover', 1);
176 foreach ($opts as $opt) {
177 $param = !empty($opt[1]) ? $opt[1] : true;
180 if ($param === true) {
182 'Invalid usage of "-d" option, expected -d config_value=value, ' .
183 'received "-d"' . "\n"
186 $possible = explode('=', $param);
187 if (count($possible) != 2) {
189 'Invalid usage of "-d" option, expected ' .
190 '-d config_value=value, received "' . $param . '"' . "\n"
193 list($key, $value) = explode('=', $param);
194 $config->set($key, $value, 'user');
197 if ($param === true) {
199 'Invalid usage of "-d" option, expected ' .
200 '-d config_value=value, received "-d"' . "\n"
203 $possible = explode('=', $param);
204 if (count($possible) != 2) {
206 'Invalid usage of "-d" option, expected ' .
207 '-d config_value=value, received "' . $param . '"' . "\n"
210 list($key, $value) = explode('=', $param);
211 $config->set($key, $value, 'system');
214 $store_user_config = true;
217 $store_system_config = true;
220 $config->remove($param, 'user');
223 $config->set('verbose', $config->get('verbose') + 1);
226 $config->set('verbose', $config->get('verbose') - 1);
229 usage(null, 'version');
234 // all non pear params goes to the command
235 $cmdopts[$opt[0]] = $param;
240 if ($store_system_config) {
241 $config->store('system');
244 if ($store_user_config) {
245 $config->store('user');
248 $command = (isset($options[1][0])) ? $options[1][0] : null;
249 if (empty($command) && ($store_user_config || $store_system_config)) {
253 if ($fetype == 'Gtk2') {
254 if (!$config->validConfiguration()) {
256 "CRITICAL ERROR: no existing valid configuration files found in " .
257 "files '$pear_user_config' or '$pear_system_config', " .
258 "please copy an existing configuration file to one of these " .
259 "locations, or use the -c and -s options to create one"
265 if ($command == 'help') {
266 usage(null, isset($options[1][1]) ? $options[1][1] : null);
269 if (!$config->validConfiguration()) {
271 "CRITICAL ERROR: no existing valid configuration files found " .
272 "in files '$pear_user_config' or '$pear_system_config', " .
273 "please copy an existing configuration file to one of " .
274 "these locations, or use the -c and -s options to create one"
278 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
279 $cmd = PEAR_Command::factory($command, $config);
280 PEAR::popErrorHandling();
281 if (PEAR::isError($cmd)) {
282 usage(null, isset($options[1][0]) ? $options[1][0] : null);
285 $short_args = $long_args = null;
286 PEAR_Command::getGetoptArgs($command, $short_args, $long_args);
287 array_shift($options[1]);
288 $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args);
290 if (PEAR::isError($tmp)) {
294 list($tmpopt, $params) = $tmp;
296 foreach ($tmpopt as $foo => $tmp2) {
297 list($opt, $value) = $tmp2;
298 if ($value === null) {
299 $value = true; // options without args
302 if (strlen($opt) == 1) {
303 $cmdoptions = $cmd->getOptions($command);
304 foreach ($cmdoptions as $o => $d) {
305 if (isset($d['shortopt']) && $d['shortopt'] == $opt) {
310 if (substr($opt, 0, 2) == '--') {
311 $opts[substr($opt, 2)] = $value;
316 $ok = $cmd->run($command, $opts, $params);
318 PEAR::raiseError("unknown command `$command'");
321 if (PEAR::isError($ok)) {
322 PEAR::setErrorHandling(
323 PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")
325 PEAR::raiseError($ok);
333 * Display usage information
335 * @param mixed $error Optional error message
336 * @param mixed $helpsubject Optional subject/command to display help for
340 function usage($error = null, $helpsubject = null)
342 global $progname, $all_commands;
343 $stdout = fopen('php://stdout', 'w');
344 if (PEAR::isError($error)) {
345 fputs($stdout, $error->getMessage() . "\n");
346 } elseif ($error !== null) {
347 fputs($stdout, "$error\n");
350 if ($helpsubject != null) {
351 $put = cmdHelp($helpsubject);
353 $put = "Commands:\n";
354 $maxlen = max(array_map("strlen", $all_commands));
355 $formatstr = "%-{$maxlen}s %s\n";
356 ksort($all_commands);
357 foreach ($all_commands as $cmd => $class) {
358 $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd));
361 "Usage: $progname [options] command [command-options] <parameters>\n".
362 "Type \"$progname help options\" to list all options.\n".
363 "Type \"$progname help shortcuts\" to list all command shortcuts.\n".
364 "Type \"$progname help version\" or ".
365 "\"$progname version\" to list version information.\n".
366 "Type \"$progname help <command>\" to get the help ".
367 "for the specified command.";
369 fputs($stdout, "$put\n");
372 if ($error === null) {
379 * Return help string for specified command
381 * @param string $command Command to return help for
385 function cmdHelp($command)
387 global $progname, $all_commands, $config;
388 if ($command == "options") {
391 " -v increase verbosity level (default 1)\n".
392 " -q be quiet, decrease verbosity level\n".
393 " -c file find user configuration in `file'\n".
394 " -C file find system configuration in `file'\n".
395 " -d foo=bar set user config variable `foo' to `bar'\n".
396 " -D foo=bar set system config variable `foo' to `bar'\n".
397 " -G start in graphical (Gtk) mode\n".
398 " -s store user configuration\n".
399 " -S store system configuration\n".
400 " -u foo unset `foo' in the user configuration\n".
401 " -h, -? display help/usage (this message)\n".
402 " -V version information\n";
403 } elseif ($command == "shortcuts") {
404 $sc = PEAR_Command::getShortcuts();
405 $ret = "Shortcuts:\n";
406 foreach ($sc as $s => $c) {
407 $ret .= sprintf(" %-8s %s\n", $s, $c);
411 } elseif ($command == "version") {
412 return "PEAR Version: ".$GLOBALS['pear_package_version'].
413 "\nPHP Version: ".phpversion().
414 "\nZend Engine Version: ".zend_version().
415 "\nRunning on: ".php_uname();
417 } elseif ($help = PEAR_Command::getHelp($command)) {
418 if (is_string($help)) {
419 return "$progname $command [options] $help\n";
422 if ($help[1] === null) {
423 return "$progname $command $help[0]";
426 return "$progname $command [options] $help[0]\n$help[1]";
429 return "Command '$command' is not valid, try '$progname help'";
437 * @param mixed $errno Error number
438 * @param mixed $errmsg Message
439 * @param mixed $file Filename
440 * @param mixed $line Line number
441 * @param mixed $vars Variables
446 function error_handler($errno, $errmsg, $file, $line, $vars)
448 if ($errno & E_STRICT
449 || $errno & E_DEPRECATED
450 || !error_reporting()
452 if ($errno & E_STRICT) {
455 if ($errno & E_DEPRECATED) {
456 return; // E_DEPRECATED
458 if (!error_reporting() && isset($GLOBALS['config']) && $GLOBALS['config']->get('verbose') < 4) {
459 return false; // @silenced error, show all if debug is high enough
463 E_DEPRECATED => 'Deprecated Warning',
465 E_WARNING => "Warning",
466 E_PARSE => "Parsing Error",
467 E_STRICT => 'Strict Warning',
468 E_NOTICE => "Notice",
469 E_CORE_ERROR => "Core Error",
470 E_CORE_WARNING => "Core Warning",
471 E_COMPILE_ERROR => "Compile Error",
472 E_COMPILE_WARNING => "Compile Warning",
473 E_USER_ERROR => "User Error",
474 E_USER_WARNING => "User Warning",
475 E_USER_NOTICE => "User Notice"
477 $prefix = $errortype[$errno];
478 global $_PEAR_PHPDIR;
479 if (stristr($file, $_PEAR_PHPDIR)) {
480 $file = substr($file, strlen($_PEAR_PHPDIR) + 1);
482 $file = basename($file);
484 print "\n$prefix: $errmsg in $file on line $line\n";
493 * indent-tabs-mode: nil