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

Commitc7aca3d

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 parent8c558b2 commitc7aca3d

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
@@ -152,6 +152,10 @@ static void WINAPI pgwin32_ServiceHandler(DWORD);
152152
staticvoidWINAPIpgwin32_ServiceMain(DWORD,LPTSTR*);
153153
staticvoidpgwin32_doRunAsService(void);
154154
staticintCreateRestrictedProcess(char*cmd,PROCESS_INFORMATION*processInfo,boolas_service);
155+
staticboolpgwin32_get_dynamic_tokeninfo(HANDLEtoken,
156+
TOKEN_INFORMATION_CLASSclass,
157+
char**InfoBuffer,char*errbuf,interrsize);
158+
staticintpgwin32_is_service(void);
155159
#endif
156160

157161
staticpgpid_tget_pgpid(boolis_status_request);
@@ -218,7 +222,7 @@ write_stderr(const char *fmt,...)
218222
* On Win32, we print to stderr if running on a console, or write to
219223
* eventlog if running as a service
220224
*/
221-
if (!isatty(fileno(stderr)))/* Running as a service */
225+
if (!pgwin32_is_service())/* Running as a service */
222226
{
223227
charerrbuf[2048];/* Arbitrary size? */
224228

@@ -1681,6 +1685,160 @@ pgwin32_doRunAsService(void)
16811685
}
16821686
}
16831687

1688+
/*
1689+
* Call GetTokenInformation() on a token and return a dynamically sized
1690+
* buffer with the information in it. This buffer must be free():d by
1691+
* the calling function!
1692+
*/
1693+
staticbool
1694+
pgwin32_get_dynamic_tokeninfo(HANDLEtoken,TOKEN_INFORMATION_CLASSclass,
1695+
char**InfoBuffer,char*errbuf,interrsize)
1696+
{
1697+
DWORDInfoBufferSize;
1698+
1699+
if (GetTokenInformation(token,class,NULL,0,&InfoBufferSize))
1700+
{
1701+
snprintf(errbuf,errsize,"could not get token information: got zero size\n");
1702+
return false;
1703+
}
1704+
1705+
if (GetLastError()!=ERROR_INSUFFICIENT_BUFFER)
1706+
{
1707+
snprintf(errbuf,errsize,"could not get token information: error code %lu\n",
1708+
GetLastError());
1709+
return false;
1710+
}
1711+
1712+
*InfoBuffer=malloc(InfoBufferSize);
1713+
if (*InfoBuffer==NULL)
1714+
{
1715+
snprintf(errbuf,errsize,"could not allocate %d bytes for token information\n",
1716+
(int)InfoBufferSize);
1717+
return false;
1718+
}
1719+
1720+
if (!GetTokenInformation(token,class,*InfoBuffer,
1721+
InfoBufferSize,&InfoBufferSize))
1722+
{
1723+
snprintf(errbuf,errsize,"could not get token information: error code %lu\n",
1724+
GetLastError());
1725+
return false;
1726+
}
1727+
1728+
return true;
1729+
}
1730+
1731+
/*
1732+
* We consider ourselves running as a service if one of the following is
1733+
* true:
1734+
*
1735+
* 1) We are running as Local System (only used by services)
1736+
* 2) Our token contains SECURITY_SERVICE_RID (automatically added to the
1737+
* process token by the SCM when starting a service)
1738+
*
1739+
* Return values:
1740+
* 0 = Not service
1741+
* 1 = Service
1742+
*-1 = Error
1743+
*
1744+
* Note: we can't report errors via write_stderr (because that calls this)
1745+
* We are therefore reduced to writing directly on stderr, which sucks, but
1746+
* we have few alternatives.
1747+
*/
1748+
int
1749+
pgwin32_is_service(void)
1750+
{
1751+
staticint_is_service=-1;
1752+
HANDLEAccessToken;
1753+
char*InfoBuffer=NULL;
1754+
charerrbuf[256];
1755+
PTOKEN_GROUPSGroups;
1756+
PTOKEN_USERUser;
1757+
PSIDServiceSid;
1758+
PSIDLocalSystemSid;
1759+
SID_IDENTIFIER_AUTHORITYNtAuthority= {SECURITY_NT_AUTHORITY};
1760+
UINTx;
1761+
1762+
/* Only check the first time */
1763+
if (_is_service!=-1)
1764+
return_is_service;
1765+
1766+
if (!OpenProcessToken(GetCurrentProcess(),TOKEN_READ,&AccessToken))
1767+
{
1768+
fprintf(stderr,"could not open process token: error code %lu\n",
1769+
GetLastError());
1770+
return-1;
1771+
}
1772+
1773+
/* First check for local system */
1774+
if (!pgwin32_get_dynamic_tokeninfo(AccessToken,TokenUser,&InfoBuffer,
1775+
errbuf,sizeof(errbuf)))
1776+
{
1777+
fprintf(stderr,"%s",errbuf);
1778+
return-1;
1779+
}
1780+
1781+
User= (PTOKEN_USER)InfoBuffer;
1782+
1783+
if (!AllocateAndInitializeSid(&NtAuthority,1,
1784+
SECURITY_LOCAL_SYSTEM_RID,0,0,0,0,0,0,0,
1785+
&LocalSystemSid))
1786+
{
1787+
fprintf(stderr,"could not get SID for local system account\n");
1788+
CloseHandle(AccessToken);
1789+
return-1;
1790+
}
1791+
1792+
if (EqualSid(LocalSystemSid,User->User.Sid))
1793+
{
1794+
FreeSid(LocalSystemSid);
1795+
free(InfoBuffer);
1796+
CloseHandle(AccessToken);
1797+
_is_service=1;
1798+
return_is_service;
1799+
}
1800+
1801+
FreeSid(LocalSystemSid);
1802+
free(InfoBuffer);
1803+
1804+
/* Now check for group SID */
1805+
if (!pgwin32_get_dynamic_tokeninfo(AccessToken,TokenGroups,&InfoBuffer,
1806+
errbuf,sizeof(errbuf)))
1807+
{
1808+
fprintf(stderr,"%s",errbuf);
1809+
return-1;
1810+
}
1811+
1812+
Groups= (PTOKEN_GROUPS)InfoBuffer;
1813+
1814+
if (!AllocateAndInitializeSid(&NtAuthority,1,
1815+
SECURITY_SERVICE_RID,0,0,0,0,0,0,0,
1816+
&ServiceSid))
1817+
{
1818+
fprintf(stderr,"could not get SID for service group\n");
1819+
free(InfoBuffer);
1820+
CloseHandle(AccessToken);
1821+
return-1;
1822+
}
1823+
1824+
_is_service=0;
1825+
for (x=0;x<Groups->GroupCount;x++)
1826+
{
1827+
if (EqualSid(ServiceSid,Groups->Groups[x].Sid))
1828+
{
1829+
_is_service=1;
1830+
break;
1831+
}
1832+
}
1833+
1834+
free(InfoBuffer);
1835+
FreeSid(ServiceSid);
1836+
1837+
CloseHandle(AccessToken);
1838+
1839+
return_is_service;
1840+
}
1841+
16841842

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

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp