From a180ba0774a106b9a59218814d78281a03c5f1f3 Mon Sep 17 00:00:00 2001 From: Iain Patterson Date: Mon, 23 Dec 2013 17:01:47 +0000 Subject: [PATCH] Store I/O redirection and environment options. Previously we queried I/O redirection and environment options from the registry when starting the service. We now add support for being able to query those options and store them in the service data structure at any time. This will allow us to edit services later. --- io.cpp | 72 +++++++++++++++++++++++++++++----------------------- registry.cpp | 60 ++++++++++++++++++++++--------------------- 2 files changed, 71 insertions(+), 61 deletions(-) diff --git a/io.cpp b/io.cpp index 4757e73..7dedce0 100644 --- a/io.cpp +++ b/io.cpp @@ -152,9 +152,6 @@ void rotate_file(TCHAR *service_name, TCHAR *path, unsigned long seconds, unsign } int get_output_handles(nssm_service_t *service, HKEY key, STARTUPINFO *si) { - TCHAR path[MAX_PATH]; - TCHAR stdout_path[MAX_PATH]; - unsigned long sharing, disposition, flags; bool set_flags = false; /* Standard security attributes allowing inheritance. */ @@ -163,49 +160,60 @@ int get_output_handles(nssm_service_t *service, HKEY key, STARTUPINFO *si) { attributes.bInheritHandle = true; /* stdin */ - if (get_createfile_parameters(key, NSSM_REG_STDIN, path, &sharing, NSSM_STDIN_SHARING, &disposition, NSSM_STDIN_DISPOSITION, &flags, NSSM_STDIN_FLAGS)) return 1; - if (path[0]) { - si->hStdInput = CreateFile(path, FILE_READ_DATA, sharing, &attributes, disposition, flags, 0); + if (get_createfile_parameters(key, NSSM_REG_STDIN, service->stdin_path, &service->stdin_sharing, NSSM_STDIN_SHARING, &service->stdin_disposition, NSSM_STDIN_DISPOSITION, &service->stdin_flags, NSSM_STDIN_FLAGS)) { + service->stdin_sharing = service->stdin_disposition = service->stdin_flags = 0; + ZeroMemory(service->stdin_path, _countof(service->stdin_path) * sizeof(TCHAR)); + return 1; + } + if (si && service->stdin_path[0]) { + si->hStdInput = CreateFile(service->stdin_path, FILE_READ_DATA, service->stdin_sharing, &attributes, service->stdin_disposition, service->stdin_flags, 0); if (! si->hStdInput) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATEFILE_FAILED, path, error_string(GetLastError())); + log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATEFILE_FAILED, service->stdin_path, error_string(GetLastError()), 0); return 2; } set_flags = true; } /* stdout */ - if (get_createfile_parameters(key, NSSM_REG_STDOUT, path, &sharing, NSSM_STDOUT_SHARING, &disposition, NSSM_STDOUT_DISPOSITION, &flags, NSSM_STDOUT_FLAGS)) return 3; - if (path[0]) { - /* Remember path for comparison with stderr. */ - if (_sntprintf_s(stdout_path, _countof(stdout_path), _TRUNCATE, _T("%s"), path) < 0) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("stdout_path"), _T("get_output_handles"), 0); - return 4; - } - - if (service->rotate_files) rotate_file(service->name, path, service->rotate_seconds, service->rotate_bytes_low, service->rotate_bytes_high); - si->hStdOutput = append_to_file(path, sharing, &attributes, disposition, flags); - if (! si->hStdOutput) return 5; + if (get_createfile_parameters(key, NSSM_REG_STDOUT, service->stdout_path, &service->stdout_sharing, NSSM_STDOUT_SHARING, &service->stdout_disposition, NSSM_STDOUT_DISPOSITION, &service->stdout_flags, NSSM_STDOUT_FLAGS)) { + service->stdout_sharing = service->stdout_disposition = service->stdout_flags = 0; + ZeroMemory(service->stdout_path, _countof(service->stdout_path) * sizeof(TCHAR)); + return 3; + } + if (si && service->stdout_path[0]) { + if (service->rotate_files) rotate_file(service->name, service->stdout_path, service->rotate_seconds, service->rotate_bytes_low, service->rotate_bytes_high); + si->hStdOutput = append_to_file(service->stdout_path, service->stdout_sharing, &attributes, service->stdout_disposition, service->stdout_flags); + if (! si->hStdOutput) return 4; set_flags = true; } - else ZeroMemory(stdout_path, sizeof(stdout_path)); /* stderr */ - if (get_createfile_parameters(key, NSSM_REG_STDERR, path, &sharing, NSSM_STDERR_SHARING, &disposition, NSSM_STDERR_DISPOSITION, &flags, NSSM_STDERR_FLAGS)) return 6; - if (path[0]) { + if (get_createfile_parameters(key, NSSM_REG_STDERR, service->stderr_path, &service->stdout_sharing, NSSM_STDERR_SHARING, &service->stdout_disposition, NSSM_STDERR_DISPOSITION, &service->stdout_flags, NSSM_STDERR_FLAGS)) { + service->stderr_sharing = service->stderr_disposition = service->stderr_flags = 0; + ZeroMemory(service->stderr_path, _countof(service->stderr_path) * sizeof(TCHAR)); + return 5; + } + if (service->stderr_path[0]) { /* Same as stdout? */ - if (str_equiv(path, stdout_path)) { - /* Two handles to the same file will create a race. */ - if (! DuplicateHandle(GetCurrentProcess(), si->hStdOutput, GetCurrentProcess(), &si->hStdError, 0, true, DUPLICATE_SAME_ACCESS)) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_DUPLICATEHANDLE_FAILED, NSSM_REG_STDOUT, error_string(GetLastError()), 0); - return 7; + if (str_equiv(service->stderr_path, service->stdout_path)) { + service->stderr_sharing = service->stdout_sharing; + service->stderr_disposition = service->stdout_disposition; + service->stderr_flags = service->stdout_flags; + + if (si) { + /* Two handles to the same file will create a race. */ + if (! DuplicateHandle(GetCurrentProcess(), si->hStdOutput, GetCurrentProcess(), &si->hStdError, 0, true, DUPLICATE_SAME_ACCESS)) { + log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_DUPLICATEHANDLE_FAILED, NSSM_REG_STDOUT, error_string(GetLastError()), 0); + return 6; + } } } - else { - if (service->rotate_files) rotate_file(service->name, path, service->rotate_seconds, service->rotate_bytes_low, service->rotate_bytes_high); - si->hStdError = append_to_file(path, sharing, &attributes, disposition, flags); + else if (si) { + if (service->rotate_files) rotate_file(service->name, service->stderr_path, service->rotate_seconds, service->rotate_bytes_low, service->rotate_bytes_high); + si->hStdError = append_to_file(service->stderr_path, service->stdout_sharing, &attributes, service->stdout_disposition, service->stdout_flags); if (! si->hStdError) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATEFILE_FAILED, path, error_string(GetLastError()), 0); - return 8; + log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATEFILE_FAILED, service->stderr_path, error_string(GetLastError()), 0); + return 7; } SetEndOfFile(si->hStdError); } @@ -218,7 +226,7 @@ int get_output_handles(nssm_service_t *service, HKEY key, STARTUPINFO *si) { We need to set the startup_info flags to make the new handles inheritable by the new process. */ - si->dwFlags |= STARTF_USESTDHANDLES; + if (si) si->dwFlags |= STARTF_USESTDHANDLES; return 0; } diff --git a/registry.cpp b/registry.cpp index 75d48c7..09ad1cb 100644 --- a/registry.cpp +++ b/registry.cpp @@ -357,36 +357,38 @@ int get_parameters(nssm_service_t *service, STARTUPINFO *si) { /* Environment variables to add to existing rather than replace - may fail. */ set_environment(service->name, key, NSSM_REG_ENV_EXTRA, &service->env_extra, &service->env_extralen); - if (service->env_extra) { - /* Append these to any other environment variables set. */ - if (service->env) { - /* Append extra variables to configured variables. */ - unsigned long envlen = service->envlen + service->env_extralen - 1; - TCHAR *env = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, envlen); - if (env) { - memmove(env, service->env, service->envlen - sizeof(TCHAR)); - /* envlen is in bytes. */ - memmove(env + (service->envlen / sizeof(TCHAR)) - 1, service->env_extra, service->env_extralen); - - HeapFree(GetProcessHeap(), 0, service->env); - service->env = env; - service->envlen = envlen; + if (si) { + if (service->env_extra) { + /* Append these to any other environment variables set. */ + if (service->env) { + /* Append extra variables to configured variables. */ + unsigned long envlen = service->envlen + service->env_extralen - 1; + TCHAR *env = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, envlen); + if (env) { + memmove(env, service->env, service->envlen - sizeof(TCHAR)); + /* envlen is in bytes. */ + memmove(env + (service->envlen / sizeof(TCHAR)) - 1, service->env_extra, service->env_extralen); + + HeapFree(GetProcessHeap(), 0, service->env); + service->env = env; + service->envlen = envlen; + } + else log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("environment"), _T("get_parameters()"), 0); } - else log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("environment"), _T("get_parameters()"), 0); - } - else { - /* Append extra variables to our environment. */ - TCHAR *env, *s; - size_t envlen, len; - - env = service->env_extra; - len = 0; - while (*env) { - envlen = _tcslen(env) + 1; - for (s = env; *s && *s != _T('='); s++); - if (*s == _T('=')) *s++ = _T('\0'); - if (! SetEnvironmentVariable(env, s)) log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_SETENVIRONMENTVARIABLE_FAILED, env, s, error_string(GetLastError()), 0); - env += envlen; + else { + /* Append extra variables to our environment. */ + TCHAR *env, *s; + size_t envlen, len; + + env = service->env_extra; + len = 0; + while (*env) { + envlen = _tcslen(env) + 1; + for (s = env; *s && *s != _T('='); s++); + if (*s == _T('=')) *s++ = _T('\0'); + if (! SetEnvironmentVariable(env, s)) log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_SETENVIRONMENTVARIABLE_FAILED, env, s, error_string(GetLastError()), 0); + env += envlen; + } } } } -- 2.20.1