LCOV - code coverage report
Current view: top level - src/backend/main - main.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 41 97 42.3 %
Date: 2017-09-29 15:12:54 Functions: 4 5 80.0 %
Legend: Lines: hit not hit

          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-2017, 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           6 : main(int argc, char *argv[])
      61             : {
      62           6 :     bool        do_check_root = true;
      63             : 
      64           6 :     progname = get_progname(argv[0]);
      65             : 
      66             :     /*
      67             :      * Platform-specific startup hacks
      68             :      */
      69           6 :     startup_hacks(progname);
      70             : 
      71             :     /*
      72             :      * Remember the physical location of the initially given argv[] array for
      73             :      * possible use by ps display.  On some platforms, the argv[] storage must
      74             :      * be overwritten in order to set the process title for ps. In such cases
      75             :      * save_ps_display_args makes and returns a new copy of the argv[] array.
      76             :      *
      77             :      * save_ps_display_args may also move the environment strings to make
      78             :      * extra room. Therefore this should be done as early as possible during
      79             :      * startup, to avoid entanglements with code that might save a getenv()
      80             :      * result pointer.
      81             :      */
      82           6 :     argv = save_ps_display_args(argc, argv);
      83             : 
      84             :     /*
      85             :      * If supported on the current platform, set up a handler to be called if
      86             :      * the backend/postmaster crashes with a fatal signal or exception.
      87             :      */
      88             : #if defined(WIN32) && defined(HAVE_MINIDUMP_TYPE)
      89             :     pgwin32_install_crashdump_handler();
      90             : #endif
      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           6 :     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           6 :     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           6 :     init_locale("LC_COLLATE", LC_COLLATE, "");
     135           6 :     init_locale("LC_CTYPE", LC_CTYPE, "");
     136             : #endif
     137             : 
     138             : #ifdef LC_MESSAGES
     139           6 :     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           6 :     init_locale("LC_MONETARY", LC_MONETARY, "C");
     147           6 :     init_locale("LC_NUMERIC", LC_NUMERIC, "C");
     148           6 :     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           6 :     unsetenv("LC_ALL");
     156             : 
     157           6 :     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           6 :     if (argc > 1)
     164             :     {
     165           6 :         if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
     166             :         {
     167           0 :             help(progname);
     168           0 :             exit(0);
     169             :         }
     170           6 :         if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
     171             :         {
     172           1 :             fputs(PG_BACKEND_VERSIONSTR, stdout);
     173           1 :             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           5 :         if (strcmp(argv[1], "--describe-config") == 0)
     187           0 :             do_check_root = false;
     188           5 :         else if (argc > 2 && strcmp(argv[1], "-C") == 0)
     189           0 :             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           5 :     if (do_check_root)
     197           5 :         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           5 :     if (argc > 1 && strcmp(argv[1], "--boot") == 0)
     220           3 :         AuxiliaryProcessMain(argc, argv);   /* does not return */
     221           2 :     else if (argc > 1 && strcmp(argv[1], "--describe-config") == 0)
     222           0 :         GucInfoMain();          /* does not return */
     223           2 :     else if (argc > 1 && strcmp(argv[1], "--single") == 0)
     224           1 :         PostgresMain(argc, argv,
     225             :                      NULL,      /* no dbname */
     226           1 :                      strdup(get_user_name_or_exit(progname)));  /* does not return */
     227             :     else
     228           1 :         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           6 : 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           6 :     SpinLockInit(&dummy_spinlock);
     296           6 : }
     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          36 : init_locale(const char *categoryname, int category, const char *locale)
     308             : {
     309          36 :     if (pg_perm_setlocale(category, locale) == NULL &&
     310           0 :         pg_perm_setlocale(category, "C") == NULL)
     311           0 :         elog(FATAL, "could not adopt \"%s\" locale nor C locale for %s",
     312             :              locale, categoryname);
     313          36 : }
     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           0 : help(const char *progname)
     327             : {
     328           0 :     printf(_("%s is the PostgreSQL server.\n\n"), progname);
     329           0 :     printf(_("Usage:\n  %s [OPTION]...\n\n"), progname);
     330           0 :     printf(_("Options:\n"));
     331           0 :     printf(_("  -B NBUFFERS        number of shared buffers\n"));
     332           0 :     printf(_("  -c NAME=VALUE      set run-time parameter\n"));
     333           0 :     printf(_("  -C NAME            print value of run-time parameter, then exit\n"));
     334           0 :     printf(_("  -d 1-5             debugging level\n"));
     335           0 :     printf(_("  -D DATADIR         database directory\n"));
     336           0 :     printf(_("  -e                 use European date input format (DMY)\n"));
     337           0 :     printf(_("  -F                 turn fsync off\n"));
     338           0 :     printf(_("  -h HOSTNAME        host name or IP address to listen on\n"));
     339           0 :     printf(_("  -i                 enable TCP/IP connections\n"));
     340           0 :     printf(_("  -k DIRECTORY       Unix-domain socket location\n"));
     341             : #ifdef USE_SSL
     342             :     printf(_("  -l                 enable SSL connections\n"));
     343             : #endif
     344           0 :     printf(_("  -N MAX-CONNECT     maximum number of allowed connections\n"));
     345           0 :     printf(_("  -o OPTIONS         pass \"OPTIONS\" to each server process (obsolete)\n"));
     346           0 :     printf(_("  -p PORT            port number to listen on\n"));
     347           0 :     printf(_("  -s                 show statistics after each query\n"));
     348           0 :     printf(_("  -S WORK-MEM        set amount of memory for sorts (in kB)\n"));
     349           0 :     printf(_("  -V, --version      output version information, then exit\n"));
     350           0 :     printf(_("  --NAME=VALUE       set run-time parameter\n"));
     351           0 :     printf(_("  --describe-config  describe configuration parameters, then exit\n"));
     352           0 :     printf(_("  -?, --help         show this help, then exit\n"));
     353             : 
     354           0 :     printf(_("\nDeveloper options:\n"));
     355           0 :     printf(_("  -f s|i|n|m|h       forbid use of some plan types\n"));
     356           0 :     printf(_("  -n                 do not reinitialize shared memory after abnormal exit\n"));
     357           0 :     printf(_("  -O                 allow system table structure changes\n"));
     358           0 :     printf(_("  -P                 disable system indexes\n"));
     359           0 :     printf(_("  -t pa|pl|ex        show timings after each query\n"));
     360           0 :     printf(_("  -T                 send SIGSTOP to all backend processes if one dies\n"));
     361           0 :     printf(_("  -W NUM             wait NUM seconds to allow attach from a debugger\n"));
     362             : 
     363           0 :     printf(_("\nOptions for single-user mode:\n"));
     364           0 :     printf(_("  --single           selects single-user mode (must be first argument)\n"));
     365           0 :     printf(_("  DBNAME             database name (defaults to user name)\n"));
     366           0 :     printf(_("  -d 0-5             override debugging level\n"));
     367           0 :     printf(_("  -E                 echo statement before execution\n"));
     368           0 :     printf(_("  -j                 do not use newline as interactive query delimiter\n"));
     369           0 :     printf(_("  -r FILENAME        send stdout and stderr to given file\n"));
     370             : 
     371           0 :     printf(_("\nOptions for bootstrapping mode:\n"));
     372           0 :     printf(_("  --boot             selects bootstrapping mode (must be first argument)\n"));
     373           0 :     printf(_("  DBNAME             database name (mandatory argument in bootstrapping mode)\n"));
     374           0 :     printf(_("  -r FILENAME        send stdout and stderr to given file\n"));
     375           0 :     printf(_("  -x NUM             internal use\n"));
     376             : 
     377           0 :     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@postgresql.org>.\n"));
     381           0 : }
     382             : 
     383             : 
     384             : 
     385             : static void
     386           5 : check_root(const char *progname)
     387             : {
     388             : #ifndef WIN32
     389           5 :     if (geteuid() == 0)
     390             :     {
     391           0 :         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           0 :         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           5 :     if (getuid() != geteuid())
     407             :     {
     408           0 :         write_stderr("%s: real and effective user IDs must match\n",
     409             :                      progname);
     410           0 :         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           5 : }

Generated by: LCOV version 1.11