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

Commit744d01c

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 parent9919f4f commit744d01c

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
@@ -149,6 +149,10 @@ static void WINAPI pgwin32_ServiceHandler(DWORD);
149149
staticvoidWINAPIpgwin32_ServiceMain(DWORD,LPTSTR*);
150150
staticvoidpgwin32_doRunAsService(void);
151151
staticintCreateRestrictedProcess(char*cmd,PROCESS_INFORMATION*processInfo,boolas_service);
152+
staticboolpgwin32_get_dynamic_tokeninfo(HANDLEtoken,
153+
TOKEN_INFORMATION_CLASSclass,
154+
char**InfoBuffer,char*errbuf,interrsize);
155+
staticintpgwin32_is_service(void);
152156
#endif
153157

154158
staticpgpid_tget_pgpid(boolis_status_request);
@@ -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

@@ -1689,6 +1693,160 @@ pgwin32_doRunAsService(void)
16891693
}
16901694
}
16911695

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

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

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp