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