Updated exit codes as constant values

Re-allocated exit status codes according to three references, which follow:

BSD sysexits.h:http://www.gsp.com/cgi-bin/man.cgi?section=3&topic=sysexits
GNU recomendations:http://www.gnu.org/software/libc/manual/html_node/Exit-Status.html
Bash scripting:http://tldp.org/LDP/abs/html/exitcodes.html

The GNU recommendations stem from and expand upon the standard C/C++ library (stdlibc)
definitions, while also suggesting some best-practice conventions which happen to prevent
exit status code collisions with bash, and probably other shells.

The re-allocated codes are now mapped to constant values, set in *application/config/constants.php*,
and used throughout the CodeIgniter core.  They would additionally be used in *index.php*,
but the constants file hasn't been loaded at that point, so the integer values are used
instead, and a comment follows each such use with amplifying information on why that
particular value was selected.

Finally, the errors documentation has been updated accordingly.

Signed-off-by: Daniel Hunsaker <danhunsaker@gmail.com>
diff --git a/application/config/constants.php b/application/config/constants.php
index 58264ed..32a7159 100644
--- a/application/config/constants.php
+++ b/application/config/constants.php
@@ -73,6 +73,116 @@
 */
 define('SHOW_DEBUG_BACKTRACE', TRUE);
 
+/*
+|--------------------------------------------------------------------------
+| Exit Status Codes
+|--------------------------------------------------------------------------
+|
+| Used to indicate the conditions under which the script is exit()ing.
+| While there is no universal standard for error codes, there are some
+| broad conventions.  Three such conventions are presented below, for
+| those who wish to make use of them.  The CodeIgniter defaults were 
+| chosen for the least overlap with these conventions, while still
+| leaving room for others to be defined in future versions and user
+| applications.  The CodeIgniter values are defined last so you can 
+| set them to values used by any of the other conventions, and do so 
+| by name instead of value.
+|
+*/
+
+/*
+ * standard C/C++ library (stdlibc):
+ */
+/*
+define('LIBC_EXIT_SUCCESS', 0);
+define('LIBC_EXIT_FAILURE', 1); // generic errors
+*/
+
+/* 
+ * BSD sysexits.h 
+ */
+/*
+define('SYS_EX_OK', 0); // successful termination
+define('SYS_EX_USAGE', 64); // command line usage error
+define('SYS_EX_DATAERR', 65); // data format error
+define('SYS_EX_NOINPUT', 66); // cannot open input
+define('SYS_EX_NOUSER', 67); // specified user unknown
+define('SYS_EX_NOHOST', 68); // specified host name unknown
+define('SYS_EX_UNAVAILABLE', 69); // service unavailable
+define('SYS_EX_SOFTWARE', 70); // internal software error
+define('SYS_EX_OSERR', 71); // system error (e.g., can't fork)
+define('SYS_EX_OSFILE', 72); // critical OS file missing
+define('SYS_EX_CANTCREAT', 73); // can't create (user) output file
+define('SYS_EX_IOERR', 74); // input/output error
+define('SYS_EX_TEMPFAIL', 75); // temporary failure; user is invited to retry
+define('SYS_EX_PROTOCOL', 76); // remote error in protocol
+define('SYS_EX_NOPERM', 77); // permission denied
+define('SYS_EX_CONFIG', 78); // configuration error
+*/
+
+/*
+ * Bash scripting 
+ */
+/*
+define('BASH_EXIT_SUCCESS', 0);
+define('BASH_EXIT_ERROR', 1);
+define('BASH_EXIT_BUILTIN_MISUSE', 2);
+define('BASH_EXIT_CANT_EXEC', 126);
+define('BASH_EXIT_CMD_NOT_FOUND', 127);
+define('BASH_EXIT_INVALID_EXIT', 128);
+define('BASH_EXIT_SIG_HUP', 129);
+define('BASH_EXIT_SIG_INT', 130);
+define('BASH_EXIT_SIG_QUIT', 131);
+define('BASH_EXIT_SIG_ILL', 132);
+define('BASH_EXIT_SIG_TRAP', 133);
+define('BASH_EXIT_SIG_ABRT', 134);
+define('BASH_EXIT_SIG_BUS', 135);
+define('BASH_EXIT_SIG_FPE', 136);
+define('BASH_EXIT_SIG_KILL', 137);
+define('BASH_EXIT_SIG_USR1', 138);
+define('BASH_EXIT_SIG_SEGV', 139);
+define('BASH_EXIT_SIG_USR2', 140);
+define('BASH_EXIT_SIG_PIPE', 141);
+define('BASH_EXIT_SIG_ALRM', 142);
+define('BASH_EXIT_SIG_TERM', 143);
+define('BASH_EXIT_SIG_STKFLT', 144);
+define('BASH_EXIT_SIG_CHLD', 145);
+define('BASH_EXIT_SIG_CONT', 146);
+define('BASH_EXIT_SIG_STOP', 147);
+define('BASH_EXIT_SIG_TSTP', 148);
+define('BASH_EXIT_SIG_TTIN', 149);
+define('BASH_EXIT_SIG_TTOU', 150);
+define('BASH_EXIT_SIG_URG', 151);
+define('BASH_EXIT_SIG_XCPU', 152);
+define('BASH_EXIT_SIG_XFSZ', 153);
+define('BASH_EXIT_SIG_VTALRM', 154);
+define('BASH_EXIT_SIG_PROF', 155);
+define('BASH_EXIT_SIG_WINCH', 156);
+define('BASH_EXIT_SIG_IO', 157);
+define('BASH_EXIT_SIG_PWR', 158);
+define('BASH_EXIT_SIG_SYS', 159);
+*/
+/*
+ * BASH_EXIT_OUTOFRANGE would be 255, and mean an exit status code beyond 
+ * the range of 0-255 was given.  However, this code CANNOT BE USED IN PHP,
+ * so it isn't actually defined, even in a comment.
+ */
+
+/*
+ * CodeIgniter defaults
+ */
+define('EXIT_SUCCESS', 0); // no errors
+define('EXIT_FAILURE', 1); // generic error
+define('EXIT_CONFIG', 3); // configuration error
+define('EXIT_404', 4); // file not found; convenience value
+define('EXIT_UNK_FILE', 4); // file not found
+define('EXIT_UNK_CLASS', 5); // unknown class
+define('EXIT_UNK_MEMBER', 6); // unknown class member
+define('EXIT_USER_INPUT', 7); // invalid user input
+define('EXIT_DATABASE', 8); // database error
+define('EXIT__AUTO_MIN', 9); // lowest automatically-assigned error code
+define('EXIT__AUTO_MAX', 125); // highest automatically-assigned error code
+ 
 
 /* End of file constants.php */
 /* Location: ./application/config/constants.php */
\ No newline at end of file
diff --git a/index.php b/index.php
index be09457..a52a021 100755
--- a/index.php
+++ b/index.php
@@ -67,7 +67,8 @@
 
 	default:
 		header('HTTP/1.1 503 Service Unavailable.', TRUE, 503);
-		exit('The application environment is not set correctly.');
+		echo 'The application environment is not set correctly.';
+		exit(1); // EXIT_* constants not yet defined; 1 is EXIT_FAILURE, a generic error.
 }
 
 /*
@@ -190,7 +191,8 @@
 	if ( ! is_dir($system_path))
 	{
 		header('HTTP/1.1 503 Service Unavailable.', TRUE, 503);
-		exit('Your system folder path does not appear to be set correctly. Please open the following file and correct this: '.pathinfo(__FILE__, PATHINFO_BASENAME));
+		echo 'Your system folder path does not appear to be set correctly. Please open the following file and correct this: '.pathinfo(__FILE__, PATHINFO_BASENAME);
+		exit(3); // EXIT_* constants not yet defined; 3 is EXIT_CONFIG.
 	}
 
 /*
@@ -225,7 +227,8 @@
 		if ( ! is_dir(BASEPATH.$application_folder.'/'))
 		{
 			header('HTTP/1.1 503 Service Unavailable.', TRUE, 503);
-			exit('Your application folder path does not appear to be set correctly. Please open the following file and correct this: '.SELF);
+			echo 'Your application folder path does not appear to be set correctly. Please open the following file and correct this: '.SELF;
+			exit(3); // EXIT_* constants not yet defined; 3 is EXIT_CONFIG.
 		}
 
 		define('APPPATH', BASEPATH.$application_folder.'/');
@@ -241,7 +244,8 @@
 		elseif ( ! is_dir(APPPATH.'views/'))
 		{
 			header('HTTP/1.1 503 Service Unavailable.', TRUE, 503);
-			exit('Your view folder path does not appear to be set correctly. Please open the following file and correct this: '.SELF);
+			echo 'Your view folder path does not appear to be set correctly. Please open the following file and correct this: '.SELF;
+			exit(3); // EXIT_* constants not yet defined; 3 is EXIT_CONFIG.
 		}
 		else
 		{
diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php
index 5a872ef..8f5271a 100644
--- a/system/core/CodeIgniter.php
+++ b/system/core/CodeIgniter.php
@@ -188,7 +188,7 @@
 	if ($EXT->call_hook('cache_override') === FALSE
 		&& $OUT->_display_cache($CFG, $URI) === TRUE)
 	{
-		exit(0);
+		exit(EXIT_SUCCESS);
 	}
 
 /*
diff --git a/system/core/Common.php b/system/core/Common.php
index 3cd97dc..479f0da 100644
--- a/system/core/Common.php
+++ b/system/core/Common.php
@@ -177,7 +177,7 @@
 			// self-referencing loop with the Exceptions class
 			set_status_header(503);
 			echo 'Unable to locate the specified class: '.$class.'.php';
-			exit(2);
+			exit(EXIT_UNK_CLASS);
 		}
 
 		// Keep track of what we just loaded
@@ -251,7 +251,7 @@
 		{
 			set_status_header(503);
 			echo 'The configuration file does not exist.';
-			exit(1);
+			exit(EXIT_CONFIG);
 		}
 
 		// Does the $config array exist in the file?
@@ -259,7 +259,7 @@
 		{
 			set_status_header(503);
 			echo 'Your config file does not appear to be formatted correctly.';
-			exit(1);
+			exit(EXIT_CONFIG);
 		}
 
 		// Are any values being dynamically replaced?
@@ -374,12 +374,16 @@
 		$status_code = abs($status_code);
 		if ($status_code < 100)
 		{
-			$exit_status = $status_code + 28;
+			$exit_status = $status_code + EXIT__AUTO_MIN;
+			if ($exit_status > EXIT__AUTO_MAX)
+			{
+				$exit_status = EXIT_FAILURE;
+			}
 			$status_code = 500;
 		}
 		else
 		{
-			$exit_status = 27;
+			$exit_status = EXIT_FAILURE;
 		}
 		
 		$_error =& load_class('Exceptions', 'core');
@@ -407,7 +411,7 @@
 	{
 		$_error =& load_class('Exceptions', 'core');
 		$_error->show_404($page, $log_error);
-		exit(4);
+		exit(EXIT_UNK_FILE);
 	}
 }
 
diff --git a/system/core/Exceptions.php b/system/core/Exceptions.php
index f799d60..423387f 100644
--- a/system/core/Exceptions.php
+++ b/system/core/Exceptions.php
@@ -117,7 +117,7 @@
 		}
 
 		echo $this->show_error($heading, $message, 'error_404', 404);
-		exit(4);
+		exit(EXIT_UNK_FILE);
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/core/Input.php b/system/core/Input.php
index 904f4d6..8d491e0 100644
--- a/system/core/Input.php
+++ b/system/core/Input.php
@@ -746,7 +746,7 @@
 		{
 			set_status_header(503);
 			echo 'Disallowed Key Characters.';
-			exit(6);
+			exit(EXIT_USER_INPUT);
 		}
 
 		// Clean UTF-8 if supported
diff --git a/system/core/Output.php b/system/core/Output.php
index d4abe87..1025703 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -696,7 +696,7 @@
 		if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $last_modified <= strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']))
 		{
 			$this->set_status_header(304);
-			exit(0);
+			exit(EXIT_SUCCESS);
 		}
 		else
 		{
diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php
index 6ae1d52..18dbbc7 100644
--- a/system/database/DB_driver.php
+++ b/system/database/DB_driver.php
@@ -1658,7 +1658,7 @@
 
 		$error =& load_class('Exceptions', 'core');
 		echo $error->show_error($heading, $message, 'error_db');
-		exit(5);
+		exit(EXIT_DATABASE);
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/helpers/download_helper.php b/system/helpers/download_helper.php
index daf59f5..25863ea 100644
--- a/system/helpers/download_helper.php
+++ b/system/helpers/download_helper.php
@@ -142,7 +142,7 @@
 		if ($data !== NULL)
 		{
 			echo $data;
-			exit(0);
+			exit(EXIT_SUCCESS);
 		}
 
 		// Flush 1MB chunks of data
@@ -152,7 +152,7 @@
 		}
 
 		fclose($fp);
-		exit(0);
+		exit(EXIT_SUCCESS);
 	}
 }
 
diff --git a/system/helpers/url_helper.php b/system/helpers/url_helper.php
index d6bf7e2..7d5ccff 100644
--- a/system/helpers/url_helper.php
+++ b/system/helpers/url_helper.php
@@ -550,7 +550,7 @@
 				header('Location: '.$uri, TRUE, $code);
 				break;
 		}
-		exit(0);
+		exit(EXIT_SUCCESS);
 	}
 }
 
diff --git a/system/libraries/Driver.php b/system/libraries/Driver.php
index ba15f81..9a56013 100644
--- a/system/libraries/Driver.php
+++ b/system/libraries/Driver.php
@@ -290,7 +290,7 @@
 
 		$trace = debug_backtrace();
 		_exception_handler(E_ERROR, "No such method '{$method}'", $trace[1]['file'], $trace[1]['line']);
-		exit(3);
+		exit(EXIT_UNK_MEMBER);
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/libraries/Trackback.php b/system/libraries/Trackback.php
index cc93b2e..ea8017e 100644
--- a/system/libraries/Trackback.php
+++ b/system/libraries/Trackback.php
@@ -212,7 +212,7 @@
 	public function send_error($message = 'Incomplete Information')
 	{
 		echo '<?xml version="1.0" encoding="utf-8"?'.">\n<response>\n<error>1</error>\n<message>".$message."</message>\n</response>";
-		exit(0);
+		exit(EXIT_SUCCESS);
 	}
 
 	// --------------------------------------------------------------------
@@ -228,7 +228,7 @@
 	public function send_success()
 	{
 		echo '<?xml version="1.0" encoding="utf-8"?'.">\n<response>\n<error>0</error>\n</response>";
-		exit(0);
+		exit(EXIT_SUCCESS);
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/libraries/Xmlrpcs.php b/system/libraries/Xmlrpcs.php
index 2d2e7f1..e150c13 100644
--- a/system/libraries/Xmlrpcs.php
+++ b/system/libraries/Xmlrpcs.php
@@ -171,7 +171,7 @@
 		header('Content-Type: text/xml');
 		header('Content-Length: '.strlen($payload));
 		echo $payload;
-		exit(0);
+		exit(EXIT_SUCCESS);
 	}
 
 	// --------------------------------------------------------------------
diff --git a/user_guide_src/source/general/errors.rst b/user_guide_src/source/general/errors.rst
index 8c941aa..1d6f812 100644
--- a/user_guide_src/source/general/errors.rst
+++ b/user_guide_src/source/general/errors.rst
@@ -18,6 +18,15 @@
 application. This approach permits error messages to get triggered
 without having to worry about class/function scoping.
 
+CodeIgniter also returns a status code whenever a portion of the core
+calls ``exit()``. This exit status code is separate from the HTTP status
+code, and serves as a notice to other processes that may be watching of
+whether the script completed successfully, or if not, what kind of 
+problem it encountered that caused it to abort. These values are 
+defined in *application/config/constants.php*. While exit status codes
+are most useful in CLI settings, returning the proper code helps server
+software keep track of your scripts and the health of your application.
+
 The following functions let you generate errors:
 
 show_error()
@@ -36,7 +45,12 @@
 	application/errors/error_general.php
 
 The optional parameter ``$status_code`` determines what HTTP status
-code should be sent with the error.
+code should be sent with the error. If ``$status_code`` is less than 100,
+the HTTP status code will be set to 500, and the exit status code will
+be set to ``$status_code + EXIT__AUTO_MIN``. If that value is larger than
+``EXIT__AUTO_MAX``, or if ``$status_code`` is 100 or higher, the exit
+status code will be set to ``EXIT_FAILURE``. You can check in 
+*application/config/constants.php* for more detail.
 
 show_404()
 ==========
@@ -53,8 +67,9 @@
 	application/errors/error_404.php
 
 The function expects the string passed to it to be the file path to the
-page that isn't found. Note that CodeIgniter automatically shows 404
-messages if controllers are not found.
+page that isn't found. The exit status code will be set to ``EXIT_UNK_FILE``.
+Note that CodeIgniter automatically shows 404 messages if controllers are
+not found.
 
 CodeIgniter automatically logs any ``show_404()`` calls. Setting the
 optional second parameter to FALSE will skip logging.