=== modified file 'init/control.c'
--- init/control.c	2013-01-08 15:57:31 +0000
+++ init/control.c	2013-01-08 17:27:53 +0000
@@ -1309,8 +1309,8 @@
  * Implements the ListEnv method of the com.ubuntu.Upstart
  * interface.
  *
- * Called to obtain an array of all environment variables that will be
- * set in a jobs environment.
+ * Called to obtain an unsorted array of all environment variables
+ * that will be set in a jobs environment.
  *
  * Returns: zero on success, negative value on raised error.
  **/

=== modified file 'util/initctl.c'
--- util/initctl.c	2012-03-16 21:02:13 +0000
+++ util/initctl.c	2013-01-08 17:27:53 +0000
@@ -126,6 +126,9 @@
 int check_config_action           (NihCommand *command, char * const *args);
 int usage_action                  (NihCommand *command, char * const *args);
 int notify_disk_writeable_action  (NihCommand *command, char * const *args);
+int get_env_action                (NihCommand *command, char * const *args);
+int set_env_action                (NihCommand *command, char * const *args);
+int list_env_action               (NihCommand *command, char * const *args);
 
 /**
  * use_dbus:
@@ -177,6 +180,15 @@
 int enumerate_events = FALSE;
 
 /**
+ * retain_var:
+ *
+ * If FALSE, the set-env command will replace any existing variable of
+ * the same name in the job environment table. If TRUE, the original
+ * value will be retained.
+ **/
+int retain_var = FALSE;
+
+/**
  * check_config_mode:
  *
  * If TRUE, parse all job configuration files looking for unreachable
@@ -1317,6 +1329,157 @@
 }
 
 /**
+ * get_env_action:
+ * @command: NihCommand invoked,
+ * @args: command-line arguments.
+ *
+ * This function is called for the "get-env" command.
+ *
+ * Returns: command exit status.
+ **/
+int
+get_env_action (NihCommand *command, char * const *args)
+{
+	nih_local NihDBusProxy  *upstart = NULL;
+	nih_local char          *envvar = NULL;
+	NihError                *err;
+	char                    *name;
+
+	nih_assert (command != NULL);
+	nih_assert (args != NULL);
+
+	name = args[0];
+
+	if (! name) {
+		fprintf (stderr, _("%s: missing variable name\n"), program_name);
+		nih_main_suggest_help ();
+		return 1;
+	}
+
+	upstart = upstart_open (NULL);
+	if (! upstart)
+		return 1;
+
+	if (upstart_get_env_sync (NULL, upstart, name, &envvar) < 0)
+		goto error;
+
+	nih_message ("%s", envvar);
+
+	return 0;
+
+error:
+	err = nih_error_get ();
+	nih_error ("%s", err->message);
+	nih_free (err);
+
+	return 1;
+}
+
+/**
+ * set_env_action:
+ * @command: NihCommand invoked,
+ * @args: command-line arguments.
+ *
+ * This function is called for the "set-env" command.
+ *
+ * Returns: command exit status.
+ **/
+int
+set_env_action (NihCommand *command, char * const *args)
+{
+	nih_local NihDBusProxy  *upstart = NULL;
+	NihError                *err;
+	char                    *envvar;
+
+	nih_assert (command != NULL);
+	nih_assert (args != NULL);
+
+	envvar = args[0];
+
+	if (! envvar) {
+		fprintf (stderr, _("%s: missing variable value\n"), program_name);
+		nih_main_suggest_help ();
+		return 1;
+	}
+
+	upstart = upstart_open (NULL);
+	if (! upstart)
+		return 1;
+
+	if (upstart_set_env_sync (NULL, upstart, envvar, ! retain_var) < 0)
+		goto error;
+
+	return 0;
+error:
+	err = nih_error_get ();
+	nih_error ("%s", err->message);
+	nih_free (err);
+
+	return 1;
+}
+
+
+/**
+ * list_env_strcmp_compar:
+ *
+ * Function to sort environment variables for list_env_action().
+ **/
+static int
+list_env_strcmp_compar (const void *a, const void *b) 
+{
+	        return strcasecmp (*(char * const *)a, *(char * const *)b);
+}
+
+/**
+ * list_env_action:
+ * @command: NihCommand invoked,
+ * @args: command-line arguments.
+ *
+ * This function is called for the "list-env" command.
+ *
+ * Output is in case-insensitive lexicographically sorted order.
+ *
+ * Returns: command exit status.
+ **/
+int
+list_env_action (NihCommand *command, char * const *args)
+{
+	nih_local NihDBusProxy  *upstart = NULL;
+	nih_local char         **env = NULL;
+	char                   **e;
+	NihError                *err;
+	size_t                   len;
+
+	nih_assert (command != NULL);
+	nih_assert (args != NULL);
+
+	upstart = upstart_open (NULL);
+	if (! upstart)
+		return 1;
+
+	if (upstart_list_env_sync (NULL, upstart, &env) < 0)
+		goto error;
+
+	/* Determine array size */
+	for (len = 0; env[len]; len++)
+		;
+
+	qsort (env, len, sizeof (env[0]), list_env_strcmp_compar);
+
+	for (e = env; e && *e; e++)
+		nih_message ("%s", *e);
+
+	return 0;
+
+error:
+	err = nih_error_get ();
+	nih_error ("%s", err->message);
+	nih_free (err);
+
+	return 1;
+}
+
+/**
  * usage_action:
  * @command: NihCommand invoked,
  * @args: command-line arguments.
@@ -2492,6 +2655,17 @@
 };
 
 /**
+ * set_env_options:
+ *
+ * Command-line options accepted for the set-env command.
+ **/
+NihOption set_env_options[] = {
+	{ 'r', "retain", N_("do not replace the value of the variable if already set"),
+	  NULL, NULL, &retain_var, NULL },
+	NIH_OPTION_LAST
+};
+
+/**
  * usage_options:
  *
  * Command-line options accepted for the usage command.
@@ -2620,6 +2794,21 @@
 	     "currently available job configuration files"),
 	  NULL, check_config_options, check_config_action },
 
+	{ "get-env", N_("VARIABLE"),
+	  N_("Get job environment variable"),
+	  N_("Display the value of a job environment variable"),
+	  NULL, NULL, get_env_action },
+
+	{ "list-env", NULL,
+	  N_("List all job environment variables"),
+	  N_("Returns unsorted list of job environment variables and values"),
+	  NULL, NULL, list_env_action },
+
+	{ "set-env", N_("VARIABLE[=VALUE]"),
+	  N_("Set job environment variable"),
+	  N_("Set a job environment variable"),
+	  NULL, set_env_options, set_env_action },
+
 	{ "usage",  N_("JOB"),
 	  N_("Show job usage message if available."),
 	  N_("JOB is the name of the job which usage is to be shown.\n" ),

