Line data Source code
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, standalone bootstrap process, or a
8 : * separately exec'd child of a postmaster) and then dispatches to the
9 : * proper FooMain() routine for the incarnation.
10 : *
11 : *
12 : * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
13 : * Portions Copyright (c) 1994, Regents of the University of California
14 : *
15 : *
16 : * IDENTIFICATION
17 : * src/backend/main/main.c
18 : *
19 : *-------------------------------------------------------------------------
20 : */
21 : #include "postgres.h"
22 :
23 : #include <unistd.h>
24 :
25 : #if defined(WIN32)
26 : #include <crtdbg.h>
27 : #endif
28 :
29 : #if defined(__NetBSD__)
30 : #include <sys/param.h>
31 : #endif
32 :
33 : #if defined(_M_AMD64) && _MSC_VER == 1800
34 : #include <math.h>
35 : #include <versionhelpers.h>
36 : #endif
37 :
38 : #include "bootstrap/bootstrap.h"
39 : #include "common/username.h"
40 : #include "port/atomics.h"
41 : #include "postmaster/postmaster.h"
42 : #include "storage/spin.h"
43 : #include "tcop/tcopprot.h"
44 : #include "utils/help_config.h"
45 : #include "utils/memutils.h"
46 : #include "utils/pg_locale.h"
47 : #include "utils/ps_status.h"
48 :
49 :
50 : const char *progname;
51 :
52 :
53 : static void startup_hacks(const char *progname);
54 : static void init_locale(const char *categoryname, int category, const char *locale);
55 : static void help(const char *progname);
56 : static void check_root(const char *progname);
57 :
58 :
59 : /*
60 : * Any Postgres server process begins execution here.
61 : */
62 : int
63 4554 : main(int argc, char *argv[])
64 : {
65 4554 : bool do_check_root = true;
66 :
67 : /*
68 : * If supported on the current platform, set up a handler to be called if
69 : * the backend/postmaster crashes with a fatal signal or exception.
70 : */
71 : #if defined(WIN32) && defined(HAVE_MINIDUMP_TYPE)
72 : pgwin32_install_crashdump_handler();
73 : #endif
74 :
75 4554 : progname = get_progname(argv[0]);
76 :
77 : /*
78 : * Platform-specific startup hacks
79 : */
80 4554 : startup_hacks(progname);
81 :
82 : /*
83 : * Remember the physical location of the initially given argv[] array for
84 : * possible use by ps display. On some platforms, the argv[] storage must
85 : * be overwritten in order to set the process title for ps. In such cases
86 : * save_ps_display_args makes and returns a new copy of the argv[] array.
87 : *
88 : * save_ps_display_args may also move the environment strings to make
89 : * extra room. Therefore this should be done as early as possible during
90 : * startup, to avoid entanglements with code that might save a getenv()
91 : * result pointer.
92 : */
93 4554 : argv = save_ps_display_args(argc, argv);
94 :
95 : /*
96 : * Fire up essential subsystems: error and memory management
97 : *
98 : * Code after this point is allowed to use elog/ereport, though
99 : * localization of messages may not work right away, and messages won't go
100 : * anywhere but stderr until GUC settings get loaded.
101 : */
102 4554 : MemoryContextInit();
103 :
104 : /*
105 : * Set up locale information
106 : */
107 4554 : set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("postgres"));
108 :
109 : /*
110 : * In the postmaster, absorb the environment values for LC_COLLATE and
111 : * LC_CTYPE. Individual backends will change these later to settings
112 : * taken from pg_database, but the postmaster cannot do that. If we leave
113 : * these set to "C" then message localization might not work well in the
114 : * postmaster.
115 : */
116 4554 : init_locale("LC_COLLATE", LC_COLLATE, "");
117 4554 : init_locale("LC_CTYPE", LC_CTYPE, "");
118 :
119 : /*
120 : * LC_MESSAGES will get set later during GUC option processing, but we set
121 : * it here to allow startup error messages to be localized.
122 : */
123 : #ifdef LC_MESSAGES
124 4554 : init_locale("LC_MESSAGES", LC_MESSAGES, "");
125 : #endif
126 :
127 : /*
128 : * We keep these set to "C" always, except transiently in pg_locale.c; see
129 : * that file for explanations.
130 : */
131 4554 : init_locale("LC_MONETARY", LC_MONETARY, "C");
132 4554 : init_locale("LC_NUMERIC", LC_NUMERIC, "C");
133 4554 : init_locale("LC_TIME", LC_TIME, "C");
134 :
135 : /*
136 : * Now that we have absorbed as much as we wish to from the locale
137 : * environment, remove any LC_ALL setting, so that the environment
138 : * variables installed by pg_perm_setlocale have force.
139 : */
140 4554 : unsetenv("LC_ALL");
141 :
142 4554 : check_strxfrm_bug();
143 :
144 : /*
145 : * Catch standard options before doing much else, in particular before we
146 : * insist on not being root.
147 : */
148 4554 : if (argc > 1)
149 : {
150 4554 : if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
151 : {
152 0 : help(progname);
153 0 : exit(0);
154 : }
155 4554 : if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
156 : {
157 1344 : fputs(PG_BACKEND_VERSIONSTR, stdout);
158 1344 : exit(0);
159 : }
160 :
161 : /*
162 : * In addition to the above, we allow "--describe-config" and "-C var"
163 : * to be called by root. This is reasonably safe since these are
164 : * read-only activities. The -C case is important because pg_ctl may
165 : * try to invoke it while still holding administrator privileges on
166 : * Windows. Note that while -C can normally be in any argv position,
167 : * if you want to bypass the root check you must put it first. This
168 : * reduces the risk that we might misinterpret some other mode's -C
169 : * switch as being the postmaster/postgres one.
170 : */
171 3210 : if (strcmp(argv[1], "--describe-config") == 0)
172 0 : do_check_root = false;
173 3210 : else if (argc > 2 && strcmp(argv[1], "-C") == 0)
174 0 : do_check_root = false;
175 : }
176 :
177 : /*
178 : * Make sure we are not running as root, unless it's safe for the selected
179 : * option.
180 : */
181 3210 : if (do_check_root)
182 3210 : check_root(progname);
183 :
184 : /*
185 : * Dispatch to one of various subprograms depending on first argument.
186 : */
187 :
188 3210 : if (argc > 1 && strcmp(argv[1], "--check") == 0)
189 1064 : BootstrapModeMain(argc, argv, true);
190 2146 : else if (argc > 1 && strcmp(argv[1], "--boot") == 0)
191 532 : BootstrapModeMain(argc, argv, false);
192 : #ifdef EXEC_BACKEND
193 : else if (argc > 1 && strncmp(argv[1], "--fork", 6) == 0)
194 : SubPostmasterMain(argc, argv);
195 : #endif
196 1614 : else if (argc > 1 && strcmp(argv[1], "--describe-config") == 0)
197 0 : GucInfoMain();
198 1614 : else if (argc > 1 && strcmp(argv[1], "--single") == 0)
199 554 : PostgresSingleUserMain(argc, argv,
200 554 : strdup(get_user_name_or_exit(progname)));
201 : else
202 1060 : PostmasterMain(argc, argv);
203 : /* the functions above should not return */
204 : abort();
205 : }
206 :
207 :
208 :
209 : /*
210 : * Place platform-specific startup hacks here. This is the right
211 : * place to put code that must be executed early in the launch of any new
212 : * server process. Note that this code will NOT be executed when a backend
213 : * or sub-bootstrap process is forked, unless we are in a fork/exec
214 : * environment (ie EXEC_BACKEND is defined).
215 : *
216 : * XXX The need for code here is proof that the platform in question
217 : * is too brain-dead to provide a standard C execution environment
218 : * without help. Avoid adding more here, if you can.
219 : */
220 : static void
221 4554 : startup_hacks(const char *progname)
222 : {
223 : /*
224 : * Windows-specific execution environment hacking.
225 : */
226 : #ifdef WIN32
227 : {
228 : WSADATA wsaData;
229 : int err;
230 :
231 : /* Make output streams unbuffered by default */
232 : setvbuf(stdout, NULL, _IONBF, 0);
233 : setvbuf(stderr, NULL, _IONBF, 0);
234 :
235 : /* Prepare Winsock */
236 : err = WSAStartup(MAKEWORD(2, 2), &wsaData);
237 : if (err != 0)
238 : {
239 : write_stderr("%s: WSAStartup failed: %d\n",
240 : progname, err);
241 : exit(1);
242 : }
243 :
244 : /*
245 : * By default abort() only generates a crash-dump in *non* debug
246 : * builds. As our Assert() / ExceptionalCondition() uses abort(),
247 : * leaving the default in place would make debugging harder.
248 : *
249 : * MINGW's own C runtime doesn't have _set_abort_behavior(). When
250 : * targeting Microsoft's UCRT with mingw, it never links to the debug
251 : * version of the library and thus doesn't need the call to
252 : * _set_abort_behavior() either.
253 : */
254 : #if !defined(__MINGW32__) && !defined(__MINGW64__)
255 : _set_abort_behavior(_CALL_REPORTFAULT | _WRITE_ABORT_MSG,
256 : _CALL_REPORTFAULT | _WRITE_ABORT_MSG);
257 : #endif /* !defined(__MINGW32__) &&
258 : * !defined(__MINGW64__) */
259 :
260 : /*
261 : * SEM_FAILCRITICALERRORS causes more errors to be reported to
262 : * callers.
263 : *
264 : * We used to also specify SEM_NOGPFAULTERRORBOX, but that prevents
265 : * windows crash reporting from working. Which includes registered
266 : * just-in-time debuggers, making it unnecessarily hard to debug
267 : * problems on windows. Now we try to disable sources of popups
268 : * separately below (note that SEM_NOGPFAULTERRORBOX did not actually
269 : * prevent all sources of such popups).
270 : */
271 : SetErrorMode(SEM_FAILCRITICALERRORS);
272 :
273 : /*
274 : * Show errors on stderr instead of popup box (note this doesn't
275 : * affect errors originating in the C runtime, see below).
276 : */
277 : _set_error_mode(_OUT_TO_STDERR);
278 :
279 : /*
280 : * In DEBUG builds, errors, including assertions, C runtime errors are
281 : * reported via _CrtDbgReport. By default such errors are displayed
282 : * with a popup (even with NOGPFAULTERRORBOX), preventing forward
283 : * progress. Instead report such errors stderr (and the debugger).
284 : * This is C runtime specific and thus the above incantations aren't
285 : * sufficient to suppress these popups.
286 : */
287 : _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
288 : _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
289 : _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
290 : _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
291 : _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
292 : _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
293 :
294 : #if defined(_M_AMD64) && _MSC_VER == 1800
295 :
296 : /*----------
297 : * Avoid crashing in certain floating-point operations if we were
298 : * compiled for x64 with MS Visual Studio 2013 and are running on
299 : * Windows prior to 7/2008R2 SP1 on an AVX2-capable CPU.
300 : *
301 : * Ref: https://connect.microsoft.com/VisualStudio/feedback/details/811093/visual-studio-2013-rtm-c-x64-code-generation-bug-for-avx2-instructions
302 : *----------
303 : */
304 : if (!IsWindows7SP1OrGreater())
305 : {
306 : _set_FMA3_enable(0);
307 : }
308 : #endif /* defined(_M_AMD64) && _MSC_VER == 1800 */
309 :
310 : }
311 : #endif /* WIN32 */
312 :
313 : /*
314 : * Initialize dummy_spinlock, in case we are on a platform where we have
315 : * to use the fallback implementation of pg_memory_barrier().
316 : */
317 4554 : SpinLockInit(&dummy_spinlock);
318 4554 : }
319 :
320 :
321 : /*
322 : * Make the initial permanent setting for a locale category. If that fails,
323 : * perhaps due to LC_foo=invalid in the environment, use locale C. If even
324 : * that fails, perhaps due to out-of-memory, the entire startup fails with it.
325 : * When this returns, we are guaranteed to have a setting for the given
326 : * category's environment variable.
327 : */
328 : static void
329 27324 : init_locale(const char *categoryname, int category, const char *locale)
330 : {
331 27324 : if (pg_perm_setlocale(category, locale) == NULL &&
332 0 : pg_perm_setlocale(category, "C") == NULL)
333 0 : elog(FATAL, "could not adopt \"%s\" locale nor C locale for %s",
334 : locale, categoryname);
335 27324 : }
336 :
337 :
338 :
339 : /*
340 : * Help display should match the options accepted by PostmasterMain()
341 : * and PostgresMain().
342 : *
343 : * XXX On Windows, non-ASCII localizations of these messages only display
344 : * correctly if the console output code page covers the necessary characters.
345 : * Messages emitted in write_console() do not exhibit this problem.
346 : */
347 : static void
348 0 : help(const char *progname)
349 : {
350 0 : printf(_("%s is the PostgreSQL server.\n\n"), progname);
351 0 : printf(_("Usage:\n %s [OPTION]...\n\n"), progname);
352 0 : printf(_("Options:\n"));
353 0 : printf(_(" -B NBUFFERS number of shared buffers\n"));
354 0 : printf(_(" -c NAME=VALUE set run-time parameter\n"));
355 0 : printf(_(" -C NAME print value of run-time parameter, then exit\n"));
356 0 : printf(_(" -d 1-5 debugging level\n"));
357 0 : printf(_(" -D DATADIR database directory\n"));
358 0 : printf(_(" -e use European date input format (DMY)\n"));
359 0 : printf(_(" -F turn fsync off\n"));
360 0 : printf(_(" -h HOSTNAME host name or IP address to listen on\n"));
361 0 : printf(_(" -i enable TCP/IP connections\n"));
362 0 : printf(_(" -k DIRECTORY Unix-domain socket location\n"));
363 : #ifdef USE_SSL
364 0 : printf(_(" -l enable SSL connections\n"));
365 : #endif
366 0 : printf(_(" -N MAX-CONNECT maximum number of allowed connections\n"));
367 0 : printf(_(" -p PORT port number to listen on\n"));
368 0 : printf(_(" -s show statistics after each query\n"));
369 0 : printf(_(" -S WORK-MEM set amount of memory for sorts (in kB)\n"));
370 0 : printf(_(" -V, --version output version information, then exit\n"));
371 0 : printf(_(" --NAME=VALUE set run-time parameter\n"));
372 0 : printf(_(" --describe-config describe configuration parameters, then exit\n"));
373 0 : printf(_(" -?, --help show this help, then exit\n"));
374 :
375 0 : printf(_("\nDeveloper options:\n"));
376 0 : printf(_(" -f s|i|n|m|h forbid use of some plan types\n"));
377 0 : printf(_(" -n do not reinitialize shared memory after abnormal exit\n"));
378 0 : printf(_(" -O allow system table structure changes\n"));
379 0 : printf(_(" -P disable system indexes\n"));
380 0 : printf(_(" -t pa|pl|ex show timings after each query\n"));
381 0 : printf(_(" -T send SIGSTOP to all backend processes if one dies\n"));
382 0 : printf(_(" -W NUM wait NUM seconds to allow attach from a debugger\n"));
383 :
384 0 : printf(_("\nOptions for single-user mode:\n"));
385 0 : printf(_(" --single selects single-user mode (must be first argument)\n"));
386 0 : printf(_(" DBNAME database name (defaults to user name)\n"));
387 0 : printf(_(" -d 0-5 override debugging level\n"));
388 0 : printf(_(" -E echo statement before execution\n"));
389 0 : printf(_(" -j do not use newline as interactive query delimiter\n"));
390 0 : printf(_(" -r FILENAME send stdout and stderr to given file\n"));
391 :
392 0 : printf(_("\nOptions for bootstrapping mode:\n"));
393 0 : printf(_(" --boot selects bootstrapping mode (must be first argument)\n"));
394 0 : printf(_(" --check selects check mode (must be first argument)\n"));
395 0 : printf(_(" DBNAME database name (mandatory argument in bootstrapping mode)\n"));
396 0 : printf(_(" -r FILENAME send stdout and stderr to given file\n"));
397 :
398 0 : printf(_("\nPlease read the documentation for the complete list of run-time\n"
399 : "configuration settings and how to set them on the command line or in\n"
400 : "the configuration file.\n\n"
401 : "Report bugs to <%s>.\n"), PACKAGE_BUGREPORT);
402 0 : printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
403 0 : }
404 :
405 :
406 :
407 : static void
408 3210 : check_root(const char *progname)
409 : {
410 : #ifndef WIN32
411 3210 : if (geteuid() == 0)
412 : {
413 0 : write_stderr("\"root\" execution of the PostgreSQL server is not permitted.\n"
414 : "The server must be started under an unprivileged user ID to prevent\n"
415 : "possible system security compromise. See the documentation for\n"
416 : "more information on how to properly start the server.\n");
417 0 : exit(1);
418 : }
419 :
420 : /*
421 : * Also make sure that real and effective uids are the same. Executing as
422 : * a setuid program from a root shell is a security hole, since on many
423 : * platforms a nefarious subroutine could setuid back to root if real uid
424 : * is root. (Since nobody actually uses postgres as a setuid program,
425 : * trying to actively fix this situation seems more trouble than it's
426 : * worth; we'll just expend the effort to check for it.)
427 : */
428 3210 : if (getuid() != geteuid())
429 : {
430 0 : write_stderr("%s: real and effective user IDs must match\n",
431 : progname);
432 0 : exit(1);
433 : }
434 : #else /* WIN32 */
435 : if (pgwin32_is_admin())
436 : {
437 : write_stderr("Execution of PostgreSQL by a user with administrative permissions is not\n"
438 : "permitted.\n"
439 : "The server must be started under an unprivileged user ID to prevent\n"
440 : "possible system security compromises. See the documentation for\n"
441 : "more information on how to properly start the server.\n");
442 : exit(1);
443 : }
444 : #endif /* WIN32 */
445 3210 : }
|