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