~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to src/backend/main/main.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
 * main.c
 
4
 *        Stub main() routine for the postgres executable.
 
5
 *
 
6
 * This does some essential startup tasks for any incarnation of postgres
 
7
 * (postmaster, standalone backend, or standalone bootstrap mode) and then
 
8
 * dispatches to the proper FooMain() routine for the incarnation.
 
9
 *
 
10
 *
 
11
 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
 
12
 * Portions Copyright (c) 1994, Regents of the University of California
 
13
 *
 
14
 *
 
15
 * IDENTIFICATION
 
16
 *        $PostgreSQL: pgsql/src/backend/main/main.c,v 1.94 2004-12-31 21:59:53 pgsql Exp $
 
17
 *
 
18
 *-------------------------------------------------------------------------
 
19
 */
 
20
#include "postgres.h"
 
21
 
 
22
#include <errno.h>
 
23
#include <pwd.h>
 
24
#include <unistd.h>
 
25
 
 
26
#if defined(__alpha) && defined(__osf__)                /* no __alpha__ ? */
 
27
#include <sys/sysinfo.h>
 
28
#include "machine/hal_sysinfo.h"
 
29
#define ASSEMBLER
 
30
#include <sys/proc.h>
 
31
#undef ASSEMBLER
 
32
#endif
 
33
#if defined(__NetBSD__)
 
34
#include <sys/param.h>
 
35
#endif
 
36
 
 
37
#include "bootstrap/bootstrap.h"
 
38
#include "miscadmin.h"
 
39
#include "pgstat.h"
 
40
#include "postmaster/postmaster.h"
 
41
#include "tcop/tcopprot.h"
 
42
#include "utils/help_config.h"
 
43
#include "utils/ps_status.h"
 
44
#ifdef WIN32
 
45
#include "libpq/pqsignal.h"
 
46
#endif
 
47
 
 
48
 
 
49
 
 
50
int
 
51
main(int argc, char *argv[])
 
52
{
 
53
        int                     len;
 
54
 
 
55
#ifndef WIN32
 
56
        struct passwd *pw;
 
57
#endif
 
58
        char       *pw_name_persist;
 
59
 
 
60
        /*
 
61
         * Place platform-specific startup hacks here.  This is the right
 
62
         * place to put code that must be executed early in launch of either a
 
63
         * postmaster, a standalone backend, or a standalone bootstrap run.
 
64
         * Note that this code will NOT be executed when a backend or
 
65
         * sub-bootstrap run is forked by the postmaster.
 
66
         *
 
67
         * XXX The need for code here is proof that the platform in question is
 
68
         * too brain-dead to provide a standard C execution environment
 
69
         * without help.  Avoid adding more here, if you can.
 
70
         */
 
71
 
 
72
#if defined(__alpha)                    /* no __alpha__ ? */
 
73
#ifdef NOFIXADE
 
74
        int                     buffer[] = {SSIN_UACPROC, UAC_SIGBUS | UAC_NOPRINT};
 
75
#endif
 
76
#endif   /* __alpha */
 
77
 
 
78
#ifdef WIN32
 
79
        char       *env_locale;
 
80
#endif
 
81
 
 
82
        /*
 
83
         * On some platforms, unaligned memory accesses result in a kernel
 
84
         * trap; the default kernel behavior is to emulate the memory
 
85
         * access, but this results in a significant performance
 
86
         * penalty. We ought to fix PG not to make such unaligned memory
 
87
         * accesses, so this code disables the kernel emulation: unaligned
 
88
         * accesses will result in SIGBUS instead.
 
89
         */
 
90
#ifdef NOFIXADE
 
91
 
 
92
#if defined(ultrix4)
 
93
        syscall(SYS_sysmips, MIPS_FIXADE, 0, NULL, NULL, NULL);
 
94
#endif
 
95
 
 
96
#if defined(__alpha)                    /* no __alpha__ ? */
 
97
        if (setsysinfo(SSI_NVPAIRS, buffer, 1, (caddr_t) NULL,
 
98
                                   (unsigned long) NULL) < 0)
 
99
                write_stderr("%s: setsysinfo failed: %s\n",
 
100
                                         argv[0], strerror(errno));
 
101
#endif
 
102
#endif   /* NOFIXADE */
 
103
 
 
104
#if defined(WIN32)
 
105
        {
 
106
                WSADATA         wsaData;
 
107
                int                     err;
 
108
 
 
109
                /* Make output streams unbuffered by default */
 
110
                setvbuf(stdout, NULL, _IONBF, 0);
 
111
                setvbuf(stderr, NULL, _IONBF, 0);
 
112
 
 
113
                /* Prepare Winsock */
 
114
                err = WSAStartup(MAKEWORD(2, 2), &wsaData);
 
115
                if (err != 0)
 
116
                {
 
117
                        write_stderr("%s: WSAStartup failed: %d\n",
 
118
                                                 argv[0], err);
 
119
                        exit(1);
 
120
                }
 
121
        }
 
122
#endif
 
123
 
 
124
#ifdef __BEOS__
 
125
        /* BeOS-specific actions on startup */
 
126
        beos_startup(argc, argv);
 
127
#endif
 
128
 
 
129
        /*
 
130
         * Not-quite-so-platform-specific startup environment checks. Still
 
131
         * best to minimize these.
 
132
         */
 
133
 
 
134
        /*
 
135
         * Remember the physical location of the initially given argv[] array
 
136
         * for possible use by ps display.      On some platforms, the argv[]
 
137
         * storage must be overwritten in order to set the process title for
 
138
         * ps. In such cases save_ps_display_args makes and returns a new copy
 
139
         * of the argv[] array.
 
140
         *
 
141
         * save_ps_display_args may also move the environment strings to make
 
142
         * extra room. Therefore this should be done as early as possible
 
143
         * during startup, to avoid entanglements with code that might save a
 
144
         * getenv() result pointer.
 
145
         */
 
146
        argv = save_ps_display_args(argc, argv);
 
147
 
 
148
        /*
 
149
         * Set up locale information from environment.  Note that LC_CTYPE and
 
150
         * LC_COLLATE will be overridden later from pg_control if we are in an
 
151
         * already-initialized database.  We set them here so that they will
 
152
         * be available to fill pg_control during initdb.  LC_MESSAGES will
 
153
         * get set later during GUC option processing, but we set it here to
 
154
         * allow startup error messages to be localized.
 
155
         */
 
156
 
 
157
        set_pglocale_pgservice(argv[0], "postgres");
 
158
 
 
159
#ifdef WIN32
 
160
 
 
161
        /*
 
162
         * Windows uses codepages rather than the environment, so we work
 
163
         * around that by querying the environment explicitly first for
 
164
         * LC_COLLATE and LC_CTYPE. We have to do this because initdb passes
 
165
         * those values in the environment. If there is nothing there we fall
 
166
         * back on the codepage.
 
167
         */
 
168
 
 
169
        if ((env_locale = getenv("LC_COLLATE")) != NULL)
 
170
                setlocale(LC_COLLATE, env_locale);
 
171
        else
 
172
                setlocale(LC_COLLATE, "");
 
173
 
 
174
        if ((env_locale = getenv("LC_CTYPE")) != NULL)
 
175
                setlocale(LC_CTYPE, env_locale);
 
176
        else
 
177
                setlocale(LC_CTYPE, "");
 
178
#else
 
179
        setlocale(LC_COLLATE, "");
 
180
        setlocale(LC_CTYPE, "");
 
181
#endif
 
182
 
 
183
#ifdef LC_MESSAGES
 
184
        setlocale(LC_MESSAGES, "");
 
185
#endif
 
186
 
 
187
        /*
 
188
         * We keep these set to "C" always, except transiently in pg_locale.c;
 
189
         * see that file for explanations.
 
190
         */
 
191
        setlocale(LC_MONETARY, "C");
 
192
        setlocale(LC_NUMERIC, "C");
 
193
        setlocale(LC_TIME, "C");
 
194
 
 
195
        /*
 
196
         * Skip permission checks if we're just trying to do --help or
 
197
         * --version; otherwise root will get unhelpful failure messages from
 
198
         * initdb.
 
199
         */
 
200
        if (!(argc > 1
 
201
                  && (strcmp(argv[1], "--help") == 0 ||
 
202
                          strcmp(argv[1], "-?") == 0 ||
 
203
                          strcmp(argv[1], "--version") == 0 ||
 
204
                          strcmp(argv[1], "-V") == 0)))
 
205
        {
 
206
#ifndef WIN32
 
207
#ifndef __BEOS__
 
208
 
 
209
                /*
 
210
                 * Make sure we are not running as root.
 
211
                 *
 
212
                 * BeOS currently runs everything as root :-(, so this check must be
 
213
                 * temporarily disabled there...
 
214
                 */
 
215
                if (geteuid() == 0)
 
216
                {
 
217
                        write_stderr("\"root\" execution of the PostgreSQL server is not permitted.\n"
 
218
                                                 "The server must be started under an unprivileged user ID to prevent\n"
 
219
                                                 "possible system security compromise.  See the documentation for\n"
 
220
                          "more information on how to properly start the server.\n");
 
221
                        exit(1);
 
222
                }
 
223
#endif   /* !__BEOS__ */
 
224
 
 
225
                /*
 
226
                 * Also make sure that real and effective uids are the same.
 
227
                 * Executing Postgres as a setuid program from a root shell is a
 
228
                 * security hole, since on many platforms a nefarious subroutine
 
229
                 * could setuid back to root if real uid is root.  (Since nobody
 
230
                 * actually uses Postgres as a setuid program, trying to actively
 
231
                 * fix this situation seems more trouble than it's worth; we'll
 
232
                 * just expend the effort to check for it.)
 
233
                 */
 
234
                if (getuid() != geteuid())
 
235
                {
 
236
                        write_stderr("%s: real and effective user IDs must match\n",
 
237
                                                 argv[0]);
 
238
                        exit(1);
 
239
                }
 
240
#else                                                   /* WIN32 */
 
241
                if (pgwin32_is_admin())
 
242
                {
 
243
                        write_stderr("Execution of PostgreSQL by a user with administrative permissions is not\n"
 
244
                                                 "permitted.\n"
 
245
                                                 "The server must be started under an unprivileged user ID to prevent\n"
 
246
                                                 "possible system security compromises.  See the documentation for\n"
 
247
                          "more information on how to properly start the server.\n");
 
248
                        exit(1);
 
249
                }
 
250
#endif   /* !WIN32 */
 
251
        }
 
252
 
 
253
        /*
 
254
         * Now dispatch to one of PostmasterMain, PostgresMain, GucInfoMain,
 
255
         * SubPostmasterMain, or BootstrapMain depending on the program name
 
256
         * (and possibly first argument) we were called with. The lack of
 
257
         * consistency here is historical.
 
258
         */
 
259
        len = strlen(argv[0]);
 
260
 
 
261
        if ((len >= 10 && strcmp(argv[0] + len - 10, "postmaster") == 0)
 
262
#ifdef WIN32
 
263
          || (len >= 14 && strcmp(argv[0] + len - 14, "postmaster.exe") == 0)
 
264
#endif
 
265
                )
 
266
        {
 
267
                /* Called as "postmaster" */
 
268
                exit(PostmasterMain(argc, argv));
 
269
        }
 
270
 
 
271
        /*
 
272
         * If the first argument begins with "-fork", then invoke
 
273
         * SubPostmasterMain.  This is used for forking postmaster child
 
274
         * processes on systems where we can't simply fork.
 
275
         */
 
276
#ifdef EXEC_BACKEND
 
277
        if (argc > 1 && strncmp(argv[1], "-fork", 5) == 0)
 
278
                exit(SubPostmasterMain(argc, argv));
 
279
#endif
 
280
 
 
281
#ifdef WIN32
 
282
        /*
 
283
         * Start our win32 signal implementation
 
284
         *
 
285
         * SubPostmasterMain() will do this for itself, but the remaining
 
286
         * modes need it here
 
287
         */
 
288
        pgwin32_signal_initialize();
 
289
#endif
 
290
 
 
291
        /*
 
292
         * If the first argument is "-boot", then invoke bootstrap mode. (This
 
293
         * path is taken only for a standalone bootstrap process.)
 
294
         */
 
295
        if (argc > 1 && strcmp(argv[1], "-boot") == 0)
 
296
                exit(BootstrapMain(argc, argv));
 
297
 
 
298
        /*
 
299
         * If the first argument is "--describe-config", then invoke runtime
 
300
         * configuration option display mode.
 
301
         */
 
302
        if (argc > 1 && strcmp(argv[1], "--describe-config") == 0)
 
303
                exit(GucInfoMain());
 
304
 
 
305
        /*
 
306
         * Otherwise we're a standalone backend.  Invoke PostgresMain,
 
307
         * specifying current userid as the "authenticated" Postgres user
 
308
         * name.
 
309
         */
 
310
#ifndef WIN32
 
311
        pw = getpwuid(geteuid());
 
312
        if (pw == NULL)
 
313
        {
 
314
                write_stderr("%s: invalid effective UID: %d\n",
 
315
                                         argv[0], (int) geteuid());
 
316
                exit(1);
 
317
        }
 
318
        /* Allocate new memory because later getpwuid() calls can overwrite it */
 
319
        pw_name_persist = strdup(pw->pw_name);
 
320
#else
 
321
        {
 
322
                long            namesize = 256 /* UNLEN */ + 1;
 
323
 
 
324
                pw_name_persist = malloc(namesize);
 
325
                if (!GetUserName(pw_name_persist, &namesize))
 
326
                {
 
327
                        write_stderr("%s: could not determine user name (GetUserName failed)\n",
 
328
                                                 argv[0]);
 
329
                        exit(1);
 
330
                }
 
331
        }
 
332
#endif   /* WIN32 */
 
333
 
 
334
        exit(PostgresMain(argc, argv, pw_name_persist));
 
335
}