Extend pg_ctl to handle service management under WIN32. Lacks docs.

Claudio Natoli and Magnus Hagander
This commit is contained in:
Tom Lane 2004-06-24 18:23:26 +00:00
parent df9d87f608
commit f8dd00c3ef
1 changed files with 423 additions and 76 deletions

View File

@ -4,7 +4,7 @@
*
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/bin/pg_ctl/pg_ctl.c,v 1.16 2004/06/11 16:36:31 momjian Exp $
* $PostgreSQL: pgsql/src/bin/pg_ctl/pg_ctl.c,v 1.17 2004/06/24 18:23:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -52,7 +52,10 @@ typedef enum
RESTART_COMMAND,
RELOAD_COMMAND,
STATUS_COMMAND,
KILL_COMMAND
KILL_COMMAND,
REGISTER_COMMAND,
UNREGISTER_COMMAND,
RUN_AS_SERVICE_COMMAND
} CtlCommand;
@ -63,14 +66,20 @@ static bool silence_echo = false;
static ShutdownMode shutdown_mode = SMART_MODE;
static int sig = SIGTERM; /* default */
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 *register_servicename = "PostgreSQL"; /* FIXME: + version ID? */
static char *register_username = NULL;
static char *register_password = NULL;
static char *argv0 = NULL;
static void write_stderr(const char *fmt,...)
/* This extension allows gcc to check the format string for consistency with
the supplied arguments. */
__attribute__((format(printf, 1, 2)));
static void *xmalloc(size_t size);
static char *xstrdup(const char *s);
static void do_advice(void);
@ -83,6 +92,16 @@ static void do_restart(void);
static void do_reload(void);
static void do_status(void);
static void do_kill(pgpid_t pid);
#ifdef WIN32
static bool pgwin32_IsInstalled(SC_HANDLE);
static char* pgwin32_CommandLine(bool);
static void pgwin32_doRegister();
static void pgwin32_doUnregister();
static void pgwin32_SetServiceStatus(DWORD);
static void WINAPI pgwin32_ServiceHandler(DWORD);
static void WINAPI pgwin32_ServiceMain(DWORD, LPTSTR*);
static void pgwin32_doRunAsService();
#endif
static pgpid_t get_pgpid(void);
static char **readfile(char *path);
static int start_postmaster(void);
@ -93,6 +112,63 @@ static char postopts_file[MAXPGPATH];
static char pid_file[MAXPGPATH];
static char conf_file[MAXPGPATH];
#ifdef WIN32
static void
write_eventlog(int level, const char *line)
{
static HANDLE evtHandle = INVALID_HANDLE_VALUE;
if (evtHandle == INVALID_HANDLE_VALUE) {
evtHandle = RegisterEventSource(NULL,"PostgreSQL");
if (evtHandle == NULL) {
evtHandle = INVALID_HANDLE_VALUE;
return;
}
}
ReportEvent(evtHandle,
level,
0,
0, /* All events are Id 0 */
NULL,
1,
0,
&line,
NULL);
}
#endif
/*
* Write errors to stderr (or by equal means when stderr is
* not available).
*/
static void
write_stderr(const char *fmt,...)
{
va_list ap;
va_start(ap, fmt);
#ifndef WIN32
/* On Unix, we just fprintf to stderr */
vfprintf(stderr, fmt, ap);
#else
/* On Win32, we print to stderr if running on a console, or write to
* eventlog if running as a service */
if (!isatty(fileno(stderr))) /* Running as a service */
{
char errbuf[2048]; /* Arbitrary size? */
vsnprintf(errbuf, sizeof(errbuf), fmt, ap);
write_eventlog(EVENTLOG_ERROR_TYPE, errbuf);
}
else /* Not running as service, write to stderr */
vfprintf(stderr, fmt, ap);
#endif
va_end(ap);
}
/*
* routines to check memory allocations and fail noisily.
*/
@ -105,7 +181,7 @@ xmalloc(size_t size)
result = malloc(size);
if (!result)
{
fprintf(stderr, _("%s: out of memory\n"), progname);
write_stderr(_("%s: out of memory\n"), progname);
exit(1);
}
return result;
@ -121,7 +197,7 @@ xstrdup(const char *s)
result = strdup(s);
if (!result)
{
fprintf(stderr, _("%s: out of memory\n"), progname);
write_stderr(_("%s: out of memory\n"), progname);
exit(1);
}
return result;
@ -352,10 +428,9 @@ do_start(void)
{
old_pid = get_pgpid();
if (old_pid != 0)
fprintf(stderr,
_("%s: Another postmaster may be running. "
"Trying to start postmaster anyway.\n"),
progname);
write_stderr(_("%s: Another postmaster may be running. "
"Trying to start postmaster anyway.\n"),
progname);
}
if (post_opts == NULL)
@ -371,13 +446,13 @@ do_start(void)
post_opts = "";
else
{
fprintf(stderr, _("%s: cannot read %s\n"), progname, postopts_file);
write_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"),
write_stderr(_("%s: option file %s must have exactly 1 line\n"),
progname, ctl_command == RESTART_COMMAND ?
postopts_file : def_postopts_file);
exit(1);
@ -419,18 +494,16 @@ do_start(void)
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);
write_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);
write_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;
@ -438,7 +511,7 @@ do_start(void)
if (start_postmaster() != 0)
{
fprintf(stderr, _("Unable to run the postmaster binary\n"));
write_stderr(_("Unable to run the postmaster binary\n"));
exit(1);
}
@ -448,10 +521,9 @@ do_start(void)
pid = get_pgpid();
if (pid == old_pid)
{
fprintf(stderr,
_("%s: cannot start postmaster\n"
"Examine the log output\n"),
progname);
write_stderr(_("%s: cannot start postmaster\n"
"Examine the log output\n"),
progname);
exit(1);
}
}
@ -485,23 +557,22 @@ do_stop(void)
if (pid == 0) /* no pid file */
{
fprintf(stderr, _("%s: could not find %s\n"), progname, pid_file);
fprintf(stderr, _("Is postmaster running?\n"));
write_stderr(_("%s: could not find %s\n"), progname, pid_file);
write_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);
write_stderr(_("%s: cannot stop postmaster; "
"postgres is running (PID: %ld)\n"),
progname, pid);
exit(1);
}
if (kill((pid_t) pid, sig) != 0)
{
fprintf(stderr, _("stop signal failed (PID: %ld): %s\n"), pid,
write_stderr(_("stop signal failed (PID: %ld): %s\n"), pid,
strerror(errno));
exit(1);
}
@ -540,7 +611,7 @@ do_stop(void)
if (!silence_echo)
printf(_(" failed\n"));
fprintf(stderr, _("%s: postmaster does not shut down\n"), progname);
write_stderr(_("%s: postmaster does not shut down\n"), progname);
exit(1);
}
if (!silence_echo)
@ -565,25 +636,24 @@ do_restart(void)
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"));
write_stderr(_("%s: could not find %s\n"), progname, pid_file);
write_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"));
write_stderr(_("%s: cannot restart postmaster; "
"postgres is running (PID: %ld)\n"),
progname, pid);
write_stderr(_("Please terminate postgres and try again.\n"));
exit(1);
}
if (kill((pid_t) pid, sig) != 0)
{
fprintf(stderr, _("stop signal failed (PID: %ld): %s\n"), pid,
write_stderr(_("stop signal failed (PID: %ld): %s\n"), pid,
strerror(errno));
exit(1);
}
@ -616,7 +686,7 @@ do_restart(void)
if (!silence_echo)
printf(_(" failed\n"));
fprintf(stderr, _("%s: postmaster does not shut down\n"), progname);
write_stderr(_("%s: postmaster does not shut down\n"), progname);
exit(1);
}
@ -636,24 +706,23 @@ do_reload(void)
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"));
write_stderr(_("%s: could not find %s\n"), progname, pid_file);
write_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"));
write_stderr(_("%s: cannot reload postmaster; "
"postgres is running (PID: %ld)\n"),
progname, pid);
write_stderr(_("Please terminate postgres and try again.\n"));
exit(1);
}
if (kill((pid_t) pid, sig) != 0)
{
fprintf(stderr, _("reload signal failed (PID: %ld): %s\n"), pid,
write_stderr(_("reload signal failed (PID: %ld): %s\n"), pid,
strerror(errno));
exit(1);
}
@ -674,7 +743,7 @@ do_status(void)
pid = get_pgpid();
if (pid == 0) /* no pid file */
{
fprintf(stderr, _("%s: postmaster or postgres not running\n"), progname);
write_stderr(_("%s: postmaster or postgres not running\n"), progname);
exit(1);
}
else if (pid < 0) /* standalone backend */
@ -702,18 +771,244 @@ do_kill(pgpid_t pid)
{
if (kill((pid_t) pid, sig) != 0)
{
fprintf(stderr, _("signal %d failed (PID: %ld): %s\n"), sig, pid,
write_stderr(_("signal %d failed (PID: %ld): %s\n"), sig, pid,
strerror(errno));
exit(1);
}
}
#ifdef WIN32
static bool pgwin32_IsInstalled(SC_HANDLE hSCM)
{
SC_HANDLE hService = OpenService(hSCM, register_servicename, SERVICE_QUERY_CONFIG);
bool bResult = (hService != NULL);
if (bResult)
CloseServiceHandle(hService);
return bResult;
}
static char* pgwin32_CommandLine(bool registration)
{
static char cmdLine[MAXPGPATH];
int ret;
if (registration)
ret = find_my_exec(argv0, cmdLine);
else
ret = find_other_exec(argv0, "postmaster", PM_VERSIONSTR, cmdLine);
if (ret != 0)
{
write_stderr(_("Unable to find exe"));
exit(1);
}
if (registration)
{
if (strcasecmp(cmdLine+strlen(cmdLine)-4,".exe"))
{
/* If commandline does not end in .exe, append it */
strcat(cmdLine,".exe");
}
strcat(cmdLine," runservice -N \"");
strcat(cmdLine,register_servicename);
strcat(cmdLine,"\"");
}
if (pg_data)
{
strcat(cmdLine," -D \"");
strcat(cmdLine,pg_data);
strcat(cmdLine,"\"");
}
if (post_opts)
{
strcat(cmdLine," ");
if (registration)
strcat(cmdLine," -o \"");
strcat(cmdLine,post_opts);
if (registration)
strcat(cmdLine,"\"");
}
return cmdLine;
}
static void
pgwin32_doRegister()
{
SC_HANDLE hService;
SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hSCM == NULL)
{
write_stderr(_("Unable to open service manager\n"));
exit(1);
}
if (pgwin32_IsInstalled(hSCM))
{
CloseServiceHandle(hSCM);
write_stderr(_("Service \"%s\" already registered\n"),register_servicename);
exit(1);
}
if ((hService = CreateService(hSCM, register_servicename, register_servicename,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
pgwin32_CommandLine(true),
NULL, NULL, "RPCSS\0", register_username, register_password)) == NULL)
{
CloseServiceHandle(hSCM);
write_stderr(_("Unable to register service \"%s\" [%d]\n"), register_servicename, (int)GetLastError());
exit(1);
}
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
}
static void
pgwin32_doUnregister()
{
SC_HANDLE hService;
SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hSCM == NULL)
{
write_stderr(_("Unable to open service manager\n"));
exit(1);
}
if (!pgwin32_IsInstalled(hSCM))
{
CloseServiceHandle(hSCM);
write_stderr(_("Service \"%s\" not registered\n"),register_servicename);
exit(1);
}
if ((hService = OpenService(hSCM, register_servicename, DELETE)) == NULL)
{
CloseServiceHandle(hSCM);
write_stderr(_("Unable to open service \"%s\" [%d]\n"), register_servicename, (int)GetLastError());
exit(1);
}
if (!DeleteService(hService)) {
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
write_stderr(_("Unable to unregister service \"%s\" [%d]\n"), register_servicename, (int)GetLastError());
exit(1);
}
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
}
static SERVICE_STATUS status;
static SERVICE_STATUS_HANDLE hStatus = (SERVICE_STATUS_HANDLE)0;
static HANDLE shutdownHandles[2];
static pid_t postmasterPID = -1;
#define shutdownEvent shutdownHandles[0]
#define postmasterProcess shutdownHandles[1]
static void pgwin32_SetServiceStatus(DWORD currentState)
{
status.dwCurrentState = currentState;
SetServiceStatus(hStatus, (LPSERVICE_STATUS)&status);
}
static void WINAPI pgwin32_ServiceHandler(DWORD request)
{
switch (request)
{
case SERVICE_CONTROL_STOP:
case SERVICE_CONTROL_SHUTDOWN:
pgwin32_SetServiceStatus(SERVICE_STOP_PENDING);
SetEvent(shutdownEvent);
return;
case SERVICE_CONTROL_PAUSE:
/* Win32 config reloading */
kill(postmasterPID,SIGHUP);
return;
/* FIXME: These could be used to replace other signals etc */
case SERVICE_CONTROL_CONTINUE:
case SERVICE_CONTROL_INTERROGATE:
default:
break;
}
}
static void WINAPI pgwin32_ServiceMain(DWORD argc, LPTSTR *argv)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
DWORD ret;
/* Initialize variables */
status.dwWin32ExitCode = S_OK;
status.dwCheckPoint = 0;
status.dwWaitHint = 0;
status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
status.dwControlsAccepted = SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_PAUSE_CONTINUE;
status.dwServiceSpecificExitCode = 0;
status.dwCurrentState = SERVICE_START_PENDING;
memset(&pi,0,sizeof(pi));
memset(&si,0,sizeof(si));
si.cb = sizeof(si);
/* Register the control request handler */
if ((hStatus = RegisterServiceCtrlHandler(register_servicename, pgwin32_ServiceHandler)) == (SERVICE_STATUS_HANDLE)0)
return;
if ((shutdownEvent = CreateEvent(NULL,true,false,NULL)) == NULL)
return;
/* Start the postmaster */
pgwin32_SetServiceStatus(SERVICE_START_PENDING);
if (!CreateProcess(NULL,pgwin32_CommandLine(false),NULL,NULL,TRUE,0,NULL,NULL,&si,&pi))
{
pgwin32_SetServiceStatus(SERVICE_STOPPED);
return;
}
postmasterPID = pi.dwProcessId;
postmasterProcess = pi.hProcess;
CloseHandle(pi.hThread);
pgwin32_SetServiceStatus(SERVICE_RUNNING);
/* Wait for quit... */
ret = WaitForMultipleObjects(2,shutdownHandles,FALSE,INFINITE);
pgwin32_SetServiceStatus(SERVICE_STOP_PENDING);
switch (ret)
{
case WAIT_OBJECT_0: /* shutdown event */
kill(postmasterPID,SIGINT);
WaitForSingleObject(postmasterProcess,INFINITE);
break;
case (WAIT_OBJECT_0+1): /* postmaster went down */
break;
default:
/* assert(false); */
}
CloseHandle(shutdownEvent);
CloseHandle(postmasterProcess);
pgwin32_SetServiceStatus(SERVICE_STOPPED);
}
static void pgwin32_doRunAsService()
{
SERVICE_TABLE_ENTRY st[] = {{ register_servicename, pgwin32_ServiceMain },
{ NULL, NULL }};
StartServiceCtrlDispatcher(st);
}
#endif
static void
do_advice(void)
{
fprintf(stderr, _("\nTry \"%s --help\" for more information.\n"), progname);
write_stderr(_("\nTry \"%s --help\" for more information.\n"), progname);
}
@ -730,9 +1025,18 @@ do_help(void)
printf(_(" %s reload [-D DATADIR] [-s]\n"), progname);
printf(_(" %s status [-D DATADIR]\n"), progname);
printf(_(" %s kill SIGNALNAME PROCESSID\n"), progname);
#ifdef WIN32
printf(_(" %s register [-N servicename] [-U username] [-P password] [-D DATADIR] [-o \"OPTIONS\"]\n"), progname);
printf(_(" %s unregister [-N servicename]\n"), progname);
#endif
printf(_("Common options:\n"));
printf(_(" -D, --pgdata DATADIR location of the database storage area\n"));
printf(_(" -s, --silent only print errors, no informational messages\n"));
#ifdef WIN32
printf(_(" -N service name with which to register PostgreSQL server\n"));
printf(_(" -P user name of account to register PostgreSQL server\n"));
printf(_(" -U password of account to register PostgreSQL server\n"));
#endif
printf(_(" -w wait until operation completes\n"));
printf(_(" -W do not wait until operation completes\n"));
printf(_(" --help show this help, then exit\n"));
@ -778,7 +1082,7 @@ set_mode(char *modeopt)
}
else
{
fprintf(stderr, _("%s: invalid shutdown mode %s\n"), progname, modeopt);
write_stderr(_("%s: invalid shutdown mode %s\n"), progname, modeopt);
do_advice();
exit(1);
}
@ -811,7 +1115,7 @@ set_sig(char *signame)
sig = SIGUSR2;
else
{
fprintf(stderr, _("%s: invalid signal \"%s\"\n"), progname, signame);
write_stderr(_("%s: invalid signal \"%s\"\n"), progname, signame);
do_advice();
exit(1);
}
@ -879,19 +1183,17 @@ main(int argc, char **argv)
/* process command-line options */
while (optind < argc)
{
while ((c = getopt_long(argc, argv, "D:l:m:o:p:swW", long_options, &option_index)) != -1)
while ((c = getopt_long(argc, argv, "D:l:m:N:o:p:P:sU:wW", long_options, &option_index)) != -1)
{
switch (c)
{
case 'D':
{
int len = strlen(optarg) + 4;
int len = strlen(optarg);
char *env_var;
pg_data_opts = xmalloc(len);
snprintf(pg_data_opts, len, "-D %s", optarg);
env_var = xmalloc(len + sizeof("PGDATA="));
snprintf(env_var, len + sizeof("PGDATA="), "PGDATA=%s", optarg);
env_var = xmalloc(len + 8);
snprintf(env_var, len + 8, "PGDATA=%s", optarg);
putenv(env_var);
break;
}
@ -901,15 +1203,36 @@ main(int argc, char **argv)
case 'm':
set_mode(optarg);
break;
case 'N':
register_servicename = xstrdup(optarg);
break;
case 'o':
post_opts = xstrdup(optarg);
break;
case 'p':
postgres_path = xstrdup(optarg);
break;
case 'P':
register_password = xstrdup(optarg);
break;
case 's':
silence_echo = true;
break;
case 'U':
if (strchr(optarg,'\\'))
register_username = xstrdup(optarg);
else /* Prepend .\ for local accounts */
{
register_username = malloc(strlen(optarg)+3);
if (!register_username)
{
write_stderr(_("%s: out of memory\n"), progname);
exit(1);
}
strcpy(register_username,".\\");
strcat(register_username,optarg);
}
break;
case 'w':
do_wait = true;
wait_set = true;
@ -919,7 +1242,7 @@ main(int argc, char **argv)
wait_set = true;
break;
default:
fprintf(stderr, _("%s: invalid option %s\n"), progname, optarg);
write_stderr(_("%s: invalid option %s\n"), progname, optarg);
do_advice();
exit(1);
}
@ -930,7 +1253,7 @@ main(int argc, char **argv)
{
if (ctl_command != NO_COMMAND)
{
fprintf(stderr, _("%s: extra operation mode %s\n"), progname, argv[optind]);
write_stderr(_("%s: extra operation mode %s\n"), progname, argv[optind]);
do_advice();
exit(1);
}
@ -949,7 +1272,7 @@ main(int argc, char **argv)
{
if (argc - optind < 3)
{
fprintf(stderr, _("%s: invalid kill syntax\n"), progname);
write_stderr(_("%s: invalid kill syntax\n"), progname);
do_advice();
exit(1);
}
@ -957,32 +1280,45 @@ main(int argc, char **argv)
set_sig(argv[++optind]);
killproc = atol(argv[++optind]);
}
#ifdef WIN32
else if (strcmp(argv[optind], "register") == 0)
ctl_command = REGISTER_COMMAND;
else if (strcmp(argv[optind], "unregister") == 0)
ctl_command = UNREGISTER_COMMAND;
else if (strcmp(argv[optind], "runservice") == 0)
ctl_command = RUN_AS_SERVICE_COMMAND;
#endif
else
{
fprintf(stderr, _("%s: invalid operation mode %s\n"), progname, argv[optind]);
write_stderr(_("%s: invalid operation mode %s\n"), progname, argv[optind]);
do_advice();
exit(1);
}
optind++;
}
}
if (ctl_command == NO_COMMAND)
{
fprintf(stderr, _("%s: no operation specified\n"), progname);
write_stderr(_("%s: no operation specified\n"), progname);
do_advice();
exit(1);
}
/* Note we put any -D switch into the env var above */
pg_data = getenv("PGDATA");
canonicalize_path(pg_data);
if (pg_data == NULL && ctl_command != KILL_COMMAND)
if (pg_data)
{
fprintf(stderr,
_("%s: no database directory specified "
"and environment variable PGDATA unset\n"),
progname);
/* XXX modifies environment var in-place ... ugly ... */
canonicalize_path(pg_data);
}
if (pg_data == NULL &&
ctl_command != KILL_COMMAND && ctl_command != UNREGISTER_COMMAND)
{
write_stderr(_("%s: no database directory specified "
"and environment variable PGDATA unset\n"),
progname);
do_advice();
exit(1);
}
@ -1034,6 +1370,17 @@ main(int argc, char **argv)
case KILL_COMMAND:
do_kill(killproc);
break;
#ifdef WIN32
case REGISTER_COMMAND:
pgwin32_doRegister();
break;
case UNREGISTER_COMMAND:
pgwin32_doUnregister();
break;
case RUN_AS_SERVICE_COMMAND:
pgwin32_doRunAsService();
break;
#endif
default:
break;
}