1 /*-------------------------------------------------------------------------
3 * pg_ctl --- start/stops/restarts the PostgreSQL server
5 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
9 *-------------------------------------------------------------------------
14 * Need this to get defines for restricted tokens and jobs. And it
15 * has to be set before any header from the Win32 API is loaded.
17 #define _WIN32_WINNT 0x0500
20 #include "postgres_fe.h"
25 #include <sys/types.h>
29 #ifdef HAVE_SYS_RESOURCE_H
31 #include <sys/resource.h>
34 #include "libpq/pqsignal.h"
35 #include "getopt_long.h"
36 #include "miscadmin.h"
38 #if defined(__CYGWIN__)
39 #include <sys/cygwin.h>
41 /* Cygwin defines WIN32 in windows.h, but we don't want it. */
45 /* PID can be negative for standalone backend */
68 RUN_AS_SERVICE_COMMAND
71 #define DEFAULT_WAIT 60
73 static bool do_wait
= false;
74 static bool wait_set
= false;
75 static int wait_seconds
= DEFAULT_WAIT
;
76 static bool silent_mode
= false;
77 static ShutdownMode shutdown_mode
= SMART_MODE
;
78 static int sig
= SIGTERM
; /* default */
79 static CtlCommand ctl_command
= NO_COMMAND
;
80 static char *pg_data
= NULL
;
81 static char *pgdata_opt
= NULL
;
82 static char *post_opts
= NULL
;
83 static const char *progname
;
84 static char *log_file
= NULL
;
85 static char *postgres_path
= NULL
;
86 static char *register_servicename
= "PostgreSQL"; /* FIXME: + version ID? */
87 static char *register_username
= NULL
;
88 static char *register_password
= NULL
;
89 static char *argv0
= NULL
;
90 static bool allow_core_files
= false;
93 write_stderr(const char *fmt
,...)
94 /* This extension allows gcc to check the format string for consistency with
95 the supplied arguments. */
96 __attribute__((format(printf
, 1, 2)));
97 static void *pg_malloc(size_t size
);
98 static char *xstrdup(const char *s
);
99 static void do_advice(void);
100 static void do_help(void);
101 static void set_mode(char *modeopt
);
102 static void set_sig(char *signame
);
103 static void do_start(void);
104 static void do_stop(void);
105 static void do_restart(void);
106 static void do_reload(void);
107 static void do_status(void);
108 static void do_kill(pgpid_t pid
);
109 static void print_msg(const char *msg
);
111 #if defined(WIN32) || defined(__CYGWIN__)
112 static bool pgwin32_IsInstalled(SC_HANDLE
);
113 static char *pgwin32_CommandLine(bool);
114 static void pgwin32_doRegister(void);
115 static void pgwin32_doUnregister(void);
116 static void pgwin32_SetServiceStatus(DWORD
);
117 static void WINAPI
pgwin32_ServiceHandler(DWORD
);
118 static void WINAPI
pgwin32_ServiceMain(DWORD
, LPTSTR
*);
119 static void pgwin32_doRunAsService(void);
120 static int CreateRestrictedProcess(char *cmd
, PROCESS_INFORMATION
*processInfo
, bool as_service
);
122 static SERVICE_STATUS status
;
123 static SERVICE_STATUS_HANDLE hStatus
= (SERVICE_STATUS_HANDLE
) 0;
124 static HANDLE shutdownHandles
[2];
125 static pid_t postmasterPID
= -1;
127 #define shutdownEvent shutdownHandles[0]
128 #define postmasterProcess shutdownHandles[1]
131 static pgpid_t
get_pgpid(void);
132 static char **readfile(const char *path
);
133 static int start_postmaster(void);
134 static void read_post_opts(void);
136 static bool test_postmaster_connection(bool);
137 static bool postmaster_is_alive(pid_t pid
);
139 static char postopts_file
[MAXPGPATH
];
140 static char pid_file
[MAXPGPATH
];
141 static char conf_file
[MAXPGPATH
];
142 static char backup_file
[MAXPGPATH
];
144 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
145 static void unlimit_core_size(void);
149 #if defined(WIN32) || defined(__CYGWIN__)
151 write_eventlog(int level
, const char *line
)
153 static HANDLE evtHandle
= INVALID_HANDLE_VALUE
;
155 if (evtHandle
== INVALID_HANDLE_VALUE
)
157 evtHandle
= RegisterEventSource(NULL
, "PostgreSQL");
158 if (evtHandle
== NULL
)
160 evtHandle
= INVALID_HANDLE_VALUE
;
165 ReportEvent(evtHandle
,
168 0, /* All events are Id 0 */
178 * Write errors to stderr (or by equal means when stderr is
182 write_stderr(const char *fmt
,...)
187 #if !defined(WIN32) && !defined(__CYGWIN__)
188 /* On Unix, we just fprintf to stderr */
189 vfprintf(stderr
, fmt
, ap
);
193 * On Win32, we print to stderr if running on a console, or write to
194 * eventlog if running as a service
196 if (!isatty(fileno(stderr
))) /* Running as a service */
198 char errbuf
[2048]; /* Arbitrary size? */
200 vsnprintf(errbuf
, sizeof(errbuf
), fmt
, ap
);
202 write_eventlog(EVENTLOG_ERROR_TYPE
, errbuf
);
205 /* Not running as service, write to stderr */
206 vfprintf(stderr
, fmt
, ap
);
212 * routines to check memory allocations and fail noisily.
216 pg_malloc(size_t size
)
220 result
= malloc(size
);
223 write_stderr(_("%s: out of memory\n"), progname
);
231 xstrdup(const char *s
)
238 write_stderr(_("%s: out of memory\n"), progname
);
245 * Given an already-localized string, print it to stdout unless the
246 * user has specified that no messages should be printed.
249 print_msg(const char *msg
)
264 pidf
= fopen(pid_file
, "r");
267 /* No pid file, not an error on startup */
272 write_stderr(_("%s: could not open PID file \"%s\": %s\n"),
273 progname
, pid_file
, strerror(errno
));
277 if (fscanf(pidf
, "%ld", &pid
) != 1)
279 write_stderr(_("%s: invalid data in PID file \"%s\"\n"),
284 return (pgpid_t
) pid
;
289 * get the lines from a text file - return NULL if file can't be opened
292 readfile(const char *path
)
302 if ((infile
= fopen(path
, "r")) == NULL
)
305 /* pass over the file twice - the first time to size the result */
307 while ((c
= fgetc(infile
)) != EOF
)
313 if (linelen
> maxlength
)
319 /* handle last line without a terminating newline (yuck) */
322 if (linelen
> maxlength
)
325 /* set up the result and the line buffer */
326 result
= (char **) pg_malloc((nlines
+ 1) * sizeof(char *));
327 buffer
= (char *) pg_malloc(maxlength
+ 1);
329 /* now reprocess the file and store the lines */
332 while (fgets(buffer
, maxlength
+ 1, infile
) != NULL
)
333 result
[nlines
++] = xstrdup(buffer
);
337 result
[nlines
] = NULL
;
345 * start/test/stop routines
349 start_postmaster(void)
356 * Since there might be quotes to handle here, it is easier simply to pass
357 * everything to a shell to process them.
359 if (log_file
!= NULL
)
360 snprintf(cmd
, MAXPGPATH
, SYSTEMQUOTE
"\"%s\" %s%s < \"%s\" >> \"%s\" 2>&1 &" SYSTEMQUOTE
,
361 postgres_path
, pgdata_opt
, post_opts
,
364 snprintf(cmd
, MAXPGPATH
, SYSTEMQUOTE
"\"%s\" %s%s < \"%s\" 2>&1 &" SYSTEMQUOTE
,
365 postgres_path
, pgdata_opt
, post_opts
, DEVNULL
);
371 * On win32 we don't use system(). So we don't need to use & (which would
372 * be START /B on win32). However, we still call the shell (CMD.EXE) with
373 * it to handle redirection etc.
375 PROCESS_INFORMATION pi
;
377 if (log_file
!= NULL
)
378 snprintf(cmd
, MAXPGPATH
, "CMD /C " SYSTEMQUOTE
"\"%s\" %s%s < \"%s\" >> \"%s\" 2>&1" SYSTEMQUOTE
,
379 postgres_path
, pgdata_opt
, post_opts
, DEVNULL
, log_file
);
381 snprintf(cmd
, MAXPGPATH
, "CMD /C " SYSTEMQUOTE
"\"%s\" %s%s < \"%s\" 2>&1" SYSTEMQUOTE
,
382 postgres_path
, pgdata_opt
, post_opts
, DEVNULL
);
384 if (!CreateRestrictedProcess(cmd
, &pi
, false))
385 return GetLastError();
386 CloseHandle(pi
.hProcess
);
387 CloseHandle(pi
.hThread
);
395 * Find the pgport and try a connection
396 * Note that the checkpoint parameter enables a Windows service control
397 * manager checkpoint, it's got nothing to do with database checkpoints!!
400 test_postmaster_connection(bool do_checkpoint
)
403 bool success
= false;
408 char connstr
[128]; /* Should be way more than enough! */
413 * Look in post_opts for a -p switch.
415 * This parsing code is not amazingly bright; it could for instance get
416 * fooled if ' -p' occurs within a quoted argument value. Given that few
417 * people pass complicated settings in post_opts, it's probably good
420 for (p
= post_opts
; *p
;)
422 /* advance past whitespace */
423 while (isspace((unsigned char) *p
))
426 if (strncmp(p
, "-p", 2) == 0)
429 /* advance past any whitespace/quoting */
430 while (isspace((unsigned char) *p
) || *p
== '\'' || *p
== '"')
432 /* find end of value (not including any ending quote!) */
435 !(isspace((unsigned char) *q
) || *q
== '\'' || *q
== '"'))
437 /* and save the argument value */
438 strlcpy(portstr
, p
, Min((q
- p
) + 1, sizeof(portstr
)));
439 /* keep looking, maybe there is another -p */
442 /* Advance to next whitespace */
443 while (*p
&& !isspace((unsigned char) *p
))
448 * Search config file for a 'port' option.
450 * This parsing code isn't amazingly bright either, but it should be okay
451 * for valid port settings.
457 optlines
= readfile(conf_file
);
458 if (optlines
!= NULL
)
460 for (; *optlines
!= NULL
; optlines
++)
464 while (isspace((unsigned char) *p
))
466 if (strncmp(p
, "port", 4) != 0)
469 while (isspace((unsigned char) *p
))
474 /* advance past any whitespace/quoting */
475 while (isspace((unsigned char) *p
) || *p
== '\'' || *p
== '"')
477 /* find end of value (not including any ending quote/comment!) */
480 !(isspace((unsigned char) *q
) ||
481 *q
== '\'' || *q
== '"' || *q
== '#'))
483 /* and save the argument value */
484 strlcpy(portstr
, p
, Min((q
- p
) + 1, sizeof(portstr
)));
485 /* keep looking, maybe there is another */
490 /* Check environment */
491 if (!*portstr
&& getenv("PGPORT") != NULL
)
492 strlcpy(portstr
, getenv("PGPORT"), sizeof(portstr
));
494 /* Else use compiled-in default */
496 snprintf(portstr
, sizeof(portstr
), "%d", DEF_PGPORT
);
499 * We need to set a connect timeout otherwise on Windows the SCM will
500 * probably timeout first
502 snprintf(connstr
, sizeof(connstr
),
503 "dbname=postgres port=%s connect_timeout=5", portstr
);
505 for (i
= 0; i
< wait_seconds
; i
++)
507 if ((conn
= PQconnectdb(connstr
)) != NULL
&&
508 (PQstatus(conn
) == CONNECTION_OK
||
509 PQconnectionNeedsPassword(conn
)))
523 * Increment the wait hint by 6 secs (connection timeout +
524 * sleep) We must do this to indicate to the SCM that our
525 * startup time is changing, otherwise it'll usually send a
526 * stop signal after 20 seconds, despite incrementing the
527 * checkpoint counter.
529 status
.dwWaitHint
+= 6000;
530 status
.dwCheckPoint
++;
531 SetServiceStatus(hStatus
, (LPSERVICE_STATUS
) &status
);
538 pg_usleep(1000000); /* 1 sec */
546 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
548 unlimit_core_size(void)
552 getrlimit(RLIMIT_CORE
, &lim
);
553 if (lim
.rlim_max
== 0)
555 write_stderr(_("%s: cannot set core file size limit; disallowed by hard limit\n"),
559 else if (lim
.rlim_max
== RLIM_INFINITY
|| lim
.rlim_cur
< lim
.rlim_max
)
561 lim
.rlim_cur
= lim
.rlim_max
;
562 setrlimit(RLIMIT_CORE
, &lim
);
570 if (post_opts
== NULL
)
572 post_opts
= ""; /* default */
573 if (ctl_command
== RESTART_COMMAND
)
577 optlines
= readfile(postopts_file
);
578 if (optlines
== NULL
)
580 write_stderr(_("%s: could not read file \"%s\"\n"), progname
, postopts_file
);
583 else if (optlines
[0] == NULL
|| optlines
[1] != NULL
)
585 write_stderr(_("%s: option file \"%s\" must have exactly one line\n"),
586 progname
, postopts_file
);
595 optline
= optlines
[0];
596 /* trim off line endings */
597 len
= strcspn(optline
, "\r\n");
601 * Are we at the first option, as defined by space and
604 if ((arg1
= strstr(optline
, " \"")) != NULL
)
606 *arg1
= '\0'; /* terminate so we get only program
608 post_opts
= arg1
+ 1; /* point past whitespace */
610 if (postgres_path
== NULL
)
611 postgres_path
= optline
;
624 if (ctl_command
!= RESTART_COMMAND
)
626 old_pid
= get_pgpid();
628 write_stderr(_("%s: another server might be running; "
629 "trying to start server anyway\n"),
635 /* No -D or -D already added during server start */
636 if (ctl_command
== RESTART_COMMAND
|| pgdata_opt
== NULL
)
639 if (postgres_path
== NULL
)
641 char *postmaster_path
;
644 postmaster_path
= pg_malloc(MAXPGPATH
);
646 if ((ret
= find_other_exec(argv0
, "postgres", PG_BACKEND_VERSIONSTR
,
647 postmaster_path
)) < 0)
649 char full_path
[MAXPGPATH
];
651 if (find_my_exec(argv0
, full_path
) < 0)
652 strlcpy(full_path
, progname
, sizeof(full_path
));
655 write_stderr(_("The program \"postgres\" is needed by %s "
656 "but was not found in the\n"
657 "same directory as \"%s\".\n"
658 "Check your installation.\n"),
659 progname
, full_path
);
661 write_stderr(_("The program \"postgres\" was found by \"%s\"\n"
662 "but was not the same version as %s.\n"
663 "Check your installation.\n"),
664 full_path
, progname
);
667 postgres_path
= postmaster_path
;
670 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
671 if (allow_core_files
)
675 exitcode
= start_postmaster();
678 write_stderr(_("%s: could not start server: exit code was %d\n"),
689 write_stderr(_("%s: could not start server\n"
690 "Examine the log output.\n"),
698 print_msg(_("waiting for server to start..."));
700 if (test_postmaster_connection(false) == false)
702 printf(_("could not start server\n"));
707 print_msg(_(" done\n"));
708 print_msg(_("server started\n"));
712 print_msg(_("server starting\n"));
725 if (pid
== 0) /* no pid file */
727 write_stderr(_("%s: PID file \"%s\" does not exist\n"), progname
, pid_file
);
728 write_stderr(_("Is server running?\n"));
731 else if (pid
< 0) /* standalone backend, not postmaster */
734 write_stderr(_("%s: cannot stop server; "
735 "single-user server is running (PID: %ld)\n"),
740 if (kill((pid_t
) pid
, sig
) != 0)
742 write_stderr(_("%s: could not send stop signal (PID: %ld): %s\n"), progname
, pid
,
749 print_msg(_("server shutting down\n"));
754 if ((shutdown_mode
== SMART_MODE
) && (stat(backup_file
, &statbuf
) == 0))
756 print_msg(_("WARNING: online backup mode is active\n"
757 "Shutdown will not complete until pg_stop_backup() is called.\n\n"));
760 print_msg(_("waiting for server to shut down..."));
762 for (cnt
= 0; cnt
< wait_seconds
; cnt
++)
764 if ((pid
= get_pgpid()) != 0)
767 pg_usleep(1000000); /* 1 sec */
773 if (pid
!= 0) /* pid file still exists */
775 print_msg(_(" failed\n"));
777 write_stderr(_("%s: server does not shut down\n"), progname
);
780 print_msg(_(" done\n"));
782 printf(_("server stopped\n"));
788 * restart/reload routines
800 if (pid
== 0) /* no pid file */
802 write_stderr(_("%s: PID file \"%s\" does not exist\n"),
804 write_stderr(_("Is server running?\n"));
805 write_stderr(_("starting server anyway\n"));
809 else if (pid
< 0) /* standalone backend, not postmaster */
812 if (postmaster_is_alive((pid_t
) pid
))
814 write_stderr(_("%s: cannot restart server; "
815 "single-user server is running (PID: %ld)\n"),
817 write_stderr(_("Please terminate the single-user server and try again.\n"));
822 if (postmaster_is_alive((pid_t
) pid
))
824 if (kill((pid_t
) pid
, sig
) != 0)
826 write_stderr(_("%s: could not send stop signal (PID: %ld): %s\n"), progname
, pid
,
831 if ((shutdown_mode
== SMART_MODE
) && (stat(backup_file
, &statbuf
) == 0))
833 print_msg(_("WARNING: online backup mode is active\n"
834 "Shutdown will not complete until pg_stop_backup() is called.\n\n"));
837 print_msg(_("waiting for server to shut down..."));
839 /* always wait for restart */
841 for (cnt
= 0; cnt
< wait_seconds
; cnt
++)
843 if ((pid
= get_pgpid()) != 0)
846 pg_usleep(1000000); /* 1 sec */
852 if (pid
!= 0) /* pid file still exists */
854 print_msg(_(" failed\n"));
856 write_stderr(_("%s: server does not shut down\n"), progname
);
860 print_msg(_(" done\n"));
861 printf(_("server stopped\n"));
865 write_stderr(_("%s: old server process (PID: %ld) seems to be gone\n"),
867 write_stderr(_("starting server anyway\n"));
880 if (pid
== 0) /* no pid file */
882 write_stderr(_("%s: PID file \"%s\" does not exist\n"), progname
, pid_file
);
883 write_stderr(_("Is server running?\n"));
886 else if (pid
< 0) /* standalone backend, not postmaster */
889 write_stderr(_("%s: cannot reload server; "
890 "single-user server is running (PID: %ld)\n"),
892 write_stderr(_("Please terminate the single-user server and try again.\n"));
896 if (kill((pid_t
) pid
, sig
) != 0)
898 write_stderr(_("%s: could not send reload signal (PID: %ld): %s\n"),
899 progname
, pid
, strerror(errno
));
903 print_msg(_("server signaled\n"));
911 postmaster_is_alive(pid_t pid
)
914 * Test to see if the process is still there. Note that we do not
915 * consider an EPERM failure to mean that the process is still there;
916 * EPERM must mean that the given PID belongs to some other userid, and
917 * considering the permissions on $PGDATA, that means it's not the
918 * postmaster we are after.
920 * Don't believe that our own PID or parent shell's PID is the postmaster,
921 * either. (Windows hasn't got getppid(), though.)
926 if (pid
== getppid())
929 if (kill(pid
, 0) == 0)
940 if (pid
!= 0) /* 0 means no pid file */
942 if (pid
< 0) /* standalone backend */
945 if (postmaster_is_alive((pid_t
) pid
))
947 printf(_("%s: single-user server is running (PID: %ld)\n"),
955 if (postmaster_is_alive((pid_t
) pid
))
959 printf(_("%s: server is running (PID: %ld)\n"),
962 optlines
= readfile(postopts_file
);
963 if (optlines
!= NULL
)
964 for (; *optlines
!= NULL
; optlines
++)
965 fputs(*optlines
, stdout
);
970 printf(_("%s: no server running\n"), progname
);
979 if (kill((pid_t
) pid
, sig
) != 0)
981 write_stderr(_("%s: could not send signal %d (PID: %ld): %s\n"),
982 progname
, sig
, pid
, strerror(errno
));
987 #if defined(WIN32) || defined(__CYGWIN__)
990 pgwin32_IsInstalled(SC_HANDLE hSCM
)
992 SC_HANDLE hService
= OpenService(hSCM
, register_servicename
, SERVICE_QUERY_CONFIG
);
993 bool bResult
= (hService
!= NULL
);
996 CloseServiceHandle(hService
);
1001 pgwin32_CommandLine(bool registration
)
1003 static char cmdLine
[MAXPGPATH
];
1007 char buf
[MAXPGPATH
];
1012 ret
= find_my_exec(argv0
, cmdLine
);
1015 write_stderr(_("%s: could not find own program executable\n"), progname
);
1021 ret
= find_other_exec(argv0
, "postgres", PG_BACKEND_VERSIONSTR
,
1025 write_stderr(_("%s: could not find postgres program executable\n"), progname
);
1031 /* need to convert to windows path */
1032 cygwin_conv_to_full_win32_path(cmdLine
, buf
);
1033 strcpy(cmdLine
, buf
);
1038 if (pg_strcasecmp(cmdLine
+ strlen(cmdLine
) - 4, ".exe"))
1040 /* If commandline does not end in .exe, append it */
1041 strcat(cmdLine
, ".exe");
1043 strcat(cmdLine
, " runservice -N \"");
1044 strcat(cmdLine
, register_servicename
);
1045 strcat(cmdLine
, "\"");
1050 strcat(cmdLine
, " -D \"");
1051 strcat(cmdLine
, pg_data
);
1052 strcat(cmdLine
, "\"");
1055 if (registration
&& do_wait
)
1056 strcat(cmdLine
, " -w");
1058 if (registration
&& wait_seconds
!= DEFAULT_WAIT
)
1060 sprintf(cmdLine
+ strlen(cmdLine
), " -t %d", wait_seconds
);
1064 strcat(cmdLine
, " ");
1066 strcat(cmdLine
, " -o \"");
1067 strcat(cmdLine
, post_opts
);
1069 strcat(cmdLine
, "\"");
1076 pgwin32_doRegister(void)
1079 SC_HANDLE hSCM
= OpenSCManager(NULL
, NULL
, SC_MANAGER_ALL_ACCESS
);
1083 write_stderr(_("%s: could not open service manager\n"), progname
);
1086 if (pgwin32_IsInstalled(hSCM
))
1088 CloseServiceHandle(hSCM
);
1089 write_stderr(_("%s: service \"%s\" already registered\n"), progname
, register_servicename
);
1093 if ((hService
= CreateService(hSCM
, register_servicename
, register_servicename
,
1094 SERVICE_ALL_ACCESS
, SERVICE_WIN32_OWN_PROCESS
,
1095 SERVICE_AUTO_START
, SERVICE_ERROR_NORMAL
,
1096 pgwin32_CommandLine(true),
1097 NULL
, NULL
, "RPCSS\0", register_username
, register_password
)) == NULL
)
1099 CloseServiceHandle(hSCM
);
1100 write_stderr(_("%s: could not register service \"%s\": error code %d\n"), progname
, register_servicename
, (int) GetLastError());
1103 CloseServiceHandle(hService
);
1104 CloseServiceHandle(hSCM
);
1108 pgwin32_doUnregister(void)
1111 SC_HANDLE hSCM
= OpenSCManager(NULL
, NULL
, SC_MANAGER_ALL_ACCESS
);
1115 write_stderr(_("%s: could not open service manager\n"), progname
);
1118 if (!pgwin32_IsInstalled(hSCM
))
1120 CloseServiceHandle(hSCM
);
1121 write_stderr(_("%s: service \"%s\" not registered\n"), progname
, register_servicename
);
1125 if ((hService
= OpenService(hSCM
, register_servicename
, DELETE
)) == NULL
)
1127 CloseServiceHandle(hSCM
);
1128 write_stderr(_("%s: could not open service \"%s\": error code %d\n"), progname
, register_servicename
, (int) GetLastError());
1131 if (!DeleteService(hService
))
1133 CloseServiceHandle(hService
);
1134 CloseServiceHandle(hSCM
);
1135 write_stderr(_("%s: could not unregister service \"%s\": error code %d\n"), progname
, register_servicename
, (int) GetLastError());
1138 CloseServiceHandle(hService
);
1139 CloseServiceHandle(hSCM
);
1143 pgwin32_SetServiceStatus(DWORD currentState
)
1145 status
.dwCurrentState
= currentState
;
1146 SetServiceStatus(hStatus
, (LPSERVICE_STATUS
) &status
);
1150 pgwin32_ServiceHandler(DWORD request
)
1154 case SERVICE_CONTROL_STOP
:
1155 case SERVICE_CONTROL_SHUTDOWN
:
1158 * We only need a short wait hint here as it just needs to wait
1159 * for the next checkpoint. They occur every 5 seconds during
1162 status
.dwWaitHint
= 10000;
1163 pgwin32_SetServiceStatus(SERVICE_STOP_PENDING
);
1164 SetEvent(shutdownEvent
);
1167 case SERVICE_CONTROL_PAUSE
:
1168 /* Win32 config reloading */
1169 status
.dwWaitHint
= 5000;
1170 kill(postmasterPID
, SIGHUP
);
1173 /* FIXME: These could be used to replace other signals etc */
1174 case SERVICE_CONTROL_CONTINUE
:
1175 case SERVICE_CONTROL_INTERROGATE
:
1182 pgwin32_ServiceMain(DWORD argc
, LPTSTR
*argv
)
1184 PROCESS_INFORMATION pi
;
1186 DWORD check_point_start
;
1188 /* Initialize variables */
1189 status
.dwWin32ExitCode
= S_OK
;
1190 status
.dwCheckPoint
= 0;
1191 status
.dwWaitHint
= 60000;
1192 status
.dwServiceType
= SERVICE_WIN32_OWN_PROCESS
;
1193 status
.dwControlsAccepted
= SERVICE_ACCEPT_STOP
| SERVICE_ACCEPT_SHUTDOWN
| SERVICE_ACCEPT_PAUSE_CONTINUE
;
1194 status
.dwServiceSpecificExitCode
= 0;
1195 status
.dwCurrentState
= SERVICE_START_PENDING
;
1197 memset(&pi
, 0, sizeof(pi
));
1201 /* Register the control request handler */
1202 if ((hStatus
= RegisterServiceCtrlHandler(register_servicename
, pgwin32_ServiceHandler
)) == (SERVICE_STATUS_HANDLE
) 0)
1205 if ((shutdownEvent
= CreateEvent(NULL
, true, false, NULL
)) == NULL
)
1208 /* Start the postmaster */
1209 pgwin32_SetServiceStatus(SERVICE_START_PENDING
);
1210 if (!CreateRestrictedProcess(pgwin32_CommandLine(false), &pi
, true))
1212 pgwin32_SetServiceStatus(SERVICE_STOPPED
);
1215 postmasterPID
= pi
.dwProcessId
;
1216 postmasterProcess
= pi
.hProcess
;
1217 CloseHandle(pi
.hThread
);
1221 write_eventlog(EVENTLOG_INFORMATION_TYPE
, _("Waiting for server startup...\n"));
1222 if (test_postmaster_connection(true) == false)
1224 write_eventlog(EVENTLOG_INFORMATION_TYPE
, _("Timed out waiting for server startup\n"));
1225 pgwin32_SetServiceStatus(SERVICE_STOPPED
);
1228 write_eventlog(EVENTLOG_INFORMATION_TYPE
, _("Server started and accepting connections\n"));
1232 * Save the checkpoint value as it might have been incremented in
1233 * test_postmaster_connection
1235 check_point_start
= status
.dwCheckPoint
;
1237 pgwin32_SetServiceStatus(SERVICE_RUNNING
);
1239 /* Wait for quit... */
1240 ret
= WaitForMultipleObjects(2, shutdownHandles
, FALSE
, INFINITE
);
1242 pgwin32_SetServiceStatus(SERVICE_STOP_PENDING
);
1245 case WAIT_OBJECT_0
: /* shutdown event */
1246 kill(postmasterPID
, SIGINT
);
1249 * Increment the checkpoint and try again Abort after 12
1250 * checkpoints as the postmaster has probably hung
1252 while (WaitForSingleObject(postmasterProcess
, 5000) == WAIT_TIMEOUT
&& status
.dwCheckPoint
< 12)
1253 status
.dwCheckPoint
++;
1256 case (WAIT_OBJECT_0
+ 1): /* postmaster went down */
1260 /* shouldn't get here? */
1264 CloseHandle(shutdownEvent
);
1265 CloseHandle(postmasterProcess
);
1267 pgwin32_SetServiceStatus(SERVICE_STOPPED
);
1271 pgwin32_doRunAsService(void)
1273 SERVICE_TABLE_ENTRY st
[] = {{register_servicename
, pgwin32_ServiceMain
},
1276 if (StartServiceCtrlDispatcher(st
) == 0)
1278 write_stderr(_("%s: could not start service \"%s\": error code %d\n"), progname
, register_servicename
, (int) GetLastError());
1285 * Mingw headers are incomplete, and so are the libraries. So we have to load
1286 * a whole lot of API functions dynamically. Since we have to do this anyway,
1287 * also load the couple of functions that *do* exist in minwg headers but not
1288 * on NT4. That way, we don't break on NT4.
1290 typedef BOOL (WINAPI
* __CreateRestrictedToken
) (HANDLE
, DWORD
, DWORD
, PSID_AND_ATTRIBUTES
, DWORD
, PLUID_AND_ATTRIBUTES
, DWORD
, PSID_AND_ATTRIBUTES
, PHANDLE
);
1291 typedef BOOL (WINAPI
* __IsProcessInJob
) (HANDLE
, HANDLE
, PBOOL
);
1292 typedef HANDLE (WINAPI
* __CreateJobObject
) (LPSECURITY_ATTRIBUTES
, LPCTSTR
);
1293 typedef BOOL (WINAPI
* __SetInformationJobObject
) (HANDLE
, JOBOBJECTINFOCLASS
, LPVOID
, DWORD
);
1294 typedef BOOL (WINAPI
* __AssignProcessToJobObject
) (HANDLE
, HANDLE
);
1295 typedef BOOL (WINAPI
* __QueryInformationJobObject
) (HANDLE
, JOBOBJECTINFOCLASS
, LPVOID
, DWORD
, LPDWORD
);
1297 /* Windows API define missing from MingW headers */
1298 #define DISABLE_MAX_PRIVILEGE 0x1
1301 * Create a restricted token, a job object sandbox, and execute the specified
1304 * Returns 0 on success, non-zero on failure, same as CreateProcess().
1306 * On NT4, or any other system not containing the required functions, will
1307 * launch the process under the current token without doing any modifications.
1309 * NOTE! Job object will only work when running as a service, because it's
1310 * automatically destroyed when pg_ctl exits.
1313 CreateRestrictedProcess(char *cmd
, PROCESS_INFORMATION
*processInfo
, bool as_service
)
1319 HANDLE restrictedToken
;
1320 SID_IDENTIFIER_AUTHORITY NtAuthority
= {SECURITY_NT_AUTHORITY
};
1321 SID_AND_ATTRIBUTES dropSids
[2];
1323 /* Functions loaded dynamically */
1324 __CreateRestrictedToken _CreateRestrictedToken
= NULL
;
1325 __IsProcessInJob _IsProcessInJob
= NULL
;
1326 __CreateJobObject _CreateJobObject
= NULL
;
1327 __SetInformationJobObject _SetInformationJobObject
= NULL
;
1328 __AssignProcessToJobObject _AssignProcessToJobObject
= NULL
;
1329 __QueryInformationJobObject _QueryInformationJobObject
= NULL
;
1330 HANDLE Kernel32Handle
;
1331 HANDLE Advapi32Handle
;
1333 ZeroMemory(&si
, sizeof(si
));
1336 Advapi32Handle
= LoadLibrary("ADVAPI32.DLL");
1337 if (Advapi32Handle
!= NULL
)
1339 _CreateRestrictedToken
= (__CreateRestrictedToken
) GetProcAddress(Advapi32Handle
, "CreateRestrictedToken");
1342 if (_CreateRestrictedToken
== NULL
)
1345 * NT4 doesn't have CreateRestrictedToken, so just call ordinary
1348 write_stderr("WARNING: cannot create restricted tokens on this platform\n");
1349 if (Advapi32Handle
!= NULL
)
1350 FreeLibrary(Advapi32Handle
);
1351 return CreateProcess(NULL
, cmd
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, processInfo
);
1354 /* Open the current token to use as a base for the restricted one */
1355 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS
, &origToken
))
1357 write_stderr("Failed to open process token: %lu\n", GetLastError());
1361 /* Allocate list of SIDs to remove */
1362 ZeroMemory(&dropSids
, sizeof(dropSids
));
1363 if (!AllocateAndInitializeSid(&NtAuthority
, 2,
1364 SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_ADMINS
, 0, 0, 0, 0, 0,
1365 0, &dropSids
[0].Sid
) ||
1366 !AllocateAndInitializeSid(&NtAuthority
, 2,
1367 SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_POWER_USERS
, 0, 0, 0, 0, 0,
1368 0, &dropSids
[1].Sid
))
1370 write_stderr("Failed to allocate SIDs: %lu\n", GetLastError());
1374 b
= _CreateRestrictedToken(origToken
,
1375 DISABLE_MAX_PRIVILEGE
,
1376 sizeof(dropSids
) / sizeof(dropSids
[0]),
1382 FreeSid(dropSids
[1].Sid
);
1383 FreeSid(dropSids
[0].Sid
);
1384 CloseHandle(origToken
);
1385 FreeLibrary(Advapi32Handle
);
1389 write_stderr("Failed to create restricted token: %lu\n", GetLastError());
1393 r
= CreateProcessAsUser(restrictedToken
, NULL
, cmd
, NULL
, NULL
, TRUE
, CREATE_SUSPENDED
, NULL
, NULL
, &si
, processInfo
);
1395 Kernel32Handle
= LoadLibrary("KERNEL32.DLL");
1396 if (Kernel32Handle
!= NULL
)
1398 _IsProcessInJob
= (__IsProcessInJob
) GetProcAddress(Kernel32Handle
, "IsProcessInJob");
1399 _CreateJobObject
= (__CreateJobObject
) GetProcAddress(Kernel32Handle
, "CreateJobObjectA");
1400 _SetInformationJobObject
= (__SetInformationJobObject
) GetProcAddress(Kernel32Handle
, "SetInformationJobObject");
1401 _AssignProcessToJobObject
= (__AssignProcessToJobObject
) GetProcAddress(Kernel32Handle
, "AssignProcessToJobObject");
1402 _QueryInformationJobObject
= (__QueryInformationJobObject
) GetProcAddress(Kernel32Handle
, "QueryInformationJobObject");
1405 /* Verify that we found all functions */
1406 if (_IsProcessInJob
== NULL
|| _CreateJobObject
== NULL
|| _SetInformationJobObject
== NULL
|| _AssignProcessToJobObject
== NULL
|| _QueryInformationJobObject
== NULL
)
1409 * IsProcessInJob() is not available on < WinXP, so there is no need
1410 * to log the error every time in that case
1414 osv
.dwOSVersionInfoSize
= sizeof(osv
);
1415 if (!GetVersionEx(&osv
) || /* could not get version */
1416 (osv
.dwMajorVersion
== 5 && osv
.dwMinorVersion
> 0) || /* 5.1=xp, 5.2=2003, etc */
1417 osv
.dwMajorVersion
> 5) /* anything newer should have the API */
1420 * Log error if we can't get version, or if we're on WinXP/2003 or
1423 write_stderr("WARNING: could not locate all job object functions in system API\n");
1429 if (_IsProcessInJob(processInfo
->hProcess
, NULL
, &inJob
))
1434 * Job objects are working, and the new process isn't in one,
1435 * so we can create one safely. If any problems show up when
1436 * setting it, we're going to ignore them.
1441 sprintf(jobname
, "PostgreSQL_%lu", processInfo
->dwProcessId
);
1443 job
= _CreateJobObject(NULL
, jobname
);
1446 JOBOBJECT_BASIC_LIMIT_INFORMATION basicLimit
;
1447 JOBOBJECT_BASIC_UI_RESTRICTIONS uiRestrictions
;
1448 JOBOBJECT_SECURITY_LIMIT_INFORMATION securityLimit
;
1451 ZeroMemory(&basicLimit
, sizeof(basicLimit
));
1452 ZeroMemory(&uiRestrictions
, sizeof(uiRestrictions
));
1453 ZeroMemory(&securityLimit
, sizeof(securityLimit
));
1455 basicLimit
.LimitFlags
= JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION
| JOB_OBJECT_LIMIT_PRIORITY_CLASS
;
1456 basicLimit
.PriorityClass
= NORMAL_PRIORITY_CLASS
;
1457 _SetInformationJobObject(job
, JobObjectBasicLimitInformation
, &basicLimit
, sizeof(basicLimit
));
1459 uiRestrictions
.UIRestrictionsClass
= JOB_OBJECT_UILIMIT_DESKTOP
| JOB_OBJECT_UILIMIT_DISPLAYSETTINGS
|
1460 JOB_OBJECT_UILIMIT_EXITWINDOWS
| JOB_OBJECT_UILIMIT_READCLIPBOARD
|
1461 JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS
| JOB_OBJECT_UILIMIT_WRITECLIPBOARD
;
1465 osv
.dwOSVersionInfoSize
= sizeof(osv
);
1466 if (!GetVersionEx(&osv
) ||
1467 osv
.dwMajorVersion
< 6 ||
1468 (osv
.dwMajorVersion
== 6 && osv
.dwMinorVersion
== 0))
1471 * On Windows 7 (and presumably later),
1472 * JOB_OBJECT_UILIMIT_HANDLES prevents us from
1473 * starting as a service. So we only enable it on
1474 * Vista and earlier (version <= 6.0)
1476 uiRestrictions
.UIRestrictionsClass
|= JOB_OBJECT_UILIMIT_HANDLES
;
1479 _SetInformationJobObject(job
, JobObjectBasicUIRestrictions
, &uiRestrictions
, sizeof(uiRestrictions
));
1481 securityLimit
.SecurityLimitFlags
= JOB_OBJECT_SECURITY_NO_ADMIN
| JOB_OBJECT_SECURITY_ONLY_TOKEN
;
1482 securityLimit
.JobToken
= restrictedToken
;
1483 _SetInformationJobObject(job
, JobObjectSecurityLimitInformation
, &securityLimit
, sizeof(securityLimit
));
1485 _AssignProcessToJobObject(job
, processInfo
->hProcess
);
1492 AddUserToDacl(processInfo
->hProcess
);
1495 CloseHandle(restrictedToken
);
1497 ResumeThread(processInfo
->hThread
);
1499 FreeLibrary(Kernel32Handle
);
1502 * We intentionally don't close the job object handle, because we want the
1503 * object to live on until pg_ctl shuts down.
1512 write_stderr(_("Try \"%s --help\" for more information.\n"), progname
);
1520 printf(_("%s is a utility to start, stop, restart, reload configuration files,\n"
1521 "report the status of a PostgreSQL server, or signal a PostgreSQL process.\n\n"), progname
);
1522 printf(_("Usage:\n"));
1523 printf(_(" %s start [-w] [-t SECS] [-D DATADIR] [-s] [-l FILENAME] [-o \"OPTIONS\"]\n"), progname
);
1524 printf(_(" %s stop [-W] [-t SECS] [-D DATADIR] [-s] [-m SHUTDOWN-MODE]\n"), progname
);
1525 printf(_(" %s restart [-w] [-t SECS] [-D DATADIR] [-s] [-m SHUTDOWN-MODE]\n"
1526 " [-o \"OPTIONS\"]\n"), progname
);
1527 printf(_(" %s reload [-D DATADIR] [-s]\n"), progname
);
1528 printf(_(" %s status [-D DATADIR]\n"), progname
);
1529 printf(_(" %s kill SIGNALNAME PID\n"), progname
);
1530 #if defined(WIN32) || defined(__CYGWIN__)
1531 printf(_(" %s register [-N SERVICENAME] [-U USERNAME] [-P PASSWORD] [-D DATADIR]\n"
1532 " [-w] [-t SECS] [-o \"OPTIONS\"]\n"), progname
);
1533 printf(_(" %s unregister [-N SERVICENAME]\n"), progname
);
1536 printf(_("\nCommon options:\n"));
1537 printf(_(" -D, --pgdata DATADIR location of the database storage area\n"));
1538 printf(_(" -s, --silent only print errors, no informational messages\n"));
1539 printf(_(" -t SECS seconds to wait when using -w option\n"));
1540 printf(_(" -w wait until operation completes\n"));
1541 printf(_(" -W do not wait until operation completes\n"));
1542 printf(_(" --help show this help, then exit\n"));
1543 printf(_(" --version output version information, then exit\n"));
1544 printf(_("(The default is to wait for shutdown, but not for start or restart.)\n\n"));
1545 printf(_("If the -D option is omitted, the environment variable PGDATA is used.\n"));
1547 printf(_("\nOptions for start or restart:\n"));
1548 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
1549 printf(_(" -c, --core-files allow postgres to produce core files\n"));
1551 printf(_(" -c, --core-files not applicable on this platform\n"));
1553 printf(_(" -l, --log FILENAME write (or append) server log to FILENAME\n"));
1554 printf(_(" -o OPTIONS command line options to pass to postgres\n"
1555 " (PostgreSQL server executable)\n"));
1556 printf(_(" -p PATH-TO-POSTGRES normally not necessary\n"));
1557 printf(_("\nOptions for stop or restart:\n"));
1558 printf(_(" -m SHUTDOWN-MODE can be \"smart\", \"fast\", or \"immediate\"\n"));
1560 printf(_("\nShutdown modes are:\n"));
1561 printf(_(" smart quit after all clients have disconnected\n"));
1562 printf(_(" fast quit directly, with proper shutdown\n"));
1563 printf(_(" immediate quit without complete shutdown; will lead to recovery on restart\n"));
1565 printf(_("\nAllowed signal names for kill:\n"));
1566 printf(" HUP INT QUIT ABRT TERM USR1 USR2\n");
1568 #if defined(WIN32) || defined(__CYGWIN__)
1569 printf(_("\nOptions for register and unregister:\n"));
1570 printf(_(" -N SERVICENAME service name with which to register PostgreSQL server\n"));
1571 printf(_(" -P PASSWORD password of account to register PostgreSQL server\n"));
1572 printf(_(" -U USERNAME user name of account to register PostgreSQL server\n"));
1575 printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
1581 set_mode(char *modeopt
)
1583 if (strcmp(modeopt
, "s") == 0 || strcmp(modeopt
, "smart") == 0)
1585 shutdown_mode
= SMART_MODE
;
1588 else if (strcmp(modeopt
, "f") == 0 || strcmp(modeopt
, "fast") == 0)
1590 shutdown_mode
= FAST_MODE
;
1593 else if (strcmp(modeopt
, "i") == 0 || strcmp(modeopt
, "immediate") == 0)
1595 shutdown_mode
= IMMEDIATE_MODE
;
1600 write_stderr(_("%s: unrecognized shutdown mode \"%s\"\n"), progname
, modeopt
);
1609 set_sig(char *signame
)
1611 if (!strcmp(signame
, "HUP"))
1613 else if (!strcmp(signame
, "INT"))
1615 else if (!strcmp(signame
, "QUIT"))
1617 else if (!strcmp(signame
, "ABRT"))
1621 * probably should NOT provide SIGKILL
1623 * else if (!strcmp(signame,"KILL")) sig = SIGKILL;
1625 else if (!strcmp(signame
, "TERM"))
1627 else if (!strcmp(signame
, "USR1"))
1629 else if (!strcmp(signame
, "USR2"))
1633 write_stderr(_("%s: unrecognized signal name \"%s\"\n"), progname
, signame
);
1643 main(int argc
, char **argv
)
1645 static struct option long_options
[] = {
1646 {"help", no_argument
, NULL
, '?'},
1647 {"version", no_argument
, NULL
, 'V'},
1648 {"log", required_argument
, NULL
, 'l'},
1649 {"mode", required_argument
, NULL
, 'm'},
1650 {"pgdata", required_argument
, NULL
, 'D'},
1651 {"silent", no_argument
, NULL
, 's'},
1652 {"timeout", required_argument
, NULL
, 't'},
1653 {"core-files", no_argument
, NULL
, 'c'},
1659 pgpid_t killproc
= 0;
1661 #if defined(WIN32) || defined(__CYGWIN__)
1662 setvbuf(stderr
, NULL
, _IONBF
, 0);
1665 progname
= get_progname(argv
[0]);
1666 set_pglocale_pgservice(argv
[0], PG_TEXTDOMAIN("pg_ctl"));
1669 * save argv[0] so do_start() can look for the postmaster if necessary. we
1670 * don't look for postmaster here because in many cases we won't need it.
1676 /* support --help and --version even if invoked as root */
1679 if (strcmp(argv
[1], "-h") == 0 || strcmp(argv
[1], "--help") == 0 ||
1680 strcmp(argv
[1], "-?") == 0)
1685 else if (strcmp(argv
[1], "-V") == 0 || strcmp(argv
[1], "--version") == 0)
1687 puts("pg_ctl (PostgreSQL) " PG_VERSION
);
1693 * Disallow running as root, to forestall any possible security holes.
1698 write_stderr(_("%s: cannot be run as root\n"
1699 "Please log in (using, e.g., \"su\") as the "
1700 "(unprivileged) user that will\n"
1701 "own the server process.\n"),
1708 * 'Action' can be before or after args so loop over both. Some
1709 * getopt_long() implementations will reorder argv[] to place all flags
1710 * first (GNU?), but we don't rely on it. Our /port version doesn't do
1715 /* process command-line options */
1716 while (optind
< argc
)
1718 while ((c
= getopt_long(argc
, argv
, "cD:l:m:N:o:p:P:st:U:wW", long_options
, &option_index
)) != -1)
1725 char *env_var
= pg_malloc(strlen(optarg
) + 8);
1727 pgdata_D
= xstrdup(optarg
);
1728 canonicalize_path(pgdata_D
);
1729 snprintf(env_var
, strlen(optarg
) + 8, "PGDATA=%s",
1734 * We could pass PGDATA just in an environment
1735 * variable but we do -D too for clearer postmaster
1738 pgdata_opt
= pg_malloc(strlen(pgdata_D
) + 7);
1739 snprintf(pgdata_opt
, strlen(pgdata_D
) + 7,
1745 log_file
= xstrdup(optarg
);
1751 register_servicename
= xstrdup(optarg
);
1754 post_opts
= xstrdup(optarg
);
1757 postgres_path
= xstrdup(optarg
);
1760 register_password
= xstrdup(optarg
);
1766 wait_seconds
= atoi(optarg
);
1769 if (strchr(optarg
, '\\'))
1770 register_username
= xstrdup(optarg
);
1772 /* Prepend .\ for local accounts */
1774 register_username
= malloc(strlen(optarg
) + 3);
1775 if (!register_username
)
1777 write_stderr(_("%s: out of memory\n"), progname
);
1780 strcpy(register_username
, ".\\");
1781 strcat(register_username
, optarg
);
1793 allow_core_files
= true;
1796 /* getopt_long already issued a suitable error message */
1802 /* Process an action */
1805 if (ctl_command
!= NO_COMMAND
)
1807 write_stderr(_("%s: too many command-line arguments (first is \"%s\")\n"), progname
, argv
[optind
]);
1812 if (strcmp(argv
[optind
], "start") == 0)
1813 ctl_command
= START_COMMAND
;
1814 else if (strcmp(argv
[optind
], "stop") == 0)
1815 ctl_command
= STOP_COMMAND
;
1816 else if (strcmp(argv
[optind
], "restart") == 0)
1817 ctl_command
= RESTART_COMMAND
;
1818 else if (strcmp(argv
[optind
], "reload") == 0)
1819 ctl_command
= RELOAD_COMMAND
;
1820 else if (strcmp(argv
[optind
], "status") == 0)
1821 ctl_command
= STATUS_COMMAND
;
1822 else if (strcmp(argv
[optind
], "kill") == 0)
1824 if (argc
- optind
< 3)
1826 write_stderr(_("%s: missing arguments for kill mode\n"), progname
);
1830 ctl_command
= KILL_COMMAND
;
1831 set_sig(argv
[++optind
]);
1832 killproc
= atol(argv
[++optind
]);
1834 #if defined(WIN32) || defined(__CYGWIN__)
1835 else if (strcmp(argv
[optind
], "register") == 0)
1836 ctl_command
= REGISTER_COMMAND
;
1837 else if (strcmp(argv
[optind
], "unregister") == 0)
1838 ctl_command
= UNREGISTER_COMMAND
;
1839 else if (strcmp(argv
[optind
], "runservice") == 0)
1840 ctl_command
= RUN_AS_SERVICE_COMMAND
;
1844 write_stderr(_("%s: unrecognized operation mode \"%s\"\n"), progname
, argv
[optind
]);
1852 if (ctl_command
== NO_COMMAND
)
1854 write_stderr(_("%s: no operation specified\n"), progname
);
1859 /* Note we put any -D switch into the env var above */
1860 pg_data
= getenv("PGDATA");
1863 pg_data
= xstrdup(pg_data
);
1864 canonicalize_path(pg_data
);
1867 if (pg_data
== NULL
&&
1868 ctl_command
!= KILL_COMMAND
&& ctl_command
!= UNREGISTER_COMMAND
)
1870 write_stderr(_("%s: no database directory specified "
1871 "and environment variable PGDATA unset\n"),
1879 switch (ctl_command
)
1881 case RESTART_COMMAND
:
1893 if (ctl_command
== RELOAD_COMMAND
)
1901 snprintf(postopts_file
, MAXPGPATH
, "%s/postmaster.opts", pg_data
);
1902 snprintf(pid_file
, MAXPGPATH
, "%s/postmaster.pid", pg_data
);
1903 snprintf(conf_file
, MAXPGPATH
, "%s/postgresql.conf", pg_data
);
1904 snprintf(backup_file
, MAXPGPATH
, "%s/backup_label", pg_data
);
1907 switch (ctl_command
)
1909 case STATUS_COMMAND
:
1918 case RESTART_COMMAND
:
1921 case RELOAD_COMMAND
:
1927 #if defined(WIN32) || defined(__CYGWIN__)
1928 case REGISTER_COMMAND
:
1929 pgwin32_doRegister();
1931 case UNREGISTER_COMMAND
:
1932 pgwin32_doUnregister();
1934 case RUN_AS_SERVICE_COMMAND
:
1935 pgwin32_doRunAsService();