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