]> granicus.if.org Git - postgresql/blob - src/backend/main/main.c
Move get_pkglib_path up into main.c too.
[postgresql] / src / backend / main / main.c
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-2003, 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.79 2004/05/18 20:27:24 momjian 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 "miscadmin.h"
38 #include "bootstrap/bootstrap.h"
39 #include "tcop/tcopprot.h"
40 #include "utils/help_config.h"
41 #include "utils/ps_status.h"
42 #include "pgstat.h"
43 #ifdef WIN32
44 #include "libpq/pqsignal.h"
45 #endif
46
47
48
49 int
50 main(int argc, char *argv[])
51 {
52         int                     len;
53 #ifndef WIN32
54         struct passwd *pw;
55 #endif
56         char       *pw_name_persist;
57
58         /*
59          * Place platform-specific startup hacks here.  This is the right
60          * place to put code that must be executed early in launch of either a
61          * postmaster, a standalone backend, or a standalone bootstrap run.
62          * Note that this code will NOT be executed when a backend or
63          * sub-bootstrap run is forked by the postmaster.
64          *
65          * XXX The need for code here is proof that the platform in question is
66          * too brain-dead to provide a standard C execution environment
67          * without help.  Avoid adding more here, if you can.
68          */
69
70 #if defined(__alpha)    /* no __alpha__ ? */
71 #ifdef NOFIXADE
72         int                     buffer[] = {SSIN_UACPROC, UAC_SIGBUS};
73 #endif   /* NOFIXADE */
74 #ifdef NOPRINTADE
75         int                     buffer[] = {SSIN_UACPROC, UAC_NOPRINT};
76 #endif   /* NOPRINTADE */
77 #endif   /* __alpha */
78
79 #ifdef WIN32
80         char *env_locale;
81 #endif
82
83 #if defined(NOFIXADE) || defined(NOPRINTADE)
84
85 #if defined(ultrix4)
86         syscall(SYS_sysmips, MIPS_FIXADE, 0, NULL, NULL, NULL);
87 #endif
88
89 #if defined(__alpha)    /* no __alpha__ ? */
90         if (setsysinfo(SSI_NVPAIRS, buffer, 1, (caddr_t) NULL,
91                                    (unsigned long) NULL) < 0)
92                 fprintf(stderr, gettext("%s: setsysinfo failed: %s\n"),
93                                 argv[0], strerror(errno));
94 #endif
95 #endif   /* NOFIXADE || NOPRINTADE */
96
97 #if defined(WIN32)
98         {
99                 WSADATA wsaData;
100                 int err;
101
102                 /* Make output streams unbuffered by default */
103                 setvbuf(stdout,NULL,_IONBF,0);
104                 setvbuf(stderr,NULL,_IONBF,0);
105
106                 /* Prepare Winsock */
107                 err = WSAStartup(MAKEWORD(2,2), &wsaData);
108                 if (err != 0)
109                 {
110                         fprintf(stderr, "%s: WSAStartup failed: %d\n",
111                                         argv[0], err);
112                         exit(1);
113                 }
114
115                 /* Start our win32 signal implementation */
116                 pgwin32_signal_initialize();
117         }
118 #endif
119
120 #ifdef __BEOS__
121         /* BeOS-specific actions on startup */
122         beos_startup(argc, argv);
123 #endif
124
125         /*
126          * Not-quite-so-platform-specific startup environment checks. Still
127          * best to minimize these.
128          */
129
130         /*
131          * Remember the physical location of the initially given argv[] array
132          * for possible use by ps display.  On some platforms, the argv[]
133          * storage must be overwritten in order to set the process title for ps.
134          * In such cases save_ps_display_args makes and returns a new copy of
135          * the argv[] array.
136          *
137          * save_ps_display_args may also move the environment strings to make
138          * extra room. Therefore this should be done as early as possible during
139          * startup, to avoid entanglements with code that might save a getenv()
140          * result pointer.
141          */
142         argv = save_ps_display_args(argc, argv);
143
144         /*
145          * Set up locale information from environment.  Note that LC_CTYPE and
146          * LC_COLLATE will be overridden later from pg_control if we are in an
147          * already-initialized database.  We set them here so that they will
148          * be available to fill pg_control during initdb.  LC_MESSAGES will get
149          * set later during GUC option processing, but we set it here to allow
150          * startup error messages to be localized.
151          */
152
153 #ifdef WIN32
154         /* 
155          * Windows uses codepages rather than the environment, so we work around
156          * that by querying the environment explicitly first for LC_COLLATE
157          * and LC_CTYPE. We have to do this because initdb passes those values
158          * in the environment. If there is nothing there we fall back on the
159          * codepage.
160          */
161
162         if ((env_locale = getenv("LC_COLLATE")) != NULL)
163             setlocale(LC_COLLATE,env_locale);
164         else
165           setlocale(LC_COLLATE, "");
166
167         if ((env_locale = getenv("LC_CTYPE")) != NULL)
168             setlocale(LC_CTYPE,env_locale);
169         else
170           setlocale(LC_CTYPE, "");
171 #else
172         setlocale(LC_COLLATE, "");
173         setlocale(LC_CTYPE, "");
174 #endif
175
176 #ifdef LC_MESSAGES
177         setlocale(LC_MESSAGES, "");
178 #endif
179
180         /*
181          * We keep these set to "C" always, except transiently in pg_locale.c;
182          * see that file for explanations.
183          */
184         setlocale(LC_MONETARY, "C");
185         setlocale(LC_NUMERIC, "C");
186         setlocale(LC_TIME, "C");
187
188 #ifdef ENABLE_NLS
189         bindtextdomain("postgres", LOCALEDIR);
190         textdomain("postgres");
191 #endif
192
193         /*
194          * Skip permission checks if we're just trying to do --help or
195          * --version; otherwise root will get unhelpful failure messages from
196          * initdb.
197          */
198         if (!(argc > 1
199                   && (strcmp(argv[1], "--help") == 0 ||
200                           strcmp(argv[1], "-?") == 0 ||
201                           strcmp(argv[1], "--version") == 0 ||
202                           strcmp(argv[1], "-V") == 0)))
203         {
204 #ifndef WIN32
205 #ifndef __BEOS__
206
207                 /*
208                  * Make sure we are not running as root.
209                  *
210                  * BeOS currently runs everything as root :-(, so this check must be
211                  * temporarily disabled there...
212                  */
213                 if (geteuid() == 0)
214                 {
215                         fprintf(stderr,
216                                         gettext("\"root\" execution of the PostgreSQL server is not permitted.\n"
217                                                         "The server must be started under an unprivileged user ID to prevent\n"
218                                                         "possible system security compromise.  See the documentation for\n"
219                                                         "more information on how to properly start the server.\n"
220                                                         ));
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                         fprintf(stderr,
237                                  gettext("%s: real and effective user IDs must match\n"),
238                                         argv[0]);
239                         exit(1);
240                 }
241 #endif   /* !WIN32 */
242         }
243
244         if (find_my_exec(argv[0], my_exec_path) < 0)
245         {
246                 fprintf(stderr,
247                                 gettext("%s: could not locate my own executable path"),
248                                                 argv[0]);
249                 exit(1);
250         }
251         
252         get_pkglib_path(my_exec_path, pkglib_path);
253
254         /*
255          * Now dispatch to one of PostmasterMain, PostgresMain, GucInfoMain,
256          * SubPostmasterMain, pgstat_main, pgstat_mainChild or BootstrapMain
257          * depending on the program name (and possibly first argument) we
258          * were called with. The lack of consistency here is historical.
259          */
260         len = strlen(argv[0]);
261
262         if ((len >= 10 && strcmp(argv[0] + len - 10, "postmaster") == 0)
263 #ifdef WIN32
264                 || (len >= 14 && strcmp(argv[0] + len - 14, "postmaster.exe") == 0)
265 #endif
266                 )
267         {
268                 /* Called as "postmaster" */
269                 exit(PostmasterMain(argc, argv));
270         }
271
272         /*
273          * If the first argument is "-boot", then invoke bootstrap mode. Note
274          * we remove "-boot" from the arguments passed on to BootstrapMain.
275          */
276         if (argc > 1 && strcmp(argv[1], "-boot") == 0)
277                 exit(BootstrapMain(argc - 1, argv + 1));
278
279 #ifdef EXEC_BACKEND
280         /*
281          * If the first argument is "-forkexec", then invoke SubPostmasterMain. Note
282          * we remove "-forkexec" from the arguments passed on to SubPostmasterMain.
283          */
284         if (argc > 1 && strcmp(argv[1], "-forkexec") == 0)
285         {
286                 SubPostmasterMain(argc - 2, argv + 2);
287                 exit(0);
288         }
289
290         /*
291          * If the first argument is "-statBuf", then invoke pgstat_main. Note
292          * we remove "-statBuf" from the arguments passed on to pgstat_main.
293          */
294         if (argc > 1 && strcmp(argv[1], "-statBuf") == 0)
295         {
296                 pgstat_main(argc - 2, argv + 2);
297                 exit(0);
298         }
299
300         /*
301          * If the first argument is "-statCol", then invoke pgstat_mainChild. Note
302          * we remove "-statCol" from the arguments passed on to pgstat_mainChild.
303          */
304         if (argc > 1 && strcmp(argv[1], "-statCol") == 0)
305         {
306                 pgstat_mainChild(argc - 2, argv + 2);
307                 exit(0);
308         }
309 #endif
310
311         /*
312          * If the first argument is "--describe-config", then invoke runtime
313          * configuration option display mode.
314          */
315         if (argc > 1 && strcmp(argv[1], "--describe-config") == 0)
316                 exit(GucInfoMain());
317
318         /*
319          * Otherwise we're a standalone backend.  Invoke PostgresMain,
320          * specifying current userid as the "authenticated" Postgres user
321          * name.
322          */
323 #ifndef WIN32
324         pw = getpwuid(geteuid());
325         if (pw == NULL)
326         {
327                 fprintf(stderr, gettext("%s: invalid effective UID: %d\n"),
328                                 argv[0], (int) geteuid());
329                 exit(1);
330         }
331         /* Allocate new memory because later getpwuid() calls can overwrite it */
332         pw_name_persist = strdup(pw->pw_name);
333 #else
334         {
335                 long            namesize = 256 /* UNLEN */ + 1;
336
337                 pw_name_persist = malloc(namesize);
338                 if (!GetUserName(pw_name_persist, &namesize))
339                 {
340                         fprintf(stderr, gettext("%s: could not determine user name (GetUserName failed)\n"),
341                                         argv[0]);
342                         exit(1);
343                 }
344         }
345 #endif
346
347         exit(PostgresMain(argc, argv, pw_name_persist));
348 }