mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-10-02 00:21:13 +02: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 = ../../../..
|
top_builddir = ../../../..
|
||||||
include $(top_builddir)/src/Makefile.global
|
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)
|
ifeq ($(have_win32_dbghelp), yes)
|
||||||
OBJS += crashdump.o
|
OBJS += crashdump.o
|
||||||
endif
|
endif
|
||||||
|
@ -216,7 +216,7 @@ write_stderr(const char *fmt,...)
|
|||||||
* On Win32, we print to stderr if running on a console, or write to
|
* On Win32, we print to stderr if running on a console, or write to
|
||||||
* eventlog if running as a service
|
* 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? */
|
char errbuf[2048]; /* Arbitrary size? */
|
||||||
|
|
||||||
|
@ -382,9 +382,6 @@ int pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout);
|
|||||||
|
|
||||||
extern int pgwin32_noblock;
|
extern int pgwin32_noblock;
|
||||||
|
|
||||||
/* in backend/port/win32/security.c */
|
|
||||||
extern int pgwin32_is_admin(void);
|
|
||||||
extern int pgwin32_is_service(void);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* in backend/port/win32_shmem.c */
|
/* in backend/port/win32_shmem.c */
|
||||||
@ -400,6 +397,10 @@ extern void _dosmaperr(unsigned long);
|
|||||||
extern int pgwin32_putenv(const char *);
|
extern int pgwin32_putenv(const char *);
|
||||||
extern void pgwin32_unsetenv(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 putenv(x) pgwin32_putenv(x)
|
||||||
#define unsetenv(x) pgwin32_unsetenv(x)
|
#define unsetenv(x) pgwin32_unsetenv(x)
|
||||||
|
|
||||||
|
@ -1,22 +1,47 @@
|
|||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* security.c
|
* win32security.c
|
||||||
* Microsoft Windows Win32 Security Support Functions
|
* Microsoft Windows Win32 Security Support Functions
|
||||||
*
|
*
|
||||||
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* src/backend/port/win32/security.c
|
* src/port/win32security.c
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef FRONTEND
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
#else
|
||||||
|
#include "postgres_fe.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static BOOL pgwin32_get_dynamic_tokeninfo(HANDLE token,
|
static BOOL pgwin32_get_dynamic_tokeninfo(HANDLE token,
|
||||||
TOKEN_INFORMATION_CLASS class, char **InfoBuffer,
|
TOKEN_INFORMATION_CLASS class,
|
||||||
char *errbuf, int errsize);
|
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,
|
* Returns nonzero if the current user has administrative privileges,
|
||||||
@ -40,7 +65,7 @@ pgwin32_is_admin(void)
|
|||||||
|
|
||||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &AccessToken))
|
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &AccessToken))
|
||||||
{
|
{
|
||||||
write_stderr("could not open process token: error code %lu\n",
|
log_error("could not open process token: error code %lu\n",
|
||||||
GetLastError());
|
GetLastError());
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -48,7 +73,7 @@ pgwin32_is_admin(void)
|
|||||||
if (!pgwin32_get_dynamic_tokeninfo(AccessToken, TokenGroups,
|
if (!pgwin32_get_dynamic_tokeninfo(AccessToken, TokenGroups,
|
||||||
&InfoBuffer, errbuf, sizeof(errbuf)))
|
&InfoBuffer, errbuf, sizeof(errbuf)))
|
||||||
{
|
{
|
||||||
write_stderr("%s", errbuf);
|
log_error("%s", errbuf);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,19 +82,21 @@ pgwin32_is_admin(void)
|
|||||||
CloseHandle(AccessToken);
|
CloseHandle(AccessToken);
|
||||||
|
|
||||||
if (!AllocateAndInitializeSid(&NtAuthority, 2,
|
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))
|
0, &AdministratorsSid))
|
||||||
{
|
{
|
||||||
write_stderr("could not get SID for Administrators group: error code %lu\n",
|
log_error("could not get SID for Administrators group: error code %lu\n",
|
||||||
GetLastError());
|
GetLastError());
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!AllocateAndInitializeSid(&NtAuthority, 2,
|
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))
|
0, &PowerUsersSid))
|
||||||
{
|
{
|
||||||
write_stderr("could not get SID for PowerUsers group: error code %lu\n",
|
log_error("could not get SID for PowerUsers group: error code %lu\n",
|
||||||
GetLastError());
|
GetLastError());
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -78,8 +105,10 @@ pgwin32_is_admin(void)
|
|||||||
|
|
||||||
for (x = 0; x < Groups->GroupCount; x++)
|
for (x = 0; x < Groups->GroupCount; x++)
|
||||||
{
|
{
|
||||||
if ((EqualSid(AdministratorsSid, Groups->Groups[x].Sid) && (Groups->Groups[x].Attributes & SE_GROUP_ENABLED)) ||
|
if ((EqualSid(AdministratorsSid, Groups->Groups[x].Sid) &&
|
||||||
(EqualSid(PowerUsersSid, Groups->Groups[x].Sid) && (Groups->Groups[x].Attributes & SE_GROUP_ENABLED)))
|
(Groups->Groups[x].Attributes & SE_GROUP_ENABLED)) ||
|
||||||
|
(EqualSid(PowerUsersSid, Groups->Groups[x].Sid) &&
|
||||||
|
(Groups->Groups[x].Attributes & SE_GROUP_ENABLED)))
|
||||||
{
|
{
|
||||||
success = TRUE;
|
success = TRUE;
|
||||||
break;
|
break;
|
||||||
@ -105,9 +134,10 @@ pgwin32_is_admin(void)
|
|||||||
* 1 = Service
|
* 1 = Service
|
||||||
* -1 = Error
|
* -1 = Error
|
||||||
*
|
*
|
||||||
* Note: we can't report errors via either ereport (we're called too early)
|
* 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
|
* in the backend) or write_stderr (because that calls this). We are
|
||||||
* writing directly on stderr, which sucks, but we have few alternatives.
|
* therefore reduced to writing directly on stderr, which sucks, but we
|
||||||
|
* have few alternatives.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
pgwin32_is_service(void)
|
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))
|
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;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
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());
|
GetLastError());
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -231,7 +263,8 @@ pgwin32_get_dynamic_tokeninfo(HANDLE token, TOKEN_INFORMATION_CLASS class,
|
|||||||
*InfoBuffer = malloc(InfoBufferSize);
|
*InfoBuffer = malloc(InfoBufferSize);
|
||||||
if (*InfoBuffer == NULL)
|
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);
|
(int) InfoBufferSize);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -239,7 +272,8 @@ pgwin32_get_dynamic_tokeninfo(HANDLE token, TOKEN_INFORMATION_CLASS class,
|
|||||||
if (!GetTokenInformation(token, class, *InfoBuffer,
|
if (!GetTokenInformation(token, class, *InfoBuffer,
|
||||||
InfoBufferSize, &InfoBufferSize))
|
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());
|
GetLastError());
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
@ -90,7 +90,7 @@ sub mkvcbuild
|
|||||||
pgcheckdir.c pgmkdirp.c pgsleep.c pgstrcasecmp.c pqsignal.c
|
pgcheckdir.c pgmkdirp.c pgsleep.c pgstrcasecmp.c pqsignal.c
|
||||||
mkdtemp.c qsort.c qsort_arg.c quotes.c system.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
|
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');
|
push(@pgportfiles, 'rint.c') if ($vsVersion < '12.00');
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user