head	1.57;
access;
symbols
	Version_2_1:1.40
	old_buffer_manager:1.22
	Version_2:1.16
	C_Demo_1:1.9;
locks; strict;
comment	@ * @;


1.57
date	92.08.12.02.47.20;	author mao;	state Exp;
branches;
next	1.56;

1.56
date	92.06.10.05.18.42;	author mer;	state Exp;
branches;
next	1.55;

1.55
date	92.05.21.18.06.05;	author mer;	state Exp;
branches;
next	1.54;

1.54
date	92.04.28.00.25.49;	author mer;	state Exp;
branches;
next	1.53;

1.53
date	92.04.27.22.35.18;	author mer;	state Exp;
branches;
next	1.52;

1.52
date	91.12.16.20.43.25;	author mer;	state Exp;
branches;
next	1.51;

1.51
date	91.11.18.20.17.57;	author clarsen;	state Exp;
branches;
next	1.50;

1.50
date	91.11.07.22.13.55;	author mer;	state Exp;
branches;
next	1.49;

1.49
date	91.09.09.23.58.33;	author mao;	state Exp;
branches;
next	1.48;

1.48
date	91.08.15.15.00.49;	author mer;	state Exp;
branches;
next	1.47;

1.47
date	91.08.14.12.36.50;	author mer;	state Exp;
branches;
next	1.46;

1.46
date	91.08.12.15.25.00;	author mer;	state Exp;
branches;
next	1.45;

1.45
date	91.07.22.22.20.07;	author mao;	state Exp;
branches;
next	1.44;

1.44
date	91.07.22.14.52.31;	author mer;	state Exp;
branches;
next	1.43;

1.43
date	91.05.08.15.19.33;	author choi;	state Exp;
branches;
next	1.42;

1.42
date	91.03.20.19.17.11;	author cimarron;	state Exp;
branches;
next	1.41;

1.41
date	91.03.10.21.10.52;	author kemnitz;	state Exp;
branches;
next	1.40;

1.40
date	91.03.09.06.58.57;	author kemnitz;	state Exp;
branches;
next	1.39;

1.39
date	91.03.09.04.10.16;	author kemnitz;	state Exp;
branches;
next	1.38;

1.38
date	91.03.07.23.18.35;	author kemnitz;	state Exp;
branches;
next	1.37;

1.37
date	91.03.05.12.57.04;	author mao;	state Exp;
branches;
next	1.36;

1.36
date	91.03.05.10.27.27;	author mer;	state Exp;
branches;
next	1.35;

1.35
date	91.03.01.17.49.12;	author mer;	state Exp;
branches;
next	1.34;

1.34
date	91.03.01.17.44.08;	author mer;	state Exp;
branches;
next	1.33;

1.33
date	91.02.28.13.46.51;	author mer;	state Exp;
branches;
next	1.32;

1.32
date	91.02.28.10.38.30;	author mer;	state Exp;
branches;
next	1.31;

1.31
date	91.02.27.00.15.18;	author hong;	state Exp;
branches;
next	1.30;

1.30
date	91.02.26.22.50.42;	author mer;	state Exp;
branches;
next	1.29;

1.29
date	91.02.25.13.36.26;	author sp;	state Exp;
branches;
next	1.28;

1.28
date	91.02.22.17.12.43;	author mer;	state Exp;
branches;
next	1.27;

1.27
date	91.02.06.13.32.21;	author kemnitz;	state Exp;
branches;
next	1.26;

1.26
date	91.02.06.13.17.19;	author kemnitz;	state Exp;
branches;
next	1.25;

1.25
date	91.02.04.17.28.24;	author kemnitz;	state Exp;
branches;
next	1.24;

1.24
date	91.02.02.18.34.10;	author mao;	state Exp;
branches;
next	1.23;

1.23
date	91.01.18.22.22.04;	author hong;	state Exp;
branches;
next	1.22;

1.22
date	90.10.16.00.29.30;	author kemnitz;	state Exp;
branches;
next	1.21;

1.21
date	90.09.25.17.23.59;	author kemnitz;	state Exp;
branches;
next	1.20;

1.20
date	90.09.25.15.52.02;	author kemnitz;	state Exp;
branches;
next	1.19;

1.19
date	90.09.18.21.57.26;	author hong;	state Exp;
branches;
next	1.18;

1.18
date	90.08.24.14.40.14;	author choi;	state Exp;
branches;
next	1.17;

1.17
date	90.08.23.16.02.59;	author hong;	state Exp;
branches;
next	1.16;

1.16
date	90.05.25.12.16.44;	author kemnitz;	state Version_2;
branches;
next	1.15;

1.15
date	90.04.19.17.49.45;	author kemnitz;	state Exp;
branches;
next	1.14;

1.14
date	90.04.11.21.42.26;	author kemnitz;	state Exp;
branches;
next	1.13;

1.13
date	90.03.31.19.06.04;	author cimarron;	state Exp;
branches;
next	1.12;

1.12
date	90.02.12.19.51.24;	author cimarron;	state Exp;
branches;
next	1.11;

1.11
date	89.11.24.15.55.35;	author hirohama;	state Exp;
branches;
next	1.10;

1.10
date	89.09.21.18.58.34;	author hirohama;	state Exp;
branches;
next	1.9;

1.9
date	89.09.05.16.53.19;	author mao;	state C_Demo_1;
branches;
next	1.8;

1.8
date	89.08.31.17.52.38;	author mao;	state Exp;
branches;
next	1.7;

1.7
date	89.08.31.10.21.08;	author goh;	state Exp;
branches;
next	1.6;

1.6
date	89.08.30.18.52.04;	author goh;	state Exp;
branches;
next	1.5;

1.5
date	89.08.02.23.56.46;	author dillon;	state Exp;
branches;
next	1.4;

1.4
date	89.07.17.14.40.16;	author dillon;	state Exp;
branches;
next	1.3;

1.3
date	89.04.14.18.33.41;	author dillon;	state Exp;
branches;
next	1.2;

1.2
date	89.02.02.15.58.13;	author dillon;	state Stab;
branches;
next	1.1;

1.1
date	89.01.17.05.57.58;	author cimarron;	state Exp;
branches;
next	;


desc
@@


1.57
log
@two new flags:  -n keeps the postmaster from reinitializing shared memory
after a backend dumps core, and -s tells it to send SIGSTOP, rather than
SIGUSR1, to peers of the dead backend.
@
text
@/*
 * $Header: /private/mao/postgres/src/support/RCS/postmaster.c,v 1.56 1992/06/10 05:18:42 mer Exp $
 *
 *	POSTMASTER
 *
 *	This program acts as a clearing house for requests to the
 *	POSTGRES system.  Frontend programs send a startup message
 *	to the Postmaster and the postmaster uses the info in the
 *	message to setup a backend process.
 *
 * Initialization:
 *	The Postmaster sets up a few shared memory data structures 
 * 	for the backends.  It should at the very least initialize the
 *	lock manager.
 *
 * Synchronization:
 *	The Postmaster shares memory with the backends and will have to lock
 *	the shared memory it accesses.  The Postmaster should never block
 *	on messages from clients.
 *	
 * Garbage Collection:
 *	The Postmaster cleans up after backends if they have an emergency
 *	exit and/or core dump.
 *
 * Communication:
 *
 * Security:  
 *	There is none. Not a little bit.
 *
 * NOTES:
 *
 */

#include <signal.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <netdb.h>
#if !sprite
#include <sys/un.h>
#endif /* !sprite */

#include "support/master.h"
#include "utils/log.h"
#include "storage/ipci.h"
#include "tmp/pqcomm.h"
#include "catalog/pg_user.h"
#include "support/list.h"

/* default permissions for opening files. */
#define OPEN_PERMISSIONS	(0666)

List *ListGarbage;	/* holds used list nodes for future use */
short CommPort;
char ShmIdStr[10];
char ShmSizeStr[10];
extern char *GetPGHome();


#ifdef DBX_VERSION
#define FORK() (0)
#else
#define FORK() fork()
#endif

/*
 * Info for garbage collection.  Whenever a process dies, the Postmaster
 * cleans up after it.  Currently, NO information is required for cleanup,
 * but I left this structure around in case that changed.
 */
typedef struct	bkend	{
  int			pid;	/* process id of backend */
} Backend;

/* list of active backends.  For garbage collection only now. */
List	*BackendList;


/* list of ports associated with still open, but incomplete connections */
List	*PortList;

/* for elog() messages.  Port to send the message to. */
Port	*SendPort;

/*
 * Default startup message parameters.  
 */
StartupPacket DefaultStartup;

/*
 * IOList is used to setup file descriptors of backend processes.
 *	Specify here how the descriptor set of the child (backend)
 *	is different from the parent (Postmaster).  I'm not sure
 *	this stuff works all that well.  I don't use any of the 
 * 	sys logs.
 *
 * See descriptor reset for some notes.
 */
typedef struct IOList {
  int	fd;
  char  *name;
  int	mode;
} IOList;

#define DEFAULT	""

IOList IO_List[] = {
  { 0, DEFAULT, (O_RDONLY) },
  { 1, DEFAULT, (O_WRONLY | O_APPEND | O_CREAT) },
  { 2, DEFAULT, (O_WRONLY | O_APPEND| O_CREAT) },
  { 0, NULL, 0 },
};

extern int NBuffers;

extern char *optarg;
extern int opterr;
extern int optind;
extern int errno;

extern bool	IsPostmaster;

short	PostPortName =	DEF_PORT;
short	ActiveBackends = FALSE;
int	NextBackendId = 0x7fffffff;	/* XXX not sure what this does */

char *Usage = "postmaster [ -p port ] [ -b backend_pathname ] [ -d [level] ]\n";
/*
 * Default Values
 */
char Username[USER_NAMESIZE];
char Dbname[64];

/* 
 * This is set by getpghome().
 */
char *Home = "";

int	ServerSock = INVALID_SOCK;  /* stream socket server */

/* 
 * Set by the -d option
 */
int	Debug = 0;

/*
 * Set by the -o option
 */
char ExtraOptions[ARGV_SIZE] = {0};

/*
 * These globals control the behavior of the postmaster in case some
 * backend dumps core.  Normally, it kills all peers of the dead backend
 * and reinitializes shared memory.  By specifying -s or -n, we can have
 * the postmaster stop (rather than kill) peers and not reinitialize
 * shared data structures.
 */
int	Reinit = 1;
int	SendStop = 0;

/* 
 * postmaster.c - function prototypes (none of the funcs are public use)
 */
int ServerLoop ARGS((int serverFd ));
int ConnStartup ARGS((Port *port ));
int ConnCreate ARGS((int serverFd , int *newFdP ));
int PortDestroy ARGS((Port *port ));
int pmdie ARGS((void ));
int reaper ARGS((void ));
int CleanupProc ARGS((int pid , int exitstatus ));
int BackendStartup ARGS((Port *port , StartupPacket *packet , IOList *ioList ));
int fixlead ARGS((char *str , char **dstP , int *sizeP ));
int DoExec ARGS((char *execFile , char *database , int portFd , StartupPacket *pack ));
int DescriptorReset ARGS((IOList *ioList ));
int ExitPostmaster ARGS((int status ));
int FindBackend ARGS((char *backend ));
int ValidBackend ARGS((char *path ));
int ReadObjDir ARGS((char *dir ));
char *zalloc ARGS((unsigned long size ));
#if 0
int *CacheAlloc ARGS((unsigned int size ));
#endif

main(argc, argv)
int	argc;
char	*argv[];
{
  char  	*getenv();
  char		getopt();
  char		opt;
  int		serverMask;
  char		*hostName;
  int		status;
  int		size;
  char 		sysLogPath[PATH_SIZE];
  char		*sysLogPtr = sysLogPath;
  char 		dblogPath[PATH_SIZE];
  char		*dblogPtr = dblogPath;

  /*
   * Initialize signal handlers.  I took this from Dillon's code.
   * Not sure who made the decision about what signals to handle.
   */
  signal(SIGCHLD, reaper);
  signal(SIGTTIN, SIG_IGN);
  signal(SIGTTOU, SIG_IGN);
  
  signal(SIGHUP, pmdie);
  signal(SIGINT, pmdie);
  signal(SIGTERM, pmdie);

  ListHead(&ListGarbage);	/* initialize ListGarbage */

  if (!(hostName = getenv("PGHOST"))) {
    hostName = "localhost";
  }

  opterr = 0;
  while ((opt = getopt(argc, argv, "B:b:dno:p:s")) != EOF) {
	switch (opt) {
		case 'B':
			/*
			 * The number of buffers to create.  Setting this
			 * option means we have to start each backend with
			 * a -B # to make sure they know how many buffers
			 * were allocated.
			 */
			NBuffers = atol(optarg);
			strcat(ExtraOptions, "-B ");
			strcat(ExtraOptions, optarg);
			break;
		case 'b':
			if (ValidBackend(optarg))
  				strcpy(DefaultStartup.execFile, optarg);
			else
				fprintf(stderr, "%s %s",
			  		"Couldn't find the requested backend",
			  		"-- Using a default search path...\n");
			break;
		case 'd':
			if ((optind < argc) && *argv[optind] != '-') {
				Debug = atoi(argv[optind]);
				optind++;
			}
			else
				Debug = 1;
			break;
		case 'n':
			/* don't reinit shared mem after abnormal exit */
			Reinit = 0;
			break;
		case 'o':
			/*
			 * Other options to pass to the backend on the
			 * command line -- Useful only for debugging.
			 */
			strcat(ExtraOptions, optarg);
			break;
		case 'p':
			PostPortName = (short)atoi(optarg);
			break;
		case 's':
			/*
			 *  In the event that some backend dumps core,
			 *  send SIGSTOP, rather than SIGUSR1, to all
			 *  its peers.  This lets the wily post_hacker
			 *  collect core dumps from everyone.
			 */
			SendStop = 1;
			break;
		default:
			perror("argument list");
			fprintf(stderr, "Usage: %s", Usage);
			exit(errno);
			break;
	}
  }

  IsPostmaster = true;

  Home = GetPGHome();

  /* default startup values */
  if (! DefaultStartup.execFile[0])
  	FindBackend(DefaultStartup.execFile);

  strncpy(Username, getenv("USER"), USER_NAMESIZE);
  strcpy(DefaultStartup.user, Username);
  strcpy(DefaultStartup.database,Username);
  strcpy(Dbname, Username);

  status = StreamServerPort(hostName,PostPortName, &ServerSock);
  if (status != STATUS_OK)  {
    elog(WARN,"PostMaster:cannot create stream port") ;
    exit(1);
  }

  /* set up shared memory and semaphores */
  EnableMemoryContext(TRUE);
  CreateSharedMemoryAndSemaphores(
	SystemPortAddressCreateIPCKey((SystemPortAddress)PostPortName));

  /*
   * Initialize the list of active backends.  This list is only
   * used for garbage collecting the backend processes.
   */
  ListHead(&BackendList);
  ListHead(&PortList);

  status = ServerLoop(ServerSock);
  ExitPostmaster(status != STATUS_OK);
}

ServerLoop(serverFd)
int	serverFd;
{
  int		mask;
  int		baseMask;
  int		serverMask;
  int		nSockets;
  int		nSelected;
  int		status;
  int		dummy;
  List		*curr;

  nSockets  = ServerSock+1;
  baseMask = 1 << ServerSock;
  serverMask = baseMask;

  for (;;) {
    dummy = 0;
    mask = baseMask;
    if ((nSelected = select(nSockets, &mask, &dummy, &dummy, NULL)) < 0) {
      if (errno == EINTR)
	continue;
      elog(WARN,"Postmaster: select failed");
      return(STATUS_ERROR);
    }

    if (serverMask & mask) {
      int	newFd;
      int	newMask;

      status = ConnCreate(serverFd, &newFd);

      if (newFd >= nSockets)
	nSockets = newFd+1;

      /* read the new connection on the first pass */
      newMask = 1 << newFd;
      nSelected--;
      /* add the new connection to the baseMask */
      baseMask |= newMask;
    }

    ListForEach( curr, PortList, PortList) {
      ConnId		connId;	/* dummy argument */
      Port		*port;	/* port for I/O */

      port = (Port *) ListElem(curr);

      if (port->mask & mask) {
	nSelected--;
	
	/*
	 * read the incoming packet into its packet buffer.  Read the
	 * connection id out of the packet so we know who the packet
	 * is from. 
	 */
	status = PacketReceive(port, (Addr) &port->buf,
			       NON_BLOCKING, &connId);
	switch (status) {
	case STATUS_OK:
	  ConnStartup (port);
	  ActiveBackends = TRUE;
	  baseMask &= ~ port->mask;
	  PortDestroy (port) ;
	  ListDelete (curr) ;
	  break;

	case STATUS_INVALID:
	  baseMask &= ~ port->mask;
	  PortDestroy (port) ;
	  ListDelete (curr) ;
	  break;

	case STATUS_NOT_DONE:
	  break;

	case STATUS_ERROR:
	  elog(WARN,"Postmaster: error receiving packet\n");
	  return(STATUS_ERROR);
	}
      }
    }
    Assert (! nSelected);
  }
  /* shouldn't ever get here */
}

ConnStartup(port)
Port	*port;		/* receiving port */	
{
    int 	status;		/* procedure return code */
    MsgType	msgType;	/* type of message recieved */
    SeqNo	seqno= INITIAL_SEQNO;/* dummy argument expected by packetData*/
    PacketLen	bufSize;	/* dummy argument */
    Addr	buf;		/* dummy argument */

    /*
     * Get the packet header information.
     */
    PacketData((Addr) &port->buf, &buf, &bufSize, &msgType,  &seqno);
    if (msgType != STARTUP_MSG) {
      elog(WARN,"Postmaster: unrecognized message type\n");
      return(STATUS_ERROR);
    }
    if (BackendStartup(port, (StartupPacket *)&port->buf, IO_List) != STATUS_OK)
    {
      elog(WARN,"Postmaster: couldn't startup backend for client\n");
      return(STATUS_ERROR);
    }
    return(STATUS_OK);
}


/*
 * ConnCreate -- create a local connection data structure
 */
ConnCreate(serverFd, newFdP)
int		serverFd;
int		*newFdP;
{
  Connection	*conn;
  int		connId;
  int		status;
  long		currTime;
  int		newFd;
  Port		*port = (Port *) zalloc(sizeof(Port));


  status = StreamConnection(serverFd,&newFd,&port->addr);

  port->sock = newFd;
  port->mask = 1 << newFd;

  ListPush(PortList, port);
  *newFdP = newFd;

  /* in case of error message */
  SendPort = port;

  /* 
   * If there was an error in the port creation, the connection
   * struct should be freed again.
   */
  if (status != STATUS_OK) {
    PortDestroy ( port ) ;
  }

  return(status);
}

PortDestroy(port)
Port	*port;
{
  StreamClose( port->sock );
  free ((char *)port);
}

/*
 * pmdie -- signal handler for cleaning up after a kill signal.
 */
pmdie()
{
  exitpg(0);
}

/*
 * Reaper -- signal handler to cleanup after a backend (child) dies.
 *
 */
reaper()
{
  union	wait	status;		/* backend exit status */
  struct	rusage	ruse;	/* resource usage structure */
  int		pid;		/* process id of dead backend */

  if (Debug)
    fprintf(stderr, "In reaper\n");
  while ((pid = wait3(&status, WNOHANG, &ruse)) > 0) {
    (void) CleanupProc(pid,status.w_status);
  }
}

/*
 * CleanupProc -- cleanup after terminated backend.
 *
 * Remove all local state associated with backend.
 *
 * Dillon's note: should log child's exit status in the system log.
 */
CleanupProc(pid,exitstatus)
int	pid;
int	exitstatus;		/* child's exit status. */
{
  List	*curr;
  int sig;

  if (Debug)
  {
    fprintf(stderr, "In CleanUpProc - ");
    fprintf(stderr, "Backend with pid %d exited with status %d\n", pid, exitstatus);
    fflush(stderr);
  }
  /* -------------------------
   * If a backend dies in an ugly way (i.e. status not 0) then
   * we must signal all other backends to quickdie.  If exit status
   * is zero we assume everything is hunky dory and simply remove the
   * backend from the active backend list.
   * -------------------------
   */
  if (!exitstatus)
  {
      ListForEach( curr, BackendList, BackendList)
      {
        Backend *bp = (Backend *) ListElem(curr);

	if (bp->pid == pid)
	{
	  (void) free ((char *)bp);
	  ListDelete(curr);
	  break;
	}
      }
      return(STATUS_OK);
  }
  ListForEach( curr, BackendList, BackendList)
  {
    Backend *bp = (Backend *) ListElem(curr);
      
    /* -----------------
     * SIGUSR1 is the special signal that sez exit without exitpg
     * and let the user know what's going on.  ProcSemaphoreKill() 
     * cleans up the backends semaphore.  If SendStop is set (-s on
     * the command line), then we send a SIGSTOP so that we can collect
     * core dumps from all backends by hand.
     * -----------------
     */
    if (SendStop)
	sig = SIGSTOP;
    else
	sig = SIGUSR1;
    if (bp->pid != pid)
    {
	if (Debug)
	  fprintf(stderr, "Sending %s to process %d\n",
		  (sig == SIGUSR1 ? "SIGUSR1" : "SIGSTOP"), bp->pid);
	kill(bp->pid, sig);
	ProcSemaphoreKill(bp->pid);
    }
    else
	ProcSemaphoreKill(bp->pid);

    (void) free ((char *)bp);
    ListDelete(curr);
  }
  /* -------------
   * Quasi_exit means run all of the on_exitpg routines but don't
   * acutally call exit().  The on_exit list of routines to do is
   * also truncated.
   *
   * Nothing up my sleeve here, ActiveBackends means that since the last time
   * we recreated shared memory and sems another frontend has requested and
   * received a connection and I have forked off another backend.  This
   * prevents me from reinitializing shared stuff more than once for the
   * set of backends that caused the failure and were killed off.
   * ----------------
   */
  if (ActiveBackends == TRUE && Reinit)
  {
    if (Debug)
      fprintf(stderr, "Reinitializing shared memory and semaphores\n");
    quasi_exitpg();
    /* --------------
     * Recreate shared memory and semaphores.
     * --------------
     */
    CreateSharedMemoryAndSemaphores(
	  SystemPortAddressCreateIPCKey((SystemPortAddress)PostPortName));
    ActiveBackends = FALSE;
  }
    return(STATUS_OK);
}

/*
 * BackendStartup -- startup backend process
 *
 * returns: STATUS_ERROR if the fork/exec failed, STATUS_OK
 *	otherwise.
 *
 */
BackendStartup(port, packet, ioList)
Port		*port;
StartupPacket	*packet;   /* client's startup packet */
IOList		*ioList;   /* io devices to setup */
{
  int		status;	   /* return status */
  Backend 	*bp;	   /* info to be used for backend cleanup */
  char		dbData[PATH_SIZE];
  char		efData[ARGV_SIZE];
  char		*execFile;
  char		*database;  /* database after fixlead */
  int		size;	   /* of fixlead string */
  int		pid;

  database = dbData;
  execFile = efData;

  bp = (Backend *) zalloc(sizeof(Backend));
  if (! bp) {
    elog(FATAL,"Postmaster: cannot zalloc backend structure\n");
    ExitPostmaster(1);
  }
  ListPush(BackendList,bp);

  /*
   * If any of the arguments is missing, use the defaults.
   */

  /* Set up the backend as specified by the startup packet */

  if (* (packet->tty)) {	/* Stdout/Stderr will become the tty file */
    ioList[1].name = packet->tty;
    ioList[2].name = packet->tty;
  }

  if (! * (packet->user)) 
    strcpy(packet->user,DefaultStartup.user);

  size = PATH_SIZE;
  if (! * (packet->database)) 
    strcpy(database,DefaultStartup.database);
  else 
    (void) fixlead(packet->database,&database,&size);

  database = dbData;
    
  size = ARGV_SIZE;
  if (! * (packet->execFile))
    strcpy(execFile, DefaultStartup.execFile);
  else
    (void) fixlead(packet->execFile, &execFile, &size);

  execFile = efData;

  /*
   * Security: check the arguments.  There should be an authorized
   *	list of execFiles at the very least.
   */

  if ((pid = FORK()) == 0) {
    /* child: 
     * 	use the ioList structure to setup your file descriptors and
     * 	then exec the file requested.
	 */
	/*
	 * These have to be made big enough!
     */
    char	envEntry1[64];
    char	envEntry2[64];
    char	envEntry3[64];

    /* This goes to backend as command line arg!!!
     * dup2(port->sock,BACKEND_SOCK); 
     */
    status = DescriptorReset(ioList);
    if (status) {
      _exit(1);
    }

    /* Set up the necessary environment variables for the backend
     * This should really be some sort of message....
     */
#ifdef sprite
    { 
      char c[50];
      sprintf(c, "%d", PostPortName);
      setenv("POSTPORT", c);
      sprintf(c, "%d", NextBackendId);
      setenv("POSTID", c);
      sprintf(c, "%s", packet->user);
      setenv("PG_USER", c);
    }
#else

    sprintf(envEntry1, "POSTPORT=%d", PostPortName);
    putenv(envEntry1);
    sprintf(envEntry2, "POSTID=%d", NextBackendId);
    putenv(envEntry2);
    sprintf(envEntry3, "PG_USER=%s", packet->user);
    putenv(envEntry3);
    if (Debug) {
	printf("ENVIRONMENT: %s, %s, %s\n", envEntry1,envEntry2,envEntry3);
    }

#endif /* sprite */

    if (! DoExec(execFile, database, port->sock,packet)) {
      return;
    }

    /* error -- exec has failed if we get here. */
    elog(FATAL,"Postmaster: DoExec failed for '%s'\n",DefaultStartup.execFile);
    _exit(1);
  }

  if (Debug)
	fprintf(stderr,
		"started '%s' for '%s' on '%s' (%d) pid (%d)\n",
	 	execFile,packet->user, database,port->sock, pid);

  if (pid < 0) {
    fprintf(stderr, "PostMaster: fork failed");
    return(STATUS_ERROR);
  } 
  else
    bp->pid = pid;

  /* adjust backend counter */
  /* XXX Don't know why this is done, but for now backend needs it */
  NextBackendId -= 1;

  return(STATUS_OK);
}

/* 
 * fixlead -- Expand special characters from path names. 
 * 
 * returns: TRUE if expansion occurred FALSE otherwise.
 * SIDE EFFECTS: copies str into dst
 *
 * NOTES: this does not use the sizeP parameter.  It should
 *	check for string overflow.
 */
fixlead(str, dstP, sizeP)
char	**dstP, *str;
int	*sizeP;
{
  char *dst = *dstP;
  int	size = *sizeP;
  int	status = TRUE;

  switch (*str) {
    /* carriage return == NULL */
  case '\n':
    return(FALSE);

  case '~':

    /* home directory of postgres installation */
    strcpy(dst, Home);
    break;

  case '&':
    strcpy(dst, Home);
    strcat(dst, "/data/base/");
    strcat(dst, Dbname);
    break;

    /* directory of database */
  case '%':
    strcpy(dst, Home);
    strcat(dst, "/data");
    break;
    /* directory of global data (should be '&/..') */
  default:
    *dst = '\0';
    status = FALSE;
  }
  if (status)
    str++;

  strncat(dst,str,size);
  size = strlen(dst);
  *dstP += size;
  *sizeP -= size;
  return(status);
}


/*
 * DoExec -- setup the arguments and make an execv system call.
 *
 * returns: 
 *	if not debugging, we shouldn't return at all (exec()).
 *	if debugging, return 0.
 *	if exec fails, return 1.
 */
DoExec(execFile,database, portFd, pack)
char	*execFile,*database;
StartupPacket	*pack;
int 	portFd;
{
  int	status;
  char portBuf[32];
  char debugBuf[32];
  char startDir[PATH_SIZE];
  char args[2*ARGV_SIZE];
  
  /*
   * Call backend with any/all desired options.  These extra options
   * can either come from the front-end via the packet or from the
   * command line of the postmaster -o option.
   */
  args[0] = '\0';
  if (pack->options[0])
  	strcpy(args, pack->options);
  if (ExtraOptions[0])
	strcat(args, ExtraOptions);

  status = 1;

  strcpy(startDir, Home);
  strcat(startDir, "/data/base/");
  strcat(startDir, pack->database);
  if (chdir(startDir))
	perror(startDir);
  /* If debugging requested pass the request along to the backend */
  if (Debug)
	sprintf(debugBuf, "-d %d", Debug);	
  else
	sprintf(debugBuf, "-Q");

  sprintf(portBuf, "-P%d", portFd);
  if (Debug) {
	printf("The port file descriptor is %d\n", portFd);
	printf("execl: %s -p %s %s %s %s\n", 
		execFile, debugBuf, portBuf, database, args);
  }
  if (!(*args)) {
  status =
    execl(execFile, execFile, "-p", debugBuf, portBuf, database, NULL);
  }
  else {
    status =
      execl(execFile, execFile, "-p", debugBuf, portBuf, args, database, NULL);
  }
  return(status);
}


/*
 * DescriptorReset -- reset the servers file descriptors to
 *	match the configuration the new backend expects.
 *
 * This routine closes, stdin etc.  It'll set up a log file.
 */
DescriptorReset(ioList)
IOList	*ioList;
{
  /*
   * For each element of the io list: 
   *   If the name is NONE, close the corresponding file descriptor.
   *   If the name is DEFAULT, let the child inherit the parent's descriptors.
   *   Otherwise, open the named descriptor.
   */
  for (;ioList->name;ioList++) {
    if (! strcmp(ioList->name, "NONE")) {
      close(ioList->fd);
    } else if (strcmp(ioList->name,DEFAULT)) {
      int tmpfd;

      if (! (tmpfd = open(ioList->name, ioList->mode, OPEN_PERMISSIONS))) {
	perror(ioList->name);
	fprintf(stderr,"PostMaster: child cannot open tty '%s'\n",ioList->name);
	return(STATUS_ERROR);
      }
      close(ioList->fd);
      dup2(tmpfd,ioList->fd);
      close(tmpfd);
    }
  }
  return(STATUS_OK);
}

/*
 * ExitPostmaster -- cleanup
 */
ExitPostmaster(status)
{
  /* should cleanup shared memory and kill all backends */

  /*
   * Not sure of the semantics here.  When the Postmaster dies,
   * should the backends all be killed? probably not.
   */
  if (ServerSock != INVALID_SOCK)
    close(ServerSock);
  exitpg(status);
}

/* Delete this once the simple list implementation is ready */

#define MAX_SIZE 450000
#define MALLOC_MAGICNO		'M'
#define PRINT_ALLOC(STR, STR1, NUM)
#define DO_ALLOC(size)
#define TOP_ADDR(str)
int TotalCacheAlloc;

int *
CacheAlloc(size)
unsigned int size;
{
  char *tmp;

  Assert(size);
  Assert(size < MAX_SIZE);
  /* have to add four bytes because zalloc is going to align the space */
  tmp = (char *)zalloc(size+4);
  Assert(tmp);
  TOP_ADDR(tmp);
  PRINT_ALLOC("CacheAlloc",tmp,size);
  DO_ALLOC(TotalCacheAlloc += size);

  *(tmp+3) = MALLOC_MAGICNO;
  tmp += 4;

  return((int *)tmp);
}

FindBackend(backend)
char *backend;
{
	char path[PATH_SIZE];
	char objDir[PATH_SIZE];
	char *envVar;
	struct stat buf;

	/* check $POSTGRESHOME/bin/postgres */

	envVar = getenv("POSTGRESHOME");
	if (envVar) {
		strncpy(path, envVar, PATH_SIZE-21);
		strcat(path, "/bin/postgres");
		if (ValidBackend(path)) {
			strcpy(backend, path);
			return;
		}
	}

	/* check $POSTTREE/bin/postgres */

	envVar = getenv("POSTTREE");
	if (envVar) {
		strncpy(path, envVar, PATH_SIZE-21);
		strcat(path, "/bin/postgres");
		if (ValidBackend(path)) {
			strcpy(backend, path);
			return;
		}
	}

	/* check $POSTTREE/<obj.dir>/support/postgres */

	ReadObjDir(objDir);

	if (objDir[0]) {
		strncpy(path, objDir, PATH_SIZE-21);
		strcat(path, "/support/postgres");
		if (ValidBackend(path)) {
			strcpy(backend, path);
			return;
		}
	}

	/* check /usr/postgres/bin/postgres */

	strncpy(path, "/usr/postgres/bin/postgres", PATH_SIZE);
	if (ValidBackend(path)) {
		strcpy(backend, path);
		return;
	}
	fprintf(stderr,"Could not find a backend to execute -- giving up...\n");
	fprintf(stderr,"Have you set POSTGRESHOME in your environment?\n");
	fprintf(stderr,"Have you installed everything successfully?\n");
	exit(1);
}

ValidBackend(path)
char *path;
{
	struct stat buf;

	if ( stat(path, &buf) < 0 )
		return (FALSE);
	else if ( ! (buf.st_mode & S_IEXEC) )
		return (FALSE);
	else
		return (TRUE);
}

ReadObjDir(dir)
char *dir;
{
	FILE *fp;
	char buf[256];
	char tmpFile[32];
	char *bufptr;
	char *envPtr;

	/* Look for $POSTTREE/newconf/config.mk */

	if ((envPtr = getenv("POSTTREE")) == NULL)
	{
		*dir = '\0';
		return;
	}

	/* make a temporary file */
	sprintf(tmpFile, "/tmp/pm.%d", getpid());

	sprintf(buf, 
		"fgrep OD= %s/newconf/config.mk | sed -e \'s/OD=\t//\' > %s",
		envPtr,
		tmpFile);

	system( buf );

	if ((fp = fopen(tmpFile, "r")) == NULL) {
		*dir = '\0';
		return;
	}

	fgets(buf, 255, fp);

	/* kill the annoying \n fgets always puts at the end of the line */

	bufptr = (char *)index(buf, '\n');
	if (bufptr)
		*bufptr = (char)NULL;
	strncpy(dir, buf, PATH_SIZE);

	fclose(fp);
	unlink(tmpFile);
	return;
}

char *
zalloc(size)

unsigned long size;

{
	char *t;

	t = (char *) malloc(size);
	bzero(t, size);
	return(t);
}
@


1.56
log
@get rid of Dblog and SysLog bogosity, fixes the evil postmaster EOF bug.
@
text
@d2 1
a2 1
 * $Header: /usr/local/dev/postgres/mastertree/newconf/RCS/postmaster.c,v 1.55 1992/05/21 18:06:05 mer Exp $
d155 10
d223 1
a223 1
  while ((opt = getopt(argc, argv, "dp:b:o:B:")) != EOF) {
d225 10
a234 2
		case 'p':
			PostPortName = (short)atoi(optarg);
d252 4
d263 4
a266 1
		case 'B':
d268 4
a271 4
			 * The number of buffers to create.  Setting this
			 * option means we have to start each backend with
			 * a -B # to make sure they know how many buffers
			 * were allocated.
d273 1
a273 3
			NBuffers = atol(optarg);
			strcat(ExtraOptions, "-B ");
			strcat(ExtraOptions, optarg);
d512 1
d546 12
a559 6
	/* -----------------
	 * SIGUSR1 is the special signal that sez exit without exitpg
	 * and let the user know what's going on.  ProcSemaphoreKill() 
	 * cleans up the backends semaphore.
	 * -----------------
	 */
d561 3
a563 2
	  fprintf(stderr, "Sending SIGUSR1 to process %d\n", bp->pid);
	kill(bp->pid, SIGUSR1);
d584 1
a584 1
  if (ActiveBackends == TRUE)
@


1.55
log
@add some options (-o and -B)
@
text
@d2 1
a2 1
 * $Header: /users/mer/pg/src/support/RCS/postmaster.c,v 1.54 1992/04/28 00:25:49 mer Exp mer $
a114 2
  { SYSLOG_FD, NULL, (O_WRONLY|O_APPEND|O_CREAT) },
  { DBLOG_FD, NULL, (O_WRONLY|O_APPEND|O_CREAT) },
a136 2
char *Dblog = DEF_DBLOG;
char *SysLogName = DEF_SLOG;
a272 12
/* The corresponding files are opened just before we exec the backend */

  size = PATH_SIZE;
  fixlead(SysLogName, &sysLogPtr, &size);
  IO_List[3].name = sysLogPath;
  Assert(IO_List[3].fd == SYSLOG_FD);

  size = PATH_SIZE;
  fixlead(Dblog, &dblogPtr, &size);
  IO_List[4].name = dblogPath;
  Assert(IO_List[4].fd == DBLOG_FD);

d692 2
a693 1
	fprintf(stderr, "starting '%s' for '%s' on '%s' (%d) pid (%d)\n",
d697 1
a697 1
    elog(WARN, "PostMaster: fork failed");
d849 1
a849 1
	elog(WARN,"PostMaster: child cannot open tty '%s'",ioList->name);
@


1.54
log
@check if env var is null before using.
@
text
@d2 1
a2 1
 * $Header: /users/mer/pg/src/support/RCS/postmaster.c,v 1.53 1992/04/27 22:35:18 mer Exp mer $
d120 1
d154 5
d217 1
a217 1
  while ((opt = getopt(argc, argv, "dp:b:")) != EOF) {
d238 18
d797 12
a808 1
  char *args = pack->options;
@


1.53
log
@get rid of bogus dlog() call.  We don't really use this anymore
@
text
@d2 1
a2 1
 * $Header: /u/mer/pg/src/support/RCS/postmaster.c,v 1.52 1991/12/16 20:43:25 mer Exp mer $
d939 2
d964 1
d968 6
d979 1
a979 1
		getenv("POSTTREE"),
@


1.52
log
@bug fix.  using a struct after it has been freed.
@
text
@d2 1
a2 1
 * $Header: /users/mer/postgres/src/support/RCS/postmaster.c,v 1.51 1991/11/18 20:17:57 clarsen Exp mer $
a625 10

#ifdef	POSTMASTERLOG
  /*
   *  this is dillon's: the old data structures are gone so I'm not sure
   *  what the log message should contain.
   */
  dlog(2, form("key %d\naddr %lx\nport %d", bp->startTime,
	       bp->addr.sin_addr.s_addr, ntohs(bp->addr.sin_port)));
#endif	/* POSTMASTERLOG */

@


1.51
log
@prototypes
@
text
@d2 1
a2 1
 * $Header: RCS/postmaster.c,v 1.50 91/11/07 22:13:55 mer Exp Locker: clarsen $
d349 1
a350 1
	  baseMask &= ~ port->mask;
d355 1
a356 1
	  baseMask &= ~ port->mask;
@


1.50
log
@prototyping changes
@
text
@d2 1
a2 1
 * $Header: /users/mer/postgres/src/support/RCS/postmaster.c,v 1.49 1991/09/09 23:58:33 mao Exp mer $
d172 1
d174 1
@


1.49
log
@use GetPGHome() instead of using getenv directly
@
text
@d2 1
a2 1
 * $Header: /local/mao/postgres/src/support/RCS/postmaster.c,v 1.48 1991/08/15 15:00:49 mer Exp mao $
a60 1
char *zalloc();
d153 21
a177 2
  int		reaper();
  int		pmdie();
d389 2
a390 1
    if (BackendStartup(port, &port->buf, IO_List) != STATUS_OK) {
d439 1
a439 1
  free (port);
d501 1
a501 1
	  (void) free (bp);
d528 1
a528 1
    (void) free (bp);
@


1.48
log
@machine depency fix with passing a structure as a parameter
@
text
@d2 1
a2 1
 * $Header: RCS/postmaster.c,v 1.47 91/08/14 12:36:50 mer Exp Locker: mer $
d62 1
d143 1
a143 1
 * This is set by getenv("POSTGRESHOME");
d222 1
a222 2
  if (!(Home = getenv("POSTGRESHOME")) && !(Home = getenv("HOME")))
	Home = "/usr/postgres";
a224 1

@


1.47
log
@add recovery functionality, now when backend exit with status > 0 
shared stuff is completely re-initialized and all backends are torched
@
text
@d2 1
a2 1
 * $Header: /users/mer/postgres/src/support/RCS/postmaster.c,v 1.46 91/08/12 15:25:00 mer Exp Locker: mer $
d445 1
a445 1
    (void) CleanupProc(pid,status);
d456 1
a456 1
CleanupProc(pid,status)
d458 1
a458 1
int	status;		/* child's exit status. */
a460 1
  union wait dummy;
d465 1
a465 1
    fprintf(stderr, "Backend with pid %d exited with status %d\n", pid, status);
d475 1
a475 1
  if (!status)
@


1.46
log
@more debug output and clean-up proc bug fix
@
text
@d2 1
a2 1
 * $Header: /users/mer/postgres/src/support/RCS/postmaster.c,v 1.45 91/07/22 22:20:07 mao Exp Locker: mer $
d129 1
d329 1
a434 3
 * Eventually, this should do more complete error handling.  Right now,
 * all it does is is call CleanupProc to cleanup local data associated
 * with the backend.
d461 1
d464 29
a492 2
    fprintf(stderr, "In CleanUpProc pid %d\n", pid);
  ListForEach( curr, BackendList, BackendList) {
d495 8
a502 15
    if (bp->pid == pid) {
      /*
       * cleanup all shared mem state associated with the 
       * POSTGRES backend.  ProcKill() is my cleanup routine.
       * if the status is zero, assume that the backend exited
       * cleanly and took care of its own cleanup.
       */
      if (Debug)
	fprintf(stderr, 
	  "Backend with pid (%d) exitted with status %d\n",
	  pid,
	  status);

      if (status)
      {
d504 3
a506 6
	  fprintf(stderr, "Backend exit status non-zero calling ProcKill()\n");
	(void) ProcKill(pid);
      }
      ListDelete(curr);
      (void) free (bp);
      return(STATUS_OK);
d508 5
d514 26
a539 1
  return(STATUS_NOT_FOUND);
a602 4
  if (Debug)
	printf("starting '%s' for '%s' on '%s' (%d)\n",
	 	execFile,packet->user, database,port->sock);

d673 4
@


1.45
log
@jukebox storage manager installation
@
text
@d2 1
a2 1
 * $Header: /users/mao/postgres/src/support/RCS/postmaster.c,v 1.44 1991/07/22 14:52:31 mer Exp mao $
d443 2
d463 2
d475 6
d482 3
d486 1
d635 2
@


1.44
log
@incremental checkin for new lock manager
@
text
@d2 1
a2 1
 * $Header: support/RCS/postmaster.c,v 1.43 91/05/08 15:19:33 choi Exp Locker: mer $
d126 2
d217 2
@


1.43
log
@sprite doesn't have <sys/un.h>
@
text
@d2 1
a2 1
 * $Header: RCS/postmaster.c,v 1.42 91/03/20 19:17:11 cimarron Exp Locker: choi $
a69 3
#define GARBAGE /* Turn on garbage collection, at least for now */

#ifdef GARBAGE
a81 1
#endif GARBAGE
a255 1
#ifdef GARBAGE
a256 1
#endif
a438 1
#ifdef GARBAGE
a441 1
#endif
a443 1
#ifdef GARBAGE
a466 1
#ifdef NOTDEF
a468 1
#endif
a476 2
#endif GARBAGE

a489 1
#ifdef GARBAGE
a490 1
#endif
a500 1
#ifdef GARBAGE
a506 1
#endif
a551 1
#ifdef GARBAGE
a553 1
#endif
@


1.42
log
@fixed a macro wierdness problem
@
text
@d2 1
a2 1
 * $Header: RCS/postmaster.c,v 1.41 91/03/10 21:10:52 kemnitz Exp $
d43 1
d45 1
@


1.41
log
@Fixes the Kansas City bug.
@
text
@d2 1
a2 1
 * $Header: RCS/postmaster.c,v 1.40 91/03/09 06:58:57 kemnitz Exp Locker: kemnitz $
d464 1
a464 1
  ListForEach ( curr, BackendList, BackendList) {
@


1.40
log
@fixed compile error.
@
text
@d2 1
a2 1
 * $Header: RCS/postmaster.c,v 1.39 91/03/09 04:10:16 kemnitz Exp Locker: kemnitz $
d578 3
d582 3
a584 3
    char	envEntry1[20];
    char	envEntry2[18];
    char	envEntry3[USER_NAMESIZE];
@


1.39
log
@"Fixed" zombie processes problem - sadly ProcKill is nowhere to be
found.  Ifdef'ed out for now.
@
text
@d2 1
a2 1
 * $Header: RCS/postmaster.c,v 1.38 91/03/07 23:18:35 kemnitz Exp Locker: kemnitz $
d76 1
a76 1
typedef struct	backend	{
@


1.38
log
@Fixed problem with uninitialized vars.
@
text
@d2 1
a2 1
 * $Header: RCS/postmaster.c,v 1.37 91/03/05 12:57:04 mao Exp Locker: kemnitz $
d68 2
d474 1
d477 1
@


1.37
log
@brain-damaged "fixlead" procedure
@
text
@d2 1
a2 1
 * $Header: RCS/postmaster.c,v 1.36 91/03/05 10:27:27 mer Exp Locker: mao $
d59 1
d388 1
a388 1
  Port		*port = (Port *) malloc(sizeof(Port));
d511 1
a511 1
  bp = (Backend *) malloc(sizeof(Backend));
d513 1
a513 1
    elog(FATAL,"Postmaster: cannot malloc backend structure\n");
d807 2
a808 2
  /* have to add four bytes because malloc is going to align the space */
  tmp = (char *)malloc(size+4);
d926 13
@


1.36
log
@added vacuum cleaner ability
@
text
@d2 1
a2 1
 * $Header: RCS/postmaster.c,v 1.35 91/03/01 17:49:12 mer Exp Locker: mer $
d545 2
@


1.35
log
@fixed usage statement
@
text
@d2 1
a2 1
 * $Header: support/RCS/postmaster.c,v 1.34 91/03/01 17:44:08 mer Exp Locker: mer $
d501 1
d507 1
a520 1
  size = ARGV_SIZE;
d540 6
d548 1
a548 2
	 	DefaultStartup.execFile,packet->user,
	 	database,port->sock);
d611 1
a611 2
    if (! DoExec(DefaultStartup.execFile, 
		database, port->sock,packet)) {
@


1.34
log
@fixed command line args and added default list of search dirs for a backend
@
text
@d2 1
a2 1
 * $Header: RCS/postmaster.c,v 1.33 91/02/28 13:46:51 mer Exp Locker: mer $
d128 1
a128 1
char *Usage = "postmaster [ -p port ] [ -b backend_pathname ] [ -d level ]\n";
@


1.33
log
@run down default list of backends to exec (if not given on command line)
@
text
@d2 1
a2 1
 * $Header: RCS/postmaster.c,v 1.32 91/02/28 10:38:30 mer Exp Locker: mer $
d121 3
d128 1
a128 1
char *Usage = "postmaster -p port -b backend_pathname [ -d ]";
d185 2
a186 1
  while ((opt = getopt(argc, argv, "d:p:b:")) != EOF) {
d192 6
a197 1
  			strcpy(DefaultStartup.execFile, optarg);
d200 6
a205 1
			Debug = atoi(optarg);
d210 1
d712 1
a712 1
	sprintf(debugBuf, "-Q -n");
d816 1
d845 6
a850 5
	
	if (envVar) {
		strncpy(path, envVar, PATH_SIZE-21);
	/* /bin/postgres for now.... */
		strcat(path, "/bin/postgres");
d864 2
d879 39
@


1.32
log
@added functionality to support debug output redirection
@
text
@d2 1
a2 1
 * $Header: RCS/postmaster.c,v 1.31 91/02/27 00:15:18 hong Exp Locker: mer $
d37 1
a203 2
  if (!DefaultStartup.execFile[0])
  	strcpy(DefaultStartup.execFile,"/usr/postgres");
d205 3
d795 65
@


1.31
log
@fixed a compilation error
@
text
@d2 1
a2 1
 * $Header: RCS/postmaster.c,v 1.30 91/02/26 22:50:42 mer Exp Locker: hong $
d504 7
d657 1
a657 1
  strcpy(dst,str,size);
d682 1
a682 1
  char *args = pack->options;	/* last parameter to execl */
d695 1
a695 1
	sprintf(debugBuf, "-n");
d703 1
a703 3
  if (!(*args))
	args = (char *)NULL;

d705 6
a710 1
    execl( execFile, execFile, "-p", debugBuf, portBuf, database, args, NULL);
@


1.30
log
@quiet down messages unless requested
@
text
@d2 1
a2 1
 * $Header: RCS/postmaster.c,v 1.29 91/02/25 13:36:26 sp Exp Locker: mer $
a41 1
#include <netinet/in.h>
@


1.29
log
@Added a 'Header' line to keep rcs happy...
,.
@
text
@d2 1
a2 1
 * $Header: $
d692 1
a692 1
  if (Debug) 
d696 1
@


1.28
log
@All new postmaster, fixes bug where applications hang on there first try.
@
text
@d2 2
@


1.27
log
@Added a check for null user options.
@
text
@a0 2
static	char	*postmaster_c = "$Header: RCS/postmaster.c,v 1.26 91/02/06 13:17:19 kemnitz Exp $";

d5 3
a7 4
 *	POSTGRES system.  Frontend programs connect here and this
 *	program decides what to do with the request.  Also, this program
 *	keeps track of system errors and communication between backend
 *	processes.
d9 4
a12 1
 *	A lock manager uses a shared memory segment started by this program.
d14 8
a21 8
 *	Backend processes are started with the following file descriptors:
 *	0, 1, 2:	Read write terminal, for emergency use.
 *	3:		System log file append write only
 *	4:		Data stream to front end
 *	5:		Packet socket
 *	6:		Database log file append write only
 *	7:		Write end of pipe to postmaster
 *	8 to NOFILE:	free
d23 7
a29 2
 *	Backend processes are started with -postmaster indicating that they
 *	are non-interactive.
d35 1
a35 2
#include <sys/stat.h>
#include <sys/param.h>
d40 2
a41 3
#include <arpa/inet.h>
#include <strings.h>
/* #include "postgres.h" */
a42 2
#include "tmp/c.h"

d46 3
a48 3
/* OPT #include "sinval.h" */
#include "storage/sinvaladt.h"
#include "tmp/xid.h"	/* XXX only to define local GetNewTransactionId */
d50 2
a51 2
extern char *calloc();
#define ALLOC(t, c)	(t *)calloc((unsigned)(c), sizeof(t))
d53 4
a56 10
short   DebugOveride = 0;	/* overide frontend's terminal spec 	*/
short	Port = DEF_PORT;
short	Pack = DEF_PACK;
char	*Slog = DEF_SLOG;
short	Loglvl = DEF_LOGLVL;
char	*Back = DEF_BIN;
char	*Dblog = DEF_DBLOG;
char	*Dbname = "dbdb";	/* place holder */
char	*Home;
char	pg_pathname[256];
a57 2
int	Slogfd, Portfd, Packfd, Pipefds[2];
int	Ttyfile, Debugfile;
d59 5
a63 2
BackendId	MyBackendId = -1;	/* XXX ipc/sinvaladt.c requires -1 */
BackendTag	MyBackendTag = -1;
d65 9
a73 2
struct	backend	Master;
struct	bcommon	Ident;
d75 2
a76 1
int	NextBackendId = 0x7fffffff;	/* XXX */
d78 1
d80 64
d148 25
a172 11
	struct	sockaddr_in	sin;
	long			selmask;
	int			reaper(), i;
	int			die();
	long			len;
	struct	stat		sbuf;
	char			comm[512];
	extern	int		errno;
	char			tslog[64];
	extern char		*getenv();
	char			*p;
d174 1
a174 33
	/* should eventually look up the HOME of postgres */
	if (!(Home = getenv("POSTGRESHOME")) && !(Home = getenv("HOME")))
		Home = "/usr/postgres";
	/* Handle arguments */
	p = index(Home, ':');
	if (p != NULL)
	   *p = '\0';
	switch (argc) {
	  default:
		fprintf(stderr, "Postmaster: warning, too many arguments!\n");
	  case 8:
		DebugOveride = 1;
		fprintf(stderr, "Warning, DebugOveride activated\n");
	  case 7:
		Dblog = argv[6];
	  case 6:
		Slog = argv[5];
	  case 5:
		Back = argv[4];
	  case 4:
		Loglvl = atoi(argv[3]);
	  case 3:
		Pack = atoi(argv[2]);
	  case 2:
		Port = atoi(argv[1]);
	  case 1:
		/* do nothing */
		;
	}
	if (!Port) {
		fputs("Usage: postmaster port packet loglevel backend syslogfile dblogfile\n", stderr);
		exitpg(1);
	}
d176 3
a178 2
	fixpath(tslog, Slog, 64);
	Slog = tslog;
d180 15
a194 4
	/* initial setup of file descriptors */
	if ((Slogfd = open(Slog, O_WRONLY|O_APPEND|O_CREAT, 0666)) < 0) {
		perror(Slog);
		exitpg(2);
d196 1
a196 41
	if (Slogfd == 0) {	/* not on a terminal */
		dup(0);
		dup(0);
		Slogfd = dup(0);
	}
	Ttyfile = 1;
	Debugfile = Slogfd;
	if ((Portfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
		perror("socket port");
		exitpg(3);
	}
	if ((Packfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
		perror("socket pack");
		exitpg(4);
	}
	if (pipe(Pipefds) < 0) {
		perror("pipe");
		exitpg(7);
	}
	if (Pipefds[1] != 7) {	/* Hmmm.  Something wrong here. */
		perror("file descriptors scrambled");
		exitpg(8);
	}
	bzero((char *)&sin, sizeof sin);
	sin.sin_family = AF_INET;
	sin.sin_port = htons(Port);
	if (bind(Portfd, (char *)&sin, sizeof sin) < 0) {
		perror("bind port");
		exitpg(5);
	}
	sin.sin_port = htons(Pack);
	if (bind(Packfd, (char *)&sin, sizeof sin) < 0) {
		perror("bind pack");
		exitpg(6);
	}
	listen(Portfd, SOMAXCONN);
	fcntl(Portfd, F_SETFD, 1);
	fcntl(Packfd, F_SETFD, 1);
	fcntl(Pipefds[0], F_SETFD, 1);
	fcntl(Portfd, F_SETFL, FNDELAY);
	fcntl(Pipefds[0], F_SETFL, FNDELAY);
d198 2
a199 3
	signal(SIGCHLD, reaper);
	signal(SIGTTIN, SIG_IGN);
	signal(SIGTTOU, SIG_IGN);
d201 3
a203 3
	signal(SIGHUP, die);
	signal(SIGINT, die);
	signal(SIGTERM, die);
d205 4
a208 1
	Ident = Master.bcomm;
d210 1
a210 7
	EnableMemoryContext(true);  /* initializes the "top context" */
#ifndef	PRODUCTION
	CreateSharedMemoryAndSemaphores(
		SystemPortAddressCreateIPCKey((SystemPortAddress)Port));
#else	/* defined(PRODUCTION) */
	CreateSharedMemoryAndSemaphores(DefaultMemoryKey);
#endif	/* defined(PRODUCTION) */
d212 112
a323 44
	/* main processing loop */
	while (1) {
		selmask = (1 << Portfd) | (1 << Packfd) | (1 << Pipefds[0]);
		if (select(32, &selmask, NULL, NULL, NULL) < 0) {
			if (errno == EINTR)
				continue;
			perror("select");
			exitpg(8);
		}
		/* incomming packet */
		if (selmask & (1 << Packfd)) {
			i = sizeof sin;
			if ((len = recvfrom(Packfd, comm, sizeof comm, 0,
				(struct sockaddr *)&sin, &i)) < 0) {
					perror("recvfrom");
					exitpg(9);
			}
			/* do packet */
			packet(comm, len, &sin);
		}
		/* incomming packet from a local backend */
		if (selmask & (1 << Pipefds[0])) {
			if (recv(Pipefds[0], (char *)&len, sizeof len,
				 MSG_PEEK) != sizeof len) {
				fputs("read pipe len error\n", stderr);
				exitpg(10);
			}
			if (len != (i = read(Pipefds[0], comm, len))) {
				fprintf(stderr, "read pipe len wrong %d %d\n",
					i, len);
				exitpg(11);
			}
			/* do packet */
			packet(comm, len, NULL);
		}
		/* incomming connection */
		if (selmask & (1 << Portfd)) {
			len = sizeof sin;
			if ((i = accept(Portfd, (char *)&sin, &len)) < 0) {
				perror("accept");
				exitpg(12);
			}
			startup(i, sin);
		}
d325 5
d332 2
a333 2
/* reap dead backends */
reaper()
d335 5
a339 2
	union	wait	status;
	struct	rusage	ruse;
d341 13
a353 4
	/* will eventually keep track of backends in operation and */
	/* log abnormal terminations */
	while (wait3(&status, WNOHANG, &ruse) > 0)
		continue;
d356 7
a362 2
/* exit gracefully */
die()
d364 28
a391 1
	exitpg(0);
d394 2
a395 5
/* packet handler */
packet(comm, len, sin)
char	*comm;
int	len;
struct	sockaddr_in	*sin;
d397 2
a398 2
	/* will eventually do lots of fun stuff */
	dlog(SLOG|PTIME, comm);
d401 4
a404 4
/* new connection handler */
startup(fd, sin)
int	fd;
struct	sockaddr_in	*sin;
d406 2
a407 7
	char	line[512], *cp, *index(), lognum[8], *mvitem();
	char	portFdBuf[32];	/* -Pn where n is the comm socket fd */
	char	debugModeBuf[32];	/* -debug if DebugOveride set */
	int	i, dportfd;
	FILE	*fp;
	struct	backend	*bp;
	struct	hostent	*hp;
d409 12
a420 19
	/* should not leave the possibility of blocking on this routine */
	fcntl(fd, F_SETFL, 0);	/* reset to block on read */
	fp = fdopen(fd, "r");
	fgets(line, 512, fp);
	fputs(line, stdout);
	fflush(stdout);
	bp = ALLOC(struct backend, 1);
	cp = mvitem(line, bp->bcomm.user, 16, "nobody");
	cp = mvitem(cp, bp->database, 64, "dbdb");
	Dbname = bp->database;
	cp = mvitem(cp, bp->tty, 16, "null");
	cp = mvitem(cp, bp->options, 16, "");
	cp = mvitem(cp, lognum, 8, "");
	if (*lognum)
		bp->bcomm.debuglvl = atoi(lognum);
	else
		bp->bcomm.debuglvl = DEF_LOGLVL;
	cp = mvitem(cp, bp->back, 64, Back);
	cp = mvitem(cp, bp->dblog, 64, DEF_DBLOG);
d422 6
a427 4
#ifdef	POSTMASTERLOG
	dlog(1, form("user %.16s db %.64s backend %.64s",
		     bp->bcomm.user, bp->database, bp->back));
#endif	/* POSTMASTERLOG */
d429 1
d431 5
a435 2
 * Set PG_USER so that Postgres can know who the user is.  I can't think of
 * any better way than to do it in the environment.
d437 5
d443 19
a461 2
	{
		char env[50];
d463 1
a463 1
#ifdef sprite
d465 21
a485 1
		setenv("PG_USER", bp->bcomm.user);
d487 1
a487 1
#else
d489 7
a495 2
		sprintf(env, "PG_USER=%s", bp->bcomm.user);
		putenv(env);
a496 1
	}
d498 4
a501 28
	bp->last = &Master;
	bp->next = Master.next;
	Master.next = bp;
	/* build a datagram port for backend */
	if ((dportfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
		perror("socket dport");
		fclose(fp);
		return;
	}
	bzero((char *)&bp->sin, sizeof (bp->sin));
	bp->sin.sin_family = AF_INET;
	bp->sin.sin_addr.s_addr = INADDR_ANY;
	if (bind(dportfd, &bp->sin, sizeof(bp->sin)) < 0) {
		perror("bind dport");
		fclose(fp);
	}
	i = sizeof(bp->sin);	
	if (getsockname(dportfd, &bp->sin, &i)) {
		perror("getsockname");
		fclose(fp);
		return;
	}
	if ((hp = gethostbyname("localhost")) && hp->h_addrtype == AF_INET)
	  bcopy(hp->h_addr, (char *)&bp->sin.sin_addr, hp->h_length);
	else
	  bp->sin.sin_addr.s_addr = inet_addr("127.0.0.1");
	/* choose a key for backend */
	bp->bcomm.key = time(0);
d503 21
d525 8
a532 2
	dlog(2, form("key %d\naddr %lx\nport %d", bp->bcomm.key,
	       bp->sin.sin_addr.s_addr, ntohs(bp->sin.sin_port)));
a534 3
	/* fork */
	if ((bp->bcomm.pid = fork()) == 0) {
	/* child: move file descriptors and open files */
d536 20
a555 8
		/*
		 * XXX Should someday write a message instead of modifying
		 * XXX the environment here.  Done this way now to aid
		 * XXX debugging.
		 */
		{
			char	environmentEntry1[20];
			char	environmentEntry2[18];
d557 9
a565 6
                        { char c[50];
                        sprintf(c, "%d", Port);
                        setenv("POSTPORT", c);
                        sprintf(c, "%d", NextBackendId);
                        setenv("POSTID", c);
                        }
a566 2
			sprintf(environmentEntry1, "POSTPORT=%d", Port);
			putenv(environmentEntry1);
d568 10
a577 3
			sprintf(environmentEntry2, "POSTID=%d",
				NextBackendId);
			putenv(environmentEntry2);
a578 1
		}
d580 38
a617 35
		if (strcmp(bp->dblog, "def")) {
			close(6);
			open(bp->dblog, O_WRONLY|O_APPEND|O_CREAT, 0644);
		}
		dup2(fd, Portfd);
#ifdef sprite
                /*
                 * Patch bug in dup2() on Sprite that doesn't clear
                 * close-on-exec flag.
                 */
                (void) fcntl(Portfd, F_SETFD, 0);
#endif
		dup2(dportfd, Packfd);
		if (strcmp(bp->tty, "def")) {
		    if (DebugOveride == 0) {
			close(0);
			close(1);
			close(2);
			open(bp->tty, O_WRONLY);
			dup(0);
			dup(0);
		    }
		}
		if (DebugOveride)
		    strcpy(debugModeBuf, "-d");
		else
		    strcpy(debugModeBuf, "-n");	/* nop */
		sprintf(portFdBuf, "-P%d", Portfd);
		for (i = 8; i < NOFILE; i++)
			close(i);
		strcpy(line, Home);
		strcat(line, "/data/base/");
		strcat(line, bp->database);
		if (chdir(line))
		  perror(line);
d619 4
a622 32
#ifdef POSTMASTERLOG
strcpy(debugModeBuf, "-d");
write(Ttyfile,bp->back,strlen(bp->back));
write(Ttyfile," ",1);
write(Ttyfile,debugModeBuf,strlen(debugModeBuf));
write(Ttyfile," ",1);
write(Ttyfile,portFdBuf,strlen(portFdBuf));
write(Ttyfile," ",1);
write(Ttyfile,bp->database,strlen(bp->database));
write(Ttyfile," ",1);
#endif	     
		if (bp->options[0] != '\0')
		{
		    execl( bp->back, bp->back, debugModeBuf, portFdBuf,
		           bp->options, "-p", bp->database, (char *)0);
		}
		else
		{
		    execl( bp->back, bp->back, debugModeBuf, portFdBuf,
		           "-p", bp->database, (char *)0);
		}
		perror(bp->back);
		fflush(stderr);
		exitpg(1);
	}
	/* parent: pid is set and close files */
	close(dportfd);
	fclose(fp);
	if (bp->bcomm.pid < 0)
	  dlog(SLOG, "fork failed");
	else
	  sendpg(bp, 'I', (char *)&bp->bcomm, sizeof(bp->bcomm));
d624 30
a653 2
	/* adjust backend counter */
	NextBackendId -= 1;
d656 13
a668 4
char *
mvitem(src, dst, len, def)
char	*src, *dst, *def;
int	len;
d670 5
a674 1
	int	i;
d676 24
a699 22
	if (src && *src != '\n') {
		if (*src == ',') {
			fixpath(dst, def, len);
			return(src+1);
		}
		i = fixlead(dst, *src);
		dst += i;
		len -= i;
		src++;
		while (len-- && *src != '\n' && *src != ',')
			*dst++ = *src++;
		if (len == -1)
			while (*src != '\n' && *src != ',')
				src++;
		else
			*dst = '\0';
		if (*src != '\n')
			return(src+1);
		return(NULL);
	}
	fixpath(dst, def, len);
	return(NULL);
d702 9
a710 2
fixlead(dst, c)
char	*dst, c;
d712 23
a734 23
	int	i;
	
	switch (c) {
	  case '~':
		/* home directory of postgres installation */
		strcpy(dst, Home);
		break;
	  case '&':
		strcpy(dst, Home);
		strcat(dst, "/data/base/");
		strcat(dst, Dbname);
		break;
		/* directory of database */
	  case '%':
		strcpy(dst, Home);
		strcat(dst, "/data");
		break;
		/* directory of global data (should be '&/..') */
	  default:
		*dst = c;
		return(1);
	}
	return(strlen(dst));
d737 4
a740 3
fixpath(dst, src, len)
char	*dst, *src;
int	len;
d742 1
a742 1
	int	i;
d744 7
a750 5
	i = fixlead(dst, *src);
	dst += i;
	len -= i;
	src++;
	strncpy(dst, src, len);
d753 12
a764 5
sendpg(bp, type, data, len)
struct	backend	*bp;
short		type;
char		*data;
short		len;
d766 1
a766 1
	static	struct	dpacket	pack;
d768 13
a780 8
	pack.key = bp->bcomm.key;
	pack.pid = bp->bcomm.pid;
	pack.type = type;
	bcopy(data, pack.data, len);
	pack.len = len + 12;
	if (sendto(Packfd, &pack, len+8, 0, &bp->sin,
		   sizeof(bp->sin)) < 0)
	  perror("sendto");
a781 1

@


1.26
log
@Fixed problem with stupid "bp" structure.
@
text
@d1 1
a1 1
static	char	*postmaster_c = "$Header: RCS/postmaster.c,v 1.25 91/02/04 17:28:24 kemnitz Exp Locker: kemnitz $";
d435 10
a444 10
		execl(
		    bp->back, 
		    bp->back, 
		    debugModeBuf,
		    portFdBuf,
		    bp->options,
		    "-p", 
		    bp->database,
		    (char *)0
		);
@


1.25
log
@Added an environment variable for user name.
@
text
@d1 1
a1 1
static	char	*postmaster_c = "$Header: RCS/postmaster.c,v 1.24 91/02/02 18:34:10 mao Exp Locker: kemnitz $";
d320 1
a320 1
		sprintf(env, "PG_USER=%s", bcomm.user);
@


1.24
log
@pass user-specified options to backend.
@
text
@d1 1
a1 1
static	char	*postmaster_c = "$Header: RCS/postmaster.c,v 1.23 91/01/18 22:22:04 hong Exp Locker: kemnitz $";
d305 19
@


1.23
log
@change for the new buffer manager
@
text
@d1 1
a1 1
static	char	*postmaster_c = "$Header: RCS/postmaster.c,v 1.22 90/10/16 00:29:30 kemnitz Exp Locker: hong $";
d292 1
d421 1
@


1.22
log
@Added pg_pathname so linking is happy.
@
text
@d1 1
a1 1
static	char	*postmaster_c = "$Header: RCS/postmaster.c,v 1.21 90/09/25 17:23:59 kemnitz Exp Locker: kemnitz $";
d185 1
@


1.21
log
@Fixed stuff.
@
text
@d1 1
a1 1
static	char	*postmaster_c = "$Header: RCS/postmaster.c,v 1.19 90/09/18 21:57:26 hong Exp $";
d61 1
@


1.20
log
@Updating from revision 1.$t2 to revision 1.$t
@
text
@d1 1
a1 1
static	char	*postmaster_c = "$Header: RCS/postmaster.c,v 1.18 90/08/24 14:40:14 choi Exp Locker: hong $";
d37 1
d88 1
d94 3
@


1.19
log
@to support file striping
@
text
@a36 1
#include <strings.h>
a86 1
	char			*p;
a91 3
	p = index(Home, ':');
	if (p != NULL)
	   *p = '\0';
@


1.18
log
@lines added for Sprite OS port.
@
text
@d1 1
a1 1
static	char	*postmaster_c = "$Header: RCS/postmaster.c,v 1.17 90/08/23 16:02:59 hong Exp Locker: choi $";
d37 1
d88 1
d94 3
@


1.17
log
@fixed #include's with path name.
@
text
@d1 1
a1 1
static	char	*postmaster_c = "$Header: RCS/postmaster.c,v 1.16 90/05/25 12:16:44 kemnitz Version_2 Locker: hong $";
d344 8
a351 1

d358 1
d366 7
@


1.16
log
@Got rid of POSTHOME variable.
@
text
@d1 1
a1 1
static	char	*postmaster_c = "$Header: RCS/postmaster.c,v 1.15 90/04/19 17:49:45 kemnitz Exp Locker: kemnitz $";
d39 1
a39 1
#include "c.h"
d41 3
a43 3
#include "master.h"
#include "log.h"
#include "ipci.h"
d45 2
a46 2
#include "sinvaladt.h"
#include "xid.h"	/* XXX only to define local GetNewTransactionId */
@


1.15
log
@Got rid of old sequent hacks - no longer needed.
@
text
@d1 1
a1 1
static	char	*postmaster_c = "$Header: RCS/postmaster.c,v 1.14 90/04/11 21:42:26 kemnitz Exp Locker: kemnitz $";
d89 1
a89 1
	if (!(Home = getenv("POSTHOME")) && !(Home = getenv("HOME")))
@


1.14
log
@Changed "debugging mode" from -debug to -d and set up to send -n
for nodebug node.
(so that tcop/postgres.c is happy with its arguments).
@
text
@d1 1
a1 1
static	char	*postmaster_c = "$Header: RCS/postmaster.c,v 1.13 90/03/31 19:06:04 cimarron Exp Locker: kemnitz $";
a71 5
/*
 * TEMPORARY SEQUENT HACKS
 *
 * on_exit()
 */
a72 15
#ifdef sequent

int Pipefd;	/* due to inclusion of pcomm.o and disclusion of cinit.o */

void
on_exit()
{
    fprintf(stderr, "on_exit() called! not implemented on sequent yet\n");
}

#endif




a507 5
sendannounce(mess)
char	*mess;
{
	dlog(SLOG, mess);
}
@


1.13
log
@removed redundant GetNewTransctionId().
@
text
@d1 1
a1 1
static	char	*postmaster_c = "$Header: RCS/postmaster.c,v 1.12 90/02/12 19:51:24 cimarron Exp $";
d390 1
a390 1
		    strcpy(debugModeBuf, "-debug");
d392 1
a392 1
		    strcpy(debugModeBuf, "-");	/* nop */
@


1.12
log
@added buffer manager statistics and exitpg() stuff -cim
@
text
@d1 1
a1 1
static	char	*postmaster_c = "$Header: RCS/postmaster.c,v 1.11 89/11/24 15:55:35 hirohama Exp $";
a531 14
}

TransactionId
GetNewTransactionId()
{
	TransactionIdData	transactionIdData;

	transactionIdData.data[0] = AsUint8(0xff);
	transactionIdData.data[1] = AsUint8(0xff);
	transactionIdData.data[2] = AsUint8(0xff);
	transactionIdData.data[3] = AsUint8(0xff);
	transactionIdData.data[4] = AsUint8(0xff);

	return(&transactionIdData);	/* XXX */
@


1.11
log
@readded argc==1 case (why was it removed?!?)
@
text
@d1 1
a1 1
static	char	*postmaster_c = "$Header: RCS/postmaster.c,v 1.10 89/09/21 18:58:34 hirohama Exp Locker: hirohama $";
d136 1
a136 1
		exit(1);
d145 1
a145 1
		exit(2);
d156 1
a156 1
		exit(3);
d160 1
a160 1
		exit(4);
d164 1
a164 1
		exit(7);
d168 1
a168 1
		exit(8);
d175 1
a175 1
		exit(5);
d180 1
a180 1
		exit(6);
d213 1
a213 1
			exit(8);
d221 1
a221 1
					exit(9);
d231 1
a231 1
				exit(10);
d236 1
a236 1
				exit(11);
d246 1
a246 1
				exit(12);
d268 1
a268 1
	exit(0);
d424 1
a424 1
		_exit(1);
@


1.10
log
@removed "postgres.h" dependency
@
text
@d1 1
a1 1
static	char	*postmaster_c = "$Header: RCS/postmaster.c,v 1.9 89/09/05 16:53:19 mao C_Demo_1 Locker: hirohama $";
d130 3
@


1.9
log
@Working version of C-only demo
@
text
@d1 1
a1 1
static	char	*postmaster_c = "$Header: RCS/postmaster.c,v 1.8 89/08/31 17:52:38 mao Exp $";
d37 1
a37 1
#include "postgres.h"
d47 3
@


1.8
log
@close stdin, stdout, stderr.
@
text
@d1 1
a1 1
static	char	*postmaster_c = "$Header: RCS/postmaster.c,v 1.7 89/08/31 10:21:08 goh Exp $";
@


1.7
log
@removed the transaction override flag.  someday should add
it back as an option
@
text
@d1 1
a1 1
static	char	*postmaster_c = "$Header: RCS/postmaster.c,v 1.6 89/08/30 18:52:04 goh Exp Locker: goh $";
a374 1
/*
a377 1
*/
@


1.6
log
@now works with postgres.c (backend) for be/fe communications
@
text
@d1 1
a1 1
static	char	*postmaster_c = "$Header: RCS/postmaster.c,v 1.5 89/08/02 23:56:46 dillon Exp $";
a414 1
		    "-O",
@


1.5
log
@major changes, works with new backend now
@
text
@d1 1
a1 1
static	char	*postmaster_c = "$Header: postmaster.c,v 1.4 89/07/17 14:40:16 dillon Exp $";
d375 1
d379 1
d397 12
a411 2
		    bp->database, 
		    "-postmaster", 
d414 3
a416 1
		    debugModeBuf,
@


1.4
log
@now passes -postmaster flag to backend on startup
@
text
@d1 1
a1 1
static	char	*postmaster_c = "$Header: postmaster.c,v 1.3 89/04/14 18:33:41 dillon Locked $";
d48 1
d110 5
d281 2
d374 1
d381 1
d383 5
d400 3
@


1.3
log
@added hacks so we don't have to include cinit.c
cinit.o..
@
text
@d1 1
a1 1
static	char	*postmaster_c = "$Header: /usr6/postgres/dillon/ptree/src/support/RCS/postmaster.c,v 1.2 89/02/02 15:58:13 dillon Stab $";
d22 3
d380 7
a386 1
		execl(bp->back, bp->back, bp->database, (char *)0);
@


1.2
log
@Txfer from old tree
@
text
@d1 1
a1 1
static	char	*postmaster_c = "$Header: postmaster.c,v 2.7 88/09/12 22:18:10 dillon Locked $";
d64 21
@


1.1
log
@Initial revision
@
text
@d1 1
a1 28

/*
 * 
 * POSTGRES Data Base Management System
 * 
 * Copyright (c) 1988 Regents of the University of California
 * 
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for educational, research, and non-profit purposes and
 * without fee is hereby granted, provided that the above copyright
 * notice appear in all copies and that both that copyright notice and
 * this permission notice appear in supporting documentation, and that
 * the name of the University of California not be used in advertising
 * or publicity pertaining to distribution of the software without
 * specific, written prior permission.  Permission to incorporate this
 * software into commercial products can be obtained from the Campus
 * Software Office, 295 Evans Hall, University of California, Berkeley,
 * Ca., 94720 provided only that the the requestor give the University
 * of California a free licence to any derived software for educational
 * and research purposes.  The University of California makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 * 
 */



static	char	*postmaster_c = "$Header: postmaster.c,v 1.1 88/11/11 16:40:22 postgres Exp $";
@
