]> granicus.if.org Git - postgresql/commitdiff
Replace direct fprintf(stderr) calls by write_stderr(), and cause this
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 24 Jun 2004 21:03:42 +0000 (21:03 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 24 Jun 2004 21:03:42 +0000 (21:03 +0000)
routine to do something appropriate on Win32.  Also, add a security check
on Win32 that parallels the can't-run-as-root check on Unix.

Magnus Hagander

13 files changed:
src/backend/bootstrap/bootstrap.c
src/backend/main/main.c
src/backend/nls.mk
src/backend/port/win32/Makefile
src/backend/port/win32/security.c [new file with mode: 0644]
src/backend/port/win32/signal.c
src/backend/postmaster/postmaster.c
src/backend/tcop/postgres.c
src/backend/utils/error/assert.c
src/backend/utils/error/elog.c
src/backend/utils/misc/help_config.c
src/include/port/win32.h
src/include/utils/elog.h

index 553cf79dd0b332adf842564401d5d73032e76c90..ccf0595835e814430042f6cc0c537add295377fb 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.184 2004/06/06 00:41:26 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.185 2004/06/24 21:02:24 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -328,12 +328,11 @@ BootstrapMain(int argc, char *argv[])
        {
                if (!potential_DataDir)
                {
-                       fprintf(stderr,
-                                       gettext("%s does not know where to find the database system data.\n"
-                                                       "You must specify the directory that contains the database system\n"
-                                                       "either by specifying the -D invocation option or by setting the\n"
-                                                       "PGDATA environment variable.\n"),
-                                       argv[0]);
+                       write_stderr("%s does not know where to find the database system data.\n"
+                                                "You must specify the directory that contains the database system\n"
+                                                "either by specifying the -D invocation option or by setting the\n"
+                                                "PGDATA environment variable.\n",
+                                                argv[0]);
                        proc_exit(1);
                }
                SetDataDir(potential_DataDir);
@@ -503,15 +502,14 @@ BootstrapMain(int argc, char *argv[])
 static void
 usage(void)
 {
-       fprintf(stderr,
-                       gettext("Usage:\n"
+       write_stderr("Usage:\n"
                                        "  postgres -boot [OPTION]... DBNAME\n"
                                        "  -c NAME=VALUE    set run-time parameter\n"
                                        "  -d 1-5           debug level\n"
                                        "  -D datadir       data directory\n"
                                        "  -F               turn off fsync\n"
                                        "  -o file          send debug output to file\n"
-                                       "  -x num           internal use\n"));
+                                       "  -x num           internal use\n");
 
        proc_exit(1);
 }
index c9c377e1e946b28b3213784c667b39f922a1b57d..b293e57c90c35a9e2210cc90d562143b711796de 100644 (file)
@@ -13,7 +13,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/main/main.c,v 1.86 2004/06/03 00:07:36 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/main/main.c,v 1.87 2004/06/24 21:02:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -91,8 +91,8 @@ main(int argc, char *argv[])
 #if defined(__alpha)                   /* no __alpha__ ? */
        if (setsysinfo(SSI_NVPAIRS, buffer, 1, (caddr_t) NULL,
                                   (unsigned long) NULL) < 0)
-               fprintf(stderr, gettext("%s: setsysinfo failed: %s\n"),
-                               argv[0], strerror(errno));
+               write_stderr("%s: setsysinfo failed: %s\n",
+                                        argv[0], strerror(errno));
 #endif
 #endif   /* NOFIXADE || NOPRINTADE */
 
@@ -109,7 +109,7 @@ main(int argc, char *argv[])
                err = WSAStartup(MAKEWORD(2, 2), &wsaData);
                if (err != 0)
                {
-                       fprintf(stderr, "%s: WSAStartup failed: %d\n",
+                       write_stderr("%s: WSAStartup failed: %d\n",
                                        argv[0], err);
                        exit(1);
                }
@@ -212,12 +212,10 @@ main(int argc, char *argv[])
                 */
                if (geteuid() == 0)
                {
-                       fprintf(stderr,
-                                       gettext("\"root\" execution of the PostgreSQL server is not permitted.\n"
-                                                       "The server must be started under an unprivileged user ID to prevent\n"
-                                                       "possible system security compromise.  See the documentation for\n"
-                               "more information on how to properly start the server.\n"
-                                                       ));
+                       write_stderr("\"root\" execution of the PostgreSQL server is not permitted.\n"
+                                                "The server must be started under an unprivileged user ID to prevent\n"
+                                                "possible system security compromise.  See the documentation for\n"
+                                                "more information on how to properly start the server.\n");
                        exit(1);
                }
 #endif   /* !__BEOS__ */
@@ -233,9 +231,17 @@ main(int argc, char *argv[])
                 */
                if (getuid() != geteuid())
                {
-                       fprintf(stderr,
-                                gettext("%s: real and effective user IDs must match\n"),
-                                       argv[0]);
+                       write_stderr("%s: real and effective user IDs must match\n",
+                                                argv[0]);
+                       exit(1);
+               }
+#else /* WIN32 */
+               if (pgwin32_is_admin())
+               {
+                       write_stderr("execution of PostgreSQL by a user with administrative permissions is not permitted.\n"
+                                                "The server must be started under an unprivileged user ID to prevent\n"
+                                                "possible system security compromise.  See the documentation for\n"
+                                                "more information on how to properly start the server.\n");
                        exit(1);
                }
 #endif   /* !WIN32 */
@@ -292,8 +298,8 @@ main(int argc, char *argv[])
        pw = getpwuid(geteuid());
        if (pw == NULL)
        {
-               fprintf(stderr, gettext("%s: invalid effective UID: %d\n"),
-                               argv[0], (int) geteuid());
+               write_stderr("%s: invalid effective UID: %d\n",
+                                        argv[0], (int) geteuid());
                exit(1);
        }
        /* Allocate new memory because later getpwuid() calls can overwrite it */
@@ -305,7 +311,7 @@ main(int argc, char *argv[])
                pw_name_persist = malloc(namesize);
                if (!GetUserName(pw_name_persist, &namesize))
                {
-                       fprintf(stderr, gettext("%s: could not determine user name (GetUserName failed)\n"),
+                       write_stderr("%s: could not determine user name (GetUserName failed)\n",
                                        argv[0]);
                        exit(1);
                }
index d4d457b871a253ce2a61d46e70fb5453fc9b1408..dff5567be59415f823e480ac0c3c1222e707b91d 100644 (file)
@@ -1,10 +1,10 @@
-# $PostgreSQL: pgsql/src/backend/nls.mk,v 1.12 2004/06/10 17:10:24 petere Exp $
+# $PostgreSQL: pgsql/src/backend/nls.mk,v 1.13 2004/06/24 21:02:40 tgl Exp $
 CATALOG_NAME   := postgres
 AVAIL_LANGUAGES        := af cs de es hr hu it nb pt_BR ru sv tr zh_CN zh_TW
 GETTEXT_FILES  := + gettext-files
 # you can add "elog:2" and "errmsg_internal" to this list if you want to
 # include internal messages in the translation list.
-GETTEXT_TRIGGERS:= errmsg errdetail errhint errcontext postmaster_error yyerror
+GETTEXT_TRIGGERS:= errmsg errdetail errhint errcontext write_stderr yyerror
 
 gettext-files: distprep
        find $(srcdir)/ -name '*.c' -print >$@
index 0d5b64ce36401c42bc6e54898c2a51847e9e06da..8069d590fd4fb581f06ba0e13770f4f1af0db5e1 100644 (file)
@@ -4,7 +4,7 @@
 #    Makefile for port/win32
 #
 # IDENTIFICATION
-#    $PostgreSQL: pgsql/src/backend/port/win32/Makefile,v 1.4 2004/04/12 16:19:18 momjian Exp $
+#    $PostgreSQL: pgsql/src/backend/port/win32/Makefile,v 1.5 2004/06/24 21:02:42 tgl Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -12,7 +12,7 @@ subdir = src/backend/port/win32
 top_builddir = ../../../..
 include $(top_builddir)/src/Makefile.global
 
-OBJS = sema.o shmem.o timer.o socket.o signal.o
+OBJS = sema.o shmem.o timer.o socket.o signal.o security.o
 
 all: SUBSYS.o
 
diff --git a/src/backend/port/win32/security.c b/src/backend/port/win32/security.c
new file mode 100644 (file)
index 0000000..acc2f41
--- /dev/null
@@ -0,0 +1,184 @@
+/*-------------------------------------------------------------------------
+ *
+ * security.c
+ *    Microsoft Windows Win32 Security Support Functions
+ *
+ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *       $PostgreSQL: pgsql/src/backend/port/win32/security.c,v 1.1 2004/06/24 21:02:42 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+
+/*
+ * Returns nonzero if the current user has administrative privileges,
+ * or zero if not.
+ *
+ * Note: this cannot use ereport() because it's called too early during
+ * startup.
+ */
+int
+pgwin32_is_admin(void)
+{
+       HANDLE AccessToken;
+       UCHAR InfoBuffer[1024];
+       PTOKEN_GROUPS Groups = (PTOKEN_GROUPS)InfoBuffer; 
+       DWORD InfoBufferSize;
+       PSID AdministratorsSid;
+       PSID PowerUsersSid;
+       SID_IDENTIFIER_AUTHORITY NtAuthority = { SECURITY_NT_AUTHORITY }; 
+       UINT x;
+       BOOL success;
+       
+       if(!OpenProcessToken(GetCurrentProcess(),TOKEN_READ,&AccessToken))
+       {
+               write_stderr("failed to open process token: %d\n",
+                                        (int)GetLastError());
+               exit(1);
+       }
+
+       if (!GetTokenInformation(AccessToken,TokenGroups,InfoBuffer,
+                                                        1024, &InfoBufferSize))
+       {
+               write_stderr("failed to get token information: %d\n",
+                                        (int)GetLastError());
+               exit(1);
+       }
+
+       CloseHandle(AccessToken);
+
+       if(!AllocateAndInitializeSid(&NtAuthority, 2,
+                                                                SECURITY_BUILTIN_DOMAIN_RID,DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0,
+                                                                0,&AdministratorsSid))
+       {
+               write_stderr("failed to get SID for Administrators group: %d\n",
+                                        (int)GetLastError());
+               exit(1);
+       }
+
+       if (!AllocateAndInitializeSid(&NtAuthority, 2,
+                                                                 SECURITY_BUILTIN_DOMAIN_RID,DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0,
+                                                                 0, &PowerUsersSid))
+       {
+               write_stderr("failed to get SID for PowerUsers group: %d\n",
+                                        (int)GetLastError());
+               exit(1);
+       }
+       
+       success = FALSE;
+       
+       for (x=0; x<Groups->GroupCount; x++)
+       {
+               if (EqualSid(AdministratorsSid, Groups->Groups[x].Sid) ||
+                       EqualSid(PowerUsersSid, Groups->Groups[x].Sid))
+               {
+                       success = TRUE;
+                       break;
+               }
+       }
+       
+       FreeSid(AdministratorsSid);
+       FreeSid(PowerUsersSid);
+       return success;
+}
+
+/*
+ * We consider ourselves running as a service if one of the following is
+ * true:
+ *
+ * 1) We are running as Local System (only used by services)
+ * 2) Our token contains SECURITY_SERVICE_RID (automatically added to the
+ *    process token by the SCM when starting a service)
+ *
+ * Return values:
+ *   0 = Not service
+ *   1 = Service
+ *  -1 = Error
+ *
+ * Note: we can't report errors via either ereport (we're called too early)
+ * or write_stderr (because that calls this).  We are therefore reduced to
+ * writing directly on stderr, which sucks, but we have few alternatives.
+ */
+int
+pgwin32_is_service(void)
+{
+       static int _is_service = -1;
+       HANDLE AccessToken;
+       UCHAR InfoBuffer[1024];
+       PTOKEN_GROUPS Groups = (PTOKEN_GROUPS)InfoBuffer;
+       PTOKEN_USER User = (PTOKEN_USER)InfoBuffer;
+       DWORD InfoBufferSize;
+       PSID ServiceSid;
+       PSID LocalSystemSid;
+       SID_IDENTIFIER_AUTHORITY NtAuthority = { SECURITY_NT_AUTHORITY }; 
+       UINT x;
+
+       /* Only check the first time */
+       if (_is_service != -1)
+               return _is_service;
+       
+       if (!OpenProcessToken(GetCurrentProcess(),TOKEN_READ,&AccessToken)) {
+               fprintf(stderr,"failed to open process token: %d\n",
+                               (int)GetLastError());
+               return -1;
+       }
+
+       /* First check for local system */
+       if (!GetTokenInformation(AccessToken,TokenUser,InfoBuffer,1024,&InfoBufferSize)) {
+               fprintf(stderr,"failed to get token information: %d\n",
+                               (int)GetLastError());
+               return -1;
+       }
+       
+       if (!AllocateAndInitializeSid(&NtAuthority,1,
+                                                                 SECURITY_LOCAL_SYSTEM_RID,0,0,0,0,0,0,0,
+                                                                 &LocalSystemSid)) {
+               fprintf(stderr,"failed to get SID for local system account\n");
+               CloseHandle(AccessToken);
+               return -1;
+       }
+
+       if (EqualSid(LocalSystemSid, User->User.Sid)) {
+               FreeSid(LocalSystemSid);
+               CloseHandle(AccessToken);
+               _is_service = 1;
+               return _is_service;
+       }
+
+       FreeSid(LocalSystemSid);
+
+       /* Now check for group SID */
+       if (!GetTokenInformation(AccessToken,TokenGroups,InfoBuffer,1024,&InfoBufferSize)) {
+               fprintf(stderr,"failed to get token information: %d\n",
+                               (int)GetLastError());
+               return -1;
+       }
+
+       if (!AllocateAndInitializeSid(&NtAuthority,1,
+                                                                 SECURITY_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0,
+                                                                 &ServiceSid)) {
+               fprintf(stderr,"failed to get SID for service group\n");
+               CloseHandle(AccessToken);
+               return -1;
+       }
+
+       _is_service = 0;
+       for (x = 0; x < Groups->GroupCount; x++)
+       {
+               if (EqualSid(ServiceSid, Groups->Groups[x].Sid)) 
+               {
+                       _is_service = 1;
+                       break;
+               }
+       }
+
+       FreeSid(ServiceSid);
+
+       CloseHandle(AccessToken);
+
+       return _is_service;
+}
index fc0652a5b01b069e0b66579d18a67ffb94df1eb0..a5cc25611236ce2f2a87ecc87a301399eac552c2 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/port/win32/signal.c,v 1.3 2004/05/27 14:39:29 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/port/win32/signal.c,v 1.4 2004/06/24 21:02:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -63,18 +63,18 @@ pgwin32_signal_initialize(void)
        pgwin32_signal_event = CreateEvent(NULL, TRUE, FALSE, NULL);
        if (pgwin32_signal_event == NULL) 
                ereport(FATAL,
-                               (errmsg_internal("Failed to create signal event: %i!",(int)GetLastError())));
+                               (errmsg_internal("failed to create signal event: %d", (int)GetLastError())));
 
        /* Create thread for handling signals */
        signal_thread_handle = CreateThread(NULL, 0, pg_signal_thread, NULL, 0, NULL);
        if (signal_thread_handle == NULL)
                ereport(FATAL,
-                               (errmsg_internal("Failed to create signal handler thread!")));
+                               (errmsg_internal("failed to create signal handler thread")));
 
        /* Create console control handle to pick up Ctrl-C etc */
        if (!SetConsoleCtrlHandler(pg_console_handler, TRUE)) 
                ereport(FATAL,
-                               (errmsg_internal("Failed to set console control handler!")));
+                               (errmsg_internal("failed to set console control handler")));
 }
 
 
@@ -209,7 +209,7 @@ pg_signal_thread(LPVOID param)
        char            pipename[128];
        HANDLE          pipe = INVALID_HANDLE_VALUE;
 
-       wsprintf(pipename, "\\\\.\\pipe\\pgsignal_%i", GetCurrentProcessId());
+       wsprintf(pipename, "\\\\.\\pipe\\pgsignal_%d", GetCurrentProcessId());
 
        for (;;)
        {
@@ -221,7 +221,7 @@ pg_signal_thread(LPVOID param)
                                                   PIPE_UNLIMITED_INSTANCES, 16, 16, 1000, NULL);
                if (pipe == INVALID_HANDLE_VALUE)
                {
-                       fprintf(stderr, gettext("Failed to create signal listener pipe: %i. Retrying.\n"), (int) GetLastError());
+                       write_stderr("failed to create signal listener pipe: %d. Retrying.\n", (int) GetLastError());
                        SleepEx(500, FALSE);
                        continue;
                }
@@ -233,7 +233,8 @@ pg_signal_thread(LPVOID param)
                                          (LPTHREAD_START_ROUTINE) pg_signal_dispatch_thread,
                                                                   (LPVOID) pipe, 0, NULL);
                        if (hThread == INVALID_HANDLE_VALUE)
-                               fprintf(stderr, gettext("Failed to create signal dispatch thread: %i\n"), (int) GetLastError());
+                               write_stderr("failed to create signal dispatch thread: %d\n",
+                                                        (int) GetLastError());
                        else
                                CloseHandle(hThread);
                }
index 5a591f2f491b94099f07a24e105686f8dd2c693d..5d908807b9d330542ff879c21bdb4403856d3fd8 100644 (file)
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.404 2004/06/14 18:08:19 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.405 2004/06/24 21:02:55 tgl Exp $
  *
  * NOTES
  *
  *             The Postmaster cleans up after backends if they have an emergency
  *             exit and/or core dump.
  *
+ * Error Reporting:
+ *             Use write_stderr() only for reporting "interactive" errors
+ *             (essentially, bogus arguments on the command line).  Once the
+ *             postmaster is launched, use ereport().  In particular, don't use
+ *             write_stderr() for anything that occurs after pmdaemonize.
+ *
  *-------------------------------------------------------------------------
  */
 
@@ -260,10 +266,6 @@ static void SignalChildren(int signal);
 static int     CountChildren(void);
 static bool CreateOptsFile(int argc, char *argv[], char *fullprogname);
 static pid_t StartChildProcess(int xlop);
-static void
-postmaster_error(const char *fmt,...)
-/* This lets gcc check the format string for consistency. */
-__attribute__((format(printf, 1, 2)));
 
 #ifdef EXEC_BACKEND
 
@@ -380,7 +382,7 @@ PostmasterMain(int argc, char *argv[])
 #ifdef USE_ASSERT_CHECKING
                                SetConfigOption("debug_assertions", optarg, PGC_POSTMASTER, PGC_S_ARGV);
 #else
-                               postmaster_error("assert checking is not compiled in");
+                               write_stderr("%s: assert checking is not compiled in\n", progname);
 #endif
                                break;
                        case 'a':
@@ -503,9 +505,8 @@ PostmasterMain(int argc, char *argv[])
                                }
 
                        default:
-                               fprintf(stderr,
-                                       gettext("Try \"%s --help\" for more information.\n"),
-                                               progname);
+                               write_stderr("Try \"%s --help\" for more information.\n",
+                                                        progname);
                                ExitPostmaster(1);
                }
        }
@@ -515,10 +516,10 @@ PostmasterMain(int argc, char *argv[])
         */
        if (optind < argc)
        {
-               postmaster_error("invalid argument: \"%s\"", argv[optind]);
-               fprintf(stderr,
-                               gettext("Try \"%s --help\" for more information.\n"),
-                               progname);
+               write_stderr("%s: invalid argument: \"%s\"\n",
+                                        progname, argv[optind]);
+               write_stderr("Try \"%s --help\" for more information.\n",
+                                        progname);
                ExitPostmaster(1);
        }
 
@@ -547,13 +548,13 @@ PostmasterMain(int argc, char *argv[])
                 * for lack of buffers.  The specific choices here are somewhat
                 * arbitrary.
                 */
-               postmaster_error("the number of buffers (-B) must be at least twice the number of allowed connections (-N) and at least 16");
+               write_stderr("%s: the number of buffers (-B) must be at least twice the number of allowed connections (-N) and at least 16\n", progname);
                ExitPostmaster(1);
        }
 
        if (ReservedBackends >= MaxBackends)
        {
-               postmaster_error("superuser_reserved_connections must be less than max_connections");
+               write_stderr("%s: superuser_reserved_connections must be less than max_connections\n", progname);
                ExitPostmaster(1);
        }
 
@@ -562,7 +563,7 @@ PostmasterMain(int argc, char *argv[])
         */
        if (!CheckDateTokenTables())
        {
-               postmaster_error("invalid datetoken tables, please fix");
+               write_stderr("%s: invalid datetoken tables, please fix\n", progname);
                ExitPostmaster(1);
        }
 
@@ -858,12 +859,11 @@ checkDataDir(const char *checkdir)
 
        if (checkdir == NULL)
        {
-               fprintf(stderr,
-                               gettext("%s does not know where to find the database system data.\n"
-                                               "You must specify the directory that contains the database system\n"
-                                               "either by specifying the -D invocation option or by setting the\n"
-                                               "PGDATA environment variable.\n"),
-                               progname);
+               write_stderr("%s does not know where to find the database system data.\n"
+                                        "You must specify the directory that contains the database system\n"
+                                        "either by specifying the -D invocation option or by setting the\n"
+                                        "PGDATA environment variable.\n",
+                                        progname);
                ExitPostmaster(2);
        }
 
@@ -905,11 +905,10 @@ checkDataDir(const char *checkdir)
        fp = AllocateFile(path, PG_BINARY_R);
        if (fp == NULL)
        {
-               fprintf(stderr,
-                               gettext("%s: could not find the database system\n"
-                                               "Expected to find it in the directory \"%s\",\n"
-                                               "but could not open file \"%s\": %s\n"),
-                               progname, checkdir, path, strerror(errno));
+               write_stderr("%s: could not find the database system\n"
+                                        "Expected to find it in the directory \"%s\",\n"
+                                        "but could not open file \"%s\": %s\n",
+                                        progname, checkdir, path, strerror(errno));
                ExitPostmaster(2);
        }
        FreeFile(fp);
@@ -952,8 +951,8 @@ pmdaemonize(void)
        pid = fork();
        if (pid == (pid_t) -1)
        {
-               postmaster_error("could not fork background process: %s",
-                                                strerror(errno));
+               write_stderr("%s: could not fork background process: %s\n",
+                                        progname, strerror(errno));
                ExitPostmaster(1);
        }
        else if (pid)
@@ -974,8 +973,8 @@ pmdaemonize(void)
 #ifdef HAVE_SETSID
        if (setsid() < 0)
        {
-               postmaster_error("could not dissociate from controlling TTY: %s",
-                                                strerror(errno));
+               write_stderr("%s: could not dissociate from controlling TTY: %s\n",
+                                        progname, strerror(errno));
                ExitPostmaster(1);
        }
 #endif
@@ -3152,24 +3151,6 @@ CreateOptsFile(int argc, char *argv[], char *fullprogname)
        return true;
 }
 
-/*
- * This should be used only for reporting "interactive" errors (essentially,
- * bogus arguments on the command line).  Once the postmaster is launched,
- * use ereport.  In particular, don't use this for anything that occurs
- * after pmdaemonize.
- */
-static void
-postmaster_error(const char *fmt,...)
-{
-       va_list         ap;
-
-       fprintf(stderr, "%s: ", progname);
-       va_start(ap, fmt);
-       vfprintf(stderr, gettext(fmt), ap);
-       va_end(ap);
-       fprintf(stderr, "\n");
-}
-
 
 #ifdef EXEC_BACKEND
 
@@ -3609,7 +3590,7 @@ win32_sigchld_waiter(LPVOID param)
        if (r == WAIT_OBJECT_0)
                pg_queue_signal(SIGCHLD);
        else
-               fprintf(stderr, "ERROR: failed to wait on child process handle: %d\n",
+               write_stderr("ERROR: failed to wait on child process handle: %d\n",
                                (int) GetLastError());
        CloseHandle(procHandle);
        return 0;
index 976b417e096fa454da871dc93b40359265550a9d..9b7cfcd66814cce67dd5fefc8a15521ca7275bc5 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.420 2004/06/11 01:09:00 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.421 2004/06/24 21:03:08 tgl Exp $
  *
  * NOTES
  *       this is the "main" module of the postgres backend and
@@ -2578,12 +2578,11 @@ PostgresMain(int argc, char *argv[], const char *username)
        {
                if (!potential_DataDir)
                {
-                       fprintf(stderr,
-                                       gettext("%s does not know where to find the database system data.\n"
-                                                       "You must specify the directory that contains the database system\n"
-                                                       "either by specifying the -D invocation option or by setting the\n"
-                                                       "PGDATA environment variable.\n"),
-                                       argv[0]);
+                       write_stderr("%s does not know where to find the database system data.\n"
+                                                "You must specify the directory that contains the database system\n"
+                                                "either by specifying the -D invocation option or by setting the\n"
+                                                "PGDATA environment variable.\n",
+                                                argv[0]);
                        proc_exit(1);
                }
                SetDataDir(potential_DataDir);
index f35636e9fecdf6a9d436bd7dde5b9fd589f13425..f740c1baa5790189221b194efaa3cc439ab36a9a 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/error/assert.c,v 1.26 2004/04/19 17:42:58 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/error/assert.c,v 1.27 2004/06/24 21:03:13 tgl Exp $
  *
  * NOTE
  *       This should eventually work with elog()
@@ -31,10 +31,10 @@ ExceptionalCondition(char *conditionName,
        if (!PointerIsValid(conditionName)
                || !PointerIsValid(fileName)
                || !PointerIsValid(errorType))
-               fprintf(stderr, "TRAP: ExceptionalCondition: bad arguments\n");
+               write_stderr("TRAP: ExceptionalCondition: bad arguments\n");
        else
        {
-               fprintf(stderr, "TRAP: %s(\"%s\", File: \"%s\", Line: %d)\n",
+               write_stderr("TRAP: %s(\"%s\", File: \"%s\", Line: %d)\n",
                                errorType, conditionName,
                                fileName, lineNumber);
        }
index e47740ededad028f2fcfc44dd898f5bf69d2ed18..c70958a9de13192489e85a6a49f514e47368bef6 100644 (file)
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.141 2004/06/21 14:12:38 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.142 2004/06/24 21:03:13 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1765,3 +1765,37 @@ append_with_tabs(StringInfo buf, const char *str)
                        appendStringInfoCharMacro(buf, '\t');
        }
 }
+
+
+/* 
+ * Write errors to stderr (or by equal means when stderr is
+ * not available). Used before ereport/elog can be used
+ * safely (memory context, GUC load etc) 
+ */
+void
+write_stderr(const char *fmt,...)
+{
+       va_list ap;
+
+       fmt = gettext(fmt);
+
+       va_start(ap, fmt);
+#ifndef WIN32
+       /* On Unix, we just fprintf to stderr */
+       vfprintf(stderr, fmt, ap);
+#else
+       /* On Win32, we print to stderr if running on a console, or write to 
+        * eventlog if running as a service */
+       if (pgwin32_is_service()) /* Running as a service */
+       {
+               char errbuf[2048]; /* Arbitrary size? */
+
+               vsnprintf(errbuf, sizeof(errbuf), fmt, ap);
+               
+               write_eventlog(EVENTLOG_ERROR_TYPE, errbuf);
+       }
+       else /* Not running as service, write to stderr */
+               vfprintf(stderr, fmt, ap);
+#endif
+       va_end(ap);
+}
index 21cd59161361a2f879c0b4a2e8ab0b97d1a8db24..b627d145cc671b79c67e0073473e3f70af8728cf 100644 (file)
@@ -10,7 +10,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/misc/help_config.c,v 1.11 2004/06/02 18:09:32 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/misc/help_config.c,v 1.12 2004/06/24 21:03:22 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -122,7 +122,7 @@ printMixedStruct(mixedStruct *structToPrint)
                        break;
 
                default:
-                       fprintf(stderr, "internal error: unrecognized run-time parameter type\n");
+                       write_stderr("internal error: unrecognized run-time parameter type\n");
                        break;
        }
 
index c10eb078c4a8a4c88226966ffea018de2a3a1052..28a583690d4c0f6c108c33f8b8cb6f4ce2271d98 100644 (file)
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/include/port/win32.h,v 1.25 2004/05/27 14:39:33 momjian Exp $ */
+/* $PostgreSQL: pgsql/src/include/port/win32.h,v 1.26 2004/06/24 21:03:33 tgl Exp $ */
 
 /* undefine and redefine after #include */
 #undef mkdir
@@ -138,6 +138,10 @@ int pgwin32_recv(SOCKET s, char* buf, int len, int flags);
 int pgwin32_send(SOCKET s, char* buf, int len, int flags);
 
 const char *pgwin32_socket_strerror(int err);
+
+/* in backend/port/win32/security.c */
+extern int pgwin32_is_admin(void);
+extern int pgwin32_is_service(void);
 #endif
 
 
index e3c8f9152abf7a11ca3e6749994c1b11a4ab26d0..84ff8bdee1e9fca811dd4603a69929593ff3cca9 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/elog.h,v 1.68 2004/04/05 03:02:10 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/elog.h,v 1.69 2004/06/24 21:03:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -186,4 +186,14 @@ extern unsigned int Log_destination;
 /* Other exported functions */
 extern void DebugFileOpen(void);
 
+/*
+ * Write errors to stderr (or by equal means when stderr is
+ * not available). Used before ereport/elog can be used
+ * safely (memory context, GUC load etc)
+ */
+extern void write_stderr(const char *fmt,...)
+/* This extension allows gcc to check the format string for consistency with
+   the supplied arguments. */
+__attribute__((format(printf, 1, 2)));
+
 #endif   /* ELOG_H */