I am almost finished Andrew's version of pg_ctl.c.  Here is the current
version I am using.

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

/*-------------------------------------------------------------------------
 *
 * pg_ctl --- start/stops/restarts the PostgreSQL server
 *
 * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
 *
 * $PostgreSQL: pgsql-server/src/bin/initdb/initdb.c,v 1.32 2004/05/18 03:36:36 momjian Exp $
 *
 *-------------------------------------------------------------------------
 */

#include "libpq-fe.h"
#include "postgres_fe.h"
#include <signal.h>
#include <errno.h>
#include "libpq/pqsignal.h"
#include <string.h>

#include <sys/types.h>
#include <sys/stat.h>

#define _(x) gettext((x))

/* postmaster version ident string */
#define PM_VERSIONSTR "postmaster (PostgreSQL) " PG_VERSION "\n"


typedef enum
{
	SMART_MODE,
	FAST_MODE,
	IMMEDIATE_MODE
}	ShutdownMode;


typedef enum
{
	NO_COMMAND = 0,
	START_COMMAND,
	STOP_COMMAND,
	RESTART_COMMAND,
	RELOAD_COMMAND,
	STATUS_COMMAND,
	KILL_COMMAND
}	CtlCommand;


static bool do_wait = false;
static bool wait_set = false;
static int	wait_seconds = 60;
static bool silence_echo = false;
static ShutdownMode shutdown_mode = SMART_MODE;
static int	sig;
static int	killproc;
static CtlCommand ctl_command = NO_COMMAND;
static char *pg_data_opts = NULL;
static char *pg_data = NULL;
static char *post_opts = NULL;
static const char *progname;
static char *log_file = NULL;
static char *postgres_path = NULL;
static char *argv0 = NULL;

static void *xmalloc(size_t size);
static char *xstrdup(const char *s);
static void do_advice(void);
static void do_help(void);
static void set_mode(char *modeopt);
static void set_sig(char *signame);
static void do_start();
static void do_stop(void);
static void do_restart(void);
static void do_reload(void);
static void do_status(void);
static void do_kill(void);
static long get_pgpid(void);
static char **readfile(char *path);
static void start_postmaster(void);
static bool test_postmaster_connection(void);

static char def_postopts_file[MAXPGPATH];
static char postopts_file[MAXPGPATH];
static char pid_file[MAXPGPATH];
static char conf_file[MAXPGPATH];

/*
 * routines to check mem allocations and fail noisily.
 *
 */
static void *
xmalloc(size_t size)
{
	void	   *result;

	result = malloc(size);
	if (!result)
	{
		fprintf(stderr, _("%s: out of memory\n"), progname);
		exit(1);
	}
	return result;
}

static char *
xstrdup(const char *s)
{
	char	   *result;

	result = strdup(s);
	if (!result)
	{
		fprintf(stderr, _("%s: out of memory\n"), progname);
		exit(1);
	}
	return result;
}

static long
get_pgpid(void)
{
	FILE	   *pidf;
	long		pid;

	pidf = fopen(pid_file, "r");
	if (pidf == NULL)
	{
		/* No pid file, not an error */
		if (errno == ENOENT)
			return 0;
		else
		{
			perror("openning pid file");
			exit(1);
		}
	}
	fscanf(pidf, "%ld", &pid);
	fclose(pidf);
	return pid;

}


/*
 * get the lines from a text file - return NULL if file can't be opened
 */
static char **
readfile(char *path)
{
	FILE	   *infile;
	int			maxlength = 0,
				linelen = 0;
	int			nlines = 0;
	char	  **result;
	char	   *buffer;
	int			c;

	if ((infile = fopen(path, "r")) == NULL)
		return NULL;

	/* pass over the file twice - the first time to size the result */

	while ((c = fgetc(infile)) != EOF)
	{
		linelen++;
		if (c == '\n')
		{
			nlines++;
			if (linelen > maxlength)
				maxlength = linelen;
			linelen = 0;
		}
	}

	/* handle last line without a terminating newline (yuck) */
	if (linelen)
		nlines++;
	if (linelen > maxlength)
		maxlength = linelen;

	/* set up the result and the line buffer */

	result = (char **) xmalloc((nlines + 1) * sizeof(char *));
	buffer = (char *) xmalloc(maxlength + 1);

	/* now reprocess the file and store the lines */
	rewind(infile);
	nlines = 0;
	while (fgets(buffer, maxlength + 1, infile) != NULL)
		result[nlines++] = xstrdup(buffer);

	fclose(infile);
	result[nlines] = NULL;

	return result;
}


static void
start_postmaster(void)
{
	/*
	 * Since there might be quotes to handle here, it is easier simply
	 * to pass everything to a shell to process them.
	 */
	char		cmd[MAXPGPATH];

	if (log_file != NULL)
		snprintf(cmd, MAXPGPATH, "\"%s\" %s </dev/null >>\"%s\" 2>&1 &",
				 postgres_path, post_opts, log_file);
	else
		snprintf(cmd, MAXPGPATH, "\"%s\" %s < /dev/null 2>&1 &",
				 postgres_path, post_opts);
	system(cmd);
}

/* Find the pgport and try a connection */
static bool
test_postmaster_connection(void)
{
	PGconn	   *conn;
	bool		success = false;
	int			i;
	char		portstr[32];

	snprintf(portstr, sizeof(portstr), "%d", DEF_PGPORT);

	for (i = 0; i < wait_seconds; i++)
	{
		if ((conn = PQsetdbLogin(NULL, portstr, NULL, NULL, "template1", NULL, NULL)) != NULL)
		{
			PQfinish(conn);
			success = true;
			break;
		}
	}

	return success;
}

static void
do_start(void)
{

	long		pid;
	long		old_pid = 0;

	if (ctl_command != RESTART_COMMAND)
	{
		old_pid = get_pgpid();
		if (old_pid != 0)
			fprintf(stderr,
					"%s: Another postmaster may be running. "
					"Trying to start postmaster anyway.\n",
					progname);
	}

	if (post_opts == NULL)
	{
		char	  **optlines;
		char	   *optline;
		int			len;

		optlines = readfile(ctl_command == RESTART_COMMAND ?
							postopts_file : def_postopts_file);
		if (optlines == NULL)
		{
			if (ctl_command == START_COMMAND)
				post_opts = "";
			else
			{
				fprintf(stderr, "%s: cannot read %s\n", progname, postopts_file);
				exit(1);
			}
		}
		else if (optlines[0] == NULL || optlines[1] != NULL)
		{
			fprintf(stderr, "%s: option file %s must have exactly 1 line\n",
					progname, ctl_command == RESTART_COMMAND ?
					postopts_file : def_postopts_file);
			exit(1);
		}
		else
		{
			optline = optlines[0];
			len = strcspn(optline, "\r\n");
			optline[len] = '\0';
	
			if (ctl_command == RESTART_COMMAND)
			{
				char	   *arg1;
	
				arg1 = strchr(optline, '\'');
				if (arg1 == NULL || arg1 == optline)
					post_opts = "";
				else
				{
					*(arg1 - 1) = '\0';
					post_opts = arg1;
				}
				if (postgres_path != NULL)
					postgres_path = optline;
			}
			else
				post_opts = optline;
		}
	}

	if (postgres_path == NULL)
	{
		char	   *postmaster_path;
		int			ret;

		postmaster_path = xmalloc(MAXPGPATH);

		if ((ret = find_other_exec(argv0, "postmaster", PM_VERSIONSTR,
								   postmaster_path)) < 0)
		{
			if (ret == -1)
				fprintf(stderr,
						_("The program \"postmaster\" is needed by %s "
				   "but was not found in the same directory as \"%s\".\n"
						  "Check your installation.\n"),
						progname, progname);
			else
				fprintf(stderr,
						_("The program \"postmaster\" was found by %s "
						  "but was not the same version as \"%s\".\n"
						  "Check your installation.\n"),
						progname, progname);
			exit(1);
		}
		postgres_path = postmaster_path;
	}

	start_postmaster();

	if (old_pid != 0)
	{
		pg_usleep(1000000);
		pid = get_pgpid();
		if (pid == old_pid)
		{
			fprintf(stderr,
					"%s: cannot start postmaster\n"
					"Examine the log output\n",
					progname);
			exit(1);
		}
	}

	if (do_wait)
	{
		if (!silence_echo)
		{
			printf("waiting for postmaster to start...");
			fflush(stdout);
		}

		if (test_postmaster_connection() == false)
			printf("could not start postmaster\n");
		else if (!silence_echo)
			printf("done\npostmaster successfully started\n");

	}
	else if (!silence_echo)
		printf("postmaster starting\n");
}

static void
do_stop(void)
{
	int			cnt;
	long		pid;

	pid = get_pgpid();

	if (pid == 0)				/* no pid file */
	{
		fprintf(stderr, "%s: could not find %s\n", progname, pid_file);
		fprintf(stderr, "Is postmaster running?\n");
		exit(1);
	}
	else if (pid < 0)			/* standalone backend, not postmaster */
	{
		pid = -pid;
		fprintf(stderr,
				"%s: cannot stop postmaster; "
				"postgres is running (PID: %ld)\n",
				progname, pid);
		exit(1);
	}

	if (kill((pid_t) pid, sig) != 0)
		fprintf(stderr, "failed\n");

	if (!do_wait)
	{
		if (!silence_echo)
			printf("postmaster shutting down\n");
		return;
	}

	/* continue on for wait case */

	if (!silence_echo)
	{
		printf("waiting for postmaster to shut down...");
		fflush(stdout);
	}

	for (cnt = 0; cnt < wait_seconds; cnt++)
	{
		if ((pid = get_pgpid()) != 0)
		{
			if (!silence_echo)
			{
				printf(".");
				fflush(stdout);
			}
			pg_usleep(1000000); /* 1 sec */
		}
		else
			break;
	}

	if (pid != 0)				/* pid file still exists */
	{
		if (!silence_echo)
			printf(" failed\n");

		fprintf(stderr, "%s: postmaster does not shut down\n", progname);
		exit(1);
	}
}

static void
do_restart(void)
{
	int			cnt;
	long		pid;

	pid = get_pgpid();

	if (pid == 0)				/* no pid file */
	{
		fprintf(stderr, "%s: could not find %s\n", progname, pid_file);
		fprintf(stderr, "Is postmaster running?\nstarting postmaster anyway\n");
		do_start();
		return;
	}
	else if (pid < 0)			/* standalone backend, not postmaster */
	{
		pid = -pid;
		fprintf(stderr,
				"%s: cannot restart postmaster; "
				"postgres is running (PID: %ld)\n",
				progname, pid);
		fprintf(stderr, "Please terminate postgres and try again.\n");
		exit(1);
	}

	if (kill((pid_t) pid, sig) != 0)
		fprintf(stderr, "failed\n");

	if (!silence_echo)
	{
		printf("waiting for postmaster to shut down...");
		fflush(stdout);
	}

	/* always wait for restart */

	for (cnt = 0; cnt < wait_seconds; cnt++)
	{
		if ((pid = get_pgpid()) != 0)
		{
			if (!silence_echo)
			{
				printf(".");
				fflush(stdout);
			}
			pg_usleep(1000000); /* 1 sec */
		}
		else
			break;
	}

	if (pid != 0)				/* pid file still exists */
	{
		if (!silence_echo)
			printf(" failed\n");
		fprintf(stderr, "%s: postmaster does not shut down\n", progname);
		exit(1);
	}

	do_start();

}


static void
do_reload(void)
{
	long		pid;

	pid = get_pgpid();
	if (pid == 0)				/* no pid file */
	{
		fprintf(stderr, "%s: could not find %s\n", progname, pid_file);
		fprintf(stderr, "Is postmaster running?\n");
		exit(1);
	}
	else if (pid < 0)			/* standalone backend, not postmaster */
	{
		pid = -pid;
		fprintf(stderr,
				"%s: cannot reload postmaster; "
				"postgres is running (PID: %ld)\n",
				progname, pid);
		fprintf(stderr, "Please terminate postgres and try again.\n");
		exit(1);
	}

	if (kill((pid_t) pid, sig) != 0)
		fprintf(stderr, "failed\n");

	if (!silence_echo)
		fprintf(stdout, "postmaster successfully signaled\n");
}

static void
do_status(void)
{
	long		pid;

	pid = get_pgpid();
	if (pid == 0)				/* no pid file */
	{
		fprintf(stderr, "%s: postmaster or postgres not running", progname);
		exit(1);
	}
	else if (pid < 0)			/* standalone backend */
	{
		pid = -pid;
		fprintf(stdout, "%s: a standalone backend \"postgres\" is running (PID: %ld)", progname, pid);
	}
	else
/* postmaster */
	{
		char	  **optlines;
		char	  **line;

		fprintf(stdout, "%s: postmaster is running (PID: %ld)", progname, pid);

		optlines = readfile(postopts_file);
		for (line = optlines; *line != NULL; line++)
			fputs(*line, stdout);
	}
}

static void
do_kill(void)
{
	if (kill(killproc, sig) != 0)
		fprintf(stderr, "failed\n");
}


static void
do_advice(void)
{
	fprintf(stderr, "\nTry \"%s --help\" for more information.\n", progname);
}


static char *helplines[] =
{
	"%s is a utility to start, stop, restart, reload configuration files,\n",
	"report the status of a PostgreSQL server, or kill a PostgreSQL process\n\n",
	"Usage:\n",
	"  %s start   [-w] [-D DATADIR] [-s] [-l FILENAME] [-o \"OPTIONS\"]\n",
	"  %s stop    [-W] [-D DATADIR] [-s] [-m SHUTDOWN-MODE]\n",
	"  %s restart [-w] [-D DATADIR] [-s] [-m SHUTDOWN-MODE] [-o \"OPTIONS\"]\n",
	"  %s reload  [-D DATADIR] [-s]\n",
	"  %s status  [-D DATADIR]\n",
	"  %s kill    SIGNALNAME PROCESSID\n",
	"Common options:\n",
	"  -D DATADIR   location of the database storage area\n",
	"  -s           only print errors, no informational messages\n",
	"  -w           wait until operation completes\n",
	"  -W           do not wait until operation completes\n",
	"  --help       show this help, then exit\n",
	"  --version    output version information, then exit\n",
	"(The default is to wait for shutdown, but not for start or restart.)\n\n",
	"If the -D option is omitted, the environment variable PGDATA is used.\n\n",
	"Options for start or restart:\n",
	"  -l FILENAME             write (or append) server log to FILENAME.  The\n",
	"                          use of this option is highly recommended.\n",
	"  -o OPTIONS              command line options to pass to the postmaster\n",
	"                          (PostgreSQL server executable)\n",
	"  -p PATH-TO-POSTMASTER   normally not necessary\n\n",
	"Options for stop or restart:\n",
	"  -m SHUTDOWN-MODE   may be 'smart', 'fast', or 'immediate'\n\n",
	"Allowed signal names for kill:\n",
	"  -HUP -INT -QUIT -ABRT -TERM -USR1 -USR2\n\n",
	"Shutdown modes are:\n",
	"  smart       quit after all clients have disconnected\n",
	"  fast        quit directly, with proper shutdown\n",
	"  immediate   quit without complete shutdown; will lead to recovery on restart\n\n",
	"Report bugs to <pgsql-bugs@postgresql.org>.\n",
	NULL
};

static void
do_help(void)
{
	char	  **line;

	for (line = helplines; *line; line++)
		/* assuming we can use gettext this way */
		printf(_(*line), progname);
}

static void
set_mode(char *modeopt)
{
	if (strcmp(modeopt, "s") == 0 || strcmp(modeopt, "smart") == 0)
	{
		shutdown_mode = SMART_MODE;
		sig = SIGTERM;
	}
	else if (strcmp(modeopt, "f") == 0 || strcmp(modeopt, "fast") == 0)
	{
		shutdown_mode = FAST_MODE;
		sig = SIGINT;
	}
	else if (strcmp(modeopt, "i") == 0 || strcmp(modeopt, "immediate") == 0)
	{
		shutdown_mode = IMMEDIATE_MODE;
		sig = SIGQUIT;
	}
	else
	{
		fprintf(stderr, "%s: invalid shutdown mode %s\n", progname, modeopt);
		do_advice();
		exit(1);
	}
}


static void
set_sig(char *signame)
{
	if (!strcmp(signame, "-HUP"))
		sig = SIGHUP;
	else if (!strcmp(signame, "-INT"))
		sig = SIGINT;
	else if (!strcmp(signame, "-QUIT"))
		sig = SIGQUIT;
	else if (!strcmp(signame, "-ABRT"))
		sig = SIGABRT;

	/*
	 * probably should NOT provide SIGKILL
	 *
	 * else if (!strcmp(signame,"-KILL")) sig = SIGKILL;
	 */
	else if (!strcmp(signame, "-TERM"))
		sig = SIGTERM;
	else if (!strcmp(signame, "-USR1"))
		sig = SIGUSR1;
	else if (!strcmp(signame, "-USR2"))
		sig = SIGUSR2;
	else
	{
		fprintf(stderr, "%s: invalid signal \"%s\"\n", progname, signame);
		do_advice();
		exit(1);
	}

}

int
main(int argc, char **argv)
{

	int			i;

#ifdef WIN32
	setvbuf(stderr, NULL, _IONBF, 0);
#endif

	progname = get_progname(argv[0]);

	/*
	 * save argv[0] so do_start() can look for the postmaster if
	 * necessary. we don't look for postmaster here because in many cases
	 * we won't need it.
	 */

	argv0 = argv[0];

	umask(077);


	for (i = 0; i < argc; i++)
	{
		char	   *arg = argv[i];

		if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0 ||
			strcmp(arg, "-?") == 0)
		{
			do_help();
			exit(0);
		}
		else if (strcmp(arg, "-V") == 0 || strcmp(arg, "--version") == 0)
		{
			printf("pg_ctl (PostgreSQL) %s\n", PG_VERSION);
			exit(0);
		}
		else if (strcmp(arg, "-D") == 0 && i < argc - 1)
		{
			int			len = strlen(arg) + 4;
			char	   *env_var;

			i++;
			arg = argv[i];

			pg_data_opts = xmalloc(len);
			snprintf(pg_data_opts, len, "-D %s", arg);
			env_var = xmalloc(len + 8);
			snprintf(env_var, len + 8, "PGDATA=%s", arg);
			putenv(env_var);
		}
		else if (strcmp(arg, "-l") == 0 && i < argc - 1)
		{
			i++;
			arg = argv[i];
			log_file = xstrdup(arg);
		}
		else if (strncmp(arg, "-l", 2) == 0 && strlen(arg) > 2)
			log_file = xstrdup(arg + 2);
		else if (strcmp(arg, "-m") == 0 && i < argc - 1)
		{
			i++;
			arg = argv[i];
			set_mode(arg);
		}
		else if (strncmp(arg, "-m", 2) == 0 && strlen(arg) > 2)
			set_mode(arg + 2);
		else if (strcmp(arg, "-o") == 0 && i < argc - 1)
		{
			i++;
			arg = argv[i];
			post_opts = xstrdup(arg);
		}
		else if (strcmp(arg, "-p") == 0 && i < argc - 1)
		{
			i++;
			arg = argv[i];
			postgres_path = xstrdup(arg);
		}
		else if (strcmp(arg, "-s") == 0)
			silence_echo = true;
		else if (strcmp(arg, "-w") == 0)
		{
			do_wait = true;
			wait_set = true;
		}
		else if (strcmp(arg, "-W") == 0)
		{
			do_wait = false;
			wait_set = true;
		}
		else if (arg[0] == '-')
		{
			fprintf(stderr, "%s: invalid option %s\n", progname, arg);
			do_advice();
			exit(1);
		}
		else if (strcmp(arg, "start") == 0 && ctl_command == NO_COMMAND)
			ctl_command = START_COMMAND;
		else if (strcmp(arg, "stop") == 0 && ctl_command == NO_COMMAND)
			ctl_command = STOP_COMMAND;
		else if (strcmp(arg, "restart") == 0 && ctl_command == NO_COMMAND)
			ctl_command = RESTART_COMMAND;
		else if (strcmp(arg, "reload") == 0 && ctl_command == NO_COMMAND)
			ctl_command = RELOAD_COMMAND;
		else if (strcmp(arg, "status") == 0 && ctl_command == NO_COMMAND)
			ctl_command = STATUS_COMMAND;
		else if (i == 0 && argc >= 3 && strcmp(arg, "kill") == 0)
		{
			/* stricter syntax for kill command */
			ctl_command = KILL_COMMAND;
			set_sig(argv[1]);
			killproc = atol(argv[2]);
			i += 2;
		}
		else if (arg[0] == '-')
		{
			fprintf(stderr, "%s: invalid operation mode %s\n", progname, arg);
			do_advice();
			exit(1);
		}
	}

	if (ctl_command == NO_COMMAND)
	{
		fprintf(stderr, "%s: no operation specified\n", progname);
		do_advice();
		exit(1);
	}

	pg_data = getenv("PGDATA");
	canonicalize_path(pg_data);

	if (pg_data == NULL && ctl_command != KILL_COMMAND)
	{
		fprintf(stderr,
				"%s: no database directory specified "
				"and environment variable PGDATA unset\n",
				progname);
		do_advice();
		exit(1);
	}

	if (!wait_set)
	{
		switch (ctl_command)
		{
			case RESTART_COMMAND:
			case START_COMMAND:
				do_wait = false;
				break;
			case STOP_COMMAND:
				do_wait = true;
				break;
			default:
				break;
		}
	}

	if (ctl_command == RELOAD_COMMAND)
	{
		sig = SIGHUP;
		do_wait = false;
	}

	snprintf(def_postopts_file, MAXPGPATH, "%s/postmaster.opts.default", pg_data);
	snprintf(postopts_file, MAXPGPATH, "%s/postmaster.opts", pg_data);
	snprintf(pid_file, MAXPGPATH, "%s/postmaster.pid", pg_data);
	snprintf(conf_file, MAXPGPATH, "%s/postgresql.conf", pg_data);

	switch (ctl_command)
	{
		case STATUS_COMMAND:
			do_status();
			break;
		case START_COMMAND:
			do_start();
			break;
		case STOP_COMMAND:
			do_stop();
			break;
		case RESTART_COMMAND:
			do_restart();
			break;
		case RELOAD_COMMAND:
			do_reload();
			break;
		case KILL_COMMAND:
			do_kill();
			break;
		default:
			break;
	}

	exit(0);

}
Tue, 25 May 2004 00:03:39 -0400 (EDT)
Bruce Momjian <pgman@candle.pha.pa.us>
pg_ctl.c
Bruce Momjian wrote:
> I am almost finished Andrew's version of pg_ctl.c.  Here is the current
> version I am using.

Sorry, I should have sent this to patches instead.

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Tue, 25 May 2004 09:54:31 -0400 (EDT)
Bruce Momjian <pgman@candle.pha.pa.us>
Re: pg_ctl.c
Bruce Momjian wrote:

>I am almost finished Andrew's version of pg_ctl.c.  Here is the current
>version I am using.
>
>  
>

Bruce,

Thanks for advancing this.

I think this is probably fairly close for Unix - the main thing missing 
is a more determined effort to find out what port is actually being used 
(i.e we need to check the options and the config file).

For Windows we will need different command lines in start_postgres() (or 
if that won't work direct calls to CreateProcess() ), and a way to make 
sure we don't collide with management by SCM - probably the easiest way 
once we have a way of detecting that this is so is to issue "net 
{stop,start} servicename" commands instead of sending 
SIGINT/SIGQUIT/SIGTERM followed by a call to run postmaster.

If you can get it in a shape that we can get it in before feature freeze 
I will try to do any polishing necessary afterwards - unfortunately 
pressure of work is restricting my time right now.

cheers

andrew



Tue, 25 May 2004 11:40:36 -0400
Andrew Dunstan <andrew@dunslane.net>
Re: [HACKERS] pg_ctl.c
Andrew Dunstan wrote:
> Bruce Momjian wrote:
> 
> >I am almost finished Andrew's version of pg_ctl.c.  Here is the current
> >version I am using.
> >
> >  
> >
> 
> Bruce,
> 
> Thanks for advancing this.
> 
> I think this is probably fairly close for Unix - the main thing missing 
> is a more determined effort to find out what port is actually being used 
> (i.e we need to check the options and the config file).

Oh, I see that now.  Let me work on that.

> For Windows we will need different command lines in start_postgres() (or 
> if that won't work direct calls to CreateProcess() ), and a way to make 
> sure we don't collide with management by SCM - probably the easiest way 
> once we have a way of detecting that this is so is to issue "net 
> {stop,start} servicename" commands instead of sending 
> SIGINT/SIGQUIT/SIGTERM followed by a call to run postmaster.
> 
> If you can get it in a shape that we can get it in before feature freeze 
> I will try to do any polishing necessary afterwards - unfortunately 
> pressure of work is restricting my time right now.

Agreed.  Once it is in CVS we can adjust it.

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Tue, 25 May 2004 11:51:16 -0400 (EDT)
Bruce Momjian <pgman@candle.pha.pa.us>
Re: [HACKERS] pg_ctl.c