Index: doc/src/sgml/runtime.sgml
===================================================================
RCS file: /cvsroot/pgsql-server/doc/src/sgml/runtime.sgml,v
retrieving revision 1.124
diff -c -r1.124 runtime.sgml
*** doc/src/sgml/runtime.sgml	12 Aug 2002 00:36:11 -0000	1.124
--- doc/src/sgml/runtime.sgml	14 Aug 2002 01:30:15 -0000
***************
*** 1191,1196 ****
--- 1191,1208 ----
       
  
       
+       DB_USER_NAMESPACE (boolean)
+       
+        
+         Prepends the database name and a period to the username when 
+         connecting to the database.  This allows per-database users.  
+         The user who ran initdb> is excluded from this
+         handling.
+        
+       
+      
+ 
+      
        
         deadlock
         timeout
Index: src/backend/libpq/auth.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/libpq/auth.c,v
retrieving revision 1.82
diff -c -r1.82 auth.c
*** src/backend/libpq/auth.c	20 Jun 2002 20:29:28 -0000	1.82
--- src/backend/libpq/auth.c	14 Aug 2002 01:30:15 -0000
***************
*** 117,123 ****
  			 version, PG_KRB4_VERSION);
  		return STATUS_ERROR;
  	}
! 	if (strncmp(port->user, auth_data.pname, SM_USER) != 0)
  	{
  		elog(LOG, "pg_krb4_recvauth: name \"%s\" != \"%s\"",
  			 port->user, auth_data.pname);
--- 117,123 ----
  			 version, PG_KRB4_VERSION);
  		return STATUS_ERROR;
  	}
! 	if (strncmp(port->user, auth_data.pname, SM_DATABASE_USER) != 0)
  	{
  		elog(LOG, "pg_krb4_recvauth: name \"%s\" != \"%s\"",
  			 port->user, auth_data.pname);
***************
*** 290,296 ****
  	}
  
  	kusername = pg_an_to_ln(kusername);
! 	if (strncmp(port->user, kusername, SM_USER))
  	{
  		elog(LOG, "pg_krb5_recvauth: user name \"%s\" != krb5 name \"%s\"",
  			 port->user, kusername);
--- 290,296 ----
  	}
  
  	kusername = pg_an_to_ln(kusername);
! 	if (strncmp(port->user, kusername, SM_DATABASE_USER))
  	{
  		elog(LOG, "pg_krb5_recvauth: user name \"%s\" != krb5 name \"%s\"",
  			 port->user, kusername);
Index: src/backend/postmaster/postmaster.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/postmaster/postmaster.c,v
retrieving revision 1.283
diff -c -r1.283 postmaster.c
*** src/backend/postmaster/postmaster.c	10 Aug 2002 20:29:18 -0000	1.283
--- src/backend/postmaster/postmaster.c	14 Aug 2002 01:30:17 -0000
***************
*** 116,122 ****
  sigset_t	UnBlockSig,
  			BlockSig,
  			AuthBlockSig;
- 
  #else
  int			UnBlockSig,
  			BlockSig,
--- 116,121 ----
***************
*** 191,196 ****
--- 190,197 ----
  bool		HostnameLookup;		/* for ps display */
  bool		ShowPortNumber;
  bool		Log_connections = false;
+ bool		Db_user_namespace = false;
+ 
  
  /* Startup/shutdown state */
  static pid_t StartupPID = 0,
***************
*** 208,213 ****
--- 209,216 ----
  
  bool ClientAuthInProgress = false;	/* T during new-client authentication */
  
+ static char InstallUser[SM_USER+1];
+ 
  /*
   * State for assigning random salts and cancel keys.
   * Also, the global MyCancelKey passes the cancel key assigned to a given
***************
*** 258,263 ****
--- 261,267 ----
  static void SignalChildren(int signal);
  static int	CountChildren(void);
  static bool CreateOptsFile(int argc, char *argv[]);
+ static bool GetInstallUser(void);
  static pid_t SSDataBase(int xlop);
         void
  postmaster_error(const char *fmt,...)
***************
*** 690,695 ****
--- 694,702 ----
  	if (!CreateOptsFile(argc, argv))
  		ExitPostmaster(1);
  
+ 	if (!GetInstallUser())
+ 		ExitPostmaster(1);
+ 
  	/*
  	 * Set up signal handlers for the postmaster process.
  	 *
***************
*** 1161,1166 ****
--- 1168,1182 ----
  	if (port->user[0] == '\0')
  		elog(FATAL, "no PostgreSQL user name specified in startup packet");
  
+ 	/* Prefix database name for per-db user namespace */
+ 	if (Db_user_namespace && strcmp(port->user, InstallUser))
+ 	{
+ 		char hold_user[SM_DATABASE_USER];
+ 		snprintf(hold_user, SM_DATABASE_USER, "%s.%s", port->database,
+ 				 port->user);
+ 		strcpy(port->user, hold_user);
+ 	}
+ 
  	/*
  	 * If we're going to reject the connection due to database state, say
  	 * so now instead of wasting cycles on an authentication exchange.
***************
*** 2587,2597 ****
  	if (FindExec(fullprogname, argv[0], "postmaster") < 0)
  		return false;
  
! 	filename = palloc(strlen(DataDir) + 20);
  	sprintf(filename, "%s/postmaster.opts", DataDir);
  
! 	fp = fopen(filename, "w");
! 	if (fp == NULL)
  	{
  		postmaster_error("cannot create file %s: %s",
  						 filename, strerror(errno));
--- 2603,2612 ----
  	if (FindExec(fullprogname, argv[0], "postmaster") < 0)
  		return false;
  
! 	filename = palloc(strlen(DataDir) + 17);
  	sprintf(filename, "%s/postmaster.opts", DataDir);
  
! 	if ((fp = fopen(filename, "w")) == NULL)
  	{
  		postmaster_error("cannot create file %s: %s",
  						 filename, strerror(errno));
***************
*** 2614,2619 ****
--- 2629,2669 ----
  	return true;
  }
  
+ /*
+  * Load install user so db_user_namespace can skip it.
+  */
+ static bool
+ GetInstallUser(void)
+ {
+ 	char	   *filename;
+ 	FILE	   *fp;
+ 
+ 	filename = palloc(strlen(DataDir) + 14);
+ 	sprintf(filename, "%s/PG_INSTALLER", DataDir);
+ 
+ 	if ((fp = fopen(filename, "r")) == NULL)
+ 	{
+ 		postmaster_error("cannot open file %s: %s",
+ 						 filename, strerror(errno));
+ 		return false;
+ 	}
+ 
+ 	if (fgets(InstallUser, SM_USER+1, fp) == NULL)
+ 	{
+ 		postmaster_error("cannot read file %s: %s",
+ 						 filename, strerror(errno));
+ 		return false;
+ 	}
+ 
+ 	/* Trim off trailing newline */
+ 	if (strchr(InstallUser, '\n') != NULL)
+ 		*strchr(InstallUser, '\n') = '\0';
+ 	
+ 	fclose(fp);
+ 	return true;
+ }
+ 
+ 	
  /*
   * This should be used only for reporting "interactive" errors (ie, errors
   * during startup.  Once the postmaster is launched, use elog.
Index: src/backend/utils/misc/guc.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/misc/guc.c,v
retrieving revision 1.79
diff -c -r1.79 guc.c
*** src/backend/utils/misc/guc.c	12 Aug 2002 00:36:11 -0000	1.79
--- src/backend/utils/misc/guc.c	14 Aug 2002 01:30:20 -0000
***************
*** 482,487 ****
--- 482,491 ----
  		{ "transform_null_equals", PGC_USERSET }, &Transform_null_equals,
  		false, NULL, NULL
  	},
+ 	{
+ 		{ "db_user_namespace", PGC_SIGHUP }, &Db_user_namespace,
+ 		false, NULL, NULL
+ 	},
  
  	{
  		{ NULL, 0 }, NULL, false, NULL, NULL
Index: src/backend/utils/misc/postgresql.conf.sample
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/misc/postgresql.conf.sample,v
retrieving revision 1.44
diff -c -r1.44 postgresql.conf.sample
*** src/backend/utils/misc/postgresql.conf.sample	12 Aug 2002 00:36:12 -0000	1.44
--- src/backend/utils/misc/postgresql.conf.sample	14 Aug 2002 01:30:20 -0000
***************
*** 113,119 ****
  #
  #	Message display
  #
- 
  #server_min_messages = notice	# Values, in order of decreasing detail:
  				#   debug5, debug4, debug3, debug2, debug1,
  				#   info, notice, warning, error, log, fatal,
--- 113,118 ----
***************
*** 201,203 ****
--- 200,203 ----
  #sql_inheritance = true
  #transform_null_equals = false
  #statement_timeout = 0				# 0 is disabled
+ #db_user_namespace = false
Index: src/bin/initdb/initdb.sh
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/initdb/initdb.sh,v
retrieving revision 1.165
diff -c -r1.165 initdb.sh
*** src/bin/initdb/initdb.sh	8 Aug 2002 19:39:05 -0000	1.165
--- src/bin/initdb/initdb.sh	14 Aug 2002 01:30:20 -0000
***************
*** 603,608 ****
--- 603,613 ----
  # Top level PG_VERSION is checked by bootstrapper, so make it first
  echo "$short_version" > "$PGDATA/PG_VERSION" || exit_nicely
  
+ # Top level PG_INSTALLER is used by db_user_namespace to prevent username 
+ # mapping just for the install user.
+ echo "$POSTGRES_SUPERUSERNAME" > "$PGDATA/PG_INSTALLER" || exit_nicely
+ 
+ 
  cat "$POSTGRES_BKI" \
  | sed -e "s/POSTGRES/$POSTGRES_SUPERUSERNAME/g" \
        -e "s/ENCODING/$MULTIBYTEID/g" \
Index: src/include/libpq/libpq-be.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/libpq/libpq-be.h,v
retrieving revision 1.32
diff -c -r1.32 libpq-be.h
*** src/include/libpq/libpq-be.h	20 Jun 2002 20:29:49 -0000	1.32
--- src/include/libpq/libpq-be.h	14 Aug 2002 01:30:20 -0000
***************
*** 59,65 ****
  
  	ProtocolVersion proto;
  	char		database[SM_DATABASE + 1];
! 	char		user[SM_USER + 1];
  	char		options[SM_OPTIONS + 1];
  	char		tty[SM_TTY + 1];
  	char		auth_arg[MAX_AUTH_ARG];
--- 59,65 ----
  
  	ProtocolVersion proto;
  	char		database[SM_DATABASE + 1];
! 	char		user[SM_DATABASE_USER + 1];
  	char		options[SM_OPTIONS + 1];
  	char		tty[SM_TTY + 1];
  	char		auth_arg[MAX_AUTH_ARG];
***************
*** 72,78 ****
  	SSL		   *ssl;
  	X509	   *peer;
  	char		peer_dn[128 + 1];
! 	char		peer_cn[SM_USER + 1];
  	unsigned long count;
  #endif
  } Port;
--- 72,78 ----
  	SSL		   *ssl;
  	X509	   *peer;
  	char		peer_dn[128 + 1];
! 	char		peer_cn[SM_DATABASE_USER + 1];
  	unsigned long count;
  #endif
  } Port;
Index: src/include/libpq/pqcomm.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/libpq/pqcomm.h,v
retrieving revision 1.65
diff -c -r1.65 pqcomm.h
*** src/include/libpq/pqcomm.h	12 Aug 2002 14:35:26 -0000	1.65
--- src/include/libpq/pqcomm.h	14 Aug 2002 01:30:20 -0000
***************
*** 114,119 ****
--- 114,121 ----
  #define SM_DATABASE		64
  /* SM_USER should be the same size as the others.  bjm 2002-06-02 */
  #define SM_USER			32
+ /* We prepend database name if db_user_namespace true. */
+ #define SM_DATABASE_USER (SM_DATABASE+SM_USER)
  #define SM_OPTIONS		64
  #define SM_UNUSED		64
  #define SM_TTY			64
***************
*** 124,135 ****
--- 126,139 ----
  {
  	ProtocolVersion protoVersion;		/* Protocol version */
  	char		database[SM_DATABASE];	/* Database name */
+ 				/* Db_user_namespace prepends dbname */
  	char		user[SM_USER];	/* User name */
  	char		options[SM_OPTIONS];	/* Optional additional args */
  	char		unused[SM_UNUSED];		/* Unused */
  	char		tty[SM_TTY];	/* Tty for debug output */
  } StartupPacket;
  
+ extern bool Db_user_namespace;
  
  /* These are the authentication requests sent by the backend. */