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