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