Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit74d4009

Browse files
committed
Windows: Make pg_ctl reliably detect service status
pg_ctl is using isatty() to verify whether the process is running in aterminal, and if not it sends its output to Windows' Event Log ... whichdoes the wrong thing when the output has been redirected to a pipe, asreported 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 frontendenvironments); pg_ctl already has access to pgport so it Just Works. Inolder branches, that's likely to cause trouble, so instead duplicate therequired code in pg_ctl.c.Author: Michael PaquierBug report and diagnosis: Egon KocjanBackpatch: all supported branches
1 parent6d899f0 commit74d4009

File tree

1 file changed

+159
-1
lines changed

1 file changed

+159
-1
lines changed

‎src/bin/pg_ctl/pg_ctl.c

Lines changed: 159 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,10 @@ static void WINAPI pgwin32_ServiceHandler(DWORD);
151151
staticvoidWINAPIpgwin32_ServiceMain(DWORD,LPTSTR*);
152152
staticvoidpgwin32_doRunAsService(void);
153153
staticintCreateRestrictedProcess(char*cmd,PROCESS_INFORMATION*processInfo,boolas_service);
154+
staticboolpgwin32_get_dynamic_tokeninfo(HANDLEtoken,
155+
TOKEN_INFORMATION_CLASSclass,
156+
char**InfoBuffer,char*errbuf,interrsize);
157+
staticintpgwin32_is_service(void);
154158
#endif
155159

156160
staticpgpid_tget_pgpid(void);
@@ -216,7 +220,7 @@ write_stderr(const char *fmt,...)
216220
* On Win32, we print to stderr if running on a console, or write to
217221
* eventlog if running as a service
218222
*/
219-
if (!isatty(fileno(stderr)))/* Running as a service */
223+
if (!pgwin32_is_service())/* Running as a service */
220224
{
221225
charerrbuf[2048];/* Arbitrary size? */
222226

@@ -1604,6 +1608,160 @@ pgwin32_doRunAsService(void)
16041608
}
16051609
}
16061610

1611+
/*
1612+
* Call GetTokenInformation() on a token and return a dynamically sized
1613+
* buffer with the information in it. This buffer must be free():d by
1614+
* the calling function!
1615+
*/
1616+
staticbool
1617+
pgwin32_get_dynamic_tokeninfo(HANDLEtoken,TOKEN_INFORMATION_CLASSclass,
1618+
char**InfoBuffer,char*errbuf,interrsize)
1619+
{
1620+
DWORDInfoBufferSize;
1621+
1622+
if (GetTokenInformation(token,class,NULL,0,&InfoBufferSize))
1623+
{
1624+
snprintf(errbuf,errsize,"could not get token information: got zero size\n");
1625+
return false;
1626+
}
1627+
1628+
if (GetLastError()!=ERROR_INSUFFICIENT_BUFFER)
1629+
{
1630+
snprintf(errbuf,errsize,"could not get token information: error code %lu\n",
1631+
GetLastError());
1632+
return false;
1633+
}
1634+
1635+
*InfoBuffer=malloc(InfoBufferSize);
1636+
if (*InfoBuffer==NULL)
1637+
{
1638+
snprintf(errbuf,errsize,"could not allocate %d bytes for token information\n",
1639+
(int)InfoBufferSize);
1640+
return false;
1641+
}
1642+
1643+
if (!GetTokenInformation(token,class,*InfoBuffer,
1644+
InfoBufferSize,&InfoBufferSize))
1645+
{
1646+
snprintf(errbuf,errsize,"could not get token information: error code %lu\n",
1647+
GetLastError());
1648+
return false;
1649+
}
1650+
1651+
return true;
1652+
}
1653+
1654+
/*
1655+
* We consider ourselves running as a service if one of the following is
1656+
* true:
1657+
*
1658+
* 1) We are running as Local System (only used by services)
1659+
* 2) Our token contains SECURITY_SERVICE_RID (automatically added to the
1660+
* process token by the SCM when starting a service)
1661+
*
1662+
* Return values:
1663+
* 0 = Not service
1664+
* 1 = Service
1665+
*-1 = Error
1666+
*
1667+
* Note: we can't report errors via write_stderr (because that calls this)
1668+
* We are therefore reduced to writing directly on stderr, which sucks, but
1669+
* we have few alternatives.
1670+
*/
1671+
int
1672+
pgwin32_is_service(void)
1673+
{
1674+
staticint_is_service=-1;
1675+
HANDLEAccessToken;
1676+
char*InfoBuffer=NULL;
1677+
charerrbuf[256];
1678+
PTOKEN_GROUPSGroups;
1679+
PTOKEN_USERUser;
1680+
PSIDServiceSid;
1681+
PSIDLocalSystemSid;
1682+
SID_IDENTIFIER_AUTHORITYNtAuthority= {SECURITY_NT_AUTHORITY};
1683+
UINTx;
1684+
1685+
/* Only check the first time */
1686+
if (_is_service!=-1)
1687+
return_is_service;
1688+
1689+
if (!OpenProcessToken(GetCurrentProcess(),TOKEN_READ,&AccessToken))
1690+
{
1691+
fprintf(stderr,"could not open process token: error code %lu\n",
1692+
GetLastError());
1693+
return-1;
1694+
}
1695+
1696+
/* First check for local system */
1697+
if (!pgwin32_get_dynamic_tokeninfo(AccessToken,TokenUser,&InfoBuffer,
1698+
errbuf,sizeof(errbuf)))
1699+
{
1700+
fprintf(stderr,"%s",errbuf);
1701+
return-1;
1702+
}
1703+
1704+
User= (PTOKEN_USER)InfoBuffer;
1705+
1706+
if (!AllocateAndInitializeSid(&NtAuthority,1,
1707+
SECURITY_LOCAL_SYSTEM_RID,0,0,0,0,0,0,0,
1708+
&LocalSystemSid))
1709+
{
1710+
fprintf(stderr,"could not get SID for local system account\n");
1711+
CloseHandle(AccessToken);
1712+
return-1;
1713+
}
1714+
1715+
if (EqualSid(LocalSystemSid,User->User.Sid))
1716+
{
1717+
FreeSid(LocalSystemSid);
1718+
free(InfoBuffer);
1719+
CloseHandle(AccessToken);
1720+
_is_service=1;
1721+
return_is_service;
1722+
}
1723+
1724+
FreeSid(LocalSystemSid);
1725+
free(InfoBuffer);
1726+
1727+
/* Now check for group SID */
1728+
if (!pgwin32_get_dynamic_tokeninfo(AccessToken,TokenGroups,&InfoBuffer,
1729+
errbuf,sizeof(errbuf)))
1730+
{
1731+
fprintf(stderr,"%s",errbuf);
1732+
return-1;
1733+
}
1734+
1735+
Groups= (PTOKEN_GROUPS)InfoBuffer;
1736+
1737+
if (!AllocateAndInitializeSid(&NtAuthority,1,
1738+
SECURITY_SERVICE_RID,0,0,0,0,0,0,0,
1739+
&ServiceSid))
1740+
{
1741+
fprintf(stderr,"could not get SID for service group\n");
1742+
free(InfoBuffer);
1743+
CloseHandle(AccessToken);
1744+
return-1;
1745+
}
1746+
1747+
_is_service=0;
1748+
for (x=0;x<Groups->GroupCount;x++)
1749+
{
1750+
if (EqualSid(ServiceSid,Groups->Groups[x].Sid))
1751+
{
1752+
_is_service=1;
1753+
break;
1754+
}
1755+
}
1756+
1757+
free(InfoBuffer);
1758+
FreeSid(ServiceSid);
1759+
1760+
CloseHandle(AccessToken);
1761+
1762+
return_is_service;
1763+
}
1764+
16071765

16081766
/*
16091767
* Mingw headers are incomplete, and so are the libraries. So we have to load

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp