mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-02-11 19:20:40 +08:00
Windows: Make pg_ctl reliably detect service status
pg_ctl is using isatty() to verify whether the process is running in a terminal, and if not it sends its output to Windows' Event Log ... which does the wrong thing when the output has been redirected to a pipe, as reported in bug #13592. To fix, make pg_ctl use the code we already have to detect service-ness: in the master branch, move src/backend/port/win32/security.c to src/port (with suitable tweaks so that it runs properly in backend and frontend environments); pg_ctl already has access to pgport so it Just Works. In older branches, that's likely to cause trouble, so instead duplicate the required code in pg_ctl.c. Author: Michael Paquier Bug report and diagnosis: Egon Kocjan Backpatch: all supported branches
This commit is contained in:
parent
dad08994b2
commit
a967613911
@ -12,7 +12,7 @@ subdir = src/backend/port/win32
|
||||
top_builddir = ../../../..
|
||||
include $(top_builddir)/src/Makefile.global
|
||||
|
||||
OBJS = timer.o socket.o signal.o security.o mingwcompat.o
|
||||
OBJS = timer.o socket.o signal.o mingwcompat.o
|
||||
ifeq ($(have_win32_dbghelp), yes)
|
||||
OBJS += crashdump.o
|
||||
endif
|
||||
|
@ -216,7 +216,7 @@ write_stderr(const char *fmt,...)
|
||||
* On Win32, we print to stderr if running on a console, or write to
|
||||
* eventlog if running as a service
|
||||
*/
|
||||
if (!isatty(fileno(stderr))) /* Running as a service */
|
||||
if (!pgwin32_is_service()) /* Running as a service */
|
||||
{
|
||||
char errbuf[2048]; /* Arbitrary size? */
|
||||
|
||||
|
@ -382,9 +382,6 @@ int pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout);
|
||||
|
||||
extern int pgwin32_noblock;
|
||||
|
||||
/* in backend/port/win32/security.c */
|
||||
extern int pgwin32_is_admin(void);
|
||||
extern int pgwin32_is_service(void);
|
||||
#endif
|
||||
|
||||
/* in backend/port/win32_shmem.c */
|
||||
@ -400,6 +397,10 @@ extern void _dosmaperr(unsigned long);
|
||||
extern int pgwin32_putenv(const char *);
|
||||
extern void pgwin32_unsetenv(const char *);
|
||||
|
||||
/* in port/win32security.c */
|
||||
extern int pgwin32_is_service(void);
|
||||
extern int pgwin32_is_admin(void);
|
||||
|
||||
#define putenv(x) pgwin32_putenv(x)
|
||||
#define unsetenv(x) pgwin32_unsetenv(x)
|
||||
|
||||
|
@ -1,22 +1,47 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* security.c
|
||||
* win32security.c
|
||||
* Microsoft Windows Win32 Security Support Functions
|
||||
*
|
||||
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* src/backend/port/win32/security.c
|
||||
* src/port/win32security.c
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef FRONTEND
|
||||
#include "postgres.h"
|
||||
#else
|
||||
#include "postgres_fe.h"
|
||||
#endif
|
||||
|
||||
|
||||
static BOOL pgwin32_get_dynamic_tokeninfo(HANDLE token,
|
||||
TOKEN_INFORMATION_CLASS class, char **InfoBuffer,
|
||||
char *errbuf, int errsize);
|
||||
TOKEN_INFORMATION_CLASS class,
|
||||
char **InfoBuffer, char *errbuf, int errsize);
|
||||
|
||||
|
||||
/*
|
||||
* Utility wrapper for frontend and backend when reporting an error
|
||||
* message.
|
||||
*/
|
||||
static
|
||||
pg_attribute_printf(1, 2)
|
||||
void
|
||||
log_error(const char *fmt,...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(fmt, ap);
|
||||
#ifndef FRONTEND
|
||||
write_stderr(fmt, ap);
|
||||
#else
|
||||
fprintf(stderr, fmt, ap);
|
||||
#endif
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns nonzero if the current user has administrative privileges,
|
||||
@ -40,15 +65,15 @@ pgwin32_is_admin(void)
|
||||
|
||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &AccessToken))
|
||||
{
|
||||
write_stderr("could not open process token: error code %lu\n",
|
||||
GetLastError());
|
||||
log_error("could not open process token: error code %lu\n",
|
||||
GetLastError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!pgwin32_get_dynamic_tokeninfo(AccessToken, TokenGroups,
|
||||
&InfoBuffer, errbuf, sizeof(errbuf)))
|
||||
{
|
||||
write_stderr("%s", errbuf);
|
||||
log_error("%s", errbuf);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -57,20 +82,22 @@ pgwin32_is_admin(void)
|
||||
CloseHandle(AccessToken);
|
||||
|
||||
if (!AllocateAndInitializeSid(&NtAuthority, 2,
|
||||
SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0,
|
||||
SECURITY_BUILTIN_DOMAIN_RID,
|
||||
DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0,
|
||||
0, &AdministratorsSid))
|
||||
{
|
||||
write_stderr("could not get SID for Administrators group: error code %lu\n",
|
||||
GetLastError());
|
||||
log_error("could not get SID for Administrators group: error code %lu\n",
|
||||
GetLastError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!AllocateAndInitializeSid(&NtAuthority, 2,
|
||||
SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0,
|
||||
SECURITY_BUILTIN_DOMAIN_RID,
|
||||
DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0,
|
||||
0, &PowerUsersSid))
|
||||
{
|
||||
write_stderr("could not get SID for PowerUsers group: error code %lu\n",
|
||||
GetLastError());
|
||||
log_error("could not get SID for PowerUsers group: error code %lu\n",
|
||||
GetLastError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -78,8 +105,10 @@ pgwin32_is_admin(void)
|
||||
|
||||
for (x = 0; x < Groups->GroupCount; x++)
|
||||
{
|
||||
if ((EqualSid(AdministratorsSid, Groups->Groups[x].Sid) && (Groups->Groups[x].Attributes & SE_GROUP_ENABLED)) ||
|
||||
(EqualSid(PowerUsersSid, Groups->Groups[x].Sid) && (Groups->Groups[x].Attributes & SE_GROUP_ENABLED)))
|
||||
if ((EqualSid(AdministratorsSid, Groups->Groups[x].Sid) &&
|
||||
(Groups->Groups[x].Attributes & SE_GROUP_ENABLED)) ||
|
||||
(EqualSid(PowerUsersSid, Groups->Groups[x].Sid) &&
|
||||
(Groups->Groups[x].Attributes & SE_GROUP_ENABLED)))
|
||||
{
|
||||
success = TRUE;
|
||||
break;
|
||||
@ -105,9 +134,10 @@ pgwin32_is_admin(void)
|
||||
* 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.
|
||||
* Note: we can't report errors via either ereport (we're called too early
|
||||
* in the backend) 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)
|
||||
@ -217,13 +247,15 @@ pgwin32_get_dynamic_tokeninfo(HANDLE token, TOKEN_INFORMATION_CLASS class,
|
||||
|
||||
if (GetTokenInformation(token, class, NULL, 0, &InfoBufferSize))
|
||||
{
|
||||
snprintf(errbuf, errsize, "could not get token information: got zero size\n");
|
||||
snprintf(errbuf, errsize,
|
||||
"could not get token information: got zero size\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
snprintf(errbuf, errsize, "could not get token information: error code %lu\n",
|
||||
snprintf(errbuf, errsize,
|
||||
"could not get token information: error code %lu\n",
|
||||
GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
@ -231,7 +263,8 @@ pgwin32_get_dynamic_tokeninfo(HANDLE token, TOKEN_INFORMATION_CLASS class,
|
||||
*InfoBuffer = malloc(InfoBufferSize);
|
||||
if (*InfoBuffer == NULL)
|
||||
{
|
||||
snprintf(errbuf, errsize, "could not allocate %d bytes for token information\n",
|
||||
snprintf(errbuf, errsize,
|
||||
"could not allocate %d bytes for token information\n",
|
||||
(int) InfoBufferSize);
|
||||
return FALSE;
|
||||
}
|
||||
@ -239,7 +272,8 @@ pgwin32_get_dynamic_tokeninfo(HANDLE token, TOKEN_INFORMATION_CLASS class,
|
||||
if (!GetTokenInformation(token, class, *InfoBuffer,
|
||||
InfoBufferSize, &InfoBufferSize))
|
||||
{
|
||||
snprintf(errbuf, errsize, "could not get token information: error code %lu\n",
|
||||
snprintf(errbuf, errsize,
|
||||
"could not get token information: error code %lu\n",
|
||||
GetLastError());
|
||||
return FALSE;
|
||||
}
|
@ -90,7 +90,7 @@ sub mkvcbuild
|
||||
pgcheckdir.c pgmkdirp.c pgsleep.c pgstrcasecmp.c pqsignal.c
|
||||
mkdtemp.c qsort.c qsort_arg.c quotes.c system.c
|
||||
sprompt.c tar.c thread.c getopt.c getopt_long.c dirent.c
|
||||
win32env.c win32error.c win32setlocale.c);
|
||||
win32env.c win32error.c win32security.c win32setlocale.c);
|
||||
|
||||
push(@pgportfiles, 'rint.c') if ($vsVersion < '12.00');
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user