Store I/O redirection and environment options.
authorIain Patterson <me@iain.cx>
Mon, 23 Dec 2013 17:01:47 +0000 (17:01 +0000)
committerIain Patterson <me@iain.cx>
Mon, 23 Dec 2013 17:01:47 +0000 (17:01 +0000)
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
registry.cpp

diff --git a/io.cpp b/io.cpp
index 4757e73..7dedce0 100644 (file)
--- a/io.cpp
+++ b/io.cpp
@@ -152,9 +152,6 @@ void rotate_file(TCHAR *service_name, TCHAR *path, unsigned long seconds, unsign
 }\r
 \r
 int get_output_handles(nssm_service_t *service, HKEY key, STARTUPINFO *si) {\r
-  TCHAR path[MAX_PATH];\r
-  TCHAR stdout_path[MAX_PATH];\r
-  unsigned long sharing, disposition, flags;\r
   bool set_flags = false;\r
 \r
   /* Standard security attributes allowing inheritance. */\r
@@ -163,49 +160,60 @@ int get_output_handles(nssm_service_t *service, HKEY key, STARTUPINFO *si) {
   attributes.bInheritHandle = true;\r
 \r
   /* stdin */\r
-  if (get_createfile_parameters(key, NSSM_REG_STDIN, path, &sharing, NSSM_STDIN_SHARING, &disposition, NSSM_STDIN_DISPOSITION, &flags, NSSM_STDIN_FLAGS)) return 1;\r
-  if (path[0]) {\r
-    si->hStdInput = CreateFile(path, FILE_READ_DATA, sharing, &attributes, disposition, flags, 0);\r
+  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)) {\r
+    service->stdin_sharing = service->stdin_disposition = service->stdin_flags = 0;\r
+    ZeroMemory(service->stdin_path, _countof(service->stdin_path) * sizeof(TCHAR));\r
+    return 1;\r
+  }\r
+  if (si && service->stdin_path[0]) {\r
+    si->hStdInput = CreateFile(service->stdin_path, FILE_READ_DATA, service->stdin_sharing, &attributes, service->stdin_disposition, service->stdin_flags, 0);\r
     if (! si->hStdInput) {\r
-      log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATEFILE_FAILED, path, error_string(GetLastError()));\r
+      log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATEFILE_FAILED, service->stdin_path, error_string(GetLastError()), 0);\r
       return 2;\r
     }\r
     set_flags = true;\r
   }\r
 \r
   /* stdout */\r
-  if (get_createfile_parameters(key, NSSM_REG_STDOUT, path, &sharing, NSSM_STDOUT_SHARING, &disposition, NSSM_STDOUT_DISPOSITION, &flags, NSSM_STDOUT_FLAGS)) return 3;\r
-  if (path[0]) {\r
-    /* Remember path for comparison with stderr. */\r
-    if (_sntprintf_s(stdout_path, _countof(stdout_path), _TRUNCATE, _T("%s"), path) < 0) {\r
-      log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("stdout_path"), _T("get_output_handles"), 0);\r
-      return 4;\r
-    }\r
-\r
-    if (service->rotate_files) rotate_file(service->name, path, service->rotate_seconds, service->rotate_bytes_low, service->rotate_bytes_high);\r
-    si->hStdOutput = append_to_file(path, sharing, &attributes, disposition, flags);\r
-    if (! si->hStdOutput) return 5;\r
+  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)) {\r
+    service->stdout_sharing = service->stdout_disposition = service->stdout_flags = 0;\r
+    ZeroMemory(service->stdout_path, _countof(service->stdout_path) * sizeof(TCHAR));\r
+    return 3;\r
+  }\r
+  if (si && service->stdout_path[0]) {\r
+    if (service->rotate_files) rotate_file(service->name, service->stdout_path, service->rotate_seconds, service->rotate_bytes_low, service->rotate_bytes_high);\r
+    si->hStdOutput = append_to_file(service->stdout_path, service->stdout_sharing, &attributes, service->stdout_disposition, service->stdout_flags);\r
+    if (! si->hStdOutput) return 4;\r
     set_flags = true;\r
   }\r
-  else ZeroMemory(stdout_path, sizeof(stdout_path));\r
 \r
   /* stderr */\r
-  if (get_createfile_parameters(key, NSSM_REG_STDERR, path, &sharing, NSSM_STDERR_SHARING, &disposition, NSSM_STDERR_DISPOSITION, &flags, NSSM_STDERR_FLAGS)) return 6;\r
-  if (path[0]) {\r
+  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)) {\r
+    service->stderr_sharing = service->stderr_disposition = service->stderr_flags = 0;\r
+    ZeroMemory(service->stderr_path, _countof(service->stderr_path) * sizeof(TCHAR));\r
+    return 5;\r
+  }\r
+  if (service->stderr_path[0]) {\r
     /* Same as stdout? */\r
-    if (str_equiv(path, stdout_path)) {\r
-      /* Two handles to the same file will create a race. */\r
-      if (! DuplicateHandle(GetCurrentProcess(), si->hStdOutput, GetCurrentProcess(), &si->hStdError, 0, true, DUPLICATE_SAME_ACCESS)) {\r
-        log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_DUPLICATEHANDLE_FAILED, NSSM_REG_STDOUT, error_string(GetLastError()), 0);\r
-        return 7;\r
+    if (str_equiv(service->stderr_path, service->stdout_path)) {\r
+      service->stderr_sharing = service->stdout_sharing;\r
+      service->stderr_disposition = service->stdout_disposition;\r
+      service->stderr_flags = service->stdout_flags;\r
+\r
+      if (si) {\r
+        /* Two handles to the same file will create a race. */\r
+        if (! DuplicateHandle(GetCurrentProcess(), si->hStdOutput, GetCurrentProcess(), &si->hStdError, 0, true, DUPLICATE_SAME_ACCESS)) {\r
+          log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_DUPLICATEHANDLE_FAILED, NSSM_REG_STDOUT, error_string(GetLastError()), 0);\r
+          return 6;\r
+        }\r
       }\r
     }\r
-    else {\r
-      if (service->rotate_files) rotate_file(service->name, path, service->rotate_seconds, service->rotate_bytes_low, service->rotate_bytes_high);\r
-      si->hStdError = append_to_file(path, sharing, &attributes, disposition, flags);\r
+    else if (si) {\r
+      if (service->rotate_files) rotate_file(service->name, service->stderr_path, service->rotate_seconds, service->rotate_bytes_low, service->rotate_bytes_high);\r
+      si->hStdError = append_to_file(service->stderr_path, service->stdout_sharing, &attributes, service->stdout_disposition, service->stdout_flags);\r
       if (! si->hStdError) {\r
-        log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATEFILE_FAILED, path, error_string(GetLastError()), 0);\r
-        return 8;\r
+        log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATEFILE_FAILED, service->stderr_path, error_string(GetLastError()), 0);\r
+        return 7;\r
       }\r
       SetEndOfFile(si->hStdError);\r
     }\r
@@ -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\r
     inheritable by the new process.\r
   */\r
-  si->dwFlags |= STARTF_USESTDHANDLES;\r
+  if (si) si->dwFlags |= STARTF_USESTDHANDLES;\r
 \r
   return 0;\r
 }\r
index 75d48c7..09ad1cb 100644 (file)
@@ -357,36 +357,38 @@ int get_parameters(nssm_service_t *service, STARTUPINFO *si) {
   /* Environment variables to add to existing rather than replace - may fail. */\r
   set_environment(service->name, key, NSSM_REG_ENV_EXTRA, &service->env_extra, &service->env_extralen);\r
 \r
-  if (service->env_extra) {\r
-    /* Append these to any other environment variables set. */\r
-    if (service->env) {\r
-      /* Append extra variables to configured variables. */\r
-      unsigned long envlen = service->envlen + service->env_extralen - 1;\r
-      TCHAR *env = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, envlen);\r
-      if (env) {\r
-        memmove(env, service->env, service->envlen - sizeof(TCHAR));\r
-        /* envlen is in bytes. */\r
-        memmove(env + (service->envlen / sizeof(TCHAR)) - 1, service->env_extra, service->env_extralen);\r
-\r
-        HeapFree(GetProcessHeap(), 0, service->env);\r
-        service->env = env;\r
-        service->envlen = envlen;\r
+  if (si) {\r
+    if (service->env_extra) {\r
+      /* Append these to any other environment variables set. */\r
+      if (service->env) {\r
+        /* Append extra variables to configured variables. */\r
+        unsigned long envlen = service->envlen + service->env_extralen - 1;\r
+        TCHAR *env = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, envlen);\r
+        if (env) {\r
+          memmove(env, service->env, service->envlen - sizeof(TCHAR));\r
+          /* envlen is in bytes. */\r
+          memmove(env + (service->envlen / sizeof(TCHAR)) - 1, service->env_extra, service->env_extralen);\r
+\r
+          HeapFree(GetProcessHeap(), 0, service->env);\r
+          service->env = env;\r
+          service->envlen = envlen;\r
+        }\r
+        else log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("environment"), _T("get_parameters()"), 0);\r
       }\r
-      else log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("environment"), _T("get_parameters()"), 0);\r
-    }\r
-    else {\r
-      /* Append extra variables to our environment. */\r
-      TCHAR *env, *s;\r
-      size_t envlen, len;\r
-\r
-      env = service->env_extra;\r
-      len = 0;\r
-      while (*env) {\r
-        envlen = _tcslen(env) + 1;\r
-        for (s = env; *s && *s != _T('='); s++);\r
-        if (*s == _T('=')) *s++ = _T('\0');\r
-        if (! SetEnvironmentVariable(env, s)) log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_SETENVIRONMENTVARIABLE_FAILED, env, s, error_string(GetLastError()), 0);\r
-        env += envlen;\r
+      else {\r
+        /* Append extra variables to our environment. */\r
+        TCHAR *env, *s;\r
+        size_t envlen, len;\r
+\r
+        env = service->env_extra;\r
+        len = 0;\r
+        while (*env) {\r
+          envlen = _tcslen(env) + 1;\r
+          for (s = env; *s && *s != _T('='); s++);\r
+          if (*s == _T('=')) *s++ = _T('\0');\r
+          if (! SetEnvironmentVariable(env, s)) log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_SETENVIRONMENTVARIABLE_FAILED, env, s, error_string(GetLastError()), 0);\r
+          env += envlen;\r
+        }\r
       }\r
     }\r
   }\r