1 /*-------------------------------------------------------------------------
4 * Stub main() routine for the postgres executable.
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.
11 * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
12 * Portions Copyright (c) 1994, Regents of the University of California
16 * $PostgreSQL: pgsql/src/backend/main/main.c,v 1.79 2004/05/18 20:27:24 momjian Exp $
18 *-------------------------------------------------------------------------
26 #if defined(__alpha) && defined(__osf__) /* no __alpha__ ? */
27 #include <sys/sysinfo.h>
28 #include "machine/hal_sysinfo.h"
33 #if defined(__NetBSD__)
34 #include <sys/param.h>
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"
44 #include "libpq/pqsignal.h"
50 main(int argc, char *argv[])
56 char *pw_name_persist;
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.
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.
70 #if defined(__alpha) /* no __alpha__ ? */
72 int buffer[] = {SSIN_UACPROC, UAC_SIGBUS};
75 int buffer[] = {SSIN_UACPROC, UAC_NOPRINT};
76 #endif /* NOPRINTADE */
83 #if defined(NOFIXADE) || defined(NOPRINTADE)
86 syscall(SYS_sysmips, MIPS_FIXADE, 0, NULL, NULL, NULL);
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));
95 #endif /* NOFIXADE || NOPRINTADE */
102 /* Make output streams unbuffered by default */
103 setvbuf(stdout,NULL,_IONBF,0);
104 setvbuf(stderr,NULL,_IONBF,0);
106 /* Prepare Winsock */
107 err = WSAStartup(MAKEWORD(2,2), &wsaData);
110 fprintf(stderr, "%s: WSAStartup failed: %d\n",
115 /* Start our win32 signal implementation */
116 pgwin32_signal_initialize();
121 /* BeOS-specific actions on startup */
122 beos_startup(argc, argv);
126 * Not-quite-so-platform-specific startup environment checks. Still
127 * best to minimize these.
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
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()
142 argv = save_ps_display_args(argc, argv);
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.
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
162 if ((env_locale = getenv("LC_COLLATE")) != NULL)
163 setlocale(LC_COLLATE,env_locale);
165 setlocale(LC_COLLATE, "");
167 if ((env_locale = getenv("LC_CTYPE")) != NULL)
168 setlocale(LC_CTYPE,env_locale);
170 setlocale(LC_CTYPE, "");
172 setlocale(LC_COLLATE, "");
173 setlocale(LC_CTYPE, "");
177 setlocale(LC_MESSAGES, "");
181 * We keep these set to "C" always, except transiently in pg_locale.c;
182 * see that file for explanations.
184 setlocale(LC_MONETARY, "C");
185 setlocale(LC_NUMERIC, "C");
186 setlocale(LC_TIME, "C");
189 bindtextdomain("postgres", LOCALEDIR);
190 textdomain("postgres");
194 * Skip permission checks if we're just trying to do --help or
195 * --version; otherwise root will get unhelpful failure messages from
199 && (strcmp(argv[1], "--help") == 0 ||
200 strcmp(argv[1], "-?") == 0 ||
201 strcmp(argv[1], "--version") == 0 ||
202 strcmp(argv[1], "-V") == 0)))
208 * Make sure we are not running as root.
210 * BeOS currently runs everything as root :-(, so this check must be
211 * temporarily disabled there...
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"
223 #endif /* !__BEOS__ */
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.)
234 if (getuid() != geteuid())
237 gettext("%s: real and effective user IDs must match\n"),
244 if (find_my_exec(argv[0], my_exec_path) < 0)
247 gettext("%s: could not locate my own executable path"),
252 get_pkglib_path(my_exec_path, pkglib_path);
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.
260 len = strlen(argv[0]);
262 if ((len >= 10 && strcmp(argv[0] + len - 10, "postmaster") == 0)
264 || (len >= 14 && strcmp(argv[0] + len - 14, "postmaster.exe") == 0)
268 /* Called as "postmaster" */
269 exit(PostmasterMain(argc, argv));
273 * If the first argument is "-boot", then invoke bootstrap mode. Note
274 * we remove "-boot" from the arguments passed on to BootstrapMain.
276 if (argc > 1 && strcmp(argv[1], "-boot") == 0)
277 exit(BootstrapMain(argc - 1, argv + 1));
281 * If the first argument is "-forkexec", then invoke SubPostmasterMain. Note
282 * we remove "-forkexec" from the arguments passed on to SubPostmasterMain.
284 if (argc > 1 && strcmp(argv[1], "-forkexec") == 0)
286 SubPostmasterMain(argc - 2, argv + 2);
291 * If the first argument is "-statBuf", then invoke pgstat_main. Note
292 * we remove "-statBuf" from the arguments passed on to pgstat_main.
294 if (argc > 1 && strcmp(argv[1], "-statBuf") == 0)
296 pgstat_main(argc - 2, argv + 2);
301 * If the first argument is "-statCol", then invoke pgstat_mainChild. Note
302 * we remove "-statCol" from the arguments passed on to pgstat_mainChild.
304 if (argc > 1 && strcmp(argv[1], "-statCol") == 0)
306 pgstat_mainChild(argc - 2, argv + 2);
312 * If the first argument is "--describe-config", then invoke runtime
313 * configuration option display mode.
315 if (argc > 1 && strcmp(argv[1], "--describe-config") == 0)
319 * Otherwise we're a standalone backend. Invoke PostgresMain,
320 * specifying current userid as the "authenticated" Postgres user
324 pw = getpwuid(geteuid());
327 fprintf(stderr, gettext("%s: invalid effective UID: %d\n"),
328 argv[0], (int) geteuid());
331 /* Allocate new memory because later getpwuid() calls can overwrite it */
332 pw_name_persist = strdup(pw->pw_name);
335 long namesize = 256 /* UNLEN */ + 1;
337 pw_name_persist = malloc(namesize);
338 if (!GetUserName(pw_name_persist, &namesize))
340 fprintf(stderr, gettext("%s: could not determine user name (GetUserName failed)\n"),
347 exit(PostgresMain(argc, argv, pw_name_persist));