Allow adding or removing individual environment variables.
[nssm.git] / settings.cpp
index f50dcc4..3ed5ec4 100644 (file)
@@ -339,17 +339,54 @@ static int setting_set_environment(const TCHAR *service_name, void *param, const
   HKEY key = (HKEY) param;\r
   if (! param) return -1;\r
 \r
-  if (! value || ! value->string || ! value->string[0]) {\r
+  TCHAR *string = 0;\r
+  TCHAR *unformatted = 0;\r
+  unsigned long envlen;\r
+  unsigned long newlen = 0;\r
+  int op = 0;\r
+  if (value && value->string && value->string[0]) {\r
+    string = value->string;\r
+    switch (string[0]) {\r
+      case _T('+'): op = 1; break;\r
+      case _T('-'): op = -1; break;\r
+      case _T(':'): string++; break;\r
+    }\r
+  }\r
+\r
+  if (op) {\r
+    string++;\r
+    TCHAR *env = 0;\r
+    if (get_environment((TCHAR *) service_name, key, (TCHAR *) name, &env, &envlen)) return -1;\r
+    if (env) {\r
+      int ret;\r
+      if (op > 0) ret = append_to_environment_block(env, envlen, string, &unformatted, &newlen);\r
+      else ret = remove_from_environment_block(env, envlen, string, &unformatted, &newlen);\r
+      if (envlen) HeapFree(GetProcessHeap(), 0, env);\r
+      if (ret) return -1;\r
+\r
+      string = unformatted;\r
+    }\r
+    else {\r
+      /*\r
+        No existing environment.\r
+        We can't remove from an empty environment so just treat an add\r
+        operation as setting a new string.\r
+      */\r
+      if (op < 0) return 0;\r
+      op = 0;\r
+    }\r
+  }\r
+\r
+  if (! string || ! string[0]) {\r
     long error = RegDeleteValue(key, name);\r
     if (error == ERROR_SUCCESS || error == ERROR_FILE_NOT_FOUND) return 0;\r
     print_message(stderr, NSSM_MESSAGE_REGDELETEVALUE_FAILED, name, service_name, error_string(error));\r
     return -1;\r
   }\r
 \r
-  unsigned long envlen = (unsigned long) _tcslen(value->string) + 1;\r
-  TCHAR *unformatted = 0;\r
-  unsigned long newlen;\r
-  if (unformat_double_null(value->string, envlen, &unformatted, &newlen)) return -1;\r
+  if (! op) {\r
+    if (unformat_double_null(string, (unsigned long) _tcslen(string), &unformatted, &newlen)) return -1;\r
+  }\r
 \r
   if (test_environment(unformatted)) {\r
     HeapFree(GetProcessHeap(), 0, unformatted);\r