------------------------------------------------------------
revno: 1410
committer: James Hunt <[email protected]>
branch nick: upstart-setenv+getenv
timestamp: Tue 2013-01-08 15:57:31 +0000
message:
  * dbus/com.ubuntu.Upstart.xml:
    - Added UnsetEnv and ResetEnv methods.
  * init/control.c:
    - control_set_env(): Now uses job_class_environment_set() rather than
      directly manipulating job_environ array.
    - control_unset_env(): New function.
    - control_get_env(): Now calls job_class_environment_get().
    - control_list_env(): Now calls job_class_environment_get_all().
    - control_reset_env(): New function.
  * init/environ.c:
    - environ_remove(): New function.
  * init/job_class.c:
    - job_environ now static.
    - job_class_environment_reset(): New function.
    - job_class_environment_set(): New function.
    - job_class_environment_unset(): New function.
    - job_class_environment_get(): Simplified.
    - job_class_environment_get_all(): New function.
modified:
  dbus/com.ubuntu.Upstart.xml
  init/control.c
  init/environ.c
  init/environ.h
  init/job_class.c
  init/job_class.h
  init/main.c


--
lp:upstart
https://code.launchpad.net/~upstart-devel/upstart/trunk

Your team Upstart Reviewers is subscribed to branch lp:upstart.
To unsubscribe from this branch go to 
https://code.launchpad.net/~upstart-devel/upstart/trunk/+edit-subscription
=== modified file 'dbus/com.ubuntu.Upstart.xml'
--- dbus/com.ubuntu.Upstart.xml	2012-12-19 16:26:16 +0000
+++ dbus/com.ubuntu.Upstart.xml	2013-01-08 15:57:31 +0000
@@ -52,10 +52,16 @@
       <arg name="replace" type="b" direction="in" />
     </method>
 
+    <method name="UnsetEnv">
+      <arg name="name" type="s" direction="in" />
+    </method>
+
     <method name="ListEnv">
       <arg name="env" type="as" direction="out" />
     </method>
 
+    <method name="ResetEnv"/>
+
     <!-- Signals for changes to the job list -->
     <signal name="JobAdded">
       <arg name="job" type="o" />

=== modified file 'init/control.c'
--- init/control.c	2012-12-19 16:26:16 +0000
+++ init/control.c	2013-01-08 15:57:31 +0000
@@ -1126,13 +1126,12 @@
  * Returns: zero on success, negative value on raised error.
  **/
 int
-control_set_env (void           *data,
-		 NihDBusMessage *message,
-		 const char     *var,
-		 int             replace)
+control_set_env (void            *data,
+		 NihDBusMessage  *message,
+		 const char      *var,
+		 int              replace)
 {
 	Session   *session;
-	char     **ret;
 	uid_t      uid;
 
 	nih_assert (message != NULL);
@@ -1162,17 +1161,75 @@
 		return -1;
 	}
 
-	job_class_environment_init ();
-
-	ret = environ_add (&job_environ, NULL, NULL, replace, var);
-
-	if (! ret)
+	if (job_class_environment_set (var, replace) < 0)
 		nih_return_no_memory_error (-1);
 
 	return 0;
 }
 
 /**
+ * control_unset_env:
+ *
+ * @data: not used,
+ * @message: D-Bus connection and message received,
+ * @name: variable to clear from the job environment array.
+ *
+ * Implements the UnsetEnv method of the com.ubuntu.Upstart
+ * interface.
+ *
+ * Called to request Upstart remove a particular variable from the job
+ * environment array.
+ *
+ * Returns: zero on success, negative value on raised error.
+ **/
+int
+control_unset_env (void           *data,
+		   NihDBusMessage *message,
+		   const char     *name)
+{
+	Session     *session;
+	uid_t        uid;
+
+	nih_assert (message != NULL);
+	nih_assert (name);
+
+	uid = getuid ();
+
+	/* 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;
+	}
+
+	/* Disallow users from changing Upstarts environment, unless they happen to
+	 * own this process (which they may do in the test scenario and
+	 * when running Upstart as a non-privileged user).
+	 */
+	if (session && session->user != uid) {
+		nih_dbus_error_raise_printf (
+			DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
+			_("You do not have permission to modify the init environment"));
+		return -1;
+	}
+
+	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;
+}
+
+/**
  * control_get_env:
  *
  * @data: not used,
@@ -1194,8 +1251,8 @@
 		 char            **value)
 {
 	Session     *session;
+	uid_t        uid;
 	const char  *tmp;
-	uid_t        uid;
 
 	nih_assert (message != NULL);
 	nih_assert (name);
@@ -1225,9 +1282,7 @@
 		return -1;
 	}
 
-	job_class_environment_init ();
-
-	tmp = environ_get (job_environ, name);
+	tmp = job_class_environment_get (name);
 	if (! tmp)
 		goto error;
 
@@ -1260,9 +1315,9 @@
  * Returns: zero on success, negative value on raised error.
  **/
 int
-control_list_env (void            *data,
-		 NihDBusMessage   *message,
-		 char           ***env)
+control_list_env (void             *data,
+		 NihDBusMessage    *message,
+		 char            ***env)
 {
 	Session     *session;
 	uid_t        uid;
@@ -1286,11 +1341,61 @@
 		return -1;
 	}
 
-	job_class_environment_init ();
-
-	*env = job_class_environment_get (message);
+	*env = job_class_environment_get_all (message);
 	if (! *env)
 		nih_return_no_memory_error (-1);
 
 	return 0;
 }
+
+/**
+ * control_reset_env:
+ *
+ * @data: not used,
+ * @message: D-Bus connection and message received.
+ *
+ * Implements the ResetEnv method of the com.ubuntu.Upstart
+ * interface.
+ *
+ * Called to reset the environment all subsequent jobs will run in to
+ * the default minimal environment.
+ *
+ * Returns: zero on success, negative value on raised error.
+ **/
+int
+control_reset_env (void           *data,
+		 NihDBusMessage   *message)
+{
+	Session     *session;
+	uid_t        uid;
+
+	nih_assert (message != NULL);
+
+	/* Get the relevant session */
+	session = session_from_dbus (NULL, message);
+
+	uid = getuid ();
+
+	/* Chroot sessions must not be able to influence
+	 * the outside system.
+	 */
+	if (session && session->chroot) {
+		nih_warn (_("Ignoring reset env request from chroot session"));
+		return 0;
+	}
+
+	/* Disallow users from modifying Upstarts environment, unless they happen to
+	 * own this process (which they may do in the test scenario and
+	 * when running Upstart as a non-privileged user).
+	 */
+	if (session && session->user != uid) {
+		nih_dbus_error_raise_printf (
+			DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
+			_("You do not have permission to reset the init environment"));
+		return -1;
+	}
+
+	job_class_environment_reset ();
+
+	return 0;
+}

=== modified file 'init/environ.c'
--- init/environ.c	2011-06-06 17:05:11 +0000
+++ init/environ.c	2013-01-08 15:57:31 +0000
@@ -155,6 +155,67 @@
 }
 
 /**
+ * environ_remove:
+ * @env: pointer to environment table,
+ * @parent: parent object for new array,
+ * @len: length of @env,
+ * @str: string to remove.
+ *
+ * Remove @str from environment table @env. If @str does not exist in
+ * @env, the returned array will have the same contents as the original
+ * @env.
+ *
+ * Returns: new array pointer or NULL if insufficient memory (or @env is
+ * too small to reduce).
+ **/
+char **
+environ_remove (char        ***env,
+		const void    *parent,
+		size_t        *len,
+		const char    *str)
+{
+	size_t    _len;
+	size_t    keylen;
+	size_t    new_len = 0;
+	char    **e;
+	char    **new_env;
+
+	nih_assert (env);
+	nih_assert (str);
+
+	if (! len) {
+		len = &_len;
+
+		_len = 0;
+		for (e = *env; e && *e; e++)
+			_len++;
+	}
+
+	/* Can't manipulate an empty array */
+	if (*len < 1)
+		return NULL;
+
+	new_env = nih_str_array_new (NULL);
+	if (! new_env)
+		return NULL;
+
+	for (e = *env; e && *e; e++) {
+		keylen = strcspn (*e, "=");
+
+		if (! strncmp (str, *e, keylen))
+			continue;
+
+		if (! environ_add (&new_env, parent, &new_len, TRUE, *e))
+			return NULL;
+	}
+
+	*env = new_env;
+	*len = new_len;
+
+	return new_env;
+}
+
+/**
  * environ_append:
  * @env: pointer to environment table,
  * @parent: parent object for new array,

=== modified file 'init/environ.h'
--- init/environ.h	2011-06-06 17:05:11 +0000
+++ init/environ.h	2013-01-08 15:57:31 +0000
@@ -28,6 +28,9 @@
 char **       environ_add       (char ***env, const void *parent, size_t *len,
 				 int replace, const char *str)
 	__attribute__ ((warn_unused_result));
+char **       environ_remove    (char ***env, const void *parent, size_t *len,
+				 const char *str)
+	__attribute__ ((warn_unused_result));
 char **       environ_append    (char ***env, const void *parent, size_t *len,
 				 int replace, char * const *new_env)
 	__attribute__ ((warn_unused_result));

=== modified file 'init/job_class.c'
--- init/job_class.c	2012-12-19 16:26:16 +0000
+++ init/job_class.c	2013-01-08 15:57:31 +0000
@@ -91,7 +91,7 @@
  * Array of environment variables that will be set in the jobs
  * environment.
  **/
-char **job_environ = NULL;
+static char **job_environ = NULL;
 
 /**
  * job_class_init:
@@ -122,25 +122,106 @@
 }
 
 /**
+ * job_class_environment_reset:
+ *
+ * Reset the environment back to defaults.
+ **/
+void
+job_class_environment_reset (void)
+{
+	if (job_environ)
+		nih_free (job_environ);
+
+	job_environ = NULL;
+
+	job_class_environment_init ();
+}
+
+/**
+ * job_class_environment_set:
+ *
+ * @var: name[/value] pair of environment variable to set,
+ * @replace: TRUE if @name should be overwritten if already set, else
+ *  FALSE.
+ *
+ * Set specified variable in job environment.
+ *
+ * Returns: 0 on success, -1 on error.
+ **/
+int
+job_class_environment_set (const char *var, int replace)
+{
+	nih_assert (var);
+
+	job_class_environment_init ();
+
+	if (! environ_add (&job_environ, NULL, NULL, replace, var))
+		return -1;
+
+	return 0;
+}
+
+/**
+ * job_class_environment_unset:
+ *
+ * @var: name of environment variable to unset.
+ *
+ * Remove specified variable from job environment array.
+ *
+ * Returns: 0 on success, -1 on error.
+ **/
+int
+job_class_environment_unset (const char *name)
+{
+	nih_assert (name);
+
+	job_class_environment_init ();
+
+	if (! environ_remove (&job_environ, NULL, NULL, name))
+		return -1;
+
+	return 0;
+}
+
+/**
+ * job_class_environment_get_all:
+ *
+ * @parent: parent for new environment array.
+ *
+ * Obtain a copy of the entire environment a job will be provided with.
+ *
+ * Returns: Newly-allocated copy of the job environment array,
+ * or NULL on error.
+ **/
+char **
+job_class_environment_get_all (const void *parent)
+{
+	job_class_environment_init ();
+
+	return nih_str_array_copy (parent, NULL, job_environ);
+}
+
+/**
  * job_class_environment_get:
  *
- * Obtain a copy of the environment a job will be provided with.
- *
- * Returns: Newly-allocated copy of the job environment array, or NULL
- * on error.
+ * @name: name of variable to query.
+ *
+ * Determine value of variable @name in job environment.
+ *
+ * XXX: The returned value must not be freed.
+ *
+ * Returns: pointer to static storage value of @name, or NULL if @name
+ * does not exist in job environment.
+ *
  **/
-char **
-job_class_environment_get (const void *parent)
+const char *
+job_class_environment_get (const char *name)
 {
-	char   **env = NULL;
+	nih_assert (name);
 
 	job_class_environment_init ();
 
-	env = nih_str_array_copy (parent, NULL, job_environ);
-	if (! env)
-		return NULL;
-
-	return env;
+	return environ_get (job_environ, name);
 }
 
 /**

=== modified file 'init/job_class.h'
--- init/job_class.h	2012-12-19 16:26:16 +0000
+++ init/job_class.h	2013-01-08 15:57:31 +0000
@@ -226,13 +226,22 @@
 NIH_BEGIN_EXTERN
 
 extern NihHash  *job_classes;
-extern char    **job_environ;
-
 
 void        job_class_init                 (void);
 
 void        job_class_environment_init     (void);
 
+void        job_class_environment_reset    (void);
+
+int         job_class_environment_set      (const char *var, int replace);
+int         job_class_environment_unset    (const char *name);
+
+char **     job_class_environment_get_all  (const void *parent)
+	__attribute__ ((warn_unused_result, malloc));
+
+const char *job_class_environment_get      (const char *name)
+	__attribute__ ((warn_unused_result));
+
 JobClass  * job_class_new                  (const void *parent,
 					    const char *name,
 					    Session *session)
@@ -347,9 +356,6 @@
 
 void job_class_prepare_reexec (void);
 
-char ** job_class_environment_get (const void *parent)
-	__attribute__ ((warn_unused_result, malloc));
-
 NIH_END_EXTERN
 
 #endif /* INIT_JOB_CLASS_H */

=== modified file 'init/main.c'
--- init/main.c	2012-12-19 09:08:57 +0000
+++ init/main.c	2013-01-08 15:57:31 +0000
@@ -640,6 +640,7 @@
 		nih_debug ("Sessions disabled");
 
 	job_class_environment_init ();
+
 	/* Set us as the child subreaper.
 	 * This ensures that even when init doesn't run as PID 1, it'll always be
 	 * the ultimate parent of everything it spawns. */

-- 
upstart-devel mailing list
[email protected]
Modify settings or unsubscribe at: 
https://lists.ubuntu.com/mailman/listinfo/upstart-devel

Reply via email to