]> granicus.if.org Git - postgresql/blobdiff - src/backend/utils/init/postinit.c
I really hope that I haven't missed anything in this one...
[postgresql] / src / backend / utils / init / postinit.c
index 7ed1b7f94fce7b9237e710a6e62a80ad034cf76b..57ce319e764ed1f72dddc9ea640806de9e92d9ba 100644 (file)
@@ -1,28 +1,28 @@
 /*-------------------------------------------------------------------------
  *
  * postinit.c--
- *    postgres initialization utilities
+ *       postgres initialization utilities
  *
  * Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.9 1997/07/24 20:17:34 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.31 1998/07/24 03:31:50 scrappy Exp $
  *
  * NOTES
- *      InitPostgres() is the function called from PostgresMain
- *      which does all non-trival initialization, mainly by calling
- *      all the other initialization functions.  InitPostgres()
- *      is only used within the "postgres" backend and so that routine
- *      is in tcop/postgres.c  InitPostgres() is needed in cinterface.a
- *      because things like the bootstrap backend program need it. Hence
- *      you find that in this file...
+ *             InitPostgres() is the function called from PostgresMain
+ *             which does all non-trival initialization, mainly by calling
+ *             all the other initialization functions.  InitPostgres()
+ *             is only used within the "postgres" backend and so that routine
+ *             is in tcop/postgres.c  InitPostgres() is needed in cinterface.a
+ *             because things like the bootstrap backend program need it. Hence
+ *             you find that in this file...
  *
- *      If you feel the need to add more initialization code, it should be
- *      done in InitPostgres() or someplace lower.  Do not start
- *      putting stuff in PostgresMain - if you do then someone
- *      will have to clean it up later, and it's not going to be me!
- *      -cim 10/3/90
+ *             If you feel the need to add more initialization code, it should be
+ *             done in InitPostgres() or someplace lower.      Do not start
+ *             putting stuff in PostgresMain - if you do then someone
+ *             will have to clean it up later, and it's not going to be me!
+ *             -cim 10/3/90
  *
  *-------------------------------------------------------------------------
  */
@@ -30,7 +30,6 @@
 #include <stdio.h>
 #include <string.h>
 #include <sys/file.h>
-#include <sys/stat.h>
 #include <sys/types.h>
 #include <math.h>
 #include <unistd.h>
 #include "access/heapam.h"
 #include "access/xact.h"
 #include "storage/bufmgr.h"
-#include "access/transam.h"     /* XXX dependency problem */
-#include "utils/tqual.h"
+#include "access/transam.h"            /* XXX dependency problem */
 #include "utils/syscache.h"
-#include "storage/bufpage.h"    /* for page layout, for InitMyDatabaseId() */
+#include "storage/bufpage.h"   /* for page layout, for
+                                                                * InitMyDatabaseInfo() */
 #include "storage/sinval.h"
 #include "storage/sinvaladt.h"
 #include "storage/lmgr.h"
 
-#include "miscadmin.h"         /* for global decls */
-#include "utils/portal.h"       /* for EnablePortalManager, etc. */
+#include "miscadmin.h"                 /* for global decls */
+#include "utils/portal.h"              /* for EnablePortalManager, etc. */
 
-#include "utils/exc.h"          /* for EnableExceptionHandling, etc. */
-#include "fmgr.h"               /* for EnableDynamicFunctionManager, etc. */
+#include "utils/exc.h"                 /* for EnableExceptionHandling, etc. */
+#include "fmgr.h"                              /* for EnableDynamicFunctionManager, etc. */
 #include "utils/elog.h"
 #include "utils/palloc.h"
-#include "utils/mcxt.h"         /* for EnableMemoryContext, etc. */
+#include "utils/mcxt.h"                        /* for EnableMemoryContext, etc. */
+#include "utils/inval.h"
 
 #include "catalog/catname.h"
+#ifdef MB
+#include "catalog/pg_database_mb.h"
+#include "mb/pg_wchar.h"
+#else
 #include "catalog/pg_database.h"
+#endif
 
-#include "port-protos.h"
-#include "libpq/libpq-be.h"
-
+#include "libpq/libpq.h"
 
-static IPCKey           PostgresIpcKey;
+static void VerifySystemDatabase(void);
+static void VerifyMyDatabase(void);
+static void InitCommunication(void);
+static void InitMyDatabaseInfo(char *name);
+static void InitStdio(void);
+static void InitUserid(void);
 
+extern char *ExpandDatabasePath(char *name);
+#ifdef MB
+extern void GetRawDatabaseInfo(char *name, Oid *owner, Oid *db_id, char *path, int *encoding);
+#else
+extern void GetRawDatabaseInfo(char *name, Oid *owner, Oid *db_id, char *path);
+#endif
 
-#ifndef private
-#ifndef EBUG
-#define private static
-#else   /* !defined(EBUG) */
-#define private
-#endif  /* !defined(EBUG) */
-#endif  /* !defined(private) */
+static IPCKey PostgresIpcKey;
 
 /* ----------------------------------------------------------------
- *                      InitPostgres support
+ *                                             InitPostgres support
  * ----------------------------------------------------------------
  */
 
 /* --------------------------------
- *  InitMyDatabaseId() -- Find and record the OID of the database we are
- *                        to open.
+ *     InitMyDatabaseInfo() -- Find and record the OID of the database we are
+ *                                               to open.
  *
- *      The database's oid forms half of the unique key for the system
- *      caches and lock tables.  We therefore want it initialized before
- *      we open any relations, since opening relations puts things in the
- *      cache.  To get around this problem, this code opens and scans the
- *      pg_database relation by hand.
+ *             The database's oid forms half of the unique key for the system
+ *             caches and lock tables.  We therefore want it initialized before
+ *             we open any relations, since opening relations puts things in the
+ *             cache.  To get around this problem, this code opens and scans the
+ *             pg_database relation by hand.
  *
- *      This algorithm relies on the fact that first attribute in the
- *      pg_database relation schema is the database name.  It also knows
- *      about the internal format of tuples on disk and the length of
- *      the datname attribute.  It knows the location of the pg_database
- *      file.
+ *             This algorithm relies on the fact that first attribute in the
+ *             pg_database relation schema is the database name.  It also knows
+ *             about the internal format of tuples on disk and the length of
+ *             the datname attribute.  It knows the location of the pg_database
+ *             file.
+ *             Actually, the code looks as though it is using the pg_database
+ *             tuple definition to locate the database name, so the above statement
+ *             seems to be no longer correct. - thomas 1997-11-01
  *
- *      This code is called from InitDatabase(), after we chdir() to the
- *      database directory but before we open any relations.
+ *             This code is called from InitPostgres(), before we chdir() to the
+ *             local database directory and before we open any relations.
+ *             Used to be called after the chdir(), but we now want to confirm
+ *             the location of the target database using pg_database info.
+ *             - thomas 1997-11-01
  * --------------------------------
  */
-void
-InitMyDatabaseId()
+static void
+InitMyDatabaseInfo(char *name)
 {
-    int         dbfd;
-    int         fileflags;
-    int         nbytes;
-    int         max, i;
-    HeapTuple   tup;
-    Page        pg;
-    PageHeader  ph;
-    char        *dbfname;
-    Form_pg_database    tup_db;
-    
-    /*
-     *  At bootstrap time, we don't need to check the oid of the database
-     *  in use, since we're not using shared memory.  This is lucky, since
-     *  the database may not be in the tables yet.
-     */
-    
-    if (IsBootstrapProcessingMode()) {
-        LockDisable(true);
-        return;
-    }
-    
-    dbfname = (char *) palloc(strlen(DataDir) + strlen("pg_database") + 2);
-    sprintf(dbfname, "%s%cpg_database", DataDir, SEP_CHAR);
-    fileflags = O_RDONLY;
-    
-    if ((dbfd = open(dbfname, O_RDONLY, 0666)) < 0)
-        elog(FATAL, "Cannot open %s", dbfname);
-    
-    pfree(dbfname);
-    
-    /* ----------------
-     *  read and examine every page in pg_database
-     *
-     *  Raw I/O! Read those tuples the hard way! Yow!
-     *
-     *  Why don't we use the access methods or move this code
-     *  someplace else?  This is really pg_database schema dependent
-     *  code.  Perhaps it should go in lib/catalog/pg_database?
-     *  -cim 10/3/90
-     *
-     *  mao replies 4 apr 91:  yeah, maybe this should be moved to
-     *  lib/catalog.  however, we CANNOT use the access methods since
-     *  those use the buffer cache, which uses the relation cache, which
-     *  requires that the dbid be set, which is what we're trying to do
-     *  here.
-     * ----------------
-     */
-    pg = (Page) palloc(BLCKSZ);
-    ph = (PageHeader) pg;
-    
-    while ((nbytes = read(dbfd, pg, BLCKSZ)) == BLCKSZ) {
-        max = PageGetMaxOffsetNumber(pg);
-        
-        /* look at each tuple on the page */
-        for (i = 0; i <= max; i++) {
-            int offset;
-            
-            /* if it's a freed tuple, ignore it */
-            if (!(ph->pd_linp[i].lp_flags & LP_USED))
-                continue;
-            
-            /* get a pointer to the tuple itself */
-            offset = (int) ph->pd_linp[i].lp_off;
-            tup = (HeapTuple) (((char *) pg) + offset);
-            
-            /*
-             *  if the tuple has been deleted (the database was destroyed),
-             *  skip this tuple.  XXX warning, will robinson:  violation of
-             *  transaction semantics happens right here.  we should check
-             *  to be sure that the xact that deleted this tuple actually
-             *  committed.  only way to do this at init time is to paw over
-             *  the log relation by hand, too.  let's be optimistic.
-             *
-             *  XXX This is an evil type cast.  tup->t_xmax is char[5] while
-             *  TransactionId is struct * { char data[5] }.  It works but
-             *  if data is ever moved and no longer the first field this 
-             *  will be broken!! -mer 11 Nov 1991.
-             */
-            if (TransactionIdIsValid((TransactionId)tup->t_xmax))
-                continue;
-            
-            /*
-             *  Okay, see if this is the one we want.
-             *  XXX 1 july 91:  mao and mer discover that tuples now squash
-             *                  t_bits.  Why is this?
-             *
-             *     24 july 92:  mer realizes that the t_bits field is only
-             *                  used in the event of null values.  If no
-             *                  fields are null we reduce the header size
-             *                  by doing the squash.  t_hoff tells you exactly
-             *                  how big the header actually is. use the PC
-             *                  means of getting at sys cat attrs.
-             */
-            tup_db = (Form_pg_database)GETSTRUCT(tup);
-            
-            if (strncmp(GetDatabaseName(),
-                        &(tup_db->datname.data[0]),
-                        16) == 0)
-                {
-                    MyDatabaseId = tup->t_oid;
-                    goto done;
-                }
-        }
-    }
-    
- done:
-    (void) close(dbfd);
-    pfree(pg);
-    
-    if (!OidIsValid(MyDatabaseId))
-        elog(FATAL,
-             "Database %s does not exist in %s",
-             GetDatabaseName(),
-             DatabaseRelationName);
-}
+       Oid                     owner;
+       char       *path,
+                               myPath[MAXPGPATH + 1];
+#ifdef MB
+       int encoding;
+#endif
 
+       SetDatabaseName(name);
+#ifdef MB
+       GetRawDatabaseInfo(name, &owner, &MyDatabaseId, myPath, &encoding);
+#else
+       GetRawDatabaseInfo(name, &owner, &MyDatabaseId, myPath);
+#endif
+
+       if (!OidIsValid(MyDatabaseId))
+               elog(FATAL,
+                        "Database %s does not exist in %s",
+                        DatabaseName,
+                        DatabaseRelationName);
+
+       path = ExpandDatabasePath(myPath);
+       SetDatabasePath(path);
+#ifdef MB
+       SetDatabaseEncoding(encoding);
+#endif
+
+       return;
+}      /* InitMyDatabaseInfo() */
 
 
 /*
  * DoChdirAndInitDatabaseNameAndPath --
- *      Set current directory to the database directory for the database
- *      named <name>.
- *      Also set global variables DatabasePath and DatabaseName to those
- *      values.  Also check for proper version of database system and
- *      database.  Exit program via elog() if anything doesn't check out.
+ *             Set current directory to the database directory for the database
+ *             named <name>.
+ *             Also set global variables DatabasePath and DatabaseName to those
+ *             values.  Also check for proper version of database system and
+ *             database.  Exit program via elog() if anything doesn't check out.
  *
  * Arguments:
- *      Path and name are invalid if it invalid as a string.
- *      Path is "badly formated" if it is not a string containing a path
- *      to a writable directory.
- *      Name is "badly formated" if it contains more than 16 characters or if
- *      it is a bad file name (e.g., it contains a '/' or an 8-bit character).
+ *             Path and name are invalid if it invalid as a string.
+ *             Path is "badly formatted" if it is not a string containing a path
+ *             to a writable directory.
+ *             Name is "badly formatted" if it contains more than 16 characters or if
+ *             it is a bad file name (e.g., it contains a '/' or an 8-bit character).
  *
  * Exceptions:
- *      BadState if called more than once.
- *      BadArg if both path and name are "badly formated" or invalid.
- *      BadArg if path and name are both "inconsistent" and valid.
+ *             BadState if called more than once.
+ *             BadArg if both path and name are "badly formatted" or invalid.
+ *             BadArg if path and name are both "inconsistent" and valid.
  *
- *      This routine is inappropriate in bootstrap mode, since the directories
- *      and version files need not exist yet if we're in bootstrap mode.
+ *             This routine is inappropriate in bootstrap mode, since the directories
+ *             and version files need not exist yet if we're in bootstrap mode.
  */
 static void
-DoChdirAndInitDatabaseNameAndPath(char *name) {
-    char *reason;  
-      /* Failure reason returned by some function.  NULL if no failure */
-    struct stat        statbuf;
-    char errormsg[1000];
-
-    if (stat(DataDir, &statbuf) < 0) 
-        sprintf(errormsg, "Database system does not exist.  "
-                "PGDATA directory '%s' not found.  Normally, you "
-                "create a database system by running initdb.",
-                DataDir);
-    else {
-        char myPath[MAXPGPATH];  /* DatabasePath points here! */
-        
-        if (strlen(DataDir) + strlen(name) + 10 > sizeof(myPath))
-            sprintf(errormsg, "Internal error in postinit.c: database "
-                    "pathname exceeds maximum allowable length.");
-        else {
-            sprintf(myPath, "%s/base/%s", DataDir, name);
-
-            if (stat(myPath, &statbuf) < 0) 
-                sprintf(errormsg, 
-                        "Database '%s' does not exist.  "
-                        "(We know this because the directory '%s' "
-                        "does not exist).  You can create a database "
-                        "with the SQL command CREATE DATABASE.  To see "
-                        "what databases exist, look at the subdirectories "
-                        "of '%s/base/'.",
-                        name, myPath, DataDir);
-            else {
-                ValidatePgVersion(DataDir, &reason);
-                if (reason != NULL) 
-                    sprintf(errormsg, 
-                        "InitPostgres could not validate that the database "
-                        "system version is compatible with this level of "
-                        "Postgres.  You may need to run initdb to create "
-                        "a new database system.  %s", 
-                        reason);
-                else {
-                    ValidatePgVersion(myPath, &reason);
-                    if (reason != NULL)
-                        sprintf(errormsg, 
-                            "InitPostgres could not validate that the "
-                            "database version is compatible with this level "
-                            "of Postgres, even though the database system "
-                            "as a whole appears to be at a compatible level.  "
-                            "You may need to recreate the database with SQL "
-                            "commands DROP DATABASE and CREATE DATABASE.  "
-                            "%s",
-                            reason);
-                    else {
-                        /* The directories and PG_VERSION files are in order.*/
-                        int rc;  /* return code from some function we call */
-                    
-                        SetDatabasePath(myPath);
-                        SetDatabaseName(name);
-                        rc = chdir(myPath);
-                        if (rc < 0)
-                           sprintf(errormsg, 
-                               "InitPostgres unable to change "
-                               "current directory to '%s', errno = %s (%d).",
-                               myPath, strerror(errno), errno);
-                        else errormsg[0] = '\0';
-                    }
-                }
-            }
-        }
-    }
-    if (errormsg[0] != '\0')
-        elog(FATAL, errormsg);
-        /* Above does not return */
-}
+VerifySystemDatabase()
+{
+       char       *reason;
+
+       /* Failure reason returned by some function.  NULL if no failure */
+       int                     fd;
+       char            errormsg[1000];
 
+       errormsg[0] = '\0';
+
+       if ((fd = open(DataDir, O_RDONLY, 0)) == -1)
+               sprintf(errormsg, "Database system does not exist.  "
+                               "PGDATA directory '%s' not found.\n\tNormally, you "
+                               "create a database system by running initdb.",
+                               DataDir);
+       else
+       {
+               close(fd);
+               ValidatePgVersion(DataDir, &reason);
+               if (reason != NULL)
+                       sprintf(errormsg,
+                                       "InitPostgres could not validate that the database"
+                                       " system version is compatible with this level of"
+                                       " Postgres.\n\tYou may need to run initdb to create"
+                                       " a new database system.\n\t%s", reason);
+       }
+       if (errormsg[0] != '\0')
+               elog(FATAL, errormsg);
+       /* Above does not return */
+}      /* VerifySystemDatabase() */
+
+
+static void
+VerifyMyDatabase()
+{
+       const char         *name;
+       const char         *myPath;
+
+       /* Failure reason returned by some function.  NULL if no failure */
+       char       *reason;
+       int                     fd;
+       char            errormsg[1000];
+
+       name = DatabaseName;
+       myPath = DatabasePath;
+
+       if ((fd = open(myPath, O_RDONLY, 0)) == -1)
+               sprintf(errormsg,
+                               "Database '%s' does not exist."
+                       "\n\tWe know this because the directory '%s' does not exist."
+                               "\n\tYou can create a database with the SQL command"
+                               " CREATE DATABASE.\n\tTo see what databases exist,"
+                               " look at the subdirectories of '%s/base/'.",
+                               name, myPath, DataDir);
+       else
+       {
+               close(fd);
+               ValidatePgVersion(myPath, &reason);
+               if (reason != NULL)
+                       sprintf(errormsg,
+                                       "InitPostgres could not validate that the database"
+                                       " version is compatible with this level of Postgres"
+                                       "\n\teven though the database system as a whole"
+                                       " appears to be at a compatible level."
+                                       "\n\tYou may need to recreate the database with SQL"
+                                       " commands DROP DATABASE and CREATE DATABASE."
+                                       "\n\t%s", reason);
+               else
+               {
+
+                       /*
+                        * The directories and PG_VERSION files are in order.
+                        */
+                       int                     rc;             /* return code from some function we call */
+
+#ifdef FILEDEBUG
+                       printf("Try changing directory for database %s to %s\n", name, myPath);
+#endif
+
+                       rc = chdir(myPath);
+                       if (rc < 0)
+                               sprintf(errormsg,
+                                               "InitPostgres unable to change "
+                                               "current directory to '%s', errno = %s (%d).",
+                                               myPath, strerror(errno), errno);
+                       else
+                               errormsg[0] = '\0';
+               }
+       }
+
+       if (errormsg[0] != '\0')
+               elog(FATAL, errormsg);
+       /* Above does not return */
+}      /* VerifyMyDatabase() */
 
 
 /* --------------------------------
- *      InitUserid
+ *             InitUserid
  *
- *      initializes crap associated with the user id.
+ *             initializes crap associated with the user id.
  * --------------------------------
  */
-void
+static void
 InitUserid()
 {
-    setuid(geteuid());
-    SetUserId();
+       setuid(geteuid());
+       SetUserId();
 }
 
 /* --------------------------------
- *      InitCommunication
+ *             InitCommunication
  *
- *      This routine initializes stuff needed for ipc, locking, etc.
- *      it should be called something more informative.
+ *             This routine initializes stuff needed for ipc, locking, etc.
+ *             it should be called something more informative.
  *
  * Note:
- *      This does not set MyBackendId.  MyBackendTag is set, however.
+ *             This does not set MyBackendId.  MyBackendTag is set, however.
  * --------------------------------
  */
-void
+static void
 InitCommunication()
 {
-    char *postid;
-    char *postport;
-    IPCKey      key = 0;
-    
-    /* ----------------
-     *  try and get the backend tag from POSTID
-     * ----------------
-     */
-    MyBackendId = -1;
-    
-    postid = getenv("POSTID");
-    if (!PointerIsValid(postid)) {
-        MyBackendTag = -1;
-    } else {
-        MyBackendTag = atoi(postid);
-        Assert(MyBackendTag >= 0);
-    }
-    
-    /* ----------------
-     *  try and get the ipc key from POSTPORT
-     * ----------------
-     */
-    postport = getenv("POSTPORT");
-    
-    if (PointerIsValid(postport)) {
-        SystemPortAddress address = atoi(postport);
-        
-        if (address == 0)
-            elog(FATAL, "InitCommunication: invalid POSTPORT");
-        
-        if (MyBackendTag == -1)
-            elog(FATAL, "InitCommunication: missing POSTID");
-        
-        key = SystemPortAddressCreateIPCKey(address);
-        
-        /*
-         * Enable this if you are trying to force the backend to run as if it 
-         * is running under the postmaster.
-         *
-         * This goto forces Postgres to attach to shared memory instead of 
-         * using malloc'ed memory (which is the normal behavior if run
-         * directly).
-         *
-         * To enable emulation, run the following shell commands (in addition
-         * to enabling this goto)
-         *
-         *     % setenv POSTID 1
-         *     % setenv POSTPORT 4321
-         *     % postmaster &
-         *     % kill -9 %1
-         *
-         * Upon doing this, Postmaster will have allocated the shared memory 
-         * resources that Postgres will attach to if you enable
-         * EMULATE_UNDER_POSTMASTER.
-         *
-         * This comment may well age with time - it is current as of
-         * 8 January 1990
-         * 
-         * Greg
-         */
-        
+       char       *postid;                     /* value of environment variable */
+       char       *postport;           /* value of environment variable */
+       char       *ipc_key;            /* value of environemnt variable */
+       IPCKey          key = 0;
+
+       /* ----------------
+        *      try and get the backend tag from POSTID
+        * ----------------
+        */
+       MyBackendId = -1;
+
+       postid = getenv("POSTID");
+       if (!PointerIsValid(postid))
+               MyBackendTag = -1;
+       else
+       {
+               MyBackendTag = atoi(postid);
+               Assert(MyBackendTag >= 0);
+       }
+
+
+       ipc_key = getenv("IPC_KEY");
+       if (!PointerIsValid(ipc_key))
+               key = -1;
+       else
+       {
+               key = atoi(ipc_key);
+               Assert(MyBackendTag >= 0);
+       }
+
+       postport = getenv("POSTPORT");
+
+       if (PointerIsValid(postport))
+       {
+               if (MyBackendTag == -1)
+                       elog(FATAL, "InitCommunication: missing POSTID");
+
+               /*
+                * Enable this if you are trying to force the backend to run as if
+                * it is running under the postmaster.
+                *
+                * This goto forces Postgres to attach to shared memory instead of
+                * using malloc'ed memory (which is the normal behavior if run
+                * directly).
+                *
+                * To enable emulation, run the following shell commands (in addition
+                * to enabling this goto)
+                *
+                * % setenv POSTID 1 % setenv POSTPORT 4321 % setenv IPC_KEY 4321000
+                * % postmaster & % kill -9 %1
+                *
+                * Upon doing this, Postmaster will have allocated the shared memory
+                * resources that Postgres will attach to if you enable
+                * EMULATE_UNDER_POSTMASTER.
+                *
+                * This comment may well age with time - it is current as of 8
+                * January 1990
+                *
+                * Greg
+                */
+
 #ifdef EMULATE_UNDER_POSTMASTER
-        
-        goto forcesharedmemory;
-        
+
+               goto forcesharedmemory;
+
 #endif
-        
-    } else if (IsUnderPostmaster) {
-        elog(FATAL,
-             "InitCommunication: under postmaster and POSTPORT not set");
-    } else {
-        /* ----------------
-         *  assume we're running a postgres backend by itself with
-         *  no front end or postmaster.
-         * ----------------
-         */
-        if (MyBackendTag == -1) {
-            MyBackendTag = 1;
-        }
-        
-        key = PrivateIPCKey;
-    }
-    
-    /* ----------------
-     *  initialize shared memory and semaphores appropriately.
-     * ----------------
-     */
+
+       }
+       else if (IsUnderPostmaster)
+       {
+               elog(FATAL,
+                        "InitCommunication: under postmaster and POSTPORT not set");
+       }
+       else
+       {
+               /* ----------------
+                *      assume we're running a postgres backend by itself with
+                *      no front end or postmaster.
+                * ----------------
+                */
+               if (MyBackendTag == -1)
+                       MyBackendTag = 1;
+
+               key = PrivateIPCKey;
+       }
+
+       /* ----------------
+        *      initialize shared memory and semaphores appropriately.
+        * ----------------
+        */
 #ifdef EMULATE_UNDER_POSTMASTER
-    
- forcesharedmemory:
-    
+
+forcesharedmemory:
+
 #endif
-    
-    PostgresIpcKey = key;
-    AttachSharedMemoryAndSemaphores(key);
+
+    if (!IsUnderPostmaster) /* postmaster already did this */
+       {
+               PostgresIpcKey = key;
+               AttachSharedMemoryAndSemaphores(key);
+       }
 }
 
 
 /* --------------------------------
- *      InitStdio
+ *             InitStdio
  *
- *      this routine consists of a bunch of code fragments
- *      that used to be randomly scattered through cinit().
- *      they all seem to do stuff associated with io.
+ *             this routine consists of a bunch of code fragments
+ *             that used to be randomly scattered through cinit().
+ *             they all seem to do stuff associated with io.
  * --------------------------------
  */
-void
+static void
 InitStdio()
 {
-    (void) DebugFileOpen();
+       DebugFileOpen();
 }
 
 /* --------------------------------
  * InitPostgres --
- *      Initialize POSTGRES.
+ *             Initialize POSTGRES.
  *
  * Note:
- *      Be very careful with the order of calls in the InitPostgres function.
+ *             Be very careful with the order of calls in the InitPostgres function.
  * --------------------------------
  */
-bool PostgresIsInitialized = false;
-extern int NBuffers;
+bool           PostgresIsInitialized = false;
+extern int     NBuffers;
 
 /*
- *  this global is used by wei for testing his code, but must be declared
- *  here rather than in postgres.c so that it's defined for cinterface.a
- *  applications.
+ *     this global is used by wei for testing his code, but must be declared
+ *     here rather than in postgres.c so that it's defined for cinterface.a
+ *     applications.
  */
 
-/*int   testFlag = 0;*/
-int     lockingOff = 0;
+/*int  testFlag = 0;*/
+int                    lockingOff = 0;
 
 /*
  */
 void
-InitPostgres(char *name)        /* database name */
+InitPostgres(char *name)               /* database name */
 {
-    bool        bootstrap;      /* true if BootstrapProcessing */
-    
-    /* ----------------
-     *  see if we're running in BootstrapProcessing mode
-     * ----------------
-     */
-    bootstrap = IsBootstrapProcessingMode();
-    
-    /* ----------------
-     *  turn on the exception handler.  Note: we cannot use elog, Assert,
-     *  AssertState, etc. until after exception handling is on.
-     * ----------------
-     */
-    EnableExceptionHandling(true);
-    
-    /* ----------------
-     *  A stupid check to make sure we don't call this more than once.
-     *  But things like ReinitPostgres() get around this by just diddling
-     *  the PostgresIsInitialized flag.
-     * ----------------
-     */
-    AssertState(!PostgresIsInitialized);
-    
-    /* ----------------
-     *  Memory system initialization.
-     *  (we may call palloc after EnableMemoryContext())
-     *
-     *  Note EnableMemoryContext() must happen before EnablePortalManager().
-     * ----------------
-     */
-    EnableMemoryContext(true);  /* initializes the "top context" */
-    EnablePortalManager(true);  /* memory for portal/transaction stuff */
-    
-    /* ----------------
-     *  initialize the backend local portal stack used by
-     *  internal PQ function calls.  see src/lib/libpq/be-dumpdata.c
-     *  This is different from the "portal manager" so this goes here.
-     *  -cim 2/12/91
-     * ----------------
-     */    
-    be_portalinit();
-    
-    /* ----------------
-     *   attach to shared memory and semaphores, and initialize our
-     *   input/output/debugging file descriptors.
-     * ----------------
-     */
-    InitCommunication();
-    InitStdio();
-    
-    /*
-     * initialize the local buffer manager
-     */
-    InitLocalBuffer();
-
-    if (!TransactionFlushEnabled())
-        on_exitpg(FlushBufferPool, (caddr_t) NULL);
-    
-    if (bootstrap) {
-        SetDatabasePath(".");
-        SetDatabaseName(name);
-    } else {
-        DoChdirAndInitDatabaseNameAndPath(name);
-    }
-    
-    /* ********************************
-     *  code after this point assumes we are in the proper directory!
-     * ********************************
-     */
-    
-    /* ----------------
-     *  initialize the database id used for system caches and lock tables
-     * ----------------
-     */
-    InitMyDatabaseId();
-    
-    smgrinit();
-    
-    /* ----------------
-     *  initialize the transaction system and the relation descriptor
-     *  cache.  Note we have to make certain the lock manager is off while
-     *  we do this.
-     * ----------------
-     */
-    AmiTransactionOverride(IsBootstrapProcessingMode());
-    LockDisable(true);
-    
-    /*
-     * Part of the initialization processing done here sets a read
-     * lock on pg_log.  Since locking is disabled the set doesn't have
-     * intended effect of locking out writers, but this is ok, since
-     * we only lock it to examine AMI transaction status, and this is
-     * never written after initdb is done. -mer 15 June 1992
-     */
-    RelationInitialize();          /* pre-allocated reldescs created here */
-    InitializeTransactionSystem(); /* pg_log,etc init/crash recovery here */
-    
-    LockDisable(false);
-    
-    /* ----------------
-     *  anyone knows what this does?  something having to do with
-     *  system catalog cache invalidation in the case of multiple
-     *  backends, I think -cim 10/3/90
-     *  Sets up MyBackendId a unique backend identifier.
-     * ----------------
-     */
-    InitSharedInvalidationState();
-    
-    /* ----------------
-     * Set up a per backend process in shared memory.  Must be done after
-     * InitSharedInvalidationState() as it relies on MyBackendId being
-     * initialized already.  XXX -mer 11 Aug 1991
-     * ----------------
-     */
-    InitProcess(PostgresIpcKey);
-    
-    if (MyBackendId > MaxBackendId || MyBackendId <= 0) {
-        elog(FATAL, "cinit2: bad backend id %d (%d)",
-             MyBackendTag,
-             MyBackendId);
-    }
-    
-    /* ----------------
-     *  initialize the access methods.
-     * ----------------
-     */
-    initam();
-    
-    /* ----------------
-     *  initialize all the system catalog caches.
-     * ----------------
-     */
-    zerocaches();
-    InitCatalogCache();
-    
-    /* ----------------
-     *   set ourselves to the proper user id and figure out our postgres
-     *   user id.  If we ever add security so that we check for valid
-     *   postgres users, we might do it here.
-     * ----------------
-     */
-    InitUserid();
-    
-    /* ----------------
-     *  ok, all done, now let's make sure we don't do it again.
-     * ----------------
-     */
-    PostgresIsInitialized = true;
-/*    on_exitpg(DestroyLocalRelList, (caddr_t) NULL); */
-    
-    /* ----------------
-     *  Done with "InitPostgres", now change to NormalProcessing unless
-     *  we're in BootstrapProcessing mode.
-     * ----------------
-     */
-    if (!bootstrap)
-        SetProcessingMode(NormalProcessing);
-/*    if (testFlag || lockingOff) */
-    if (lockingOff)
-        LockDisable(true);
-}
+       bool            bootstrap;              /* true if BootstrapProcessing */
+
+       /* ----------------
+        *      see if we're running in BootstrapProcessing mode
+        * ----------------
+        */
+       bootstrap = IsBootstrapProcessingMode();
+
+       /* ----------------
+        *      turn on the exception handler.  Note: we cannot use elog, Assert,
+        *      AssertState, etc. until after exception handling is on.
+        * ----------------
+        */
+       EnableExceptionHandling(true);
+
+       /* ----------------
+        *      A stupid check to make sure we don't call this more than once.
+        *      But things like ReinitPostgres() get around this by just diddling
+        *      the PostgresIsInitialized flag.
+        * ----------------
+        */
+       AssertState(!PostgresIsInitialized);
+
+       /* ----------------
+        *      Memory system initialization.
+        *      (we may call palloc after EnableMemoryContext())
+        *
+        *      Note EnableMemoryContext() must happen before EnablePortalManager().
+        * ----------------
+        */
+       EnableMemoryContext(true);      /* initializes the "top context" */
+       EnablePortalManager(true);      /* memory for portal/transaction stuff */
+
+       /* ----------------
+        *      initialize the backend local portal stack used by
+        *      internal PQ function calls.  see src/lib/libpq/be-dumpdata.c
+        *      This is different from the "portal manager" so this goes here.
+        *      -cim 2/12/91
+        * ----------------
+        */
+       be_portalinit();
 
+       /* ----------------
+        *       attach to shared memory and semaphores, and initialize our
+        *       input/output/debugging file descriptors.
+        * ----------------
+        */
+       InitCommunication();
+       InitStdio();
 
+       /*
+        * initialize the local buffer manager
+        */
+       InitLocalBuffer();
+
+       if (!TransactionFlushEnabled())
+               on_shmem_exit(FlushBufferPool, (caddr_t) NULL);
+
+       /* ----------------
+        *      initialize the database id used for system caches and lock tables
+        * ----------------
+        */
+       if (bootstrap)
+       {
+               SetDatabasePath(ExpandDatabasePath(name));
+               SetDatabaseName(name);
+               LockDisable(true);
+       }
+       else
+       {
+               VerifySystemDatabase();
+               InitMyDatabaseInfo(name);
+               VerifyMyDatabase();
+       }
+
+       /*
+        * ********************************
+        *
+        * code after this point assumes we are in the proper directory!
+        *
+        * So, how do we implement alternate locations for databases? There are
+        * two possible locations for tables and we need to look in
+        * DataDir/pg_database to find the true location of an individual
+        * database. We can brute-force it as done in InitMyDatabaseInfo(), or
+        * we can be patient and wait until we open pg_database gracefully.
+        * Will try that, but may not work... - thomas 1997-11-01 ********************************
+        *
+        */
+
+       /* Does not touch files (?) - thomas 1997-11-01 */
+       smgrinit();
+
+       /* ----------------
+        *      initialize the transaction system and the relation descriptor cache.
+        *      Note we have to make certain the lock manager is off while we do this.
+        * ----------------
+        */
+       AmiTransactionOverride(IsBootstrapProcessingMode());
+       LockDisable(true);
+
+       /*
+        * Part of the initialization processing done here sets a read lock on
+        * pg_log.      Since locking is disabled the set doesn't have intended
+        * effect of locking out writers, but this is ok, since we only lock
+        * it to examine AMI transaction status, and this is never written
+        * after initdb is done. -mer 15 June 1992
+        */
+       RelationInitialize();           /* pre-allocated reldescs created here */
+       InitializeTransactionSystem();          /* pg_log,etc init/crash recovery
+                                                                                * here */
+
+       LockDisable(false);
+
+       /* ----------------
+        *      anyone knows what this does?  something having to do with
+        *      system catalog cache invalidation in the case of multiple
+        *      backends, I think -cim 10/3/90
+        *      Sets up MyBackendId a unique backend identifier.
+        * ----------------
+        */
+       InitSharedInvalidationState();
+
+       /* ----------------
+        * Set up a per backend process in shared memory.  Must be done after
+        * InitSharedInvalidationState() as it relies on MyBackendId being
+        * initialized already.  XXX -mer 11 Aug 1991
+        * ----------------
+        */
+       InitProcess(PostgresIpcKey);
+
+       if (MyBackendId > MaxBackendId || MyBackendId <= 0)
+       {
+               elog(FATAL, "cinit2: bad backend id %d (%d)",
+                        MyBackendTag,
+                        MyBackendId);
+       }
+
+       /* ----------------
+        *      initialize the access methods.
+        *      Does not touch files (?) - thomas 1997-11-01
+        * ----------------
+        */
+       initam();
+
+       /* ----------------
+        *      initialize all the system catalog caches.
+        * ----------------
+        */
+       zerocaches();
+
+       /*
+        * Does not touch files since all routines are builtins (?) - thomas
+        * 1997-11-01
+        */
+       InitCatalogCache();
+
+       /* ----------------
+        *       set ourselves to the proper user id and figure out our postgres
+        *       user id.  If we ever add security so that we check for valid
+        *       postgres users, we might do it here.
+        * ----------------
+        */
+       InitUserid();
+
+       /* ----------------
+        *       initialize local data in cache invalidation stuff
+        * ----------------
+        */
+       if (!bootstrap)
+               InitLocalInvalidateData();
+
+       /* ----------------
+        *      ok, all done, now let's make sure we don't do it again.
+        * ----------------
+        */
+       PostgresIsInitialized = true;
+/*       on_shmem_exit(DestroyLocalRelList, (caddr_t) NULL); */
+
+       /* ----------------
+        *      Done with "InitPostgres", now change to NormalProcessing unless
+        *      we're in BootstrapProcessing mode.
+        * ----------------
+        */
+       if (!bootstrap)
+               SetProcessingMode(NormalProcessing);
+/*       if (testFlag || lockingOff) */
+       if (lockingOff)
+               LockDisable(true);
+}