Install tinc as a service under Windows (MinGW). Remove cleanup_and_exit(),
either exit() directly on errors or let main_loop() shutdown gracefully.
This commit is contained in:
parent
7c34122af7
commit
f08fc359a0
9 changed files with 410 additions and 175 deletions
|
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: logger.c,v 1.1.2.8 2003/07/29 22:59:00 guus Exp $
|
||||
$Id: logger.c,v 1.1.2.9 2003/08/02 20:50:38 guus Exp $
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
|
|
@ -71,6 +71,7 @@ void logger(int priority, const char *format, ...) {
|
|||
fprintf(logfile, "%ld %s[%d]: ", time(NULL), logident, logpid);
|
||||
vfprintf(logfile, format, ap);
|
||||
fprintf(logfile, "\n");
|
||||
fflush(logfile);
|
||||
break;
|
||||
case LOGMODE_SYSLOG:
|
||||
#ifdef HAVE_SYSLOG_H
|
||||
|
|
|
|||
17
src/net.c
17
src/net.c
|
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: net.c,v 1.35.4.195 2003/07/29 22:59:00 guus Exp $
|
||||
$Id: net.c,v 1.35.4.196 2003/08/02 20:50:38 guus Exp $
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
|
|
@ -42,6 +42,7 @@
|
|||
#include "xalloc.h"
|
||||
|
||||
bool do_purge = false;
|
||||
volatile bool running;
|
||||
|
||||
time_t now = 0;
|
||||
|
||||
|
|
@ -280,7 +281,7 @@ static void check_network_activity(fd_set * f)
|
|||
/*
|
||||
this is where it all happens...
|
||||
*/
|
||||
void main_loop(void)
|
||||
int main_loop(void)
|
||||
{
|
||||
fd_set fset;
|
||||
struct timeval tv;
|
||||
|
|
@ -294,7 +295,9 @@ void main_loop(void)
|
|||
last_config_check = now;
|
||||
srand(now);
|
||||
|
||||
for(;;) {
|
||||
running = true;
|
||||
|
||||
while(running) {
|
||||
now = time(NULL);
|
||||
|
||||
tv.tv_sec = 1 + (rand() & 7); /* Approx. 5 seconds, randomized to prevent global synchronisation effects */
|
||||
|
|
@ -310,7 +313,7 @@ void main_loop(void)
|
|||
strerror(errno));
|
||||
cp_trace();
|
||||
dump_connections();
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
|
||||
continue;
|
||||
|
|
@ -379,7 +382,7 @@ void main_loop(void)
|
|||
|
||||
if(!read_server_config()) {
|
||||
logger(LOG_ERR, _("Unable to reread configuration file, exitting."));
|
||||
exit(1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Close connections to hosts that have a changed or deleted host config file */
|
||||
|
|
@ -405,8 +408,8 @@ void main_loop(void)
|
|||
/* Try to make outgoing connections */
|
||||
|
||||
try_outgoing_connections();
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: net.h,v 1.9.4.68 2003/07/29 22:59:00 guus Exp $
|
||||
$Id: net.h,v 1.9.4.69 2003/08/02 20:50:38 guus Exp $
|
||||
*/
|
||||
|
||||
#ifndef __TINC_NET_H__
|
||||
|
|
@ -135,7 +135,7 @@ extern bool setup_network_connections(void);
|
|||
extern void setup_outgoing_connection(struct outgoing_t *);
|
||||
extern void try_outgoing_connections(void);
|
||||
extern void close_network_connections(void);
|
||||
extern void main_loop(void);
|
||||
extern int main_loop(void);
|
||||
extern void terminate_connection(struct connection_t *, bool);
|
||||
extern void flush_queue(struct node_t *);
|
||||
extern bool read_rsa_public_key(struct connection_t *);
|
||||
|
|
|
|||
175
src/process.c
175
src/process.c
|
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: process.c,v 1.1.2.60 2003/07/31 14:24:19 guus Exp $
|
||||
$Id: process.c,v 1.1.2.61 2003/08/02 20:50:38 guus Exp $
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
|
|
@ -43,6 +43,7 @@ extern char *identname;
|
|||
extern char *pidfilename;
|
||||
extern char **g_argv;
|
||||
extern bool use_logfile;
|
||||
extern volatile bool running;
|
||||
|
||||
sigset_t emptysigset;
|
||||
|
||||
|
|
@ -70,24 +71,154 @@ static int fcloseall(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
Close network connections, and terminate neatly
|
||||
*/
|
||||
void cleanup_and_exit(int c)
|
||||
{
|
||||
cp();
|
||||
#ifdef HAVE_MINGW
|
||||
extern char *identname;
|
||||
extern char *program_name;
|
||||
extern char **g_argv;
|
||||
|
||||
close_network_connections();
|
||||
static SC_HANDLE manager = NULL;
|
||||
static SC_HANDLE service = NULL;
|
||||
static SERVICE_STATUS status = {0};
|
||||
static SERVICE_STATUS_HANDLE statushandle = 0;
|
||||
|
||||
ifdebug(CONNECTIONS)
|
||||
dump_device_stats();
|
||||
bool install_service(void) {
|
||||
char command[4096] = "";
|
||||
char **argp;
|
||||
|
||||
logger(LOG_NOTICE, _("Terminating"));
|
||||
manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
||||
if(!manager) {
|
||||
logger(LOG_ERR, _("Could not open service manager: %s"), winerror(GetLastError()));
|
||||
return false;
|
||||
}
|
||||
|
||||
closelogger();
|
||||
exit(c);
|
||||
if(!strchr(program_name, '\\')) {
|
||||
GetCurrentDirectory(sizeof(command), command);
|
||||
strncat(command, "\\", sizeof(command));
|
||||
}
|
||||
|
||||
strncat(command, program_name, sizeof(command));
|
||||
for(argp = g_argv + 1; *argp; argp++) {
|
||||
strncat(command, " ", sizeof(command));
|
||||
strncat(command, *argp, sizeof(command));
|
||||
}
|
||||
|
||||
service = CreateService(manager, identname, identname,
|
||||
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
|
||||
command, "NDIS", NULL, NULL, NULL, NULL);
|
||||
|
||||
if(!service) {
|
||||
logger(LOG_ERR, _("Could not create %s service: %s"), identname, winerror(GetLastError()));
|
||||
return false;
|
||||
}
|
||||
|
||||
logger(LOG_INFO, _("%s service installed"), identname);
|
||||
|
||||
if(!StartService(service, 0, NULL))
|
||||
logger(LOG_WARNING, _("Could not start %s service: %s"), identname, winerror(GetLastError()));
|
||||
else
|
||||
logger(LOG_INFO, _("%s service started"), identname);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool remove_service(void) {
|
||||
manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
||||
if(!manager) {
|
||||
logger(LOG_ERR, _("Could not open service manager: %s"), winerror(GetLastError()));
|
||||
return false;
|
||||
}
|
||||
|
||||
service = OpenService(manager, identname, SERVICE_ALL_ACCESS);
|
||||
|
||||
if(!service) {
|
||||
logger(LOG_ERR, _("Could not open %s service: %s"), identname, winerror(GetLastError()));
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!ControlService(service, SERVICE_CONTROL_STOP, &status))
|
||||
logger(LOG_ERR, _("Could not stop %s service: %s"), identname, winerror(GetLastError()));
|
||||
else
|
||||
logger(LOG_INFO, _("%s service stopped"), identname);
|
||||
|
||||
if(!DeleteService(service)) {
|
||||
logger(LOG_ERR, _("Could not remove %s service: %s"), identname, winerror(GetLastError()));
|
||||
return false;
|
||||
}
|
||||
|
||||
logger(LOG_INFO, _("%s service removed"), identname);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
DWORD WINAPI controlhandler(DWORD request, DWORD type, LPVOID boe, LPVOID bah) {
|
||||
switch(request) {
|
||||
case SERVICE_CONTROL_STOP:
|
||||
logger(LOG_NOTICE, _("Got %s request"), "SERVICE_CONTROL_STOP");
|
||||
running = false;
|
||||
break;
|
||||
case SERVICE_CONTROL_SHUTDOWN:
|
||||
logger(LOG_NOTICE, _("Got %s request"), "SERVICE_CONTROL_SHUTDOWN");
|
||||
running = false;
|
||||
break;
|
||||
default:
|
||||
logger(LOG_WARNING, _("Got unexpected request %d"), request);
|
||||
return ERROR_CALL_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
VOID WINAPI run_service(DWORD argc, LPTSTR* argv)
|
||||
{
|
||||
int err = 1;
|
||||
extern int main2(int argc, char **argv);
|
||||
|
||||
|
||||
status.dwServiceType = SERVICE_WIN32;
|
||||
status.dwCurrentState = SERVICE_RUNNING;
|
||||
status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
|
||||
status.dwWin32ExitCode = 0;
|
||||
status.dwServiceSpecificExitCode = 0;
|
||||
status.dwCheckPoint = 0;
|
||||
status.dwWaitHint = 0;
|
||||
|
||||
statushandle = RegisterServiceCtrlHandlerEx(identname, controlhandler, NULL);
|
||||
|
||||
if (!statushandle) {
|
||||
logger(LOG_ERR, _("System call `%s' failed: %s"), "RegisterServiceCtrlHandlerEx", winerror(GetLastError()));
|
||||
err = 1;
|
||||
} else {
|
||||
SetServiceStatus(statushandle, &status);
|
||||
|
||||
err = main2(argc, argv);
|
||||
|
||||
status.dwCurrentState = SERVICE_STOPPED;
|
||||
status.dwWin32ExitCode = err;
|
||||
|
||||
SetServiceStatus(statushandle, &status);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool init_service(void) {
|
||||
SERVICE_TABLE_ENTRY services[] = {
|
||||
{identname, run_service},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
if(!StartServiceCtrlDispatcher(services)) {
|
||||
if(GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) {
|
||||
return false;
|
||||
}
|
||||
else
|
||||
logger(LOG_ERR, _("System call `%s' failed: %s"), "StartServiceCtrlDispatcher", winerror(GetLastError()));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_MINGW
|
||||
/*
|
||||
check for an existing tinc for this net, and write pid to pidfile
|
||||
|
|
@ -151,9 +282,11 @@ bool kill_other(int signal)
|
|||
fprintf(stderr, _("Removing stale lock file.\n"));
|
||||
remove_pid(pidfilename);
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
#else
|
||||
return remove_service();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -170,14 +303,14 @@ bool detach(void)
|
|||
#ifndef HAVE_MINGW
|
||||
if(!write_pidfile())
|
||||
return false;
|
||||
#endif
|
||||
|
||||
/* If we succeeded in doing that, detach */
|
||||
|
||||
closelogger();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FORK
|
||||
if(do_detach) {
|
||||
#ifndef HAVE_MINGW
|
||||
if(daemon(0, 0)) {
|
||||
fprintf(stderr, _("Couldn't detach from terminal: %s"),
|
||||
strerror(errno));
|
||||
|
|
@ -188,8 +321,11 @@ bool detach(void)
|
|||
|
||||
if(!write_pid(pidfilename))
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
if(!statushandle)
|
||||
exit(install_service());
|
||||
#endif
|
||||
}
|
||||
|
||||
openlogger(identname, use_logfile?LOGMODE_FILE:(do_detach?LOGMODE_SYSLOG:LOGMODE_STDERR));
|
||||
|
||||
|
|
@ -312,14 +448,13 @@ bool execute_script(const char *name, char **envp)
|
|||
static RETSIGTYPE sigterm_handler(int a)
|
||||
{
|
||||
logger(LOG_NOTICE, _("Got TERM signal"));
|
||||
|
||||
cleanup_and_exit(0);
|
||||
running = false;
|
||||
}
|
||||
|
||||
static RETSIGTYPE sigquit_handler(int a)
|
||||
{
|
||||
logger(LOG_NOTICE, _("Got QUIT signal"));
|
||||
cleanup_and_exit(0);
|
||||
running = false;
|
||||
}
|
||||
|
||||
static RETSIGTYPE fatal_signal_square(int a)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: process.h,v 1.1.2.18 2003/07/30 21:52:41 guus Exp $
|
||||
$Id: process.h,v 1.1.2.19 2003/08/02 20:50:38 guus Exp $
|
||||
*/
|
||||
|
||||
#ifndef __TINC_PROCESS_H__
|
||||
|
|
@ -31,6 +31,5 @@ extern void setup_signals(void);
|
|||
extern bool execute_script(const char *, char **);
|
||||
extern bool detach(void);
|
||||
extern bool kill_other(int);
|
||||
extern void cleanup_and_exit(int) __attribute__ ((__noreturn__));
|
||||
|
||||
#endif /* __TINC_PROCESS_H__ */
|
||||
|
|
|
|||
66
src/tincd.c
66
src/tincd.c
|
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: tincd.c,v 1.10.4.79 2003/07/30 11:50:45 guus Exp $
|
||||
$Id: tincd.c,v 1.10.4.80 2003/08/02 20:50:38 guus Exp $
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
|
|
@ -77,7 +77,8 @@ char *identname = NULL; /* program name for syslog */
|
|||
char *pidfilename = NULL; /* pid file location */
|
||||
char *logfilename = NULL; /* log file location */
|
||||
char **g_argv; /* a copy of the cmdline arguments */
|
||||
char **environment; /* A pointer to the environment on startup */
|
||||
|
||||
int exitstatus = 0;
|
||||
|
||||
static struct option const long_options[] = {
|
||||
{"config", required_argument, NULL, 'c'},
|
||||
|
|
@ -119,11 +120,9 @@ static void usage(bool status)
|
|||
" --version Output version information and exit.\n\n"));
|
||||
printf(_("Report bugs to tinc@nl.linux.org.\n"));
|
||||
}
|
||||
|
||||
exit(status);
|
||||
}
|
||||
|
||||
static void parse_options(int argc, char **argv, char **envp)
|
||||
static bool parse_options(int argc, char **argv)
|
||||
{
|
||||
int r;
|
||||
int option_index = 0;
|
||||
|
|
@ -178,10 +177,13 @@ static void parse_options(int argc, char **argv, char **envp)
|
|||
fprintf(stderr, _("Invalid argument `%s'; SIGNAL must be a number or one of HUP, TERM, KILL, USR1, USR2, WINCH, INT or ALRM.\n"),
|
||||
optarg);
|
||||
usage(true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else
|
||||
kill_tincd = SIGTERM;
|
||||
#else
|
||||
kill_tincd = 1;
|
||||
#endif
|
||||
break;
|
||||
|
||||
|
|
@ -197,6 +199,7 @@ static void parse_options(int argc, char **argv, char **envp)
|
|||
fprintf(stderr, _("Invalid argument `%s'; BITS must be a number equal to or greater than 512.\n"),
|
||||
optarg);
|
||||
usage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
generate_keys &= ~7; /* Round it to bytes */
|
||||
|
|
@ -228,11 +231,14 @@ static void parse_options(int argc, char **argv, char **envp)
|
|||
|
||||
case '?':
|
||||
usage(true);
|
||||
return false;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* This function prettyprints the key generation process */
|
||||
|
|
@ -354,7 +360,7 @@ static void make_names(void)
|
|||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
program_name = argv[0];
|
||||
|
||||
|
|
@ -362,8 +368,9 @@ int main(int argc, char **argv, char **envp)
|
|||
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
textdomain(PACKAGE);
|
||||
|
||||
environment = envp;
|
||||
parse_options(argc, argv, envp);
|
||||
if(!parse_options(argc, argv))
|
||||
return 1;
|
||||
|
||||
make_names();
|
||||
|
||||
if(show_version) {
|
||||
|
|
@ -378,11 +385,13 @@ int main(int argc, char **argv, char **envp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if(show_help)
|
||||
if(show_help) {
|
||||
usage(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(kill_tincd)
|
||||
exit(!kill_other(kill_tincd));
|
||||
return !kill_other(kill_tincd);
|
||||
|
||||
openlogger("tinc", LOGMODE_STDERR);
|
||||
|
||||
|
|
@ -412,31 +421,48 @@ int main(int argc, char **argv, char **envp)
|
|||
|
||||
if(generate_keys) {
|
||||
read_server_config();
|
||||
exit(!keygen(generate_keys));
|
||||
return !keygen(generate_keys);
|
||||
}
|
||||
|
||||
if(!read_server_config())
|
||||
exit(1);
|
||||
return 1;
|
||||
|
||||
if(lzo_init() != LZO_E_OK) {
|
||||
logger(LOG_ERR, _("Error initializing LZO compressor!"));
|
||||
exit(1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_MINGW
|
||||
if(WSAStartup(MAKEWORD(2, 2), &wsa_state)) {
|
||||
logger(LOG_ERR, _("System call `%s' failed: %s"), "WSAStartup", strerror(errno));
|
||||
exit(1);
|
||||
logger(LOG_ERR, _("System call `%s' failed: %s"), "WSAStartup", winerror(GetLastError()));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!do_detach || !init_service())
|
||||
return main2(argc, argv);
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main2(int argc, char **argv)
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
if(!detach())
|
||||
exit(1);
|
||||
return 1;
|
||||
|
||||
for(;;) {
|
||||
if(setup_network_connections()) {
|
||||
main_loop();
|
||||
cleanup_and_exit(1);
|
||||
int status;
|
||||
status = main_loop();
|
||||
|
||||
close_network_connections();
|
||||
|
||||
ifdebug(CONNECTIONS)
|
||||
dump_device_stats();
|
||||
|
||||
logger(LOG_NOTICE, _("Terminating"));
|
||||
return status;
|
||||
}
|
||||
|
||||
logger(LOG_ERR, _("Unrecoverable error"));
|
||||
|
|
@ -447,7 +473,7 @@ int main(int argc, char **argv, char **envp)
|
|||
sleep(maxtimeout);
|
||||
} else {
|
||||
logger(LOG_ERR, _("Not restarting."));
|
||||
exit(1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue