diff options
author | Nick Mathewson <nickm@torproject.org> | 2005-01-27 21:45:32 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2005-01-27 21:45:32 +0000 |
commit | e03f571ee31a4d0e028db48d003a4bae105717f8 (patch) | |
tree | 51bf8a3195e3c08060e0f450cab2f5a2d4e5f419 /src | |
parent | 5dbfcd876a33b2979d2d104c5120a7564a343d71 (diff) | |
download | tor-e03f571ee31a4d0e028db48d003a4bae105717f8.tar.gz tor-e03f571ee31a4d0e028db48d003a4bae105717f8.zip |
Forward-port win32 service patch; try to clean it a touch.
svn:r3438
Diffstat (limited to 'src')
-rw-r--r-- | src/or/main.c | 75 |
1 files changed, 56 insertions, 19 deletions
diff --git a/src/or/main.c b/src/or/main.c index 6038f18d92..3bd618b2c4 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -89,6 +89,9 @@ SERVICE_STATUS service_status; SERVICE_STATUS_HANDLE hStatus; static char **backup_argv; static int backup_argc; +static int nt_service_is_stopped(void); +#else +#define nt_service_is_stopped() (0) #endif #define CHECK_DESCRIPTOR_INTERVAL 60 @@ -982,14 +985,8 @@ static int do_main_loop(void) { second_elapsed_callback(0,0,NULL); for (;;) { -#ifdef MS_WINDOWS_SERVICE /* Do service stuff only on windows. */ - if (service_status.dwCurrentState == SERVICE_STOP_PENDING) { - service_status.dwWin32ExitCode = 0; - service_status.dwCurrentState = SERVICE_STOPPED; - SetServiceStatus(hStatus, &service_status); + if (nt_service_is_stopped()) return 0; - } -#endif /* poll until we have an event, or the second ends */ loop_result = event_dispatch(); @@ -1234,6 +1231,7 @@ static int tor_init(int argc, char *argv[]) { /* give it somewhere to log to initially */ add_temp_log(); + log_fn(LOG_NOTICE,"Tor v%s. This is experimental software. Do not rely on it for strong anonymity.",VERSION); if (network_init()<0) { @@ -1324,6 +1322,22 @@ static void do_hash_password(void) } #ifdef MS_WINDOWS_SERVICE +/** If we're compile to run as an NT service, and the service has been + * shut down, then change our current status and return 1. Else + * return 0. + */ +static int +nt_service_is_stopped(void) +{ + if (service_status.dwCurrentState == SERVICE_STOP_PENDING) { + service_status.dwWin32ExitCode = 0; + service_status.dwCurrentState = SERVICE_STOPPED; + SetServiceStatus(hStatus, &service_status); + return 1; + } + return 0; +} + void nt_service_control(DWORD request) { switch (request) { @@ -1339,7 +1353,6 @@ void nt_service_control(DWORD request) void nt_service_body(int argc, char **argv) { int err; - FILE *f; service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; service_status.dwCurrentState = SERVICE_START_PENDING; service_status.dwControlsAccepted = @@ -1349,10 +1362,12 @@ void nt_service_body(int argc, char **argv) service_status.dwCheckPoint = 0; service_status.dwWaitHint = 1000; hStatus = RegisterServiceCtrlHandler(GENSRV_SERVICENAME, (LPHANDLER_FUNCTION) nt_service_control); + if (hStatus == 0) { // failed; return; } + err = tor_init(backup_argc, backup_argv); // refactor this part out of tor_main and do_main_loop if (err) { // failed. @@ -1376,6 +1391,7 @@ void nt_service_main(void) table[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)nt_service_body; table[1].lpServiceName = NULL; table[1].lpServiceProc = NULL; + if (!StartServiceCtrlDispatcher(table)) { result = GetLastError(); printf("Error was %d\n",result); @@ -1404,11 +1420,15 @@ int nt_service_install() { /* XXXX Problems with NT services: * 1. The configuration file needs to be in the same directory as the .exe + * * 2. The exe and the configuration file can't be on any directory path * that contains a space. + * mje - you can quote the string (i.e., "c:\program files") + * * 3. Ideally, there should be one EXE that can either run as a * separate process (as now) or that can install and run itself * as an NT service. I have no idea how hard this is. + * mje - should be done. It can install and run itself as a service * * Notes about developing NT services: * @@ -1432,14 +1452,21 @@ int nt_service_install() return 0; _tsplitpath(szPath, szDrive, szDir, NULL, NULL); - len = _MAX_PATH + strlen(cmd1) + _MAX_DRIVE + _MAX_DIR + strlen(cmd2); + + /* Account for the extra quotes */ + //len = _MAX_PATH + strlen(cmd1) + _MAX_DRIVE + _MAX_DIR + strlen(cmd2); + len = _MAX_PATH + strlen(cmd1) + _MAX_DRIVE + _MAX_DIR + strlen(cmd2) + 4; command = tor_malloc(len); - strlcpy(command, szPath, len); - strlcat(command, " -f ", len); - strlcat(command, szDrive, len); - strlcat(command, szDir, len); - strlcat(command, "\\torrc", len); + /* Create a quoted command line, like "c:\with spaces\tor.exe" -f + * "c:\with spaces\tor.exe" + */ + if (tor_snprintf(command, len, "\"%s\" -f \"%s%storrc\"", + szPath, szDrive, szDir)<0) { + printf("Failed: tor_snprinf()\n"); + free(command); + return 0; + } if ((hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE)) == NULL) { printf("Failed: OpenSCManager()\n"); @@ -1447,21 +1474,31 @@ int nt_service_install() return 0; } + /* 1/26/2005 mje + * - changed the service start type to auto + * - and changed the lpPassword param to "" instead of NULL as per an + * MSDN article. + */ if ((hService = CreateService(hSCManager, GENSRV_SERVICENAME, GENSRV_DISPLAYNAME, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, - SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE, command, - NULL, NULL, NULL, NULL, NULL)) == NULL) { + SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, command, + NULL, NULL, NULL, NULL, "")) == NULL) { printf("Failed: CreateService()\n"); CloseServiceHandle(hSCManager); free(command); return 0; } + /* Start the service initially, so you don't have to muck with it in the SCM + */ + if(!StartService(hService, 0, NULL)) + printf("Service installed, but not started.\n"); + else + printf("Service installed and started successfully!\n"); + CloseServiceHandle(hService); CloseServiceHandle(hSCManager); - free(command); - - printf("Install service successfully\n"); + tor_free(command); return 0; } |