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-2019, 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(__NetBSD__) |
26 | #include <sys/param.h> |
27 | #endif |
28 | |
29 | #if defined(_M_AMD64) && _MSC_VER == 1800 |
30 | #include <math.h> |
31 | #include <versionhelpers.h> |
32 | #endif |
33 | |
34 | #include "bootstrap/bootstrap.h" |
35 | #include "common/username.h" |
36 | #include "port/atomics.h" |
37 | #include "postmaster/postmaster.h" |
38 | #include "storage/s_lock.h" |
39 | #include "storage/spin.h" |
40 | #include "tcop/tcopprot.h" |
41 | #include "utils/help_config.h" |
42 | #include "utils/memutils.h" |
43 | #include "utils/pg_locale.h" |
44 | #include "utils/ps_status.h" |
45 | |
46 | |
47 | const char *progname; |
48 | |
49 | |
50 | static void startup_hacks(const char *progname); |
51 | static void init_locale(const char *categoryname, int category, const char *locale); |
52 | static void help(const char *progname); |
53 | static void check_root(const char *progname); |
54 | |
55 | |
56 | /* |
57 | * Any Postgres server process begins execution here. |
58 | */ |
59 | int |
60 | main(int argc, char *argv[]) |
61 | { |
62 | bool do_check_root = 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) && defined(HAVE_MINIDUMP_TYPE) |
69 | pgwin32_install_crashdump_handler(); |
70 | #endif |
71 | |
72 | progname = get_progname(argv[0]); |
73 | |
74 | /* |
75 | * Platform-specific startup hacks |
76 | */ |
77 | 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 | */ |
90 | 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 | */ |
99 | MemoryContextInit(); |
100 | |
101 | /* |
102 | * Set up locale information from environment. Note that LC_CTYPE and |
103 | * LC_COLLATE will be overridden later from pg_control if we are in an |
104 | * already-initialized database. We set them here so that they will be |
105 | * available to fill pg_control during initdb. LC_MESSAGES will get set |
106 | * later during GUC option processing, but we set it here to allow startup |
107 | * error messages to be localized. |
108 | */ |
109 | |
110 | set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("postgres" )); |
111 | |
112 | #ifdef WIN32 |
113 | |
114 | /* |
115 | * Windows uses codepages rather than the environment, so we work around |
116 | * that by querying the environment explicitly first for LC_COLLATE and |
117 | * LC_CTYPE. We have to do this because initdb passes those values in the |
118 | * environment. If there is nothing there we fall back on the codepage. |
119 | */ |
120 | { |
121 | char *env_locale; |
122 | |
123 | if ((env_locale = getenv("LC_COLLATE" )) != NULL) |
124 | init_locale("LC_COLLATE" , LC_COLLATE, env_locale); |
125 | else |
126 | init_locale("LC_COLLATE" , LC_COLLATE, "" ); |
127 | |
128 | if ((env_locale = getenv("LC_CTYPE" )) != NULL) |
129 | init_locale("LC_CTYPE" , LC_CTYPE, env_locale); |
130 | else |
131 | init_locale("LC_CTYPE" , LC_CTYPE, "" ); |
132 | } |
133 | #else |
134 | init_locale("LC_COLLATE" , LC_COLLATE, "" ); |
135 | init_locale("LC_CTYPE" , LC_CTYPE, "" ); |
136 | #endif |
137 | |
138 | #ifdef LC_MESSAGES |
139 | init_locale("LC_MESSAGES" , LC_MESSAGES, "" ); |
140 | #endif |
141 | |
142 | /* |
143 | * We keep these set to "C" always, except transiently in pg_locale.c; see |
144 | * that file for explanations. |
145 | */ |
146 | init_locale("LC_MONETARY" , LC_MONETARY, "C" ); |
147 | init_locale("LC_NUMERIC" , LC_NUMERIC, "C" ); |
148 | init_locale("LC_TIME" , LC_TIME, "C" ); |
149 | |
150 | /* |
151 | * Now that we have absorbed as much as we wish to from the locale |
152 | * environment, remove any LC_ALL setting, so that the environment |
153 | * variables installed by pg_perm_setlocale have force. |
154 | */ |
155 | unsetenv("LC_ALL" ); |
156 | |
157 | check_strxfrm_bug(); |
158 | |
159 | /* |
160 | * Catch standard options before doing much else, in particular before we |
161 | * insist on not being root. |
162 | */ |
163 | if (argc > 1) |
164 | { |
165 | if (strcmp(argv[1], "--help" ) == 0 || strcmp(argv[1], "-?" ) == 0) |
166 | { |
167 | help(progname); |
168 | exit(0); |
169 | } |
170 | if (strcmp(argv[1], "--version" ) == 0 || strcmp(argv[1], "-V" ) == 0) |
171 | { |
172 | fputs(PG_BACKEND_VERSIONSTR, stdout); |
173 | exit(0); |
174 | } |
175 | |
176 | /* |
177 | * In addition to the above, we allow "--describe-config" and "-C var" |
178 | * to be called by root. This is reasonably safe since these are |
179 | * read-only activities. The -C case is important because pg_ctl may |
180 | * try to invoke it while still holding administrator privileges on |
181 | * Windows. Note that while -C can normally be in any argv position, |
182 | * if you want to bypass the root check you must put it first. This |
183 | * reduces the risk that we might misinterpret some other mode's -C |
184 | * switch as being the postmaster/postgres one. |
185 | */ |
186 | if (strcmp(argv[1], "--describe-config" ) == 0) |
187 | do_check_root = false; |
188 | else if (argc > 2 && strcmp(argv[1], "-C" ) == 0) |
189 | do_check_root = false; |
190 | } |
191 | |
192 | /* |
193 | * Make sure we are not running as root, unless it's safe for the selected |
194 | * option. |
195 | */ |
196 | if (do_check_root) |
197 | check_root(progname); |
198 | |
199 | /* |
200 | * Dispatch to one of various subprograms depending on first argument. |
201 | */ |
202 | |
203 | #ifdef EXEC_BACKEND |
204 | if (argc > 1 && strncmp(argv[1], "--fork" , 6) == 0) |
205 | SubPostmasterMain(argc, argv); /* does not return */ |
206 | #endif |
207 | |
208 | #ifdef WIN32 |
209 | |
210 | /* |
211 | * Start our win32 signal implementation |
212 | * |
213 | * SubPostmasterMain() will do this for itself, but the remaining modes |
214 | * need it here |
215 | */ |
216 | pgwin32_signal_initialize(); |
217 | #endif |
218 | |
219 | if (argc > 1 && strcmp(argv[1], "--boot" ) == 0) |
220 | AuxiliaryProcessMain(argc, argv); /* does not return */ |
221 | else if (argc > 1 && strcmp(argv[1], "--describe-config" ) == 0) |
222 | GucInfoMain(); /* does not return */ |
223 | else if (argc > 1 && strcmp(argv[1], "--single" ) == 0) |
224 | PostgresMain(argc, argv, |
225 | NULL, /* no dbname */ |
226 | strdup(get_user_name_or_exit(progname))); /* does not return */ |
227 | else |
228 | PostmasterMain(argc, argv); /* does not return */ |
229 | abort(); /* should not get here */ |
230 | } |
231 | |
232 | |
233 | |
234 | /* |
235 | * Place platform-specific startup hacks here. This is the right |
236 | * place to put code that must be executed early in the launch of any new |
237 | * server process. Note that this code will NOT be executed when a backend |
238 | * or sub-bootstrap process is forked, unless we are in a fork/exec |
239 | * environment (ie EXEC_BACKEND is defined). |
240 | * |
241 | * XXX The need for code here is proof that the platform in question |
242 | * is too brain-dead to provide a standard C execution environment |
243 | * without help. Avoid adding more here, if you can. |
244 | */ |
245 | static void |
246 | startup_hacks(const char *progname) |
247 | { |
248 | /* |
249 | * Windows-specific execution environment hacking. |
250 | */ |
251 | #ifdef WIN32 |
252 | { |
253 | WSADATA wsaData; |
254 | int err; |
255 | |
256 | /* Make output streams unbuffered by default */ |
257 | setvbuf(stdout, NULL, _IONBF, 0); |
258 | setvbuf(stderr, NULL, _IONBF, 0); |
259 | |
260 | /* Prepare Winsock */ |
261 | err = WSAStartup(MAKEWORD(2, 2), &wsaData); |
262 | if (err != 0) |
263 | { |
264 | write_stderr("%s: WSAStartup failed: %d\n" , |
265 | progname, err); |
266 | exit(1); |
267 | } |
268 | |
269 | /* In case of general protection fault, don't show GUI popup box */ |
270 | SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); |
271 | |
272 | #if defined(_M_AMD64) && _MSC_VER == 1800 |
273 | |
274 | /*---------- |
275 | * Avoid crashing in certain floating-point operations if we were |
276 | * compiled for x64 with MS Visual Studio 2013 and are running on |
277 | * Windows prior to 7/2008R2 SP1 on an AVX2-capable CPU. |
278 | * |
279 | * Ref: https://connect.microsoft.com/VisualStudio/feedback/details/811093/visual-studio-2013-rtm-c-x64-code-generation-bug-for-avx2-instructions |
280 | *---------- |
281 | */ |
282 | if (!IsWindows7SP1OrGreater()) |
283 | { |
284 | _set_FMA3_enable(0); |
285 | } |
286 | #endif /* defined(_M_AMD64) && _MSC_VER == 1800 */ |
287 | |
288 | } |
289 | #endif /* WIN32 */ |
290 | |
291 | /* |
292 | * Initialize dummy_spinlock, in case we are on a platform where we have |
293 | * to use the fallback implementation of pg_memory_barrier(). |
294 | */ |
295 | SpinLockInit(&dummy_spinlock); |
296 | } |
297 | |
298 | |
299 | /* |
300 | * Make the initial permanent setting for a locale category. If that fails, |
301 | * perhaps due to LC_foo=invalid in the environment, use locale C. If even |
302 | * that fails, perhaps due to out-of-memory, the entire startup fails with it. |
303 | * When this returns, we are guaranteed to have a setting for the given |
304 | * category's environment variable. |
305 | */ |
306 | static void |
307 | init_locale(const char *categoryname, int category, const char *locale) |
308 | { |
309 | if (pg_perm_setlocale(category, locale) == NULL && |
310 | pg_perm_setlocale(category, "C" ) == NULL) |
311 | elog(FATAL, "could not adopt \"%s\" locale nor C locale for %s" , |
312 | locale, categoryname); |
313 | } |
314 | |
315 | |
316 | |
317 | /* |
318 | * Help display should match the options accepted by PostmasterMain() |
319 | * and PostgresMain(). |
320 | * |
321 | * XXX On Windows, non-ASCII localizations of these messages only display |
322 | * correctly if the console output code page covers the necessary characters. |
323 | * Messages emitted in write_console() do not exhibit this problem. |
324 | */ |
325 | static void |
326 | help(const char *progname) |
327 | { |
328 | printf(_("%s is the PostgreSQL server.\n\n" ), progname); |
329 | printf(_("Usage:\n %s [OPTION]...\n\n" ), progname); |
330 | printf(_("Options:\n" )); |
331 | printf(_(" -B NBUFFERS number of shared buffers\n" )); |
332 | printf(_(" -c NAME=VALUE set run-time parameter\n" )); |
333 | printf(_(" -C NAME print value of run-time parameter, then exit\n" )); |
334 | printf(_(" -d 1-5 debugging level\n" )); |
335 | printf(_(" -D DATADIR database directory\n" )); |
336 | printf(_(" -e use European date input format (DMY)\n" )); |
337 | printf(_(" -F turn fsync off\n" )); |
338 | printf(_(" -h HOSTNAME host name or IP address to listen on\n" )); |
339 | printf(_(" -i enable TCP/IP connections\n" )); |
340 | printf(_(" -k DIRECTORY Unix-domain socket location\n" )); |
341 | #ifdef USE_SSL |
342 | printf(_(" -l enable SSL connections\n" )); |
343 | #endif |
344 | printf(_(" -N MAX-CONNECT maximum number of allowed connections\n" )); |
345 | printf(_(" -o OPTIONS pass \"OPTIONS\" to each server process (obsolete)\n" )); |
346 | printf(_(" -p PORT port number to listen on\n" )); |
347 | printf(_(" -s show statistics after each query\n" )); |
348 | printf(_(" -S WORK-MEM set amount of memory for sorts (in kB)\n" )); |
349 | printf(_(" -V, --version output version information, then exit\n" )); |
350 | printf(_(" --NAME=VALUE set run-time parameter\n" )); |
351 | printf(_(" --describe-config describe configuration parameters, then exit\n" )); |
352 | printf(_(" -?, --help show this help, then exit\n" )); |
353 | |
354 | printf(_("\nDeveloper options:\n" )); |
355 | printf(_(" -f s|i|n|m|h forbid use of some plan types\n" )); |
356 | printf(_(" -n do not reinitialize shared memory after abnormal exit\n" )); |
357 | printf(_(" -O allow system table structure changes\n" )); |
358 | printf(_(" -P disable system indexes\n" )); |
359 | printf(_(" -t pa|pl|ex show timings after each query\n" )); |
360 | printf(_(" -T send SIGSTOP to all backend processes if one dies\n" )); |
361 | printf(_(" -W NUM wait NUM seconds to allow attach from a debugger\n" )); |
362 | |
363 | printf(_("\nOptions for single-user mode:\n" )); |
364 | printf(_(" --single selects single-user mode (must be first argument)\n" )); |
365 | printf(_(" DBNAME database name (defaults to user name)\n" )); |
366 | printf(_(" -d 0-5 override debugging level\n" )); |
367 | printf(_(" -E echo statement before execution\n" )); |
368 | printf(_(" -j do not use newline as interactive query delimiter\n" )); |
369 | printf(_(" -r FILENAME send stdout and stderr to given file\n" )); |
370 | |
371 | printf(_("\nOptions for bootstrapping mode:\n" )); |
372 | printf(_(" --boot selects bootstrapping mode (must be first argument)\n" )); |
373 | printf(_(" DBNAME database name (mandatory argument in bootstrapping mode)\n" )); |
374 | printf(_(" -r FILENAME send stdout and stderr to given file\n" )); |
375 | printf(_(" -x NUM internal use\n" )); |
376 | |
377 | printf(_("\nPlease read the documentation for the complete list of run-time\n" |
378 | "configuration settings and how to set them on the command line or in\n" |
379 | "the configuration file.\n\n" |
380 | "Report bugs to <pgsql-bugs@lists.postgresql.org>.\n" )); |
381 | } |
382 | |
383 | |
384 | |
385 | static void |
386 | check_root(const char *progname) |
387 | { |
388 | #ifndef WIN32 |
389 | if (geteuid() == 0) |
390 | { |
391 | write_stderr("\"root\" execution of the PostgreSQL server is not permitted.\n" |
392 | "The server must be started under an unprivileged user ID to prevent\n" |
393 | "possible system security compromise. See the documentation for\n" |
394 | "more information on how to properly start the server.\n" ); |
395 | exit(1); |
396 | } |
397 | |
398 | /* |
399 | * Also make sure that real and effective uids are the same. Executing as |
400 | * a setuid program from a root shell is a security hole, since on many |
401 | * platforms a nefarious subroutine could setuid back to root if real uid |
402 | * is root. (Since nobody actually uses postgres as a setuid program, |
403 | * trying to actively fix this situation seems more trouble than it's |
404 | * worth; we'll just expend the effort to check for it.) |
405 | */ |
406 | if (getuid() != geteuid()) |
407 | { |
408 | write_stderr("%s: real and effective user IDs must match\n" , |
409 | progname); |
410 | exit(1); |
411 | } |
412 | #else /* WIN32 */ |
413 | if (pgwin32_is_admin()) |
414 | { |
415 | write_stderr("Execution of PostgreSQL by a user with administrative permissions is not\n" |
416 | "permitted.\n" |
417 | "The server must be started under an unprivileged user ID to prevent\n" |
418 | "possible system security compromises. See the documentation for\n" |
419 | "more information on how to properly start the server.\n" ); |
420 | exit(1); |
421 | } |
422 | #endif /* WIN32 */ |
423 | } |
424 | |