Index: includes/database.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/database.inc,v
retrieving revision 1.41
diff -u -F^f -r1.41 database.inc
--- includes/database.inc	22 Jun 2005 20:19:58 -0000	1.41
+++ includes/database.inc	21 Jul 2005 23:17:19 -0000
@@ -116,7 +116,11 @@ function db_set_active($name = 'default'
       include_once($handler);
     }
     else {
-      die('Unsupported database type');
+      drupal_bootstrap_theme_system();
+      drupal_set_title('Unsupported database type');
+      print theme('maintenance_page', '<p>The database type <code>'. $db_type .'</code> is unsupported. Please use either <code>mysql</code> for MySQL databases or <code>pgsql</code> for PostgreSQL databases. The database information is in your <code>settings.php</code> file.</p>
+<p>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.</p>');
+      exit;
     }
 
     $db_conns[$name] = db_connect($connect_url);
Index: includes/database.pgsql.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/database.pgsql.inc,v
retrieving revision 1.9
diff -u -F^f -r1.9 database.pgsql.inc
--- includes/database.pgsql.inc	22 Jun 2005 20:19:58 -0000	1.9
+++ includes/database.pgsql.inc	21 Jul 2005 23:17:20 -0000
@@ -25,7 +25,32 @@ function db_connect($url) {
 
   $conn_string = ' user='. $url['user'] .' dbname='. substr($url['path'], 1) .' password='. $url['pass'] . ' host=' . $url['host'];
   $conn_string .= isset($url['port']) ? ' port=' . $url['port'] : '';
-  $connection = pg_connect($conn_string) or die(pg_last_error());
+
+  // pg_last_error() does not return a useful error message for database
+  // connection errors. We must turn on error tracking to get at a good error
+  // message, which will be stored in $php_errormsg.
+  $track_errors_previous = ini_get('track_errors');
+  ini_set('track_errors', 1);
+
+  $connection = @pg_connect($conn_string);
+  if (!$connection) {
+    drupal_bootstrap_theme_system();
+    drupal_set_title('Unable to connect to database');
+    print theme('maintenance_page', '<p>This either means that the database information in your <code>settings.php</code> file is incorrect or we can\'t contact the PostgreSQL database server. This could mean your hosting provider\'s database server is down.</p>
+<p>The PostgreSQL error was: <em>'. $php_errormsg .'</em></p>
+<p>Currently, the database is <code>'. substr($url['path'], 1) .'</code>, the username is <code>'. $url['user'] .'</code>, and the database server is <code>'. $url['host'] .'</code>.</p>
+<ul>
+  <li>Are you sure you have the correct username and password?</li>
+  <li>Are you sure that you have typed the correct hostname?</li>
+  <li>Are you sure you have the correct database name?</li>
+  <li>Are you sure that the database server is running?</li>
+</ul>
+<p>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.</p>');
+    exit;
+  }
+
+  // Restore error tracking setting
+  ini_set('track_errors', $track_errors_previous);
 
   return $connection;
 }
Index: includes/database.mysql.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/database.mysql.inc,v
retrieving revision 1.31
diff -u -F^f -r1.31 database.mysql.inc
--- includes/database.mysql.inc	22 Jun 2005 20:19:58 -0000	1.31
+++ includes/database.mysql.inc	21 Jul 2005 23:17:20 -0000
@@ -34,9 +34,36 @@ function db_connect($url) {
   //   server.
   // - 2 means CLIENT_FOUND_ROWS: return the number of found
   //   (matched) rows, not the number of affected rows.
-  $connection = mysql_connect($url['host'], $url['user'], $url['pass'], TRUE, 2) or die(mysql_error());
-
-  mysql_select_db(substr($url['path'], 1)) or die('unable to select database');
+  $connection = @mysql_connect($url['host'], $url['user'], $url['pass'], TRUE, 2);
+  if (!$connection) {
+    drupal_bootstrap_theme_system();
+    drupal_set_title('Unable to connect to database server');
+    print theme('maintenance_page', '<p>This either means that the username and password information in your <code>settings.php</code> file is incorrect or we can\'t contact the MySQL database server. This could mean your hosting provider\'s database server is down.</p>
+<p>The MySQL error was: <em>'. mysql_error() .'</em>.</p>
+<p>Currently, the username is <code>'. $url['user'] .'</code> and the database server is <code>'. $url['host'] .'</code>.</p>
+<ul>
+  <li>Are you sure you have the correct username and password?</li>
+  <li>Are you sure that you have typed the correct hostname?</li>
+  <li>Are you sure that the database server is running?</li>
+</ul>
+<p>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.</p>');
+    exit;
+  }
+
+  if (!mysql_select_db(substr($url['path'], 1))) {
+    drupal_bootstrap_theme_system();
+    drupal_set_title('Unable to select database');
+    print theme('maintenance_page', '<p>We were able to connect to the MySQL database server (which means your username and password is okay) but not able to select the database.</p>
+<p>The MySQL error was: <em>'. mysql_error() .'</em>.</p>
+<p>Currently, the database is <code>'. substr($url['path'], 1) .'</code>. The username is <code>'. $url['user'] .'</code> and the database server is <code>'. $url['host'] .'</code>.</p>
+<ul>
+  <li>Are you sure you have the correct database name?</li>
+  <li>Are you sure the database exists?</li>
+  <li>Are you sure the username has permission to access the database?</li>
+</ul>
+<p>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.</p>');
+    exit;
+  }
 
   return $connection;
 }
Index: includes/theme.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/theme.inc,v
retrieving revision 1.245
diff -u -F^f -r1.245 theme.inc
--- includes/theme.inc	2 Jul 2005 12:32:09 -0000	1.245
+++ includes/theme.inc	21 Jul 2005 23:17:20 -0000
@@ -160,7 +160,7 @@ function list_theme_engines($refresh = F
 function theme() {
   global $theme, $theme_engine;
 
-  if (!$theme) {
+  if (is_null($theme)) {
     // Initialize the enabled theme.
     $theme = init_theme();
   }
@@ -440,6 +440,30 @@ function theme_page($content) {
   return $output;
 }
 
+function theme_maintenance_page($content) {
+  theme('add_style', 'misc/drupal.css');
+  theme('add_style', 'misc/maintenance.css');
+  $output = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n";
+  $output .= '<html xmlns="http://www.w3.org/1999/xhtml">';
+  $output .= '<head>';
+  $output .= '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
+  $output .= ' <title>'. drupal_get_title() .'</title>';
+  $output .= theme_get_styles();
+  $output .= '</head>';
+  $output .= '<body>';
+  $output .= '<h1>' . drupal_get_title() . '</h1>';
+
+  $output .= theme('status_messages');
+
+  $output .= "\n<!-- begin content -->\n";
+  $output .= $content;
+  $output .= "\n<!-- end content -->\n";
+
+  $output .= '</body></html>';
+
+  return $output;
+}
+
 /**
  * Returns themed set of status and/or error messages.  The messages are grouped
  * by type.
Index: includes/bootstrap.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/bootstrap.inc,v
retrieving revision 1.55
diff -U2 -F^f -r1.55 bootstrap.inc
--- includes/bootstrap.inc	3 Jul 2005 10:09:08 -0000	1.55
+++ includes/bootstrap.inc	21 Jul 2005 23:17:24 -0000
@@ -856,3 +865,16 @@ function _drupal_bootstrap($phase) {
 }
 
+/**
+ * Enables use of the theme system without requireing database access. Since
+ * there is not database access no theme will be enabled and the default
+ * themeable fuctions will be called. Some themeable functions can not be used
+ * without the full Drupal API loaded. For example, theme_page() is
+ * unavailiable and theme_maintenance_page() must be used in it's place.
+ */
+function drupal_bootstrap_theme_system() {
+  global $theme;
+  require_once 'includes/theme.inc';
+  $theme = '';
+}
+
 ?>
