Merge authors: James Hunt (jamesodhunt) Related merge proposals: https://code.launchpad.net/~jamesodhunt/upstart/bug-1315060/+merge/218953 proposed by: James Hunt (jamesodhunt) ------------------------------------------------------------ revno: 1630 [merge] committer: Dimitri John Ledkov <dimitri.led...@canonical.com> branch nick: trunk timestamp: Wed 2014-06-04 17:55:28 +0100 message: merge lp:~jamesodhunt/upstart/bug-1315060 modified: ChangeLog init/main.c init/man/init.5 init/man/init.8 init/tests/test_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 'ChangeLog' --- ChangeLog 2014-06-04 16:30:21 +0000 +++ ChangeLog 2014-06-04 16:55:28 +0000 @@ -1,3 +1,18 @@ +2014-05-21 James Hunt <james.h...@ubuntu.com> + + * init/main.c: Add support for '--prepend-confdir'. + * init/man/init.8: Add '--prepend-confdir'. + * init/tests/test_main.c: Add tests for '--prepend-confdir'. + +2014-05-09 James Hunt <james.h...@ubuntu.com> + + * init/main.c: add '--append-confdir' command-line option (LP: #1315060). + * init/man/init.8: + - Document '--append-confdir'. + - Add init(5) reference for '--confdir'. + * init/tests/test_main.c: New Session and System init tests for + '--append-confdir'. + 2014-05-09 Dimitri John Ledkov <x...@ubuntu.com> * util/reboot.c: only use rebootcommand code path in runlevels 0, @@ -11,6 +26,15 @@ * Convert calls to deprecated json_object_object_get() to json_object_object_get_ex(). +2014-05-02 James Hunt <james.h...@ubuntu.com> + + * init/main.c: main(): Allow System Init read from multiple + configuration to directories like a Session Init (LP: #1315060). + * init/man/init.5: Clarify default directory. + * init/man/init.8: Explain new behaviour. + * init/tests/test_main.c: test_confdir(): Update tests for new + '--confdir' behaviour of System init. + 2014-04-24 James Hunt <james.h...@ubuntu.com> * init/man/init.5: === modified file 'init/main.c' --- init/main.c 2014-04-11 21:15:39 +0000 +++ init/main.c 2014-05-21 18:40:46 +0000 @@ -1,6 +1,6 @@ /* upstart * - * Copyright © 2009-2011 Canonical Ltd. + * Copyright 2009-2011 Canonical Ltd. * Author: Scott James Remnant <sc...@netsplit.com>. * * This program is free software; you can redistribute it and/or modify @@ -85,10 +85,12 @@ static void usr1_handler (void *data, NihSignal *signal); #endif /* DEBUG */ -static void handle_confdir (void); -static void handle_logdir (void); -static int console_type_setter (NihOption *option, const char *arg); -static int conf_dir_setter (NihOption *option, const char *arg); +static void handle_confdir (void); +static void handle_logdir (void); +static int console_type_setter (NihOption *option, const char *arg); +static int conf_dir_setter (NihOption *option, const char *arg); +static int prepend_conf_dir_setter (NihOption *option, const char *arg); +static int append_conf_dir_setter (NihOption *option, const char *arg); /** @@ -107,6 +109,22 @@ static char **conf_dirs = NULL; /** + * prepend_conf_dirs: + * + * Array of full paths to job configuration file directories that will + * be added to before the other values in conf_dirs. + **/ +static char **prepend_conf_dirs = NULL; + +/** + * append_conf_dirs: + * + * Array of full paths to job configuration file directories that will + * be added to conf_dirs. + **/ +static char **append_conf_dirs = NULL; + +/** * initial_event: * * Alternate event to emit at startup (rather than STARTUP_EVENT). @@ -146,30 +164,36 @@ * Command-line options we accept. **/ static NihOption options[] = { + { 0, "append-confdir", N_("specify additional directory to load configuration files from"), + NULL, "DIR", NULL, append_conf_dir_setter }, + + { 0, "chroot-sessions", N_("enable chroot sessions"), + NULL, NULL, &chroot_sessions, NULL }, + { 0, "confdir", N_("specify alternative directory to load configuration files from"), NULL, "DIR", NULL, conf_dir_setter }, { 0, "default-console", N_("default value for console stanza"), NULL, "VALUE", NULL, console_type_setter }, + { 0, "logdir", N_("specify alternative directory to store job output logs in"), + NULL, "DIR", &log_dir, NULL }, + { 0, "no-dbus", N_("do not connect to a D-Bus bus"), NULL, NULL, &disable_dbus, NULL }, { 0, "no-inherit-env", N_("jobs will not inherit environment of init"), NULL, NULL, &no_inherit_env , NULL }, - { 0, "logdir", N_("specify alternative directory to store job output logs in"), - NULL, "DIR", &log_dir, NULL }, - { 0, "no-log", N_("disable job logging"), NULL, NULL, &disable_job_logging, NULL }, - { 0, "chroot-sessions", N_("enable chroot sessions"), - NULL, NULL, &chroot_sessions, NULL }, - { 0, "no-startup-event", N_("do not emit any startup event (for testing)"), NULL, NULL, &disable_startup_event, NULL }, + { 0, "prepend-confdir", N_("specify additional initial directory to load configuration files from"), + NULL, "DIR", NULL, prepend_conf_dir_setter }, + /* Must be specified for both stateful and stateless re-exec */ { 0, "restart", N_("flag a re-exec has occurred"), NULL, NULL, &restart, NULL }, @@ -205,6 +229,8 @@ int ret; conf_dirs = NIH_MUST (nih_str_array_new (NULL)); + append_conf_dirs = NIH_MUST (nih_str_array_new (NULL)); + prepend_conf_dirs = NIH_MUST (nih_str_array_new (NULL)); args_copy = NIH_MUST (nih_str_array_copy (NULL, NULL, argv)); @@ -567,25 +593,22 @@ } /* Read configuration */ + if (prepend_conf_dirs[0]) { + for (char **d = prepend_conf_dirs; d && *d; d++) { + nih_debug ("Prepending configuration directory %s", *d); + NIH_MUST (conf_source_new (NULL, *d, CONF_JOB_DIR)); + } + } + if (! user_mode) { - char *conf_dir; - int len = 0; - nih_assert (conf_dirs[0]); - /* Count entries */ - for (char **d = conf_dirs; d && *d; d++, len++) - ; - - nih_assert (len); - - /* Use last value specified */ - conf_dir = conf_dirs[len-1]; - NIH_MUST (conf_source_new (NULL, CONFFILE, CONF_FILE)); - nih_debug ("Using configuration directory %s", conf_dir); - NIH_MUST (conf_source_new (NULL, conf_dir, CONF_JOB_DIR)); + for (char **d = conf_dirs; d && *d; d++) { + nih_debug ("Using configuration directory %s", *d); + NIH_MUST (conf_source_new (NULL, *d, CONF_JOB_DIR)); + } } else { nih_local char **dirs = NULL; @@ -597,7 +620,16 @@ } } + if (append_conf_dirs[0]) { + for (char **d = append_conf_dirs; d && *d; d++) { + nih_debug ("Adding configuration directory %s", *d); + NIH_MUST (conf_source_new (NULL, *d, CONF_JOB_DIR)); + } + } + nih_free (conf_dirs); + nih_free (prepend_conf_dirs); + nih_free (append_conf_dirs); job_class_environment_init (); @@ -1105,3 +1137,37 @@ return 0; } + +/** + * NihOption setter function to handle selection of configuration file + * directories. + * + * Returns: 0 on success, -1 on invalid console type. + **/ +static int +prepend_conf_dir_setter (NihOption *option, const char *arg) +{ + nih_assert (prepend_conf_dirs); + nih_assert (option); + + NIH_MUST (nih_str_array_add (&prepend_conf_dirs, NULL, NULL, arg)); + + return 0; +} + +/** + * NihOption setter function to handle selection of configuration file + * directories. + * + * Returns: 0 on success, -1 on invalid console type. + **/ +static int +append_conf_dir_setter (NihOption *option, const char *arg) +{ + nih_assert (append_conf_dirs); + nih_assert (option); + + NIH_MUST (nih_str_array_add (&append_conf_dirs, NULL, NULL, arg)); + + return 0; +} === modified file 'init/man/init.5' --- init/man/init.5 2014-04-24 12:39:18 +0000 +++ init/man/init.5 2014-05-02 13:02:19 +0000 @@ -22,7 +22,7 @@ .BR init (8) daemon reads its job configuration from files in the .I /etc/init/ -directory, and watches for future changes to these files using +directory by default, and watches for future changes to these files using .BR inotify (7). If Upstart was invoked as a user process with \-\-user option, it will === modified file 'init/man/init.8' --- init/man/init.8 2013-12-23 17:31:22 +0000 +++ init/man/init.8 2014-05-21 18:40:46 +0000 @@ -253,14 +253,41 @@ by placing them on the kernel command-line. .\" .TP +.B \-\-append-confdir \fIdirectory\fP +Add the specified directory to the default directory or directories +that job configuration files will be read from. This option may be +specified multiple times which will result in job configuration files +being loaded from each directory specified (which must exist). +Directories will be searched for jobs in the specified order after the +default directories have been searched. + +Note that if this option is used in combination with +.BR \-\-confdir "," +or +.BR \-\-prepend\-confdir "," +regardless of the order of the options on the command-line, the append +directories will be added +.I after +the other directories. +.\" +.TP .B \-\-confdir \fIdirectory\fP Read job configuration files from a directory other than the default -(\fI/etc/init\fP for process ID 1). - -When running as process ID 1, the last directory specified will be used. - -In user session mode, multiple directories will be honoured and job -configuration files loaded from the directories in the order specified. +(\fI/etc/init\fP for process ID 1). This option may be specified +multiple times which will result in job configuration files being +loaded from each directory specified (which must exist). Directories +will be searched for jobs in the specified order. + +In the case that multiple directories specify a job of the same name, +the first job encountered will be honoured. + +See section +.B User Session Mode +in +.BR init (5) +for the ordered list of default configuration directories a +Session Init will consider. + .\" .TP .B \-\-default-console \fIvalue\fP @@ -308,6 +335,24 @@ daemon from starting \fBany\fP jobs automatically. .\" .TP +.B \-\-prepend-confdir \fIdirectory\fP +Add the specified directory to the directory or directories +that job configuration files will be read from. This option may be +specified multiple times which will result in job configuration files +being loaded from each directory specified (which must exist). +Directories will be searched for jobs in the specified order before the +default directories have been searched. + +Note that if this option is used in combination with +.BR \-\-confdir "," +or +.BR \-\-append\-confdir "," +regardless of the order of the options on the command-line, the prepend +directories will be added +.I before +the other directories. +.\" +.TP .B \-\-session Connect to the D\-Bus session bus. This should only be used for testing. .\" === modified file 'init/tests/test_main.c' --- init/tests/test_main.c 2013-11-12 12:17:30 +0000 +++ init/tests/test_main.c 2014-05-21 18:40:46 +0000 @@ -46,6 +46,10 @@ { char confdir_a[PATH_MAX]; char confdir_b[PATH_MAX]; + char confdir_c[PATH_MAX]; + char confdir_d[PATH_MAX]; + char confdir_e[PATH_MAX]; + char confdir_f[PATH_MAX]; char *xdg_config_home; char *xdg_runtime_dir; char logdir[PATH_MAX]; @@ -58,8 +62,10 @@ nih_local char *session_file = NULL; nih_local char *path = NULL; - /* space for 2 sets of confdir options and a terminator */ - char *extra[5]; + /* space for 2 sets of confdir options, 2 sets of + * prepend-confdir, 2 sets of append-confdirs and a terminator. + */ + char *extra[13]; xdg_config_home = getenv ("XDG_CONFIG_HOME"); TEST_NE_P (xdg_config_home, NULL); @@ -75,6 +81,18 @@ TEST_FILENAME (confdir_b); assert0 (mkdir (confdir_b, 0755)); + TEST_FILENAME (confdir_c); + assert0 (mkdir (confdir_c, 0755)); + + TEST_FILENAME (confdir_d); + assert0 (mkdir (confdir_d, 0755)); + + TEST_FILENAME (confdir_e); + assert0 (mkdir (confdir_e, 0755)); + + TEST_FILENAME (confdir_f); + assert0 (mkdir (confdir_f, 0755)); + xdg_conf_dir = nih_sprintf (NULL, "%s/%s", xdg_config_home, "upstart"); TEST_NE_P (xdg_conf_dir, NULL); assert0 (mkdir (xdg_conf_dir, 0755)); @@ -151,6 +169,89 @@ assert0 (unlink (session_file)); /************************************************************/ + TEST_FEATURE ("Session Init with --prepend-confdir"); + + CREATE_FILE (confdir_a, "foo.conf", "exec foo"); + CREATE_FILE (confdir_a, "conflict.conf", "emits prepend"); + CREATE_FILE (xdg_conf_dir, "conflict.conf", "emits confdir"); + CREATE_FILE (xdg_conf_dir, "baz.conf", "exec baz"); + + extra[0] = "--prepend-confdir"; + extra[1] = confdir_a; + extra[2] = NULL; + + start_upstart_common (&upstart_pid, TRUE, FALSE, NULL, logdir, extra); + + /* Should be running */ + assert0 (kill (upstart_pid, 0)); + + session_file = get_session_file (xdg_runtime_dir, upstart_pid); + + cmd = nih_sprintf (NULL, "%s list 2>&1", get_initctl ()); + TEST_NE_P (cmd, NULL); + RUN_COMMAND (NULL, cmd, &output, &lines); + + qsort (output, lines, sizeof (output[0]), strcmp_compar); + + TEST_EQ (lines, 3); + TEST_STR_MATCH (output[0], "baz stop/waiting"); + TEST_STR_MATCH (output[1], "conflict stop/waiting"); + TEST_STR_MATCH (output[2], "foo stop/waiting"); + nih_free (output); + + cmd = nih_sprintf (NULL, "%s show-config %s 2>&1", get_initctl (), "conflict"); + TEST_NE_P (cmd, NULL); + RUN_COMMAND (NULL, cmd, &output, &lines); + + TEST_EQ (lines, 2); + TEST_STR_MATCH (output[0], "conflict"); + TEST_STR_MATCH (output[1], " emits prepend"); + nih_free (output); + + DELETE_FILE (confdir_a, "foo.conf"); + DELETE_FILE (confdir_a, "conflict.conf"); + DELETE_FILE (xdg_conf_dir, "conflict.conf"); + DELETE_FILE (xdg_conf_dir, "baz.conf"); + + STOP_UPSTART (upstart_pid); + assert0 (unlink (session_file)); + + /************************************************************/ + TEST_FEATURE ("Session Init with --append-confdir"); + + CREATE_FILE (xdg_conf_dir, "xdg_dir_job.conf", "exec true"); + CREATE_FILE (confdir_a, "conf_dir_job.conf", "exec true"); + + extra[0] = "--append-confdir"; + extra[1] = confdir_a; + extra[2] = NULL; + + start_upstart_common (&upstart_pid, TRUE, FALSE, NULL, logdir, extra); + + /* Should be running */ + assert0 (kill (upstart_pid, 0)); + + session_file = get_session_file (xdg_runtime_dir, upstart_pid); + + cmd = nih_sprintf (NULL, "%s list 2>&1", get_initctl ()); + TEST_NE_P (cmd, NULL); + RUN_COMMAND (NULL, cmd, &output, &lines); + + qsort (output, lines, sizeof (output[0]), strcmp_compar); + + /* jobs in xdg_conf_dir should be considered */ + TEST_EQ (lines, 2); + TEST_STR_MATCH (output[0], "conf_dir_job stop/waiting"); + TEST_STR_MATCH (output[1], "xdg_dir_job stop/waiting"); + nih_free (output); + + DELETE_FILE (xdg_conf_dir, "xdg_dir_job.conf"); + DELETE_FILE (confdir_a, "conf_dir_job.conf"); + + STOP_UPSTART (upstart_pid); + assert0 (unlink (session_file)); + + /************************************************************/ TEST_FEATURE ("Session Init with multiple --confdir"); CREATE_FILE (xdg_conf_dir, "xdg_dir_job.conf", "exec true"); @@ -191,6 +292,88 @@ assert0 (unlink (session_file)); /************************************************************/ + TEST_FEATURE ("Session Init with multiple --prepend-confdir"); + + CREATE_FILE (xdg_conf_dir, "xdg_dir_job.conf", "exec true"); + CREATE_FILE (confdir_a, "conf_dir_a_job.conf", "exec true"); + CREATE_FILE (confdir_b, "conf_dir_b_job.conf", "exec true"); + + extra[0] = "--prepend-confdir"; + extra[1] = confdir_a; + extra[2] = "--prepend-confdir"; + extra[3] = confdir_b; + extra[4] = NULL; + + /* pass 2 confdir directories */ + start_upstart_common (&upstart_pid, TRUE, FALSE, NULL, logdir, extra); + + /* Should be running */ + assert0 (kill (upstart_pid, 0)); + + session_file = get_session_file (xdg_runtime_dir, upstart_pid); + + cmd = nih_sprintf (NULL, "%s list 2>&1", get_initctl ()); + TEST_NE_P (cmd, NULL); + RUN_COMMAND (NULL, cmd, &output, &lines); + + qsort (output, lines, sizeof (output[0]), strcmp_compar); + + /* jobs in xdg_conf_dir should be considered */ + TEST_EQ (lines, 3); + TEST_STR_MATCH (output[0], "conf_dir_a_job stop/waiting"); + TEST_STR_MATCH (output[1], "conf_dir_b_job stop/waiting"); + TEST_STR_MATCH (output[2], "xdg_dir_job stop/waiting"); + nih_free (output); + + DELETE_FILE (xdg_conf_dir, "xdg_dir_job.conf"); + DELETE_FILE (confdir_a, "conf_dir_a_job.conf"); + DELETE_FILE (confdir_b, "conf_dir_b_job.conf"); + + STOP_UPSTART (upstart_pid); + assert0 (unlink (session_file)); + + /************************************************************/ + TEST_FEATURE ("Session Init with multiple --append-confdir"); + + CREATE_FILE (xdg_conf_dir, "xdg_dir_job.conf", "exec true"); + CREATE_FILE (confdir_a, "conf_dir_a_job.conf", "exec true"); + CREATE_FILE (confdir_b, "conf_dir_b_job.conf", "exec true"); + + extra[0] = "--append-confdir"; + extra[1] = confdir_a; + extra[2] = "--append-confdir"; + extra[3] = confdir_b; + extra[4] = NULL; + + /* pass 2 confdir directories */ + start_upstart_common (&upstart_pid, TRUE, FALSE, NULL, logdir, extra); + + /* Should be running */ + assert0 (kill (upstart_pid, 0)); + + session_file = get_session_file (xdg_runtime_dir, upstart_pid); + + cmd = nih_sprintf (NULL, "%s list 2>&1", get_initctl ()); + TEST_NE_P (cmd, NULL); + RUN_COMMAND (NULL, cmd, &output, &lines); + + qsort (output, lines, sizeof (output[0]), strcmp_compar); + + /* jobs in xdg_conf_dir should be considered */ + TEST_EQ (lines, 3); + TEST_STR_MATCH (output[0], "conf_dir_a_job stop/waiting"); + TEST_STR_MATCH (output[1], "conf_dir_b_job stop/waiting"); + TEST_STR_MATCH (output[2], "xdg_dir_job stop/waiting"); + nih_free (output); + + DELETE_FILE (xdg_conf_dir, "xdg_dir_job.conf"); + DELETE_FILE (confdir_a, "conf_dir_a_job.conf"); + DELETE_FILE (confdir_b, "conf_dir_b_job.conf"); + + STOP_UPSTART (upstart_pid); + assert0 (unlink (session_file)); + + /************************************************************/ TEST_FEATURE ("Session Init with multiple --confdir and conflicting names"); CREATE_FILE (xdg_conf_dir, "conflict.conf", "emits xdg_conf_dir"); @@ -241,6 +424,233 @@ assert0 (unlink (session_file)); /************************************************************/ + TEST_FEATURE ("Session Init with multiple --prepend-confdir and conflicting names"); + + CREATE_FILE (xdg_conf_dir, "conflict.conf", "emits xdg_conf_dir"); + CREATE_FILE (confdir_a, "conflict.conf", "emits confdir_a"); + CREATE_FILE (confdir_b, "foo.conf", "exec true"); + + extra[0] = "--prepend-confdir"; + extra[1] = confdir_a; + extra[2] = "--prepend-confdir"; + extra[3] = confdir_b; + extra[4] = NULL; + + /* pass 2 confdir directories */ + start_upstart_common (&upstart_pid, TRUE, FALSE, NULL, logdir, extra); + + /* Should be running */ + assert0 (kill (upstart_pid, 0)); + + session_file = get_session_file (xdg_runtime_dir, upstart_pid); + + cmd = nih_sprintf (NULL, "%s list 2>&1", get_initctl ()); + TEST_NE_P (cmd, NULL); + RUN_COMMAND (NULL, cmd, &output, &lines); + + qsort (output, lines, sizeof (output[0]), strcmp_compar); + + /* We expect jobs in xdg_conf_dir to be ignored */ + TEST_EQ (lines, 2); + TEST_STR_MATCH (output[0], "conflict stop/waiting"); + TEST_STR_MATCH (output[1], "foo stop/waiting"); + nih_free (output); + + cmd = nih_sprintf (NULL, "%s show-config %s 2>&1", get_initctl (), "conflict"); + TEST_NE_P (cmd, NULL); + RUN_COMMAND (NULL, cmd, &output, &lines); + + /* Ensure the correct version of the conflict job is found */ + TEST_EQ (lines, 2); + TEST_STR_MATCH (output[0], "conflict"); + TEST_STR_MATCH (output[1], " emits confdir_a"); + nih_free (output); + + DELETE_FILE (xdg_conf_dir, "conflict.conf"); + DELETE_FILE (confdir_a, "conflict.conf"); + DELETE_FILE (confdir_b, "foo.conf"); + + STOP_UPSTART (upstart_pid); + assert0 (unlink (session_file)); + + /************************************************************/ + TEST_FEATURE ("Session Init with multiple --append-confdir and conflicting names"); + + CREATE_FILE (xdg_conf_dir, "conflict.conf", "emits xdg_conf_dir"); + CREATE_FILE (confdir_a, "conflict.conf", "emits confdir_a"); + CREATE_FILE (confdir_b, "foo.conf", "exec true"); + + extra[0] = "--append-confdir"; + extra[1] = confdir_a; + extra[2] = "--append-confdir"; + extra[3] = confdir_b; + extra[4] = NULL; + + /* pass 2 confdir directories */ + start_upstart_common (&upstart_pid, TRUE, FALSE, NULL, logdir, extra); + + /* Should be running */ + assert0 (kill (upstart_pid, 0)); + + session_file = get_session_file (xdg_runtime_dir, upstart_pid); + + cmd = nih_sprintf (NULL, "%s list 2>&1", get_initctl ()); + TEST_NE_P (cmd, NULL); + RUN_COMMAND (NULL, cmd, &output, &lines); + + qsort (output, lines, sizeof (output[0]), strcmp_compar); + + /* We expect jobs in xdg_conf_dir to be ignored */ + TEST_EQ (lines, 2); + TEST_STR_MATCH (output[0], "conflict stop/waiting"); + TEST_STR_MATCH (output[1], "foo stop/waiting"); + nih_free (output); + + cmd = nih_sprintf (NULL, "%s show-config %s 2>&1", get_initctl (), "conflict"); + TEST_NE_P (cmd, NULL); + RUN_COMMAND (NULL, cmd, &output, &lines); + + /* Ensure the correct version of the conflict job is found */ + TEST_EQ (lines, 2); + TEST_STR_MATCH (output[0], "conflict"); + TEST_STR_MATCH (output[1], " emits xdg_conf_dir"); + nih_free (output); + + DELETE_FILE (xdg_conf_dir, "conflict.conf"); + DELETE_FILE (confdir_a, "conflict.conf"); + DELETE_FILE (confdir_b, "foo.conf"); + + STOP_UPSTART (upstart_pid); + assert0 (unlink (session_file)); + + /************************************************************/ + TEST_FEATURE ("Session Init with multiple --confdir, --prepend-confdir and --append-confdir with conflicting names"); + + CREATE_FILE (xdg_conf_dir, "conflict.conf", "emits xdg_conf_dir"); + CREATE_FILE (confdir_a, "conflict.conf", "emits confdir_a"); + CREATE_FILE (confdir_b, "foo.conf", "exec true"); + CREATE_FILE (confdir_c, "conflict.conf", "emits confdir_c"); + CREATE_FILE (confdir_d, "conflict.conf", "emits confdir_d"); + CREATE_FILE (confdir_e, "bar.conf", "exec false"); + + extra[0] = "--prepend-confdir"; + extra[1] = confdir_d; + extra[2] = "--prepend-confdir"; + extra[3] = confdir_e; + extra[4] = "--confdir"; + extra[5] = confdir_a; + extra[6] = "--confdir"; + extra[7] = confdir_b; + extra[8] = "--append-confdir"; + extra[9] = confdir_c; + extra[10] = NULL; + + start_upstart_common (&upstart_pid, TRUE, FALSE, NULL, logdir, extra); + + /* Should be running */ + assert0 (kill (upstart_pid, 0)); + + session_file = get_session_file (xdg_runtime_dir, upstart_pid); + + cmd = nih_sprintf (NULL, "%s list 2>&1", get_initctl ()); + TEST_NE_P (cmd, NULL); + RUN_COMMAND (NULL, cmd, &output, &lines); + + qsort (output, lines, sizeof (output[0]), strcmp_compar); + + TEST_EQ (lines, 3); + TEST_STR_MATCH (output[0], "bar stop/waiting"); + TEST_STR_MATCH (output[1], "conflict stop/waiting"); + TEST_STR_MATCH (output[2], "foo stop/waiting"); + nih_free (output); + + cmd = nih_sprintf (NULL, "%s show-config %s 2>&1", get_initctl (), "conflict"); + TEST_NE_P (cmd, NULL); + RUN_COMMAND (NULL, cmd, &output, &lines); + + /* Ensure the correct version of the conflict job is found */ + TEST_EQ (lines, 2); + TEST_STR_MATCH (output[0], "conflict"); + TEST_STR_MATCH (output[1], " emits confdir_d"); + nih_free (output); + + DELETE_FILE (xdg_conf_dir, "conflict.conf"); + DELETE_FILE (confdir_a, "conflict.conf"); + DELETE_FILE (confdir_b, "foo.conf"); + DELETE_FILE (confdir_c, "conflict.conf"); + DELETE_FILE (confdir_d, "conflict.conf"); + DELETE_FILE (confdir_e, "bar.conf"); + + STOP_UPSTART (upstart_pid); + assert0 (unlink (session_file)); + + /************************************************************/ + TEST_FEATURE ("Session Init with multiple out of order --confdir, --prepend-confdir and --append-confdir"); + + CREATE_FILE (xdg_conf_dir, "conflict.conf", "emits xdg_conf_dir"); + CREATE_FILE (confdir_a, "conflict.conf", "emits confdir_a"); + CREATE_FILE (confdir_b, "foo.conf", "exec true"); + CREATE_FILE (confdir_c, "conflict.conf", "emits confdir_c"); + CREATE_FILE (confdir_d, "conflict.conf", "emits confdir_d"); + CREATE_FILE (confdir_e, "bar.conf", "exec false"); + CREATE_FILE (confdir_f, "baz.conf", "exec false"); + + extra[0] = "--append-confdir"; + extra[1] = confdir_a; + extra[2] = "--prepend-confdir"; + extra[3] = confdir_e; + extra[4] = "--confdir"; + extra[5] = confdir_b; + extra[6] = "--append-confdir"; + extra[7] = confdir_c; + extra[8] = "--prepend-confdir"; + extra[9] = confdir_f; + extra[10] = "--confdir"; + extra[11] = confdir_d; + extra[12] = NULL; + + start_upstart_common (&upstart_pid, TRUE, FALSE, NULL, logdir, extra); + + /* Should be running */ + assert0 (kill (upstart_pid, 0)); + + session_file = get_session_file (xdg_runtime_dir, upstart_pid); + + cmd = nih_sprintf (NULL, "%s list 2>&1", get_initctl ()); + TEST_NE_P (cmd, NULL); + RUN_COMMAND (NULL, cmd, &output, &lines); + + qsort (output, lines, sizeof (output[0]), strcmp_compar); + + TEST_EQ (lines, 4); + TEST_STR_MATCH (output[0], "bar stop/waiting"); + TEST_STR_MATCH (output[1], "baz stop/waiting"); + TEST_STR_MATCH (output[2], "conflict stop/waiting"); + TEST_STR_MATCH (output[3], "foo stop/waiting"); + nih_free (output); + + cmd = nih_sprintf (NULL, "%s show-config %s 2>&1", get_initctl (), "conflict"); + TEST_NE_P (cmd, NULL); + RUN_COMMAND (NULL, cmd, &output, &lines); + + /* Ensure the correct version of the conflict job is found */ + TEST_EQ (lines, 2); + TEST_STR_MATCH (output[0], "conflict"); + TEST_STR_MATCH (output[1], " emits confdir_d"); + nih_free (output); + + DELETE_FILE (xdg_conf_dir, "conflict.conf"); + DELETE_FILE (confdir_a, "conflict.conf"); + DELETE_FILE (confdir_b, "foo.conf"); + DELETE_FILE (confdir_c, "conflict.conf"); + DELETE_FILE (confdir_d, "conflict.conf"); + DELETE_FILE (confdir_e, "bar.conf"); + DELETE_FILE (confdir_f, "baz.conf"); + + STOP_UPSTART (upstart_pid); + assert0 (unlink (session_file)); + + /************************************************************/ TEST_FEATURE ("System Init without --confdir"); /* Use the "secret" interface */ @@ -305,6 +715,66 @@ STOP_UPSTART (upstart_pid); /************************************************************/ + TEST_FEATURE ("System Init with --prepend-confdir"); + + TEST_FALSE (file_exists ("/etc/init/must-not-exist-by-default.conf")); + + CREATE_FILE (confdir_a, "must-not-exist-by-default.conf", "exec true"); + + extra[0] = "--prepend-confdir"; + extra[1] = confdir_a; + extra[2] = NULL; + + start_upstart_common (&upstart_pid, FALSE, FALSE, NULL, logdir, extra); + + /* Should be running */ + assert0 (kill (upstart_pid, 0)); + + cmd = nih_sprintf (NULL, "%s status %s 2>&1", get_initctl (), "must-not-exist-by-default"); + TEST_NE_P (cmd, NULL); + RUN_COMMAND (NULL, cmd, &output, &lines); + + qsort (output, lines, sizeof (output[0]), strcmp_compar); + + TEST_EQ (lines, 1); + TEST_STR_MATCH (output[0], "must-not-exist-by-default stop/waiting"); + nih_free (output); + + DELETE_FILE (confdir_a, "must-not-exist-by-default.conf"); + + STOP_UPSTART (upstart_pid); + + /************************************************************/ + TEST_FEATURE ("System Init with --append-confdir"); + + TEST_FALSE (file_exists ("/etc/init/must-not-exist-by-default.conf")); + + CREATE_FILE (confdir_a, "must-not-exist-by-default.conf", "exec true"); + + extra[0] = "--append-confdir"; + extra[1] = confdir_a; + extra[2] = NULL; + + start_upstart_common (&upstart_pid, FALSE, FALSE, NULL, logdir, extra); + + /* Should be running */ + assert0 (kill (upstart_pid, 0)); + + cmd = nih_sprintf (NULL, "%s status %s 2>&1", get_initctl (), "must-not-exist-by-default"); + TEST_NE_P (cmd, NULL); + RUN_COMMAND (NULL, cmd, &output, &lines); + + qsort (output, lines, sizeof (output[0]), strcmp_compar); + + TEST_EQ (lines, 1); + TEST_STR_MATCH (output[0], "must-not-exist-by-default stop/waiting"); + nih_free (output); + + DELETE_FILE (confdir_a, "must-not-exist-by-default.conf"); + + STOP_UPSTART (upstart_pid); + + /************************************************************/ TEST_FEATURE ("System Init with multiple --confdir"); assert0 (setenv ("UPSTART_CONFDIR", xdg_conf_dir, 1)); @@ -331,14 +801,14 @@ qsort (output, lines, sizeof (output[0]), strcmp_compar); - TEST_EQ (lines, 2); - /* XXX: Only the last instance of --confdir should be honoured. - * - * This behaviour deviates from running as a Session Init where *all* - * --confdir's specified are used. + /* Like a Session Init, the System Init behaviour is (now) to + * honour all --confdirs. */ - TEST_STR_MATCH (output[0], "baz stop/waiting"); - TEST_STR_MATCH (output[1], "qux stop/waiting"); + TEST_EQ (lines, 3); + + TEST_STR_MATCH (output[0], "bar stop/waiting"); + TEST_STR_MATCH (output[1], "baz stop/waiting"); + TEST_STR_MATCH (output[2], "qux stop/waiting"); nih_free (output); DELETE_FILE (xdg_conf_dir, "foo.conf"); @@ -349,6 +819,96 @@ STOP_UPSTART (upstart_pid); /************************************************************/ + TEST_FEATURE ("System Init with multiple --prepend-confdir"); + + TEST_FALSE (file_exists ("/etc/init/must-not-exist-by-default.conf")); + TEST_FALSE (file_exists ("/etc/init/must-not-exist-by-default2.conf")); + + CREATE_FILE (confdir_a, "must-not-exist-by-default.conf", "exec true"); + CREATE_FILE (confdir_b, "must-not-exist-by-default2.conf", "exec true"); + + extra[0] = "--prepend-confdir"; + extra[1] = confdir_a; + extra[2] = "--prepend-confdir"; + extra[3] = confdir_b; + extra[4] = NULL; + + start_upstart_common (&upstart_pid, FALSE, FALSE, NULL, logdir, extra); + + /* Should be running */ + assert0 (kill (upstart_pid, 0)); + + cmd = nih_sprintf (NULL, "%s status %s 2>&1", get_initctl (), "must-not-exist-by-default"); + TEST_NE_P (cmd, NULL); + RUN_COMMAND (NULL, cmd, &output, &lines); + + qsort (output, lines, sizeof (output[0]), strcmp_compar); + + TEST_EQ (lines, 1); + TEST_STR_MATCH (output[0], "must-not-exist-by-default stop/waiting"); + nih_free (output); + + cmd = nih_sprintf (NULL, "%s status %s 2>&1", get_initctl (), "must-not-exist-by-default2"); + TEST_NE_P (cmd, NULL); + RUN_COMMAND (NULL, cmd, &output, &lines); + + qsort (output, lines, sizeof (output[0]), strcmp_compar); + + TEST_EQ (lines, 1); + TEST_STR_MATCH (output[0], "must-not-exist-by-default2 stop/waiting"); + nih_free (output); + + DELETE_FILE (confdir_a, "must-not-exist-by-default.conf"); + DELETE_FILE (confdir_b, "must-not-exist-by-default2.conf"); + + STOP_UPSTART (upstart_pid); + + /************************************************************/ + TEST_FEATURE ("System Init with multiple --append-confdir"); + + TEST_FALSE (file_exists ("/etc/init/must-not-exist-by-default.conf")); + TEST_FALSE (file_exists ("/etc/init/must-not-exist-by-default2.conf")); + + CREATE_FILE (confdir_a, "must-not-exist-by-default.conf", "exec true"); + CREATE_FILE (confdir_b, "must-not-exist-by-default2.conf", "exec true"); + + extra[0] = "--append-confdir"; + extra[1] = confdir_a; + extra[2] = "--append-confdir"; + extra[3] = confdir_b; + extra[4] = NULL; + + start_upstart_common (&upstart_pid, FALSE, FALSE, NULL, logdir, extra); + + /* Should be running */ + assert0 (kill (upstart_pid, 0)); + + cmd = nih_sprintf (NULL, "%s status %s 2>&1", get_initctl (), "must-not-exist-by-default"); + TEST_NE_P (cmd, NULL); + RUN_COMMAND (NULL, cmd, &output, &lines); + + qsort (output, lines, sizeof (output[0]), strcmp_compar); + + TEST_EQ (lines, 1); + TEST_STR_MATCH (output[0], "must-not-exist-by-default stop/waiting"); + nih_free (output); + + cmd = nih_sprintf (NULL, "%s status %s 2>&1", get_initctl (), "must-not-exist-by-default2"); + TEST_NE_P (cmd, NULL); + RUN_COMMAND (NULL, cmd, &output, &lines); + + qsort (output, lines, sizeof (output[0]), strcmp_compar); + + TEST_EQ (lines, 1); + TEST_STR_MATCH (output[0], "must-not-exist-by-default2 stop/waiting"); + nih_free (output); + + DELETE_FILE (confdir_a, "must-not-exist-by-default.conf"); + DELETE_FILE (confdir_b, "must-not-exist-by-default2.conf"); + + STOP_UPSTART (upstart_pid); + + /************************************************************/ TEST_FEATURE ("System Init with multiple --confdir and conflicting names"); assert0 (setenv ("UPSTART_CONFDIR", xdg_conf_dir, 1)); @@ -363,6 +923,7 @@ extra[3] = confdir_b; extra[4] = NULL; + /* pass 2 confdir directories */ start_upstart_common (&upstart_pid, FALSE, FALSE, NULL, logdir, extra); /* Should be running */ @@ -375,7 +936,6 @@ qsort (output, lines, sizeof (output[0]), strcmp_compar); TEST_EQ (lines, 1); - /* only the last instance of --confdir should be honoured */ TEST_STR_MATCH (output[0], "conflict stop/waiting"); nih_free (output); @@ -386,7 +946,7 @@ /* Ensure the correct version of the conflict job is found */ TEST_EQ (lines, 2); TEST_STR_MATCH (output[0], "conflict"); - TEST_STR_MATCH (output[1], " emits confdir_b"); + TEST_STR_MATCH (output[1], " emits confdir_a"); nih_free (output); DELETE_FILE (xdg_conf_dir, "conflict.conf"); @@ -396,11 +956,171 @@ STOP_UPSTART (upstart_pid); /************************************************************/ + TEST_FEATURE ("System Init with multiple --prepend-confdir and conflicting names"); + + TEST_FALSE (file_exists ("/etc/init/must-not-exist-by-default.conf")); + + CREATE_FILE (confdir_a, "must-not-exist-by-default.conf", "emits confdir_a"); + CREATE_FILE (confdir_b, "must-not-exist-by-default.conf", "emits confdir_b"); + + extra[0] = "--prepend-confdir"; + extra[1] = confdir_a; + extra[2] = "--prepend-confdir"; + extra[3] = confdir_b; + extra[4] = NULL; + + start_upstart_common (&upstart_pid, FALSE, FALSE, NULL, logdir, extra); + + /* Should be running */ + assert0 (kill (upstart_pid, 0)); + + cmd = nih_sprintf (NULL, "%s show-config %s 2>&1", get_initctl (), "must-not-exist-by-default"); + TEST_NE_P (cmd, NULL); + RUN_COMMAND (NULL, cmd, &output, &lines); + + /* Ensure the correct version of the conflict job is found */ + TEST_EQ (lines, 2); + TEST_STR_MATCH (output[0], "must-not-exist-by-default"); + TEST_STR_MATCH (output[1], " emits confdir_a"); + nih_free (output); + + DELETE_FILE (confdir_a, "must-not-exist-by-default.conf"); + DELETE_FILE (confdir_b, "must-not-exist-by-default.conf"); + + STOP_UPSTART (upstart_pid); + + /************************************************************/ + TEST_FEATURE ("System Init with multiple --append-confdir and conflicting names"); + + TEST_FALSE (file_exists ("/etc/init/must-not-exist-by-default.conf")); + + CREATE_FILE (confdir_a, "must-not-exist-by-default.conf", "emits confdir_a"); + CREATE_FILE (confdir_b, "must-not-exist-by-default.conf", "emits confdir_b"); + + extra[0] = "--append-confdir"; + extra[1] = confdir_a; + extra[2] = "--append-confdir"; + extra[3] = confdir_b; + extra[4] = NULL; + + start_upstart_common (&upstart_pid, FALSE, FALSE, NULL, logdir, extra); + + /* Should be running */ + assert0 (kill (upstart_pid, 0)); + + cmd = nih_sprintf (NULL, "%s show-config %s 2>&1", get_initctl (), "must-not-exist-by-default"); + TEST_NE_P (cmd, NULL); + RUN_COMMAND (NULL, cmd, &output, &lines); + + /* Ensure the correct version of the conflict job is found */ + TEST_EQ (lines, 2); + TEST_STR_MATCH (output[0], "must-not-exist-by-default"); + TEST_STR_MATCH (output[1], " emits confdir_a"); + nih_free (output); + + DELETE_FILE (confdir_a, "must-not-exist-by-default.conf"); + DELETE_FILE (confdir_b, "must-not-exist-by-default.conf"); + + STOP_UPSTART (upstart_pid); + + /************************************************************/ + TEST_FEATURE ("System Init with multiple out of order --confdir, --prepend-confdir and --append-confdir"); + + CREATE_FILE (confdir_a, "conflict.conf", "emits confdir_a"); + CREATE_FILE (confdir_a, "wibble.conf", "emits wobble"); + CREATE_FILE (confdir_b, "conflict.conf", "emits confdir_b"); + CREATE_FILE (confdir_c, "conflict.conf", "emits confdir_c"); + CREATE_FILE (confdir_d, "foo.conf", "emits hello"); + CREATE_FILE (confdir_e, "bar.conf", "emits world"); + CREATE_FILE (confdir_e, "conflict.conf", "emits confdir_e"); + CREATE_FILE (confdir_f, "conflict.conf", "emits confdir_f"); + CREATE_FILE (confdir_f, "baz.conf", "exec true"); + + extra[0] = "--append-confdir"; + extra[1] = confdir_a; + extra[2] = "--prepend-confdir"; + extra[3] = confdir_e; + extra[4] = "--confdir"; + extra[5] = confdir_b; + extra[6] = "--append-confdir"; + extra[7] = confdir_f; + extra[8] = "--confdir"; + extra[9] = confdir_c; + extra[10] = "--prepend-confdir"; + extra[11] = confdir_d; + extra[12] = NULL; + + start_upstart_common (&upstart_pid, FALSE, FALSE, NULL, logdir, extra); + + /* Should be running */ + assert0 (kill (upstart_pid, 0)); + + cmd = nih_sprintf (NULL, "%s list 2>&1", get_initctl ()); + TEST_NE_P (cmd, NULL); + RUN_COMMAND (NULL, cmd, &output, &lines); + + qsort (output, lines, sizeof (output[0]), strcmp_compar); + + TEST_EQ (lines, 5); + TEST_STR_MATCH (output[0], "bar stop/waiting"); + TEST_STR_MATCH (output[1], "baz stop/waiting"); + TEST_STR_MATCH (output[2], "conflict stop/waiting"); + TEST_STR_MATCH (output[3], "foo stop/waiting"); + TEST_STR_MATCH (output[4], "wibble stop/waiting"); + nih_free (output); + + cmd = nih_sprintf (NULL, "%s show-config %s 2>&1", get_initctl (), "conflict"); + TEST_NE_P (cmd, NULL); + RUN_COMMAND (NULL, cmd, &output, &lines); + TEST_EQ (lines, 2); + TEST_STR_MATCH (output[0], "conflict"); + TEST_STR_MATCH (output[1], " emits confdir_e"); + nih_free (output); + + cmd = nih_sprintf (NULL, "%s show-config %s 2>&1", get_initctl (), "wibble"); + TEST_NE_P (cmd, NULL); + RUN_COMMAND (NULL, cmd, &output, &lines); + TEST_EQ (lines, 2); + TEST_STR_MATCH (output[0], "wibble"); + TEST_STR_MATCH (output[1], " emits wobble"); + nih_free (output); + + cmd = nih_sprintf (NULL, "%s show-config %s 2>&1", get_initctl (), "foo"); + TEST_NE_P (cmd, NULL); + RUN_COMMAND (NULL, cmd, &output, &lines); + TEST_EQ (lines, 2); + TEST_STR_MATCH (output[0], "foo"); + TEST_STR_MATCH (output[1], " emits hello"); + nih_free (output); + + cmd = nih_sprintf (NULL, "%s show-config %s 2>&1", get_initctl (), "bar"); + TEST_NE_P (cmd, NULL); + RUN_COMMAND (NULL, cmd, &output, &lines); + TEST_EQ (lines, 2); + TEST_STR_MATCH (output[0], "bar"); + TEST_STR_MATCH (output[1], " emits world"); + nih_free (output); + + DELETE_FILE (confdir_a, "conflict.conf"); + DELETE_FILE (confdir_a, "wibble.conf"); + DELETE_FILE (confdir_b, "conflict.conf"); + DELETE_FILE (confdir_c, "conflict.conf"); + DELETE_FILE (confdir_d, "foo.conf"); + DELETE_FILE (confdir_e, "bar.conf"); + DELETE_FILE (confdir_e, "conflict.conf"); + DELETE_FILE (confdir_f, "conflict.conf"); + DELETE_FILE (confdir_f, "baz.conf"); + + STOP_UPSTART (upstart_pid); TEST_DBUS_END (dbus_pid); assert0 (rmdir (confdir_a)); assert0 (rmdir (confdir_b)); + assert0 (rmdir (confdir_c)); + assert0 (rmdir (confdir_d)); + assert0 (rmdir (confdir_e)); + assert0 (rmdir (confdir_f)); assert0 (rmdir (xdg_conf_dir)); assert0 (rmdir (logdir)); assert0 (unsetenv ("UPSTART_CONFDIR"));
-- upstart-devel mailing list upstart-devel@lists.ubuntu.com Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/upstart-devel