Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * pg_ctl --- start/stops/restarts the PostgreSQL server
4 : *
5 : * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
6 : *
7 : * src/bin/pg_ctl/pg_ctl.c
8 : *
9 : *-------------------------------------------------------------------------
10 : */
11 :
12 : #include "postgres_fe.h"
13 :
14 : #include <fcntl.h>
15 : #include <signal.h>
16 : #include <time.h>
17 : #include <sys/resource.h>
18 : #include <sys/stat.h>
19 : #include <sys/time.h>
20 : #include <sys/wait.h>
21 : #include <unistd.h>
22 :
23 :
24 : #include "catalog/pg_control.h"
25 : #include "common/controldata_utils.h"
26 : #include "common/file_perm.h"
27 : #include "common/logging.h"
28 : #include "common/string.h"
29 : #include "datatype/timestamp.h"
30 : #include "getopt_long.h"
31 : #include "utils/pidfile.h"
32 :
33 : #ifdef WIN32 /* on Unix, we don't need libpq */
34 : #include "pqexpbuffer.h"
35 : #endif
36 :
37 :
38 : typedef enum
39 : {
40 : SMART_MODE,
41 : FAST_MODE,
42 : IMMEDIATE_MODE,
43 : } ShutdownMode;
44 :
45 : typedef enum
46 : {
47 : POSTMASTER_READY,
48 : POSTMASTER_STILL_STARTING,
49 : POSTMASTER_SHUTDOWN_IN_RECOVERY,
50 : POSTMASTER_FAILED,
51 : } WaitPMResult;
52 :
53 : typedef enum
54 : {
55 : NO_COMMAND = 0,
56 : INIT_COMMAND,
57 : START_COMMAND,
58 : STOP_COMMAND,
59 : RESTART_COMMAND,
60 : RELOAD_COMMAND,
61 : STATUS_COMMAND,
62 : PROMOTE_COMMAND,
63 : LOGROTATE_COMMAND,
64 : KILL_COMMAND,
65 : REGISTER_COMMAND,
66 : UNREGISTER_COMMAND,
67 : RUN_AS_SERVICE_COMMAND,
68 : } CtlCommand;
69 :
70 : #define DEFAULT_WAIT 60
71 :
72 : #define WAITS_PER_SEC 10
73 : StaticAssertDecl(USECS_PER_SEC % WAITS_PER_SEC == 0,
74 : "WAITS_PER_SEC must divide USECS_PER_SEC evenly");
75 :
76 : static bool do_wait = true;
77 : static int wait_seconds = DEFAULT_WAIT;
78 : static bool wait_seconds_arg = false;
79 : static bool silent_mode = false;
80 : static ShutdownMode shutdown_mode = FAST_MODE;
81 : static int sig = SIGINT; /* default */
82 : static CtlCommand ctl_command = NO_COMMAND;
83 : static char *pg_data = NULL;
84 : static char *pg_config = NULL;
85 : static char *pgdata_opt = NULL;
86 : static char *post_opts = NULL;
87 : static const char *progname;
88 : static char *log_file = NULL;
89 : static char *exec_path = NULL;
90 : static char *event_source = NULL;
91 : static char *register_servicename = "PostgreSQL"; /* FIXME: + version ID? */
92 : static char *register_username = NULL;
93 : static char *register_password = NULL;
94 : static char *argv0 = NULL;
95 : static bool allow_core_files = false;
96 : static time_t start_time;
97 :
98 : static char postopts_file[MAXPGPATH];
99 : static char version_file[MAXPGPATH];
100 : static char pid_file[MAXPGPATH];
101 : static char promote_file[MAXPGPATH];
102 : static char logrotate_file[MAXPGPATH];
103 :
104 : static volatile pid_t postmasterPID = -1;
105 :
106 : #ifdef WIN32
107 : static DWORD pgctl_start_type = SERVICE_AUTO_START;
108 : static SERVICE_STATUS status;
109 : static SERVICE_STATUS_HANDLE hStatus = (SERVICE_STATUS_HANDLE) 0;
110 : static HANDLE shutdownHandles[2];
111 :
112 : #define shutdownEvent shutdownHandles[0]
113 : #define postmasterProcess shutdownHandles[1]
114 : #endif
115 :
116 :
117 : static void write_stderr(const char *fmt,...) pg_attribute_printf(1, 2);
118 : static void do_advice(void);
119 : static void do_help(void);
120 : static void set_mode(char *modeopt);
121 : static void set_sig(char *signame);
122 : static void do_init(void);
123 : static void do_start(void);
124 : static void do_stop(void);
125 : static void do_restart(void);
126 : static void do_reload(void);
127 : static void do_status(void);
128 : static void do_promote(void);
129 : static void do_logrotate(void);
130 : static void do_kill(pid_t pid);
131 : static void print_msg(const char *msg);
132 : static void adjust_data_dir(void);
133 :
134 : #ifdef WIN32
135 : #include <versionhelpers.h>
136 : static bool pgwin32_IsInstalled(SC_HANDLE);
137 : static char *pgwin32_CommandLine(bool);
138 : static void pgwin32_doRegister(void);
139 : static void pgwin32_doUnregister(void);
140 : static void pgwin32_SetServiceStatus(DWORD);
141 : static void WINAPI pgwin32_ServiceHandler(DWORD);
142 : static void WINAPI pgwin32_ServiceMain(DWORD, LPTSTR *);
143 : static void pgwin32_doRunAsService(void);
144 : static int CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo, bool as_service);
145 : static PTOKEN_PRIVILEGES GetPrivilegesToDelete(HANDLE hToken);
146 : #endif
147 :
148 : static pid_t get_pgpid(bool is_status_request);
149 : static char **readfile(const char *path, int *numlines);
150 : static void free_readfile(char **optlines);
151 : static pid_t start_postmaster(void);
152 : static void read_post_opts(void);
153 :
154 : static WaitPMResult wait_for_postmaster_start(pid_t pm_pid, bool do_checkpoint);
155 : static bool wait_for_postmaster_stop(void);
156 : static bool wait_for_postmaster_promote(void);
157 : static bool postmaster_is_alive(pid_t pid);
158 :
159 : #if defined(HAVE_GETRLIMIT)
160 : static void unlimit_core_size(void);
161 : #endif
162 :
163 : static DBState get_control_dbstate(void);
164 :
165 :
166 : #ifdef WIN32
167 : static void
168 : write_eventlog(int level, const char *line)
169 : {
170 : static HANDLE evtHandle = INVALID_HANDLE_VALUE;
171 :
172 : if (silent_mode && level == EVENTLOG_INFORMATION_TYPE)
173 : return;
174 :
175 : if (evtHandle == INVALID_HANDLE_VALUE)
176 : {
177 : evtHandle = RegisterEventSource(NULL,
178 : event_source ? event_source : DEFAULT_EVENT_SOURCE);
179 : if (evtHandle == NULL)
180 : {
181 : evtHandle = INVALID_HANDLE_VALUE;
182 : return;
183 : }
184 : }
185 :
186 : ReportEvent(evtHandle,
187 : level,
188 : 0,
189 : 0, /* All events are Id 0 */
190 : NULL,
191 : 1,
192 : 0,
193 : &line,
194 : NULL);
195 : }
196 : #endif
197 :
198 : /*
199 : * Write errors to stderr (or by equal means when stderr is
200 : * not available).
201 : */
202 : static void
203 78 : write_stderr(const char *fmt,...)
204 : {
205 : va_list ap;
206 :
207 78 : va_start(ap, fmt);
208 : #ifndef WIN32
209 : /* On Unix, we just fprintf to stderr */
210 78 : vfprintf(stderr, fmt, ap);
211 : #else
212 :
213 : /*
214 : * On Win32, we print to stderr if running on a console, or write to
215 : * eventlog if running as a service
216 : */
217 : if (pgwin32_is_service()) /* Running as a service */
218 : {
219 : char errbuf[2048]; /* Arbitrary size? */
220 :
221 : vsnprintf(errbuf, sizeof(errbuf), fmt, ap);
222 :
223 : write_eventlog(EVENTLOG_ERROR_TYPE, errbuf);
224 : }
225 : else
226 : /* Not running as service, write to stderr */
227 : vfprintf(stderr, fmt, ap);
228 : #endif
229 78 : va_end(ap);
230 78 : }
231 :
232 : /*
233 : * Given an already-localized string, print it to stdout unless the
234 : * user has specified that no messages should be printed.
235 : */
236 : static void
237 13982 : print_msg(const char *msg)
238 : {
239 13982 : if (!silent_mode)
240 : {
241 12988 : fputs(msg, stdout);
242 12988 : fflush(stdout);
243 : }
244 13982 : }
245 :
246 : static pid_t
247 14160 : get_pgpid(bool is_status_request)
248 : {
249 : FILE *pidf;
250 : int pid;
251 : struct stat statbuf;
252 :
253 14160 : if (stat(pg_data, &statbuf) != 0)
254 : {
255 6 : if (errno == ENOENT)
256 6 : write_stderr(_("%s: directory \"%s\" does not exist\n"), progname,
257 : pg_data);
258 : else
259 0 : write_stderr(_("%s: could not access directory \"%s\": %m\n"), progname,
260 : pg_data);
261 :
262 : /*
263 : * The Linux Standard Base Core Specification 3.1 says this should
264 : * return '4, program or service status is unknown'
265 : * https://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
266 : */
267 6 : exit(is_status_request ? 4 : 1);
268 : }
269 :
270 14154 : if (stat(version_file, &statbuf) != 0 && errno == ENOENT)
271 : {
272 0 : write_stderr(_("%s: directory \"%s\" is not a database cluster directory\n"),
273 : progname, pg_data);
274 0 : exit(is_status_request ? 4 : 1);
275 : }
276 :
277 14154 : pidf = fopen(pid_file, "r");
278 14154 : if (pidf == NULL)
279 : {
280 : /* No pid file, not an error on startup */
281 3112 : if (errno == ENOENT)
282 3112 : return 0;
283 : else
284 : {
285 0 : write_stderr(_("%s: could not open PID file \"%s\": %m\n"),
286 : progname, pid_file);
287 0 : exit(1);
288 : }
289 : }
290 11042 : if (fscanf(pidf, "%d", &pid) != 1)
291 : {
292 : /* Is the file empty? */
293 0 : if (ftell(pidf) == 0 && feof(pidf))
294 0 : write_stderr(_("%s: the PID file \"%s\" is empty\n"),
295 : progname, pid_file);
296 : else
297 0 : write_stderr(_("%s: invalid data in PID file \"%s\"\n"),
298 : progname, pid_file);
299 0 : exit(1);
300 : }
301 11042 : fclose(pidf);
302 11042 : return (pid_t) pid;
303 : }
304 :
305 :
306 : /*
307 : * get the lines from a text file - return NULL if file can't be opened
308 : *
309 : * Trailing newlines are deleted from the lines (this is a change from pre-v10)
310 : *
311 : * *numlines is set to the number of line pointers returned; there is
312 : * also an additional NULL pointer after the last real line.
313 : */
314 : static char **
315 6934 : readfile(const char *path, int *numlines)
316 : {
317 : int fd;
318 : int nlines;
319 : char **result;
320 : char *buffer;
321 : char *linebegin;
322 : int i;
323 : int n;
324 : int len;
325 : struct stat statbuf;
326 :
327 6934 : *numlines = 0; /* in case of failure or empty file */
328 :
329 : /*
330 : * Slurp the file into memory.
331 : *
332 : * The file can change concurrently, so we read the whole file into memory
333 : * with a single read() call. That's not guaranteed to get an atomic
334 : * snapshot, but in practice, for a small file, it's close enough for the
335 : * current use.
336 : */
337 6934 : fd = open(path, O_RDONLY | PG_BINARY, 0);
338 6934 : if (fd < 0)
339 1748 : return NULL;
340 5186 : if (fstat(fd, &statbuf) < 0)
341 : {
342 0 : close(fd);
343 0 : return NULL;
344 : }
345 5186 : if (statbuf.st_size == 0)
346 : {
347 : /* empty file */
348 0 : close(fd);
349 0 : result = (char **) pg_malloc(sizeof(char *));
350 0 : *result = NULL;
351 0 : return result;
352 : }
353 5186 : buffer = pg_malloc(statbuf.st_size + 1);
354 :
355 5186 : len = read(fd, buffer, statbuf.st_size + 1);
356 5186 : close(fd);
357 5186 : if (len != statbuf.st_size)
358 : {
359 : /* oops, the file size changed between fstat and read */
360 0 : free(buffer);
361 0 : return NULL;
362 : }
363 :
364 : /*
365 : * Count newlines. We expect there to be a newline after each full line,
366 : * including one at the end of file. If there isn't a newline at the end,
367 : * any characters after the last newline will be ignored.
368 : */
369 5186 : nlines = 0;
370 870912 : for (i = 0; i < len; i++)
371 : {
372 865726 : if (buffer[i] == '\n')
373 39628 : nlines++;
374 : }
375 :
376 : /* set up the result buffer */
377 5186 : result = (char **) pg_malloc((nlines + 1) * sizeof(char *));
378 5186 : *numlines = nlines;
379 :
380 : /* now split the buffer into lines */
381 5186 : linebegin = buffer;
382 5186 : n = 0;
383 870912 : for (i = 0; i < len; i++)
384 : {
385 865726 : if (buffer[i] == '\n')
386 : {
387 39628 : int slen = &buffer[i] - linebegin;
388 39628 : char *linebuf = pg_malloc(slen + 1);
389 :
390 39628 : memcpy(linebuf, linebegin, slen);
391 : /* we already dropped the \n, but get rid of any \r too */
392 39628 : if (slen > 0 && linebuf[slen - 1] == '\r')
393 0 : slen--;
394 39628 : linebuf[slen] = '\0';
395 39628 : result[n++] = linebuf;
396 39628 : linebegin = &buffer[i + 1];
397 : }
398 : }
399 5186 : result[n] = NULL;
400 :
401 5186 : free(buffer);
402 :
403 5186 : return result;
404 : }
405 :
406 :
407 : /*
408 : * Free memory allocated for optlines through readfile()
409 : */
410 : static void
411 6934 : free_readfile(char **optlines)
412 : {
413 6934 : char *curr_line = NULL;
414 6934 : int i = 0;
415 :
416 6934 : if (!optlines)
417 1748 : return;
418 :
419 44814 : while ((curr_line = optlines[i++]))
420 39628 : free(curr_line);
421 :
422 5186 : free(optlines);
423 : }
424 :
425 : /*
426 : * start/test/stop routines
427 : */
428 :
429 : /*
430 : * Start the postmaster and return its PID.
431 : *
432 : * Currently, on Windows what we return is the PID of the shell process
433 : * that launched the postmaster (and, we trust, is waiting for it to exit).
434 : * So the PID is usable for "is the postmaster still running" checks,
435 : * but cannot be compared directly to postmaster.pid.
436 : *
437 : * On Windows, we also save aside a handle to the shell process in
438 : * "postmasterProcess", which the caller should close when done with it.
439 : */
440 : static pid_t
441 1590 : start_postmaster(void)
442 : {
443 : char *cmd;
444 :
445 : #ifndef WIN32
446 : pid_t pm_pid;
447 :
448 : /* Flush stdio channels just before fork, to avoid double-output problems */
449 1590 : fflush(NULL);
450 :
451 : #ifdef EXEC_BACKEND
452 : pg_disable_aslr();
453 : #endif
454 :
455 1590 : pm_pid = fork();
456 3180 : if (pm_pid < 0)
457 : {
458 : /* fork failed */
459 0 : write_stderr(_("%s: could not start server: %m\n"),
460 : progname);
461 0 : exit(1);
462 : }
463 3180 : if (pm_pid > 0)
464 : {
465 : /* fork succeeded, in parent */
466 1590 : return pm_pid;
467 : }
468 :
469 : /* fork succeeded, in child */
470 :
471 : /*
472 : * If possible, detach the postmaster process from the launching process
473 : * group and make it a group leader, so that it doesn't get signaled along
474 : * with the current group that launched it.
475 : */
476 : #ifdef HAVE_SETSID
477 1590 : if (setsid() < 0)
478 : {
479 0 : write_stderr(_("%s: could not start server due to setsid() failure: %m\n"),
480 : progname);
481 0 : exit(1);
482 : }
483 : #endif
484 :
485 : /*
486 : * Since there might be quotes to handle here, it is easier simply to pass
487 : * everything to a shell to process them. Use exec so that the postmaster
488 : * has the same PID as the current child process.
489 : */
490 1590 : if (log_file != NULL)
491 1560 : cmd = psprintf("exec \"%s\" %s%s < \"%s\" >> \"%s\" 2>&1",
492 : exec_path, pgdata_opt, post_opts,
493 : DEVNULL, log_file);
494 : else
495 30 : cmd = psprintf("exec \"%s\" %s%s < \"%s\" 2>&1",
496 : exec_path, pgdata_opt, post_opts, DEVNULL);
497 :
498 1590 : (void) execl("/bin/sh", "/bin/sh", "-c", cmd, (char *) NULL);
499 :
500 : /* exec failed */
501 1590 : write_stderr(_("%s: could not start server: %m\n"),
502 : progname);
503 0 : exit(1);
504 :
505 : return 0; /* keep dumb compilers quiet */
506 :
507 : #else /* WIN32 */
508 :
509 : /*
510 : * As with the Unix case, it's easiest to use the shell (CMD.EXE) to
511 : * handle redirection etc. Unfortunately CMD.EXE lacks any equivalent of
512 : * "exec", so we don't get to find out the postmaster's PID immediately.
513 : */
514 : PROCESS_INFORMATION pi;
515 : const char *comspec;
516 :
517 : /* Find CMD.EXE location using COMSPEC, if it's set */
518 : comspec = getenv("COMSPEC");
519 : if (comspec == NULL)
520 : comspec = "CMD";
521 :
522 : if (log_file != NULL)
523 : {
524 : /*
525 : * First, open the log file if it exists. The idea is that if the
526 : * file is still locked by a previous postmaster run, we'll wait until
527 : * it comes free, instead of failing with ERROR_SHARING_VIOLATION.
528 : * (It'd be better to open the file in a sharing-friendly mode, but we
529 : * can't use CMD.EXE to do that, so work around it. Note that the
530 : * previous postmaster will still have the file open for a short time
531 : * after removing postmaster.pid.)
532 : *
533 : * If the log file doesn't exist, we *must not* create it here. If we
534 : * were launched with higher privileges than the restricted process
535 : * will have, the log file might end up with permissions settings that
536 : * prevent the postmaster from writing on it.
537 : */
538 : int fd = open(log_file, O_RDWR, 0);
539 :
540 : if (fd == -1)
541 : {
542 : /*
543 : * ENOENT is expectable since we didn't use O_CREAT. Otherwise
544 : * complain. We could just fall through and let CMD.EXE report
545 : * the problem, but its error reporting is pretty miserable.
546 : */
547 : if (errno != ENOENT)
548 : {
549 : write_stderr(_("%s: could not open log file \"%s\": %m\n"),
550 : progname, log_file);
551 : exit(1);
552 : }
553 : }
554 : else
555 : close(fd);
556 :
557 : cmd = psprintf("\"%s\" /C \"\"%s\" %s%s < \"%s\" >> \"%s\" 2>&1\"",
558 : comspec, exec_path, pgdata_opt, post_opts, DEVNULL, log_file);
559 : }
560 : else
561 : cmd = psprintf("\"%s\" /C \"\"%s\" %s%s < \"%s\" 2>&1\"",
562 : comspec, exec_path, pgdata_opt, post_opts, DEVNULL);
563 :
564 : if (!CreateRestrictedProcess(cmd, &pi, false))
565 : {
566 : write_stderr(_("%s: could not start server: error code %lu\n"),
567 : progname, (unsigned long) GetLastError());
568 : exit(1);
569 : }
570 : /* Don't close command process handle here; caller must do so */
571 : postmasterProcess = pi.hProcess;
572 : CloseHandle(pi.hThread);
573 : return pi.dwProcessId; /* Shell's PID, not postmaster's! */
574 : #endif /* WIN32 */
575 : }
576 :
577 :
578 :
579 : /*
580 : * Wait for the postmaster to become ready.
581 : *
582 : * On Unix, pm_pid is the PID of the just-launched postmaster. On Windows,
583 : * it may be the PID of an ancestor shell process, so we can't check the
584 : * contents of postmaster.pid quite as carefully.
585 : *
586 : * On Windows, the static variable postmasterProcess is an implicit argument
587 : * to this routine; it contains a handle to the postmaster process or an
588 : * ancestor shell process thereof.
589 : *
590 : * Note that the checkpoint parameter enables a Windows service control
591 : * manager checkpoint, it's got nothing to do with database checkpoints!!
592 : */
593 : static WaitPMResult
594 1590 : wait_for_postmaster_start(pid_t pm_pid, bool do_checkpoint)
595 : {
596 : int i;
597 :
598 6696 : for (i = 0; i < wait_seconds * WAITS_PER_SEC; i++)
599 : {
600 : char **optlines;
601 : int numlines;
602 :
603 : /*
604 : * Try to read the postmaster.pid file. If it's not valid, or if the
605 : * status line isn't there yet, just keep waiting.
606 : */
607 6696 : if ((optlines = readfile(pid_file, &numlines)) != NULL &&
608 4948 : numlines >= LOCK_FILE_LINE_PM_STATUS)
609 : {
610 : /* File is complete enough for us, parse it */
611 : pid_t pmpid;
612 : time_t pmstart;
613 :
614 : /*
615 : * Make sanity checks. If it's for the wrong PID, or the recorded
616 : * start time is before pg_ctl started, then either we are looking
617 : * at the wrong data directory, or this is a pre-existing pidfile
618 : * that hasn't (yet?) been overwritten by our child postmaster.
619 : * Allow 2 seconds slop for possible cross-process clock skew.
620 : */
621 4770 : pmpid = atol(optlines[LOCK_FILE_LINE_PID - 1]);
622 4770 : pmstart = atoll(optlines[LOCK_FILE_LINE_START_TIME - 1]);
623 4770 : if (pmstart >= start_time - 2 &&
624 : #ifndef WIN32
625 : pmpid == pm_pid
626 : #else
627 : /* Windows can only reject standalone-backend PIDs */
628 : pmpid > 0
629 : #endif
630 : )
631 : {
632 : /*
633 : * OK, seems to be a valid pidfile from our child. Check the
634 : * status line (this assumes a v10 or later server).
635 : */
636 4762 : char *pmstatus = optlines[LOCK_FILE_LINE_PM_STATUS - 1];
637 :
638 4762 : if (strcmp(pmstatus, PM_STATUS_READY) == 0 ||
639 3202 : strcmp(pmstatus, PM_STATUS_STANDBY) == 0)
640 : {
641 : /* postmaster is done starting up */
642 1564 : free_readfile(optlines);
643 1590 : return POSTMASTER_READY;
644 : }
645 : }
646 : }
647 :
648 : /*
649 : * Free the results of readfile.
650 : *
651 : * This is safe to call even if optlines is NULL.
652 : */
653 5132 : free_readfile(optlines);
654 :
655 : /*
656 : * Check whether the child postmaster process is still alive. This
657 : * lets us exit early if the postmaster fails during startup.
658 : *
659 : * On Windows, we may be checking the postmaster's parent shell, but
660 : * that's fine for this purpose.
661 : */
662 : {
663 : bool pm_died;
664 : #ifndef WIN32
665 : int exitstatus;
666 :
667 5132 : pm_died = (waitpid(pm_pid, &exitstatus, WNOHANG) == pm_pid);
668 : #else
669 : pm_died = (WaitForSingleObject(postmasterProcess, 0) == WAIT_OBJECT_0);
670 : #endif
671 5132 : if (pm_died)
672 : {
673 : /* See if postmaster terminated intentionally */
674 26 : if (get_control_dbstate() == DB_SHUTDOWNED_IN_RECOVERY)
675 26 : return POSTMASTER_SHUTDOWN_IN_RECOVERY;
676 : else
677 24 : return POSTMASTER_FAILED;
678 : }
679 : }
680 :
681 : /* Startup still in process; wait, printing a dot once per second */
682 5106 : if (i % WAITS_PER_SEC == 0)
683 : {
684 : #ifdef WIN32
685 : if (do_checkpoint)
686 : {
687 : /*
688 : * Increment the wait hint by 6 secs (connection timeout +
689 : * sleep). We must do this to indicate to the SCM that our
690 : * startup time is changing, otherwise it'll usually send a
691 : * stop signal after 20 seconds, despite incrementing the
692 : * checkpoint counter.
693 : */
694 : status.dwWaitHint += 6000;
695 : status.dwCheckPoint++;
696 : SetServiceStatus(hStatus, (LPSERVICE_STATUS) &status);
697 : }
698 : else
699 : #endif
700 1632 : print_msg(".");
701 : }
702 :
703 5106 : pg_usleep(USECS_PER_SEC / WAITS_PER_SEC);
704 : }
705 :
706 : /* out of patience; report that postmaster is still starting up */
707 0 : return POSTMASTER_STILL_STARTING;
708 : }
709 :
710 :
711 : /*
712 : * Wait for the postmaster to stop.
713 : *
714 : * Returns true if the postmaster stopped cleanly (i.e., removed its pidfile).
715 : * Returns false if the postmaster dies uncleanly, or if we time out.
716 : */
717 : static bool
718 1748 : wait_for_postmaster_stop(void)
719 : {
720 : int cnt;
721 :
722 10222 : for (cnt = 0; cnt < wait_seconds * WAITS_PER_SEC; cnt++)
723 : {
724 : pid_t pid;
725 :
726 10222 : if ((pid = get_pgpid(false)) == 0)
727 1748 : return true; /* pid file is gone */
728 :
729 8474 : if (kill(pid, 0) != 0)
730 : {
731 : /*
732 : * Postmaster seems to have died. Check the pid file once more to
733 : * avoid a race condition, but give up waiting.
734 : */
735 0 : if (get_pgpid(false) == 0)
736 0 : return true; /* pid file is gone */
737 0 : return false; /* postmaster died untimely */
738 : }
739 :
740 8474 : if (cnt % WAITS_PER_SEC == 0)
741 1800 : print_msg(".");
742 8474 : pg_usleep(USECS_PER_SEC / WAITS_PER_SEC);
743 : }
744 0 : return false; /* timeout reached */
745 : }
746 :
747 :
748 : /*
749 : * Wait for the postmaster to promote.
750 : *
751 : * Returns true on success, else false.
752 : * To avoid waiting uselessly, we check for postmaster death here too.
753 : */
754 : static bool
755 82 : wait_for_postmaster_promote(void)
756 : {
757 : int cnt;
758 :
759 498 : for (cnt = 0; cnt < wait_seconds * WAITS_PER_SEC; cnt++)
760 : {
761 : pid_t pid;
762 : DBState state;
763 :
764 498 : if ((pid = get_pgpid(false)) == 0)
765 0 : return false; /* pid file is gone */
766 498 : if (kill(pid, 0) != 0)
767 0 : return false; /* postmaster died */
768 :
769 498 : state = get_control_dbstate();
770 498 : if (state == DB_IN_PRODUCTION)
771 82 : return true; /* successful promotion */
772 :
773 416 : if (cnt % WAITS_PER_SEC == 0)
774 84 : print_msg(".");
775 416 : pg_usleep(USECS_PER_SEC / WAITS_PER_SEC);
776 : }
777 0 : return false; /* timeout reached */
778 : }
779 :
780 :
781 : #if defined(HAVE_GETRLIMIT)
782 : static void
783 0 : unlimit_core_size(void)
784 : {
785 : struct rlimit lim;
786 :
787 0 : getrlimit(RLIMIT_CORE, &lim);
788 0 : if (lim.rlim_max == 0)
789 : {
790 0 : write_stderr(_("%s: cannot set core file size limit; disallowed by hard limit\n"),
791 : progname);
792 0 : return;
793 : }
794 0 : else if (lim.rlim_max == RLIM_INFINITY || lim.rlim_cur < lim.rlim_max)
795 : {
796 0 : lim.rlim_cur = lim.rlim_max;
797 0 : setrlimit(RLIMIT_CORE, &lim);
798 : }
799 : }
800 : #endif
801 :
802 : static void
803 1590 : read_post_opts(void)
804 : {
805 1590 : if (post_opts == NULL)
806 : {
807 262 : post_opts = ""; /* default */
808 262 : if (ctl_command == RESTART_COMMAND)
809 : {
810 : char **optlines;
811 : int numlines;
812 :
813 236 : optlines = readfile(postopts_file, &numlines);
814 236 : if (optlines == NULL)
815 : {
816 0 : write_stderr(_("%s: could not read file \"%s\"\n"), progname, postopts_file);
817 0 : exit(1);
818 : }
819 236 : else if (numlines != 1)
820 : {
821 0 : write_stderr(_("%s: option file \"%s\" must have exactly one line\n"),
822 : progname, postopts_file);
823 0 : exit(1);
824 : }
825 : else
826 : {
827 : char *optline;
828 : char *arg1;
829 :
830 236 : optline = optlines[0];
831 :
832 : /*
833 : * Are we at the first option, as defined by space and
834 : * double-quote?
835 : */
836 236 : if ((arg1 = strstr(optline, " \"")) != NULL)
837 : {
838 236 : *arg1 = '\0'; /* terminate so we get only program name */
839 236 : post_opts = pg_strdup(arg1 + 1); /* point past whitespace */
840 : }
841 236 : if (exec_path == NULL)
842 236 : exec_path = pg_strdup(optline);
843 : }
844 :
845 : /* Free the results of readfile. */
846 236 : free_readfile(optlines);
847 : }
848 : }
849 1590 : }
850 :
851 : /*
852 : * SIGINT signal handler used while waiting for postmaster to start up.
853 : * Forwards the SIGINT to the postmaster process, asking it to shut down,
854 : * before terminating pg_ctl itself. This way, if the user hits CTRL-C while
855 : * waiting for the server to start up, the server launch is aborted.
856 : */
857 : static void
858 0 : trap_sigint_during_startup(SIGNAL_ARGS)
859 : {
860 0 : if (postmasterPID != -1)
861 : {
862 0 : if (kill(postmasterPID, SIGINT) != 0)
863 0 : write_stderr(_("%s: could not send stop signal (PID: %d): %m\n"),
864 : progname, (int) postmasterPID);
865 : }
866 :
867 : /*
868 : * Clear the signal handler, and send the signal again, to terminate the
869 : * process as normal.
870 : */
871 0 : pqsignal(postgres_signal_arg, SIG_DFL);
872 0 : raise(postgres_signal_arg);
873 0 : }
874 :
875 : static char *
876 1356 : find_other_exec_or_die(const char *argv0, const char *target, const char *versionstr)
877 : {
878 : int ret;
879 : char *found_path;
880 :
881 1356 : found_path = pg_malloc(MAXPGPATH);
882 :
883 1356 : if ((ret = find_other_exec(argv0, target, versionstr, found_path)) < 0)
884 : {
885 : char full_path[MAXPGPATH];
886 :
887 0 : if (find_my_exec(argv0, full_path) < 0)
888 0 : strlcpy(full_path, progname, sizeof(full_path));
889 :
890 0 : if (ret == -1)
891 0 : write_stderr(_("program \"%s\" is needed by %s but was not found in the same directory as \"%s\"\n"),
892 : target, progname, full_path);
893 : else
894 0 : write_stderr(_("program \"%s\" was found by \"%s\" but was not the same version as %s\n"),
895 : target, full_path, progname);
896 0 : exit(1);
897 : }
898 :
899 1356 : return found_path;
900 : }
901 :
902 : static void
903 2 : do_init(void)
904 : {
905 : char *cmd;
906 :
907 2 : if (exec_path == NULL)
908 2 : exec_path = find_other_exec_or_die(argv0, "initdb", "initdb (PostgreSQL) " PG_VERSION "\n");
909 :
910 2 : if (pgdata_opt == NULL)
911 0 : pgdata_opt = "";
912 :
913 2 : if (post_opts == NULL)
914 0 : post_opts = "";
915 :
916 2 : if (!silent_mode)
917 2 : cmd = psprintf("\"%s\" %s%s",
918 : exec_path, pgdata_opt, post_opts);
919 : else
920 0 : cmd = psprintf("\"%s\" %s%s > \"%s\"",
921 : exec_path, pgdata_opt, post_opts, DEVNULL);
922 :
923 2 : fflush(NULL);
924 2 : if (system(cmd) != 0)
925 : {
926 0 : write_stderr(_("%s: database system initialization failed\n"), progname);
927 0 : exit(1);
928 : }
929 2 : }
930 :
931 : static void
932 1592 : do_start(void)
933 : {
934 1592 : pid_t old_pid = 0;
935 : pid_t pm_pid;
936 :
937 1592 : if (ctl_command != RESTART_COMMAND)
938 : {
939 1356 : old_pid = get_pgpid(false);
940 1354 : if (old_pid != 0)
941 6 : write_stderr(_("%s: another server might be running; "
942 : "trying to start server anyway\n"),
943 : progname);
944 : }
945 :
946 1590 : read_post_opts();
947 :
948 : /* No -D or -D already added during server start */
949 1590 : if (ctl_command == RESTART_COMMAND || pgdata_opt == NULL)
950 236 : pgdata_opt = "";
951 :
952 1590 : if (exec_path == NULL)
953 1354 : exec_path = find_other_exec_or_die(argv0, "postgres", PG_BACKEND_VERSIONSTR);
954 :
955 : #if defined(HAVE_GETRLIMIT)
956 1590 : if (allow_core_files)
957 0 : unlimit_core_size();
958 : #endif
959 :
960 : /*
961 : * If possible, tell the postmaster our parent shell's PID (see the
962 : * comments in CreateLockFile() for motivation). Windows hasn't got
963 : * getppid() unfortunately.
964 : */
965 : #ifndef WIN32
966 : {
967 : char env_var[32];
968 :
969 1590 : snprintf(env_var, sizeof(env_var), "%d", (int) getppid());
970 1590 : setenv("PG_GRANDPARENT_PID", env_var, 1);
971 : }
972 : #endif
973 :
974 1590 : pm_pid = start_postmaster();
975 :
976 1590 : if (do_wait)
977 : {
978 : /*
979 : * If the user interrupts the startup (e.g. with CTRL-C), we'd like to
980 : * abort the server launch. Install a signal handler that will
981 : * forward SIGINT to the postmaster process, while we wait.
982 : *
983 : * (We don't bother to reset the signal handler after the launch, as
984 : * we're about to exit, anyway.)
985 : */
986 1590 : postmasterPID = pm_pid;
987 1590 : pqsignal(SIGINT, trap_sigint_during_startup);
988 :
989 1590 : print_msg(_("waiting for server to start..."));
990 :
991 1590 : switch (wait_for_postmaster_start(pm_pid, false))
992 : {
993 1564 : case POSTMASTER_READY:
994 1564 : print_msg(_(" done\n"));
995 1564 : print_msg(_("server started\n"));
996 1564 : break;
997 0 : case POSTMASTER_STILL_STARTING:
998 0 : print_msg(_(" stopped waiting\n"));
999 0 : write_stderr(_("%s: server did not start in time\n"),
1000 : progname);
1001 0 : exit(1);
1002 : break;
1003 2 : case POSTMASTER_SHUTDOWN_IN_RECOVERY:
1004 2 : print_msg(_(" done\n"));
1005 2 : print_msg(_("server shut down because of recovery target settings\n"));
1006 2 : break;
1007 24 : case POSTMASTER_FAILED:
1008 24 : print_msg(_(" stopped waiting\n"));
1009 24 : write_stderr(_("%s: could not start server\n"
1010 : "Examine the log output.\n"),
1011 : progname);
1012 24 : exit(1);
1013 : break;
1014 : }
1015 : }
1016 : else
1017 0 : print_msg(_("server starting\n"));
1018 :
1019 : #ifdef WIN32
1020 : /* Now we don't need the handle to the shell process anymore */
1021 : CloseHandle(postmasterProcess);
1022 : postmasterProcess = INVALID_HANDLE_VALUE;
1023 : #endif
1024 1566 : }
1025 :
1026 :
1027 : static void
1028 1524 : do_stop(void)
1029 : {
1030 : pid_t pid;
1031 :
1032 1524 : pid = get_pgpid(false);
1033 :
1034 1524 : if (pid == 0) /* no pid file */
1035 : {
1036 2 : write_stderr(_("%s: PID file \"%s\" does not exist\n"), progname, pid_file);
1037 2 : write_stderr(_("Is server running?\n"));
1038 2 : exit(1);
1039 : }
1040 1522 : else if (pid < 0) /* standalone backend, not postmaster */
1041 : {
1042 0 : pid = -pid;
1043 0 : write_stderr(_("%s: cannot stop server; "
1044 : "single-user server is running (PID: %d)\n"),
1045 : progname, (int) pid);
1046 0 : exit(1);
1047 : }
1048 :
1049 1522 : if (kill(pid, sig) != 0)
1050 : {
1051 0 : write_stderr(_("%s: could not send stop signal (PID: %d): %m\n"), progname, (int) pid);
1052 0 : exit(1);
1053 : }
1054 :
1055 1522 : if (!do_wait)
1056 : {
1057 0 : print_msg(_("server shutting down\n"));
1058 0 : return;
1059 : }
1060 : else
1061 : {
1062 1522 : print_msg(_("waiting for server to shut down..."));
1063 :
1064 1522 : if (!wait_for_postmaster_stop())
1065 : {
1066 0 : print_msg(_(" failed\n"));
1067 :
1068 0 : write_stderr(_("%s: server does not shut down\n"), progname);
1069 0 : if (shutdown_mode == SMART_MODE)
1070 0 : write_stderr(_("HINT: The \"-m fast\" option immediately disconnects sessions rather than\n"
1071 : "waiting for session-initiated disconnection.\n"));
1072 0 : exit(1);
1073 : }
1074 1522 : print_msg(_(" done\n"));
1075 :
1076 1522 : print_msg(_("server stopped\n"));
1077 : }
1078 : }
1079 :
1080 :
1081 : /*
1082 : * restart/reload routines
1083 : */
1084 :
1085 : static void
1086 236 : do_restart(void)
1087 : {
1088 : pid_t pid;
1089 :
1090 236 : pid = get_pgpid(false);
1091 :
1092 236 : if (pid == 0) /* no pid file */
1093 : {
1094 10 : write_stderr(_("%s: PID file \"%s\" does not exist\n"),
1095 : progname, pid_file);
1096 10 : write_stderr(_("Is server running?\n"));
1097 10 : write_stderr(_("trying to start server anyway\n"));
1098 10 : do_start();
1099 8 : return;
1100 : }
1101 226 : else if (pid < 0) /* standalone backend, not postmaster */
1102 : {
1103 0 : pid = -pid;
1104 0 : if (postmaster_is_alive(pid))
1105 : {
1106 0 : write_stderr(_("%s: cannot restart server; "
1107 : "single-user server is running (PID: %d)\n"),
1108 : progname, (int) pid);
1109 0 : write_stderr(_("Please terminate the single-user server and try again.\n"));
1110 0 : exit(1);
1111 : }
1112 : }
1113 :
1114 226 : if (postmaster_is_alive(pid))
1115 : {
1116 226 : if (kill(pid, sig) != 0)
1117 : {
1118 0 : write_stderr(_("%s: could not send stop signal (PID: %d): %m\n"), progname, (int) pid);
1119 0 : exit(1);
1120 : }
1121 :
1122 226 : print_msg(_("waiting for server to shut down..."));
1123 :
1124 : /* always wait for restart */
1125 226 : if (!wait_for_postmaster_stop())
1126 : {
1127 0 : print_msg(_(" failed\n"));
1128 :
1129 0 : write_stderr(_("%s: server does not shut down\n"), progname);
1130 0 : if (shutdown_mode == SMART_MODE)
1131 0 : write_stderr(_("HINT: The \"-m fast\" option immediately disconnects sessions rather than\n"
1132 : "waiting for session-initiated disconnection.\n"));
1133 0 : exit(1);
1134 : }
1135 :
1136 226 : print_msg(_(" done\n"));
1137 226 : print_msg(_("server stopped\n"));
1138 : }
1139 : else
1140 : {
1141 0 : write_stderr(_("%s: old server process (PID: %d) seems to be gone\n"),
1142 : progname, (int) pid);
1143 0 : write_stderr(_("starting server anyway\n"));
1144 : }
1145 :
1146 226 : do_start();
1147 : }
1148 :
1149 : static void
1150 226 : do_reload(void)
1151 : {
1152 : pid_t pid;
1153 :
1154 226 : pid = get_pgpid(false);
1155 226 : if (pid == 0) /* no pid file */
1156 : {
1157 0 : write_stderr(_("%s: PID file \"%s\" does not exist\n"), progname, pid_file);
1158 0 : write_stderr(_("Is server running?\n"));
1159 0 : exit(1);
1160 : }
1161 226 : else if (pid < 0) /* standalone backend, not postmaster */
1162 : {
1163 0 : pid = -pid;
1164 0 : write_stderr(_("%s: cannot reload server; "
1165 : "single-user server is running (PID: %d)\n"),
1166 : progname, (int) pid);
1167 0 : write_stderr(_("Please terminate the single-user server and try again.\n"));
1168 0 : exit(1);
1169 : }
1170 :
1171 226 : if (kill(pid, sig) != 0)
1172 : {
1173 0 : write_stderr(_("%s: could not send reload signal (PID: %d): %m\n"),
1174 : progname, (int) pid);
1175 0 : exit(1);
1176 : }
1177 :
1178 226 : print_msg(_("server signaled\n"));
1179 226 : }
1180 :
1181 :
1182 : /*
1183 : * promote
1184 : */
1185 :
1186 : static void
1187 90 : do_promote(void)
1188 : {
1189 : FILE *prmfile;
1190 : pid_t pid;
1191 :
1192 90 : pid = get_pgpid(false);
1193 :
1194 88 : if (pid == 0) /* no pid file */
1195 : {
1196 2 : write_stderr(_("%s: PID file \"%s\" does not exist\n"), progname, pid_file);
1197 2 : write_stderr(_("Is server running?\n"));
1198 2 : exit(1);
1199 : }
1200 86 : else if (pid < 0) /* standalone backend, not postmaster */
1201 : {
1202 0 : pid = -pid;
1203 0 : write_stderr(_("%s: cannot promote server; "
1204 : "single-user server is running (PID: %d)\n"),
1205 : progname, (int) pid);
1206 0 : exit(1);
1207 : }
1208 :
1209 86 : if (get_control_dbstate() != DB_IN_ARCHIVE_RECOVERY)
1210 : {
1211 2 : write_stderr(_("%s: cannot promote server; "
1212 : "server is not in standby mode\n"),
1213 : progname);
1214 2 : exit(1);
1215 : }
1216 :
1217 84 : snprintf(promote_file, MAXPGPATH, "%s/promote", pg_data);
1218 :
1219 84 : if ((prmfile = fopen(promote_file, "w")) == NULL)
1220 : {
1221 0 : write_stderr(_("%s: could not create promote signal file \"%s\": %m\n"),
1222 : progname, promote_file);
1223 0 : exit(1);
1224 : }
1225 84 : if (fclose(prmfile))
1226 : {
1227 0 : write_stderr(_("%s: could not write promote signal file \"%s\": %m\n"),
1228 : progname, promote_file);
1229 0 : exit(1);
1230 : }
1231 :
1232 84 : sig = SIGUSR1;
1233 84 : if (kill(pid, sig) != 0)
1234 : {
1235 0 : write_stderr(_("%s: could not send promote signal (PID: %d): %m\n"),
1236 : progname, (int) pid);
1237 0 : if (unlink(promote_file) != 0)
1238 0 : write_stderr(_("%s: could not remove promote signal file \"%s\": %m\n"),
1239 : progname, promote_file);
1240 0 : exit(1);
1241 : }
1242 :
1243 84 : if (do_wait)
1244 : {
1245 82 : print_msg(_("waiting for server to promote..."));
1246 82 : if (wait_for_postmaster_promote())
1247 : {
1248 82 : print_msg(_(" done\n"));
1249 82 : print_msg(_("server promoted\n"));
1250 : }
1251 : else
1252 : {
1253 0 : print_msg(_(" stopped waiting\n"));
1254 0 : write_stderr(_("%s: server did not promote in time\n"),
1255 : progname);
1256 0 : exit(1);
1257 : }
1258 : }
1259 : else
1260 2 : print_msg(_("server promoting\n"));
1261 84 : }
1262 :
1263 : /*
1264 : * log rotate
1265 : */
1266 :
1267 : static void
1268 2 : do_logrotate(void)
1269 : {
1270 : FILE *logrotatefile;
1271 : pid_t pid;
1272 :
1273 2 : pid = get_pgpid(false);
1274 :
1275 2 : if (pid == 0) /* no pid file */
1276 : {
1277 0 : write_stderr(_("%s: PID file \"%s\" does not exist\n"), progname, pid_file);
1278 0 : write_stderr(_("Is server running?\n"));
1279 0 : exit(1);
1280 : }
1281 2 : else if (pid < 0) /* standalone backend, not postmaster */
1282 : {
1283 0 : pid = -pid;
1284 0 : write_stderr(_("%s: cannot rotate log file; "
1285 : "single-user server is running (PID: %d)\n"),
1286 : progname, (int) pid);
1287 0 : exit(1);
1288 : }
1289 :
1290 2 : snprintf(logrotate_file, MAXPGPATH, "%s/logrotate", pg_data);
1291 :
1292 2 : if ((logrotatefile = fopen(logrotate_file, "w")) == NULL)
1293 : {
1294 0 : write_stderr(_("%s: could not create log rotation signal file \"%s\": %m\n"),
1295 : progname, logrotate_file);
1296 0 : exit(1);
1297 : }
1298 2 : if (fclose(logrotatefile))
1299 : {
1300 0 : write_stderr(_("%s: could not write log rotation signal file \"%s\": %m\n"),
1301 : progname, logrotate_file);
1302 0 : exit(1);
1303 : }
1304 :
1305 2 : sig = SIGUSR1;
1306 2 : if (kill(pid, sig) != 0)
1307 : {
1308 0 : write_stderr(_("%s: could not send log rotation signal (PID: %d): %m\n"),
1309 : progname, (int) pid);
1310 0 : if (unlink(logrotate_file) != 0)
1311 0 : write_stderr(_("%s: could not remove log rotation signal file \"%s\": %m\n"),
1312 : progname, logrotate_file);
1313 0 : exit(1);
1314 : }
1315 :
1316 2 : print_msg(_("server signaled to rotate log file\n"));
1317 2 : }
1318 :
1319 :
1320 : /*
1321 : * utility routines
1322 : */
1323 :
1324 : static bool
1325 228 : postmaster_is_alive(pid_t pid)
1326 : {
1327 : /*
1328 : * Test to see if the process is still there. Note that we do not
1329 : * consider an EPERM failure to mean that the process is still there;
1330 : * EPERM must mean that the given PID belongs to some other userid, and
1331 : * considering the permissions on $PGDATA, that means it's not the
1332 : * postmaster we are after.
1333 : *
1334 : * Don't believe that our own PID or parent shell's PID is the postmaster,
1335 : * either. (Windows hasn't got getppid(), though.)
1336 : */
1337 228 : if (pid == getpid())
1338 0 : return false;
1339 : #ifndef WIN32
1340 228 : if (pid == getppid())
1341 0 : return false;
1342 : #endif
1343 228 : if (kill(pid, 0) == 0)
1344 228 : return true;
1345 0 : return false;
1346 : }
1347 :
1348 : static void
1349 6 : do_status(void)
1350 : {
1351 : pid_t pid;
1352 :
1353 6 : pid = get_pgpid(true);
1354 : /* Is there a pid file? */
1355 4 : if (pid != 0)
1356 : {
1357 : /* standalone backend? */
1358 2 : if (pid < 0)
1359 : {
1360 0 : pid = -pid;
1361 0 : if (postmaster_is_alive(pid))
1362 : {
1363 0 : printf(_("%s: single-user server is running (PID: %d)\n"),
1364 : progname, (int) pid);
1365 0 : return;
1366 : }
1367 : }
1368 : else
1369 : /* must be a postmaster */
1370 : {
1371 2 : if (postmaster_is_alive(pid))
1372 : {
1373 : char **optlines;
1374 : char **curr_line;
1375 : int numlines;
1376 :
1377 2 : printf(_("%s: server is running (PID: %d)\n"),
1378 : progname, (int) pid);
1379 :
1380 2 : optlines = readfile(postopts_file, &numlines);
1381 2 : if (optlines != NULL)
1382 : {
1383 4 : for (curr_line = optlines; *curr_line != NULL; curr_line++)
1384 2 : puts(*curr_line);
1385 :
1386 : /* Free the results of readfile */
1387 2 : free_readfile(optlines);
1388 : }
1389 2 : return;
1390 : }
1391 : }
1392 : }
1393 2 : printf(_("%s: no server running\n"), progname);
1394 :
1395 : /*
1396 : * The Linux Standard Base Core Specification 3.1 says this should return
1397 : * '3, program is not running'
1398 : * https://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
1399 : */
1400 2 : exit(3);
1401 : }
1402 :
1403 :
1404 :
1405 : static void
1406 20 : do_kill(pid_t pid)
1407 : {
1408 20 : if (kill(pid, sig) != 0)
1409 : {
1410 0 : write_stderr(_("%s: could not send signal %d (PID: %d): %m\n"),
1411 : progname, sig, (int) pid);
1412 0 : exit(1);
1413 : }
1414 20 : }
1415 :
1416 : #ifdef WIN32
1417 :
1418 : static bool
1419 : pgwin32_IsInstalled(SC_HANDLE hSCM)
1420 : {
1421 : SC_HANDLE hService = OpenService(hSCM, register_servicename, SERVICE_QUERY_CONFIG);
1422 : bool bResult = (hService != NULL);
1423 :
1424 : if (bResult)
1425 : CloseServiceHandle(hService);
1426 : return bResult;
1427 : }
1428 :
1429 : static char *
1430 : pgwin32_CommandLine(bool registration)
1431 : {
1432 : PQExpBuffer cmdLine = createPQExpBuffer();
1433 : char cmdPath[MAXPGPATH];
1434 : int ret;
1435 :
1436 : if (registration)
1437 : {
1438 : ret = find_my_exec(argv0, cmdPath);
1439 : if (ret != 0)
1440 : {
1441 : write_stderr(_("%s: could not find own program executable\n"), progname);
1442 : exit(1);
1443 : }
1444 : }
1445 : else
1446 : {
1447 : ret = find_other_exec(argv0, "postgres", PG_BACKEND_VERSIONSTR,
1448 : cmdPath);
1449 : if (ret != 0)
1450 : {
1451 : write_stderr(_("%s: could not find postgres program executable\n"), progname);
1452 : exit(1);
1453 : }
1454 : }
1455 :
1456 : /* if path does not end in .exe, append it */
1457 : if (strlen(cmdPath) < 4 ||
1458 : pg_strcasecmp(cmdPath + strlen(cmdPath) - 4, ".exe") != 0)
1459 : snprintf(cmdPath + strlen(cmdPath), sizeof(cmdPath) - strlen(cmdPath),
1460 : ".exe");
1461 :
1462 : /* use backslashes in path to avoid problems with some third-party tools */
1463 : make_native_path(cmdPath);
1464 :
1465 : /* be sure to double-quote the executable's name in the command */
1466 : appendPQExpBuffer(cmdLine, "\"%s\"", cmdPath);
1467 :
1468 : /* append assorted switches to the command line, as needed */
1469 :
1470 : if (registration)
1471 : appendPQExpBuffer(cmdLine, " runservice -N \"%s\"",
1472 : register_servicename);
1473 :
1474 : if (pg_config)
1475 : {
1476 : /* We need the -D path to be absolute */
1477 : char *dataDir;
1478 :
1479 : if ((dataDir = make_absolute_path(pg_config)) == NULL)
1480 : {
1481 : /* make_absolute_path already reported the error */
1482 : exit(1);
1483 : }
1484 : make_native_path(dataDir);
1485 : appendPQExpBuffer(cmdLine, " -D \"%s\"", dataDir);
1486 : free(dataDir);
1487 : }
1488 :
1489 : if (registration && event_source != NULL)
1490 : appendPQExpBuffer(cmdLine, " -e \"%s\"", event_source);
1491 :
1492 : if (registration && do_wait)
1493 : appendPQExpBufferStr(cmdLine, " -w");
1494 :
1495 : /* Don't propagate a value from an environment variable. */
1496 : if (registration && wait_seconds_arg && wait_seconds != DEFAULT_WAIT)
1497 : appendPQExpBuffer(cmdLine, " -t %d", wait_seconds);
1498 :
1499 : if (registration && silent_mode)
1500 : appendPQExpBufferStr(cmdLine, " -s");
1501 :
1502 : if (post_opts)
1503 : {
1504 : if (registration)
1505 : appendPQExpBuffer(cmdLine, " -o \"%s\"", post_opts);
1506 : else
1507 : appendPQExpBuffer(cmdLine, " %s", post_opts);
1508 : }
1509 :
1510 : return cmdLine->data;
1511 : }
1512 :
1513 : static void
1514 : pgwin32_doRegister(void)
1515 : {
1516 : SC_HANDLE hService;
1517 : SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
1518 :
1519 : if (hSCM == NULL)
1520 : {
1521 : write_stderr(_("%s: could not open service manager\n"), progname);
1522 : exit(1);
1523 : }
1524 : if (pgwin32_IsInstalled(hSCM))
1525 : {
1526 : CloseServiceHandle(hSCM);
1527 : write_stderr(_("%s: service \"%s\" already registered\n"), progname, register_servicename);
1528 : exit(1);
1529 : }
1530 :
1531 : if ((hService = CreateService(hSCM, register_servicename, register_servicename,
1532 : SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
1533 : pgctl_start_type, SERVICE_ERROR_NORMAL,
1534 : pgwin32_CommandLine(true),
1535 : NULL, NULL, "RPCSS\0", register_username, register_password)) == NULL)
1536 : {
1537 : CloseServiceHandle(hSCM);
1538 : write_stderr(_("%s: could not register service \"%s\": error code %lu\n"),
1539 : progname, register_servicename,
1540 : (unsigned long) GetLastError());
1541 : exit(1);
1542 : }
1543 : CloseServiceHandle(hService);
1544 : CloseServiceHandle(hSCM);
1545 : }
1546 :
1547 : static void
1548 : pgwin32_doUnregister(void)
1549 : {
1550 : SC_HANDLE hService;
1551 : SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
1552 :
1553 : if (hSCM == NULL)
1554 : {
1555 : write_stderr(_("%s: could not open service manager\n"), progname);
1556 : exit(1);
1557 : }
1558 : if (!pgwin32_IsInstalled(hSCM))
1559 : {
1560 : CloseServiceHandle(hSCM);
1561 : write_stderr(_("%s: service \"%s\" not registered\n"), progname, register_servicename);
1562 : exit(1);
1563 : }
1564 :
1565 : if ((hService = OpenService(hSCM, register_servicename, DELETE)) == NULL)
1566 : {
1567 : CloseServiceHandle(hSCM);
1568 : write_stderr(_("%s: could not open service \"%s\": error code %lu\n"),
1569 : progname, register_servicename,
1570 : (unsigned long) GetLastError());
1571 : exit(1);
1572 : }
1573 : if (!DeleteService(hService))
1574 : {
1575 : CloseServiceHandle(hService);
1576 : CloseServiceHandle(hSCM);
1577 : write_stderr(_("%s: could not unregister service \"%s\": error code %lu\n"),
1578 : progname, register_servicename,
1579 : (unsigned long) GetLastError());
1580 : exit(1);
1581 : }
1582 : CloseServiceHandle(hService);
1583 : CloseServiceHandle(hSCM);
1584 : }
1585 :
1586 : static void
1587 : pgwin32_SetServiceStatus(DWORD currentState)
1588 : {
1589 : status.dwCurrentState = currentState;
1590 : SetServiceStatus(hStatus, (LPSERVICE_STATUS) &status);
1591 : }
1592 :
1593 : static void WINAPI
1594 : pgwin32_ServiceHandler(DWORD request)
1595 : {
1596 : switch (request)
1597 : {
1598 : case SERVICE_CONTROL_STOP:
1599 : case SERVICE_CONTROL_SHUTDOWN:
1600 :
1601 : /*
1602 : * We only need a short wait hint here as it just needs to wait
1603 : * for the next checkpoint. They occur every 5 seconds during
1604 : * shutdown
1605 : */
1606 : status.dwWaitHint = 10000;
1607 : pgwin32_SetServiceStatus(SERVICE_STOP_PENDING);
1608 : SetEvent(shutdownEvent);
1609 : return;
1610 :
1611 : case SERVICE_CONTROL_PAUSE:
1612 : /* Win32 config reloading */
1613 : status.dwWaitHint = 5000;
1614 : kill(postmasterPID, SIGHUP);
1615 : return;
1616 :
1617 : /* FIXME: These could be used to replace other signals etc */
1618 : case SERVICE_CONTROL_CONTINUE:
1619 : case SERVICE_CONTROL_INTERROGATE:
1620 : default:
1621 : break;
1622 : }
1623 : }
1624 :
1625 : static void WINAPI
1626 : pgwin32_ServiceMain(DWORD argc, LPTSTR *argv)
1627 : {
1628 : PROCESS_INFORMATION pi;
1629 : DWORD ret;
1630 :
1631 : /* Initialize variables */
1632 : status.dwWin32ExitCode = S_OK;
1633 : status.dwCheckPoint = 0;
1634 : status.dwWaitHint = 60000;
1635 : status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1636 : status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE;
1637 : status.dwServiceSpecificExitCode = 0;
1638 : status.dwCurrentState = SERVICE_START_PENDING;
1639 :
1640 : memset(&pi, 0, sizeof(pi));
1641 :
1642 : read_post_opts();
1643 :
1644 : /* Register the control request handler */
1645 : if ((hStatus = RegisterServiceCtrlHandler(register_servicename, pgwin32_ServiceHandler)) == (SERVICE_STATUS_HANDLE) 0)
1646 : return;
1647 :
1648 : if ((shutdownEvent = CreateEvent(NULL, true, false, NULL)) == NULL)
1649 : return;
1650 :
1651 : /* Start the postmaster */
1652 : pgwin32_SetServiceStatus(SERVICE_START_PENDING);
1653 : if (!CreateRestrictedProcess(pgwin32_CommandLine(false), &pi, true))
1654 : {
1655 : pgwin32_SetServiceStatus(SERVICE_STOPPED);
1656 : return;
1657 : }
1658 : postmasterPID = pi.dwProcessId;
1659 : postmasterProcess = pi.hProcess;
1660 : CloseHandle(pi.hThread);
1661 :
1662 : if (do_wait)
1663 : {
1664 : write_eventlog(EVENTLOG_INFORMATION_TYPE, _("Waiting for server startup...\n"));
1665 : if (wait_for_postmaster_start(postmasterPID, true) != POSTMASTER_READY)
1666 : {
1667 : write_eventlog(EVENTLOG_ERROR_TYPE, _("Timed out waiting for server startup\n"));
1668 : pgwin32_SetServiceStatus(SERVICE_STOPPED);
1669 : return;
1670 : }
1671 : write_eventlog(EVENTLOG_INFORMATION_TYPE, _("Server started and accepting connections\n"));
1672 : }
1673 :
1674 : pgwin32_SetServiceStatus(SERVICE_RUNNING);
1675 :
1676 : /* Wait for quit... */
1677 : ret = WaitForMultipleObjects(2, shutdownHandles, FALSE, INFINITE);
1678 :
1679 : pgwin32_SetServiceStatus(SERVICE_STOP_PENDING);
1680 : switch (ret)
1681 : {
1682 : case WAIT_OBJECT_0: /* shutdown event */
1683 : {
1684 : /*
1685 : * status.dwCheckPoint can be incremented by
1686 : * wait_for_postmaster_start(), so it might not start from 0.
1687 : */
1688 : int maxShutdownCheckPoint = status.dwCheckPoint + 12;
1689 :
1690 : kill(postmasterPID, SIGINT);
1691 :
1692 : /*
1693 : * Increment the checkpoint and try again. Abort after 12
1694 : * checkpoints as the postmaster has probably hung.
1695 : */
1696 : while (WaitForSingleObject(postmasterProcess, 5000) == WAIT_TIMEOUT && status.dwCheckPoint < maxShutdownCheckPoint)
1697 : {
1698 : status.dwCheckPoint++;
1699 : SetServiceStatus(hStatus, (LPSERVICE_STATUS) &status);
1700 : }
1701 : break;
1702 : }
1703 :
1704 : case (WAIT_OBJECT_0 + 1): /* postmaster went down */
1705 : break;
1706 :
1707 : default:
1708 : /* shouldn't get here? */
1709 : break;
1710 : }
1711 :
1712 : CloseHandle(shutdownEvent);
1713 : CloseHandle(postmasterProcess);
1714 :
1715 : pgwin32_SetServiceStatus(SERVICE_STOPPED);
1716 : }
1717 :
1718 : static void
1719 : pgwin32_doRunAsService(void)
1720 : {
1721 : SERVICE_TABLE_ENTRY st[] = {{register_servicename, pgwin32_ServiceMain},
1722 : {NULL, NULL}};
1723 :
1724 : if (StartServiceCtrlDispatcher(st) == 0)
1725 : {
1726 : write_stderr(_("%s: could not start service \"%s\": error code %lu\n"),
1727 : progname, register_servicename,
1728 : (unsigned long) GetLastError());
1729 : exit(1);
1730 : }
1731 : }
1732 :
1733 :
1734 : /*
1735 : * Set up STARTUPINFO for the new process to inherit this process' handles.
1736 : *
1737 : * Process started as services appear to have "empty" handles (GetStdHandle()
1738 : * returns NULL) rather than invalid ones. But passing down NULL ourselves
1739 : * doesn't work, it's interpreted as STARTUPINFO->hStd* not being set. But we
1740 : * can pass down INVALID_HANDLE_VALUE - which makes GetStdHandle() in the new
1741 : * process (and its child processes!) return INVALID_HANDLE_VALUE. Which
1742 : * achieves the goal of postmaster running in a similar environment as pg_ctl.
1743 : */
1744 : static void
1745 : InheritStdHandles(STARTUPINFO *si)
1746 : {
1747 : si->dwFlags |= STARTF_USESTDHANDLES;
1748 : si->hStdInput = GetStdHandle(STD_INPUT_HANDLE);
1749 : if (si->hStdInput == NULL)
1750 : si->hStdInput = INVALID_HANDLE_VALUE;
1751 : si->hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
1752 : if (si->hStdOutput == NULL)
1753 : si->hStdOutput = INVALID_HANDLE_VALUE;
1754 : si->hStdError = GetStdHandle(STD_ERROR_HANDLE);
1755 : if (si->hStdError == NULL)
1756 : si->hStdError = INVALID_HANDLE_VALUE;
1757 : }
1758 :
1759 : /*
1760 : * Create a restricted token, a job object sandbox, and execute the specified
1761 : * process with it.
1762 : *
1763 : * Returns 0 on success, non-zero on failure, same as CreateProcess().
1764 : *
1765 : * NOTE! Job object will only work when running as a service, because it's
1766 : * automatically destroyed when pg_ctl exits.
1767 : */
1768 : static int
1769 : CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo, bool as_service)
1770 : {
1771 : int r;
1772 : BOOL b;
1773 : STARTUPINFO si;
1774 : HANDLE origToken;
1775 : HANDLE restrictedToken;
1776 : BOOL inJob;
1777 : SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
1778 : SID_AND_ATTRIBUTES dropSids[2];
1779 : PTOKEN_PRIVILEGES delPrivs;
1780 :
1781 : ZeroMemory(&si, sizeof(si));
1782 : si.cb = sizeof(si);
1783 :
1784 : /*
1785 : * Set stdin/stdout/stderr handles to be inherited in the child process.
1786 : * That allows postmaster and the processes it starts to perform
1787 : * additional checks to see if running in a service (otherwise they get
1788 : * the default console handles - which point to "somewhere").
1789 : */
1790 : InheritStdHandles(&si);
1791 :
1792 : /* Open the current token to use as a base for the restricted one */
1793 : if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &origToken))
1794 : {
1795 : /*
1796 : * Most Windows targets make DWORD a 32-bit unsigned long, but in case
1797 : * it doesn't cast DWORD before printing.
1798 : */
1799 : write_stderr(_("%s: could not open process token: error code %lu\n"),
1800 : progname, (unsigned long) GetLastError());
1801 : return 0;
1802 : }
1803 :
1804 : /* Allocate list of SIDs to remove */
1805 : ZeroMemory(&dropSids, sizeof(dropSids));
1806 : if (!AllocateAndInitializeSid(&NtAuthority, 2,
1807 : SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0,
1808 : 0, &dropSids[0].Sid) ||
1809 : !AllocateAndInitializeSid(&NtAuthority, 2,
1810 : SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0,
1811 : 0, &dropSids[1].Sid))
1812 : {
1813 : write_stderr(_("%s: could not allocate SIDs: error code %lu\n"),
1814 : progname, (unsigned long) GetLastError());
1815 : return 0;
1816 : }
1817 :
1818 : /* Get list of privileges to remove */
1819 : delPrivs = GetPrivilegesToDelete(origToken);
1820 : if (delPrivs == NULL)
1821 : /* Error message already printed */
1822 : return 0;
1823 :
1824 : b = CreateRestrictedToken(origToken,
1825 : 0,
1826 : sizeof(dropSids) / sizeof(dropSids[0]),
1827 : dropSids,
1828 : delPrivs->PrivilegeCount, delPrivs->Privileges,
1829 : 0, NULL,
1830 : &restrictedToken);
1831 :
1832 : free(delPrivs);
1833 : FreeSid(dropSids[1].Sid);
1834 : FreeSid(dropSids[0].Sid);
1835 : CloseHandle(origToken);
1836 :
1837 : if (!b)
1838 : {
1839 : write_stderr(_("%s: could not create restricted token: error code %lu\n"),
1840 : progname, (unsigned long) GetLastError());
1841 : return 0;
1842 : }
1843 :
1844 : AddUserToTokenDacl(restrictedToken);
1845 : r = CreateProcessAsUser(restrictedToken, NULL, cmd, NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL, &si, processInfo);
1846 :
1847 : if (IsProcessInJob(processInfo->hProcess, NULL, &inJob))
1848 : {
1849 : if (!inJob)
1850 : {
1851 : /*
1852 : * Job objects are working, and the new process isn't in one, so
1853 : * we can create one safely. If any problems show up when setting
1854 : * it, we're going to ignore them.
1855 : */
1856 : HANDLE job;
1857 : char jobname[128];
1858 :
1859 : sprintf(jobname, "PostgreSQL_%lu",
1860 : (unsigned long) processInfo->dwProcessId);
1861 :
1862 : job = CreateJobObject(NULL, jobname);
1863 : if (job)
1864 : {
1865 : JOBOBJECT_BASIC_LIMIT_INFORMATION basicLimit;
1866 : JOBOBJECT_BASIC_UI_RESTRICTIONS uiRestrictions;
1867 : JOBOBJECT_SECURITY_LIMIT_INFORMATION securityLimit;
1868 :
1869 : ZeroMemory(&basicLimit, sizeof(basicLimit));
1870 : ZeroMemory(&uiRestrictions, sizeof(uiRestrictions));
1871 : ZeroMemory(&securityLimit, sizeof(securityLimit));
1872 :
1873 : basicLimit.LimitFlags = JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION | JOB_OBJECT_LIMIT_PRIORITY_CLASS;
1874 : basicLimit.PriorityClass = NORMAL_PRIORITY_CLASS;
1875 : SetInformationJobObject(job, JobObjectBasicLimitInformation, &basicLimit, sizeof(basicLimit));
1876 :
1877 : uiRestrictions.UIRestrictionsClass = JOB_OBJECT_UILIMIT_DESKTOP | JOB_OBJECT_UILIMIT_DISPLAYSETTINGS |
1878 : JOB_OBJECT_UILIMIT_EXITWINDOWS | JOB_OBJECT_UILIMIT_READCLIPBOARD |
1879 : JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS | JOB_OBJECT_UILIMIT_WRITECLIPBOARD;
1880 :
1881 : SetInformationJobObject(job, JobObjectBasicUIRestrictions, &uiRestrictions, sizeof(uiRestrictions));
1882 :
1883 : securityLimit.SecurityLimitFlags = JOB_OBJECT_SECURITY_NO_ADMIN | JOB_OBJECT_SECURITY_ONLY_TOKEN;
1884 : securityLimit.JobToken = restrictedToken;
1885 : SetInformationJobObject(job, JobObjectSecurityLimitInformation, &securityLimit, sizeof(securityLimit));
1886 :
1887 : AssignProcessToJobObject(job, processInfo->hProcess);
1888 : }
1889 : }
1890 : }
1891 :
1892 : CloseHandle(restrictedToken);
1893 :
1894 : ResumeThread(processInfo->hThread);
1895 :
1896 : /*
1897 : * We intentionally don't close the job object handle, because we want the
1898 : * object to live on until pg_ctl shuts down.
1899 : */
1900 : return r;
1901 : }
1902 :
1903 : /*
1904 : * Get a list of privileges to delete from the access token. We delete all privileges
1905 : * except SeLockMemoryPrivilege which is needed to use large pages, and
1906 : * SeChangeNotifyPrivilege which is enabled by default in DISABLE_MAX_PRIVILEGE.
1907 : */
1908 : static PTOKEN_PRIVILEGES
1909 : GetPrivilegesToDelete(HANDLE hToken)
1910 : {
1911 : int i,
1912 : j;
1913 : DWORD length;
1914 : PTOKEN_PRIVILEGES tokenPrivs;
1915 : LUID luidLockPages;
1916 : LUID luidChangeNotify;
1917 :
1918 : if (!LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, &luidLockPages) ||
1919 : !LookupPrivilegeValue(NULL, SE_CHANGE_NOTIFY_NAME, &luidChangeNotify))
1920 : {
1921 : write_stderr(_("%s: could not get LUIDs for privileges: error code %lu\n"),
1922 : progname, (unsigned long) GetLastError());
1923 : return NULL;
1924 : }
1925 :
1926 : if (!GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &length) &&
1927 : GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1928 : {
1929 : write_stderr(_("%s: could not get token information: error code %lu\n"),
1930 : progname, (unsigned long) GetLastError());
1931 : return NULL;
1932 : }
1933 :
1934 : tokenPrivs = (PTOKEN_PRIVILEGES) pg_malloc_extended(length,
1935 : MCXT_ALLOC_NO_OOM);
1936 : if (tokenPrivs == NULL)
1937 : {
1938 : write_stderr(_("%s: out of memory\n"), progname);
1939 : return NULL;
1940 : }
1941 :
1942 : if (!GetTokenInformation(hToken, TokenPrivileges, tokenPrivs, length, &length))
1943 : {
1944 : write_stderr(_("%s: could not get token information: error code %lu\n"),
1945 : progname, (unsigned long) GetLastError());
1946 : free(tokenPrivs);
1947 : return NULL;
1948 : }
1949 :
1950 : for (i = 0; i < tokenPrivs->PrivilegeCount; i++)
1951 : {
1952 : if (memcmp(&tokenPrivs->Privileges[i].Luid, &luidLockPages, sizeof(LUID)) == 0 ||
1953 : memcmp(&tokenPrivs->Privileges[i].Luid, &luidChangeNotify, sizeof(LUID)) == 0)
1954 : {
1955 : for (j = i; j < tokenPrivs->PrivilegeCount - 1; j++)
1956 : tokenPrivs->Privileges[j] = tokenPrivs->Privileges[j + 1];
1957 : tokenPrivs->PrivilegeCount--;
1958 : }
1959 : }
1960 :
1961 : return tokenPrivs;
1962 : }
1963 : #endif /* WIN32 */
1964 :
1965 : static void
1966 2 : do_advice(void)
1967 : {
1968 2 : write_stderr(_("Try \"%s --help\" for more information.\n"), progname);
1969 2 : }
1970 :
1971 :
1972 :
1973 : static void
1974 2 : do_help(void)
1975 : {
1976 2 : printf(_("%s is a utility to initialize, start, stop, or control a PostgreSQL server.\n\n"), progname);
1977 2 : printf(_("Usage:\n"));
1978 2 : printf(_(" %s init[db] [-D DATADIR] [-s] [-o OPTIONS]\n"), progname);
1979 2 : printf(_(" %s start [-D DATADIR] [-l FILENAME] [-W] [-t SECS] [-s]\n"
1980 : " [-o OPTIONS] [-p PATH] [-c]\n"), progname);
1981 2 : printf(_(" %s stop [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]\n"), progname);
1982 2 : printf(_(" %s restart [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]\n"
1983 : " [-o OPTIONS] [-c]\n"), progname);
1984 2 : printf(_(" %s reload [-D DATADIR] [-s]\n"), progname);
1985 2 : printf(_(" %s status [-D DATADIR]\n"), progname);
1986 2 : printf(_(" %s promote [-D DATADIR] [-W] [-t SECS] [-s]\n"), progname);
1987 2 : printf(_(" %s logrotate [-D DATADIR] [-s]\n"), progname);
1988 2 : printf(_(" %s kill SIGNALNAME PID\n"), progname);
1989 : #ifdef WIN32
1990 : printf(_(" %s register [-D DATADIR] [-N SERVICENAME] [-U USERNAME] [-P PASSWORD]\n"
1991 : " [-S START-TYPE] [-e SOURCE] [-W] [-t SECS] [-s] [-o OPTIONS]\n"), progname);
1992 : printf(_(" %s unregister [-N SERVICENAME]\n"), progname);
1993 : #endif
1994 :
1995 2 : printf(_("\nCommon options:\n"));
1996 2 : printf(_(" -D, --pgdata=DATADIR location of the database storage area\n"));
1997 : #ifdef WIN32
1998 : printf(_(" -e SOURCE event source for logging when running as a service\n"));
1999 : #endif
2000 2 : printf(_(" -s, --silent only print errors, no informational messages\n"));
2001 2 : printf(_(" -t, --timeout=SECS seconds to wait when using -w option\n"));
2002 2 : printf(_(" -V, --version output version information, then exit\n"));
2003 2 : printf(_(" -w, --wait wait until operation completes (default)\n"));
2004 2 : printf(_(" -W, --no-wait do not wait until operation completes\n"));
2005 2 : printf(_(" -?, --help show this help, then exit\n"));
2006 2 : printf(_("If the -D option is omitted, the environment variable PGDATA is used.\n"));
2007 :
2008 2 : printf(_("\nOptions for start or restart:\n"));
2009 : #if defined(HAVE_GETRLIMIT)
2010 2 : printf(_(" -c, --core-files allow postgres to produce core files\n"));
2011 : #else
2012 : printf(_(" -c, --core-files not applicable on this platform\n"));
2013 : #endif
2014 2 : printf(_(" -l, --log=FILENAME write (or append) server log to FILENAME\n"));
2015 2 : printf(_(" -o, --options=OPTIONS command line options to pass to postgres\n"
2016 : " (PostgreSQL server executable) or initdb\n"));
2017 2 : printf(_(" -p PATH-TO-POSTGRES normally not necessary\n"));
2018 2 : printf(_("\nOptions for stop or restart:\n"));
2019 2 : printf(_(" -m, --mode=MODE MODE can be \"smart\", \"fast\", or \"immediate\"\n"));
2020 :
2021 2 : printf(_("\nShutdown modes are:\n"));
2022 2 : printf(_(" smart quit after all clients have disconnected\n"));
2023 2 : printf(_(" fast quit directly, with proper shutdown (default)\n"));
2024 2 : printf(_(" immediate quit without complete shutdown; will lead to recovery on restart\n"));
2025 :
2026 2 : printf(_("\nAllowed signal names for kill:\n"));
2027 2 : printf(" ABRT HUP INT KILL QUIT TERM USR1 USR2\n");
2028 :
2029 : #ifdef WIN32
2030 : printf(_("\nOptions for register and unregister:\n"));
2031 : printf(_(" -N SERVICENAME service name with which to register PostgreSQL server\n"));
2032 : printf(_(" -P PASSWORD password of account to register PostgreSQL server\n"));
2033 : printf(_(" -U USERNAME user name of account to register PostgreSQL server\n"));
2034 : printf(_(" -S START-TYPE service start type to register PostgreSQL server\n"));
2035 :
2036 : printf(_("\nStart types are:\n"));
2037 : printf(_(" auto start service automatically during system startup (default)\n"));
2038 : printf(_(" demand start service on demand\n"));
2039 : #endif
2040 :
2041 2 : printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
2042 2 : printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
2043 2 : }
2044 :
2045 :
2046 :
2047 : static void
2048 1294 : set_mode(char *modeopt)
2049 : {
2050 1294 : if (strcmp(modeopt, "s") == 0 || strcmp(modeopt, "smart") == 0)
2051 : {
2052 80 : shutdown_mode = SMART_MODE;
2053 80 : sig = SIGTERM;
2054 : }
2055 1214 : else if (strcmp(modeopt, "f") == 0 || strcmp(modeopt, "fast") == 0)
2056 : {
2057 546 : shutdown_mode = FAST_MODE;
2058 546 : sig = SIGINT;
2059 : }
2060 668 : else if (strcmp(modeopt, "i") == 0 || strcmp(modeopt, "immediate") == 0)
2061 : {
2062 668 : shutdown_mode = IMMEDIATE_MODE;
2063 668 : sig = SIGQUIT;
2064 : }
2065 : else
2066 : {
2067 0 : write_stderr(_("%s: unrecognized shutdown mode \"%s\"\n"), progname, modeopt);
2068 0 : do_advice();
2069 0 : exit(1);
2070 : }
2071 1294 : }
2072 :
2073 :
2074 :
2075 : static void
2076 20 : set_sig(char *signame)
2077 : {
2078 20 : if (strcmp(signame, "HUP") == 0)
2079 0 : sig = SIGHUP;
2080 20 : else if (strcmp(signame, "INT") == 0)
2081 8 : sig = SIGINT;
2082 12 : else if (strcmp(signame, "QUIT") == 0)
2083 4 : sig = SIGQUIT;
2084 8 : else if (strcmp(signame, "ABRT") == 0)
2085 0 : sig = SIGABRT;
2086 8 : else if (strcmp(signame, "KILL") == 0)
2087 8 : sig = SIGKILL;
2088 0 : else if (strcmp(signame, "TERM") == 0)
2089 0 : sig = SIGTERM;
2090 0 : else if (strcmp(signame, "USR1") == 0)
2091 0 : sig = SIGUSR1;
2092 0 : else if (strcmp(signame, "USR2") == 0)
2093 0 : sig = SIGUSR2;
2094 : else
2095 : {
2096 0 : write_stderr(_("%s: unrecognized signal name \"%s\"\n"), progname, signame);
2097 0 : do_advice();
2098 0 : exit(1);
2099 : }
2100 20 : }
2101 :
2102 :
2103 : #ifdef WIN32
2104 : static void
2105 : set_starttype(char *starttypeopt)
2106 : {
2107 : if (strcmp(starttypeopt, "a") == 0 || strcmp(starttypeopt, "auto") == 0)
2108 : pgctl_start_type = SERVICE_AUTO_START;
2109 : else if (strcmp(starttypeopt, "d") == 0 || strcmp(starttypeopt, "demand") == 0)
2110 : pgctl_start_type = SERVICE_DEMAND_START;
2111 : else
2112 : {
2113 : write_stderr(_("%s: unrecognized start type \"%s\"\n"), progname, starttypeopt);
2114 : do_advice();
2115 : exit(1);
2116 : }
2117 : }
2118 : #endif
2119 :
2120 : /*
2121 : * adjust_data_dir
2122 : *
2123 : * If a configuration-only directory was specified, find the real data dir.
2124 : */
2125 : static void
2126 3462 : adjust_data_dir(void)
2127 : {
2128 : char filename[MAXPGPATH];
2129 : char *my_exec_path,
2130 : *cmd;
2131 : FILE *fd;
2132 :
2133 : /* do nothing if we're working without knowledge of data dir */
2134 3462 : if (pg_config == NULL)
2135 3462 : return;
2136 :
2137 : /* If there is no postgresql.conf, it can't be a config-only dir */
2138 3442 : snprintf(filename, sizeof(filename), "%s/postgresql.conf", pg_config);
2139 3442 : if ((fd = fopen(filename, "r")) == NULL)
2140 8 : return;
2141 3434 : fclose(fd);
2142 :
2143 : /* If PG_VERSION exists, it can't be a config-only dir */
2144 3434 : snprintf(filename, sizeof(filename), "%s/PG_VERSION", pg_config);
2145 3434 : if ((fd = fopen(filename, "r")) != NULL)
2146 : {
2147 3434 : fclose(fd);
2148 3434 : return;
2149 : }
2150 :
2151 : /* Must be a configuration directory, so find the data directory */
2152 :
2153 : /* we use a private my_exec_path to avoid interfering with later uses */
2154 0 : if (exec_path == NULL)
2155 0 : my_exec_path = find_other_exec_or_die(argv0, "postgres", PG_BACKEND_VERSIONSTR);
2156 : else
2157 0 : my_exec_path = pg_strdup(exec_path);
2158 :
2159 : /* it's important for -C to be the first option, see main.c */
2160 0 : cmd = psprintf("\"%s\" -C data_directory %s%s",
2161 : my_exec_path,
2162 0 : pgdata_opt ? pgdata_opt : "",
2163 0 : post_opts ? post_opts : "");
2164 0 : fflush(NULL);
2165 :
2166 0 : fd = popen(cmd, "r");
2167 0 : if (fd == NULL || fgets(filename, sizeof(filename), fd) == NULL || pclose(fd) != 0)
2168 : {
2169 0 : write_stderr(_("%s: could not determine the data directory using command \"%s\"\n"), progname, cmd);
2170 0 : exit(1);
2171 : }
2172 0 : free(my_exec_path);
2173 :
2174 : /* strip trailing newline and carriage return */
2175 0 : (void) pg_strip_crlf(filename);
2176 :
2177 0 : free(pg_data);
2178 0 : pg_data = pg_strdup(filename);
2179 0 : canonicalize_path(pg_data);
2180 : }
2181 :
2182 :
2183 : static DBState
2184 610 : get_control_dbstate(void)
2185 : {
2186 : DBState ret;
2187 : bool crc_ok;
2188 610 : ControlFileData *control_file_data = get_controlfile(pg_data, &crc_ok);
2189 :
2190 610 : if (!crc_ok)
2191 : {
2192 0 : write_stderr(_("%s: control file appears to be corrupt\n"), progname);
2193 0 : exit(1);
2194 : }
2195 :
2196 610 : ret = control_file_data->state;
2197 610 : pfree(control_file_data);
2198 610 : return ret;
2199 : }
2200 :
2201 :
2202 : int
2203 3624 : main(int argc, char **argv)
2204 : {
2205 : static struct option long_options[] = {
2206 : {"help", no_argument, NULL, '?'},
2207 : {"version", no_argument, NULL, 'V'},
2208 : {"log", required_argument, NULL, 'l'},
2209 : {"mode", required_argument, NULL, 'm'},
2210 : {"pgdata", required_argument, NULL, 'D'},
2211 : {"options", required_argument, NULL, 'o'},
2212 : {"silent", no_argument, NULL, 's'},
2213 : {"timeout", required_argument, NULL, 't'},
2214 : {"core-files", no_argument, NULL, 'c'},
2215 : {"wait", no_argument, NULL, 'w'},
2216 : {"no-wait", no_argument, NULL, 'W'},
2217 : {NULL, 0, NULL, 0}
2218 : };
2219 :
2220 : char *env_wait;
2221 : int option_index;
2222 : int c;
2223 3624 : pid_t killproc = 0;
2224 :
2225 3624 : pg_logging_init(argv[0]);
2226 3624 : progname = get_progname(argv[0]);
2227 3624 : set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_ctl"));
2228 3624 : start_time = time(NULL);
2229 :
2230 : /*
2231 : * save argv[0] so do_start() can look for the postmaster if necessary. we
2232 : * don't look for postmaster here because in many cases we won't need it.
2233 : */
2234 3624 : argv0 = argv[0];
2235 :
2236 : /* Set restrictive mode mask until PGDATA permissions are checked */
2237 3624 : umask(PG_MODE_MASK_OWNER);
2238 :
2239 : /* support --help and --version even if invoked as root */
2240 3624 : if (argc > 1)
2241 : {
2242 3624 : if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
2243 : {
2244 2 : do_help();
2245 2 : exit(0);
2246 : }
2247 3622 : else if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
2248 : {
2249 158 : puts("pg_ctl (PostgreSQL) " PG_VERSION);
2250 158 : exit(0);
2251 : }
2252 : }
2253 :
2254 : /*
2255 : * Disallow running as root, to forestall any possible security holes.
2256 : */
2257 : #ifndef WIN32
2258 3464 : if (geteuid() == 0)
2259 : {
2260 0 : write_stderr(_("%s: cannot be run as root\n"
2261 : "Please log in (using, e.g., \"su\") as the "
2262 : "(unprivileged) user that will\n"
2263 : "own the server process.\n"),
2264 : progname);
2265 0 : exit(1);
2266 : }
2267 : #endif
2268 :
2269 3464 : env_wait = getenv("PGCTLTIMEOUT");
2270 3464 : if (env_wait != NULL)
2271 0 : wait_seconds = atoi(env_wait);
2272 :
2273 : /* process command-line options */
2274 13224 : while ((c = getopt_long(argc, argv, "cD:e:l:m:N:o:p:P:sS:t:U:wW",
2275 13224 : long_options, &option_index)) != -1)
2276 : {
2277 9762 : switch (c)
2278 : {
2279 3442 : case 'D':
2280 : {
2281 : char *pgdata_D;
2282 :
2283 3442 : pgdata_D = pg_strdup(optarg);
2284 3442 : canonicalize_path(pgdata_D);
2285 3442 : setenv("PGDATA", pgdata_D, 1);
2286 :
2287 : /*
2288 : * We could pass PGDATA just in an environment variable
2289 : * but we do -D too for clearer postmaster 'ps' display
2290 : */
2291 3442 : pgdata_opt = psprintf("-D \"%s\" ", pgdata_D);
2292 3442 : free(pgdata_D);
2293 3442 : break;
2294 : }
2295 0 : case 'e':
2296 0 : event_source = pg_strdup(optarg);
2297 0 : break;
2298 1640 : case 'l':
2299 1640 : log_file = pg_strdup(optarg);
2300 1640 : break;
2301 1294 : case 'm':
2302 1294 : set_mode(optarg);
2303 1294 : break;
2304 0 : case 'N':
2305 0 : register_servicename = pg_strdup(optarg);
2306 0 : break;
2307 1504 : case 'o':
2308 : /* append option? */
2309 1504 : if (!post_opts)
2310 1424 : post_opts = pg_strdup(optarg);
2311 : else
2312 : {
2313 80 : char *old_post_opts = post_opts;
2314 :
2315 80 : post_opts = psprintf("%s %s", old_post_opts, optarg);
2316 80 : free(old_post_opts);
2317 : }
2318 1504 : break;
2319 0 : case 'p':
2320 0 : exec_path = pg_strdup(optarg);
2321 0 : break;
2322 0 : case 'P':
2323 0 : register_password = pg_strdup(optarg);
2324 0 : break;
2325 246 : case 's':
2326 246 : silent_mode = true;
2327 246 : break;
2328 0 : case 'S':
2329 : #ifdef WIN32
2330 : set_starttype(optarg);
2331 : #else
2332 0 : write_stderr(_("%s: -S option not supported on this platform\n"),
2333 : progname);
2334 0 : exit(1);
2335 : #endif
2336 : break;
2337 2 : case 't':
2338 2 : wait_seconds = atoi(optarg);
2339 2 : wait_seconds_arg = true;
2340 2 : break;
2341 0 : case 'U':
2342 0 : if (strchr(optarg, '\\'))
2343 0 : register_username = pg_strdup(optarg);
2344 : else
2345 : /* Prepend .\ for local accounts */
2346 0 : register_username = psprintf(".\\%s", optarg);
2347 0 : break;
2348 1630 : case 'w':
2349 1630 : do_wait = true;
2350 1630 : break;
2351 2 : case 'W':
2352 2 : do_wait = false;
2353 2 : break;
2354 0 : case 'c':
2355 0 : allow_core_files = true;
2356 0 : break;
2357 2 : default:
2358 : /* getopt_long already issued a suitable error message */
2359 2 : do_advice();
2360 2 : exit(1);
2361 : }
2362 : }
2363 :
2364 : /* Process an action */
2365 3462 : if (optind < argc)
2366 : {
2367 3462 : if (strcmp(argv[optind], "init") == 0
2368 3462 : || strcmp(argv[optind], "initdb") == 0)
2369 2 : ctl_command = INIT_COMMAND;
2370 3460 : else if (strcmp(argv[optind], "start") == 0)
2371 1356 : ctl_command = START_COMMAND;
2372 2104 : else if (strcmp(argv[optind], "stop") == 0)
2373 1524 : ctl_command = STOP_COMMAND;
2374 580 : else if (strcmp(argv[optind], "restart") == 0)
2375 236 : ctl_command = RESTART_COMMAND;
2376 344 : else if (strcmp(argv[optind], "reload") == 0)
2377 226 : ctl_command = RELOAD_COMMAND;
2378 118 : else if (strcmp(argv[optind], "status") == 0)
2379 6 : ctl_command = STATUS_COMMAND;
2380 112 : else if (strcmp(argv[optind], "promote") == 0)
2381 90 : ctl_command = PROMOTE_COMMAND;
2382 22 : else if (strcmp(argv[optind], "logrotate") == 0)
2383 2 : ctl_command = LOGROTATE_COMMAND;
2384 20 : else if (strcmp(argv[optind], "kill") == 0)
2385 : {
2386 20 : if (argc - optind < 3)
2387 : {
2388 0 : write_stderr(_("%s: missing arguments for kill mode\n"), progname);
2389 0 : do_advice();
2390 0 : exit(1);
2391 : }
2392 20 : ctl_command = KILL_COMMAND;
2393 20 : set_sig(argv[++optind]);
2394 20 : killproc = atol(argv[++optind]);
2395 : }
2396 : #ifdef WIN32
2397 : else if (strcmp(argv[optind], "register") == 0)
2398 : ctl_command = REGISTER_COMMAND;
2399 : else if (strcmp(argv[optind], "unregister") == 0)
2400 : ctl_command = UNREGISTER_COMMAND;
2401 : else if (strcmp(argv[optind], "runservice") == 0)
2402 : ctl_command = RUN_AS_SERVICE_COMMAND;
2403 : #endif
2404 : else
2405 : {
2406 0 : write_stderr(_("%s: unrecognized operation mode \"%s\"\n"), progname, argv[optind]);
2407 0 : do_advice();
2408 0 : exit(1);
2409 : }
2410 3462 : optind++;
2411 : }
2412 :
2413 3462 : if (optind < argc)
2414 : {
2415 0 : write_stderr(_("%s: too many command-line arguments (first is \"%s\")\n"), progname, argv[optind]);
2416 0 : do_advice();
2417 0 : exit(1);
2418 : }
2419 :
2420 3462 : if (ctl_command == NO_COMMAND)
2421 : {
2422 0 : write_stderr(_("%s: no operation specified\n"), progname);
2423 0 : do_advice();
2424 0 : exit(1);
2425 : }
2426 :
2427 : /* Note we put any -D switch into the env var above */
2428 3462 : pg_config = getenv("PGDATA");
2429 3462 : if (pg_config)
2430 : {
2431 3442 : pg_config = pg_strdup(pg_config);
2432 3442 : canonicalize_path(pg_config);
2433 3442 : pg_data = pg_strdup(pg_config);
2434 : }
2435 :
2436 : /* -D might point at config-only directory; if so find the real PGDATA */
2437 3462 : adjust_data_dir();
2438 :
2439 : /* Complain if -D needed and not provided */
2440 3462 : if (pg_config == NULL &&
2441 20 : ctl_command != KILL_COMMAND && ctl_command != UNREGISTER_COMMAND)
2442 : {
2443 0 : write_stderr(_("%s: no database directory specified and environment variable PGDATA unset\n"),
2444 : progname);
2445 0 : do_advice();
2446 0 : exit(1);
2447 : }
2448 :
2449 3462 : if (ctl_command == RELOAD_COMMAND)
2450 : {
2451 226 : sig = SIGHUP;
2452 226 : do_wait = false;
2453 : }
2454 :
2455 3462 : if (pg_data)
2456 : {
2457 3442 : snprintf(postopts_file, MAXPGPATH, "%s/postmaster.opts", pg_data);
2458 3442 : snprintf(version_file, MAXPGPATH, "%s/PG_VERSION", pg_data);
2459 3442 : snprintf(pid_file, MAXPGPATH, "%s/postmaster.pid", pg_data);
2460 :
2461 : /*
2462 : * Set mask based on PGDATA permissions,
2463 : *
2464 : * Don't error here if the data directory cannot be stat'd. This is
2465 : * handled differently based on the command and we don't want to
2466 : * interfere with that logic.
2467 : */
2468 3442 : if (GetDataDirectoryCreatePerm(pg_data))
2469 3434 : umask(pg_mode_mask);
2470 : }
2471 :
2472 3462 : switch (ctl_command)
2473 : {
2474 2 : case INIT_COMMAND:
2475 2 : do_init();
2476 2 : break;
2477 6 : case STATUS_COMMAND:
2478 6 : do_status();
2479 2 : break;
2480 1356 : case START_COMMAND:
2481 1356 : do_start();
2482 1338 : break;
2483 1524 : case STOP_COMMAND:
2484 1524 : do_stop();
2485 1522 : break;
2486 236 : case RESTART_COMMAND:
2487 236 : do_restart();
2488 228 : break;
2489 226 : case RELOAD_COMMAND:
2490 226 : do_reload();
2491 226 : break;
2492 90 : case PROMOTE_COMMAND:
2493 90 : do_promote();
2494 84 : break;
2495 2 : case LOGROTATE_COMMAND:
2496 2 : do_logrotate();
2497 2 : break;
2498 20 : case KILL_COMMAND:
2499 20 : do_kill(killproc);
2500 20 : break;
2501 : #ifdef WIN32
2502 : case REGISTER_COMMAND:
2503 : pgwin32_doRegister();
2504 : break;
2505 : case UNREGISTER_COMMAND:
2506 : pgwin32_doUnregister();
2507 : break;
2508 : case RUN_AS_SERVICE_COMMAND:
2509 : pgwin32_doRunAsService();
2510 : break;
2511 : #endif
2512 0 : default:
2513 0 : break;
2514 : }
2515 :
2516 3424 : exit(0);
2517 : }
|