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