James Hunt has proposed merging lp:~jamesodhunt/upstart/bug-1324096 into 
lp:upstart.

Requested reviews:
  Upstart Reviewers (upstart-reviewers)
Related bugs:
  Bug #1324096 in upstart (Ubuntu): "dbus call needed to set multiple 
environment variables in a single pass"
  https://bugs.launchpad.net/ubuntu/+source/upstart/+bug/1324096

For more details, see:
https://code.launchpad.net/~jamesodhunt/upstart/bug-1324096/+merge/221743
-- 
https://code.launchpad.net/~jamesodhunt/upstart/bug-1324096/+merge/221743
Your team Upstart Reviewers is requested to review the proposed merge of 
lp:~jamesodhunt/upstart/bug-1324096 into lp:upstart.
=== modified file 'ChangeLog'
--- ChangeLog	2014-05-09 15:23:36 +0000
+++ ChangeLog	2014-06-04 15:33:50 +0000
@@ -1,3 +1,37 @@
+2014-06-04  James Hunt  <james.h...@ubuntu.com>
+
+	* dbus/com.ubuntu.Upstart.xml: Renamed SetEnvMulti to SetEnvList and
+	  UnsetEnvMulti to UnsetEnvList for clarity.
+	* init/control.c:
+	  - control_set_env_list(): Renamed from control_set_env_multi().
+	  - control_unset_env_list(): Renamed from control_unset_env_multi().
+	  - control_unset_env(): Actually make it call control_unset_env_list().
+	* util/initctl.c: Updated to call renamed functions.
+
+2014-06-02  James Hunt  <james.h...@ubuntu.com>
+
+	* dbus/com.ubuntu.Upstart.xml: Added 'SetEnvMulti' and 'UnsetEnvMulti'
+	  methods to allow multiple job environment variables to be
+	  set/unset simultaneously (LP: #1324096).
+	* init/control.c:
+	  - control_set_env_multi(): Implementation for 'SetEnvMulti'.
+	  - control_set_env(): Retained 'SetEnv' implementation that now calls
+	    control_set_env_multi().
+	  - control_unset_env_multi(): Implementation for 'UnSetEnvMulti'.
+	* util/initctl.c:
+	  - set_env_action(): Updated to call set_env_multi_sync().
+	  - unset_env_action(): Updated to call unset_env_multi_sync().
+	* util/man/initctl.8: Updated to document ability for 'set-env' and
+	  'unset-env' to set and unset multiple variables simultaneously.
+	* util/tests/test_initctl.c: Added new tests:
+	  - "multiple set-env in 'name=value' form"
+	  - "multiple set-env in 'name=' form"
+	  - "multiple set-env in 'name' form"
+	  - "set-env for multiple already set variables"
+	  - "set-env with multiple variables, some already set"
+	  - "set-env with multiple variables in different forms"
+	  - "set-env --retain with multiple variables, some already set"
+
 2014-05-09  Dimitri John Ledkov  <x...@ubuntu.com>
 
 	* util/reboot.c: only use rebootcommand code path in runlevels 0,

=== modified file 'dbus/com.ubuntu.Upstart.xml'
--- dbus/com.ubuntu.Upstart.xml	2013-10-25 13:49:49 +0000
+++ dbus/com.ubuntu.Upstart.xml	2014-06-04 15:33:50 +0000
@@ -48,17 +48,30 @@
       <arg name="value" type="s" direction="out" />
     </method>
 
+    <!-- Deprecated - use SetEnvList instead -->
     <method name="SetEnv">
       <arg name="job_details" type="as" direction="in" />
       <arg name="var" type="s" direction="in" />
       <arg name="replace" type="b" direction="in" />
     </method>
 
+    <method name="SetEnvList">
+      <arg name="job_details" type="as" direction="in" />
+      <arg name="vars" type="as" direction="in" />
+      <arg name="replace" type="b" direction="in" />
+    </method>
+
+    <!-- Deprecated - use UnsetEnvList instead -->
     <method name="UnsetEnv">
       <arg name="job_details" type="as" direction="in" />
       <arg name="name" type="s" direction="in" />
     </method>
 
+    <method name="UnsetEnvList">
+      <arg name="job_details" type="as" direction="in" />
+      <arg name="name" type="as" direction="in" />
+    </method>
+
     <method name="ListEnv">
       <arg name="job_details" type="as" direction="in" />
       <arg name="env" type="as" direction="out" />

=== modified file 'init/control.c'
--- init/control.c	2014-03-06 15:21:54 +0000
+++ init/control.c	2014-06-04 15:33:50 +0000
@@ -1253,6 +1253,119 @@
 }
 
 /**
+ * control_set_env_list:
+ *
+ * @data: not used,
+ * @message: D-Bus connection and message received,
+ * @job_details: name and instance of job to apply operation to,
+ * @vars: array of name[/value] pairs of environment variables to set,
+ * @replace: TRUE if @name should be overwritten if already set, else
+ *  FALSE.
+ *
+ * Implements the SetEnvList method of the com.ubuntu.Upstart
+ * interface.
+ *
+ * Called to request Upstart store one or more name/value pairs.
+ *
+ * If @job_details is empty, change will be applied to all job
+ * environments, else only apply changes to specific job environment
+ * encoded within @job_details.
+ *
+ * Returns: zero on success, negative value on raised error.
+ **/
+int
+control_set_env_list (void            *data,
+		      NihDBusMessage  *message,
+		      char * const    *job_details,
+		      char * const    *vars,
+		      int              replace)
+{
+	Session         *session;
+	Job             *job = NULL;
+	char            *job_name = NULL;
+	char            *instance = NULL;
+	char * const    *var;
+
+	nih_assert (message);
+	nih_assert (job_details);
+	nih_assert (vars);
+
+	if (! control_check_permission (message)) {
+		nih_dbus_error_raise_printf (
+			DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
+			_("You do not have permission to modify job environment"));
+		return -1;
+	}
+
+	if (job_details[0]) {
+		job_name = job_details[0];
+
+		/* this can be a null value */
+		instance = job_details[1];
+	} else if (getpid () == 1) {
+		nih_dbus_error_raise_printf (
+			DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
+			_("Not permissible to modify PID 1 job environment"));
+		return -1;
+	}
+
+	/* Verify that job name is valid */
+	if (job_name && ! strlen (job_name)) {
+		nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
+					     _("Job may not be empty string"));
+		return -1;
+	}
+
+	/* Get the relevant session */
+	session = session_from_dbus (NULL, message);
+
+	/* Chroot sessions must not be able to influence
+	 * the outside system.
+	 */
+	if (session && session->chroot) {
+		nih_warn (_("Ignoring set env request from chroot session"));
+		return 0;
+	}
+
+	/* Lookup the job */
+	control_get_job (session, job, job_name, instance);
+
+	for (var = vars; var && *var; var++) {
+		nih_local char *envvar = NULL;
+
+		if (! *var) {
+			nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
+					_("Variable may not be empty string"));
+			return -1;
+		}
+
+		/* If variable does not contain a delimiter, add one to ensure
+		 * it gets entered into the job environment table. Without the
+		 * delimiter, the variable will be silently ignored unless it's
+		 * already set in inits environment. But in that case there is
+		 * no point in setting such a variable to its already existing
+		 * value.
+		 */
+		if (! strchr (*var, '=')) {
+			envvar = NIH_MUST (nih_sprintf (NULL, "%s=", *var));
+		} else {
+			envvar = NIH_MUST (nih_strdup (NULL, *var));
+		}
+
+		if (job) {
+			/* Modify job-specific environment */
+			nih_assert (job->env);
+
+			NIH_MUST (environ_add (&job->env, job, NULL, replace, envvar));
+		} else if (job_class_environment_set (envvar, replace) < 0) {
+			nih_return_no_memory_error (-1);
+		}
+	}
+
+	return 0;
+}
+
+/**
  * control_set_env:
  *
  * @data: not used,
@@ -1280,14 +1393,46 @@
 		 const char      *var,
 		 int              replace)
 {
+	nih_local char **vars = NULL;
+	
+	vars = NIH_MUST (nih_str_array_new (NULL));
+
+	NIH_MUST (nih_str_array_add (&vars, NULL, NULL, var));
+
+	return control_set_env_list (data, message, job_details, vars, replace);
+}
+
+/**
+ * control_unset_env_list:
+ *
+ * @data: not used,
+ * @message: D-Bus connection and message received,
+ * @job_details: name and instance of job to apply operation to,
+ * @names: array of variables to clear from the job environment array.
+ *
+ * Implements the UnsetEnvList method of the com.ubuntu.Upstart
+ * interface.
+ *
+ * Called to request Upstart remove one or more variables from the job
+ * environment array.
+ *
+ * Returns: zero on success, negative value on raised error.
+ **/
+int
+control_unset_env_list (void            *data,
+			NihDBusMessage  *message,
+			char * const    *job_details,
+			char * const    *names)
+{
 	Session         *session;
 	Job             *job = NULL;
 	char            *job_name = NULL;
 	char            *instance = NULL;
-	nih_local char  *envvar = NULL;
+	char * const    *name;
 
 	nih_assert (message);
 	nih_assert (job_details);
+	nih_assert (names);
 
 	if (! control_check_permission (message)) {
 		nih_dbus_error_raise_printf (
@@ -1308,12 +1453,6 @@
 		return -1;
 	}
 
-	if (! var || ! *var) {
-		nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
-				_("Variable may not be empty string"));
-		return -1;
-	}
-
 	/* Verify that job name is valid */
 	if (job_name && ! strlen (job_name)) {
 		nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
@@ -1328,38 +1467,38 @@
 	 * the outside system.
 	 */
 	if (session && session->chroot) {
-		nih_warn (_("Ignoring set env request from chroot session"));
+		nih_warn (_("Ignoring unset env request from chroot session"));
 		return 0;
 	}
 
 	/* Lookup the job */
 	control_get_job (session, job, job_name, instance);
 
-	/* If variable does not contain a delimiter, add one to ensure
-	 * it gets entered into the job environment table. Without the
-	 * delimiter, the variable will be silently ignored unless it's
-	 * already set in inits environment. But in that case there is
-	 * no point in setting such a variable to its already existing
-	 * value.
-	 */
-	if (! strchr (var, '='))
-		envvar = NIH_MUST (nih_sprintf (NULL, "%s=", var));
-	else
-		envvar = NIH_MUST (nih_strdup (NULL, var));
-
-	if (job) {
-		/* Modify job-specific environment */
-
-		nih_assert (job->env);
-
-		NIH_MUST (environ_add (&job->env, job, NULL, replace, envvar));
-		return 0;
+	for (name = names; name && *name; name++) {
+		if (! *name) {
+			nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
+					_("Variable may not be empty string"));
+			return -1;
+		}
+
+		if (job) {
+			/* Modify job-specific environment */
+			nih_assert (job->env);
+
+			if (! environ_remove (&job->env, job, NULL, *name))
+				return -1;
+		} else if (job_class_environment_unset (*name) < 0) {
+			goto error;
+		}
 	}
 
-	if (job_class_environment_set (envvar, replace) < 0)
-		nih_return_no_memory_error (-1);
-
 	return 0;
+
+error:
+	nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
+			"%s: %s",
+			_("No such variable"), *name);
+	return -1;
 }
 
 /**
@@ -1384,81 +1523,13 @@
 		   char * const    *job_details,
 		   const char      *name)
 {
-	Session         *session;
-	Job             *job = NULL;
-	char            *job_name = NULL;
-	char            *instance = NULL;
-
-	nih_assert (message);
-	nih_assert (job_details);
-
-	if (! control_check_permission (message)) {
-		nih_dbus_error_raise_printf (
-			DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
-			_("You do not have permission to modify job environment"));
-		return -1;
-	}
-
-	if (! name || ! *name) {
-		nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
-				_("Variable may not be empty string"));
-		return -1;
-	}
-
-	if (job_details[0]) {
-		job_name = job_details[0];
-
-		/* this can be a null value */
-		instance = job_details[1];
-	} else if (getpid () == 1) {
-		nih_dbus_error_raise_printf (
-			DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
-			_("Not permissible to modify PID 1 job environment"));
-		return -1;
-	}
-
-	/* Verify that job name is valid */
-	if (job_name && ! strlen (job_name)) {
-		nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
-					     _("Job may not be empty string"));
-		return -1;
-	}
-
-	/* Get the relevant session */
-	session = session_from_dbus (NULL, message);
-
-	/* Chroot sessions must not be able to influence
-	 * the outside system.
-	 */
-	if (session && session->chroot) {
-		nih_warn (_("Ignoring unset env request from chroot session"));
-		return 0;
-	}
-
-	/* Lookup the job */
-	control_get_job (session, job, job_name, instance);
-
-	if (job) {
-		/* Modify job-specific environment */
-
-		nih_assert (job->env);
-
-		if (! environ_remove (&job->env, job, NULL, name))
-			return -1;
-
-		return 0;
-	}
-
-	if (job_class_environment_unset (name) < 0)
-		goto error;
-
-	return 0;
-
-error:
-	nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
-			"%s: %s",
-			_("No such variable"), name);
-	return -1;
+	nih_local char **names = NULL;
+	
+	names = NIH_MUST (nih_str_array_new (NULL));
+
+	NIH_MUST (nih_str_array_add (&names, NULL, NULL, name));
+
+	return control_unset_env_list (data, message, job_details, names);
 }
 
 /**

=== modified file 'init/control.h'
--- init/control.h	2014-03-06 15:21:54 +0000
+++ init/control.h	2014-06-04 15:33:50 +0000
@@ -170,6 +170,13 @@
 		     const char *address)
 	__attribute__ ((warn_unused_result));
 
+int control_set_env_multi (void           *data,
+		 NihDBusMessage *message,
+		 char * const    *job_details,
+		 char * const    *vars,
+		 int             replace)
+	__attribute__ ((warn_unused_result));
+
 int control_set_env (void           *data,
 		 NihDBusMessage *message,
 		 char * const    *job_details,
@@ -195,6 +202,12 @@
 		 char * const    *job_details)
 	__attribute__ ((warn_unused_result));
 
+int control_unset_env_multi (void            *data,
+		   NihDBusMessage  *message,
+		   char * const    *job_details,
+		   char * const    *names)
+	__attribute__ ((warn_unused_result));
+
 int control_unset_env (void            *data,
 		   NihDBusMessage  *message,
 		   char * const    *job_details,

=== modified file 'util/initctl.c'
--- util/initctl.c	2014-04-17 14:56:06 +0000
+++ util/initctl.c	2014-06-04 15:33:50 +0000
@@ -1451,7 +1451,6 @@
 {
 	nih_local NihDBusProxy  *upstart = NULL;
 	NihError                *err;
-	char                    *envvar;
 	nih_local char         **job_details = NULL;
 	int                      ret;
 
@@ -1468,14 +1467,12 @@
 	if (! job_details)
 		return 1;
 
-	envvar = args[0];
-
 	upstart = upstart_open (NULL);
 	if (! upstart)
 		return 1;
 
-	ret = upstart_set_env_sync (NULL, upstart, job_details,
-			envvar, ! retain_var);
+	ret = upstart_set_env_list_sync (NULL, upstart, job_details,
+			args, ! retain_var);
 
 	if (ret < 0)
 		goto error;
@@ -1504,15 +1501,12 @@
 {
 	nih_local NihDBusProxy  *upstart = NULL;
 	NihError                *err;
-	char                    *name;
 	nih_local char         **job_details = NULL;
 
 	nih_assert (command != NULL);
 	nih_assert (args != NULL);
 
-	name = args[0];
-
-	if (! name) {
+	if (! args[0]) {
 		fprintf (stderr, _("%s: missing variable name\n"), program_name);
 		nih_main_suggest_help ();
 		return 1;
@@ -1526,7 +1520,7 @@
 	if (! upstart)
 		return 1;
 
-	if (upstart_unset_env_sync (NULL, upstart, job_details, name) < 0)
+	if (upstart_unset_env_list_sync (NULL, upstart, job_details, args) < 0)
 		goto error;
 
 	return 0;
@@ -3247,13 +3241,13 @@
 	  &env_group, reset_env_options, reset_env_action },
 
 	{ "set-env", N_("VARIABLE[=VALUE]"),
-	  N_("Set a job environment variable."),
-	  N_("Adds or updates a variable in the job environment table."),
+	  N_("Set one or more job environment variables."),
+	  N_("Adds or updates variables in the job environment table."),
 	  &env_group, set_env_options, set_env_action },
 
 	{ "unset-env", N_("VARIABLE"),
-	  N_("Remove a job environment variable."),
-	  N_("Discards the specified variable from the job environment table."),
+	  N_("Remove one or more job environment variables."),
+	  N_("Discards variables from the job environment table."),
 	  &env_group, unset_env_options, unset_env_action },
 
 	{ "usage",  N_("JOB"),

=== modified file 'util/man/initctl.8'
--- util/man/initctl.8	2013-12-20 17:37:26 +0000
+++ util/man/initctl.8	2014-06-04 15:33:50 +0000
@@ -655,9 +655,9 @@
 .\"
 .TP
 .B set\-env
-.RI [ OPTIONS "] " VARIABLE[=VALUE]
+.RI [ OPTIONS "] " VARIABLE[=VALUE] " ..."
 
-Adds or updates a variable in a job environment table. Variables set
+Adds or updates one or more variables in a job environment table. Variables set
 in this way will apply to all the subsequently-starting processes for a
 job.
 
@@ -670,7 +670,7 @@
 .B OPTIONS
 .RS
 .IP "\fB\-r\fP, \fB\-\-retain\fP"
-If the specified variable is already set, do not modify it.
+If any of the specified variables are already set, do not modify them.
 .RE
 .RS
 .IP "\fB\-g\fP, \fB\-\-global\fP"
@@ -688,10 +688,11 @@
 .\"
 .TP
 .B unset\-env
-.RI [ OPTIONS "] " VARIABLE
+.RI [ OPTIONS "] " VARIABLE " ..."
 
-Remove the specified variable from a job environment table. If the
-variable does not already exist in the table, no change will be made.
+Remove the specified variables from a job environment table. If any of
+the variables specified do not already exist in the table, those
+variables will be ignored.
 
 This command is only permitted when running in
 .B User Session Mode.
@@ -702,7 +703,7 @@
 .B OPTIONS
 .RS
 .IP "\fB\-r\fP, \fB\-\-retain\fP"
-If the specified variable is already set, do not modify it.
+If any of the specified variables are already set, do not unset them.
 .RE
 .RS
 .IP "\fB\-g\fP, \fB\-\-global\fP"

=== modified file 'util/tests/test_initctl.c'
--- util/tests/test_initctl.c	2014-06-04 12:47:47 +0000
+++ util/tests/test_initctl.c	2014-06-04 15:33:50 +0000
@@ -16292,6 +16292,17 @@
 	TEST_EQ (line_count, 1);
 	TEST_EQ_STR (output[0], "initctl: No such variable: foo");
 
+	/* ensure unset-env (multiple variables) tolerates empty environment */
+	cmd = nih_sprintf (NULL, "%s unset-env %s %s 2>&1", get_initctl (), "foo", "bar");
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+
+	/* Although 2 variables have been specified, since neither is
+	 * set, we only expect 1 error for the first variable.
+	 */
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], "initctl: No such variable: foo");
+
 	/*******************************************************************/
 	TEST_FEATURE ("ensure job runs in empty environment");
 
@@ -16352,6 +16363,12 @@
 	nih_local char  *cmd = NULL;
 	nih_local char  *name = NULL;
 	nih_local char  *value = NULL;
+	nih_local char  *name2 = NULL;
+	nih_local char  *value2 = NULL;
+	nih_local char  *name3 = NULL;
+	nih_local char  *value3 = NULL;
+	nih_local char  *name4 = NULL;
+	nih_local char  *value4 = NULL;
 	char           **output;
 	nih_local char  *logfile = NULL;
 	size_t           line_count;
@@ -16381,6 +16398,8 @@
 
 	name = NIH_MUST (nih_strdup (NULL, "foo"));
 	value = NIH_MUST (nih_strdup (NULL, "bar"));
+	name2 = NIH_MUST (nih_strdup (NULL, "baz"));
+	value2 = NIH_MUST (nih_strdup (NULL, "qux"));
 
 	cmd = nih_sprintf (NULL, "%s set-env %s=%s 2>&1", get_initctl (),
 			name, value);
@@ -16388,25 +16407,98 @@
 	RUN_COMMAND (NULL, cmd, &output, &line_count);
 	TEST_EQ (line_count, 0);
 
-	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
-			name);
-	TEST_NE_P (cmd, NULL);
-	RUN_COMMAND (NULL, cmd, &output, &line_count);
-	TEST_EQ (line_count, 1);
-	TEST_EQ_STR (output[0], value);
-	nih_free (output);
-
-	cmd = nih_sprintf (NULL, "%s unset-env %s 2>&1", get_initctl (), name);
-	TEST_NE_P (cmd, NULL);
-	RUN_COMMAND (NULL, cmd, &output, &line_count);
-	TEST_EQ (line_count, 0);
-
-	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
-			name);
-	TEST_NE_P (cmd, NULL);
-	RUN_COMMAND (NULL, cmd, &output, &line_count);
-	TEST_EQ (line_count, 1);
-	TEST_EQ_STR (output[0], "initctl: No such variable: foo");
+	cmd = nih_sprintf (NULL, "%s set-env %s=%s 2>&1", get_initctl (),
+			name2, value2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], value);
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], value2);
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s unset-env %s %s 2>&1", get_initctl (), name, name2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], "initctl: No such variable: foo");
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], "initctl: No such variable: baz");
+	nih_free (output);
+
+	/*******************************************************************/
+	TEST_FEATURE ("multiple set-env in 'name=value' form");
+
+	name = NIH_MUST (nih_strdup (NULL, "foo"));
+	value = NIH_MUST (nih_strdup (NULL, "bar"));
+	name2 = NIH_MUST (nih_strdup (NULL, "baz"));
+	value2 = NIH_MUST (nih_strdup (NULL, "qux"));
+
+	cmd = nih_sprintf (NULL, "%s set-env %s=%s %s=%s 2>&1", get_initctl (),
+			name, value, name2, value2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], value);
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], value2);
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s unset-env %s %s 2>&1", get_initctl (), name, name2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], "initctl: No such variable: foo");
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], "initctl: No such variable: baz");
 	nih_free (output);
 
 	/*******************************************************************/
@@ -16447,6 +16539,67 @@
 	nih_free (output);
 
 	/*******************************************************************/
+	TEST_FEATURE ("multiple set-env in 'name=' form");
+
+	name = NIH_MUST (nih_strdup (NULL, "foo"));
+	name2 = NIH_MUST (nih_strdup (NULL, "baz"));
+
+	cmd = nih_sprintf (NULL, "%s set-env %s= %s= 2>&1", get_initctl (),
+			name, name2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+
+	/* nul string value expected if none specified when set */
+	TEST_EQ_STR (output[0], "");
+
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+
+	/* nul string value expected if none specified when set */
+	TEST_EQ_STR (output[0], "");
+
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s unset-env %s 2>&1", get_initctl (), name);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], "initctl: No such variable: foo");
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s unset-env %s 2>&1", get_initctl (), name2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], "initctl: No such variable: baz");
+	nih_free (output);
+
+	/*******************************************************************/
 	TEST_FEATURE ("set-env in 'name' form");
 
 	name = NIH_MUST (nih_strdup (NULL, "foo"));
@@ -16483,6 +16636,68 @@
 	nih_free (output);
 
 	/*******************************************************************/
+	TEST_FEATURE ("multiple set-env in 'name' form");
+
+	name = NIH_MUST (nih_strdup (NULL, "foo"));
+	name2 = NIH_MUST (nih_strdup (NULL, "baz"));
+
+	cmd = nih_sprintf (NULL, "%s set-env %s %s 2>&1", get_initctl (),
+			name, name2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+
+	TEST_EQ (line_count, 1);
+
+	/* nul string value expected if none specified when set */
+	TEST_EQ_STR (output[0], "");
+
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+
+	TEST_EQ (line_count, 1);
+
+	/* nul string value expected if none specified when set */
+	TEST_EQ_STR (output[0], "");
+
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s unset-env %s 2>&1", get_initctl (), name);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], "initctl: No such variable: foo");
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s unset-env %s 2>&1", get_initctl (), name2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], "initctl: No such variable: baz");
+	nih_free (output);
+
+	/*******************************************************************/
 	TEST_FEATURE ("set-env for already set variable");
 
 	name = NIH_MUST (nih_strdup (NULL, "foo"));
@@ -16536,6 +16751,344 @@
 	nih_free (output);
 
 	/*******************************************************************/
+	TEST_FEATURE ("set-env for multiple already set variables");
+
+	name = NIH_MUST (nih_strdup (NULL, "foo"));
+	value = NIH_MUST (nih_strdup (NULL, "bar"));
+	name2 = NIH_MUST (nih_strdup (NULL, "baz"));
+	value2 = NIH_MUST (nih_strdup (NULL, "qux"));
+
+	/* set them */
+	cmd = nih_sprintf (NULL, "%s set-env %s=%s %s=%s 2>&1", get_initctl (),
+			name, value, name2, value2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+
+	/* check them */
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+
+	TEST_EQ_STR (output[0], value);
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+
+	TEST_EQ_STR (output[0], value2);
+	nih_free (output);
+
+	/* set them again */
+	cmd = nih_sprintf (NULL, "%s set-env %s=%s %s=%s 2>&1", get_initctl (),
+			name, value, name2, value2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+
+	/* check again */
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+
+	TEST_EQ_STR (output[0], value);
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+
+	TEST_EQ_STR (output[0], value2);
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s unset-env %s 2>&1", get_initctl (), name);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+
+	cmd = nih_sprintf (NULL, "%s unset-env %s 2>&1", get_initctl (), name2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], "initctl: No such variable: foo");
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], "initctl: No such variable: baz");
+	nih_free (output);
+
+	/*******************************************************************/
+	TEST_FEATURE ("set-env with multiple variables, some already set");
+
+	name = NIH_MUST (nih_strdup (NULL, "foo"));
+	value = NIH_MUST (nih_strdup (NULL, "bar"));
+	name2 = NIH_MUST (nih_strdup (NULL, "baz"));
+	value2 = NIH_MUST (nih_strdup (NULL, "qux"));
+	name3 = NIH_MUST (nih_strdup (NULL, "hello"));
+	value3 = NIH_MUST (nih_strdup (NULL, "world"));
+	name4 = NIH_MUST (nih_strdup (NULL, "bonjour"));
+	value4 = NIH_MUST (nih_strdup (NULL, "tout le monde"));
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name3);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], "initctl: No such variable: hello");
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name4);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], "initctl: No such variable: bonjour");
+	nih_free (output);
+
+	/* set 2 variables initially */
+	cmd = nih_sprintf (NULL, "%s set-env %s='%s' %s='%s' 2>&1", get_initctl (),
+			name3, value3, name4, value4);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+
+	/* check them */
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name3);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+
+	TEST_EQ_STR (output[0], value3);
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name4);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+
+	TEST_EQ_STR (output[0], value4);
+	nih_free (output);
+
+	/* set them all */
+	cmd = nih_sprintf (NULL, "%s set-env %s='%s' %s='%s' %s='%s' %s='%s' 2>&1", get_initctl (),
+			name, value, name3, value3, name2, value2, name4, value4);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+
+	/* check again */
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], value);
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], value2);
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name3);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], value3);
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name4);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], value4);
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s unset-env %s 2>&1", get_initctl (), name);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+
+	cmd = nih_sprintf (NULL, "%s unset-env %s 2>&1", get_initctl (), name2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+
+	cmd = nih_sprintf (NULL, "%s unset-env %s 2>&1", get_initctl (), name3);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+
+	cmd = nih_sprintf (NULL, "%s unset-env %s 2>&1", get_initctl (), name4);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], "initctl: No such variable: foo");
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], "initctl: No such variable: baz");
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name3);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], "initctl: No such variable: hello");
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name4);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], "initctl: No such variable: bonjour");
+	nih_free (output);
+
+	/*******************************************************************/
+	TEST_FEATURE ("set-env with multiple variables in different forms");
+
+	name = NIH_MUST (nih_strdup (NULL, "foo"));
+	value = NIH_MUST (nih_strdup (NULL, "bar"));
+	name2 = NIH_MUST (nih_strdup (NULL, "baz"));
+	value2 = NIH_MUST (nih_strdup (NULL, "qux"));
+
+	name3 = NIH_MUST (nih_strdup (NULL, "name-equals"));
+	name4 = NIH_MUST (nih_strdup (NULL, "just-name"));
+
+	/* set them all */
+	cmd = nih_sprintf (NULL, "%s set-env %s='%s' %s= %s %s='%s' 2>&1", get_initctl (),
+			name, value, name3, name4, name2, value2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], value);
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], value2);
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name3);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+
+	/* nul string value expected if none specified when set */
+	TEST_EQ_STR (output[0], "");
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name4);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+
+	/* nul string value expected if none specified when set */
+	TEST_EQ_STR (output[0], "");
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s unset-env %s 2>&1", get_initctl (), name);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+
+	cmd = nih_sprintf (NULL, "%s unset-env %s 2>&1", get_initctl (), name2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+
+	cmd = nih_sprintf (NULL, "%s unset-env %s 2>&1", get_initctl (), name3);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+
+	cmd = nih_sprintf (NULL, "%s unset-env %s 2>&1", get_initctl (), name4);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], "initctl: No such variable: foo");
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], "initctl: No such variable: baz");
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name3);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], "initctl: No such variable: name-equals");
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name4);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], "initctl: No such variable: just-name");
+	nih_free (output);
+
+	/*******************************************************************/
 	TEST_FEATURE ("set-env --retain");
 
 	name = NIH_MUST (nih_strdup (NULL, "foo"));
@@ -16587,6 +17140,151 @@
 	nih_free (output);
 
 	/*******************************************************************/
+	TEST_FEATURE ("set-env --retain with multiple variables, some already set");
+
+	name = NIH_MUST (nih_strdup (NULL, "foo"));
+	value = NIH_MUST (nih_strdup (NULL, "bar"));
+	name3 = NIH_MUST (nih_strdup (NULL, "hello"));
+	value3 = NIH_MUST (nih_strdup (NULL, "world"));
+	name4 = NIH_MUST (nih_strdup (NULL, "bonjour"));
+	value4 = NIH_MUST (nih_strdup (NULL, "tout le monde"));
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name3);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], "initctl: No such variable: hello");
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name4);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], "initctl: No such variable: bonjour");
+	nih_free (output);
+
+	/* set 2 variables initially */
+	cmd = nih_sprintf (NULL, "%s set-env %s='%s' %s='%s' 2>&1", get_initctl (),
+			name3, value3, name4, value4);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+
+	/* check them */
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name3);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+
+	TEST_EQ_STR (output[0], value3);
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name4);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+
+	TEST_EQ_STR (output[0], value4);
+	nih_free (output);
+
+	/* set them all */
+	cmd = nih_sprintf (NULL, "%s set-env --retain %s='%s' %s='%s' %s='%s' %s='%s' 2>&1",
+			get_initctl (), name, value, name3, "AAAA", name2, value2, name4, "BBBB");
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+
+	/* check that the original values did *NOT* change */
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name3);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], value3);
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name4);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], value4);
+	nih_free (output);
+
+	/* Check that the initially-not set variables were set */
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], value);
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], value2);
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s unset-env %s 2>&1", get_initctl (), name);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+
+	cmd = nih_sprintf (NULL, "%s unset-env %s 2>&1", get_initctl (), name2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+
+	cmd = nih_sprintf (NULL, "%s unset-env %s 2>&1", get_initctl (), name3);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+
+	cmd = nih_sprintf (NULL, "%s unset-env %s 2>&1", get_initctl (), name4);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 0);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], "initctl: No such variable: foo");
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name2);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], "initctl: No such variable: baz");
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name3);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], "initctl: No such variable: hello");
+	nih_free (output);
+
+	cmd = nih_sprintf (NULL, "%s get-env %s 2>&1", get_initctl (),
+			name4);
+	TEST_NE_P (cmd, NULL);
+	RUN_COMMAND (NULL, cmd, &output, &line_count);
+	TEST_EQ (line_count, 1);
+	TEST_EQ_STR (output[0], "initctl: No such variable: bonjour");
+	nih_free (output);
+
+	/*******************************************************************/
 	TEST_FEATURE ("set-env with space within value and trailing tab");
 
 	name = NIH_MUST (nih_strdup (NULL, "foo"));
@@ -17422,8 +18120,10 @@
 	test_version_action ();
 	test_log_priority_action ();
 	test_usage ();
+
 	test_job_env ();
 	test_reexec ();
+
 	test_list_sessions ();
 	if (have_timed_waitpid ()) {
 		test_quiesce ();

-- 
upstart-devel mailing list
upstart-devel@lists.ubuntu.com
Modify settings or unsubscribe at: 
https://lists.ubuntu.com/mailman/listinfo/upstart-devel

Reply via email to