OSDN Git Service

Make it reasonably safe to use pg_ctl to start the postmaster from a boot-time
[pg-rex/syncrep.git] / src / bin / pg_ctl / pg_ctl.c
1 /*-------------------------------------------------------------------------
2  *
3  * pg_ctl --- start/stops/restarts the PostgreSQL server
4  *
5  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
6  *
7  * $PostgreSQL: pgsql/src/bin/pg_ctl/pg_ctl.c,v 1.112 2009/08/27 16:59:38 tgl Exp $
8  *
9  *-------------------------------------------------------------------------
10  */
11
12 #ifdef WIN32
13 /*
14  * Need this to get defines for restricted tokens and jobs. And it
15  * has to be set before any header from the Win32 API is loaded.
16  */
17 #define _WIN32_WINNT 0x0500
18 #endif
19
20 #include "postgres_fe.h"
21 #include "libpq-fe.h"
22
23 #include <locale.h>
24 #include <signal.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <unistd.h>
28
29 #ifdef HAVE_SYS_RESOURCE_H
30 #include <sys/time.h>
31 #include <sys/resource.h>
32 #endif
33
34 #include "libpq/pqsignal.h"
35 #include "getopt_long.h"
36 #include "miscadmin.h"
37
38 #if defined(__CYGWIN__)
39 #include <sys/cygwin.h>
40 #include <windows.h>
41 /* Cygwin defines WIN32 in windows.h, but we don't want it. */
42 #undef WIN32
43 #endif
44
45 /* PID can be negative for standalone backend */
46 typedef long pgpid_t;
47
48
49 typedef enum
50 {
51         SMART_MODE,
52         FAST_MODE,
53         IMMEDIATE_MODE
54 } ShutdownMode;
55
56
57 typedef enum
58 {
59         NO_COMMAND = 0,
60         START_COMMAND,
61         STOP_COMMAND,
62         RESTART_COMMAND,
63         RELOAD_COMMAND,
64         STATUS_COMMAND,
65         KILL_COMMAND,
66         REGISTER_COMMAND,
67         UNREGISTER_COMMAND,
68         RUN_AS_SERVICE_COMMAND
69 } CtlCommand;
70
71 #define DEFAULT_WAIT    60
72
73 static bool do_wait = false;
74 static bool wait_set = false;
75 static int      wait_seconds = DEFAULT_WAIT;
76 static bool silent_mode = false;
77 static ShutdownMode shutdown_mode = SMART_MODE;
78 static int      sig = SIGTERM;          /* default */
79 static CtlCommand ctl_command = NO_COMMAND;
80 static char *pg_data = NULL;
81 static char *pgdata_opt = NULL;
82 static char *post_opts = NULL;
83 static const char *progname;
84 static char *log_file = NULL;
85 static char *postgres_path = NULL;
86 static char *register_servicename = "PostgreSQL";               /* FIXME: + version ID? */
87 static char *register_username = NULL;
88 static char *register_password = NULL;
89 static char *argv0 = NULL;
90 static bool allow_core_files = false;
91
92 static void
93 write_stderr(const char *fmt,...)
94 /* This extension allows gcc to check the format string for consistency with
95    the supplied arguments. */
96 __attribute__((format(printf, 1, 2)));
97 static void *pg_malloc(size_t size);
98 static char *xstrdup(const char *s);
99 static void do_advice(void);
100 static void do_help(void);
101 static void set_mode(char *modeopt);
102 static void set_sig(char *signame);
103 static void do_start(void);
104 static void do_stop(void);
105 static void do_restart(void);
106 static void do_reload(void);
107 static void do_status(void);
108 static void do_kill(pgpid_t pid);
109 static void print_msg(const char *msg);
110
111 #if defined(WIN32) || defined(__CYGWIN__)
112 static bool pgwin32_IsInstalled(SC_HANDLE);
113 static char *pgwin32_CommandLine(bool);
114 static void pgwin32_doRegister(void);
115 static void pgwin32_doUnregister(void);
116 static void pgwin32_SetServiceStatus(DWORD);
117 static void WINAPI pgwin32_ServiceHandler(DWORD);
118 static void WINAPI pgwin32_ServiceMain(DWORD, LPTSTR *);
119 static void pgwin32_doRunAsService(void);
120 static int      CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo, bool as_service);
121
122 static SERVICE_STATUS status;
123 static SERVICE_STATUS_HANDLE hStatus = (SERVICE_STATUS_HANDLE) 0;
124 static HANDLE shutdownHandles[2];
125 static pid_t postmasterPID = -1;
126
127 #define shutdownEvent     shutdownHandles[0]
128 #define postmasterProcess shutdownHandles[1]
129 #endif
130
131 static pgpid_t get_pgpid(void);
132 static char **readfile(const char *path);
133 static int      start_postmaster(void);
134 static void read_post_opts(void);
135
136 static bool test_postmaster_connection(bool);
137 static bool postmaster_is_alive(pid_t pid);
138
139 static char postopts_file[MAXPGPATH];
140 static char pid_file[MAXPGPATH];
141 static char conf_file[MAXPGPATH];
142 static char backup_file[MAXPGPATH];
143
144 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
145 static void unlimit_core_size(void);
146 #endif
147
148
149 #if defined(WIN32) || defined(__CYGWIN__)
150 static void
151 write_eventlog(int level, const char *line)
152 {
153         static HANDLE evtHandle = INVALID_HANDLE_VALUE;
154
155         if (evtHandle == INVALID_HANDLE_VALUE)
156         {
157                 evtHandle = RegisterEventSource(NULL, "PostgreSQL");
158                 if (evtHandle == NULL)
159                 {
160                         evtHandle = INVALID_HANDLE_VALUE;
161                         return;
162                 }
163         }
164
165         ReportEvent(evtHandle,
166                                 level,
167                                 0,
168                                 0,                              /* All events are Id 0 */
169                                 NULL,
170                                 1,
171                                 0,
172                                 &line,
173                                 NULL);
174 }
175 #endif
176
177 /*
178  * Write errors to stderr (or by equal means when stderr is
179  * not available).
180  */
181 static void
182 write_stderr(const char *fmt,...)
183 {
184         va_list         ap;
185
186         va_start(ap, fmt);
187 #if !defined(WIN32) && !defined(__CYGWIN__)
188         /* On Unix, we just fprintf to stderr */
189         vfprintf(stderr, fmt, ap);
190 #else
191
192         /*
193          * On Win32, we print to stderr if running on a console, or write to
194          * eventlog if running as a service
195          */
196         if (!isatty(fileno(stderr)))    /* Running as a service */
197         {
198                 char            errbuf[2048];           /* Arbitrary size? */
199
200                 vsnprintf(errbuf, sizeof(errbuf), fmt, ap);
201
202                 write_eventlog(EVENTLOG_ERROR_TYPE, errbuf);
203         }
204         else
205                 /* Not running as service, write to stderr */
206                 vfprintf(stderr, fmt, ap);
207 #endif
208         va_end(ap);
209 }
210
211 /*
212  * routines to check memory allocations and fail noisily.
213  */
214
215 static void *
216 pg_malloc(size_t size)
217 {
218         void       *result;
219
220         result = malloc(size);
221         if (!result)
222         {
223                 write_stderr(_("%s: out of memory\n"), progname);
224                 exit(1);
225         }
226         return result;
227 }
228
229
230 static char *
231 xstrdup(const char *s)
232 {
233         char       *result;
234
235         result = strdup(s);
236         if (!result)
237         {
238                 write_stderr(_("%s: out of memory\n"), progname);
239                 exit(1);
240         }
241         return result;
242 }
243
244 /*
245  * Given an already-localized string, print it to stdout unless the
246  * user has specified that no messages should be printed.
247  */
248 static void
249 print_msg(const char *msg)
250 {
251         if (!silent_mode)
252         {
253                 fputs(msg, stdout);
254                 fflush(stdout);
255         }
256 }
257
258 static pgpid_t
259 get_pgpid(void)
260 {
261         FILE       *pidf;
262         long            pid;
263
264         pidf = fopen(pid_file, "r");
265         if (pidf == NULL)
266         {
267                 /* No pid file, not an error on startup */
268                 if (errno == ENOENT)
269                         return 0;
270                 else
271                 {
272                         write_stderr(_("%s: could not open PID file \"%s\": %s\n"),
273                                                  progname, pid_file, strerror(errno));
274                         exit(1);
275                 }
276         }
277         if (fscanf(pidf, "%ld", &pid) != 1)
278         {
279                 write_stderr(_("%s: invalid data in PID file \"%s\"\n"),
280                                          progname, pid_file);
281                 exit(1);
282         }
283         fclose(pidf);
284         return (pgpid_t) pid;
285 }
286
287
288 /*
289  * get the lines from a text file - return NULL if file can't be opened
290  */
291 static char **
292 readfile(const char *path)
293 {
294         FILE       *infile;
295         int                     maxlength = 0,
296                                 linelen = 0;
297         int                     nlines = 0;
298         char      **result;
299         char       *buffer;
300         int                     c;
301
302         if ((infile = fopen(path, "r")) == NULL)
303                 return NULL;
304
305         /* pass over the file twice - the first time to size the result */
306
307         while ((c = fgetc(infile)) != EOF)
308         {
309                 linelen++;
310                 if (c == '\n')
311                 {
312                         nlines++;
313                         if (linelen > maxlength)
314                                 maxlength = linelen;
315                         linelen = 0;
316                 }
317         }
318
319         /* handle last line without a terminating newline (yuck) */
320         if (linelen)
321                 nlines++;
322         if (linelen > maxlength)
323                 maxlength = linelen;
324
325         /* set up the result and the line buffer */
326         result = (char **) pg_malloc((nlines + 1) * sizeof(char *));
327         buffer = (char *) pg_malloc(maxlength + 1);
328
329         /* now reprocess the file and store the lines */
330         rewind(infile);
331         nlines = 0;
332         while (fgets(buffer, maxlength + 1, infile) != NULL)
333                 result[nlines++] = xstrdup(buffer);
334
335         fclose(infile);
336         free(buffer);
337         result[nlines] = NULL;
338
339         return result;
340 }
341
342
343
344 /*
345  * start/test/stop routines
346  */
347
348 static int
349 start_postmaster(void)
350 {
351         char            cmd[MAXPGPATH];
352
353 #ifndef WIN32
354
355         /*
356          * Since there might be quotes to handle here, it is easier simply to pass
357          * everything to a shell to process them.
358          */
359         if (log_file != NULL)
360                 snprintf(cmd, MAXPGPATH, SYSTEMQUOTE "\"%s\" %s%s < \"%s\" >> \"%s\" 2>&1 &" SYSTEMQUOTE,
361                                  postgres_path, pgdata_opt, post_opts,
362                                  DEVNULL, log_file);
363         else
364                 snprintf(cmd, MAXPGPATH, SYSTEMQUOTE "\"%s\" %s%s < \"%s\" 2>&1 &" SYSTEMQUOTE,
365                                  postgres_path, pgdata_opt, post_opts, DEVNULL);
366
367         return system(cmd);
368 #else                                                   /* WIN32 */
369
370         /*
371          * On win32 we don't use system(). So we don't need to use & (which would
372          * be START /B on win32). However, we still call the shell (CMD.EXE) with
373          * it to handle redirection etc.
374          */
375         PROCESS_INFORMATION pi;
376
377         if (log_file != NULL)
378                 snprintf(cmd, MAXPGPATH, "CMD /C " SYSTEMQUOTE "\"%s\" %s%s < \"%s\" >> \"%s\" 2>&1" SYSTEMQUOTE,
379                                  postgres_path, pgdata_opt, post_opts, DEVNULL, log_file);
380         else
381                 snprintf(cmd, MAXPGPATH, "CMD /C " SYSTEMQUOTE "\"%s\" %s%s < \"%s\" 2>&1" SYSTEMQUOTE,
382                                  postgres_path, pgdata_opt, post_opts, DEVNULL);
383
384         if (!CreateRestrictedProcess(cmd, &pi, false))
385                 return GetLastError();
386         CloseHandle(pi.hProcess);
387         CloseHandle(pi.hThread);
388         return 0;
389 #endif   /* WIN32 */
390 }
391
392
393
394 /*
395  * Find the pgport and try a connection
396  * Note that the checkpoint parameter enables a Windows service control
397  * manager checkpoint, it's got nothing to do with database checkpoints!!
398  */
399 static bool
400 test_postmaster_connection(bool do_checkpoint)
401 {
402         PGconn     *conn;
403         bool            success = false;
404         int                     i;
405         char            portstr[32];
406         char       *p;
407         char       *q;
408         char            connstr[128];   /* Should be way more than enough! */
409
410         *portstr = '\0';
411
412         /*
413          * Look in post_opts for a -p switch.
414          *
415          * This parsing code is not amazingly bright; it could for instance get
416          * fooled if ' -p' occurs within a quoted argument value.  Given that few
417          * people pass complicated settings in post_opts, it's probably good
418          * enough.
419          */
420         for (p = post_opts; *p;)
421         {
422                 /* advance past whitespace */
423                 while (isspace((unsigned char) *p))
424                         p++;
425
426                 if (strncmp(p, "-p", 2) == 0)
427                 {
428                         p += 2;
429                         /* advance past any whitespace/quoting */
430                         while (isspace((unsigned char) *p) || *p == '\'' || *p == '"')
431                                 p++;
432                         /* find end of value (not including any ending quote!) */
433                         q = p;
434                         while (*q &&
435                                    !(isspace((unsigned char) *q) || *q == '\'' || *q == '"'))
436                                 q++;
437                         /* and save the argument value */
438                         strlcpy(portstr, p, Min((q - p) + 1, sizeof(portstr)));
439                         /* keep looking, maybe there is another -p */
440                         p = q;
441                 }
442                 /* Advance to next whitespace */
443                 while (*p && !isspace((unsigned char) *p))
444                         p++;
445         }
446
447         /*
448          * Search config file for a 'port' option.
449          *
450          * This parsing code isn't amazingly bright either, but it should be okay
451          * for valid port settings.
452          */
453         if (!*portstr)
454         {
455                 char      **optlines;
456
457                 optlines = readfile(conf_file);
458                 if (optlines != NULL)
459                 {
460                         for (; *optlines != NULL; optlines++)
461                         {
462                                 p = *optlines;
463
464                                 while (isspace((unsigned char) *p))
465                                         p++;
466                                 if (strncmp(p, "port", 4) != 0)
467                                         continue;
468                                 p += 4;
469                                 while (isspace((unsigned char) *p))
470                                         p++;
471                                 if (*p != '=')
472                                         continue;
473                                 p++;
474                                 /* advance past any whitespace/quoting */
475                                 while (isspace((unsigned char) *p) || *p == '\'' || *p == '"')
476                                         p++;
477                                 /* find end of value (not including any ending quote/comment!) */
478                                 q = p;
479                                 while (*q &&
480                                            !(isspace((unsigned char) *q) ||
481                                                  *q == '\'' || *q == '"' || *q == '#'))
482                                         q++;
483                                 /* and save the argument value */
484                                 strlcpy(portstr, p, Min((q - p) + 1, sizeof(portstr)));
485                                 /* keep looking, maybe there is another */
486                         }
487                 }
488         }
489
490         /* Check environment */
491         if (!*portstr && getenv("PGPORT") != NULL)
492                 strlcpy(portstr, getenv("PGPORT"), sizeof(portstr));
493
494         /* Else use compiled-in default */
495         if (!*portstr)
496                 snprintf(portstr, sizeof(portstr), "%d", DEF_PGPORT);
497
498         /*
499          * We need to set a connect timeout otherwise on Windows the SCM will
500          * probably timeout first
501          */
502         snprintf(connstr, sizeof(connstr),
503                          "dbname=postgres port=%s connect_timeout=5", portstr);
504
505         for (i = 0; i < wait_seconds; i++)
506         {
507                 if ((conn = PQconnectdb(connstr)) != NULL &&
508                         (PQstatus(conn) == CONNECTION_OK ||
509                          PQconnectionNeedsPassword(conn)))
510                 {
511                         PQfinish(conn);
512                         success = true;
513                         break;
514                 }
515                 else
516                 {
517                         PQfinish(conn);
518
519 #if defined(WIN32)
520                         if (do_checkpoint)
521                         {
522                                 /*
523                                  * Increment the wait hint by 6 secs (connection timeout +
524                                  * sleep) We must do this to indicate to the SCM that our
525                                  * startup time is changing, otherwise it'll usually send a
526                                  * stop signal after 20 seconds, despite incrementing the
527                                  * checkpoint counter.
528                                  */
529                                 status.dwWaitHint += 6000;
530                                 status.dwCheckPoint++;
531                                 SetServiceStatus(hStatus, (LPSERVICE_STATUS) &status);
532                         }
533
534                         else
535 #endif
536                                 print_msg(".");
537
538                         pg_usleep(1000000); /* 1 sec */
539                 }
540         }
541
542         return success;
543 }
544
545
546 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
547 static void
548 unlimit_core_size(void)
549 {
550         struct rlimit lim;
551
552         getrlimit(RLIMIT_CORE, &lim);
553         if (lim.rlim_max == 0)
554         {
555                 write_stderr(_("%s: cannot set core file size limit; disallowed by hard limit\n"),
556                                          progname);
557                 return;
558         }
559         else if (lim.rlim_max == RLIM_INFINITY || lim.rlim_cur < lim.rlim_max)
560         {
561                 lim.rlim_cur = lim.rlim_max;
562                 setrlimit(RLIMIT_CORE, &lim);
563         }
564 }
565 #endif
566
567 static void
568 read_post_opts(void)
569 {
570         if (post_opts == NULL)
571         {
572                 post_opts = "";                 /* default */
573                 if (ctl_command == RESTART_COMMAND)
574                 {
575                         char      **optlines;
576
577                         optlines = readfile(postopts_file);
578                         if (optlines == NULL)
579                         {
580                                 write_stderr(_("%s: could not read file \"%s\"\n"), progname, postopts_file);
581                                 exit(1);
582                         }
583                         else if (optlines[0] == NULL || optlines[1] != NULL)
584                         {
585                                 write_stderr(_("%s: option file \"%s\" must have exactly one line\n"),
586                                                          progname, postopts_file);
587                                 exit(1);
588                         }
589                         else
590                         {
591                                 int                     len;
592                                 char       *optline;
593                                 char       *arg1;
594
595                                 optline = optlines[0];
596                                 /* trim off line endings */
597                                 len = strcspn(optline, "\r\n");
598                                 optline[len] = '\0';
599
600                                 /*
601                                  * Are we at the first option, as defined by space and
602                                  * double-quote?
603                                  */
604                                 if ((arg1 = strstr(optline, " \"")) != NULL)
605                                 {
606                                         *arg1 = '\0';           /* terminate so we get only program
607                                                                                  * name */
608                                         post_opts = arg1 + 1;           /* point past whitespace */
609                                 }
610                                 if (postgres_path == NULL)
611                                         postgres_path = optline;
612                         }
613                 }
614         }
615 }
616
617 static void
618 do_start(void)
619 {
620         pgpid_t         pid;
621         pgpid_t         old_pid = 0;
622         int                     exitcode;
623
624         if (ctl_command != RESTART_COMMAND)
625         {
626                 old_pid = get_pgpid();
627                 if (old_pid != 0)
628                         write_stderr(_("%s: another server might be running; "
629                                                    "trying to start server anyway\n"),
630                                                  progname);
631         }
632
633         read_post_opts();
634
635         /* No -D or -D already added during server start */
636         if (ctl_command == RESTART_COMMAND || pgdata_opt == NULL)
637                 pgdata_opt = "";
638
639         if (postgres_path == NULL)
640         {
641                 char       *postmaster_path;
642                 int                     ret;
643
644                 postmaster_path = pg_malloc(MAXPGPATH);
645
646                 if ((ret = find_other_exec(argv0, "postgres", PG_BACKEND_VERSIONSTR,
647                                                                    postmaster_path)) < 0)
648                 {
649                         char            full_path[MAXPGPATH];
650
651                         if (find_my_exec(argv0, full_path) < 0)
652                                 strlcpy(full_path, progname, sizeof(full_path));
653
654                         if (ret == -1)
655                                 write_stderr(_("The program \"postgres\" is needed by %s "
656                                                            "but was not found in the\n"
657                                                            "same directory as \"%s\".\n"
658                                                            "Check your installation.\n"),
659                                                          progname, full_path);
660                         else
661                                 write_stderr(_("The program \"postgres\" was found by \"%s\"\n"
662                                                            "but was not the same version as %s.\n"
663                                                            "Check your installation.\n"),
664                                                          full_path, progname);
665                         exit(1);
666                 }
667                 postgres_path = postmaster_path;
668         }
669
670 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
671         if (allow_core_files)
672                 unlimit_core_size();
673 #endif
674
675         /*
676          * If possible, tell the postmaster our parent shell's PID (see the
677          * comments in CreateLockFile() for motivation).  Windows hasn't got
678          * getppid() unfortunately.
679          */
680 #ifndef WIN32
681         {
682                 static char env_var[32];
683
684                 snprintf(env_var, sizeof(env_var), "PG_GRANDPARENT_PID=%d",
685                                  (int) getppid());
686                 putenv(env_var);
687         }
688 #endif
689
690         exitcode = start_postmaster();
691         if (exitcode != 0)
692         {
693                 write_stderr(_("%s: could not start server: exit code was %d\n"),
694                                          progname, exitcode);
695                 exit(1);
696         }
697
698         if (old_pid != 0)
699         {
700                 pg_usleep(1000000);
701                 pid = get_pgpid();
702                 if (pid == old_pid)
703                 {
704                         write_stderr(_("%s: could not start server\n"
705                                                    "Examine the log output.\n"),
706                                                  progname);
707                         exit(1);
708                 }
709         }
710
711         if (do_wait)
712         {
713                 print_msg(_("waiting for server to start..."));
714
715                 if (test_postmaster_connection(false) == false)
716                 {
717                         printf(_("could not start server\n"));
718                         exit(1);
719                 }
720                 else
721                 {
722                         print_msg(_(" done\n"));
723                         print_msg(_("server started\n"));
724                 }
725         }
726         else
727                 print_msg(_("server starting\n"));
728 }
729
730
731 static void
732 do_stop(void)
733 {
734         int                     cnt;
735         pgpid_t         pid;
736         struct stat statbuf;
737
738         pid = get_pgpid();
739
740         if (pid == 0)                           /* no pid file */
741         {
742                 write_stderr(_("%s: PID file \"%s\" does not exist\n"), progname, pid_file);
743                 write_stderr(_("Is server running?\n"));
744                 exit(1);
745         }
746         else if (pid < 0)                       /* standalone backend, not postmaster */
747         {
748                 pid = -pid;
749                 write_stderr(_("%s: cannot stop server; "
750                                            "single-user server is running (PID: %ld)\n"),
751                                          progname, pid);
752                 exit(1);
753         }
754
755         if (kill((pid_t) pid, sig) != 0)
756         {
757                 write_stderr(_("%s: could not send stop signal (PID: %ld): %s\n"), progname, pid,
758                                          strerror(errno));
759                 exit(1);
760         }
761
762         if (!do_wait)
763         {
764                 print_msg(_("server shutting down\n"));
765                 return;
766         }
767         else
768         {
769                 if ((shutdown_mode == SMART_MODE) && (stat(backup_file, &statbuf) == 0))
770                 {
771                         print_msg(_("WARNING: online backup mode is active\n"
772                                                 "Shutdown will not complete until pg_stop_backup() is called.\n\n"));
773                 }
774
775                 print_msg(_("waiting for server to shut down..."));
776
777                 for (cnt = 0; cnt < wait_seconds; cnt++)
778                 {
779                         if ((pid = get_pgpid()) != 0)
780                         {
781                                 print_msg(".");
782                                 pg_usleep(1000000);             /* 1 sec */
783                         }
784                         else
785                                 break;
786                 }
787
788                 if (pid != 0)                   /* pid file still exists */
789                 {
790                         print_msg(_(" failed\n"));
791
792                         write_stderr(_("%s: server does not shut down\n"), progname);
793                         exit(1);
794                 }
795                 print_msg(_(" done\n"));
796
797                 printf(_("server stopped\n"));
798         }
799 }
800
801
802 /*
803  *      restart/reload routines
804  */
805
806 static void
807 do_restart(void)
808 {
809         int                     cnt;
810         pgpid_t         pid;
811         struct stat statbuf;
812
813         pid = get_pgpid();
814
815         if (pid == 0)                           /* no pid file */
816         {
817                 write_stderr(_("%s: PID file \"%s\" does not exist\n"),
818                                          progname, pid_file);
819                 write_stderr(_("Is server running?\n"));
820                 write_stderr(_("starting server anyway\n"));
821                 do_start();
822                 return;
823         }
824         else if (pid < 0)                       /* standalone backend, not postmaster */
825         {
826                 pid = -pid;
827                 if (postmaster_is_alive((pid_t) pid))
828                 {
829                         write_stderr(_("%s: cannot restart server; "
830                                                    "single-user server is running (PID: %ld)\n"),
831                                                  progname, pid);
832                         write_stderr(_("Please terminate the single-user server and try again.\n"));
833                         exit(1);
834                 }
835         }
836
837         if (postmaster_is_alive((pid_t) pid))
838         {
839                 if (kill((pid_t) pid, sig) != 0)
840                 {
841                         write_stderr(_("%s: could not send stop signal (PID: %ld): %s\n"), progname, pid,
842                                                  strerror(errno));
843                         exit(1);
844                 }
845
846                 if ((shutdown_mode == SMART_MODE) && (stat(backup_file, &statbuf) == 0))
847                 {
848                         print_msg(_("WARNING: online backup mode is active\n"
849                                                 "Shutdown will not complete until pg_stop_backup() is called.\n\n"));
850                 }
851
852                 print_msg(_("waiting for server to shut down..."));
853
854                 /* always wait for restart */
855
856                 for (cnt = 0; cnt < wait_seconds; cnt++)
857                 {
858                         if ((pid = get_pgpid()) != 0)
859                         {
860                                 print_msg(".");
861                                 pg_usleep(1000000);             /* 1 sec */
862                         }
863                         else
864                                 break;
865                 }
866
867                 if (pid != 0)                   /* pid file still exists */
868                 {
869                         print_msg(_(" failed\n"));
870
871                         write_stderr(_("%s: server does not shut down\n"), progname);
872                         exit(1);
873                 }
874
875                 print_msg(_(" done\n"));
876                 printf(_("server stopped\n"));
877         }
878         else
879         {
880                 write_stderr(_("%s: old server process (PID: %ld) seems to be gone\n"),
881                                          progname, pid);
882                 write_stderr(_("starting server anyway\n"));
883         }
884
885         do_start();
886 }
887
888
889 static void
890 do_reload(void)
891 {
892         pgpid_t         pid;
893
894         pid = get_pgpid();
895         if (pid == 0)                           /* no pid file */
896         {
897                 write_stderr(_("%s: PID file \"%s\" does not exist\n"), progname, pid_file);
898                 write_stderr(_("Is server running?\n"));
899                 exit(1);
900         }
901         else if (pid < 0)                       /* standalone backend, not postmaster */
902         {
903                 pid = -pid;
904                 write_stderr(_("%s: cannot reload server; "
905                                            "single-user server is running (PID: %ld)\n"),
906                                          progname, pid);
907                 write_stderr(_("Please terminate the single-user server and try again.\n"));
908                 exit(1);
909         }
910
911         if (kill((pid_t) pid, sig) != 0)
912         {
913                 write_stderr(_("%s: could not send reload signal (PID: %ld): %s\n"),
914                                          progname, pid, strerror(errno));
915                 exit(1);
916         }
917
918         print_msg(_("server signaled\n"));
919 }
920
921 /*
922  *      utility routines
923  */
924
925 static bool
926 postmaster_is_alive(pid_t pid)
927 {
928         /*
929          * Test to see if the process is still there.  Note that we do not
930          * consider an EPERM failure to mean that the process is still there;
931          * EPERM must mean that the given PID belongs to some other userid, and
932          * considering the permissions on $PGDATA, that means it's not the
933          * postmaster we are after.
934          *
935          * Don't believe that our own PID or parent shell's PID is the postmaster,
936          * either.      (Windows hasn't got getppid(), though.)
937          */
938         if (pid == getpid())
939                 return false;
940 #ifndef WIN32
941         if (pid == getppid())
942                 return false;
943 #endif
944         if (kill(pid, 0) == 0)
945                 return true;
946         return false;
947 }
948
949 static void
950 do_status(void)
951 {
952         pgpid_t         pid;
953
954         pid = get_pgpid();
955         if (pid != 0)                           /* 0 means no pid file */
956         {
957                 if (pid < 0)                    /* standalone backend */
958                 {
959                         pid = -pid;
960                         if (postmaster_is_alive((pid_t) pid))
961                         {
962                                 printf(_("%s: single-user server is running (PID: %ld)\n"),
963                                            progname, pid);
964                                 return;
965                         }
966                 }
967                 else
968                         /* postmaster */
969                 {
970                         if (postmaster_is_alive((pid_t) pid))
971                         {
972                                 char      **optlines;
973
974                                 printf(_("%s: server is running (PID: %ld)\n"),
975                                            progname, pid);
976
977                                 optlines = readfile(postopts_file);
978                                 if (optlines != NULL)
979                                         for (; *optlines != NULL; optlines++)
980                                                 fputs(*optlines, stdout);
981                                 return;
982                         }
983                 }
984         }
985         printf(_("%s: no server running\n"), progname);
986         exit(1);
987 }
988
989
990
991 static void
992 do_kill(pgpid_t pid)
993 {
994         if (kill((pid_t) pid, sig) != 0)
995         {
996                 write_stderr(_("%s: could not send signal %d (PID: %ld): %s\n"),
997                                          progname, sig, pid, strerror(errno));
998                 exit(1);
999         }
1000 }
1001
1002 #if defined(WIN32) || defined(__CYGWIN__)
1003
1004 static bool
1005 pgwin32_IsInstalled(SC_HANDLE hSCM)
1006 {
1007         SC_HANDLE       hService = OpenService(hSCM, register_servicename, SERVICE_QUERY_CONFIG);
1008         bool            bResult = (hService != NULL);
1009
1010         if (bResult)
1011                 CloseServiceHandle(hService);
1012         return bResult;
1013 }
1014
1015 static char *
1016 pgwin32_CommandLine(bool registration)
1017 {
1018         static char cmdLine[MAXPGPATH];
1019         int                     ret;
1020
1021 #ifdef __CYGWIN__
1022         char            buf[MAXPGPATH];
1023 #endif
1024
1025         if (registration)
1026         {
1027                 ret = find_my_exec(argv0, cmdLine);
1028                 if (ret != 0)
1029                 {
1030                         write_stderr(_("%s: could not find own program executable\n"), progname);
1031                         exit(1);
1032                 }
1033         }
1034         else
1035         {
1036                 ret = find_other_exec(argv0, "postgres", PG_BACKEND_VERSIONSTR,
1037                                                           cmdLine);
1038                 if (ret != 0)
1039                 {
1040                         write_stderr(_("%s: could not find postgres program executable\n"), progname);
1041                         exit(1);
1042                 }
1043         }
1044
1045 #ifdef __CYGWIN__
1046         /* need to convert to windows path */
1047         cygwin_conv_to_full_win32_path(cmdLine, buf);
1048         strcpy(cmdLine, buf);
1049 #endif
1050
1051         if (registration)
1052         {
1053                 if (pg_strcasecmp(cmdLine + strlen(cmdLine) - 4, ".exe"))
1054                 {
1055                         /* If commandline does not end in .exe, append it */
1056                         strcat(cmdLine, ".exe");
1057                 }
1058                 strcat(cmdLine, " runservice -N \"");
1059                 strcat(cmdLine, register_servicename);
1060                 strcat(cmdLine, "\"");
1061         }
1062
1063         if (pg_data)
1064         {
1065                 strcat(cmdLine, " -D \"");
1066                 strcat(cmdLine, pg_data);
1067                 strcat(cmdLine, "\"");
1068         }
1069
1070         if (registration && do_wait)
1071                 strcat(cmdLine, " -w");
1072
1073         if (registration && wait_seconds != DEFAULT_WAIT)
1074                 /* concatenate */
1075                 sprintf(cmdLine + strlen(cmdLine), " -t %d", wait_seconds);
1076
1077         if (post_opts)
1078         {
1079                 strcat(cmdLine, " ");
1080                 if (registration)
1081                         strcat(cmdLine, " -o \"");
1082                 strcat(cmdLine, post_opts);
1083                 if (registration)
1084                         strcat(cmdLine, "\"");
1085         }
1086
1087         return cmdLine;
1088 }
1089
1090 static void
1091 pgwin32_doRegister(void)
1092 {
1093         SC_HANDLE       hService;
1094         SC_HANDLE       hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
1095
1096         if (hSCM == NULL)
1097         {
1098                 write_stderr(_("%s: could not open service manager\n"), progname);
1099                 exit(1);
1100         }
1101         if (pgwin32_IsInstalled(hSCM))
1102         {
1103                 CloseServiceHandle(hSCM);
1104                 write_stderr(_("%s: service \"%s\" already registered\n"), progname, register_servicename);
1105                 exit(1);
1106         }
1107
1108         if ((hService = CreateService(hSCM, register_servicename, register_servicename,
1109                                                            SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
1110                                                                   SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
1111                                                                   pgwin32_CommandLine(true),
1112            NULL, NULL, "RPCSS\0", register_username, register_password)) == NULL)
1113         {
1114                 CloseServiceHandle(hSCM);
1115                 write_stderr(_("%s: could not register service \"%s\": error code %d\n"), progname, register_servicename, (int) GetLastError());
1116                 exit(1);
1117         }
1118         CloseServiceHandle(hService);
1119         CloseServiceHandle(hSCM);
1120 }
1121
1122 static void
1123 pgwin32_doUnregister(void)
1124 {
1125         SC_HANDLE       hService;
1126         SC_HANDLE       hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
1127
1128         if (hSCM == NULL)
1129         {
1130                 write_stderr(_("%s: could not open service manager\n"), progname);
1131                 exit(1);
1132         }
1133         if (!pgwin32_IsInstalled(hSCM))
1134         {
1135                 CloseServiceHandle(hSCM);
1136                 write_stderr(_("%s: service \"%s\" not registered\n"), progname, register_servicename);
1137                 exit(1);
1138         }
1139
1140         if ((hService = OpenService(hSCM, register_servicename, DELETE)) == NULL)
1141         {
1142                 CloseServiceHandle(hSCM);
1143                 write_stderr(_("%s: could not open service \"%s\": error code %d\n"), progname, register_servicename, (int) GetLastError());
1144                 exit(1);
1145         }
1146         if (!DeleteService(hService))
1147         {
1148                 CloseServiceHandle(hService);
1149                 CloseServiceHandle(hSCM);
1150                 write_stderr(_("%s: could not unregister service \"%s\": error code %d\n"), progname, register_servicename, (int) GetLastError());
1151                 exit(1);
1152         }
1153         CloseServiceHandle(hService);
1154         CloseServiceHandle(hSCM);
1155 }
1156
1157 static void
1158 pgwin32_SetServiceStatus(DWORD currentState)
1159 {
1160         status.dwCurrentState = currentState;
1161         SetServiceStatus(hStatus, (LPSERVICE_STATUS) &status);
1162 }
1163
1164 static void WINAPI
1165 pgwin32_ServiceHandler(DWORD request)
1166 {
1167         switch (request)
1168         {
1169                 case SERVICE_CONTROL_STOP:
1170                 case SERVICE_CONTROL_SHUTDOWN:
1171
1172                         /*
1173                          * We only need a short wait hint here as it just needs to wait
1174                          * for the next checkpoint. They occur every 5 seconds during
1175                          * shutdown
1176                          */
1177                         status.dwWaitHint = 10000;
1178                         pgwin32_SetServiceStatus(SERVICE_STOP_PENDING);
1179                         SetEvent(shutdownEvent);
1180                         return;
1181
1182                 case SERVICE_CONTROL_PAUSE:
1183                         /* Win32 config reloading */
1184                         status.dwWaitHint = 5000;
1185                         kill(postmasterPID, SIGHUP);
1186                         return;
1187
1188                         /* FIXME: These could be used to replace other signals etc */
1189                 case SERVICE_CONTROL_CONTINUE:
1190                 case SERVICE_CONTROL_INTERROGATE:
1191                 default:
1192                         break;
1193         }
1194 }
1195
1196 static void WINAPI
1197 pgwin32_ServiceMain(DWORD argc, LPTSTR *argv)
1198 {
1199         PROCESS_INFORMATION pi;
1200         DWORD           ret;
1201         DWORD           check_point_start;
1202
1203         /* Initialize variables */
1204         status.dwWin32ExitCode = S_OK;
1205         status.dwCheckPoint = 0;
1206         status.dwWaitHint = 60000;
1207         status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1208         status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE;
1209         status.dwServiceSpecificExitCode = 0;
1210         status.dwCurrentState = SERVICE_START_PENDING;
1211
1212         memset(&pi, 0, sizeof(pi));
1213
1214         read_post_opts();
1215
1216         /* Register the control request handler */
1217         if ((hStatus = RegisterServiceCtrlHandler(register_servicename, pgwin32_ServiceHandler)) == (SERVICE_STATUS_HANDLE) 0)
1218                 return;
1219
1220         if ((shutdownEvent = CreateEvent(NULL, true, false, NULL)) == NULL)
1221                 return;
1222
1223         /* Start the postmaster */
1224         pgwin32_SetServiceStatus(SERVICE_START_PENDING);
1225         if (!CreateRestrictedProcess(pgwin32_CommandLine(false), &pi, true))
1226         {
1227                 pgwin32_SetServiceStatus(SERVICE_STOPPED);
1228                 return;
1229         }
1230         postmasterPID = pi.dwProcessId;
1231         postmasterProcess = pi.hProcess;
1232         CloseHandle(pi.hThread);
1233
1234         if (do_wait)
1235         {
1236                 write_eventlog(EVENTLOG_INFORMATION_TYPE, _("Waiting for server startup...\n"));
1237                 if (test_postmaster_connection(true) == false)
1238                 {
1239                         write_eventlog(EVENTLOG_INFORMATION_TYPE, _("Timed out waiting for server startup\n"));
1240                         pgwin32_SetServiceStatus(SERVICE_STOPPED);
1241                         return;
1242                 }
1243                 write_eventlog(EVENTLOG_INFORMATION_TYPE, _("Server started and accepting connections\n"));
1244         }
1245
1246         /*
1247          * Save the checkpoint value as it might have been incremented in
1248          * test_postmaster_connection
1249          */
1250         check_point_start = status.dwCheckPoint;
1251
1252         pgwin32_SetServiceStatus(SERVICE_RUNNING);
1253
1254         /* Wait for quit... */
1255         ret = WaitForMultipleObjects(2, shutdownHandles, FALSE, INFINITE);
1256
1257         pgwin32_SetServiceStatus(SERVICE_STOP_PENDING);
1258         switch (ret)
1259         {
1260                 case WAIT_OBJECT_0:             /* shutdown event */
1261                         kill(postmasterPID, SIGINT);
1262
1263                         /*
1264                          * Increment the checkpoint and try again Abort after 12
1265                          * checkpoints as the postmaster has probably hung
1266                          */
1267                         while (WaitForSingleObject(postmasterProcess, 5000) == WAIT_TIMEOUT && status.dwCheckPoint < 12)
1268                                 status.dwCheckPoint++;
1269                         break;
1270
1271                 case (WAIT_OBJECT_0 + 1):               /* postmaster went down */
1272                         break;
1273
1274                 default:
1275                         /* shouldn't get here? */
1276                         break;
1277         }
1278
1279         CloseHandle(shutdownEvent);
1280         CloseHandle(postmasterProcess);
1281
1282         pgwin32_SetServiceStatus(SERVICE_STOPPED);
1283 }
1284
1285 static void
1286 pgwin32_doRunAsService(void)
1287 {
1288         SERVICE_TABLE_ENTRY st[] = {{register_servicename, pgwin32_ServiceMain},
1289         {NULL, NULL}};
1290
1291         if (StartServiceCtrlDispatcher(st) == 0)
1292         {
1293                 write_stderr(_("%s: could not start service \"%s\": error code %d\n"), progname, register_servicename, (int) GetLastError());
1294                 exit(1);
1295         }
1296 }
1297
1298
1299 /*
1300  * Mingw headers are incomplete, and so are the libraries. So we have to load
1301  * a whole lot of API functions dynamically. Since we have to do this anyway,
1302  * also load the couple of functions that *do* exist in minwg headers but not
1303  * on NT4. That way, we don't break on NT4.
1304  */
1305 typedef BOOL (WINAPI * __CreateRestrictedToken) (HANDLE, DWORD, DWORD, PSID_AND_ATTRIBUTES, DWORD, PLUID_AND_ATTRIBUTES, DWORD, PSID_AND_ATTRIBUTES, PHANDLE);
1306 typedef BOOL (WINAPI * __IsProcessInJob) (HANDLE, HANDLE, PBOOL);
1307 typedef HANDLE (WINAPI * __CreateJobObject) (LPSECURITY_ATTRIBUTES, LPCTSTR);
1308 typedef BOOL (WINAPI * __SetInformationJobObject) (HANDLE, JOBOBJECTINFOCLASS, LPVOID, DWORD);
1309 typedef BOOL (WINAPI * __AssignProcessToJobObject) (HANDLE, HANDLE);
1310 typedef BOOL (WINAPI * __QueryInformationJobObject) (HANDLE, JOBOBJECTINFOCLASS, LPVOID, DWORD, LPDWORD);
1311
1312 /* Windows API define missing from MingW headers */
1313 #define DISABLE_MAX_PRIVILEGE   0x1
1314
1315 /*
1316  * Create a restricted token, a job object sandbox, and execute the specified
1317  * process with it.
1318  *
1319  * Returns 0 on success, non-zero on failure, same as CreateProcess().
1320  *
1321  * On NT4, or any other system not containing the required functions, will
1322  * launch the process under the current token without doing any modifications.
1323  *
1324  * NOTE! Job object will only work when running as a service, because it's
1325  * automatically destroyed when pg_ctl exits.
1326  */
1327 static int
1328 CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo, bool as_service)
1329 {
1330         int                     r;
1331         BOOL            b;
1332         STARTUPINFO si;
1333         HANDLE          origToken;
1334         HANDLE          restrictedToken;
1335         SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
1336         SID_AND_ATTRIBUTES dropSids[2];
1337
1338         /* Functions loaded dynamically */
1339         __CreateRestrictedToken _CreateRestrictedToken = NULL;
1340         __IsProcessInJob _IsProcessInJob = NULL;
1341         __CreateJobObject _CreateJobObject = NULL;
1342         __SetInformationJobObject _SetInformationJobObject = NULL;
1343         __AssignProcessToJobObject _AssignProcessToJobObject = NULL;
1344         __QueryInformationJobObject _QueryInformationJobObject = NULL;
1345         HANDLE          Kernel32Handle;
1346         HANDLE          Advapi32Handle;
1347
1348         ZeroMemory(&si, sizeof(si));
1349         si.cb = sizeof(si);
1350
1351         Advapi32Handle = LoadLibrary("ADVAPI32.DLL");
1352         if (Advapi32Handle != NULL)
1353         {
1354                 _CreateRestrictedToken = (__CreateRestrictedToken) GetProcAddress(Advapi32Handle, "CreateRestrictedToken");
1355         }
1356
1357         if (_CreateRestrictedToken == NULL)
1358         {
1359                 /*
1360                  * NT4 doesn't have CreateRestrictedToken, so just call ordinary
1361                  * CreateProcess
1362                  */
1363                 write_stderr("WARNING: cannot create restricted tokens on this platform\n");
1364                 if (Advapi32Handle != NULL)
1365                         FreeLibrary(Advapi32Handle);
1366                 return CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, processInfo);
1367         }
1368
1369         /* Open the current token to use as a base for the restricted one */
1370         if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &origToken))
1371         {
1372                 write_stderr("Failed to open process token: %lu\n", GetLastError());
1373                 return 0;
1374         }
1375
1376         /* Allocate list of SIDs to remove */
1377         ZeroMemory(&dropSids, sizeof(dropSids));
1378         if (!AllocateAndInitializeSid(&NtAuthority, 2,
1379                  SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0,
1380                                                                   0, &dropSids[0].Sid) ||
1381                 !AllocateAndInitializeSid(&NtAuthority, 2,
1382         SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0,
1383                                                                   0, &dropSids[1].Sid))
1384         {
1385                 write_stderr("Failed to allocate SIDs: %lu\n", GetLastError());
1386                 return 0;
1387         }
1388
1389         b = _CreateRestrictedToken(origToken,
1390                                                            DISABLE_MAX_PRIVILEGE,
1391                                                            sizeof(dropSids) / sizeof(dropSids[0]),
1392                                                            dropSids,
1393                                                            0, NULL,
1394                                                            0, NULL,
1395                                                            &restrictedToken);
1396
1397         FreeSid(dropSids[1].Sid);
1398         FreeSid(dropSids[0].Sid);
1399         CloseHandle(origToken);
1400         FreeLibrary(Advapi32Handle);
1401
1402         if (!b)
1403         {
1404                 write_stderr("Failed to create restricted token: %lu\n", GetLastError());
1405                 return 0;
1406         }
1407
1408         r = CreateProcessAsUser(restrictedToken, NULL, cmd, NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL, &si, processInfo);
1409
1410         Kernel32Handle = LoadLibrary("KERNEL32.DLL");
1411         if (Kernel32Handle != NULL)
1412         {
1413                 _IsProcessInJob = (__IsProcessInJob) GetProcAddress(Kernel32Handle, "IsProcessInJob");
1414                 _CreateJobObject = (__CreateJobObject) GetProcAddress(Kernel32Handle, "CreateJobObjectA");
1415                 _SetInformationJobObject = (__SetInformationJobObject) GetProcAddress(Kernel32Handle, "SetInformationJobObject");
1416                 _AssignProcessToJobObject = (__AssignProcessToJobObject) GetProcAddress(Kernel32Handle, "AssignProcessToJobObject");
1417                 _QueryInformationJobObject = (__QueryInformationJobObject) GetProcAddress(Kernel32Handle, "QueryInformationJobObject");
1418         }
1419
1420         /* Verify that we found all functions */
1421         if (_IsProcessInJob == NULL || _CreateJobObject == NULL || _SetInformationJobObject == NULL || _AssignProcessToJobObject == NULL || _QueryInformationJobObject == NULL)
1422         {
1423                 /*
1424                  * IsProcessInJob() is not available on < WinXP, so there is no need
1425                  * to log the error every time in that case
1426                  */
1427                 OSVERSIONINFO osv;
1428
1429                 osv.dwOSVersionInfoSize = sizeof(osv);
1430                 if (!GetVersionEx(&osv) ||              /* could not get version */
1431                         (osv.dwMajorVersion == 5 && osv.dwMinorVersion > 0) ||          /* 5.1=xp, 5.2=2003, etc */
1432                         osv.dwMajorVersion > 5)         /* anything newer should have the API */
1433
1434                         /*
1435                          * Log error if we can't get version, or if we're on WinXP/2003 or
1436                          * newer
1437                          */
1438                         write_stderr("WARNING: could not locate all job object functions in system API\n");
1439         }
1440         else
1441         {
1442                 BOOL            inJob;
1443
1444                 if (_IsProcessInJob(processInfo->hProcess, NULL, &inJob))
1445                 {
1446                         if (!inJob)
1447                         {
1448                                 /*
1449                                  * Job objects are working, and the new process isn't in one,
1450                                  * so we can create one safely. If any problems show up when
1451                                  * setting it, we're going to ignore them.
1452                                  */
1453                                 HANDLE          job;
1454                                 char            jobname[128];
1455
1456                                 sprintf(jobname, "PostgreSQL_%lu", processInfo->dwProcessId);
1457
1458                                 job = _CreateJobObject(NULL, jobname);
1459                                 if (job)
1460                                 {
1461                                         JOBOBJECT_BASIC_LIMIT_INFORMATION basicLimit;
1462                                         JOBOBJECT_BASIC_UI_RESTRICTIONS uiRestrictions;
1463                                         JOBOBJECT_SECURITY_LIMIT_INFORMATION securityLimit;
1464                                         OSVERSIONINFO osv;
1465
1466                                         ZeroMemory(&basicLimit, sizeof(basicLimit));
1467                                         ZeroMemory(&uiRestrictions, sizeof(uiRestrictions));
1468                                         ZeroMemory(&securityLimit, sizeof(securityLimit));
1469
1470                                         basicLimit.LimitFlags = JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION | JOB_OBJECT_LIMIT_PRIORITY_CLASS;
1471                                         basicLimit.PriorityClass = NORMAL_PRIORITY_CLASS;
1472                                         _SetInformationJobObject(job, JobObjectBasicLimitInformation, &basicLimit, sizeof(basicLimit));
1473
1474                                         uiRestrictions.UIRestrictionsClass = JOB_OBJECT_UILIMIT_DESKTOP | JOB_OBJECT_UILIMIT_DISPLAYSETTINGS |
1475                                                 JOB_OBJECT_UILIMIT_EXITWINDOWS | JOB_OBJECT_UILIMIT_READCLIPBOARD |
1476                                                 JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS | JOB_OBJECT_UILIMIT_WRITECLIPBOARD;
1477
1478                                         if (as_service)
1479                                         {
1480                                                 osv.dwOSVersionInfoSize = sizeof(osv);
1481                                                 if (!GetVersionEx(&osv) ||
1482                                                         osv.dwMajorVersion < 6 ||
1483                                                 (osv.dwMajorVersion == 6 && osv.dwMinorVersion == 0))
1484                                                 {
1485                                                         /*
1486                                                          * On Windows 7 (and presumably later),
1487                                                          * JOB_OBJECT_UILIMIT_HANDLES prevents us from
1488                                                          * starting as a service. So we only enable it on
1489                                                          * Vista and earlier (version <= 6.0)
1490                                                          */
1491                                                         uiRestrictions.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_HANDLES;
1492                                                 }
1493                                         }
1494                                         _SetInformationJobObject(job, JobObjectBasicUIRestrictions, &uiRestrictions, sizeof(uiRestrictions));
1495
1496                                         securityLimit.SecurityLimitFlags = JOB_OBJECT_SECURITY_NO_ADMIN | JOB_OBJECT_SECURITY_ONLY_TOKEN;
1497                                         securityLimit.JobToken = restrictedToken;
1498                                         _SetInformationJobObject(job, JobObjectSecurityLimitInformation, &securityLimit, sizeof(securityLimit));
1499
1500                                         _AssignProcessToJobObject(job, processInfo->hProcess);
1501                                 }
1502                         }
1503                 }
1504         }
1505
1506 #ifndef __CYGWIN__
1507         AddUserToDacl(processInfo->hProcess);
1508 #endif
1509
1510         CloseHandle(restrictedToken);
1511
1512         ResumeThread(processInfo->hThread);
1513
1514         FreeLibrary(Kernel32Handle);
1515
1516         /*
1517          * We intentionally don't close the job object handle, because we want the
1518          * object to live on until pg_ctl shuts down.
1519          */
1520         return r;
1521 }
1522 #endif
1523
1524 static void
1525 do_advice(void)
1526 {
1527         write_stderr(_("Try \"%s --help\" for more information.\n"), progname);
1528 }
1529
1530
1531
1532 static void
1533 do_help(void)
1534 {
1535         printf(_("%s is a utility to start, stop, restart, reload configuration files,\n"
1536                          "report the status of a PostgreSQL server, or signal a PostgreSQL process.\n\n"), progname);
1537         printf(_("Usage:\n"));
1538         printf(_("  %s start   [-w] [-t SECS] [-D DATADIR] [-s] [-l FILENAME] [-o \"OPTIONS\"]\n"), progname);
1539         printf(_("  %s stop    [-W] [-t SECS] [-D DATADIR] [-s] [-m SHUTDOWN-MODE]\n"), progname);
1540         printf(_("  %s restart [-w] [-t SECS] [-D DATADIR] [-s] [-m SHUTDOWN-MODE]\n"
1541                          "                 [-o \"OPTIONS\"]\n"), progname);
1542         printf(_("  %s reload  [-D DATADIR] [-s]\n"), progname);
1543         printf(_("  %s status  [-D DATADIR]\n"), progname);
1544         printf(_("  %s kill    SIGNALNAME PID\n"), progname);
1545 #if defined(WIN32) || defined(__CYGWIN__)
1546         printf(_("  %s register   [-N SERVICENAME] [-U USERNAME] [-P PASSWORD] [-D DATADIR]\n"
1547                  "                    [-w] [-t SECS] [-o \"OPTIONS\"]\n"), progname);
1548         printf(_("  %s unregister [-N SERVICENAME]\n"), progname);
1549 #endif
1550
1551         printf(_("\nCommon options:\n"));
1552         printf(_("  -D, --pgdata DATADIR   location of the database storage area\n"));
1553         printf(_("  -s, --silent           only print errors, no informational messages\n"));
1554         printf(_("  -t SECS                seconds to wait when using -w option\n"));
1555         printf(_("  -w                     wait until operation completes\n"));
1556         printf(_("  -W                     do not wait until operation completes\n"));
1557         printf(_("  --help                 show this help, then exit\n"));
1558         printf(_("  --version              output version information, then exit\n"));
1559         printf(_("(The default is to wait for shutdown, but not for start or restart.)\n\n"));
1560         printf(_("If the -D option is omitted, the environment variable PGDATA is used.\n"));
1561
1562         printf(_("\nOptions for start or restart:\n"));
1563 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
1564         printf(_("  -c, --core-files       allow postgres to produce core files\n"));
1565 #else
1566         printf(_("  -c, --core-files       not applicable on this platform\n"));
1567 #endif
1568         printf(_("  -l, --log FILENAME     write (or append) server log to FILENAME\n"));
1569         printf(_("  -o OPTIONS             command line options to pass to postgres\n"
1570                          "                         (PostgreSQL server executable)\n"));
1571         printf(_("  -p PATH-TO-POSTGRES    normally not necessary\n"));
1572         printf(_("\nOptions for stop or restart:\n"));
1573         printf(_("  -m SHUTDOWN-MODE   can be \"smart\", \"fast\", or \"immediate\"\n"));
1574
1575         printf(_("\nShutdown modes are:\n"));
1576         printf(_("  smart       quit after all clients have disconnected\n"));
1577         printf(_("  fast        quit directly, with proper shutdown\n"));
1578         printf(_("  immediate   quit without complete shutdown; will lead to recovery on restart\n"));
1579
1580         printf(_("\nAllowed signal names for kill:\n"));
1581         printf("  HUP INT QUIT ABRT TERM USR1 USR2\n");
1582
1583 #if defined(WIN32) || defined(__CYGWIN__)
1584         printf(_("\nOptions for register and unregister:\n"));
1585         printf(_("  -N SERVICENAME  service name with which to register PostgreSQL server\n"));
1586         printf(_("  -P PASSWORD     password of account to register PostgreSQL server\n"));
1587         printf(_("  -U USERNAME     user name of account to register PostgreSQL server\n"));
1588 #endif
1589
1590         printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
1591 }
1592
1593
1594
1595 static void
1596 set_mode(char *modeopt)
1597 {
1598         if (strcmp(modeopt, "s") == 0 || strcmp(modeopt, "smart") == 0)
1599         {
1600                 shutdown_mode = SMART_MODE;
1601                 sig = SIGTERM;
1602         }
1603         else if (strcmp(modeopt, "f") == 0 || strcmp(modeopt, "fast") == 0)
1604         {
1605                 shutdown_mode = FAST_MODE;
1606                 sig = SIGINT;
1607         }
1608         else if (strcmp(modeopt, "i") == 0 || strcmp(modeopt, "immediate") == 0)
1609         {
1610                 shutdown_mode = IMMEDIATE_MODE;
1611                 sig = SIGQUIT;
1612         }
1613         else
1614         {
1615                 write_stderr(_("%s: unrecognized shutdown mode \"%s\"\n"), progname, modeopt);
1616                 do_advice();
1617                 exit(1);
1618         }
1619 }
1620
1621
1622
1623 static void
1624 set_sig(char *signame)
1625 {
1626         if (!strcmp(signame, "HUP"))
1627                 sig = SIGHUP;
1628         else if (!strcmp(signame, "INT"))
1629                 sig = SIGINT;
1630         else if (!strcmp(signame, "QUIT"))
1631                 sig = SIGQUIT;
1632         else if (!strcmp(signame, "ABRT"))
1633                 sig = SIGABRT;
1634
1635         /*
1636          * probably should NOT provide SIGKILL
1637          *
1638          * else if (!strcmp(signame,"KILL")) sig = SIGKILL;
1639          */
1640         else if (!strcmp(signame, "TERM"))
1641                 sig = SIGTERM;
1642         else if (!strcmp(signame, "USR1"))
1643                 sig = SIGUSR1;
1644         else if (!strcmp(signame, "USR2"))
1645                 sig = SIGUSR2;
1646         else
1647         {
1648                 write_stderr(_("%s: unrecognized signal name \"%s\"\n"), progname, signame);
1649                 do_advice();
1650                 exit(1);
1651         }
1652
1653 }
1654
1655
1656
1657 int
1658 main(int argc, char **argv)
1659 {
1660         static struct option long_options[] = {
1661                 {"help", no_argument, NULL, '?'},
1662                 {"version", no_argument, NULL, 'V'},
1663                 {"log", required_argument, NULL, 'l'},
1664                 {"mode", required_argument, NULL, 'm'},
1665                 {"pgdata", required_argument, NULL, 'D'},
1666                 {"silent", no_argument, NULL, 's'},
1667                 {"timeout", required_argument, NULL, 't'},
1668                 {"core-files", no_argument, NULL, 'c'},
1669                 {NULL, 0, NULL, 0}
1670         };
1671
1672         int                     option_index;
1673         int                     c;
1674         pgpid_t         killproc = 0;
1675
1676 #if defined(WIN32) || defined(__CYGWIN__)
1677         setvbuf(stderr, NULL, _IONBF, 0);
1678 #endif
1679
1680         progname = get_progname(argv[0]);
1681         set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_ctl"));
1682
1683         /*
1684          * save argv[0] so do_start() can look for the postmaster if necessary. we
1685          * don't look for postmaster here because in many cases we won't need it.
1686          */
1687         argv0 = argv[0];
1688
1689         umask(077);
1690
1691         /* support --help and --version even if invoked as root */
1692         if (argc > 1)
1693         {
1694                 if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 ||
1695                         strcmp(argv[1], "-?") == 0)
1696                 {
1697                         do_help();
1698                         exit(0);
1699                 }
1700                 else if (strcmp(argv[1], "-V") == 0 || strcmp(argv[1], "--version") == 0)
1701                 {
1702                         puts("pg_ctl (PostgreSQL) " PG_VERSION);
1703                         exit(0);
1704                 }
1705         }
1706
1707         /*
1708          * Disallow running as root, to forestall any possible security holes.
1709          */
1710 #ifndef WIN32
1711         if (geteuid() == 0)
1712         {
1713                 write_stderr(_("%s: cannot be run as root\n"
1714                                            "Please log in (using, e.g., \"su\") as the "
1715                                            "(unprivileged) user that will\n"
1716                                            "own the server process.\n"),
1717                                          progname);
1718                 exit(1);
1719         }
1720 #endif
1721
1722         /*
1723          * 'Action' can be before or after args so loop over both. Some
1724          * getopt_long() implementations will reorder argv[] to place all flags
1725          * first (GNU?), but we don't rely on it. Our /port version doesn't do
1726          * that.
1727          */
1728         optind = 1;
1729
1730         /* process command-line options */
1731         while (optind < argc)
1732         {
1733                 while ((c = getopt_long(argc, argv, "cD:l:m:N:o:p:P:st:U:wW", long_options, &option_index)) != -1)
1734                 {
1735                         switch (c)
1736                         {
1737                                 case 'D':
1738                                         {
1739                                                 char       *pgdata_D;
1740                                                 char       *env_var = pg_malloc(strlen(optarg) + 8);
1741
1742                                                 pgdata_D = xstrdup(optarg);
1743                                                 canonicalize_path(pgdata_D);
1744                                                 snprintf(env_var, strlen(optarg) + 8, "PGDATA=%s",
1745                                                                  pgdata_D);
1746                                                 putenv(env_var);
1747
1748                                                 /*
1749                                                  * We could pass PGDATA just in an environment
1750                                                  * variable but we do -D too for clearer postmaster
1751                                                  * 'ps' display
1752                                                  */
1753                                                 pgdata_opt = pg_malloc(strlen(pgdata_D) + 7);
1754                                                 snprintf(pgdata_opt, strlen(pgdata_D) + 7,
1755                                                                  "-D \"%s\" ",
1756                                                                  pgdata_D);
1757                                                 break;
1758                                         }
1759                                 case 'l':
1760                                         log_file = xstrdup(optarg);
1761                                         break;
1762                                 case 'm':
1763                                         set_mode(optarg);
1764                                         break;
1765                                 case 'N':
1766                                         register_servicename = xstrdup(optarg);
1767                                         break;
1768                                 case 'o':
1769                                         post_opts = xstrdup(optarg);
1770                                         break;
1771                                 case 'p':
1772                                         postgres_path = xstrdup(optarg);
1773                                         break;
1774                                 case 'P':
1775                                         register_password = xstrdup(optarg);
1776                                         break;
1777                                 case 's':
1778                                         silent_mode = true;
1779                                         break;
1780                                 case 't':
1781                                         wait_seconds = atoi(optarg);
1782                                         break;
1783                                 case 'U':
1784                                         if (strchr(optarg, '\\'))
1785                                                 register_username = xstrdup(optarg);
1786                                         else
1787                                                 /* Prepend .\ for local accounts */
1788                                         {
1789                                                 register_username = malloc(strlen(optarg) + 3);
1790                                                 if (!register_username)
1791                                                 {
1792                                                         write_stderr(_("%s: out of memory\n"), progname);
1793                                                         exit(1);
1794                                                 }
1795                                                 strcpy(register_username, ".\\");
1796                                                 strcat(register_username, optarg);
1797                                         }
1798                                         break;
1799                                 case 'w':
1800                                         do_wait = true;
1801                                         wait_set = true;
1802                                         break;
1803                                 case 'W':
1804                                         do_wait = false;
1805                                         wait_set = true;
1806                                         break;
1807                                 case 'c':
1808                                         allow_core_files = true;
1809                                         break;
1810                                 default:
1811                                         /* getopt_long already issued a suitable error message */
1812                                         do_advice();
1813                                         exit(1);
1814                         }
1815                 }
1816
1817                 /* Process an action */
1818                 if (optind < argc)
1819                 {
1820                         if (ctl_command != NO_COMMAND)
1821                         {
1822                                 write_stderr(_("%s: too many command-line arguments (first is \"%s\")\n"), progname, argv[optind]);
1823                                 do_advice();
1824                                 exit(1);
1825                         }
1826
1827                         if (strcmp(argv[optind], "start") == 0)
1828                                 ctl_command = START_COMMAND;
1829                         else if (strcmp(argv[optind], "stop") == 0)
1830                                 ctl_command = STOP_COMMAND;
1831                         else if (strcmp(argv[optind], "restart") == 0)
1832                                 ctl_command = RESTART_COMMAND;
1833                         else if (strcmp(argv[optind], "reload") == 0)
1834                                 ctl_command = RELOAD_COMMAND;
1835                         else if (strcmp(argv[optind], "status") == 0)
1836                                 ctl_command = STATUS_COMMAND;
1837                         else if (strcmp(argv[optind], "kill") == 0)
1838                         {
1839                                 if (argc - optind < 3)
1840                                 {
1841                                         write_stderr(_("%s: missing arguments for kill mode\n"), progname);
1842                                         do_advice();
1843                                         exit(1);
1844                                 }
1845                                 ctl_command = KILL_COMMAND;
1846                                 set_sig(argv[++optind]);
1847                                 killproc = atol(argv[++optind]);
1848                         }
1849 #if defined(WIN32) || defined(__CYGWIN__)
1850                         else if (strcmp(argv[optind], "register") == 0)
1851                                 ctl_command = REGISTER_COMMAND;
1852                         else if (strcmp(argv[optind], "unregister") == 0)
1853                                 ctl_command = UNREGISTER_COMMAND;
1854                         else if (strcmp(argv[optind], "runservice") == 0)
1855                                 ctl_command = RUN_AS_SERVICE_COMMAND;
1856 #endif
1857                         else
1858                         {
1859                                 write_stderr(_("%s: unrecognized operation mode \"%s\"\n"), progname, argv[optind]);
1860                                 do_advice();
1861                                 exit(1);
1862                         }
1863                         optind++;
1864                 }
1865         }
1866
1867         if (ctl_command == NO_COMMAND)
1868         {
1869                 write_stderr(_("%s: no operation specified\n"), progname);
1870                 do_advice();
1871                 exit(1);
1872         }
1873
1874         /* Note we put any -D switch into the env var above */
1875         pg_data = getenv("PGDATA");
1876         if (pg_data)
1877         {
1878                 pg_data = xstrdup(pg_data);
1879                 canonicalize_path(pg_data);
1880         }
1881
1882         if (pg_data == NULL &&
1883                 ctl_command != KILL_COMMAND && ctl_command != UNREGISTER_COMMAND)
1884         {
1885                 write_stderr(_("%s: no database directory specified "
1886                                            "and environment variable PGDATA unset\n"),
1887                                          progname);
1888                 do_advice();
1889                 exit(1);
1890         }
1891
1892         if (!wait_set)
1893         {
1894                 switch (ctl_command)
1895                 {
1896                         case RESTART_COMMAND:
1897                         case START_COMMAND:
1898                                 do_wait = false;
1899                                 break;
1900                         case STOP_COMMAND:
1901                                 do_wait = true;
1902                                 break;
1903                         default:
1904                                 break;
1905                 }
1906         }
1907
1908         if (ctl_command == RELOAD_COMMAND)
1909         {
1910                 sig = SIGHUP;
1911                 do_wait = false;
1912         }
1913
1914         if (pg_data)
1915         {
1916                 snprintf(postopts_file, MAXPGPATH, "%s/postmaster.opts", pg_data);
1917                 snprintf(pid_file, MAXPGPATH, "%s/postmaster.pid", pg_data);
1918                 snprintf(conf_file, MAXPGPATH, "%s/postgresql.conf", pg_data);
1919                 snprintf(backup_file, MAXPGPATH, "%s/backup_label", pg_data);
1920         }
1921
1922         switch (ctl_command)
1923         {
1924                 case STATUS_COMMAND:
1925                         do_status();
1926                         break;
1927                 case START_COMMAND:
1928                         do_start();
1929                         break;
1930                 case STOP_COMMAND:
1931                         do_stop();
1932                         break;
1933                 case RESTART_COMMAND:
1934                         do_restart();
1935                         break;
1936                 case RELOAD_COMMAND:
1937                         do_reload();
1938                         break;
1939                 case KILL_COMMAND:
1940                         do_kill(killproc);
1941                         break;
1942 #if defined(WIN32) || defined(__CYGWIN__)
1943                 case REGISTER_COMMAND:
1944                         pgwin32_doRegister();
1945                         break;
1946                 case UNREGISTER_COMMAND:
1947                         pgwin32_doUnregister();
1948                         break;
1949                 case RUN_AS_SERVICE_COMMAND:
1950                         pgwin32_doRunAsService();
1951                         break;
1952 #endif
1953                 default:
1954                         break;
1955         }
1956
1957         exit(0);
1958 }