Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
f8dd00c3
Commit
f8dd00c3
authored
Jun 24, 2004
by
Tom Lane
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Extend pg_ctl to handle service management under WIN32. Lacks docs.
Claudio Natoli and Magnus Hagander
parent
df9d87f6
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
422 additions
and
75 deletions
+422
-75
src/bin/pg_ctl/pg_ctl.c
src/bin/pg_ctl/pg_ctl.c
+422
-75
No files found.
src/bin/pg_ctl/pg_ctl.c
View file @
f8dd00c3
...
@@ -4,7 +4,7 @@
...
@@ -4,7 +4,7 @@
*
*
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
*
*
* $PostgreSQL: pgsql/src/bin/pg_ctl/pg_ctl.c,v 1.1
6 2004/06/11 16:36:31 momjian
Exp $
* $PostgreSQL: pgsql/src/bin/pg_ctl/pg_ctl.c,v 1.1
7 2004/06/24 18:23:26 tgl
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -52,7 +52,10 @@ typedef enum
...
@@ -52,7 +52,10 @@ typedef enum
RESTART_COMMAND
,
RESTART_COMMAND
,
RELOAD_COMMAND
,
RELOAD_COMMAND
,
STATUS_COMMAND
,
STATUS_COMMAND
,
KILL_COMMAND
KILL_COMMAND
,
REGISTER_COMMAND
,
UNREGISTER_COMMAND
,
RUN_AS_SERVICE_COMMAND
}
CtlCommand
;
}
CtlCommand
;
...
@@ -63,14 +66,20 @@ static bool silence_echo = false;
...
@@ -63,14 +66,20 @@ static bool silence_echo = false;
static
ShutdownMode
shutdown_mode
=
SMART_MODE
;
static
ShutdownMode
shutdown_mode
=
SMART_MODE
;
static
int
sig
=
SIGTERM
;
/* default */
static
int
sig
=
SIGTERM
;
/* default */
static
CtlCommand
ctl_command
=
NO_COMMAND
;
static
CtlCommand
ctl_command
=
NO_COMMAND
;
static
char
*
pg_data_opts
=
NULL
;
static
char
*
pg_data
=
NULL
;
static
char
*
pg_data
=
NULL
;
static
char
*
post_opts
=
NULL
;
static
char
*
post_opts
=
NULL
;
static
const
char
*
progname
;
static
const
char
*
progname
;
static
char
*
log_file
=
NULL
;
static
char
*
log_file
=
NULL
;
static
char
*
postgres_path
=
NULL
;
static
char
*
postgres_path
=
NULL
;
static
char
*
register_servicename
=
"PostgreSQL"
;
/* FIXME: + version ID? */
static
char
*
register_username
=
NULL
;
static
char
*
register_password
=
NULL
;
static
char
*
argv0
=
NULL
;
static
char
*
argv0
=
NULL
;
static
void
write_stderr
(
const
char
*
fmt
,...)
/* This extension allows gcc to check the format string for consistency with
the supplied arguments. */
__attribute__
((
format
(
printf
,
1
,
2
)));
static
void
*
xmalloc
(
size_t
size
);
static
void
*
xmalloc
(
size_t
size
);
static
char
*
xstrdup
(
const
char
*
s
);
static
char
*
xstrdup
(
const
char
*
s
);
static
void
do_advice
(
void
);
static
void
do_advice
(
void
);
...
@@ -83,6 +92,16 @@ static void do_restart(void);
...
@@ -83,6 +92,16 @@ static void do_restart(void);
static
void
do_reload
(
void
);
static
void
do_reload
(
void
);
static
void
do_status
(
void
);
static
void
do_status
(
void
);
static
void
do_kill
(
pgpid_t
pid
);
static
void
do_kill
(
pgpid_t
pid
);
#ifdef WIN32
static
bool
pgwin32_IsInstalled
(
SC_HANDLE
);
static
char
*
pgwin32_CommandLine
(
bool
);
static
void
pgwin32_doRegister
();
static
void
pgwin32_doUnregister
();
static
void
pgwin32_SetServiceStatus
(
DWORD
);
static
void
WINAPI
pgwin32_ServiceHandler
(
DWORD
);
static
void
WINAPI
pgwin32_ServiceMain
(
DWORD
,
LPTSTR
*
);
static
void
pgwin32_doRunAsService
();
#endif
static
pgpid_t
get_pgpid
(
void
);
static
pgpid_t
get_pgpid
(
void
);
static
char
**
readfile
(
char
*
path
);
static
char
**
readfile
(
char
*
path
);
static
int
start_postmaster
(
void
);
static
int
start_postmaster
(
void
);
...
@@ -93,6 +112,63 @@ static char postopts_file[MAXPGPATH];
...
@@ -93,6 +112,63 @@ static char postopts_file[MAXPGPATH];
static
char
pid_file
[
MAXPGPATH
];
static
char
pid_file
[
MAXPGPATH
];
static
char
conf_file
[
MAXPGPATH
];
static
char
conf_file
[
MAXPGPATH
];
#ifdef WIN32
static
void
write_eventlog
(
int
level
,
const
char
*
line
)
{
static
HANDLE
evtHandle
=
INVALID_HANDLE_VALUE
;
if
(
evtHandle
==
INVALID_HANDLE_VALUE
)
{
evtHandle
=
RegisterEventSource
(
NULL
,
"PostgreSQL"
);
if
(
evtHandle
==
NULL
)
{
evtHandle
=
INVALID_HANDLE_VALUE
;
return
;
}
}
ReportEvent
(
evtHandle
,
level
,
0
,
0
,
/* All events are Id 0 */
NULL
,
1
,
0
,
&
line
,
NULL
);
}
#endif
/*
* Write errors to stderr (or by equal means when stderr is
* not available).
*/
static
void
write_stderr
(
const
char
*
fmt
,...)
{
va_list
ap
;
va_start
(
ap
,
fmt
);
#ifndef WIN32
/* On Unix, we just fprintf to stderr */
vfprintf
(
stderr
,
fmt
,
ap
);
#else
/* On Win32, we print to stderr if running on a console, or write to
* eventlog if running as a service */
if
(
!
isatty
(
fileno
(
stderr
)))
/* Running as a service */
{
char
errbuf
[
2048
];
/* Arbitrary size? */
vsnprintf
(
errbuf
,
sizeof
(
errbuf
),
fmt
,
ap
);
write_eventlog
(
EVENTLOG_ERROR_TYPE
,
errbuf
);
}
else
/* Not running as service, write to stderr */
vfprintf
(
stderr
,
fmt
,
ap
);
#endif
va_end
(
ap
);
}
/*
/*
* routines to check memory allocations and fail noisily.
* routines to check memory allocations and fail noisily.
*/
*/
...
@@ -105,7 +181,7 @@ xmalloc(size_t size)
...
@@ -105,7 +181,7 @@ xmalloc(size_t size)
result
=
malloc
(
size
);
result
=
malloc
(
size
);
if
(
!
result
)
if
(
!
result
)
{
{
fprintf
(
stderr
,
_
(
"%s: out of memory
\n
"
),
progname
);
write_stderr
(
_
(
"%s: out of memory
\n
"
),
progname
);
exit
(
1
);
exit
(
1
);
}
}
return
result
;
return
result
;
...
@@ -121,7 +197,7 @@ xstrdup(const char *s)
...
@@ -121,7 +197,7 @@ xstrdup(const char *s)
result
=
strdup
(
s
);
result
=
strdup
(
s
);
if
(
!
result
)
if
(
!
result
)
{
{
fprintf
(
stderr
,
_
(
"%s: out of memory
\n
"
),
progname
);
write_stderr
(
_
(
"%s: out of memory
\n
"
),
progname
);
exit
(
1
);
exit
(
1
);
}
}
return
result
;
return
result
;
...
@@ -352,8 +428,7 @@ do_start(void)
...
@@ -352,8 +428,7 @@ do_start(void)
{
{
old_pid
=
get_pgpid
();
old_pid
=
get_pgpid
();
if
(
old_pid
!=
0
)
if
(
old_pid
!=
0
)
fprintf
(
stderr
,
write_stderr
(
_
(
"%s: Another postmaster may be running. "
_
(
"%s: Another postmaster may be running. "
"Trying to start postmaster anyway.
\n
"
),
"Trying to start postmaster anyway.
\n
"
),
progname
);
progname
);
}
}
...
@@ -371,13 +446,13 @@ do_start(void)
...
@@ -371,13 +446,13 @@ do_start(void)
post_opts
=
""
;
post_opts
=
""
;
else
else
{
{
fprintf
(
stderr
,
_
(
"%s: cannot read %s
\n
"
),
progname
,
postopts_file
);
write_stderr
(
_
(
"%s: cannot read %s
\n
"
),
progname
,
postopts_file
);
exit
(
1
);
exit
(
1
);
}
}
}
}
else
if
(
optlines
[
0
]
==
NULL
||
optlines
[
1
]
!=
NULL
)
else
if
(
optlines
[
0
]
==
NULL
||
optlines
[
1
]
!=
NULL
)
{
{
fprintf
(
stderr
,
_
(
"%s: option file %s must have exactly 1 line
\n
"
),
write_stderr
(
_
(
"%s: option file %s must have exactly 1 line
\n
"
),
progname
,
ctl_command
==
RESTART_COMMAND
?
progname
,
ctl_command
==
RESTART_COMMAND
?
postopts_file
:
def_postopts_file
);
postopts_file
:
def_postopts_file
);
exit
(
1
);
exit
(
1
);
...
@@ -419,15 +494,13 @@ do_start(void)
...
@@ -419,15 +494,13 @@ do_start(void)
postmaster_path
))
<
0
)
postmaster_path
))
<
0
)
{
{
if
(
ret
==
-
1
)
if
(
ret
==
-
1
)
fprintf
(
stderr
,
write_stderr
(
_
(
"The program
\"
postmaster
\"
is needed by %s "
_
(
"The program
\"
postmaster
\"
is needed by %s "
"but was not found in the same directory as "
"but was not found in the same directory as "
"
\"
%s
\"
.
\n
"
"
\"
%s
\"
.
\n
"
"Check your installation.
\n
"
),
"Check your installation.
\n
"
),
progname
,
progname
);
progname
,
progname
);
else
else
fprintf
(
stderr
,
write_stderr
(
_
(
"The program
\"
postmaster
\"
was found by %s "
_
(
"The program
\"
postmaster
\"
was found by %s "
"but was not the same version as
\"
%s
\"
.
\n
"
"but was not the same version as
\"
%s
\"
.
\n
"
"Check your installation.
\n
"
),
"Check your installation.
\n
"
),
progname
,
progname
);
progname
,
progname
);
...
@@ -438,7 +511,7 @@ do_start(void)
...
@@ -438,7 +511,7 @@ do_start(void)
if
(
start_postmaster
()
!=
0
)
if
(
start_postmaster
()
!=
0
)
{
{
fprintf
(
stderr
,
_
(
"Unable to run the postmaster binary
\n
"
));
write_stderr
(
_
(
"Unable to run the postmaster binary
\n
"
));
exit
(
1
);
exit
(
1
);
}
}
...
@@ -448,8 +521,7 @@ do_start(void)
...
@@ -448,8 +521,7 @@ do_start(void)
pid
=
get_pgpid
();
pid
=
get_pgpid
();
if
(
pid
==
old_pid
)
if
(
pid
==
old_pid
)
{
{
fprintf
(
stderr
,
write_stderr
(
_
(
"%s: cannot start postmaster
\n
"
_
(
"%s: cannot start postmaster
\n
"
"Examine the log output
\n
"
),
"Examine the log output
\n
"
),
progname
);
progname
);
exit
(
1
);
exit
(
1
);
...
@@ -485,15 +557,14 @@ do_stop(void)
...
@@ -485,15 +557,14 @@ do_stop(void)
if
(
pid
==
0
)
/* no pid file */
if
(
pid
==
0
)
/* no pid file */
{
{
fprintf
(
stderr
,
_
(
"%s: could not find %s
\n
"
),
progname
,
pid_file
);
write_stderr
(
_
(
"%s: could not find %s
\n
"
),
progname
,
pid_file
);
fprintf
(
stderr
,
_
(
"Is postmaster running?
\n
"
));
write_stderr
(
_
(
"Is postmaster running?
\n
"
));
exit
(
1
);
exit
(
1
);
}
}
else
if
(
pid
<
0
)
/* standalone backend, not postmaster */
else
if
(
pid
<
0
)
/* standalone backend, not postmaster */
{
{
pid
=
-
pid
;
pid
=
-
pid
;
fprintf
(
stderr
,
write_stderr
(
_
(
"%s: cannot stop postmaster; "
_
(
"%s: cannot stop postmaster; "
"postgres is running (PID: %ld)
\n
"
),
"postgres is running (PID: %ld)
\n
"
),
progname
,
pid
);
progname
,
pid
);
exit
(
1
);
exit
(
1
);
...
@@ -501,7 +572,7 @@ do_stop(void)
...
@@ -501,7 +572,7 @@ do_stop(void)
if
(
kill
((
pid_t
)
pid
,
sig
)
!=
0
)
if
(
kill
((
pid_t
)
pid
,
sig
)
!=
0
)
{
{
fprintf
(
stderr
,
_
(
"stop signal failed (PID: %ld): %s
\n
"
),
pid
,
write_stderr
(
_
(
"stop signal failed (PID: %ld): %s
\n
"
),
pid
,
strerror
(
errno
));
strerror
(
errno
));
exit
(
1
);
exit
(
1
);
}
}
...
@@ -540,7 +611,7 @@ do_stop(void)
...
@@ -540,7 +611,7 @@ do_stop(void)
if
(
!
silence_echo
)
if
(
!
silence_echo
)
printf
(
_
(
" failed
\n
"
));
printf
(
_
(
" failed
\n
"
));
fprintf
(
stderr
,
_
(
"%s: postmaster does not shut down
\n
"
),
progname
);
write_stderr
(
_
(
"%s: postmaster does not shut down
\n
"
),
progname
);
exit
(
1
);
exit
(
1
);
}
}
if
(
!
silence_echo
)
if
(
!
silence_echo
)
...
@@ -565,25 +636,24 @@ do_restart(void)
...
@@ -565,25 +636,24 @@ do_restart(void)
if
(
pid
==
0
)
/* no pid file */
if
(
pid
==
0
)
/* no pid file */
{
{
fprintf
(
stderr
,
_
(
"%s: could not find %s
\n
"
),
progname
,
pid_file
);
write_stderr
(
_
(
"%s: could not find %s
\n
"
),
progname
,
pid_file
);
fprintf
(
stderr
,
_
(
"Is postmaster running?
\n
starting postmaster anyway
\n
"
));
write_stderr
(
_
(
"Is postmaster running?
\n
starting postmaster anyway
\n
"
));
do_start
();
do_start
();
return
;
return
;
}
}
else
if
(
pid
<
0
)
/* standalone backend, not postmaster */
else
if
(
pid
<
0
)
/* standalone backend, not postmaster */
{
{
pid
=
-
pid
;
pid
=
-
pid
;
fprintf
(
stderr
,
write_stderr
(
_
(
"%s: cannot restart postmaster; "
_
(
"%s: cannot restart postmaster; "
"postgres is running (PID: %ld)
\n
"
),
"postgres is running (PID: %ld)
\n
"
),
progname
,
pid
);
progname
,
pid
);
fprintf
(
stderr
,
_
(
"Please terminate postgres and try again.
\n
"
));
write_stderr
(
_
(
"Please terminate postgres and try again.
\n
"
));
exit
(
1
);
exit
(
1
);
}
}
if
(
kill
((
pid_t
)
pid
,
sig
)
!=
0
)
if
(
kill
((
pid_t
)
pid
,
sig
)
!=
0
)
{
{
fprintf
(
stderr
,
_
(
"stop signal failed (PID: %ld): %s
\n
"
),
pid
,
write_stderr
(
_
(
"stop signal failed (PID: %ld): %s
\n
"
),
pid
,
strerror
(
errno
));
strerror
(
errno
));
exit
(
1
);
exit
(
1
);
}
}
...
@@ -616,7 +686,7 @@ do_restart(void)
...
@@ -616,7 +686,7 @@ do_restart(void)
if
(
!
silence_echo
)
if
(
!
silence_echo
)
printf
(
_
(
" failed
\n
"
));
printf
(
_
(
" failed
\n
"
));
fprintf
(
stderr
,
_
(
"%s: postmaster does not shut down
\n
"
),
progname
);
write_stderr
(
_
(
"%s: postmaster does not shut down
\n
"
),
progname
);
exit
(
1
);
exit
(
1
);
}
}
...
@@ -636,24 +706,23 @@ do_reload(void)
...
@@ -636,24 +706,23 @@ do_reload(void)
pid
=
get_pgpid
();
pid
=
get_pgpid
();
if
(
pid
==
0
)
/* no pid file */
if
(
pid
==
0
)
/* no pid file */
{
{
fprintf
(
stderr
,
_
(
"%s: could not find %s
\n
"
),
progname
,
pid_file
);
write_stderr
(
_
(
"%s: could not find %s
\n
"
),
progname
,
pid_file
);
fprintf
(
stderr
,
_
(
"Is postmaster running?
\n
"
));
write_stderr
(
_
(
"Is postmaster running?
\n
"
));
exit
(
1
);
exit
(
1
);
}
}
else
if
(
pid
<
0
)
/* standalone backend, not postmaster */
else
if
(
pid
<
0
)
/* standalone backend, not postmaster */
{
{
pid
=
-
pid
;
pid
=
-
pid
;
fprintf
(
stderr
,
write_stderr
(
_
(
"%s: cannot reload postmaster; "
_
(
"%s: cannot reload postmaster; "
"postgres is running (PID: %ld)
\n
"
),
"postgres is running (PID: %ld)
\n
"
),
progname
,
pid
);
progname
,
pid
);
fprintf
(
stderr
,
_
(
"Please terminate postgres and try again.
\n
"
));
write_stderr
(
_
(
"Please terminate postgres and try again.
\n
"
));
exit
(
1
);
exit
(
1
);
}
}
if
(
kill
((
pid_t
)
pid
,
sig
)
!=
0
)
if
(
kill
((
pid_t
)
pid
,
sig
)
!=
0
)
{
{
fprintf
(
stderr
,
_
(
"reload signal failed (PID: %ld): %s
\n
"
),
pid
,
write_stderr
(
_
(
"reload signal failed (PID: %ld): %s
\n
"
),
pid
,
strerror
(
errno
));
strerror
(
errno
));
exit
(
1
);
exit
(
1
);
}
}
...
@@ -674,7 +743,7 @@ do_status(void)
...
@@ -674,7 +743,7 @@ do_status(void)
pid
=
get_pgpid
();
pid
=
get_pgpid
();
if
(
pid
==
0
)
/* no pid file */
if
(
pid
==
0
)
/* no pid file */
{
{
fprintf
(
stderr
,
_
(
"%s: postmaster or postgres not running
\n
"
),
progname
);
write_stderr
(
_
(
"%s: postmaster or postgres not running
\n
"
),
progname
);
exit
(
1
);
exit
(
1
);
}
}
else
if
(
pid
<
0
)
/* standalone backend */
else
if
(
pid
<
0
)
/* standalone backend */
...
@@ -702,18 +771,244 @@ do_kill(pgpid_t pid)
...
@@ -702,18 +771,244 @@ do_kill(pgpid_t pid)
{
{
if
(
kill
((
pid_t
)
pid
,
sig
)
!=
0
)
if
(
kill
((
pid_t
)
pid
,
sig
)
!=
0
)
{
{
fprintf
(
stderr
,
_
(
"signal %d failed (PID: %ld): %s
\n
"
),
sig
,
pid
,
write_stderr
(
_
(
"signal %d failed (PID: %ld): %s
\n
"
),
sig
,
pid
,
strerror
(
errno
));
strerror
(
errno
));
exit
(
1
);
exit
(
1
);
}
}
}
}
#ifdef WIN32
static
bool
pgwin32_IsInstalled
(
SC_HANDLE
hSCM
)
{
SC_HANDLE
hService
=
OpenService
(
hSCM
,
register_servicename
,
SERVICE_QUERY_CONFIG
);
bool
bResult
=
(
hService
!=
NULL
);
if
(
bResult
)
CloseServiceHandle
(
hService
);
return
bResult
;
}
static
char
*
pgwin32_CommandLine
(
bool
registration
)
{
static
char
cmdLine
[
MAXPGPATH
];
int
ret
;
if
(
registration
)
ret
=
find_my_exec
(
argv0
,
cmdLine
);
else
ret
=
find_other_exec
(
argv0
,
"postmaster"
,
PM_VERSIONSTR
,
cmdLine
);
if
(
ret
!=
0
)
{
write_stderr
(
_
(
"Unable to find exe"
));
exit
(
1
);
}
if
(
registration
)
{
if
(
strcasecmp
(
cmdLine
+
strlen
(
cmdLine
)
-
4
,
".exe"
))
{
/* If commandline does not end in .exe, append it */
strcat
(
cmdLine
,
".exe"
);
}
strcat
(
cmdLine
,
" runservice -N
\"
"
);
strcat
(
cmdLine
,
register_servicename
);
strcat
(
cmdLine
,
"
\"
"
);
}
if
(
pg_data
)
{
strcat
(
cmdLine
,
" -D
\"
"
);
strcat
(
cmdLine
,
pg_data
);
strcat
(
cmdLine
,
"
\"
"
);
}
if
(
post_opts
)
{
strcat
(
cmdLine
,
" "
);
if
(
registration
)
strcat
(
cmdLine
,
" -o
\"
"
);
strcat
(
cmdLine
,
post_opts
);
if
(
registration
)
strcat
(
cmdLine
,
"
\"
"
);
}
return
cmdLine
;
}
static
void
pgwin32_doRegister
()
{
SC_HANDLE
hService
;
SC_HANDLE
hSCM
=
OpenSCManager
(
NULL
,
NULL
,
SC_MANAGER_ALL_ACCESS
);
if
(
hSCM
==
NULL
)
{
write_stderr
(
_
(
"Unable to open service manager
\n
"
));
exit
(
1
);
}
if
(
pgwin32_IsInstalled
(
hSCM
))
{
CloseServiceHandle
(
hSCM
);
write_stderr
(
_
(
"Service
\"
%s
\"
already registered
\n
"
),
register_servicename
);
exit
(
1
);
}
if
((
hService
=
CreateService
(
hSCM
,
register_servicename
,
register_servicename
,
SERVICE_ALL_ACCESS
,
SERVICE_WIN32_OWN_PROCESS
,
SERVICE_AUTO_START
,
SERVICE_ERROR_NORMAL
,
pgwin32_CommandLine
(
true
),
NULL
,
NULL
,
"RPCSS
\0
"
,
register_username
,
register_password
))
==
NULL
)
{
CloseServiceHandle
(
hSCM
);
write_stderr
(
_
(
"Unable to register service
\"
%s
\"
[%d]
\n
"
),
register_servicename
,
(
int
)
GetLastError
());
exit
(
1
);
}
CloseServiceHandle
(
hService
);
CloseServiceHandle
(
hSCM
);
}
static
void
pgwin32_doUnregister
()
{
SC_HANDLE
hService
;
SC_HANDLE
hSCM
=
OpenSCManager
(
NULL
,
NULL
,
SC_MANAGER_ALL_ACCESS
);
if
(
hSCM
==
NULL
)
{
write_stderr
(
_
(
"Unable to open service manager
\n
"
));
exit
(
1
);
}
if
(
!
pgwin32_IsInstalled
(
hSCM
))
{
CloseServiceHandle
(
hSCM
);
write_stderr
(
_
(
"Service
\"
%s
\"
not registered
\n
"
),
register_servicename
);
exit
(
1
);
}
if
((
hService
=
OpenService
(
hSCM
,
register_servicename
,
DELETE
))
==
NULL
)
{
CloseServiceHandle
(
hSCM
);
write_stderr
(
_
(
"Unable to open service
\"
%s
\"
[%d]
\n
"
),
register_servicename
,
(
int
)
GetLastError
());
exit
(
1
);
}
if
(
!
DeleteService
(
hService
))
{
CloseServiceHandle
(
hService
);
CloseServiceHandle
(
hSCM
);
write_stderr
(
_
(
"Unable to unregister service
\"
%s
\"
[%d]
\n
"
),
register_servicename
,
(
int
)
GetLastError
());
exit
(
1
);
}
CloseServiceHandle
(
hService
);
CloseServiceHandle
(
hSCM
);
}
static
SERVICE_STATUS
status
;
static
SERVICE_STATUS_HANDLE
hStatus
=
(
SERVICE_STATUS_HANDLE
)
0
;
static
HANDLE
shutdownHandles
[
2
];
static
pid_t
postmasterPID
=
-
1
;
#define shutdownEvent shutdownHandles[0]
#define postmasterProcess shutdownHandles[1]
static
void
pgwin32_SetServiceStatus
(
DWORD
currentState
)
{
status
.
dwCurrentState
=
currentState
;
SetServiceStatus
(
hStatus
,
(
LPSERVICE_STATUS
)
&
status
);
}
static
void
WINAPI
pgwin32_ServiceHandler
(
DWORD
request
)
{
switch
(
request
)
{
case
SERVICE_CONTROL_STOP
:
case
SERVICE_CONTROL_SHUTDOWN
:
pgwin32_SetServiceStatus
(
SERVICE_STOP_PENDING
);
SetEvent
(
shutdownEvent
);
return
;
case
SERVICE_CONTROL_PAUSE
:
/* Win32 config reloading */
kill
(
postmasterPID
,
SIGHUP
);
return
;
/* FIXME: These could be used to replace other signals etc */
case
SERVICE_CONTROL_CONTINUE
:
case
SERVICE_CONTROL_INTERROGATE
:
default:
break
;
}
}
static
void
WINAPI
pgwin32_ServiceMain
(
DWORD
argc
,
LPTSTR
*
argv
)
{
STARTUPINFO
si
;
PROCESS_INFORMATION
pi
;
DWORD
ret
;
/* Initialize variables */
status
.
dwWin32ExitCode
=
S_OK
;
status
.
dwCheckPoint
=
0
;
status
.
dwWaitHint
=
0
;
status
.
dwServiceType
=
SERVICE_WIN32_OWN_PROCESS
;
status
.
dwControlsAccepted
=
SERVICE_ACCEPT_STOP
|
SERVICE_ACCEPT_PAUSE_CONTINUE
;
status
.
dwServiceSpecificExitCode
=
0
;
status
.
dwCurrentState
=
SERVICE_START_PENDING
;
memset
(
&
pi
,
0
,
sizeof
(
pi
));
memset
(
&
si
,
0
,
sizeof
(
si
));
si
.
cb
=
sizeof
(
si
);
/* Register the control request handler */
if
((
hStatus
=
RegisterServiceCtrlHandler
(
register_servicename
,
pgwin32_ServiceHandler
))
==
(
SERVICE_STATUS_HANDLE
)
0
)
return
;
if
((
shutdownEvent
=
CreateEvent
(
NULL
,
true
,
false
,
NULL
))
==
NULL
)
return
;
/* Start the postmaster */
pgwin32_SetServiceStatus
(
SERVICE_START_PENDING
);
if
(
!
CreateProcess
(
NULL
,
pgwin32_CommandLine
(
false
),
NULL
,
NULL
,
TRUE
,
0
,
NULL
,
NULL
,
&
si
,
&
pi
))
{
pgwin32_SetServiceStatus
(
SERVICE_STOPPED
);
return
;
}
postmasterPID
=
pi
.
dwProcessId
;
postmasterProcess
=
pi
.
hProcess
;
CloseHandle
(
pi
.
hThread
);
pgwin32_SetServiceStatus
(
SERVICE_RUNNING
);
/* Wait for quit... */
ret
=
WaitForMultipleObjects
(
2
,
shutdownHandles
,
FALSE
,
INFINITE
);
pgwin32_SetServiceStatus
(
SERVICE_STOP_PENDING
);
switch
(
ret
)
{
case
WAIT_OBJECT_0
:
/* shutdown event */
kill
(
postmasterPID
,
SIGINT
);
WaitForSingleObject
(
postmasterProcess
,
INFINITE
);
break
;
case
(
WAIT_OBJECT_0
+
1
):
/* postmaster went down */
break
;
default:
/* assert(false); */
}
CloseHandle
(
shutdownEvent
);
CloseHandle
(
postmasterProcess
);
pgwin32_SetServiceStatus
(
SERVICE_STOPPED
);
}
static
void
pgwin32_doRunAsService
()
{
SERVICE_TABLE_ENTRY
st
[]
=
{{
register_servicename
,
pgwin32_ServiceMain
},
{
NULL
,
NULL
}};
StartServiceCtrlDispatcher
(
st
);
}
#endif
static
void
static
void
do_advice
(
void
)
do_advice
(
void
)
{
{
fprintf
(
stderr
,
_
(
"
\n
Try
\"
%s --help
\"
for more information.
\n
"
),
progname
);
write_stderr
(
_
(
"
\n
Try
\"
%s --help
\"
for more information.
\n
"
),
progname
);
}
}
...
@@ -730,9 +1025,18 @@ do_help(void)
...
@@ -730,9 +1025,18 @@ do_help(void)
printf
(
_
(
" %s reload [-D DATADIR] [-s]
\n
"
),
progname
);
printf
(
_
(
" %s reload [-D DATADIR] [-s]
\n
"
),
progname
);
printf
(
_
(
" %s status [-D DATADIR]
\n
"
),
progname
);
printf
(
_
(
" %s status [-D DATADIR]
\n
"
),
progname
);
printf
(
_
(
" %s kill SIGNALNAME PROCESSID
\n
"
),
progname
);
printf
(
_
(
" %s kill SIGNALNAME PROCESSID
\n
"
),
progname
);
#ifdef WIN32
printf
(
_
(
" %s register [-N servicename] [-U username] [-P password] [-D DATADIR] [-o
\"
OPTIONS
\"
]
\n
"
),
progname
);
printf
(
_
(
" %s unregister [-N servicename]
\n
"
),
progname
);
#endif
printf
(
_
(
"Common options:
\n
"
));
printf
(
_
(
"Common options:
\n
"
));
printf
(
_
(
" -D, --pgdata DATADIR location of the database storage area
\n
"
));
printf
(
_
(
" -D, --pgdata DATADIR location of the database storage area
\n
"
));
printf
(
_
(
" -s, --silent only print errors, no informational messages
\n
"
));
printf
(
_
(
" -s, --silent only print errors, no informational messages
\n
"
));
#ifdef WIN32
printf
(
_
(
" -N service name with which to register PostgreSQL server
\n
"
));
printf
(
_
(
" -P user name of account to register PostgreSQL server
\n
"
));
printf
(
_
(
" -U password of account to register PostgreSQL server
\n
"
));
#endif
printf
(
_
(
" -w wait until operation completes
\n
"
));
printf
(
_
(
" -w wait until operation completes
\n
"
));
printf
(
_
(
" -W do not wait until operation completes
\n
"
));
printf
(
_
(
" -W do not wait until operation completes
\n
"
));
printf
(
_
(
" --help show this help, then exit
\n
"
));
printf
(
_
(
" --help show this help, then exit
\n
"
));
...
@@ -778,7 +1082,7 @@ set_mode(char *modeopt)
...
@@ -778,7 +1082,7 @@ set_mode(char *modeopt)
}
}
else
else
{
{
fprintf
(
stderr
,
_
(
"%s: invalid shutdown mode %s
\n
"
),
progname
,
modeopt
);
write_stderr
(
_
(
"%s: invalid shutdown mode %s
\n
"
),
progname
,
modeopt
);
do_advice
();
do_advice
();
exit
(
1
);
exit
(
1
);
}
}
...
@@ -811,7 +1115,7 @@ set_sig(char *signame)
...
@@ -811,7 +1115,7 @@ set_sig(char *signame)
sig
=
SIGUSR2
;
sig
=
SIGUSR2
;
else
else
{
{
fprintf
(
stderr
,
_
(
"%s: invalid signal
\"
%s
\"\n
"
),
progname
,
signame
);
write_stderr
(
_
(
"%s: invalid signal
\"
%s
\"\n
"
),
progname
,
signame
);
do_advice
();
do_advice
();
exit
(
1
);
exit
(
1
);
}
}
...
@@ -879,19 +1183,17 @@ main(int argc, char **argv)
...
@@ -879,19 +1183,17 @@ main(int argc, char **argv)
/* process command-line options */
/* process command-line options */
while
(
optind
<
argc
)
while
(
optind
<
argc
)
{
{
while
((
c
=
getopt_long
(
argc
,
argv
,
"D:l:m:
o:p:s
wW"
,
long_options
,
&
option_index
))
!=
-
1
)
while
((
c
=
getopt_long
(
argc
,
argv
,
"D:l:m:
N:o:p:P:sU:
wW"
,
long_options
,
&
option_index
))
!=
-
1
)
{
{
switch
(
c
)
switch
(
c
)
{
{
case
'D'
:
case
'D'
:
{
{
int
len
=
strlen
(
optarg
)
+
4
;
int
len
=
strlen
(
optarg
);
char
*
env_var
;
char
*
env_var
;
pg_data_opts
=
xmalloc
(
len
);
env_var
=
xmalloc
(
len
+
8
);
snprintf
(
pg_data_opts
,
len
,
"-D %s"
,
optarg
);
snprintf
(
env_var
,
len
+
8
,
"PGDATA=%s"
,
optarg
);
env_var
=
xmalloc
(
len
+
sizeof
(
"PGDATA="
));
snprintf
(
env_var
,
len
+
sizeof
(
"PGDATA="
),
"PGDATA=%s"
,
optarg
);
putenv
(
env_var
);
putenv
(
env_var
);
break
;
break
;
}
}
...
@@ -901,15 +1203,36 @@ main(int argc, char **argv)
...
@@ -901,15 +1203,36 @@ main(int argc, char **argv)
case
'm'
:
case
'm'
:
set_mode
(
optarg
);
set_mode
(
optarg
);
break
;
break
;
case
'N'
:
register_servicename
=
xstrdup
(
optarg
);
break
;
case
'o'
:
case
'o'
:
post_opts
=
xstrdup
(
optarg
);
post_opts
=
xstrdup
(
optarg
);
break
;
break
;
case
'p'
:
case
'p'
:
postgres_path
=
xstrdup
(
optarg
);
postgres_path
=
xstrdup
(
optarg
);
break
;
break
;
case
'P'
:
register_password
=
xstrdup
(
optarg
);
break
;
case
's'
:
case
's'
:
silence_echo
=
true
;
silence_echo
=
true
;
break
;
break
;
case
'U'
:
if
(
strchr
(
optarg
,
'\\'
))
register_username
=
xstrdup
(
optarg
);
else
/* Prepend .\ for local accounts */
{
register_username
=
malloc
(
strlen
(
optarg
)
+
3
);
if
(
!
register_username
)
{
write_stderr
(
_
(
"%s: out of memory
\n
"
),
progname
);
exit
(
1
);
}
strcpy
(
register_username
,
".
\\
"
);
strcat
(
register_username
,
optarg
);
}
break
;
case
'w'
:
case
'w'
:
do_wait
=
true
;
do_wait
=
true
;
wait_set
=
true
;
wait_set
=
true
;
...
@@ -919,7 +1242,7 @@ main(int argc, char **argv)
...
@@ -919,7 +1242,7 @@ main(int argc, char **argv)
wait_set
=
true
;
wait_set
=
true
;
break
;
break
;
default:
default:
fprintf
(
stderr
,
_
(
"%s: invalid option %s
\n
"
),
progname
,
optarg
);
write_stderr
(
_
(
"%s: invalid option %s
\n
"
),
progname
,
optarg
);
do_advice
();
do_advice
();
exit
(
1
);
exit
(
1
);
}
}
...
@@ -930,7 +1253,7 @@ main(int argc, char **argv)
...
@@ -930,7 +1253,7 @@ main(int argc, char **argv)
{
{
if
(
ctl_command
!=
NO_COMMAND
)
if
(
ctl_command
!=
NO_COMMAND
)
{
{
fprintf
(
stderr
,
_
(
"%s: extra operation mode %s
\n
"
),
progname
,
argv
[
optind
]);
write_stderr
(
_
(
"%s: extra operation mode %s
\n
"
),
progname
,
argv
[
optind
]);
do_advice
();
do_advice
();
exit
(
1
);
exit
(
1
);
}
}
...
@@ -949,7 +1272,7 @@ main(int argc, char **argv)
...
@@ -949,7 +1272,7 @@ main(int argc, char **argv)
{
{
if
(
argc
-
optind
<
3
)
if
(
argc
-
optind
<
3
)
{
{
fprintf
(
stderr
,
_
(
"%s: invalid kill syntax
\n
"
),
progname
);
write_stderr
(
_
(
"%s: invalid kill syntax
\n
"
),
progname
);
do_advice
();
do_advice
();
exit
(
1
);
exit
(
1
);
}
}
...
@@ -957,9 +1280,17 @@ main(int argc, char **argv)
...
@@ -957,9 +1280,17 @@ main(int argc, char **argv)
set_sig
(
argv
[
++
optind
]);
set_sig
(
argv
[
++
optind
]);
killproc
=
atol
(
argv
[
++
optind
]);
killproc
=
atol
(
argv
[
++
optind
]);
}
}
#ifdef WIN32
else
if
(
strcmp
(
argv
[
optind
],
"register"
)
==
0
)
ctl_command
=
REGISTER_COMMAND
;
else
if
(
strcmp
(
argv
[
optind
],
"unregister"
)
==
0
)
ctl_command
=
UNREGISTER_COMMAND
;
else
if
(
strcmp
(
argv
[
optind
],
"runservice"
)
==
0
)
ctl_command
=
RUN_AS_SERVICE_COMMAND
;
#endif
else
else
{
{
fprintf
(
stderr
,
_
(
"%s: invalid operation mode %s
\n
"
),
progname
,
argv
[
optind
]);
write_stderr
(
_
(
"%s: invalid operation mode %s
\n
"
),
progname
,
argv
[
optind
]);
do_advice
();
do_advice
();
exit
(
1
);
exit
(
1
);
}
}
...
@@ -969,18 +1300,23 @@ main(int argc, char **argv)
...
@@ -969,18 +1300,23 @@ main(int argc, char **argv)
if
(
ctl_command
==
NO_COMMAND
)
if
(
ctl_command
==
NO_COMMAND
)
{
{
fprintf
(
stderr
,
_
(
"%s: no operation specified
\n
"
),
progname
);
write_stderr
(
_
(
"%s: no operation specified
\n
"
),
progname
);
do_advice
();
do_advice
();
exit
(
1
);
exit
(
1
);
}
}
/* Note we put any -D switch into the env var above */
pg_data
=
getenv
(
"PGDATA"
);
pg_data
=
getenv
(
"PGDATA"
);
if
(
pg_data
)
{
/* XXX modifies environment var in-place ... ugly ... */
canonicalize_path
(
pg_data
);
canonicalize_path
(
pg_data
);
}
if
(
pg_data
==
NULL
&&
ctl_command
!=
KILL_COMMAND
)
if
(
pg_data
==
NULL
&&
ctl_command
!=
KILL_COMMAND
&&
ctl_command
!=
UNREGISTER_COMMAND
)
{
{
fprintf
(
stderr
,
write_stderr
(
_
(
"%s: no database directory specified "
_
(
"%s: no database directory specified "
"and environment variable PGDATA unset
\n
"
),
"and environment variable PGDATA unset
\n
"
),
progname
);
progname
);
do_advice
();
do_advice
();
...
@@ -1034,6 +1370,17 @@ main(int argc, char **argv)
...
@@ -1034,6 +1370,17 @@ main(int argc, char **argv)
case
KILL_COMMAND
:
case
KILL_COMMAND
:
do_kill
(
killproc
);
do_kill
(
killproc
);
break
;
break
;
#ifdef WIN32
case
REGISTER_COMMAND
:
pgwin32_doRegister
();
break
;
case
UNREGISTER_COMMAND
:
pgwin32_doUnregister
();
break
;
case
RUN_AS_SERVICE_COMMAND
:
pgwin32_doRunAsService
();
break
;
#endif
default:
default:
break
;
break
;
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment