Skip to content

Commit a967613

Browse files
committed
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
1 parent dad0899 commit a967613

File tree

5 files changed

+63
-28
lines changed

5 files changed

+63
-28
lines changed

src/backend/port/win32/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ subdir = src/backend/port/win32
1212
top_builddir = ../../../..
1313
include $(top_builddir)/src/Makefile.global
1414

15-
OBJS = timer.o socket.o signal.o security.o mingwcompat.o
15+
OBJS = timer.o socket.o signal.o mingwcompat.o
1616
ifeq ($(have_win32_dbghelp), yes)
1717
OBJS += crashdump.o
1818
endif

src/bin/pg_ctl/pg_ctl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ write_stderr(const char *fmt,...)
216216
* On Win32, we print to stderr if running on a console, or write to
217217
* eventlog if running as a service
218218
*/
219-
if (!isatty(fileno(stderr))) /* Running as a service */
219+
if (!pgwin32_is_service()) /* Running as a service */
220220
{
221221
char errbuf[2048]; /* Arbitrary size? */
222222

src/include/port/win32.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -382,9 +382,6 @@ int pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout);
382382

383383
extern int pgwin32_noblock;
384384

385-
/* in backend/port/win32/security.c */
386-
extern int pgwin32_is_admin(void);
387-
extern int pgwin32_is_service(void);
388385
#endif
389386

390387
/* in backend/port/win32_shmem.c */
@@ -400,6 +397,10 @@ extern void _dosmaperr(unsigned long);
400397
extern int pgwin32_putenv(const char *);
401398
extern void pgwin32_unsetenv(const char *);
402399

400+
/* in port/win32security.c */
401+
extern int pgwin32_is_service(void);
402+
extern int pgwin32_is_admin(void);
403+
403404
#define putenv(x) pgwin32_putenv(x)
404405
#define unsetenv(x) pgwin32_unsetenv(x)
405406

src/backend/port/win32/security.c renamed to src/port/win32security.c

Lines changed: 56 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,47 @@
11
/*-------------------------------------------------------------------------
22
*
3-
* security.c
3+
* win32security.c
44
* Microsoft Windows Win32 Security Support Functions
55
*
66
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
77
*
88
* IDENTIFICATION
9-
* src/backend/port/win32/security.c
9+
* src/port/win32security.c
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
1313

14+
#ifndef FRONTEND
1415
#include "postgres.h"
16+
#else
17+
#include "postgres_fe.h"
18+
#endif
1519

1620

1721
static BOOL pgwin32_get_dynamic_tokeninfo(HANDLE token,
18-
TOKEN_INFORMATION_CLASS class, char **InfoBuffer,
19-
char *errbuf, int errsize);
22+
TOKEN_INFORMATION_CLASS class,
23+
char **InfoBuffer, char *errbuf, int errsize);
24+
25+
26+
/*
27+
* Utility wrapper for frontend and backend when reporting an error
28+
* message.
29+
*/
30+
static
31+
pg_attribute_printf(1, 2)
32+
void
33+
log_error(const char *fmt,...)
34+
{
35+
va_list ap;
36+
37+
va_start(fmt, ap);
38+
#ifndef FRONTEND
39+
write_stderr(fmt, ap);
40+
#else
41+
fprintf(stderr, fmt, ap);
42+
#endif
43+
va_end(ap);
44+
}
2045

2146
/*
2247
* Returns nonzero if the current user has administrative privileges,
@@ -40,15 +65,15 @@ pgwin32_is_admin(void)
4065

4166
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &AccessToken))
4267
{
43-
write_stderr("could not open process token: error code %lu\n",
44-
GetLastError());
68+
log_error("could not open process token: error code %lu\n",
69+
GetLastError());
4570
exit(1);
4671
}
4772

4873
if (!pgwin32_get_dynamic_tokeninfo(AccessToken, TokenGroups,
4974
&InfoBuffer, errbuf, sizeof(errbuf)))
5075
{
51-
write_stderr("%s", errbuf);
76+
log_error("%s", errbuf);
5277
exit(1);
5378
}
5479

@@ -57,29 +82,33 @@ pgwin32_is_admin(void)
5782
CloseHandle(AccessToken);
5883

5984
if (!AllocateAndInitializeSid(&NtAuthority, 2,
60-
SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0,
85+
SECURITY_BUILTIN_DOMAIN_RID,
86+
DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0,
6187
0, &AdministratorsSid))
6288
{
63-
write_stderr("could not get SID for Administrators group: error code %lu\n",
64-
GetLastError());
89+
log_error("could not get SID for Administrators group: error code %lu\n",
90+
GetLastError());
6591
exit(1);
6692
}
6793

6894
if (!AllocateAndInitializeSid(&NtAuthority, 2,
69-
SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0,
95+
SECURITY_BUILTIN_DOMAIN_RID,
96+
DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0,
7097
0, &PowerUsersSid))
7198
{
72-
write_stderr("could not get SID for PowerUsers group: error code %lu\n",
73-
GetLastError());
99+
log_error("could not get SID for PowerUsers group: error code %lu\n",
100+
GetLastError());
74101
exit(1);
75102
}
76103

77104
success = FALSE;
78105

79106
for (x = 0; x < Groups->GroupCount; x++)
80107
{
81-
if ((EqualSid(AdministratorsSid, Groups->Groups[x].Sid) && (Groups->Groups[x].Attributes & SE_GROUP_ENABLED)) ||
82-
(EqualSid(PowerUsersSid, Groups->Groups[x].Sid) && (Groups->Groups[x].Attributes & SE_GROUP_ENABLED)))
108+
if ((EqualSid(AdministratorsSid, Groups->Groups[x].Sid) &&
109+
(Groups->Groups[x].Attributes & SE_GROUP_ENABLED)) ||
110+
(EqualSid(PowerUsersSid, Groups->Groups[x].Sid) &&
111+
(Groups->Groups[x].Attributes & SE_GROUP_ENABLED)))
83112
{
84113
success = TRUE;
85114
break;
@@ -105,9 +134,10 @@ pgwin32_is_admin(void)
105134
* 1 = Service
106135
* -1 = Error
107136
*
108-
* Note: we can't report errors via either ereport (we're called too early)
109-
* or write_stderr (because that calls this). We are therefore reduced to
110-
* writing directly on stderr, which sucks, but we have few alternatives.
137+
* Note: we can't report errors via either ereport (we're called too early
138+
* in the backend) or write_stderr (because that calls this). We are
139+
* therefore reduced to writing directly on stderr, which sucks, but we
140+
* have few alternatives.
111141
*/
112142
int
113143
pgwin32_is_service(void)
@@ -217,29 +247,33 @@ pgwin32_get_dynamic_tokeninfo(HANDLE token, TOKEN_INFORMATION_CLASS class,
217247

218248
if (GetTokenInformation(token, class, NULL, 0, &InfoBufferSize))
219249
{
220-
snprintf(errbuf, errsize, "could not get token information: got zero size\n");
250+
snprintf(errbuf, errsize,
251+
"could not get token information: got zero size\n");
221252
return FALSE;
222253
}
223254

224255
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
225256
{
226-
snprintf(errbuf, errsize, "could not get token information: error code %lu\n",
257+
snprintf(errbuf, errsize,
258+
"could not get token information: error code %lu\n",
227259
GetLastError());
228260
return FALSE;
229261
}
230262

231263
*InfoBuffer = malloc(InfoBufferSize);
232264
if (*InfoBuffer == NULL)
233265
{
234-
snprintf(errbuf, errsize, "could not allocate %d bytes for token information\n",
266+
snprintf(errbuf, errsize,
267+
"could not allocate %d bytes for token information\n",
235268
(int) InfoBufferSize);
236269
return FALSE;
237270
}
238271

239272
if (!GetTokenInformation(token, class, *InfoBuffer,
240273
InfoBufferSize, &InfoBufferSize))
241274
{
242-
snprintf(errbuf, errsize, "could not get token information: error code %lu\n",
275+
snprintf(errbuf, errsize,
276+
"could not get token information: error code %lu\n",
243277
GetLastError());
244278
return FALSE;
245279
}

src/tools/msvc/Mkvcbuild.pm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ sub mkvcbuild
9090
pgcheckdir.c pgmkdirp.c pgsleep.c pgstrcasecmp.c pqsignal.c
9191
mkdtemp.c qsort.c qsort_arg.c quotes.c system.c
9292
sprompt.c tar.c thread.c getopt.c getopt_long.c dirent.c
93-
win32env.c win32error.c win32setlocale.c);
93+
win32env.c win32error.c win32security.c win32setlocale.c);
9494

9595
push(@pgportfiles, 'rint.c') if ($vsVersion < '12.00');
9696

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy