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