Dmitrijs Ledkovs has proposed merging lp:~xnox/upstart/xdg into lp:upstart.

Requested reviews:
  Upstart Reviewers (upstart-reviewers)

For more details, see:
https://code.launchpad.net/~xnox/upstart/xdg/+merge/139943

https://wiki.ubuntu.com/FoundationsTeam/Specs/RaringUpstartUserSessions#Configuration_Files_for_User_Jobs

When we get `--user' option, we will need to setup configuration file sources.
This branch implements get_user_upstart_dirs, which returns an array of paths 
in priority order.
It doesn't implement the location under "/usr" as the name hasn't been agreed 
yet, but it will be easy to add later.

Currently it relies on environment variable HOME to be set.
Depending on how we implement, --user, we may have environ object with 
HOME,XDG_CONFIG_HOME,XDG_CONFIG_DIRS variables in it, then we can use 
environ_expand instead of current processing.

I am not entirely sure about the tests, especially about TEST_ALLOC_FAIL (see 
comments in the test file).

Under valgrind get_user_upstart_dirs seems to leak memory, not sure if I am 
using api form nih/strings.h correctly there.

Next, I'll work on .override processing from any-dir, but exclude those beyond 
the jobfile itself. 
-- 
https://code.launchpad.net/~xnox/upstart/xdg/+merge/139943
Your team Upstart Reviewers is requested to review the proposed merge of 
lp:~xnox/upstart/xdg into lp:upstart.
=== modified file 'ChangeLog'
--- ChangeLog	2012-12-11 13:59:01 +0000
+++ ChangeLog	2012-12-14 16:07:48 +0000
@@ -1,3 +1,8 @@
+2012-12-14  Dmitrijs Ledkovs  <[email protected]>
+
+	* init/xdg.c: Add functions to construct user session config
+	source paths.
+
 2012-12-11  James Hunt  <[email protected]>
 
 	* init/Makefile.am: Add explicit -lrt for tests (LP: #1088863)

=== modified file 'init/Makefile.am'
--- init/Makefile.am	2012-12-11 13:59:01 +0000
+++ init/Makefile.am	2012-12-14 16:07:48 +0000
@@ -56,6 +56,7 @@
 	parse_conf.c parse_conf.h \
 	conf.c conf.h \
 	control.c control.h \
+	xdg.c xdg.h \
 	errors.h
 nodist_init_SOURCES = \
 	$(com_ubuntu_Upstart_OUTPUTS) \
@@ -134,7 +135,6 @@
 	$(TEST_DATA_DIR)/upstart-1.6.json
 
 EXTRA_DIST = init.supp $(TEST_DATA_FILES)
-	
 
 test_util_SOURCES = \
 	tests/test_util.c tests/test_util.h
@@ -154,6 +154,7 @@
 	test_parse_job \
 	test_parse_conf \
 	test_conf \
+	test_xdg \
 	test_control
 
 check_PROGRAMS = $(TESTS)
@@ -338,6 +339,13 @@
 	$(JSON_LIBS) \
 	-lrt
 
+test_xdg_SOURCES = tests/test_xdg.c
+test_xdg_LDADD = \
+	xdg.o \
+	environ.o \
+	$(NIH_LIBS) \
+	-lrt
+
 test_control_SOURCES = tests/test_control.c
 test_control_LDADD = \
 	system.o environ.o process.o \

=== modified file 'init/paths.h'
--- init/paths.h	2012-09-10 07:50:32 +0000
+++ init/paths.h	2012-12-14 16:07:48 +0000
@@ -96,6 +96,15 @@
 #define CONFDIR_ENV "UPSTART_CONFDIR"
 #endif
 
+/**
+ * INIT_XDG_SUBDIR:
+ *
+ * This is the name of the sub folder we will use when constructing
+ * config source dirs with XDG compliant folders.
+ **/
+#ifndef INIT_XDG_SUBDIR
+#define INIT_XDG_SUBDIR "upstart"
+#endif
 
 /**
  * SHELL:

=== added file 'init/tests/test_xdg.c'
--- init/tests/test_xdg.c	1970-01-01 00:00:00 +0000
+++ init/tests/test_xdg.c	2012-12-14 16:07:48 +0000
@@ -0,0 +1,311 @@
+/* upstart
+ *
+ * test_xdg.c - test suite for init/xdg.c
+ *
+ * Copyright © 2012 Canonical Ltd.
+ * Author: Dmitrijs Ledkovs <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <nih/string.h>
+#include <nih/test.h>
+
+#include <stdlib.h>
+#include <limits.h>
+
+#include "xdg.h"
+
+void
+test_get_home_subdir (void)
+{
+	char    dirname[PATH_MAX];
+	char       *dir;
+	char * expected=NULL;
+
+	TEST_FUNCTION ("get_home_subdir");
+
+	TEST_FEATURE ("with HOME not set");
+	TEST_EQ (unsetenv ("HOME"), 0);
+
+	TEST_ALLOC_FAIL {
+		dir = get_home_subdir ("test");
+		TEST_EQ_P (dir, NULL);
+	}
+
+	TEST_FEATURE ("with HOME set");
+	TEST_FILENAME (dirname);
+	TEST_EQ (setenv ("HOME", dirname, 1), 0);
+
+	TEST_ALLOC_FAIL {
+		TEST_ALLOC_SAFE {
+			dir = NULL;
+			expected = NIH_MUST (nih_sprintf (NULL, "%s/test", dirname));
+		}
+
+		dir = get_home_subdir ("test");
+
+		/* if I inverted the below if statement and write it
+                 *  as "if ( test_alloc_failed )" and change around
+                 *  the branches respectively the unit test fails. Why
+                 *  is that?
+		 */
+		if ( ! test_alloc_failed ) {
+			TEST_EQ_STR (dir, expected);
+			nih_free (dir);
+		} else {
+			TEST_EQ_P (dir, NULL);
+		}
+
+		if (expected)
+			nih_free (expected);
+	}
+}
+
+void
+test_get_config_home (void)
+{
+	char   dirname[PATH_MAX];
+	char * outname;
+	char * expected;
+
+	TEST_FUNCTION ("xdg_get_config_home");
+
+	TEST_FEATURE ("with HOME set and without environment override");
+	TEST_FILENAME (dirname);
+	TEST_EQ (setenv ("HOME", dirname, 1), 0);
+	TEST_EQ (unsetenv ("XDG_CONFIG_HOME"), 0);
+
+	TEST_ALLOC_FAIL {
+		TEST_ALLOC_SAFE {
+			expected = NIH_MUST (nih_sprintf (NULL, "%s/.config", dirname));
+		}
+
+		outname = NULL;
+		outname = xdg_get_config_home ();
+
+		/* Something strange is going on.
+                 * I am expected the failed alloc branch
+                 * to pass TEST_EQ_P (outname, NULL)
+                 */
+
+		if (! test_alloc_failed)
+			TEST_EQ_STR (outname, expected);
+		else
+			TEST_EQ_STR (outname, expected);
+
+		if (outname)
+			nih_free (outname);
+
+		nih_free(expected);
+	}
+
+	TEST_FEATURE ("with HOME set and with empty environment override");
+	TEST_EQ (setenv ("XDG_CONFIG_HOME", "", 1), 0);
+
+	TEST_ALLOC_FAIL {
+		TEST_ALLOC_SAFE {
+			expected = NIH_MUST (nih_sprintf (NULL, "%s/.config", dirname));
+			outname = NULL;
+			/* the below call should be in _FAIL scope */
+			outname = xdg_get_config_home();
+		}
+
+		if (test_alloc_failed)
+			TEST_EQ_P (outname, NULL);
+		else {
+			TEST_EQ_STR (outname, expected);
+		}
+		if (outname)
+			nih_free (outname);
+
+		nih_free(expected);
+
+	}
+
+	TEST_FEATURE ("with HOME set and with environment override");
+	expected = NIH_MUST (nih_strdup (NULL, "/home/me/.config-test"));
+	TEST_EQ (setenv ("XDG_CONFIG_HOME", expected, 1), 0);
+
+	TEST_ALLOC_FAIL {
+		TEST_ALLOC_SAFE {
+			outname = NULL;
+			/* the below call should be in _FAIL scope */
+			outname = xdg_get_config_home();
+		}
+
+		if (test_alloc_failed)
+			TEST_EQ_P (outname, NULL);
+		else {
+			TEST_EQ_STR (outname, expected);
+		}
+		if (outname)
+			nih_free (outname);
+
+	}
+
+
+	TEST_FEATURE ("without HOME set and with environment override");
+	TEST_EQ (unsetenv ("HOME"), 0);
+
+	TEST_ALLOC_FAIL {
+		TEST_ALLOC_SAFE {
+			outname = NULL;
+			/* the below call should be in _FAIL scope */
+			outname = xdg_get_config_home();
+		}
+
+		if (test_alloc_failed)
+			TEST_EQ_P (outname, NULL);
+		else {
+			TEST_EQ_STR (outname, expected);
+		}
+		if (outname)
+			nih_free (outname);
+	}
+
+	nih_free(expected);
+
+	TEST_FEATURE ("without HOME set and with empty environment override");
+	TEST_EQ (setenv ("XDG_CONFIG_HOME", "", 1), 0);
+
+	TEST_ALLOC_FAIL {
+		outname = NULL;
+		outname = xdg_get_config_home();
+		TEST_EQ_P (outname, NULL);
+	}
+
+	TEST_FEATURE ("without HOME set and without environment override");
+	TEST_EQ (unsetenv ("XDG_CONFIG_HOME"), 0);
+	TEST_ALLOC_FAIL {
+		outname = NULL;
+		outname = xdg_get_config_home();
+		TEST_EQ_P (outname, NULL);
+	}
+}
+
+void
+test_get_config_dirs (void)
+{
+	char   **dirs = NULL;
+
+	TEST_FUNCTION ("xdg_get_config_dirs");
+	TEST_FEATURE ("without environment override set");
+	TEST_EQ (unsetenv ("XDG_CONFIG_DIRS"), 0);
+
+	TEST_ALLOC_FAIL {
+		dirs = xdg_get_config_dirs();
+
+		if (! test_alloc_failed) {
+			TEST_EQ_STR (dirs[0], "/etc/xdg");
+			TEST_EQ (dirs[1], NULL);
+			nih_free (dirs);
+		}
+	}
+
+	TEST_FEATURE ("with empty environment override");
+	TEST_EQ (setenv ("XDG_CONFIG_DIRS", "", 1), 0);
+	TEST_ALLOC_FAIL {
+		dirs = xdg_get_config_dirs();
+
+		if (! test_alloc_failed) {
+			TEST_EQ_STR (dirs[0], "/etc/xdg");
+			TEST_EQ (dirs[1], NULL);
+			nih_free (dirs);
+		}
+	}
+
+	TEST_FEATURE ("with environment override set to single path");
+	TEST_EQ (setenv ("XDG_CONFIG_DIRS", "/etc/xdg/xdg-test", 1), 0);
+	TEST_ALLOC_FAIL {
+		dirs = xdg_get_config_dirs();
+
+		if (! test_alloc_failed) {
+			TEST_EQ_STR (dirs[0], "/etc/xdg/xdg-test");
+			TEST_EQ (dirs[1], NULL);
+			nih_free (dirs);
+		}
+	}
+
+	TEST_FEATURE ("with environment override set to multiple paths");
+	TEST_FEATURE ("with environment override set to single path");
+	TEST_EQ (setenv ("XDG_CONFIG_DIRS", "/etc/xdg/xdg-test:/etc/xdg/xdg-other", 1), 0);
+	TEST_ALLOC_FAIL {
+		dirs = xdg_get_config_dirs();
+
+		if (! test_alloc_failed) {
+			TEST_EQ_STR (dirs[0], "/etc/xdg/xdg-test");
+			TEST_EQ_STR (dirs[1], "/etc/xdg/xdg-other");
+			TEST_EQ (dirs[2], NULL);
+			nih_free (dirs);
+		}
+	}
+}
+
+void
+test_get_user_upstart_dirs (void)
+{
+	char   dirname[PATH_MAX];
+	char      ** dirs = NULL;
+	char       * path = NULL;
+	char  ** expected = NULL;
+
+	/* Currently only one test for "typical" output.
+         * Not sure what else to test here.
+         */
+	TEST_FUNCTION ("get_user_upstart_dirs");
+
+	TEST_FEATURE ("with HOME set");
+	TEST_FILENAME (dirname);
+	TEST_EQ (setenv ("HOME", dirname, 1), 0);
+	TEST_EQ (unsetenv ("XDG_CONFIG_HOME"), 0);
+	TEST_EQ (unsetenv ("XDG_CONFIG_DIRS"), 0);
+
+	TEST_ALLOC_FAIL {
+		TEST_ALLOC_SAFE {
+			dirs = NULL;
+			expected = nih_str_array_new (NULL);
+			path = NIH_MUST (nih_sprintf (NULL, "%s/.config/upstart", dirname));
+			assert (nih_str_array_add (&expected, NULL, NULL, path));
+			nih_free(path);
+			path = NIH_MUST (nih_sprintf (NULL, "%s/.init", dirname));
+			assert (nih_str_array_add (&expected, NULL, NULL, path));
+			nih_free(path);
+		}
+
+		dirs = get_user_upstart_dirs ();
+
+		if (! test_alloc_failed) {
+			TEST_EQ_STR (dirs[0], expected[0]);
+			TEST_EQ_STR (dirs[1], expected[1]);
+			TEST_EQ_STR (dirs[2], "/etc/xdg/upstart");
+			TEST_EQ (dirs[3], NULL);
+			nih_free (dirs);
+		}
+		nih_free(expected);
+	}
+
+}
+
+int
+main (int   argc,
+      char *argv[])
+{
+	test_get_home_subdir ();
+	test_get_config_home ();
+	test_get_config_dirs ();
+	test_get_user_upstart_dirs ();
+
+	return 0;
+}

=== added file 'init/xdg.c'
--- init/xdg.c	1970-01-01 00:00:00 +0000
+++ init/xdg.c	2012-12-14 16:07:48 +0000
@@ -0,0 +1,144 @@
+/* upstart
+ *
+ * xdg.c - XDG compliant path constructor
+ *
+ * Copyright © 2012 Canonical Ltd.
+ * Author: Dmitrijs Ledkovs <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+
+#include <nih/alloc.h>
+#include <nih/logging.h>
+#include <nih/string.h>
+
+#include "paths.h"
+#include "xdg.h"
+
+/**
+ * get_home_subdir:
+ *
+ * Construct path to directory in user's HOME dir.
+ */
+
+char *
+get_home_subdir (char * suffix)
+{
+	char *dir;
+	nih_assert (suffix && suffix[0]);
+	
+	dir = getenv("HOME");
+	if ( dir && dir[0] ) {
+		dir = nih_sprintf (NULL, "%s/%s", dir, suffix);
+		return dir;
+	}
+
+	return NULL;
+}
+
+/**
+ * xdg_get_config_home:
+ *
+ * Determine an XDG compliant XDG_CONFIG_HOME
+ *
+ **/
+char *
+xdg_get_config_home (void)
+{
+	nih_local char  **env = NULL;
+	size_t            len = 0;
+	char             *dir;
+
+	dir = getenv("XDG_CONFIG_HOME");
+	
+	if ( dir && dir[0] ) {
+		dir = nih_strdup (NULL, dir);
+		return dir;
+	}
+
+	dir = get_home_subdir (".config");
+
+	return dir;
+}
+
+/**
+ * xdg_get_config_dirs:
+ *
+ * Determine a list of XDG compliant XDG_CONFIG_DIRS
+ *
+ **/
+char **
+xdg_get_config_dirs (void)
+{
+	char         *env_path;
+	char         *result = NULL;
+	size_t        len = 0;
+	char        **dirs = NULL;
+
+	env_path = getenv ("XDG_CONFIG_DIRS");
+	if (! env_path || ! env_path[0])
+		env_path = "/etc/xdg";
+
+	dirs = nih_str_split(NULL, env_path, ":", TRUE);
+
+	return dirs;
+}
+
+/**
+ * xdg_get_dirs:
+ *
+ * Construct an array of user session config source paths to config dirs for a
+ * particular user. This array can be iterated to add each of these
+ * directories as config source dirs, when e.g. upstart is running as user session init.
+ * This is a convenience function.
+ *
+ **/
+char **
+get_user_upstart_dirs (void)
+{
+	char       *path;
+	char      **dirs = NULL;
+	char  **all_dirs = NULL;
+
+	all_dirs = nih_str_array_new (NULL);
+
+	path = xdg_get_config_home ();
+	if (path && path[0]) {
+		NIH_MUST (nih_strcat_sprintf (&path, NULL, "/%s", INIT_XDG_SUBDIR));
+		NIH_MUST (nih_str_array_add (&all_dirs, NULL, NULL, path));
+		nih_free(path);
+	}
+
+	path = get_home_subdir (USERCONFDIR);
+	if (path && path[0]) {
+		NIH_MUST (nih_str_array_add (&all_dirs, NULL, NULL, path));
+		nih_free(path);
+	}
+
+	dirs = xdg_get_config_dirs ();
+
+	for (char **p = dirs; p && *p; p++) {
+		NIH_MUST (nih_strcat_sprintf (p, NULL, "/%s", INIT_XDG_SUBDIR));
+		NIH_MUST (nih_str_array_add (&all_dirs, NULL, NULL, *p));
+	}
+
+	return all_dirs;
+}
+

=== added file 'init/xdg.h'
--- init/xdg.h	1970-01-01 00:00:00 +0000
+++ init/xdg.h	2012-12-14 16:07:48 +0000
@@ -0,0 +1,41 @@
+/* upstart
+ *
+ * Copyright © 2012 Canonical Ltd.
+ * Author: Dmitrijs Ledkovs <[email protected]>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef INIT_XDG_H
+#define INIT_XDG_H
+
+#include <nih/macros.h>
+
+NIH_BEGIN_EXTERN
+
+char *    get_home_subdir        (char * suffix)
+	__attribute__ ((malloc, warn_unused_result));
+
+char *    xdg_get_config_home    (void)
+	__attribute__ ((malloc, warn_unused_result));
+
+char **   xdg_get_config_dirs    (void)
+	__attribute__ ((malloc, warn_unused_result));
+
+char **   get_user_upstart_dirs  (void)
+	__attribute__ ((malloc, warn_unused_result));
+
+NIH_END_EXTERN
+
+#endif /* INIT_XDG_H */

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

Reply via email to