Subject: postgres for NS 3.1

From: [email-masked] (Tom R.Hageman)
Date: Thu, 9 Sep 93 19:52:14 +0200

Hello Aoki,

Here are some patches to postgres that were necessary to get it running on
NEXTSTEP 3.1. 

1) Sometimes the environment that is passed from the postmaster to the backend
was corrupted; apparently the semantics of vfork() has changed in NS 3.1...

*** 1.2 1993/08/13 16:52:04
--- src/backend/postmaster/postmaster.c        1993/09/03 00:23:08
***************
*** 663,667 ****
      BackendNode       *bn;            /* for backend cleanup */
      int               pid;
!     char              envEntry[4][2 * ARGV_SIZE];
      extern Pointer calloc();

--- 663,670 ----
      BackendNode       *bn;            /* for backend cleanup */
      int               pid;
!     static char       envEntry[4][2 * ARGV_SIZE];
!     /* XXX [TRH] declared static to avoid a snag with vfork and non-copying
!        putenv -- if allocated on stack the parent snatches it from under
!        the child's butt when this function returns... */
      extern Pointer calloc();

2) This is just a prototype fix:

*** 1.1.1.1     1993/08/11 13:05:16
--- src/backend/tmp/libpq.h     1993/09/02 16:57:38
***************
*** 213,216 ****
--- 213,219 ----
  extern void pq_putnchar ARGS((char *s, int n));
  extern void pq_putint ARGS((int i, int b));
+ #if __STDC__
+ struct sockaddr_in;
+ #endif
  extern int pq_getinaddr ARGS((struct sockaddr_in *sin, char *host, int port));
  extern int pq_getinserv ARGS((struct sockaddr_in *sin, char *host, char *serv));

3) This is to make dynamic loading work with multi-architecture binaries:

*** postgres/src/backend/port/next/dynloader.c:1.1	Mon Aug 30 16:40:36 1993
--- postgres/src/backend/port/next/dynloader.c	Mon Aug 30 16:40:36 1993
***************
*** 20,29 ****
  #include <mach/mach.h>
  #include <nlist.h>
  #include <mach-o/rld.h>

  static DynamicFunctionList *load_symbols();

- 

  /* Error message handling. */

  static struct {
--- 20,31 ----
  #include <mach/mach.h>
  #include <nlist.h>
  #include <mach-o/rld.h>
+ #include <mach-o/fat.h>
+ #include <mach-o/arch.h>

  static DynamicFunctionList *load_symbols();
+ static int handle_fat_binary();

  /* Error message handling. */

  static struct {
***************
*** 130,136 ****

  	NXGetMemoryBuffer(loadStream, &objAddr, &objSize, &dummy);

! 	if (!rld_load_from_memory(loadErrorStream, &header, filename,
  				  objAddr, objSize, NULL) ||
  	    (!(result = load_symbols(filename, objAddr, loadErrorStream)) &&
  	     (rld_unload(NULL), TRUE))) {
--- 132,139 ----

  	NXGetMemoryBuffer(loadStream, &objAddr, &objSize, &dummy);

! 	if (!handle_fat_binary(&objAddr, &objSize, filename, loadErrorStream) ||
! 	    !rld_load_from_memory(loadErrorStream, &header, filename,
  				  objAddr, objSize, NULL) ||
  	    (!(result = load_symbols(filename, objAddr, loadErrorStream)) &&
  	     (rld_unload(NULL), TRUE))) {
***************
*** 260,265 ****
--- 263,331 ----
  #endif
  	return funcList;
  }
+ 

+ 

+ /* Examine the memory-mapped file given by `*objAddrPtr' and `*objSizePtr'.
+    If it is a fat binary, adjust `*objAddrPtr' and `*objSizePtr' to point
+    to the object that matches the current architecture and return 1; if no
+    match is found, return 0.  If it is not a fat binary, don't do
+    anything and return -1. */
+ 

+ static int
+ handle_fat_binary(objAddrPtr, objSizePtr, filename, errorStream)
+ 

+ char **objAddrPtr;
+ int *objSizePtr;
+ const char *filename;
+ NXStream *errorStream;
+ 

+ {
+ 	struct fat_header *fat_header = (struct fat_header *) *objAddrPtr;
+ 	struct fat_arch *fat_arch = (struct fat_arch *) &fat_header[1];
+ 	const NXArchInfo *hostArch;
+ 	unsigned long i;
+ 

+ 	if (fat_header->magic == FAT_MAGIC) {
+ 		/* A fat file, in host order */
+ 	}
+ 	else if (fat_header->magic == FAT_CIGAM) {
+ 		/* A fat file, in non-host order; must be swapped. */
+ 		unsigned long *lp = (long *) fat_header;
+ 

+ 		i = (NXSwapLong(fat_header->nfat_arch) * sizeof(*fat_arch) +
+ 		     sizeof(*fat_header)) / sizeof(unsigned long);
+ 

+ 		do {
+ 			*lp = NXSwapLong(*lp);
+ 			lp++;
+ 		} while (--i);
+ 	}
+ 	else {
+ 		/* Not a fat file. */
+ 		return -1;
+ 	}
+ 

+ 	/* Now that we have a fat file, find a member that matches the
+ 	   host architecture. */
+ 	if ((hostArch = NXGetLocalArchInfo()) == NULL) {
+ 		NXPrintf(errorStream, "cannot determine architecture of host!");
+ 		return 0;
+ 	}
+ 	if ((fat_arch = NXFindBestFatArch(hostArch->cputype,
+ 					  hostArch->cpusubtype, fat_arch,
+ 					  fat_header->nfat_arch)) == NULL) {
+ 		NXPrintf(errorStream, "cannot find matching architecture"
+ 			 " for %s in fat file %s.", hostArch->name, filename);
+ 		return 0;
+ 	}
+ 

+ 	/* Adjust object address and -size to point to the matching member. */
+ 	(*objAddrPtr) += fat_arch->offset;
+ 	(*objSizePtr) = fat_arch->size;
+ 

+ 	return 1;
+ }
+ 

  func_ptr
  dynamic_load(err)

4) This is an argument type fix, necessary to get it compiled if ntonl() has a prototype:

*** postgres/src/bin/unfsd/init.c:1.2	Mon Aug 30 16:42:11 1993
--- postgres/src/bin/unfsd/init.c	Mon Aug 30 16:42:11 1993
***************
*** 522,528 ****
  	else
  	{
  		syslog(LOG_DAEMON|LOG_CRIT, "Access attempt by unknown client %08X",
! 			ntohl(svc_getcaller(rqstp->rq_xprt)->sin_addr));
  		return NULL;
  	}
      found_it:
--- 522,528 ----
  	else
  	{
  		syslog(LOG_DAEMON|LOG_CRIT, "Access attempt by unknown client %08X",
! 			ntohl(svc_getcaller(rqstp->rq_xprt)->sin_addr.s_addr));
  		return NULL;
  	}
      found_it:
***************
*** 530,536 ****
  	if (ntohs(svc_getcaller(rqstp->rq_xprt)->sin_port) >= IPPORT_RESERVED && cp->o.secure_port)
  	{
  		syslog(LOG_DAEMON|LOG_CRIT, "NFS request from %08X originated on insecure port",
! 			ntohl(svc_getcaller(rqstp->rq_xprt)->sin_addr));
  		return NULL;
  	}
  	return cp;
--- 530,536 ----
  	if (ntohs(svc_getcaller(rqstp->rq_xprt)->sin_port) >= IPPORT_RESERVED && cp->o.secure_port)
  	{
  		syslog(LOG_DAEMON|LOG_CRIT, "NFS request from %08X originated on insecure port",
! 			ntohl(svc_getcaller(rqstp->rq_xprt)->sin_addr.s_addr));
  		return NULL;
  	}
  	return cp;

BTW, is it a good idea to roll the functionality of the postmaster into the postgres backend?
(I.e., have postgres' main() call PostMasterMain() when it is invoked as postmaster.)
In my opinion this has the following advantages:
 - better use of VM (code sections of postgres and postmaster can be shared in memory)
 - shorter link time (only need to link one large executable instead of 2)
 - less disk usage (postmaster can be a link to postgres)
and I see no disadvantages (but maybe I'm biased;-)

Bye,
--
__/__/__/__/  Tom Hageman  ([email-masked])  [NeXTMail accepted]
  __/ __/_/
 __/__/__/
__/  _/_/           <space for quote intentionally left blank>