21 #ifdef HAVE_SYS_RESOURCE_H 23 #include <sys/resource.h> 70 #define DEFAULT_WAIT 60 72 #define USEC_PER_SEC 1000000 74 #define WAITS_PER_SEC 10 81 static int sig = SIGINT;
105 static DWORD pgctl_start_type = SERVICE_AUTO_START;
106 static SERVICE_STATUS
status;
107 static SERVICE_STATUS_HANDLE hStatus = (SERVICE_STATUS_HANDLE) 0;
108 static HANDLE shutdownHandles[2];
109 static pid_t postmasterPID = -1;
111 #define shutdownEvent shutdownHandles[0] 112 #define postmasterProcess shutdownHandles[1] 119 static
void set_mode(
char *modeopt);
120 static
void set_sig(
char *signame);
133 #if (_MSC_VER >= 1800) 134 #include <versionhelpers.h> 136 static bool IsWindowsXPOrGreater(
void);
137 static bool IsWindows7OrGreater(
void);
139 static bool pgwin32_IsInstalled(SC_HANDLE);
140 static char *pgwin32_CommandLine(
bool);
141 static void pgwin32_doRegister(
void);
142 static void pgwin32_doUnregister(
void);
143 static void pgwin32_SetServiceStatus(DWORD);
144 static void WINAPI pgwin32_ServiceHandler(DWORD);
145 static void WINAPI pgwin32_ServiceMain(DWORD, LPTSTR *);
146 static void pgwin32_doRunAsService(
void);
147 static int CreateRestrictedProcess(
char *cmd, PROCESS_INFORMATION *processInfo,
bool as_service);
148 static PTOKEN_PRIVILEGES GetPrivilegesToDelete(HANDLE hToken);
152 static char **
readfile(
const char *path,
int *numlines);
160 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE) 161 static void unlimit_core_size(
void);
169 write_eventlog(
int level,
const char *line)
171 static HANDLE evtHandle = INVALID_HANDLE_VALUE;
173 if (
silent_mode && level == EVENTLOG_INFORMATION_TYPE)
176 if (evtHandle == INVALID_HANDLE_VALUE)
178 evtHandle = RegisterEventSource(NULL,
180 if (evtHandle == NULL)
182 evtHandle = INVALID_HANDLE_VALUE;
187 ReportEvent(evtHandle,
211 vfprintf(stderr, fmt, ap);
222 vsnprintf(errbuf,
sizeof(errbuf), fmt, ap);
224 write_eventlog(EVENTLOG_ERROR_TYPE, errbuf);
228 vfprintf(stderr, fmt, ap);
268 exit(is_status_request ? 4 : 1);
273 write_stderr(
_(
"%s: directory \"%s\" is not a database cluster directory\n"),
275 exit(is_status_request ? 4 : 1);
291 if (fscanf(pidf,
"%ld", &pid) != 1)
294 if (ftell(pidf) == 0 && feof(pidf))
338 fd = open(path, O_RDONLY |
PG_BINARY, 0);
341 if (fstat(fd, &statbuf) < 0)
346 if (statbuf.st_size == 0)
350 result = (
char **)
pg_malloc(
sizeof(
char *));
356 len =
read(fd, buffer, statbuf.st_size + 1);
358 if (len != statbuf.st_size)
371 for (i = 0; i < len; i++)
373 if (buffer[i] ==
'\n')
378 result = (
char **)
pg_malloc((nlines + 1) *
sizeof(
char *));
384 for (i = 0; i < len; i++)
386 if (buffer[i] ==
'\n')
388 int slen = &buffer[
i] - linebegin;
391 memcpy(linebuf, linebegin, slen);
393 if (slen > 0 && linebuf[slen - 1] ==
'\r')
395 linebuf[slen] =
'\0';
396 result[n++] = linebuf;
397 linebegin = &buffer[i + 1];
414 char *curr_line = NULL;
420 while ((curr_line = optlines[i++]))
484 (void) execl(
"/bin/sh",
"/bin/sh",
"-c", cmd, (
char *) NULL);
500 PROCESS_INFORMATION pi;
509 if (!CreateRestrictedProcess(cmd, &pi,
false))
511 write_stderr(
_(
"%s: could not start server: error code %lu\n"),
512 progname, (
unsigned long) GetLastError());
516 postmasterProcess = pi.hProcess;
517 CloseHandle(pi.hThread);
518 return pi.dwProcessId;
611 if (waitpid((pid_t) pm_pid, &exitstatus, WNOHANG) == (pid_t) pm_pid)
615 if (WaitForSingleObject(postmasterProcess, 0) == WAIT_OBJECT_0)
620 if (i % WAITS_PER_SEC == 0)
632 status.dwWaitHint += 6000;
634 SetServiceStatus(hStatus, (LPSERVICE_STATUS) &
status);
649 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE) 651 unlimit_core_size(
void)
655 getrlimit(RLIMIT_CORE, &lim);
656 if (lim.rlim_max == 0)
658 write_stderr(
_(
"%s: cannot set core file size limit; disallowed by hard limit\n"),
662 else if (lim.rlim_max == RLIM_INFINITY || lim.rlim_cur < lim.rlim_max)
664 lim.rlim_cur = lim.rlim_max;
665 setrlimit(RLIMIT_CORE, &lim);
682 if (optlines == NULL)
687 else if (numlines != 1)
689 write_stderr(
_(
"%s: option file \"%s\" must have exactly one line\n"),
698 optline = optlines[0];
704 if ((arg1 = strstr(optline,
" \"")) != NULL)
727 if ((ret =
find_other_exec(argv0, target, versionstr, found_path)) < 0)
736 "but was not found in the\n" 737 "same directory as \"%s\".\n" 738 "Check your installation.\n"),
742 "but was not the same version as %s.\n" 743 "Check your installation.\n"),
772 if (system(cmd) != 0)
790 "trying to start server anyway\n"),
803 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE) 815 static char env_var[32];
817 snprintf(env_var,
sizeof(env_var),
"PG_GRANDPARENT_PID=%d",
827 print_msg(
_(
"waiting for server to start..."));
844 "Examine the log output.\n"),
855 CloseHandle(postmasterProcess);
856 postmasterProcess = INVALID_HANDLE_VALUE;
880 "single-user server is running (PID: %ld)\n"),
885 if (
kill((pid_t) pid,
sig) != 0)
909 print_msg(
_(
"WARNING: online backup mode is active\n" 910 "Shutdown will not complete until pg_stop_backup() is called.\n\n"));
913 print_msg(
_(
"waiting for server to shut down..."));
919 if (cnt % WAITS_PER_SEC == 0)
933 write_stderr(
_(
"HINT: The \"-m fast\" option immediately disconnects sessions rather than\n" 934 "waiting for session-initiated disconnection.\n"));
972 "single-user server is running (PID: %ld)\n"),
974 write_stderr(
_(
"Please terminate the single-user server and try again.\n"));
981 if (
kill((pid_t) pid,
sig) != 0)
998 print_msg(
_(
"WARNING: online backup mode is active\n" 999 "Shutdown will not complete until pg_stop_backup() is called.\n\n"));
1002 print_msg(
_(
"waiting for server to shut down..."));
1010 if (cnt % WAITS_PER_SEC == 0)
1024 write_stderr(
_(
"HINT: The \"-m fast\" option immediately disconnects sessions rather than\n" 1025 "waiting for session-initiated disconnection.\n"));
1034 write_stderr(
_(
"%s: old server process (PID: %ld) seems to be gone\n"),
1058 "single-user server is running (PID: %ld)\n"),
1060 write_stderr(
_(
"Please terminate the single-user server and try again.\n"));
1064 if (
kill((pid_t) pid,
sig) != 0)
1066 write_stderr(
_(
"%s: could not send reload signal (PID: %ld): %s\n"),
1097 "single-user server is running (PID: %ld)\n"),
1105 "server is not in standby mode\n"),
1119 write_stderr(
_(
"%s: could not create promote signal file \"%s\": %s\n"),
1123 if (fclose(prmfile))
1125 write_stderr(
_(
"%s: could not write promote signal file \"%s\": %s\n"),
1131 if (
kill((pid_t) pid,
sig) != 0)
1133 write_stderr(
_(
"%s: could not send promote signal (PID: %ld): %s\n"),
1136 write_stderr(
_(
"%s: could not remove promote signal file \"%s\": %s\n"),
1146 print_msg(
_(
"waiting for server to promote..."));
1153 if (cnt % WAITS_PER_SEC == 0)
1192 if (pid == getpid())
1195 if (pid == getppid())
1198 if (
kill(pid, 0) == 0)
1218 printf(
_(
"%s: single-user server is running (PID: %ld)\n"),
1232 printf(
_(
"%s: server is running (PID: %ld)\n"),
1236 if (optlines != NULL)
1238 for (curr_line = optlines; *curr_line != NULL; curr_line++)
1248 printf(
_(
"%s: no server running\n"),
progname);
1263 if (
kill((pid_t) pid,
sig) != 0)
1265 write_stderr(
_(
"%s: could not send signal %d (PID: %ld): %s\n"),
1273 #if (_MSC_VER < 1800) 1275 IsWindowsXPOrGreater(
void)
1279 osv.dwOSVersionInfoSize =
sizeof(osv);
1282 return (!GetVersionEx(&osv) ||
1283 osv.dwMajorVersion > 5 || (osv.dwMajorVersion == 5 && osv.dwMinorVersion >= 1));
1287 IsWindows7OrGreater(
void)
1291 osv.dwOSVersionInfoSize =
sizeof(osv);
1294 return (!GetVersionEx(&osv) ||
1295 osv.dwMajorVersion > 6 || (osv.dwMajorVersion == 6 && osv.dwMinorVersion >= 0));
1300 pgwin32_IsInstalled(SC_HANDLE hSCM)
1303 bool bResult = (hService != NULL);
1306 CloseServiceHandle(hService);
1311 pgwin32_CommandLine(
bool registration)
1338 if (strlen(cmdPath) < 4 ||
1340 snprintf(cmdPath + strlen(cmdPath),
sizeof(cmdPath) - strlen(cmdPath),
1391 return cmdLine->
data;
1395 pgwin32_doRegister(
void)
1398 SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
1405 if (pgwin32_IsInstalled(hSCM))
1407 CloseServiceHandle(hSCM);
1413 SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
1414 pgctl_start_type, SERVICE_ERROR_NORMAL,
1415 pgwin32_CommandLine(
true),
1418 CloseServiceHandle(hSCM);
1419 write_stderr(
_(
"%s: could not register service \"%s\": error code %lu\n"),
1421 (
unsigned long) GetLastError());
1424 CloseServiceHandle(hService);
1425 CloseServiceHandle(hSCM);
1429 pgwin32_doUnregister(
void)
1432 SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
1439 if (!pgwin32_IsInstalled(hSCM))
1441 CloseServiceHandle(hSCM);
1448 CloseServiceHandle(hSCM);
1449 write_stderr(
_(
"%s: could not open service \"%s\": error code %lu\n"),
1451 (
unsigned long) GetLastError());
1454 if (!DeleteService(hService))
1456 CloseServiceHandle(hService);
1457 CloseServiceHandle(hSCM);
1458 write_stderr(
_(
"%s: could not unregister service \"%s\": error code %lu\n"),
1460 (
unsigned long) GetLastError());
1463 CloseServiceHandle(hService);
1464 CloseServiceHandle(hSCM);
1468 pgwin32_SetServiceStatus(DWORD currentState)
1470 status.dwCurrentState = currentState;
1471 SetServiceStatus(hStatus, (LPSERVICE_STATUS) &
status);
1475 pgwin32_ServiceHandler(DWORD request)
1479 case SERVICE_CONTROL_STOP:
1480 case SERVICE_CONTROL_SHUTDOWN:
1487 status.dwWaitHint = 10000;
1488 pgwin32_SetServiceStatus(SERVICE_STOP_PENDING);
1489 SetEvent(shutdownEvent);
1492 case SERVICE_CONTROL_PAUSE:
1494 status.dwWaitHint = 5000;
1499 case SERVICE_CONTROL_CONTINUE:
1500 case SERVICE_CONTROL_INTERROGATE:
1507 pgwin32_ServiceMain(DWORD argc, LPTSTR *argv)
1509 PROCESS_INFORMATION pi;
1513 status.dwWin32ExitCode = S_OK;
1515 status.dwWaitHint = 60000;
1516 status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1517 status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE;
1518 status.dwServiceSpecificExitCode = 0;
1519 status.dwCurrentState = SERVICE_START_PENDING;
1521 memset(&pi, 0,
sizeof(pi));
1526 if ((hStatus = RegisterServiceCtrlHandler(
register_servicename, pgwin32_ServiceHandler)) == (SERVICE_STATUS_HANDLE) 0)
1529 if ((shutdownEvent = CreateEvent(NULL,
true,
false, NULL)) == NULL)
1533 pgwin32_SetServiceStatus(SERVICE_START_PENDING);
1534 if (!CreateRestrictedProcess(pgwin32_CommandLine(
false), &pi,
true))
1536 pgwin32_SetServiceStatus(SERVICE_STOPPED);
1539 postmasterPID = pi.dwProcessId;
1540 postmasterProcess = pi.hProcess;
1541 CloseHandle(pi.hThread);
1545 write_eventlog(EVENTLOG_INFORMATION_TYPE,
_(
"Waiting for server startup...\n"));
1548 write_eventlog(EVENTLOG_ERROR_TYPE,
_(
"Timed out waiting for server startup\n"));
1549 pgwin32_SetServiceStatus(SERVICE_STOPPED);
1552 write_eventlog(EVENTLOG_INFORMATION_TYPE,
_(
"Server started and accepting connections\n"));
1555 pgwin32_SetServiceStatus(SERVICE_RUNNING);
1558 ret = WaitForMultipleObjects(2, shutdownHandles,
FALSE, INFINITE);
1560 pgwin32_SetServiceStatus(SERVICE_STOP_PENDING);
1569 int maxShutdownCheckPoint =
status.dwCheckPoint + 12;
1571 kill(postmasterPID, SIGINT);
1577 while (WaitForSingleObject(postmasterProcess, 5000) == WAIT_TIMEOUT &&
status.dwCheckPoint < maxShutdownCheckPoint)
1580 SetServiceStatus(hStatus, (LPSERVICE_STATUS) &
status);
1585 case (WAIT_OBJECT_0 + 1):
1593 CloseHandle(shutdownEvent);
1594 CloseHandle(postmasterProcess);
1596 pgwin32_SetServiceStatus(SERVICE_STOPPED);
1600 pgwin32_doRunAsService(
void)
1605 if (StartServiceCtrlDispatcher(st) == 0)
1607 write_stderr(
_(
"%s: could not start service \"%s\": error code %lu\n"),
1609 (
unsigned long) GetLastError());
1621 typedef BOOL (WINAPI * __CreateRestrictedToken) (HANDLE, DWORD, DWORD, PSID_AND_ATTRIBUTES, DWORD, PLUID_AND_ATTRIBUTES, DWORD, PSID_AND_ATTRIBUTES, PHANDLE);
1622 typedef BOOL (WINAPI * __IsProcessInJob) (HANDLE, HANDLE, PBOOL);
1623 typedef HANDLE (WINAPI * __CreateJobObject) (LPSECURITY_ATTRIBUTES, LPCTSTR);
1624 typedef BOOL (WINAPI * __SetInformationJobObject) (HANDLE, JOBOBJECTINFOCLASS, LPVOID, DWORD);
1625 typedef BOOL (WINAPI * __AssignProcessToJobObject) (HANDLE, HANDLE);
1626 typedef BOOL (WINAPI * __QueryInformationJobObject) (HANDLE, JOBOBJECTINFOCLASS, LPVOID, DWORD, LPDWORD);
1641 CreateRestrictedProcess(
char *cmd, PROCESS_INFORMATION *processInfo,
bool as_service)
1647 HANDLE restrictedToken;
1648 SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
1649 SID_AND_ATTRIBUTES dropSids[2];
1650 PTOKEN_PRIVILEGES delPrivs;
1653 __CreateRestrictedToken _CreateRestrictedToken = NULL;
1654 __IsProcessInJob _IsProcessInJob = NULL;
1655 __CreateJobObject _CreateJobObject = NULL;
1656 __SetInformationJobObject _SetInformationJobObject = NULL;
1657 __AssignProcessToJobObject _AssignProcessToJobObject = NULL;
1658 __QueryInformationJobObject _QueryInformationJobObject = NULL;
1659 HANDLE Kernel32Handle;
1660 HANDLE Advapi32Handle;
1662 ZeroMemory(&si,
sizeof(si));
1665 Advapi32Handle = LoadLibrary(
"ADVAPI32.DLL");
1666 if (Advapi32Handle != NULL)
1668 _CreateRestrictedToken = (__CreateRestrictedToken) GetProcAddress(Advapi32Handle,
"CreateRestrictedToken");
1671 if (_CreateRestrictedToken == NULL)
1678 if (Advapi32Handle != NULL)
1679 FreeLibrary(Advapi32Handle);
1680 return CreateProcess(NULL, cmd, NULL, NULL,
FALSE, 0, NULL, NULL, &si, processInfo);
1684 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &origToken))
1690 write_stderr(
_(
"%s: could not open process token: error code %lu\n"),
1691 progname, (
unsigned long) GetLastError());
1696 ZeroMemory(&dropSids,
sizeof(dropSids));
1697 if (!AllocateAndInitializeSid(&NtAuthority, 2,
1698 SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0,
1699 0, &dropSids[0].Sid) ||
1700 !AllocateAndInitializeSid(&NtAuthority, 2,
1701 SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0,
1702 0, &dropSids[1].Sid))
1704 write_stderr(
_(
"%s: could not allocate SIDs: error code %lu\n"),
1705 progname, (
unsigned long) GetLastError());
1710 delPrivs = GetPrivilegesToDelete(origToken);
1711 if (delPrivs == NULL)
1715 b = _CreateRestrictedToken(origToken,
1717 sizeof(dropSids) /
sizeof(dropSids[0]),
1719 delPrivs->PrivilegeCount, delPrivs->Privileges,
1724 FreeSid(dropSids[1].Sid);
1725 FreeSid(dropSids[0].Sid);
1726 CloseHandle(origToken);
1727 FreeLibrary(Advapi32Handle);
1731 write_stderr(
_(
"%s: could not create restricted token: error code %lu\n"),
1732 progname, (
unsigned long) GetLastError());
1737 r = CreateProcessAsUser(restrictedToken, NULL, cmd, NULL, NULL,
TRUE, CREATE_SUSPENDED, NULL, NULL, &si, processInfo);
1739 Kernel32Handle = LoadLibrary(
"KERNEL32.DLL");
1740 if (Kernel32Handle != NULL)
1742 _IsProcessInJob = (__IsProcessInJob) GetProcAddress(Kernel32Handle,
"IsProcessInJob");
1743 _CreateJobObject = (__CreateJobObject) GetProcAddress(Kernel32Handle,
"CreateJobObjectA");
1744 _SetInformationJobObject = (__SetInformationJobObject) GetProcAddress(Kernel32Handle,
"SetInformationJobObject");
1745 _AssignProcessToJobObject = (__AssignProcessToJobObject) GetProcAddress(Kernel32Handle,
"AssignProcessToJobObject");
1746 _QueryInformationJobObject = (__QueryInformationJobObject) GetProcAddress(Kernel32Handle,
"QueryInformationJobObject");
1750 if (_IsProcessInJob == NULL || _CreateJobObject == NULL || _SetInformationJobObject == NULL || _AssignProcessToJobObject == NULL || _QueryInformationJobObject == NULL)
1756 if (IsWindowsXPOrGreater())
1762 write_stderr(
_(
"%s: WARNING: could not locate all job object functions in system API\n"),
progname);
1768 if (_IsProcessInJob(processInfo->hProcess, NULL, &inJob))
1780 sprintf(jobname,
"PostgreSQL_%lu",
1781 (
unsigned long) processInfo->dwProcessId);
1783 job = _CreateJobObject(NULL, jobname);
1786 JOBOBJECT_BASIC_LIMIT_INFORMATION basicLimit;
1787 JOBOBJECT_BASIC_UI_RESTRICTIONS uiRestrictions;
1788 JOBOBJECT_SECURITY_LIMIT_INFORMATION securityLimit;
1790 ZeroMemory(&basicLimit,
sizeof(basicLimit));
1791 ZeroMemory(&uiRestrictions,
sizeof(uiRestrictions));
1792 ZeroMemory(&securityLimit,
sizeof(securityLimit));
1794 basicLimit.LimitFlags = JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION | JOB_OBJECT_LIMIT_PRIORITY_CLASS;
1795 basicLimit.PriorityClass = NORMAL_PRIORITY_CLASS;
1796 _SetInformationJobObject(job, JobObjectBasicLimitInformation, &basicLimit,
sizeof(basicLimit));
1798 uiRestrictions.UIRestrictionsClass = JOB_OBJECT_UILIMIT_DESKTOP | JOB_OBJECT_UILIMIT_DISPLAYSETTINGS |
1799 JOB_OBJECT_UILIMIT_EXITWINDOWS | JOB_OBJECT_UILIMIT_READCLIPBOARD |
1800 JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS | JOB_OBJECT_UILIMIT_WRITECLIPBOARD;
1804 if (!IsWindows7OrGreater())
1812 uiRestrictions.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_HANDLES;
1815 _SetInformationJobObject(job, JobObjectBasicUIRestrictions, &uiRestrictions,
sizeof(uiRestrictions));
1817 securityLimit.SecurityLimitFlags = JOB_OBJECT_SECURITY_NO_ADMIN | JOB_OBJECT_SECURITY_ONLY_TOKEN;
1818 securityLimit.JobToken = restrictedToken;
1819 _SetInformationJobObject(job, JobObjectSecurityLimitInformation, &securityLimit,
sizeof(securityLimit));
1821 _AssignProcessToJobObject(job, processInfo->hProcess);
1828 CloseHandle(restrictedToken);
1830 ResumeThread(processInfo->hThread);
1832 FreeLibrary(Kernel32Handle);
1846 static PTOKEN_PRIVILEGES
1847 GetPrivilegesToDelete(HANDLE hToken)
1851 PTOKEN_PRIVILEGES tokenPrivs;
1853 LUID luidChangeNotify;
1855 if (!LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, &luidLockPages) ||
1856 !LookupPrivilegeValue(NULL, SE_CHANGE_NOTIFY_NAME, &luidChangeNotify))
1858 write_stderr(
_(
"%s: could not get LUIDs for privileges: error code %lu\n"),
1859 progname, (
unsigned long) GetLastError());
1863 if (!GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &length) &&
1864 GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1866 write_stderr(
_(
"%s: could not get token information: error code %lu\n"),
1867 progname, (
unsigned long) GetLastError());
1871 tokenPrivs = (PTOKEN_PRIVILEGES)
malloc(length);
1872 if (tokenPrivs == NULL)
1878 if (!GetTokenInformation(hToken, TokenPrivileges, tokenPrivs, length, &length))
1880 write_stderr(
_(
"%s: could not get token information: error code %lu\n"),
1881 progname, (
unsigned long) GetLastError());
1886 for (i = 0; i < tokenPrivs->PrivilegeCount; i++)
1888 if (memcmp(&tokenPrivs->Privileges[i].Luid, &luidLockPages,
sizeof(LUID)) == 0 ||
1889 memcmp(&tokenPrivs->Privileges[i].Luid, &luidChangeNotify,
sizeof(LUID)) == 0)
1891 for (j = i; j < tokenPrivs->PrivilegeCount - 1; j++)
1892 tokenPrivs->Privileges[j] = tokenPrivs->Privileges[j + 1];
1893 tokenPrivs->PrivilegeCount--;
1912 printf(
_(
"%s is a utility to initialize, start, stop, or control a PostgreSQL server.\n\n"),
progname);
1913 printf(
_(
"Usage:\n"));
1914 printf(
_(
" %s init[db] [-D DATADIR] [-s] [-o OPTIONS]\n"),
progname);
1915 printf(
_(
" %s start [-D DATADIR] [-l FILENAME] [-W] [-t SECS] [-s]\n" 1916 " [-o OPTIONS] [-p PATH] [-c]\n"),
progname);
1917 printf(
_(
" %s stop [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]\n"),
progname);
1918 printf(
_(
" %s restart [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]\n" 1919 " [-o OPTIONS] [-c]\n"),
progname);
1920 printf(
_(
" %s reload [-D DATADIR] [-s]\n"),
progname);
1921 printf(
_(
" %s status [-D DATADIR]\n"),
progname);
1922 printf(
_(
" %s promote [-D DATADIR] [-W] [-t SECS] [-s]\n"),
progname);
1923 printf(
_(
" %s kill SIGNALNAME PID\n"),
progname);
1925 printf(
_(
" %s register [-D DATADIR] [-N SERVICENAME] [-U USERNAME] [-P PASSWORD]\n" 1926 " [-S START-TYPE] [-e SOURCE] [-W] [-t SECS] [-s] [-o OPTIONS]\n"),
progname);
1927 printf(
_(
" %s unregister [-N SERVICENAME]\n"),
progname);
1930 printf(
_(
"\nCommon options:\n"));
1931 printf(
_(
" -D, --pgdata=DATADIR location of the database storage area\n"));
1933 printf(
_(
" -e SOURCE event source for logging when running as a service\n"));
1935 printf(
_(
" -s, --silent only print errors, no informational messages\n"));
1936 printf(
_(
" -t, --timeout=SECS seconds to wait when using -w option\n"));
1937 printf(
_(
" -V, --version output version information, then exit\n"));
1938 printf(
_(
" -w, --wait wait until operation completes (default)\n"));
1939 printf(
_(
" -W, --no-wait do not wait until operation completes\n"));
1940 printf(
_(
" -?, --help show this help, then exit\n"));
1941 printf(
_(
"If the -D option is omitted, the environment variable PGDATA is used.\n"));
1943 printf(
_(
"\nOptions for start or restart:\n"));
1944 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE) 1945 printf(
_(
" -c, --core-files allow postgres to produce core files\n"));
1947 printf(
_(
" -c, --core-files not applicable on this platform\n"));
1949 printf(
_(
" -l, --log=FILENAME write (or append) server log to FILENAME\n"));
1950 printf(
_(
" -o, --options=OPTIONS command line options to pass to postgres\n" 1951 " (PostgreSQL server executable) or initdb\n"));
1952 printf(
_(
" -p PATH-TO-POSTGRES normally not necessary\n"));
1953 printf(
_(
"\nOptions for stop or restart:\n"));
1954 printf(
_(
" -m, --mode=MODE MODE can be \"smart\", \"fast\", or \"immediate\"\n"));
1956 printf(
_(
"\nShutdown modes are:\n"));
1957 printf(
_(
" smart quit after all clients have disconnected\n"));
1958 printf(
_(
" fast quit directly, with proper shutdown (default)\n"));
1959 printf(
_(
" immediate quit without complete shutdown; will lead to recovery on restart\n"));
1961 printf(
_(
"\nAllowed signal names for kill:\n"));
1962 printf(
" ABRT HUP INT KILL QUIT TERM USR1 USR2\n");
1965 printf(
_(
"\nOptions for register and unregister:\n"));
1966 printf(
_(
" -N SERVICENAME service name with which to register PostgreSQL server\n"));
1967 printf(
_(
" -P PASSWORD password of account to register PostgreSQL server\n"));
1968 printf(
_(
" -U USERNAME user name of account to register PostgreSQL server\n"));
1969 printf(
_(
" -S START-TYPE service start type to register PostgreSQL server\n"));
1971 printf(
_(
"\nStart types are:\n"));
1972 printf(
_(
" auto start service automatically during system startup (default)\n"));
1973 printf(
_(
" demand start service on demand\n"));
1976 printf(
_(
"\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
1984 if (strcmp(modeopt,
"s") == 0 || strcmp(modeopt,
"smart") == 0)
1989 else if (strcmp(modeopt,
"f") == 0 || strcmp(modeopt,
"fast") == 0)
1994 else if (strcmp(modeopt,
"i") == 0 || strcmp(modeopt,
"immediate") == 0)
2012 if (strcmp(signame,
"HUP") == 0)
2014 else if (strcmp(signame,
"INT") == 0)
2016 else if (strcmp(signame,
"QUIT") == 0)
2018 else if (strcmp(signame,
"ABRT") == 0)
2020 else if (strcmp(signame,
"KILL") == 0)
2022 else if (strcmp(signame,
"TERM") == 0)
2024 else if (strcmp(signame,
"USR1") == 0)
2026 else if (strcmp(signame,
"USR2") == 0)
2039 set_starttype(
char *starttypeopt)
2041 if (strcmp(starttypeopt,
"a") == 0 || strcmp(starttypeopt,
"auto") == 0)
2042 pgctl_start_type = SERVICE_AUTO_START;
2043 else if (strcmp(starttypeopt,
"d") == 0 || strcmp(starttypeopt,
"demand") == 0)
2044 pgctl_start_type = SERVICE_DEMAND_START;
2073 if ((fd = fopen(filename,
"r")) == NULL)
2079 if ((fd = fopen(filename,
"r")) != NULL)
2099 fd = popen(cmd,
"r");
2100 if (fd == NULL || fgets(filename,
sizeof(filename), fd) == NULL)
2102 write_stderr(
_(
"%s: could not determine the data directory using command \"%s\"\n"),
progname, cmd);
2109 if (strchr(filename,
'\n') != NULL)
2110 *strchr(filename,
'\n') =
'\0';
2131 ret = control_file_data->
state;
2132 pfree(control_file_data);
2140 static struct option long_options[] = {
2161 setvbuf(stderr, NULL, _IONBF, 0);
2180 if (strcmp(argv[1],
"--help") == 0 || strcmp(argv[1],
"-?") == 0)
2185 else if (strcmp(argv[1],
"--version") == 0 || strcmp(argv[1],
"-V") == 0)
2187 puts(
"pg_ctl (PostgreSQL) " PG_VERSION);
2199 "Please log in (using, e.g., \"su\") as the " 2200 "(unprivileged) user that will\n" 2201 "own the server process.\n"),
2207 env_wait = getenv(
"PGCTLTIMEOUT");
2208 if (env_wait != NULL)
2222 while ((c =
getopt_long(argc, argv,
"cD:e:l:m:N:o:p:P:sS:t:U:wW",
2223 long_options, &option_index)) != -1)
2234 env_var =
psprintf(
"PGDATA=%s", pgdata_D);
2266 free(old_post_opts);
2282 write_stderr(
_(
"%s: -S option not supported on this platform\n"),
2292 if (strchr(
optarg,
'\\'))
2324 if (strcmp(argv[
optind],
"init") == 0
2325 || strcmp(argv[optind],
"initdb") == 0)
2327 else if (strcmp(argv[optind],
"start") == 0)
2329 else if (strcmp(argv[optind],
"stop") == 0)
2331 else if (strcmp(argv[optind],
"restart") == 0)
2333 else if (strcmp(argv[optind],
"reload") == 0)
2335 else if (strcmp(argv[optind],
"status") == 0)
2337 else if (strcmp(argv[optind],
"promote") == 0)
2339 else if (strcmp(argv[optind],
"kill") == 0)
2341 if (argc - optind < 3)
2349 killproc = atol(argv[++optind]);
2352 else if (strcmp(argv[optind],
"register") == 0)
2354 else if (strcmp(argv[optind],
"unregister") == 0)
2356 else if (strcmp(argv[optind],
"runservice") == 0)
2392 write_stderr(
_(
"%s: no database directory specified and environment variable PGDATA unset\n"),
2450 pgwin32_doRegister();
2453 pgwin32_doUnregister();
2456 pgwin32_doRunAsService();
#define LOCK_FILE_LINE_PID
char * make_absolute_path(const char *path)
int length(const List *list)
int find_other_exec(const char *argv0, const char *target, const char *versionstr, char *retpath)
static void read_post_opts(void)
void * pg_malloc(size_t size)
const char * get_progname(const char *argv0)
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
ControlFileData * get_controlfile(const char *DataDir, const char *progname, bool *crc_ok_p)
char * psprintf(const char *fmt,...)
static void do_help(void)
void make_native_path(char *path)
static void do_stop(void)
void canonicalize_path(char *path)
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
int pg_strcasecmp(const char *s1, const char *s2)
static ShutdownMode shutdown_mode
BOOL AddUserToTokenDacl(HANDLE hToken)
static char ** readfile(const char *path, int *numlines)
static void adjust_data_dir(void)
#define LOCK_FILE_LINE_START_TIME
static int fd(const char *x, int i)
#define pg_attribute_printf(f, a)
static char * register_password
int int vsnprintf(char *str, size_t count, const char *fmt, va_list args)
void pg_usleep(long microsec)
#define required_argument
void pfree(void *pointer)
static char pid_file[MAXPGPATH]
static char backup_file[MAXPGPATH]
static char * register_username
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
int find_my_exec(const char *argv0, char *retpath)
static char * register_servicename
static void do_start(void)
char * pg_strdup(const char *in)
int pgwin32_is_service(void)
int main(int argc, char **argv)
static void do_kill(pgpid_t pid)
static void do_restart(void)
static pgpid_t get_pgpid(bool is_status_request)
static void do_status(void)
char my_exec_path[MAXPGPATH]
#define PG_TEXTDOMAIN(domain)
#define PG_MODE_MASK_OWNER
PQExpBuffer createPQExpBuffer(void)
static char postopts_file[MAXPGPATH]
static void free_readfile(char **optlines)
#define PG_BACKEND_VERSIONSTR
size_t strlcpy(char *dst, const char *src, size_t siz)
#define PM_STATUS_STANDBY
#define DEFAULT_EVENT_SOURCE
static void do_promote(void)
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
static WaitPMResult wait_for_postmaster(pgpid_t pm_pid, bool do_checkpoint)
static bool allow_core_files
static bool postmaster_is_alive(pid_t pid)
static void do_init(void)
static char * event_source
static const char * progname
static bool wait_seconds_arg
static pgpid_t start_postmaster(void)
static void write_stderr(const char *fmt,...) pg_attribute_printf(1
static char promote_file[MAXPGPATH]
bool GetDataDirectoryCreatePerm(const char *dataDir)
void set_pglocale_pgservice(const char *argv0, const char *app)
static void set_mode(char *modeopt)
static void do_reload(void)
static void static void do_advice(void)
const char * strerror(int errnum)
static char version_file[MAXPGPATH]
static void static void status(const char *fmt,...) pg_attribute_printf(1
static DBState get_control_dbstate(void)
#define LOCK_FILE_LINE_PM_STATUS
static CtlCommand ctl_command
static void print_msg(const char *msg)
static char * find_other_exec_or_die(const char *argv0, const char *target, const char *versionstr)
static void set_sig(char *signame)