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