~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to src/bin/pg_ctl/pg_ctl.c

  • Committer: alvherre
  • Date: 2005-12-16 21:24:52 UTC
  • Revision ID: svn-v4:db760fc0-0f08-0410-9d63-cc6633f64896:trunk:1
Initial import of the REL8_0_3 sources from the Pgsql CVS repository.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 *
 
3
 * pg_ctl --- start/stops/restarts the PostgreSQL server
 
4
 *
 
5
 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
 
6
 *
 
7
 * $PostgreSQL: pgsql/src/bin/pg_ctl/pg_ctl.c,v 1.53.4.2 2005-05-04 22:35:22 tgl Exp $
 
8
 *
 
9
 *-------------------------------------------------------------------------
 
10
 */
 
11
 
 
12
#include "postgres_fe.h"
 
13
#include "libpq-fe.h"
 
14
 
 
15
#include <locale.h>
 
16
#include <signal.h>
 
17
#include <sys/types.h>
 
18
#include <sys/stat.h>
 
19
#include <unistd.h>
 
20
 
 
21
#include "libpq/pqsignal.h"
 
22
#include "getopt_long.h"
 
23
 
 
24
#if defined(__CYGWIN__)
 
25
#include <sys/cygwin.h>
 
26
#include <windows.h>
 
27
/* Cygwin defines WIN32 in windows.h, but we don't want it. */
 
28
#undef WIN32
 
29
#endif
 
30
 
 
31
#ifndef HAVE_INT_OPTRESET
 
32
int                     optreset;
 
33
#endif
 
34
 
 
35
/* PID can be negative for standalone backend */
 
36
typedef long pgpid_t;
 
37
 
 
38
#define _(x) gettext((x))
 
39
 
 
40
#define WHITESPACE "\f\n\r\t\v" /* as defined by isspace() */
 
41
 
 
42
/* postmaster version ident string */
 
43
#define PM_VERSIONSTR "postmaster (PostgreSQL) " PG_VERSION "\n"
 
44
 
 
45
 
 
46
typedef enum
 
47
{
 
48
        SMART_MODE,
 
49
        FAST_MODE,
 
50
        IMMEDIATE_MODE
 
51
} ShutdownMode;
 
52
 
 
53
 
 
54
typedef enum
 
55
{
 
56
        NO_COMMAND = 0,
 
57
        START_COMMAND,
 
58
        STOP_COMMAND,
 
59
        RESTART_COMMAND,
 
60
        RELOAD_COMMAND,
 
61
        STATUS_COMMAND,
 
62
        KILL_COMMAND,
 
63
        REGISTER_COMMAND,
 
64
        UNREGISTER_COMMAND,
 
65
        RUN_AS_SERVICE_COMMAND
 
66
} CtlCommand;
 
67
 
 
68
 
 
69
static bool do_wait = false;
 
70
static bool wait_set = false;
 
71
static int      wait_seconds = 60;
 
72
static bool silent_mode = false;
 
73
static ShutdownMode shutdown_mode = SMART_MODE;
 
74
static int      sig = SIGTERM;          /* default */
 
75
static CtlCommand ctl_command = NO_COMMAND;
 
76
static char *pg_data = NULL;
 
77
static char *pgdata_opt = NULL;
 
78
static char *post_opts = NULL;
 
79
static const char *progname;
 
80
static char *log_file = NULL;
 
81
static char *postgres_path = NULL;
 
82
static char *register_servicename = "PostgreSQL";               /* FIXME: + version ID? */
 
83
static char *register_username = NULL;
 
84
static char *register_password = NULL;
 
85
static char *argv0 = NULL;
 
86
 
 
87
static void
 
88
write_stderr(const char *fmt,...)
 
89
/* This extension allows gcc to check the format string for consistency with
 
90
   the supplied arguments. */
 
91
__attribute__((format(printf, 1, 2)));
 
92
static void *xmalloc(size_t size);
 
93
static char *xstrdup(const char *s);
 
94
static void do_advice(void);
 
95
static void do_help(void);
 
96
static void set_mode(char *modeopt);
 
97
static void set_sig(char *signame);
 
98
static void do_start(void);
 
99
static void do_stop(void);
 
100
static void do_restart(void);
 
101
static void do_reload(void);
 
102
static void do_status(void);
 
103
static void do_kill(pgpid_t pid);
 
104
static void print_msg(const char *msg);
 
105
 
 
106
#if defined(WIN32) || defined(__CYGWIN__)
 
107
static bool pgwin32_IsInstalled(SC_HANDLE);
 
108
static char *pgwin32_CommandLine(bool);
 
109
static void pgwin32_doRegister(void);
 
110
static void pgwin32_doUnregister(void);
 
111
static void pgwin32_SetServiceStatus(DWORD);
 
112
static void WINAPI pgwin32_ServiceHandler(DWORD);
 
113
static void WINAPI pgwin32_ServiceMain(DWORD, LPTSTR *);
 
114
static void pgwin32_doRunAsService(void);
 
115
#endif
 
116
static pgpid_t get_pgpid(void);
 
117
static char **readfile(const char *path);
 
118
static int      start_postmaster(void);
 
119
static bool test_postmaster_connection(void);
 
120
static bool postmaster_is_alive(pid_t pid);
 
121
 
 
122
static char def_postopts_file[MAXPGPATH];
 
123
static char postopts_file[MAXPGPATH];
 
124
static char pid_file[MAXPGPATH];
 
125
static char conf_file[MAXPGPATH];
 
126
 
 
127
 
 
128
#if defined(WIN32) || defined(__CYGWIN__)
 
129
static void
 
130
write_eventlog(int level, const char *line)
 
131
{
 
132
        static HANDLE evtHandle = INVALID_HANDLE_VALUE;
 
133
 
 
134
        if (evtHandle == INVALID_HANDLE_VALUE)
 
135
        {
 
136
                evtHandle = RegisterEventSource(NULL, "PostgreSQL");
 
137
                if (evtHandle == NULL)
 
138
                {
 
139
                        evtHandle = INVALID_HANDLE_VALUE;
 
140
                        return;
 
141
                }
 
142
        }
 
143
 
 
144
        ReportEvent(evtHandle,
 
145
                                level,
 
146
                                0,
 
147
                                0,                              /* All events are Id 0 */
 
148
                                NULL,
 
149
                                1,
 
150
                                0,
 
151
                                &line,
 
152
                                NULL);
 
153
}
 
154
#endif
 
155
 
 
156
/*
 
157
 * Write errors to stderr (or by equal means when stderr is
 
158
 * not available).
 
159
 */
 
160
static void
 
161
write_stderr(const char *fmt,...)
 
162
{
 
163
        va_list         ap;
 
164
 
 
165
        va_start(ap, fmt);
 
166
#if !defined(WIN32) && !defined(__CYGWIN__)
 
167
        /* On Unix, we just fprintf to stderr */
 
168
        vfprintf(stderr, fmt, ap);
 
169
#else
 
170
 
 
171
        /*
 
172
         * On Win32, we print to stderr if running on a console, or write to
 
173
         * eventlog if running as a service
 
174
         */
 
175
        if (!isatty(fileno(stderr)))    /* Running as a service */
 
176
        {
 
177
                char            errbuf[2048];           /* Arbitrary size? */
 
178
 
 
179
                vsnprintf(errbuf, sizeof(errbuf), fmt, ap);
 
180
 
 
181
                write_eventlog(EVENTLOG_ERROR_TYPE, errbuf);
 
182
        }
 
183
        else
 
184
                /* Not running as service, write to stderr */
 
185
                vfprintf(stderr, fmt, ap);
 
186
#endif
 
187
        va_end(ap);
 
188
}
 
189
 
 
190
/*
 
191
 * routines to check memory allocations and fail noisily.
 
192
 */
 
193
 
 
194
static void *
 
195
xmalloc(size_t size)
 
196
{
 
197
        void       *result;
 
198
 
 
199
        result = malloc(size);
 
200
        if (!result)
 
201
        {
 
202
                write_stderr(_("%s: out of memory\n"), progname);
 
203
                exit(1);
 
204
        }
 
205
        return result;
 
206
}
 
207
 
 
208
 
 
209
static char *
 
210
xstrdup(const char *s)
 
211
{
 
212
        char       *result;
 
213
 
 
214
        result = strdup(s);
 
215
        if (!result)
 
216
        {
 
217
                write_stderr(_("%s: out of memory\n"), progname);
 
218
                exit(1);
 
219
        }
 
220
        return result;
 
221
}
 
222
 
 
223
/*
 
224
 * Given an already-localized string, print it to stdout unless the
 
225
 * user has specified that no messages should be printed.
 
226
 */
 
227
static void
 
228
print_msg(const char *msg)
 
229
{
 
230
        if (!silent_mode)
 
231
        {
 
232
                fputs(msg, stdout);
 
233
                fflush(stdout);
 
234
        }
 
235
}
 
236
 
 
237
static pgpid_t
 
238
get_pgpid(void)
 
239
{
 
240
        FILE       *pidf;
 
241
        long            pid;
 
242
 
 
243
        pidf = fopen(pid_file, "r");
 
244
        if (pidf == NULL)
 
245
        {
 
246
                /* No pid file, not an error on startup */
 
247
                if (errno == ENOENT)
 
248
                        return 0;
 
249
                else
 
250
                {
 
251
                        write_stderr(_("%s: could not open PID file \"%s\": %s\n"),
 
252
                                                 progname, pid_file, strerror(errno));
 
253
                        exit(1);
 
254
                }
 
255
        }
 
256
        if (fscanf(pidf, "%ld", &pid) != 1)
 
257
        {
 
258
                write_stderr(_("%s: invalid data in PID file \"%s\"\n"),
 
259
                                         progname, pid_file);
 
260
                exit(1);
 
261
        }
 
262
        fclose(pidf);
 
263
        return (pgpid_t) pid;
 
264
}
 
265
 
 
266
 
 
267
/*
 
268
 * get the lines from a text file - return NULL if file can't be opened
 
269
 */
 
270
static char **
 
271
readfile(const char *path)
 
272
{
 
273
        FILE       *infile;
 
274
        int                     maxlength = 0,
 
275
                                linelen = 0;
 
276
        int                     nlines = 0;
 
277
        char      **result;
 
278
        char       *buffer;
 
279
        int                     c;
 
280
 
 
281
        if ((infile = fopen(path, "r")) == NULL)
 
282
                return NULL;
 
283
 
 
284
        /* pass over the file twice - the first time to size the result */
 
285
 
 
286
        while ((c = fgetc(infile)) != EOF)
 
287
        {
 
288
                linelen++;
 
289
                if (c == '\n')
 
290
                {
 
291
                        nlines++;
 
292
                        if (linelen > maxlength)
 
293
                                maxlength = linelen;
 
294
                        linelen = 0;
 
295
                }
 
296
        }
 
297
 
 
298
        /* handle last line without a terminating newline (yuck) */
 
299
        if (linelen)
 
300
                nlines++;
 
301
        if (linelen > maxlength)
 
302
                maxlength = linelen;
 
303
 
 
304
        /* set up the result and the line buffer */
 
305
        result = (char **) xmalloc((nlines + 1) * sizeof(char *));
 
306
        buffer = (char *) xmalloc(maxlength + 1);
 
307
 
 
308
        /* now reprocess the file and store the lines */
 
309
        rewind(infile);
 
310
        nlines = 0;
 
311
        while (fgets(buffer, maxlength + 1, infile) != NULL)
 
312
                result[nlines++] = xstrdup(buffer);
 
313
 
 
314
        fclose(infile);
 
315
        result[nlines] = NULL;
 
316
 
 
317
        return result;
 
318
}
 
319
 
 
320
 
 
321
 
 
322
/*
 
323
 * start/test/stop routines
 
324
 */
 
325
 
 
326
static int
 
327
start_postmaster(void)
 
328
{
 
329
        /*
 
330
         * Since there might be quotes to handle here, it is easier simply to
 
331
         * pass everything to a shell to process them.
 
332
         */
 
333
        char            cmd[MAXPGPATH];
 
334
 
 
335
        /*
 
336
         * Win32 needs START /B rather than "&".
 
337
         *
 
338
         * Win32 has a problem with START and quoted executable names. You must
 
339
         * add a "" as the title at the beginning so you can quote the
 
340
         * executable name:
 
341
         * http://www.winnetmag.com/Article/ArticleID/14589/14589.html
 
342
         * http://dev.remotenetworktechnology.com/cmd/cmdfaq.htm
 
343
         */
 
344
        if (log_file != NULL)
 
345
#ifndef WIN32   /* Cygwin doesn't have START */
 
346
                snprintf(cmd, MAXPGPATH, "%s\"%s\" %s%s < \"%s\" >> \"%s\" 2>&1 &%s",
 
347
#else
 
348
                snprintf(cmd, MAXPGPATH, "%sSTART /B \"\" \"%s\" %s%s < \"%s\" >> \"%s\" 2>&1%s",
 
349
#endif
 
350
                                 SYSTEMQUOTE, postgres_path, pgdata_opt, post_opts,
 
351
                                 DEVNULL, log_file, SYSTEMQUOTE);
 
352
        else
 
353
#ifndef WIN32   /* Cygwin doesn't have START */
 
354
                snprintf(cmd, MAXPGPATH, "%s\"%s\" %s%s < \"%s\" 2>&1 &%s",
 
355
#else
 
356
                snprintf(cmd, MAXPGPATH, "%sSTART /B \"\" \"%s\" %s%s < \"%s\" 2>&1%s",
 
357
#endif
 
358
                                 SYSTEMQUOTE, postgres_path, pgdata_opt, post_opts,
 
359
                                 DEVNULL, SYSTEMQUOTE);
 
360
 
 
361
        return system(cmd);
 
362
}
 
363
 
 
364
 
 
365
 
 
366
/* Find the pgport and try a connection */
 
367
static bool
 
368
test_postmaster_connection(void)
 
369
{
 
370
        PGconn     *conn;
 
371
        bool            success = false;
 
372
        int                     i;
 
373
        char            portstr[32];
 
374
        char       *p;
 
375
 
 
376
        *portstr = '\0';
 
377
 
 
378
        /* post_opts */
 
379
        for (p = post_opts; *p;)
 
380
        {
 
381
                /* advance past whitespace/quoting */
 
382
                while (isspace((unsigned char) *p) || *p == '\'' || *p == '"')
 
383
                        p++;
 
384
 
 
385
                if (strncmp(p, "-p", strlen("-p")) == 0)
 
386
                {
 
387
                        p += strlen("-p");
 
388
                        /* advance past whitespace/quoting */
 
389
                        while (isspace((unsigned char) *p) || *p == '\'' || *p == '"')
 
390
                                p++;
 
391
                        StrNCpy(portstr, p, Min(strcspn(p, "\"'" WHITESPACE) + 1,
 
392
                                                                        sizeof(portstr)));
 
393
                        /* keep looking, maybe there is another -p */
 
394
                }
 
395
                /* Advance to next whitespace */
 
396
                while (*p && !isspace((unsigned char) *p))
 
397
                        p++;
 
398
        }
 
399
 
 
400
        /* config file */
 
401
        if (!*portstr)
 
402
        {
 
403
                char      **optlines;
 
404
 
 
405
                optlines = readfile(conf_file);
 
406
                if (optlines != NULL)
 
407
                {
 
408
                        for (; *optlines != NULL; optlines++)
 
409
                        {
 
410
                                p = *optlines;
 
411
 
 
412
                                while (isspace((unsigned char) *p))
 
413
                                        p++;
 
414
                                if (strncmp(p, "port", strlen("port")) != 0)
 
415
                                        continue;
 
416
                                p += strlen("port");
 
417
                                while (isspace((unsigned char) *p))
 
418
                                        p++;
 
419
                                if (*p != '=')
 
420
                                        continue;
 
421
                                p++;
 
422
                                while (isspace((unsigned char) *p))
 
423
                                        p++;
 
424
                                StrNCpy(portstr, p, Min(strcspn(p, "#" WHITESPACE) + 1,
 
425
                                                                                sizeof(portstr)));
 
426
                                /* keep looking, maybe there is another */
 
427
                        }
 
428
                }
 
429
        }
 
430
 
 
431
        /* environment */
 
432
        if (!*portstr && getenv("PGPORT") != NULL)
 
433
                StrNCpy(portstr, getenv("PGPORT"), sizeof(portstr));
 
434
 
 
435
        /* default */
 
436
        if (!*portstr)
 
437
                snprintf(portstr, sizeof(portstr), "%d", DEF_PGPORT);
 
438
 
 
439
        for (i = 0; i < wait_seconds; i++)
 
440
        {
 
441
                if ((conn = PQsetdbLogin(NULL, portstr, NULL, NULL,
 
442
                                                                 "template1", NULL, NULL)) != NULL &&
 
443
                        (PQstatus(conn) == CONNECTION_OK ||
 
444
                         (strcmp(PQerrorMessage(conn),
 
445
                                         PQnoPasswordSupplied) == 0)))
 
446
                {
 
447
                        PQfinish(conn);
 
448
                        success = true;
 
449
                        break;
 
450
                }
 
451
                else
 
452
                {
 
453
                        print_msg(".");
 
454
                        pg_usleep(1000000); /* 1 sec */
 
455
                }
 
456
        }
 
457
 
 
458
        return success;
 
459
}
 
460
 
 
461
 
 
462
 
 
463
static void
 
464
do_start(void)
 
465
{
 
466
        pgpid_t         pid;
 
467
        pgpid_t         old_pid = 0;
 
468
        char       *optline = NULL;
 
469
        int                     exitcode;
 
470
 
 
471
        if (ctl_command != RESTART_COMMAND)
 
472
        {
 
473
                old_pid = get_pgpid();
 
474
                if (old_pid != 0)
 
475
                        write_stderr(_("%s: another postmaster may be running; "
 
476
                                                   "trying to start postmaster anyway\n"),
 
477
                                                 progname);
 
478
        }
 
479
 
 
480
        if (post_opts == NULL)
 
481
        {
 
482
                char      **optlines;
 
483
                int                     len;
 
484
 
 
485
                optlines = readfile(ctl_command == RESTART_COMMAND ?
 
486
                                                        postopts_file : def_postopts_file);
 
487
                if (optlines == NULL)
 
488
                {
 
489
                        if (ctl_command == START_COMMAND)
 
490
                                post_opts = "";
 
491
                        else
 
492
                        {
 
493
                                write_stderr(_("%s: could not read file \"%s\"\n"), progname, postopts_file);
 
494
                                exit(1);
 
495
                        }
 
496
                }
 
497
                else if (optlines[0] == NULL || optlines[1] != NULL)
 
498
                {
 
499
                        write_stderr(_("%s: option file \"%s\" must have exactly one line\n"),
 
500
                                                 progname, ctl_command == RESTART_COMMAND ?
 
501
                                                 postopts_file : def_postopts_file);
 
502
                        exit(1);
 
503
                }
 
504
                else
 
505
                {
 
506
                        optline = optlines[0];
 
507
                        len = strcspn(optline, "\r\n");
 
508
                        optline[len] = '\0';
 
509
 
 
510
                        if (ctl_command == RESTART_COMMAND)
 
511
                        {
 
512
                                char       *arg1;
 
513
 
 
514
                                arg1 = strchr(optline, *SYSTEMQUOTE);
 
515
                                if (arg1 == NULL || arg1 == optline)
 
516
                                        post_opts = "";
 
517
                                else
 
518
                                {
 
519
                                        *(arg1 - 1) = '\0'; /* this should be a space */
 
520
                                        post_opts = arg1;
 
521
                                }
 
522
                                if (postgres_path != NULL)
 
523
                                        postgres_path = optline;
 
524
                        }
 
525
                        else
 
526
                                post_opts = optline;
 
527
                }
 
528
        }
 
529
 
 
530
        /* No -D or -D already added during server start */
 
531
        if (ctl_command == RESTART_COMMAND || pgdata_opt == NULL)
 
532
                pgdata_opt = "";
 
533
 
 
534
        if (postgres_path == NULL)
 
535
        {
 
536
                char       *postmaster_path;
 
537
                int                     ret;
 
538
 
 
539
                postmaster_path = xmalloc(MAXPGPATH);
 
540
 
 
541
                if ((ret = find_other_exec(argv0, "postmaster", PM_VERSIONSTR,
 
542
                                                                   postmaster_path)) < 0)
 
543
                {
 
544
                        char full_path[MAXPGPATH];
 
545
        
 
546
                        if (find_my_exec(argv0, full_path) < 0)
 
547
                                StrNCpy(full_path, progname, MAXPGPATH);
 
548
        
 
549
                        if (ret == -1)
 
550
                                write_stderr(_("The program \"postmaster\" is needed by %s "
 
551
                                                           "but was not found in the\n"
 
552
                                                           "same directory as \"%s\".\n"
 
553
                                                           "Check your installation.\n"),
 
554
                                                         progname, full_path);
 
555
                        else
 
556
                                write_stderr(_("The program \"postmaster\" was found by \"%s\"\n"
 
557
                                                           "but was not the same version as %s.\n"
 
558
                                                           "Check your installation.\n"),
 
559
                                                         full_path, progname);
 
560
                        exit(1);
 
561
                }
 
562
                postgres_path = postmaster_path;
 
563
        }
 
564
 
 
565
        exitcode = start_postmaster();
 
566
        if (exitcode != 0)
 
567
        {
 
568
                write_stderr(_("%s: could not start postmaster: exit code was %d\n"),
 
569
                                         progname, exitcode);
 
570
                exit(1);
 
571
        }
 
572
 
 
573
        if (old_pid != 0)
 
574
        {
 
575
                pg_usleep(1000000);
 
576
                pid = get_pgpid();
 
577
                if (pid == old_pid)
 
578
                {
 
579
                        write_stderr(_("%s: could not start postmaster\n"
 
580
                                                   "Examine the log output.\n"),
 
581
                                                 progname);
 
582
                        exit(1);
 
583
                }
 
584
        }
 
585
 
 
586
        if (do_wait)
 
587
        {
 
588
                print_msg(_("waiting for postmaster to start..."));
 
589
 
 
590
                if (test_postmaster_connection() == false)
 
591
                {
 
592
                        printf(_("could not start postmaster\n"));
 
593
                        exit(1);
 
594
                }
 
595
                else
 
596
                {
 
597
                        print_msg(_(" done\n"));
 
598
                        print_msg(_("postmaster started\n"));
 
599
                }
 
600
        }
 
601
        else
 
602
                print_msg(_("postmaster starting\n"));
 
603
}
 
604
 
 
605
 
 
606
static void
 
607
do_stop(void)
 
608
{
 
609
        int                     cnt;
 
610
        pgpid_t         pid;
 
611
 
 
612
        pid = get_pgpid();
 
613
 
 
614
        if (pid == 0)                           /* no pid file */
 
615
        {
 
616
                write_stderr(_("%s: PID file \"%s\" does not exist\n"), progname, pid_file);
 
617
                write_stderr(_("Is postmaster running?\n"));
 
618
                exit(1);
 
619
        }
 
620
        else if (pid < 0)                       /* standalone backend, not postmaster */
 
621
        {
 
622
                pid = -pid;
 
623
                write_stderr(_("%s: cannot stop postmaster; "
 
624
                                           "postgres is running (PID: %ld)\n"),
 
625
                                         progname, pid);
 
626
                exit(1);
 
627
        }
 
628
 
 
629
        if (kill((pid_t) pid, sig) != 0)
 
630
        {
 
631
                write_stderr(_("%s: could not send stop signal (PID: %ld): %s\n"), progname, pid,
 
632
                                         strerror(errno));
 
633
                exit(1);
 
634
        }
 
635
 
 
636
        if (!do_wait)
 
637
        {
 
638
                print_msg(_("postmaster shutting down\n"));
 
639
                return;
 
640
        }
 
641
        else
 
642
        {
 
643
                print_msg(_("waiting for postmaster to shut down..."));
 
644
 
 
645
                for (cnt = 0; cnt < wait_seconds; cnt++)
 
646
                {
 
647
                        if ((pid = get_pgpid()) != 0)
 
648
                        {
 
649
                                print_msg(".");
 
650
                                pg_usleep(1000000);             /* 1 sec */
 
651
                        }
 
652
                        else
 
653
                                break;
 
654
                }
 
655
 
 
656
                if (pid != 0)                   /* pid file still exists */
 
657
                {
 
658
                        print_msg(_(" failed\n"));
 
659
 
 
660
                        write_stderr(_("%s: postmaster does not shut down\n"), progname);
 
661
                        exit(1);
 
662
                }
 
663
                print_msg(_(" done\n"));
 
664
 
 
665
                printf(_("postmaster stopped\n"));
 
666
        }
 
667
}
 
668
 
 
669
 
 
670
/*
 
671
 *      restart/reload routines
 
672
 */
 
673
 
 
674
static void
 
675
do_restart(void)
 
676
{
 
677
        int                     cnt;
 
678
        pgpid_t         pid;
 
679
 
 
680
        pid = get_pgpid();
 
681
 
 
682
        if (pid == 0)                           /* no pid file */
 
683
        {
 
684
                write_stderr(_("%s: PID file \"%s\" does not exist\n"),
 
685
                                         progname, pid_file);
 
686
                write_stderr(_("Is postmaster running?\n"));
 
687
                write_stderr(_("starting postmaster anyway\n"));
 
688
                do_start();
 
689
                return;
 
690
        }
 
691
        else if (pid < 0)                       /* standalone backend, not postmaster */
 
692
        {
 
693
                pid = -pid;
 
694
                if (postmaster_is_alive((pid_t) pid))
 
695
                {
 
696
                        write_stderr(_("%s: cannot restart postmaster; "
 
697
                                                   "postgres is running (PID: %ld)\n"),
 
698
                                                 progname, pid);
 
699
                        write_stderr(_("Please terminate postgres and try again.\n"));
 
700
                        exit(1);
 
701
                }
 
702
        }
 
703
 
 
704
        if (postmaster_is_alive((pid_t) pid))
 
705
        {
 
706
                if (kill((pid_t) pid, sig) != 0)
 
707
                {
 
708
                        write_stderr(_("%s: could not send stop signal (PID: %ld): %s\n"), progname, pid,
 
709
                                                 strerror(errno));
 
710
                        exit(1);
 
711
                }
 
712
 
 
713
                print_msg(_("waiting for postmaster to shut down..."));
 
714
 
 
715
        /* always wait for restart */
 
716
 
 
717
                for (cnt = 0; cnt < wait_seconds; cnt++)
 
718
                {
 
719
                        if ((pid = get_pgpid()) != 0)
 
720
                        {
 
721
                                print_msg(".");
 
722
                                pg_usleep(1000000); /* 1 sec */
 
723
                        }
 
724
                        else
 
725
                                break;
 
726
                }
 
727
 
 
728
                if (pid != 0)                           /* pid file still exists */
 
729
                {
 
730
                        print_msg(_(" failed\n"));
 
731
 
 
732
                        write_stderr(_("%s: postmaster does not shut down\n"), progname);
 
733
                        exit(1);
 
734
                }
 
735
 
 
736
                print_msg(_(" done\n"));
 
737
                printf(_("postmaster stopped\n"));
 
738
        }
 
739
        else
 
740
        {
 
741
                write_stderr(_("%s: old postmaster process (PID: %ld) seems to be gone\n"),
 
742
                                         progname, pid);
 
743
                write_stderr(_("starting postmaster anyway\n"));
 
744
        }
 
745
 
 
746
        do_start();
 
747
}
 
748
 
 
749
 
 
750
static void
 
751
do_reload(void)
 
752
{
 
753
        pgpid_t         pid;
 
754
 
 
755
        pid = get_pgpid();
 
756
        if (pid == 0)                           /* no pid file */
 
757
        {
 
758
                write_stderr(_("%s: PID file \"%s\" does not exist\n"), progname, pid_file);
 
759
                write_stderr(_("Is postmaster running?\n"));
 
760
                exit(1);
 
761
        }
 
762
        else if (pid < 0)                       /* standalone backend, not postmaster */
 
763
        {
 
764
                pid = -pid;
 
765
                write_stderr(_("%s: cannot reload postmaster; "
 
766
                                           "postgres is running (PID: %ld)\n"),
 
767
                                         progname, pid);
 
768
                write_stderr(_("Please terminate postgres and try again.\n"));
 
769
                exit(1);
 
770
        }
 
771
 
 
772
        if (kill((pid_t) pid, sig) != 0)
 
773
        {
 
774
                write_stderr(_("%s: could not send reload signal (PID: %ld): %s\n"),
 
775
                                         progname, pid, strerror(errno));
 
776
                exit(1);
 
777
        }
 
778
 
 
779
        print_msg(_("postmaster signaled\n"));
 
780
}
 
781
 
 
782
/*
 
783
 *      utility routines
 
784
 */
 
785
 
 
786
static bool
 
787
postmaster_is_alive(pid_t pid)
 
788
{
 
789
        /*
 
790
         * Test to see if the process is still there.  Note that we do not
 
791
         * consider an EPERM failure to mean that the process is still there;
 
792
         * EPERM must mean that the given PID belongs to some other userid,
 
793
         * and considering the permissions on $PGDATA, that means it's not
 
794
         * the postmaster we are after.
 
795
         *
 
796
         * Don't believe that our own PID or parent shell's PID is the postmaster,
 
797
         * either.  (Windows hasn't got getppid(), though.)
 
798
         */
 
799
        if (pid == getpid())
 
800
                return false;
 
801
#ifndef WIN32
 
802
        if (pid == getppid())
 
803
                return false;
 
804
#endif
 
805
        if (kill(pid, 0) == 0)
 
806
                return true;
 
807
        return false;
 
808
}
 
809
 
 
810
static void
 
811
do_status(void)
 
812
{
 
813
        pgpid_t         pid;
 
814
 
 
815
        pid = get_pgpid();
 
816
        if (pid != 0)                           /* 0 means no pid file */
 
817
        {
 
818
                if (pid < 0)                    /* standalone backend */
 
819
                {
 
820
                        pid = -pid;
 
821
                        if (postmaster_is_alive((pid_t) pid))
 
822
                        {
 
823
                                printf(_("%s: a standalone backend \"postgres\" is running (PID: %ld)\n"),
 
824
                                           progname, pid);
 
825
                                return;
 
826
                        }
 
827
                }
 
828
                else                                    /* postmaster */
 
829
                {
 
830
                        if (postmaster_is_alive((pid_t) pid))
 
831
                        {
 
832
                                char      **optlines;
 
833
 
 
834
                                printf(_("%s: postmaster is running (PID: %ld)\n"),
 
835
                                           progname, pid);
 
836
 
 
837
                                optlines = readfile(postopts_file);
 
838
                                if (optlines != NULL)
 
839
                                        for (; *optlines != NULL; optlines++)
 
840
                                                fputs(*optlines, stdout);
 
841
                                return;
 
842
                        }
 
843
                }
 
844
        }
 
845
        printf(_("%s: neither postmaster nor postgres running\n"), progname);
 
846
        exit(1);
 
847
}
 
848
 
 
849
 
 
850
 
 
851
static void
 
852
do_kill(pgpid_t pid)
 
853
{
 
854
        if (kill((pid_t) pid, sig) != 0)
 
855
        {
 
856
                write_stderr(_("%s: could not send signal %d (PID: %ld): %s\n"),
 
857
                                         progname, sig, pid, strerror(errno));
 
858
                exit(1);
 
859
        }
 
860
}
 
861
 
 
862
#if defined(WIN32) || defined(__CYGWIN__)
 
863
 
 
864
static bool
 
865
pgwin32_IsInstalled(SC_HANDLE hSCM)
 
866
{
 
867
        SC_HANDLE       hService = OpenService(hSCM, register_servicename, SERVICE_QUERY_CONFIG);
 
868
        bool            bResult = (hService != NULL);
 
869
 
 
870
        if (bResult)
 
871
                CloseServiceHandle(hService);
 
872
        return bResult;
 
873
}
 
874
 
 
875
static char *
 
876
pgwin32_CommandLine(bool registration)
 
877
{
 
878
        static char cmdLine[MAXPGPATH];
 
879
        int                     ret;
 
880
#ifdef __CYGWIN__
 
881
        char            buf[MAXPGPATH];
 
882
#endif
 
883
 
 
884
        if (registration)
 
885
        {
 
886
                ret = find_my_exec(argv0, cmdLine);
 
887
                if (ret != 0)
 
888
                {
 
889
                        write_stderr(_("%s: could not find own program executable\n"), progname);
 
890
                        exit(1);
 
891
                }
 
892
        }
 
893
        else
 
894
        {
 
895
                ret = find_other_exec(argv0, "postmaster", PM_VERSIONSTR, cmdLine);
 
896
                if (ret != 0)
 
897
                {
 
898
                        write_stderr(_("%s: could not find postmaster program executable\n"), progname);
 
899
                        exit(1);
 
900
                }
 
901
        }
 
902
 
 
903
#ifdef __CYGWIN__
 
904
        /* need to convert to windows path */
 
905
        cygwin_conv_to_full_win32_path(cmdLine, buf);
 
906
        strcpy(cmdLine, buf);
 
907
#endif
 
908
 
 
909
        if (registration)
 
910
        {
 
911
                if (strcasecmp(cmdLine + strlen(cmdLine) - 4, ".exe"))
 
912
                {
 
913
                        /* If commandline does not end in .exe, append it */
 
914
                        strcat(cmdLine, ".exe");
 
915
                }
 
916
                strcat(cmdLine, " runservice -N \"");
 
917
                strcat(cmdLine, register_servicename);
 
918
                strcat(cmdLine, "\"");
 
919
        }
 
920
 
 
921
        if (pg_data)
 
922
        {
 
923
                strcat(cmdLine, " -D \"");
 
924
                strcat(cmdLine, pg_data);
 
925
                strcat(cmdLine, "\"");
 
926
        }
 
927
 
 
928
        if (do_wait)
 
929
                strcat(cmdLine, " -w");
 
930
 
 
931
        if (post_opts)
 
932
        {
 
933
                strcat(cmdLine, " ");
 
934
                if (registration)
 
935
                        strcat(cmdLine, " -o \"");
 
936
                strcat(cmdLine, post_opts);
 
937
                if (registration)
 
938
                        strcat(cmdLine, "\"");
 
939
        }
 
940
 
 
941
        return cmdLine;
 
942
}
 
943
 
 
944
static void
 
945
pgwin32_doRegister(void)
 
946
{
 
947
        SC_HANDLE       hService;
 
948
        SC_HANDLE       hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
 
949
 
 
950
        if (hSCM == NULL)
 
951
        {
 
952
                write_stderr(_("%s: could not open service manager\n"), progname);
 
953
                exit(1);
 
954
        }
 
955
        if (pgwin32_IsInstalled(hSCM))
 
956
        {
 
957
                CloseServiceHandle(hSCM);
 
958
                write_stderr(_("%s: service \"%s\" already registered\n"), progname, register_servicename);
 
959
                exit(1);
 
960
        }
 
961
 
 
962
        if ((hService = CreateService(hSCM, register_servicename, register_servicename,
 
963
                                                   SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
 
964
                                                                SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
 
965
                                                                  pgwin32_CommandLine(true),
 
966
        NULL, NULL, "RPCSS\0", register_username, register_password)) == NULL)
 
967
        {
 
968
                CloseServiceHandle(hSCM);
 
969
                write_stderr(_("%s: could not register service \"%s\": error code %d\n"), progname, register_servicename, (int) GetLastError());
 
970
                exit(1);
 
971
        }
 
972
        CloseServiceHandle(hService);
 
973
        CloseServiceHandle(hSCM);
 
974
}
 
975
 
 
976
static void
 
977
pgwin32_doUnregister(void)
 
978
{
 
979
        SC_HANDLE       hService;
 
980
        SC_HANDLE       hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
 
981
 
 
982
        if (hSCM == NULL)
 
983
        {
 
984
                write_stderr(_("%s: could not open service manager\n"), progname);
 
985
                exit(1);
 
986
        }
 
987
        if (!pgwin32_IsInstalled(hSCM))
 
988
        {
 
989
                CloseServiceHandle(hSCM);
 
990
                write_stderr(_("%s: service \"%s\" not registered\n"), progname, register_servicename);
 
991
                exit(1);
 
992
        }
 
993
 
 
994
        if ((hService = OpenService(hSCM, register_servicename, DELETE)) == NULL)
 
995
        {
 
996
                CloseServiceHandle(hSCM);
 
997
                write_stderr(_("%s: could not open service \"%s\": error code %d\n"), progname, register_servicename, (int) GetLastError());
 
998
                exit(1);
 
999
        }
 
1000
        if (!DeleteService(hService))
 
1001
        {
 
1002
                CloseServiceHandle(hService);
 
1003
                CloseServiceHandle(hSCM);
 
1004
                write_stderr(_("%s: could not unregister service \"%s\": error code %d\n"), progname, register_servicename, (int) GetLastError());
 
1005
                exit(1);
 
1006
        }
 
1007
        CloseServiceHandle(hService);
 
1008
        CloseServiceHandle(hSCM);
 
1009
}
 
1010
 
 
1011
 
 
1012
static SERVICE_STATUS status;
 
1013
static SERVICE_STATUS_HANDLE hStatus = (SERVICE_STATUS_HANDLE) 0;
 
1014
static HANDLE shutdownHandles[2];
 
1015
static pid_t postmasterPID = -1;
 
1016
 
 
1017
#define shutdownEvent     shutdownHandles[0]
 
1018
#define postmasterProcess shutdownHandles[1]
 
1019
 
 
1020
static void
 
1021
pgwin32_SetServiceStatus(DWORD currentState)
 
1022
{
 
1023
        status.dwCurrentState = currentState;
 
1024
        SetServiceStatus(hStatus, (LPSERVICE_STATUS) & status);
 
1025
}
 
1026
 
 
1027
static void WINAPI
 
1028
pgwin32_ServiceHandler(DWORD request)
 
1029
{
 
1030
        switch (request)
 
1031
        {
 
1032
                case SERVICE_CONTROL_STOP:
 
1033
                case SERVICE_CONTROL_SHUTDOWN:
 
1034
 
 
1035
                        /*
 
1036
                         * We only need a short wait hint here as it just needs to
 
1037
                         * wait for the next checkpoint. They occur every 5 seconds
 
1038
                         * during shutdown
 
1039
                         */
 
1040
                        status.dwWaitHint = 10000;
 
1041
                        pgwin32_SetServiceStatus(SERVICE_STOP_PENDING);
 
1042
                        SetEvent(shutdownEvent);
 
1043
                        return;
 
1044
 
 
1045
                case SERVICE_CONTROL_PAUSE:
 
1046
                        /* Win32 config reloading */
 
1047
                        status.dwWaitHint = 5000;
 
1048
                        kill(postmasterPID, SIGHUP);
 
1049
                        return;
 
1050
 
 
1051
                        /* FIXME: These could be used to replace other signals etc */
 
1052
                case SERVICE_CONTROL_CONTINUE:
 
1053
                case SERVICE_CONTROL_INTERROGATE:
 
1054
                default:
 
1055
                        break;
 
1056
        }
 
1057
}
 
1058
 
 
1059
static void WINAPI
 
1060
pgwin32_ServiceMain(DWORD argc, LPTSTR * argv)
 
1061
{
 
1062
        STARTUPINFO si;
 
1063
        PROCESS_INFORMATION pi;
 
1064
        DWORD           ret;
 
1065
 
 
1066
        /* Initialize variables */
 
1067
        status.dwWin32ExitCode = S_OK;
 
1068
        status.dwCheckPoint = 0;
 
1069
        status.dwWaitHint = 60000;
 
1070
        status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
 
1071
        status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE;
 
1072
        status.dwServiceSpecificExitCode = 0;
 
1073
        status.dwCurrentState = SERVICE_START_PENDING;
 
1074
 
 
1075
        memset(&pi, 0, sizeof(pi));
 
1076
        memset(&si, 0, sizeof(si));
 
1077
        si.cb = sizeof(si);
 
1078
 
 
1079
        /* Register the control request handler */
 
1080
        if ((hStatus = RegisterServiceCtrlHandler(register_servicename, pgwin32_ServiceHandler)) == (SERVICE_STATUS_HANDLE) 0)
 
1081
                return;
 
1082
 
 
1083
        if ((shutdownEvent = CreateEvent(NULL, true, false, NULL)) == NULL)
 
1084
                return;
 
1085
 
 
1086
        /* Start the postmaster */
 
1087
        pgwin32_SetServiceStatus(SERVICE_START_PENDING);
 
1088
        if (!CreateProcess(NULL, pgwin32_CommandLine(false), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
 
1089
        {
 
1090
                pgwin32_SetServiceStatus(SERVICE_STOPPED);
 
1091
                return;
 
1092
        }
 
1093
        postmasterPID = pi.dwProcessId;
 
1094
        postmasterProcess = pi.hProcess;
 
1095
        CloseHandle(pi.hThread);
 
1096
        pgwin32_SetServiceStatus(SERVICE_RUNNING);
 
1097
 
 
1098
        /* Wait for quit... */
 
1099
        ret = WaitForMultipleObjects(2, shutdownHandles, FALSE, INFINITE);
 
1100
        pgwin32_SetServiceStatus(SERVICE_STOP_PENDING);
 
1101
        switch (ret)
 
1102
        {
 
1103
                case WAIT_OBJECT_0:             /* shutdown event */
 
1104
                        kill(postmasterPID, SIGINT);
 
1105
 
 
1106
                        /*
 
1107
                         * Increment the checkpoint and try again Abort after 12
 
1108
                         * checkpoints as the postmaster has probably hung
 
1109
                         */
 
1110
                        while (WaitForSingleObject(postmasterProcess, 5000) == WAIT_TIMEOUT && status.dwCheckPoint < 12)
 
1111
                                status.dwCheckPoint++;
 
1112
                        break;
 
1113
 
 
1114
                case (WAIT_OBJECT_0 + 1):               /* postmaster went down */
 
1115
                        break;
 
1116
 
 
1117
                default:
 
1118
                        /* shouldn't get here? */
 
1119
                        break;
 
1120
        }
 
1121
 
 
1122
        CloseHandle(shutdownEvent);
 
1123
        CloseHandle(postmasterProcess);
 
1124
 
 
1125
        pgwin32_SetServiceStatus(SERVICE_STOPPED);
 
1126
}
 
1127
 
 
1128
static void
 
1129
pgwin32_doRunAsService(void)
 
1130
{
 
1131
        SERVICE_TABLE_ENTRY st[] = {{register_servicename, pgwin32_ServiceMain},
 
1132
        {NULL, NULL}};
 
1133
 
 
1134
        if (StartServiceCtrlDispatcher(st) == 0)
 
1135
        {
 
1136
                write_stderr(_("%s: could not start service \"%s\": error code %d\n"), progname, register_servicename, (int) GetLastError());
 
1137
                exit(1);
 
1138
        }
 
1139
}
 
1140
#endif
 
1141
 
 
1142
static void
 
1143
do_advice(void)
 
1144
{
 
1145
        write_stderr(_("Try \"%s --help\" for more information.\n"), progname);
 
1146
}
 
1147
 
 
1148
 
 
1149
 
 
1150
static void
 
1151
do_help(void)
 
1152
{
 
1153
        printf(_("%s is a utility to start, stop, restart, reload configuration files,\n"
 
1154
                         "report the status of a PostgreSQL server, or signal a PostgreSQL process.\n\n"), progname);
 
1155
        printf(_("Usage:\n"));
 
1156
        printf(_("  %s start   [-w] [-D DATADIR] [-s] [-l FILENAME] [-o \"OPTIONS\"]\n"), progname);
 
1157
        printf(_("  %s stop    [-W] [-D DATADIR] [-s] [-m SHUTDOWN-MODE]\n"), progname);
 
1158
        printf(_("  %s restart [-w] [-D DATADIR] [-s] [-m SHUTDOWN-MODE] [-o \"OPTIONS\"]\n"), progname);
 
1159
        printf(_("  %s reload  [-D DATADIR] [-s]\n"), progname);
 
1160
        printf(_("  %s status  [-D DATADIR]\n"), progname);
 
1161
        printf(_("  %s kill    SIGNALNAME PID\n"), progname);
 
1162
#if defined(WIN32) || defined(__CYGWIN__)
 
1163
        printf(_("  %s register   [-N SERVICENAME] [-U USERNAME] [-P PASSWORD] [-D DATADIR]\n"
 
1164
                         "                    [-w] [-o \"OPTIONS\"]\n"), progname);
 
1165
        printf(_("  %s unregister [-N SERVICENAME]\n"), progname);
 
1166
#endif
 
1167
 
 
1168
        printf(_("\nCommon options:\n"));
 
1169
        printf(_("  -D, --pgdata DATADIR   location of the database storage area\n"));
 
1170
        printf(_("  -s, --silent           only print errors, no informational messages\n"));
 
1171
        printf(_("  -w                     wait until operation completes\n"));
 
1172
        printf(_("  -W                     do not wait until operation completes\n"));
 
1173
        printf(_("  --help                 show this help, then exit\n"));
 
1174
        printf(_("  --version              output version information, then exit\n"));
 
1175
        printf(_("(The default is to wait for shutdown, but not for start or restart.)\n\n"));
 
1176
        printf(_("If the -D option is omitted, the environment variable PGDATA is used.\n"));
 
1177
 
 
1178
        printf(_("\nOptions for start or restart:\n"));
 
1179
        printf(_("  -l, --log FILENAME     write (or append) server log to FILENAME\n"));
 
1180
        printf(_("  -o OPTIONS             command line options to pass to the postmaster\n"
 
1181
                         "                         (PostgreSQL server executable)\n"));
 
1182
        printf(_("  -p PATH-TO-POSTMASTER  normally not necessary\n"));
 
1183
 
 
1184
        printf(_("\nOptions for stop or restart:\n"));
 
1185
        printf(_("  -m SHUTDOWN-MODE   may be \"smart\", \"fast\", or \"immediate\"\n"));
 
1186
 
 
1187
        printf(_("\nShutdown modes are:\n"));
 
1188
        printf(_("  smart       quit after all clients have disconnected\n"));
 
1189
        printf(_("  fast        quit directly, with proper shutdown\n"));
 
1190
        printf(_("  immediate   quit without complete shutdown; will lead to recovery on restart\n"));
 
1191
 
 
1192
        printf(_("\nAllowed signal names for kill:\n"));
 
1193
        printf("  HUP INT QUIT ABRT TERM USR1 USR2\n");
 
1194
 
 
1195
#if defined(WIN32) || defined(__CYGWIN__)
 
1196
        printf(_("\nOptions for register and unregister:\n"));
 
1197
        printf(_("  -N SERVICENAME  service name with which to register PostgreSQL server\n"));
 
1198
        printf(_("  -P PASSWORD     password of account to register PostgreSQL server\n"));
 
1199
        printf(_("  -U USERNAME     user name of account to register PostgreSQL server\n"));
 
1200
#endif
 
1201
 
 
1202
        printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
 
1203
}
 
1204
 
 
1205
 
 
1206
 
 
1207
static void
 
1208
set_mode(char *modeopt)
 
1209
{
 
1210
        if (strcmp(modeopt, "s") == 0 || strcmp(modeopt, "smart") == 0)
 
1211
        {
 
1212
                shutdown_mode = SMART_MODE;
 
1213
                sig = SIGTERM;
 
1214
        }
 
1215
        else if (strcmp(modeopt, "f") == 0 || strcmp(modeopt, "fast") == 0)
 
1216
        {
 
1217
                shutdown_mode = FAST_MODE;
 
1218
                sig = SIGINT;
 
1219
        }
 
1220
        else if (strcmp(modeopt, "i") == 0 || strcmp(modeopt, "immediate") == 0)
 
1221
        {
 
1222
                shutdown_mode = IMMEDIATE_MODE;
 
1223
                sig = SIGQUIT;
 
1224
        }
 
1225
        else
 
1226
        {
 
1227
                write_stderr(_("%s: unrecognized shutdown mode \"%s\"\n"), progname, modeopt);
 
1228
                do_advice();
 
1229
                exit(1);
 
1230
        }
 
1231
}
 
1232
 
 
1233
 
 
1234
 
 
1235
static void
 
1236
set_sig(char *signame)
 
1237
{
 
1238
        if (!strcmp(signame, "HUP"))
 
1239
                sig = SIGHUP;
 
1240
        else if (!strcmp(signame, "INT"))
 
1241
                sig = SIGINT;
 
1242
        else if (!strcmp(signame, "QUIT"))
 
1243
                sig = SIGQUIT;
 
1244
        else if (!strcmp(signame, "ABRT"))
 
1245
                sig = SIGABRT;
 
1246
 
 
1247
        /*
 
1248
         * probably should NOT provide SIGKILL
 
1249
         *
 
1250
         * else if (!strcmp(signame,"KILL")) sig = SIGKILL;
 
1251
         */
 
1252
        else if (!strcmp(signame, "TERM"))
 
1253
                sig = SIGTERM;
 
1254
        else if (!strcmp(signame, "USR1"))
 
1255
                sig = SIGUSR1;
 
1256
        else if (!strcmp(signame, "USR2"))
 
1257
                sig = SIGUSR2;
 
1258
        else
 
1259
        {
 
1260
                write_stderr(_("%s: unrecognized signal name \"%s\"\n"), progname, signame);
 
1261
                do_advice();
 
1262
                exit(1);
 
1263
        }
 
1264
 
 
1265
}
 
1266
 
 
1267
 
 
1268
 
 
1269
int
 
1270
main(int argc, char **argv)
 
1271
{
 
1272
        static struct option long_options[] = {
 
1273
                {"help", no_argument, NULL, '?'},
 
1274
                {"version", no_argument, NULL, 'V'},
 
1275
                {"log", required_argument, NULL, 'l'},
 
1276
                {"mode", required_argument, NULL, 'm'},
 
1277
                {"pgdata", required_argument, NULL, 'D'},
 
1278
                {"silent", no_argument, NULL, 's'},
 
1279
                {NULL, 0, NULL, 0}
 
1280
        };
 
1281
 
 
1282
        int                     option_index;
 
1283
        int                     c;
 
1284
        pgpid_t         killproc = 0;
 
1285
 
 
1286
#if defined(WIN32) || defined(__CYGWIN__)
 
1287
        setvbuf(stderr, NULL, _IONBF, 0);
 
1288
#endif
 
1289
 
 
1290
        progname = get_progname(argv[0]);
 
1291
        set_pglocale_pgservice(argv[0], "pg_ctl");
 
1292
 
 
1293
        /*
 
1294
         * save argv[0] so do_start() can look for the postmaster if
 
1295
         * necessary. we don't look for postmaster here because in many cases
 
1296
         * we won't need it.
 
1297
         */
 
1298
        argv0 = argv[0];
 
1299
 
 
1300
        umask(077);
 
1301
 
 
1302
        /* support --help and --version even if invoked as root */
 
1303
        if (argc > 1)
 
1304
        {
 
1305
                if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 ||
 
1306
                        strcmp(argv[1], "-?") == 0)
 
1307
                {
 
1308
                        do_help();
 
1309
                        exit(0);
 
1310
                }
 
1311
                else if (strcmp(argv[1], "-V") == 0 || strcmp(argv[1], "--version") == 0)
 
1312
                {
 
1313
                        printf("%s (PostgreSQL) %s\n", progname, PG_VERSION);
 
1314
                        exit(0);
 
1315
                }
 
1316
        }
 
1317
 
 
1318
        /*
 
1319
         * Disallow running as root, to forestall any possible security holes.
 
1320
         */
 
1321
#ifndef WIN32
 
1322
#ifndef __BEOS__                                /* no root check on BEOS */
 
1323
        if (geteuid() == 0)
 
1324
        {
 
1325
                write_stderr(_("%s: cannot be run as root\n"
 
1326
                                           "Please log in (using, e.g., \"su\") as the "
 
1327
                                           "(unprivileged) user that will\n"
 
1328
                                           "own the server process.\n"),
 
1329
                                         progname);
 
1330
                exit(1);
 
1331
        }
 
1332
#endif
 
1333
#endif
 
1334
 
 
1335
        /*
 
1336
         * 'Action' can be before or after args so loop over both. Some
 
1337
         * getopt_long() implementations will reorder argv[] to place all
 
1338
         * flags first (GNU?), but we don't rely on it. Our /port version
 
1339
         * doesn't do that.
 
1340
         */
 
1341
        optind = 1;
 
1342
 
 
1343
        /* process command-line options */
 
1344
        while (optind < argc)
 
1345
        {
 
1346
                while ((c = getopt_long(argc, argv, "D:l:m:N:o:p:P:sU:wW", long_options, &option_index)) != -1)
 
1347
                {
 
1348
                        switch (c)
 
1349
                        {
 
1350
                                case 'D':
 
1351
                                        {
 
1352
                                                char       *pgdata_D;
 
1353
                                                char       *env_var = xmalloc(strlen(optarg) + 8);
 
1354
 
 
1355
                                                pgdata_D = xstrdup(optarg);
 
1356
                                                canonicalize_path(pgdata_D);
 
1357
                                                snprintf(env_var, strlen(optarg) + 8, "PGDATA=%s",
 
1358
                                                                 pgdata_D);
 
1359
                                                putenv(env_var);
 
1360
 
 
1361
                                                /*
 
1362
                                                 *      We could pass PGDATA just in an environment
 
1363
                                                 *      variable but we do -D too for clearer
 
1364
                                                 *      postmaster 'ps' display
 
1365
                                                 */
 
1366
                                                pgdata_opt = xmalloc(strlen(pgdata_D) + 7);
 
1367
                                                snprintf(pgdata_opt, strlen(pgdata_D) + 7,
 
1368
                                                                 "-D \"%s\" ",
 
1369
                                                                 pgdata_D);
 
1370
                                                break;
 
1371
                                        }
 
1372
                                case 'l':
 
1373
                                        log_file = xstrdup(optarg);
 
1374
                                        break;
 
1375
                                case 'm':
 
1376
                                        set_mode(optarg);
 
1377
                                        break;
 
1378
                                case 'N':
 
1379
                                        register_servicename = xstrdup(optarg);
 
1380
                                        break;
 
1381
                                case 'o':
 
1382
                                        post_opts = xstrdup(optarg);
 
1383
                                        break;
 
1384
                                case 'p':
 
1385
                                        postgres_path = xstrdup(optarg);
 
1386
                                        break;
 
1387
                                case 'P':
 
1388
                                        register_password = xstrdup(optarg);
 
1389
                                        break;
 
1390
                                case 's':
 
1391
                                        silent_mode = true;
 
1392
                                        break;
 
1393
                                case 'U':
 
1394
                                        if (strchr(optarg, '\\'))
 
1395
                                                register_username = xstrdup(optarg);
 
1396
                                        else
 
1397
                                        /* Prepend .\ for local accounts */
 
1398
                                        {
 
1399
                                                register_username = malloc(strlen(optarg) + 3);
 
1400
                                                if (!register_username)
 
1401
                                                {
 
1402
                                                        write_stderr(_("%s: out of memory\n"), progname);
 
1403
                                                        exit(1);
 
1404
                                                }
 
1405
                                                strcpy(register_username, ".\\");
 
1406
                                                strcat(register_username, optarg);
 
1407
                                        }
 
1408
                                        break;
 
1409
                                case 'w':
 
1410
                                        do_wait = true;
 
1411
                                        wait_set = true;
 
1412
                                        break;
 
1413
                                case 'W':
 
1414
                                        do_wait = false;
 
1415
                                        wait_set = true;
 
1416
                                        break;
 
1417
                                default:
 
1418
                                        write_stderr(_("%s: invalid option %s\n"), progname, optarg);
 
1419
                                        do_advice();
 
1420
                                        exit(1);
 
1421
                        }
 
1422
                }
 
1423
 
 
1424
                /* Process an action */
 
1425
                if (optind < argc)
 
1426
                {
 
1427
                        if (ctl_command != NO_COMMAND)
 
1428
                        {
 
1429
                                write_stderr(_("%s: too many command-line arguments (first is \"%s\")\n"), progname, argv[optind]);
 
1430
                                do_advice();
 
1431
                                exit(1);
 
1432
                        }
 
1433
 
 
1434
                        if (strcmp(argv[optind], "start") == 0)
 
1435
                                ctl_command = START_COMMAND;
 
1436
                        else if (strcmp(argv[optind], "stop") == 0)
 
1437
                                ctl_command = STOP_COMMAND;
 
1438
                        else if (strcmp(argv[optind], "restart") == 0)
 
1439
                                ctl_command = RESTART_COMMAND;
 
1440
                        else if (strcmp(argv[optind], "reload") == 0)
 
1441
                                ctl_command = RELOAD_COMMAND;
 
1442
                        else if (strcmp(argv[optind], "status") == 0)
 
1443
                                ctl_command = STATUS_COMMAND;
 
1444
                        else if (strcmp(argv[optind], "kill") == 0)
 
1445
                        {
 
1446
                                if (argc - optind < 3)
 
1447
                                {
 
1448
                                        write_stderr(_("%s: missing arguments for kill mode\n"), progname);
 
1449
                                        do_advice();
 
1450
                                        exit(1);
 
1451
                                }
 
1452
                                ctl_command = KILL_COMMAND;
 
1453
                                set_sig(argv[++optind]);
 
1454
                                killproc = atol(argv[++optind]);
 
1455
                        }
 
1456
#if defined(WIN32) || defined(__CYGWIN__)
 
1457
                        else if (strcmp(argv[optind], "register") == 0)
 
1458
                                ctl_command = REGISTER_COMMAND;
 
1459
                        else if (strcmp(argv[optind], "unregister") == 0)
 
1460
                                ctl_command = UNREGISTER_COMMAND;
 
1461
                        else if (strcmp(argv[optind], "runservice") == 0)
 
1462
                                ctl_command = RUN_AS_SERVICE_COMMAND;
 
1463
#endif
 
1464
                        else
 
1465
                        {
 
1466
                                write_stderr(_("%s: unrecognized operation mode \"%s\"\n"), progname, argv[optind]);
 
1467
                                do_advice();
 
1468
                                exit(1);
 
1469
                        }
 
1470
                        optind++;
 
1471
                }
 
1472
        }
 
1473
 
 
1474
        if (ctl_command == NO_COMMAND)
 
1475
        {
 
1476
                write_stderr(_("%s: no operation specified\n"), progname);
 
1477
                do_advice();
 
1478
                exit(1);
 
1479
        }
 
1480
 
 
1481
        /* Note we put any -D switch into the env var above */
 
1482
        pg_data = getenv("PGDATA");
 
1483
        if (pg_data)
 
1484
        {
 
1485
                pg_data = xstrdup(pg_data);
 
1486
                canonicalize_path(pg_data);
 
1487
        }
 
1488
 
 
1489
        if (pg_data == NULL &&
 
1490
                ctl_command != KILL_COMMAND && ctl_command != UNREGISTER_COMMAND)
 
1491
        {
 
1492
                write_stderr(_("%s: no database directory specified "
 
1493
                                           "and environment variable PGDATA unset\n"),
 
1494
                                         progname);
 
1495
                do_advice();
 
1496
                exit(1);
 
1497
        }
 
1498
 
 
1499
        if (!wait_set)
 
1500
        {
 
1501
                switch (ctl_command)
 
1502
                {
 
1503
                        case RESTART_COMMAND:
 
1504
                        case START_COMMAND:
 
1505
                                do_wait = false;
 
1506
                                break;
 
1507
                        case STOP_COMMAND:
 
1508
                                do_wait = true;
 
1509
                                break;
 
1510
                        default:
 
1511
                                break;
 
1512
                }
 
1513
        }
 
1514
 
 
1515
        if (ctl_command == RELOAD_COMMAND)
 
1516
        {
 
1517
                sig = SIGHUP;
 
1518
                do_wait = false;
 
1519
        }
 
1520
 
 
1521
        snprintf(def_postopts_file, MAXPGPATH, "%s/postmaster.opts.default", pg_data);
 
1522
        snprintf(postopts_file, MAXPGPATH, "%s/postmaster.opts", pg_data);
 
1523
        snprintf(pid_file, MAXPGPATH, "%s/postmaster.pid", pg_data);
 
1524
        snprintf(conf_file, MAXPGPATH, "%s/postgresql.conf", pg_data);
 
1525
 
 
1526
        switch (ctl_command)
 
1527
        {
 
1528
                case STATUS_COMMAND:
 
1529
                        do_status();
 
1530
                        break;
 
1531
                case START_COMMAND:
 
1532
                        do_start();
 
1533
                        break;
 
1534
                case STOP_COMMAND:
 
1535
                        do_stop();
 
1536
                        break;
 
1537
                case RESTART_COMMAND:
 
1538
                        do_restart();
 
1539
                        break;
 
1540
                case RELOAD_COMMAND:
 
1541
                        do_reload();
 
1542
                        break;
 
1543
                case KILL_COMMAND:
 
1544
                        do_kill(killproc);
 
1545
                        break;
 
1546
#if defined(WIN32) || defined(__CYGWIN__)
 
1547
                case REGISTER_COMMAND:
 
1548
                        pgwin32_doRegister();
 
1549
                        break;
 
1550
                case UNREGISTER_COMMAND:
 
1551
                        pgwin32_doUnregister();
 
1552
                        break;
 
1553
                case RUN_AS_SERVICE_COMMAND:
 
1554
                        pgwin32_doRunAsService();
 
1555
                        break;
 
1556
#endif
 
1557
                default:
 
1558
                        break;
 
1559
        }
 
1560
 
 
1561
        exit(0);
 
1562
}