21 #ifdef HAVE_SYS_RESOURCE_H
23 #include <sys/resource.h>
73 #define DEFAULT_WAIT 60
75 #define USEC_PER_SEC 1000000
77 #define WAITS_PER_SEC 10
84 static int sig = SIGINT;
111 static DWORD pgctl_start_type = SERVICE_AUTO_START;
112 static SERVICE_STATUS
status;
113 static SERVICE_STATUS_HANDLE hStatus = (SERVICE_STATUS_HANDLE) 0;
114 static HANDLE shutdownHandles[2];
116 #define shutdownEvent shutdownHandles[0]
117 #define postmasterProcess shutdownHandles[1]
124 static
void set_mode(
char *modeopt);
125 static
void set_sig(
char *signame);
139 #include <versionhelpers.h>
140 static bool pgwin32_IsInstalled(SC_HANDLE);
141 static char *pgwin32_CommandLine(
bool);
142 static void pgwin32_doRegister(
void);
143 static void pgwin32_doUnregister(
void);
144 static void pgwin32_SetServiceStatus(DWORD);
145 static void WINAPI pgwin32_ServiceHandler(DWORD);
146 static void WINAPI pgwin32_ServiceMain(DWORD, LPTSTR *);
147 static void pgwin32_doRunAsService(
void);
148 static int CreateRestrictedProcess(
char *cmd, PROCESS_INFORMATION *processInfo,
bool as_service);
149 static PTOKEN_PRIVILEGES GetPrivilegesToDelete(HANDLE hToken);
153 static char **
readfile(
const char *path,
int *numlines);
163 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
164 static void unlimit_core_size(
void);
172 write_eventlog(
int level,
const char *line)
174 static HANDLE evtHandle = INVALID_HANDLE_VALUE;
176 if (
silent_mode && level == EVENTLOG_INFORMATION_TYPE)
179 if (evtHandle == INVALID_HANDLE_VALUE)
181 evtHandle = RegisterEventSource(NULL,
183 if (evtHandle == NULL)
185 evtHandle = INVALID_HANDLE_VALUE;
190 ReportEvent(evtHandle,
227 write_eventlog(EVENTLOG_ERROR_TYPE, errbuf);
271 exit(is_status_request ? 4 : 1);
276 write_stderr(
_(
"%s: directory \"%s\" is not a database cluster directory\n"),
278 exit(is_status_request ? 4 : 1);
294 if (fscanf(pidf,
"%ld", &pid) != 1)
297 if (ftell(pidf) == 0 && feof(pidf))
353 result = (
char **)
pg_malloc(
sizeof(
char *));
376 if (buffer[
i] ==
'\n')
381 result = (
char **)
pg_malloc((nlines + 1) *
sizeof(
char *));
389 if (buffer[
i] ==
'\n')
391 int slen = &buffer[
i] - linebegin;
394 memcpy(linebuf, linebegin, slen);
396 if (slen > 0 && linebuf[slen - 1] ==
'\r')
398 linebuf[slen] =
'\0';
399 result[n++] = linebuf;
400 linebegin = &buffer[
i + 1];
417 char *curr_line = NULL;
423 while ((curr_line = optlines[
i++]))
484 write_stderr(
_(
"%s: could not start server due to setsid() failure: %s\n"),
496 cmd =
psprintf(
"exec \"%s\" %s%s < \"%s\" >> \"%s\" 2>&1",
500 cmd =
psprintf(
"exec \"%s\" %s%s < \"%s\" 2>&1",
503 (void) execl(
"/bin/sh",
"/bin/sh",
"-c", cmd, (
char *) NULL);
519 PROCESS_INFORMATION pi;
523 comspec = getenv(
"COMSPEC");
562 cmd =
psprintf(
"\"%s\" /C \"\"%s\" %s%s < \"%s\" >> \"%s\" 2>&1\"",
566 cmd =
psprintf(
"\"%s\" /C \"\"%s\" %s%s < \"%s\" 2>&1\"",
569 if (!CreateRestrictedProcess(cmd, &pi,
false))
571 write_stderr(
_(
"%s: could not start server: error code %lu\n"),
572 progname, (
unsigned long) GetLastError());
576 postmasterProcess = pi.hProcess;
577 CloseHandle(pi.hThread);
578 return pi.dwProcessId;
671 if (waitpid((pid_t) pm_pid, &exitstatus, WNOHANG) == (pid_t) pm_pid)
675 if (WaitForSingleObject(postmasterProcess, 0) == WAIT_OBJECT_0)
692 status.dwWaitHint += 6000;
694 SetServiceStatus(hStatus, (LPSERVICE_STATUS) &
status);
727 if (
kill((pid_t) pid, 0) != 0)
764 if (
kill((pid_t) pid, 0) != 0)
779 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
781 unlimit_core_size(
void)
785 getrlimit(RLIMIT_CORE, &lim);
786 if (lim.rlim_max == 0)
788 write_stderr(
_(
"%s: cannot set core file size limit; disallowed by hard limit\n"),
792 else if (lim.rlim_max == RLIM_INFINITY || lim.rlim_cur < lim.rlim_max)
794 lim.rlim_cur = lim.rlim_max;
795 setrlimit(RLIMIT_CORE, &lim);
812 if (optlines == NULL)
817 else if (numlines != 1)
819 write_stderr(
_(
"%s: option file \"%s\" must have exactly one line\n"),
828 optline = optlines[0];
834 if ((arg1 = strstr(optline,
" \"")) != NULL)
861 write_stderr(
_(
"%s: could not send stop signal (PID: %ld): %s\n"),
889 write_stderr(
_(
"program \"%s\" is needed by %s but was not found in the same directory as \"%s\"\n"),
892 write_stderr(
_(
"program \"%s\" was found by \"%s\" but was not the same version as %s\n"),
918 cmd =
psprintf(
"\"%s\" %s%s > \"%s\"",
921 if (system(cmd) != 0)
939 "trying to start server anyway\n"),
952 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
966 snprintf(env_var,
sizeof(env_var),
"%d", (
int) getppid());
967 setenv(
"PG_GRANDPARENT_PID", env_var, 1);
986 print_msg(
_(
"waiting for server to start..."));
1003 "Examine the log output.\n"),
1014 CloseHandle(postmasterProcess);
1015 postmasterProcess = INVALID_HANDLE_VALUE;
1037 "single-user server is running (PID: %ld)\n"),
1042 if (
kill((pid_t) pid,
sig) != 0)
1056 print_msg(
_(
"waiting for server to shut down..."));
1064 write_stderr(
_(
"HINT: The \"-m fast\" option immediately disconnects sessions rather than\n"
1065 "waiting for session-initiated disconnection.\n"));
1101 "single-user server is running (PID: %ld)\n"),
1103 write_stderr(
_(
"Please terminate the single-user server and try again.\n"));
1110 if (
kill((pid_t) pid,
sig) != 0)
1117 print_msg(
_(
"waiting for server to shut down..."));
1126 write_stderr(
_(
"HINT: The \"-m fast\" option immediately disconnects sessions rather than\n"
1127 "waiting for session-initiated disconnection.\n"));
1136 write_stderr(
_(
"%s: old server process (PID: %ld) seems to be gone\n"),
1160 "single-user server is running (PID: %ld)\n"),
1162 write_stderr(
_(
"Please terminate the single-user server and try again.\n"));
1166 if (
kill((pid_t) pid,
sig) != 0)
1168 write_stderr(
_(
"%s: could not send reload signal (PID: %ld): %s\n"),
1199 "single-user server is running (PID: %ld)\n"),
1207 "server is not in standby mode\n"),
1216 write_stderr(
_(
"%s: could not create promote signal file \"%s\": %s\n"),
1220 if (fclose(prmfile))
1222 write_stderr(
_(
"%s: could not write promote signal file \"%s\": %s\n"),
1228 if (
kill((pid_t) pid,
sig) != 0)
1230 write_stderr(
_(
"%s: could not send promote signal (PID: %ld): %s\n"),
1233 write_stderr(
_(
"%s: could not remove promote signal file \"%s\": %s\n"),
1240 print_msg(
_(
"waiting for server to promote..."));
1265 FILE *logrotatefile;
1280 "single-user server is running (PID: %ld)\n"),
1289 write_stderr(
_(
"%s: could not create log rotation signal file \"%s\": %s\n"),
1293 if (fclose(logrotatefile))
1295 write_stderr(
_(
"%s: could not write log rotation signal file \"%s\": %s\n"),
1301 if (
kill((pid_t) pid,
sig) != 0)
1303 write_stderr(
_(
"%s: could not send log rotation signal (PID: %ld): %s\n"),
1306 write_stderr(
_(
"%s: could not remove log rotation signal file \"%s\": %s\n"),
1311 print_msg(
_(
"server signaled to rotate log file\n"));
1332 if (pid == getpid())
1335 if (pid == getppid())
1338 if (
kill(pid, 0) == 0)
1358 printf(
_(
"%s: single-user server is running (PID: %ld)\n"),
1372 printf(
_(
"%s: server is running (PID: %ld)\n"),
1376 if (optlines != NULL)
1378 for (curr_line = optlines; *curr_line != NULL; curr_line++)
1403 if (
kill((pid_t) pid,
sig) != 0)
1405 write_stderr(
_(
"%s: could not send signal %d (PID: %ld): %s\n"),
1414 pgwin32_IsInstalled(SC_HANDLE hSCM)
1417 bool bResult = (hService != NULL);
1420 CloseServiceHandle(hService);
1425 pgwin32_CommandLine(
bool registration)
1452 if (strlen(cmdPath) < 4 ||
1454 snprintf(cmdPath + strlen(cmdPath),
sizeof(cmdPath) - strlen(cmdPath),
1505 return cmdLine->
data;
1509 pgwin32_doRegister(
void)
1512 SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
1519 if (pgwin32_IsInstalled(hSCM))
1521 CloseServiceHandle(hSCM);
1527 SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
1528 pgctl_start_type, SERVICE_ERROR_NORMAL,
1529 pgwin32_CommandLine(
true),
1532 CloseServiceHandle(hSCM);
1533 write_stderr(
_(
"%s: could not register service \"%s\": error code %lu\n"),
1535 (
unsigned long) GetLastError());
1538 CloseServiceHandle(hService);
1539 CloseServiceHandle(hSCM);
1543 pgwin32_doUnregister(
void)
1546 SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
1553 if (!pgwin32_IsInstalled(hSCM))
1555 CloseServiceHandle(hSCM);
1562 CloseServiceHandle(hSCM);
1563 write_stderr(
_(
"%s: could not open service \"%s\": error code %lu\n"),
1565 (
unsigned long) GetLastError());
1568 if (!DeleteService(hService))
1570 CloseServiceHandle(hService);
1571 CloseServiceHandle(hSCM);
1572 write_stderr(
_(
"%s: could not unregister service \"%s\": error code %lu\n"),
1574 (
unsigned long) GetLastError());
1577 CloseServiceHandle(hService);
1578 CloseServiceHandle(hSCM);
1582 pgwin32_SetServiceStatus(DWORD currentState)
1584 status.dwCurrentState = currentState;
1585 SetServiceStatus(hStatus, (LPSERVICE_STATUS) &
status);
1589 pgwin32_ServiceHandler(DWORD request)
1593 case SERVICE_CONTROL_STOP:
1594 case SERVICE_CONTROL_SHUTDOWN:
1601 status.dwWaitHint = 10000;
1602 pgwin32_SetServiceStatus(SERVICE_STOP_PENDING);
1603 SetEvent(shutdownEvent);
1606 case SERVICE_CONTROL_PAUSE:
1608 status.dwWaitHint = 5000;
1613 case SERVICE_CONTROL_CONTINUE:
1614 case SERVICE_CONTROL_INTERROGATE:
1621 pgwin32_ServiceMain(DWORD argc, LPTSTR *argv)
1623 PROCESS_INFORMATION pi;
1627 status.dwWin32ExitCode = S_OK;
1629 status.dwWaitHint = 60000;
1630 status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1631 status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE;
1632 status.dwServiceSpecificExitCode = 0;
1633 status.dwCurrentState = SERVICE_START_PENDING;
1635 memset(&pi, 0,
sizeof(pi));
1640 if ((hStatus = RegisterServiceCtrlHandler(
register_servicename, pgwin32_ServiceHandler)) == (SERVICE_STATUS_HANDLE) 0)
1643 if ((shutdownEvent = CreateEvent(NULL,
true,
false, NULL)) == NULL)
1647 pgwin32_SetServiceStatus(SERVICE_START_PENDING);
1648 if (!CreateRestrictedProcess(pgwin32_CommandLine(
false), &pi,
true))
1650 pgwin32_SetServiceStatus(SERVICE_STOPPED);
1654 postmasterProcess = pi.hProcess;
1655 CloseHandle(pi.hThread);
1659 write_eventlog(EVENTLOG_INFORMATION_TYPE,
_(
"Waiting for server startup...\n"));
1662 write_eventlog(EVENTLOG_ERROR_TYPE,
_(
"Timed out waiting for server startup\n"));
1663 pgwin32_SetServiceStatus(SERVICE_STOPPED);
1666 write_eventlog(EVENTLOG_INFORMATION_TYPE,
_(
"Server started and accepting connections\n"));
1669 pgwin32_SetServiceStatus(SERVICE_RUNNING);
1672 ret = WaitForMultipleObjects(2, shutdownHandles, FALSE, INFINITE);
1674 pgwin32_SetServiceStatus(SERVICE_STOP_PENDING);
1683 int maxShutdownCheckPoint =
status.dwCheckPoint + 12;
1691 while (WaitForSingleObject(postmasterProcess, 5000) == WAIT_TIMEOUT &&
status.dwCheckPoint < maxShutdownCheckPoint)
1694 SetServiceStatus(hStatus, (LPSERVICE_STATUS) &
status);
1699 case (WAIT_OBJECT_0 + 1):
1707 CloseHandle(shutdownEvent);
1708 CloseHandle(postmasterProcess);
1710 pgwin32_SetServiceStatus(SERVICE_STOPPED);
1714 pgwin32_doRunAsService(
void)
1719 if (StartServiceCtrlDispatcher(st) == 0)
1721 write_stderr(
_(
"%s: could not start service \"%s\": error code %lu\n"),
1723 (
unsigned long) GetLastError());
1735 typedef BOOL (WINAPI * __CreateRestrictedToken) (HANDLE, DWORD, DWORD, PSID_AND_ATTRIBUTES, DWORD, PLUID_AND_ATTRIBUTES, DWORD, PSID_AND_ATTRIBUTES, PHANDLE);
1736 typedef BOOL (WINAPI * __IsProcessInJob) (HANDLE, HANDLE, PBOOL);
1737 typedef HANDLE (WINAPI * __CreateJobObject) (LPSECURITY_ATTRIBUTES, LPCTSTR);
1738 typedef BOOL (WINAPI * __SetInformationJobObject) (HANDLE, JOBOBJECTINFOCLASS, LPVOID, DWORD);
1739 typedef BOOL (WINAPI * __AssignProcessToJobObject) (HANDLE, HANDLE);
1740 typedef BOOL (WINAPI * __QueryInformationJobObject) (HANDLE, JOBOBJECTINFOCLASS, LPVOID, DWORD, LPDWORD);
1753 InheritStdHandles(STARTUPINFO *si)
1755 si->dwFlags |= STARTF_USESTDHANDLES;
1756 si->hStdInput = GetStdHandle(STD_INPUT_HANDLE);
1757 if (si->hStdInput == NULL)
1758 si->hStdInput = INVALID_HANDLE_VALUE;
1759 si->hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
1760 if (si->hStdOutput == NULL)
1761 si->hStdOutput = INVALID_HANDLE_VALUE;
1762 si->hStdError = GetStdHandle(STD_ERROR_HANDLE);
1763 if (si->hStdError == NULL)
1764 si->hStdError = INVALID_HANDLE_VALUE;
1780 CreateRestrictedProcess(
char *cmd, PROCESS_INFORMATION *processInfo,
bool as_service)
1786 HANDLE restrictedToken;
1787 SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
1788 SID_AND_ATTRIBUTES dropSids[2];
1789 PTOKEN_PRIVILEGES delPrivs;
1792 __CreateRestrictedToken _CreateRestrictedToken = NULL;
1793 __IsProcessInJob _IsProcessInJob = NULL;
1794 __CreateJobObject _CreateJobObject = NULL;
1795 __SetInformationJobObject _SetInformationJobObject = NULL;
1796 __AssignProcessToJobObject _AssignProcessToJobObject = NULL;
1797 __QueryInformationJobObject _QueryInformationJobObject = NULL;
1798 HANDLE Kernel32Handle;
1799 HANDLE Advapi32Handle;
1801 ZeroMemory(&si,
sizeof(si));
1810 InheritStdHandles(&si);
1812 Advapi32Handle = LoadLibrary(
"ADVAPI32.DLL");
1813 if (Advapi32Handle != NULL)
1815 _CreateRestrictedToken = (__CreateRestrictedToken) (
pg_funcptr_t) GetProcAddress(Advapi32Handle,
"CreateRestrictedToken");
1818 if (_CreateRestrictedToken == NULL)
1825 if (Advapi32Handle != NULL)
1826 FreeLibrary(Advapi32Handle);
1827 return CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, processInfo);
1831 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &origToken))
1837 write_stderr(
_(
"%s: could not open process token: error code %lu\n"),
1838 progname, (
unsigned long) GetLastError());
1843 ZeroMemory(&dropSids,
sizeof(dropSids));
1844 if (!AllocateAndInitializeSid(&NtAuthority, 2,
1845 SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0,
1846 0, &dropSids[0].Sid) ||
1847 !AllocateAndInitializeSid(&NtAuthority, 2,
1848 SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0,
1849 0, &dropSids[1].Sid))
1851 write_stderr(
_(
"%s: could not allocate SIDs: error code %lu\n"),
1852 progname, (
unsigned long) GetLastError());
1857 delPrivs = GetPrivilegesToDelete(origToken);
1858 if (delPrivs == NULL)
1862 b = _CreateRestrictedToken(origToken,
1864 sizeof(dropSids) /
sizeof(dropSids[0]),
1866 delPrivs->PrivilegeCount, delPrivs->Privileges,
1871 FreeSid(dropSids[1].Sid);
1872 FreeSid(dropSids[0].Sid);
1873 CloseHandle(origToken);
1874 FreeLibrary(Advapi32Handle);
1878 write_stderr(
_(
"%s: could not create restricted token: error code %lu\n"),
1879 progname, (
unsigned long) GetLastError());
1884 r = CreateProcessAsUser(restrictedToken, NULL, cmd, NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL, &si, processInfo);
1886 Kernel32Handle = LoadLibrary(
"KERNEL32.DLL");
1887 if (Kernel32Handle != NULL)
1889 _IsProcessInJob = (__IsProcessInJob) (
pg_funcptr_t) GetProcAddress(Kernel32Handle,
"IsProcessInJob");
1890 _CreateJobObject = (__CreateJobObject) (
pg_funcptr_t) GetProcAddress(Kernel32Handle,
"CreateJobObjectA");
1891 _SetInformationJobObject = (__SetInformationJobObject) (
pg_funcptr_t) GetProcAddress(Kernel32Handle,
"SetInformationJobObject");
1892 _AssignProcessToJobObject = (__AssignProcessToJobObject) (
pg_funcptr_t) GetProcAddress(Kernel32Handle,
"AssignProcessToJobObject");
1893 _QueryInformationJobObject = (__QueryInformationJobObject) (
pg_funcptr_t) GetProcAddress(Kernel32Handle,
"QueryInformationJobObject");
1897 if (_IsProcessInJob == NULL || _CreateJobObject == NULL || _SetInformationJobObject == NULL || _AssignProcessToJobObject == NULL || _QueryInformationJobObject == NULL)
1903 if (IsWindowsXPOrGreater())
1909 write_stderr(
_(
"%s: WARNING: could not locate all job object functions in system API\n"),
progname);
1915 if (_IsProcessInJob(processInfo->hProcess, NULL, &inJob))
1927 sprintf(jobname,
"PostgreSQL_%lu",
1928 (
unsigned long) processInfo->dwProcessId);
1930 job = _CreateJobObject(NULL, jobname);
1933 JOBOBJECT_BASIC_LIMIT_INFORMATION basicLimit;
1934 JOBOBJECT_BASIC_UI_RESTRICTIONS uiRestrictions;
1935 JOBOBJECT_SECURITY_LIMIT_INFORMATION securityLimit;
1937 ZeroMemory(&basicLimit,
sizeof(basicLimit));
1938 ZeroMemory(&uiRestrictions,
sizeof(uiRestrictions));
1939 ZeroMemory(&securityLimit,
sizeof(securityLimit));
1941 basicLimit.LimitFlags = JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION | JOB_OBJECT_LIMIT_PRIORITY_CLASS;
1942 basicLimit.PriorityClass = NORMAL_PRIORITY_CLASS;
1943 _SetInformationJobObject(job, JobObjectBasicLimitInformation, &basicLimit,
sizeof(basicLimit));
1945 uiRestrictions.UIRestrictionsClass = JOB_OBJECT_UILIMIT_DESKTOP | JOB_OBJECT_UILIMIT_DISPLAYSETTINGS |
1946 JOB_OBJECT_UILIMIT_EXITWINDOWS | JOB_OBJECT_UILIMIT_READCLIPBOARD |
1947 JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS | JOB_OBJECT_UILIMIT_WRITECLIPBOARD;
1951 if (!IsWindows7OrGreater())
1959 uiRestrictions.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_HANDLES;
1962 _SetInformationJobObject(job, JobObjectBasicUIRestrictions, &uiRestrictions,
sizeof(uiRestrictions));
1964 securityLimit.SecurityLimitFlags = JOB_OBJECT_SECURITY_NO_ADMIN | JOB_OBJECT_SECURITY_ONLY_TOKEN;
1965 securityLimit.JobToken = restrictedToken;
1966 _SetInformationJobObject(job, JobObjectSecurityLimitInformation, &securityLimit,
sizeof(securityLimit));
1968 _AssignProcessToJobObject(job, processInfo->hProcess);
1975 CloseHandle(restrictedToken);
1977 ResumeThread(processInfo->hThread);
1979 FreeLibrary(Kernel32Handle);
1993 static PTOKEN_PRIVILEGES
1994 GetPrivilegesToDelete(HANDLE hToken)
1999 PTOKEN_PRIVILEGES tokenPrivs;
2001 LUID luidChangeNotify;
2003 if (!LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, &luidLockPages) ||
2004 !LookupPrivilegeValue(NULL, SE_CHANGE_NOTIFY_NAME, &luidChangeNotify))
2006 write_stderr(
_(
"%s: could not get LUIDs for privileges: error code %lu\n"),
2007 progname, (
unsigned long) GetLastError());
2011 if (!GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &length) &&
2012 GetLastError() != ERROR_INSUFFICIENT_BUFFER)
2014 write_stderr(
_(
"%s: could not get token information: error code %lu\n"),
2015 progname, (
unsigned long) GetLastError());
2021 if (tokenPrivs == NULL)
2027 if (!GetTokenInformation(hToken, TokenPrivileges, tokenPrivs, length, &length))
2029 write_stderr(
_(
"%s: could not get token information: error code %lu\n"),
2030 progname, (
unsigned long) GetLastError());
2035 for (
i = 0;
i < tokenPrivs->PrivilegeCount;
i++)
2037 if (memcmp(&tokenPrivs->Privileges[
i].Luid, &luidLockPages,
sizeof(LUID)) == 0 ||
2038 memcmp(&tokenPrivs->Privileges[
i].Luid, &luidChangeNotify,
sizeof(LUID)) == 0)
2040 for (
j =
i;
j < tokenPrivs->PrivilegeCount - 1;
j++)
2041 tokenPrivs->Privileges[
j] = tokenPrivs->Privileges[
j + 1];
2042 tokenPrivs->PrivilegeCount--;
2061 printf(
_(
"%s is a utility to initialize, start, stop, or control a PostgreSQL server.\n\n"),
progname);
2064 printf(
_(
" %s start [-D DATADIR] [-l FILENAME] [-W] [-t SECS] [-s]\n"
2065 " [-o OPTIONS] [-p PATH] [-c]\n"),
progname);
2066 printf(
_(
" %s stop [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]\n"),
progname);
2067 printf(
_(
" %s restart [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]\n"
2068 " [-o OPTIONS] [-c]\n"),
progname);
2071 printf(
_(
" %s promote [-D DATADIR] [-W] [-t SECS] [-s]\n"),
progname);
2075 printf(
_(
" %s register [-D DATADIR] [-N SERVICENAME] [-U USERNAME] [-P PASSWORD]\n"
2076 " [-S START-TYPE] [-e SOURCE] [-W] [-t SECS] [-s] [-o OPTIONS]\n"),
progname);
2080 printf(
_(
"\nCommon options:\n"));
2081 printf(
_(
" -D, --pgdata=DATADIR location of the database storage area\n"));
2083 printf(
_(
" -e SOURCE event source for logging when running as a service\n"));
2085 printf(
_(
" -s, --silent only print errors, no informational messages\n"));
2086 printf(
_(
" -t, --timeout=SECS seconds to wait when using -w option\n"));
2087 printf(
_(
" -V, --version output version information, then exit\n"));
2088 printf(
_(
" -w, --wait wait until operation completes (default)\n"));
2089 printf(
_(
" -W, --no-wait do not wait until operation completes\n"));
2090 printf(
_(
" -?, --help show this help, then exit\n"));
2091 printf(
_(
"If the -D option is omitted, the environment variable PGDATA is used.\n"));
2093 printf(
_(
"\nOptions for start or restart:\n"));
2094 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
2095 printf(
_(
" -c, --core-files allow postgres to produce core files\n"));
2097 printf(
_(
" -c, --core-files not applicable on this platform\n"));
2099 printf(
_(
" -l, --log=FILENAME write (or append) server log to FILENAME\n"));
2100 printf(
_(
" -o, --options=OPTIONS command line options to pass to postgres\n"
2101 " (PostgreSQL server executable) or initdb\n"));
2102 printf(
_(
" -p PATH-TO-POSTGRES normally not necessary\n"));
2103 printf(
_(
"\nOptions for stop or restart:\n"));
2104 printf(
_(
" -m, --mode=MODE MODE can be \"smart\", \"fast\", or \"immediate\"\n"));
2106 printf(
_(
"\nShutdown modes are:\n"));
2107 printf(
_(
" smart quit after all clients have disconnected\n"));
2108 printf(
_(
" fast quit directly, with proper shutdown (default)\n"));
2109 printf(
_(
" immediate quit without complete shutdown; will lead to recovery on restart\n"));
2111 printf(
_(
"\nAllowed signal names for kill:\n"));
2112 printf(
" ABRT HUP INT KILL QUIT TERM USR1 USR2\n");
2115 printf(
_(
"\nOptions for register and unregister:\n"));
2116 printf(
_(
" -N SERVICENAME service name with which to register PostgreSQL server\n"));
2117 printf(
_(
" -P PASSWORD password of account to register PostgreSQL server\n"));
2118 printf(
_(
" -U USERNAME user name of account to register PostgreSQL server\n"));
2119 printf(
_(
" -S START-TYPE service start type to register PostgreSQL server\n"));
2121 printf(
_(
"\nStart types are:\n"));
2122 printf(
_(
" auto start service automatically during system startup (default)\n"));
2123 printf(
_(
" demand start service on demand\n"));
2126 printf(
_(
"\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
2127 printf(
_(
"%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
2135 if (strcmp(modeopt,
"s") == 0 || strcmp(modeopt,
"smart") == 0)
2140 else if (strcmp(modeopt,
"f") == 0 || strcmp(modeopt,
"fast") == 0)
2145 else if (strcmp(modeopt,
"i") == 0 || strcmp(modeopt,
"immediate") == 0)
2163 if (strcmp(signame,
"HUP") == 0)
2165 else if (strcmp(signame,
"INT") == 0)
2167 else if (strcmp(signame,
"QUIT") == 0)
2169 else if (strcmp(signame,
"ABRT") == 0)
2171 else if (strcmp(signame,
"KILL") == 0)
2173 else if (strcmp(signame,
"TERM") == 0)
2175 else if (strcmp(signame,
"USR1") == 0)
2177 else if (strcmp(signame,
"USR2") == 0)
2190 set_starttype(
char *starttypeopt)
2192 if (strcmp(starttypeopt,
"a") == 0 || strcmp(starttypeopt,
"auto") == 0)
2193 pgctl_start_type = SERVICE_AUTO_START;
2194 else if (strcmp(starttypeopt,
"d") == 0 || strcmp(starttypeopt,
"demand") == 0)
2195 pgctl_start_type = SERVICE_DEMAND_START;
2245 cmd =
psprintf(
"\"%s\" -C data_directory %s%s",
2250 fd = popen(cmd,
"r");
2253 write_stderr(
_(
"%s: could not determine the data directory using command \"%s\"\n"),
progname, cmd);
2281 ret = control_file_data->
state;
2282 pfree(control_file_data);
2290 static struct option long_options[] = {
2327 if (strcmp(argv[1],
"--help") == 0 || strcmp(argv[1],
"-?") == 0)
2332 else if (strcmp(argv[1],
"--version") == 0 || strcmp(argv[1],
"-V") == 0)
2334 puts(
"pg_ctl (PostgreSQL) " PG_VERSION);
2346 "Please log in (using, e.g., \"su\") as the "
2347 "(unprivileged) user that will\n"
2348 "own the server process.\n"),
2354 env_wait = getenv(
"PGCTLTIMEOUT");
2355 if (env_wait != NULL)
2369 while ((
c =
getopt_long(argc, argv,
"cD:e:l:m:N:o:p:P:sS:t:U:wW",
2370 long_options, &option_index)) != -1)
2380 setenv(
"PGDATA", pgdata_D, 1);
2412 free(old_post_opts);
2428 write_stderr(
_(
"%s: -S option not supported on this platform\n"),
2438 if (strchr(
optarg,
'\\'))
2470 if (strcmp(argv[
optind],
"init") == 0
2471 || strcmp(argv[
optind],
"initdb") == 0)
2473 else if (strcmp(argv[
optind],
"start") == 0)
2475 else if (strcmp(argv[
optind],
"stop") == 0)
2477 else if (strcmp(argv[
optind],
"restart") == 0)
2479 else if (strcmp(argv[
optind],
"reload") == 0)
2481 else if (strcmp(argv[
optind],
"status") == 0)
2483 else if (strcmp(argv[
optind],
"promote") == 0)
2485 else if (strcmp(argv[
optind],
"logrotate") == 0)
2487 else if (strcmp(argv[
optind],
"kill") == 0)
2497 killproc = atol(argv[++
optind]);
2500 else if (strcmp(argv[
optind],
"register") == 0)
2502 else if (strcmp(argv[
optind],
"unregister") == 0)
2504 else if (strcmp(argv[
optind],
"runservice") == 0)
2540 write_stderr(
_(
"%s: no database directory specified and environment variable PGDATA unset\n"),
2601 pgwin32_doRegister();
2604 pgwin32_doUnregister();
2607 pgwin32_doRunAsService();
#define PG_TEXTDOMAIN(domain)
#define pg_attribute_printf(f, a)
void(* pg_funcptr_t)(void)
int find_my_exec(const char *argv0, char *retpath)
void set_pglocale_pgservice(const char *argv0, const char *app)
int find_other_exec(const char *argv0, const char *target, const char *versionstr, char *retpath)
ControlFileData * get_controlfile(const char *DataDir, bool *crc_ok_p)
void * pg_malloc_extended(size_t size, int flags)
char * pg_strdup(const char *in)
void * pg_malloc(size_t size)
#define MCXT_ALLOC_NO_OOM
bool GetDataDirectoryCreatePerm(const char *dataDir)
#define PG_MODE_MASK_OWNER
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
#define required_argument
char my_exec_path[MAXPGPATH]
static void const char fflush(stdout)
vfprintf(stderr, fmt, args)
static void const char * fmt
void pg_logging_init(const char *argv0)
void pfree(void *pointer)
#define DEFAULT_EVENT_SOURCE
static void trap_sigint_during_startup(int sig)
static void read_post_opts(void)
static void static void do_advice(void)
static void do_reload(void)
static void do_help(void)
static void free_readfile(char **optlines)
static char * register_username
static char * find_other_exec_or_die(const char *argv0, const char *target, const char *versionstr)
static char * event_source
static void adjust_data_dir(void)
static char * register_servicename
static char version_file[MAXPGPATH]
static pgpid_t get_pgpid(bool is_status_request)
static volatile pgpid_t postmasterPID
static bool allow_core_files
static pgpid_t start_postmaster(void)
int main(int argc, char **argv)
static char ** readfile(const char *path, int *numlines)
static bool wait_for_postmaster_promote(void)
static char postopts_file[MAXPGPATH]
@ POSTMASTER_STILL_STARTING
static void set_mode(char *modeopt)
static char promote_file[MAXPGPATH]
static void do_start(void)
static DBState get_control_dbstate(void)
static char backup_file[MAXPGPATH]
static void do_logrotate(void)
static void do_stop(void)
static char pid_file[MAXPGPATH]
static char * register_password
static CtlCommand ctl_command
static void do_init(void)
static void print_msg(const char *msg)
static WaitPMResult wait_for_postmaster_start(pgpid_t pm_pid, bool do_checkpoint)
static void do_kill(pgpid_t pid)
static bool postmaster_is_alive(pid_t pid)
static void do_restart(void)
static bool wait_seconds_arg
static bool wait_for_postmaster_stop(void)
static void write_stderr(const char *fmt,...) pg_attribute_printf(1
static void do_promote(void)
static void set_sig(char *signame)
static const char * progname
static void do_status(void)
static char logrotate_file[MAXPGPATH]
static ShutdownMode shutdown_mode
PGDLLIMPORT char * optarg
static void static void status(const char *fmt,...) pg_attribute_printf(1
#define PM_STATUS_STANDBY
#define LOCK_FILE_LINE_START_TIME
#define LOCK_FILE_LINE_PM_STATUS
#define LOCK_FILE_LINE_PID
char * make_absolute_path(const char *path)
int pg_strcasecmp(const char *s1, const char *s2)
void make_native_path(char *path)
void canonicalize_path(char *path)
const char * get_progname(const char *argv0)
#define PG_BACKEND_VERSIONSTR
size_t strlcpy(char *dst, const char *src, size_t siz)
PQExpBuffer createPQExpBuffer(void)
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
static int fd(const char *x, int i)
char * psprintf(const char *fmt,...)
void pg_usleep(long microsec)
pqsigfunc pqsignal(int signum, pqsigfunc handler)
int pg_strip_crlf(char *str)
BOOL AddUserToTokenDacl(HANDLE hToken)
int pgwin32_is_service(void)