blob: 494891f7fc555e76e2b92cf761fe1df69f4ae42c [file] [log] [blame]
Scott James Remnant5befd932006-08-19 19:24:54 +01001/* upstart
2 *
Scott James Remnant004d8c02010-02-04 11:08:07 -08003 * Copyright © 2010 Canonical Ltd.
Scott James Remnant7d5b2ea2009-05-22 15:20:12 +02004 * Author: Scott James Remnant <scott@netsplit.com>.
Scott James Remnant5befd932006-08-19 19:24:54 +01005 *
Scott James Remnant0c0c5a52009-06-23 10:29:35 +01006 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2, as
Scott James Remnant75123022009-05-22 13:27:56 +02008 * published by the Free Software Foundation.
Scott James Remnant5befd932006-08-19 19:24:54 +01009 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
Scott James Remnant0c0c5a52009-06-23 10:29:35 +010015 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Scott James Remnant5befd932006-08-19 19:24:54 +010018 */
19
20#ifdef HAVE_CONFIG_H
21# include <config.h>
22#endif /* HAVE_CONFIG_H */
23
Scott James Remnantcf2e8332009-07-06 20:32:07 +010024
25#include <dbus/dbus.h>
Scott James Remnant5befd932006-08-19 19:24:54 +010026
Scott James Remnant10a35f22009-07-08 20:05:46 +010027#include <sys/types.h>
28
Scott James Remnant4cd63672007-03-05 16:15:39 +000029#include <stdio.h>
Scott James Remnant5befd932006-08-19 19:24:54 +010030#include <stdlib.h>
Scott James Remnant10a35f22009-07-08 20:05:46 +010031#include <unistd.h>
Scott James Remnant5befd932006-08-19 19:24:54 +010032
33#include <nih/macros.h>
Scott James Remnant4cd63672007-03-05 16:15:39 +000034#include <nih/alloc.h>
35#include <nih/string.h>
Scott James Remnant5befd932006-08-19 19:24:54 +010036#include <nih/main.h>
37#include <nih/option.h>
Scott James Remnant48622982006-10-13 15:15:50 +010038#include <nih/command.h>
Scott James Remnant3bcd15e2006-08-19 19:50:12 +010039#include <nih/logging.h>
40#include <nih/error.h>
James Hunteec19232011-06-01 12:13:42 +010041#include <nih/hash.h>
42#include <nih/tree.h>
Scott James Remnant3bcd15e2006-08-19 19:50:12 +010043
Scott James Remnantcf2e8332009-07-06 20:32:07 +010044#include <nih-dbus/dbus_error.h>
45#include <nih-dbus/dbus_proxy.h>
46#include <nih-dbus/errors.h>
47
48#include "dbus/upstart.h"
49
50#include "com.ubuntu.Upstart.h"
51#include "com.ubuntu.Upstart.Job.h"
52#include "com.ubuntu.Upstart.Instance.h"
Scott James Remnant5befd932006-08-19 19:24:54 +010053
James Hunteec19232011-06-01 12:13:42 +010054#include "../init/events.h"
55#include "initctl.h"
56
Scott James Remnant4cd63672007-03-05 16:15:39 +000057
Scott James Remnantcf2e8332009-07-06 20:32:07 +010058/* Prototypes for local functions */
59NihDBusProxy *upstart_open (const void *parent)
60 __attribute__ ((warn_unused_result, malloc));
61char * job_status (const void *parent,
62 NihDBusProxy *job_class, NihDBusProxy *job)
63 __attribute__ ((warn_unused_result, malloc));
Scott James Remnant4cd63672007-03-05 16:15:39 +000064
65/* Prototypes for static functions */
Scott James Remnantcf2e8332009-07-06 20:32:07 +010066static void start_reply_handler (char **job_path, NihDBusMessage *message,
67 const char *instance);
68static void reply_handler (int *ret, NihDBusMessage *message);
69static void error_handler (void *data, NihDBusMessage *message);
Scott James Remnant4f19cb92007-03-09 16:48:41 +000070
James Hunteec19232011-06-01 12:13:42 +010071static void job_class_condition_handler (void *data,
72 NihDBusMessage *message,
73 char ** const *value);
74
75static void job_class_condition_err_handler (void *data,
76 NihDBusMessage *message);
77
78static void job_class_parse_events (const ConditionHandlerData *data,
79 char ** const *variant_array);
80
81static void job_class_show_emits (const void *parent,
82 NihDBusProxy *job_class_proxy, const char *job_class_name);
83
84static void job_class_show_conditions (NihDBusProxy *job_class_proxy,
85 const char *job_class_name);
86
James Hunt5f0b3542011-06-01 10:42:05 +010087#ifndef TEST
88
89static int dbus_bus_type_setter (NihOption *option, const char *arg);
90
91#endif
Scott James Remnant4cd63672007-03-05 16:15:39 +000092
Scott James Remnant4f19cb92007-03-09 16:48:41 +000093/* Prototypes for option and command functions */
Scott James Remnantcf2e8332009-07-06 20:32:07 +010094int start_action (NihCommand *command, char * const *args);
95int stop_action (NihCommand *command, char * const *args);
96int restart_action (NihCommand *command, char * const *args);
Scott James Remnant004d8c02010-02-04 11:08:07 -080097int reload_action (NihCommand *command, char * const *args);
Scott James Remnantcf2e8332009-07-06 20:32:07 +010098int status_action (NihCommand *command, char * const *args);
99int list_action (NihCommand *command, char * const *args);
100int emit_action (NihCommand *command, char * const *args);
101int reload_configuration_action (NihCommand *command, char * const *args);
102int version_action (NihCommand *command, char * const *args);
103int log_priority_action (NihCommand *command, char * const *args);
James Hunteec19232011-06-01 12:13:42 +0100104int show_config_action (NihCommand *command, char * const *args);
Scott James Remnant66384202007-01-06 14:23:18 +0000105
106
107/**
James Hunt5f0b3542011-06-01 10:42:05 +0100108 * use_dbus:
Scott James Remnant66384202007-01-06 14:23:18 +0000109 *
James Hunt5f0b3542011-06-01 10:42:05 +0100110 * If 1, connect using a D-Bus bus.
111 * If 0, connect using private connection.
112 * If -1, determine appropriate connection based on UID.
113 */
114int use_dbus = -1;
115
116/**
117 * dbus_bus_type:
118 *
119 * D-Bus bus to connect to (DBUS_BUS_SYSTEM or DBUS_BUS_SESSION), or -1
120 * to have an appropriate bus selected.
121 */
122int dbus_bus_type = -1;
Scott James Remnant66384202007-01-06 14:23:18 +0000123
124/**
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100125 * dest_name:
Scott James Remnant66384202007-01-06 14:23:18 +0000126 *
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100127 * Name on the D-Bus system bus that the message should be sent to when
128 * system is TRUE.
Scott James Remnant66384202007-01-06 14:23:18 +0000129 **/
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100130char *dest_name = NULL;
Scott James Remnant48622982006-10-13 15:15:50 +0100131
Scott James Remnant4cd63672007-03-05 16:15:39 +0000132/**
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100133 * dest_address:
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000134 *
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100135 * Address for private D-Bus connection.
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000136 **/
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100137const char *dest_address = DBUS_ADDRESS_UPSTART;
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000138
139/**
140 * no_wait:
141 *
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100142 * Whether to wait for a job or event to be finished before existing or not.
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000143 **/
144int no_wait = FALSE;
145
James Hunt5f0b3542011-06-01 10:42:05 +0100146/**
James Hunteec19232011-06-01 12:13:42 +0100147 * enumerate_events:
148 *
149 * If TRUE, list out all events/jobs that a particular job *may require* to
150 * be run: essentially any event/job mentioned in a job configuration files
151 * "start on" / "stop on" condition. Used for showing dependencies
152 * between jobs and events.
153 **/
154int enumerate_events = FALSE;
155
156/**
James Hunt5f0b3542011-06-01 10:42:05 +0100157 * NihOption setter function to handle selection of appropriate D-Bus
158 * bus.
159 *
160 * Always returns 1 denoting success.
161 **/
162int
163dbus_bus_type_setter (NihOption *option, const char *arg)
164{
165 nih_assert (option);
166
167 if (! strcmp (option->long_option, "system")) {
168 use_dbus = TRUE;
169 dbus_bus_type = DBUS_BUS_SYSTEM;
170 }
171 else if (! strcmp (option->long_option, "session")) {
172 use_dbus = TRUE;
173 dbus_bus_type = DBUS_BUS_SESSION;
174 }
175
176 return 1;
177}
Scott James Remnant4cd63672007-03-05 16:15:39 +0000178
179/**
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100180 * upstart_open:
181 * @parent: parent object for new proxy.
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000182 *
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100183 * Opens a connection to the init daemon and returns a proxy to the manager
184 * object. If @dest_name is not NULL, a connection is instead opened to
185 * the system bus and the proxy linked to the well-known name given.
186 *
187 * Error messages are output to standard error.
188 *
189 * If @parent is not NULL, it should be a pointer to another object which
190 * will be used as a parent for the returned proxy. When all parents
191 * of the returned proxy are freed, the returned proxy will also be
192 * freed.
193 *
194 * Returns: newly allocated D-Bus proxy or NULL on error.
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000195 **/
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100196NihDBusProxy *
197upstart_open (const void *parent)
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000198{
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100199 DBusError dbus_error;
200 DBusConnection *connection;
201 NihDBusProxy * upstart;
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000202
James Hunt5f0b3542011-06-01 10:42:05 +0100203 if (use_dbus < 0)
204 use_dbus = getuid () ? TRUE : FALSE;
205 if (use_dbus >= 0 && dbus_bus_type < 0)
206 dbus_bus_type = DBUS_BUS_SYSTEM;
Scott James Remnant10a35f22009-07-08 20:05:46 +0100207
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100208 dbus_error_init (&dbus_error);
James Hunt5f0b3542011-06-01 10:42:05 +0100209 if (use_dbus) {
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100210 if (! dest_name)
211 dest_name = DBUS_SERVICE_UPSTART;
212
James Hunt5f0b3542011-06-01 10:42:05 +0100213 connection = dbus_bus_get (dbus_bus_type, &dbus_error);
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100214 if (! connection) {
James Hunt5f0b3542011-06-01 10:42:05 +0100215 nih_error ("%s: %s",
216 dbus_bus_type == DBUS_BUS_SYSTEM
217 ? _("Unable to connect to system bus")
218 : _("Unable to connect to session bus"),
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100219 dbus_error.message);
220 dbus_error_free (&dbus_error);
221 return NULL;
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000222 }
223
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100224 dbus_connection_set_exit_on_disconnect (connection, FALSE);
225 } else {
226 if (dest_name) {
227 fprintf (stderr, _("%s: --dest given without --system\n"),
228 program_name);
229 nih_main_suggest_help ();
230 return NULL;
231 }
232
233 connection = dbus_connection_open (dest_address, &dbus_error);
234 if (! connection) {
235 nih_error ("%s: %s", _("Unable to connect to Upstart"),
236 dbus_error.message);
237 dbus_error_free (&dbus_error);
238 return NULL;
239 }
240 }
241 dbus_error_free (&dbus_error);
242
243 upstart = nih_dbus_proxy_new (parent, connection,
244 dest_name,
245 DBUS_PATH_UPSTART,
246 NULL, NULL);
247 if (! upstart) {
248 NihError *err;
249
250 err = nih_error_get ();
251 nih_error ("%s", err->message);
252 nih_free (err);
253
254 dbus_connection_unref (connection);
255 return NULL;
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000256 }
257
Scott James Remnant10a35f22009-07-08 20:05:46 +0100258 upstart->auto_start = FALSE;
259
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100260 /* Drop initial reference now the proxy holds one */
261 dbus_connection_unref (connection);
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000262
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100263 return upstart;
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000264}
265
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100266
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000267/**
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100268 * job_status:
269 * @parent: parent object for new string,
270 * @job_class: proxy for remote job class object,
271 * @job: proxy for remote instance object.
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000272 *
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100273 * Queries the job object @job and contructs a string defining the status
274 * of that instance, containing the name of the @job_class and @job,
275 * the goal, state and any running processes.
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000276 *
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100277 * @job may be NULL in which case a non-running job is assumed, the
278 * function also catches the remote object no longer existing.
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000279 *
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100280 * If @parent is not NULL, it should be a pointer to another object which
281 * will be used as a parent for the returned string. When all parents
282 * of the returned string are freed, the returned string will also be
283 * freed.
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000284 *
James Hunteec19232011-06-01 12:13:42 +0100285 * Returns: newly allocated string or NULL on raised error.
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000286 **/
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100287char *
288job_status (const void * parent,
289 NihDBusProxy *job_class,
290 NihDBusProxy *job)
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000291{
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100292 nih_local char * job_class_name = NULL;
293 nih_local JobProperties *props = NULL;
294 char * str = NULL;
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000295
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100296 nih_assert (job_class != NULL);
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000297
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100298 /* Get the job name */
299 if (job_class_get_name_sync (NULL, job_class, &job_class_name) < 0)
300 return NULL;
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000301
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100302 /* Get the instance properties, catching the instance going away
303 * between the time we got it and this call.
304 */
305 if (job) {
306 if (job_get_all_sync (NULL, job, &props) < 0) {
307 NihDBusError *dbus_err;
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000308
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100309 dbus_err = (NihDBusError *)nih_error_get ();
310 if ((dbus_err->number != NIH_DBUS_ERROR)
311 || strcmp (dbus_err->name, DBUS_ERROR_UNKNOWN_METHOD)) {
312 return NULL;
313 } else {
314 nih_free (dbus_err);
315 }
316 }
317 }
318
319 if (props && *props->name) {
320 str = nih_sprintf (parent, "%s (%s)",
321 job_class_name, props->name);
322 if (! str)
323 nih_return_no_memory_error (NULL);
324 } else {
325 str = nih_strdup (parent, job_class_name);
326 if (! str)
327 nih_return_no_memory_error (NULL);
328 }
329
330 if (props) {
331 if (! nih_strcat_sprintf (&str, parent, " %s/%s",
332 props->goal, props->state)) {
333 nih_error_raise_no_memory ();
334 nih_free (str);
335 return NULL;
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000336 }
337
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100338 /* The first process returned is always the main process,
339 * which is the process we always want to display alongside
340 * the state if there is one. Prefix if it's not one of
341 * the standard processes.
342 */
343 if (props->processes[0]) {
344 if (strcmp (props->processes[0]->item0, "main")
345 && strcmp (props->processes[0]->item0, "pre-start")
346 && strcmp (props->processes[0]->item0, "post-stop")) {
347 if (! nih_strcat_sprintf (&str, parent, ", (%s) process %d",
348 props->processes[0]->item0,
349 props->processes[0]->item1)) {
350 nih_error_raise_no_memory ();
351 nih_free (str);
352 return NULL;
353 }
354 } else {
355 if (! nih_strcat_sprintf (&str, parent, ", process %d",
356 props->processes[0]->item1)) {
357 nih_error_raise_no_memory ();
358 nih_free (str);
359 return NULL;
360 }
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000361 }
362
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100363 /* Append a line for each additional process */
364 for (JobProcessesElement **p = &props->processes[1];
365 p && *p; p++) {
366 if (! nih_strcat_sprintf (&str, parent, "\n\t%s process %d",
367 (*p)->item0,
368 (*p)->item1)) {
369 nih_error_raise_no_memory ();
370 nih_free (str);
371 return NULL;
372 }
373 }
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000374 }
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000375 } else {
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100376 if (! nih_strcat (&str, parent, " stop/waiting")) {
377 nih_error_raise_no_memory ();
378 nih_free (str);
379 return NULL;
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000380 }
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000381 }
382
383 return str;
384}
385
386
Scott James Remnant509f8a62007-03-11 17:39:27 +0000387/**
Scott James Remnant4cd63672007-03-05 16:15:39 +0000388 * start_action:
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000389 * @command: NihCommand invoked,
390 * @args: command-line arguments.
Scott James Remnant4cd63672007-03-05 16:15:39 +0000391 *
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100392 * This function is called for the "start" command.
Scott James Remnant4cd63672007-03-05 16:15:39 +0000393 *
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000394 * Returns: command exit status.
Scott James Remnant4cd63672007-03-05 16:15:39 +0000395 **/
396int
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100397start_action (NihCommand * command,
Scott James Remnant4cd63672007-03-05 16:15:39 +0000398 char * const *args)
399{
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100400 nih_local NihDBusProxy *upstart = NULL;
401 const char * upstart_job = NULL;
402 const char * upstart_instance = NULL;
403 nih_local char * job_class_path = NULL;
404 nih_local NihDBusProxy *job_class = NULL;
405 nih_local char * job_path = NULL;
406 nih_local NihDBusProxy *job = NULL;
407 DBusPendingCall * pending_call;
408 int ret = 1;
409 NihError * err;
Scott James Remnant4cd63672007-03-05 16:15:39 +0000410
411 nih_assert (command != NULL);
412 nih_assert (args != NULL);
413
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100414 if (args[0]) {
415 upstart_job = args[0];
416 } else {
417 upstart_job = getenv ("UPSTART_JOB");
418 upstart_instance = getenv ("UPSTART_INSTANCE");
Scott James Remnant4cd63672007-03-05 16:15:39 +0000419
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100420 if (! (upstart_job && upstart_instance)) {
421 fprintf (stderr, _("%s: missing job name\n"), program_name);
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000422 nih_main_suggest_help ();
423 return 1;
424 }
425 }
426
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100427 upstart = upstart_open (NULL);
428 if (! upstart)
429 return 1;
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000430
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100431 /* Obtain a proxy to the job */
432 if (upstart_get_job_by_name_sync (NULL, upstart, upstart_job,
433 &job_class_path) < 0)
434 goto error;
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000435
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100436 job_class = nih_dbus_proxy_new (NULL, upstart->connection,
437 upstart->name, job_class_path,
438 NULL, NULL);
439 if (! job_class)
440 goto error;
Scott James Remnant4cd63672007-03-05 16:15:39 +0000441
Scott James Remnant10a35f22009-07-08 20:05:46 +0100442 job_class->auto_start = FALSE;
443
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100444 /* When called from a job handler, we directly change the goal
445 * so we need the instance. These calls are always made without
446 * waiting, since otherwise we'd block the job we're called from.
447 */
448 if (upstart_instance) {
449 if (job_class_get_instance_by_name_sync (NULL, job_class,
450 upstart_instance,
451 &job_path) < 0)
452 goto error;
453
454 job = nih_dbus_proxy_new (NULL, upstart->connection,
455 upstart->name, job_path,
456 NULL, NULL);
457 if (! job)
458 goto error;
459
Scott James Remnant10a35f22009-07-08 20:05:46 +0100460 job->auto_start = FALSE;
461
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100462 pending_call = job_start (job, FALSE,
463 (JobStartReply)reply_handler,
464 error_handler, &ret,
465 NIH_DBUS_TIMEOUT_NEVER);
466 if (! pending_call)
467 goto error;
468 } else {
469 /* job_path is nih_local, so whatever gets filled in will
470 * be automatically freed.
471 */
472 pending_call = job_class_start (job_class, &args[1], (! no_wait),
473 (JobClassStartReply)start_reply_handler,
474 error_handler, &job_path,
475 NIH_DBUS_TIMEOUT_NEVER);
476 if (! pending_call)
477 goto error;
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000478 }
Scott James Remnant4cd63672007-03-05 16:15:39 +0000479
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100480 dbus_pending_call_block (pending_call);
481 dbus_pending_call_unref (pending_call);
482
483 /* Make sure we got a valid job path, and in the case of the instance
484 * path, no error message. Then display the current job status.
485 */
486 if (job_path && ((job == NULL) || (ret == 0))) {
487 nih_local char *status = NULL;
488
489 if (! job) {
490 job = NIH_SHOULD (nih_dbus_proxy_new (
491 NULL, upstart->connection,
492 upstart->name, job_path,
493 NULL, NULL));
494 if (! job)
495 goto error;
Scott James Remnant10a35f22009-07-08 20:05:46 +0100496
497 job->auto_start = FALSE;
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100498 }
499
500 status = NIH_SHOULD (job_status (NULL, job_class, job));
501 if (! status)
502 goto error;
503
504 nih_message ("%s", status);
505
506 ret = 0;
507 } else {
508 ret = 1;
509 }
510
511 return ret;
512
513error:
514 err = nih_error_get ();
515 nih_error ("%s", err->message);
516 nih_free (err);
517
518 return 1;
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000519}
520
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100521
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000522/**
523 * stop_action:
524 * @command: NihCommand invoked,
525 * @args: command-line arguments.
526 *
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100527 * This function is called for the "stop" command.
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000528 *
529 * Returns: command exit status.
530 **/
531int
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100532stop_action (NihCommand * command,
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000533 char * const *args)
534{
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100535 nih_local NihDBusProxy *upstart = NULL;
536 const char * upstart_job = NULL;
537 const char * upstart_instance = NULL;
538 nih_local char * job_class_path = NULL;
539 nih_local NihDBusProxy *job_class = NULL;
540 nih_local char * job_path = NULL;
541 nih_local NihDBusProxy *job = NULL;
542 DBusPendingCall * pending_call;
543 int ret = 1;
544 NihError * err;
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000545
546 nih_assert (command != NULL);
547 nih_assert (args != NULL);
548
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100549 if (args[0]) {
550 upstart_job = args[0];
551 } else {
552 upstart_job = getenv ("UPSTART_JOB");
553 upstart_instance = getenv ("UPSTART_INSTANCE");
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000554
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100555 if (! (upstart_job && upstart_instance)) {
556 fprintf (stderr, _("%s: missing job name\n"), program_name);
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000557 nih_main_suggest_help ();
558 return 1;
559 }
560 }
561
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100562 upstart = upstart_open (NULL);
563 if (! upstart)
564 return 1;
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000565
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100566 /* Obtain a proxy to the job */
567 if (upstart_get_job_by_name_sync (NULL, upstart, upstart_job,
568 &job_class_path) < 0)
569 goto error;
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000570
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100571 job_class = nih_dbus_proxy_new (NULL, upstart->connection,
572 upstart->name, job_class_path,
573 NULL, NULL);
574 if (! job_class)
575 goto error;
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000576
Scott James Remnant10a35f22009-07-08 20:05:46 +0100577 job_class->auto_start = FALSE;
578
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100579 /* When called from a job handler, we directly change the goal
580 * so need the instance. These calls are always made without
581 * waiting, since otherwise we'd block the job we're called from.
582 */
583 if (upstart_instance) {
584 if (job_class_get_instance_by_name_sync (NULL, job_class,
585 upstart_instance,
586 &job_path) < 0)
587 goto error;
588
589 job = nih_dbus_proxy_new (NULL, upstart->connection,
590 upstart->name, job_path,
591 NULL, NULL);
592 if (! job)
593 goto error;
594
Scott James Remnant10a35f22009-07-08 20:05:46 +0100595 job->auto_start = FALSE;
596
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100597 pending_call = job_stop (job, FALSE,
598 (JobStopReply)reply_handler,
599 error_handler, &ret,
600 NIH_DBUS_TIMEOUT_NEVER);
601 if (! pending_call)
602 goto error;
603 } else {
604 /* Lookup the instance that we'll end up stopping */
605 if (job_class_get_instance_sync (NULL, job_class, &args[1],
606 &job_path) < 0)
607 goto error;
608
609 job = nih_dbus_proxy_new (NULL, upstart->connection,
610 upstart->name, job_path,
611 NULL, NULL);
612 if (! job)
613 goto error;
614
Scott James Remnant10a35f22009-07-08 20:05:46 +0100615 job->auto_start = FALSE;
616
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100617 pending_call = job_class_stop (job_class, &args[1], (! no_wait),
618 (JobClassStopReply)reply_handler,
619 error_handler, &ret,
620 NIH_DBUS_TIMEOUT_NEVER);
621 if (! pending_call)
622 goto error;
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000623 }
624
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100625 dbus_pending_call_block (pending_call);
626 dbus_pending_call_unref (pending_call);
627
628 /* Display the current job status */
629 if (ret == 0) {
630 nih_local char *status = NULL;
631
632 status = NIH_SHOULD (job_status (NULL, job_class, job));
633 if (! status)
634 goto error;
635
636 nih_message ("%s", status);
637 }
638
639 return ret;
640
641error:
642 err = nih_error_get ();
643 nih_error ("%s", err->message);
644 nih_free (err);
645
646 return 1;
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000647}
648
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100649
650/**
651 * restart_action:
652 * @command: NihCommand invoked,
653 * @args: command-line arguments.
654 *
655 * This function is called for the "restart" command.
656 *
657 * Returns: command exit status.
658 **/
659int
660restart_action (NihCommand * command,
661 char * const *args)
662{
663 nih_local NihDBusProxy *upstart = NULL;
664 const char * upstart_job = NULL;
665 const char * upstart_instance = NULL;
666 nih_local char * job_class_path = NULL;
667 nih_local NihDBusProxy *job_class = NULL;
668 nih_local char * job_path = NULL;
669 nih_local NihDBusProxy *job = NULL;
670 DBusPendingCall * pending_call;
671 int ret = 1;
672 NihError * err;
673
674 nih_assert (command != NULL);
675 nih_assert (args != NULL);
676
677 if (args[0]) {
678 upstart_job = args[0];
679 } else {
680 upstart_job = getenv ("UPSTART_JOB");
681 upstart_instance = getenv ("UPSTART_INSTANCE");
682
683 if (! (upstart_job && upstart_instance)) {
684 fprintf (stderr, _("%s: missing job name\n"), program_name);
685 nih_main_suggest_help ();
686 return 1;
687 }
688 }
689
690 upstart = upstart_open (NULL);
691 if (! upstart)
692 return 1;
693
694 /* Obtain a proxy to the job */
695 if (upstart_get_job_by_name_sync (NULL, upstart, upstart_job,
696 &job_class_path) < 0)
697 goto error;
698
699 job_class = nih_dbus_proxy_new (NULL, upstart->connection,
700 upstart->name, job_class_path,
701 NULL, NULL);
702 if (! job_class)
703 goto error;
704
Scott James Remnant10a35f22009-07-08 20:05:46 +0100705 job_class->auto_start = FALSE;
706
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100707 /* When called from a job handler, we directly toggle the goal
708 * so we need the instance. These calls are always made without
709 * waiting, since otherwise we'd block the job we're called from.
710 */
711 if (upstart_instance) {
712 if (job_class_get_instance_by_name_sync (NULL, job_class,
713 upstart_instance,
714 &job_path) < 0)
715 goto error;
716
717 job = nih_dbus_proxy_new (NULL, upstart->connection,
718 upstart->name, job_path,
719 NULL, NULL);
720 if (! job)
721 goto error;
722
Scott James Remnant10a35f22009-07-08 20:05:46 +0100723 job->auto_start = FALSE;
724
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100725 pending_call = job_restart (job, FALSE,
726 (JobRestartReply)reply_handler,
727 error_handler, &ret,
728 NIH_DBUS_TIMEOUT_NEVER);
729 if (! pending_call)
730 goto error;
731 } else {
732 /* job_path is nih_local, so whatever gets filled in will
733 * be automatically freed.
734 */
735 pending_call = job_class_restart (job_class, &args[1], (! no_wait),
736 (JobClassRestartReply)start_reply_handler,
737 error_handler, &job_path,
738 NIH_DBUS_TIMEOUT_NEVER);
James Hunteec19232011-06-01 12:13:42 +0100739
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100740 if (! pending_call)
741 goto error;
742 }
743
744 dbus_pending_call_block (pending_call);
745 dbus_pending_call_unref (pending_call);
746
747 /* Make sure we got a valid job path, and in the case of the instance
748 * path, no error message. Then display the current job status.
749 */
750 if (job_path && ((job == NULL) || (ret == 0))) {
751 nih_local char *status = NULL;
752
753 if (! job) {
754 job = NIH_SHOULD (nih_dbus_proxy_new (
755 NULL, upstart->connection,
756 upstart->name, job_path,
757 NULL, NULL));
758 if (! job)
759 goto error;
Scott James Remnant10a35f22009-07-08 20:05:46 +0100760
761 job->auto_start = FALSE;
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100762 }
763
764 status = NIH_SHOULD (job_status (NULL, job_class, job));
765 if (! status)
766 goto error;
767
768 nih_message ("%s", status);
769
770 ret = 0;
771 } else {
772 ret = 1;
773 }
774
775 return ret;
776
777error:
778 err = nih_error_get ();
779 nih_error ("%s", err->message);
780 nih_free (err);
781
782 return 1;
783}
784
785
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000786/**
Scott James Remnant004d8c02010-02-04 11:08:07 -0800787 * reload_action:
788 * @command: NihCommand invoked,
789 * @args: command-line arguments.
790 *
791 * This function is called for the "reload" command.
792 *
793 * Returns: command exit status.
794 **/
795int
796reload_action (NihCommand * command,
797 char * const *args)
798{
799 nih_local NihDBusProxy *upstart = NULL;
800 const char * upstart_job = NULL;
801 const char * upstart_instance = NULL;
802 nih_local char * job_class_path = NULL;
803 nih_local NihDBusProxy *job_class = NULL;
804 nih_local char * job_path = NULL;
805 nih_local NihDBusProxy *job = NULL;
806 nih_local JobProcessesElement **processes = NULL;
807 NihError * err;
808
809 nih_assert (command != NULL);
810 nih_assert (args != NULL);
811
812 if (args[0]) {
813 upstart_job = args[0];
814 } else {
815 upstart_job = getenv ("UPSTART_JOB");
816 upstart_instance = getenv ("UPSTART_INSTANCE");
817
818 if (! (upstart_job && upstart_instance)) {
819 fprintf (stderr, _("%s: missing job name\n"), program_name);
820 nih_main_suggest_help ();
821 return 1;
822 }
823 }
824
825 upstart = upstart_open (NULL);
826 if (! upstart)
827 return 1;
828
829 /* Obtain a proxy to the job */
830 if (upstart_get_job_by_name_sync (NULL, upstart, upstart_job,
831 &job_class_path) < 0)
832 goto error;
833
834 job_class = nih_dbus_proxy_new (NULL, upstart->connection,
835 upstart->name, job_class_path,
836 NULL, NULL);
837 if (! job_class)
838 goto error;
839
840 job_class->auto_start = FALSE;
841
842 /* Obtain a proxy to the specific instance. Catch the case where
843 * we were just given a job name, and there was no single instance
844 * running.
845 */
846 if (upstart_instance) {
847 if (job_class_get_instance_by_name_sync (NULL, job_class,
848 upstart_instance,
849 &job_path) < 0)
850 goto error;
851 } else {
852 if (job_class_get_instance_sync (NULL, job_class,
853 &args[1], &job_path) < 0)
854 goto error;
855 }
856
857 job = nih_dbus_proxy_new (NULL, upstart->connection,
858 upstart->name, job_path,
859 NULL, NULL);
860 if (! job)
861 goto error;
862
863 job->auto_start = FALSE;
864
865 /* Get the process list */
866 if (job_get_processes_sync (NULL, job, &processes) < 0)
867 goto error;
868
869 if ((! processes[0]) || strcmp (processes[0]->item0, "main")) {
870 nih_error (_("Not running"));
871 return 1;
872 }
873
874 if (kill (processes[0]->item1, SIGHUP) < 0) {
875 nih_error_raise_system ();
876 goto error;
877 }
878
879 return 0;
880
881error:
882 err = nih_error_get ();
883 nih_error ("%s", err->message);
884 nih_free (err);
885
886 return 1;
887}
888
889
890/**
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000891 * status_action:
892 * @command: NihCommand invoked,
893 * @args: command-line arguments.
894 *
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100895 * This function is called for the "status" command.
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000896 *
897 * Returns: command exit status.
898 **/
899int
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100900status_action (NihCommand * command,
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000901 char * const *args)
902{
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100903 nih_local NihDBusProxy *upstart = NULL;
904 const char * upstart_job = NULL;
905 const char * upstart_instance = NULL;
906 nih_local char * job_class_path = NULL;
907 nih_local NihDBusProxy *job_class = NULL;
908 nih_local char * job_path = NULL;
909 nih_local NihDBusProxy *job = NULL;
910 nih_local char * status = NULL;
911 NihError * err;
912 NihDBusError * dbus_err;
Scott James Remnant4f19cb92007-03-09 16:48:41 +0000913
914 nih_assert (command != NULL);
915 nih_assert (args != NULL);
916
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100917 if (args[0]) {
918 upstart_job = args[0];
919 } else {
920 upstart_job = getenv ("UPSTART_JOB");
921 upstart_instance = getenv ("UPSTART_INSTANCE");
Scott James Remnant4cd63672007-03-05 16:15:39 +0000922
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100923 if (! (upstart_job && upstart_instance)) {
924 fprintf (stderr, _("%s: missing job name\n"), program_name);
925 nih_main_suggest_help ();
926 return 1;
Scott James Remnant4cd63672007-03-05 16:15:39 +0000927 }
928 }
929
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100930 upstart = upstart_open (NULL);
931 if (! upstart)
932 return 1;
933
934 /* Obtain a proxy to the job */
935 if (upstart_get_job_by_name_sync (NULL, upstart, upstart_job,
936 &job_class_path) < 0)
937 goto error;
938
939 job_class = nih_dbus_proxy_new (NULL, upstart->connection,
940 upstart->name, job_class_path,
941 NULL, NULL);
942 if (! job_class)
943 goto error;
944
Scott James Remnant10a35f22009-07-08 20:05:46 +0100945 job_class->auto_start = FALSE;
946
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100947 /* Obtain a proxy to the specific instance. Catch the case where
948 * we were just given a job name, and there was no single instance
949 * running.
950 */
951 if (upstart_instance) {
952 if (job_class_get_instance_by_name_sync (NULL, job_class,
953 upstart_instance,
954 &job_path) < 0)
955 goto error;
956 } else {
957 if (job_class_get_instance_sync (NULL, job_class,
958 &args[1], &job_path) < 0) {
959 dbus_err = (NihDBusError *)nih_error_get ();
960 if (args[1]
961 || (dbus_err->number != NIH_DBUS_ERROR)
962 || strcmp (dbus_err->name, DBUS_INTERFACE_UPSTART ".Error.UnknownInstance"))
963 goto error;
964
965 nih_free (dbus_err);
966 }
967 }
968
969 if (job_path) {
970 job = nih_dbus_proxy_new (NULL, upstart->connection,
971 upstart->name, job_path,
972 NULL, NULL);
973 if (! job)
974 goto error;
Scott James Remnant10a35f22009-07-08 20:05:46 +0100975
976 job->auto_start = FALSE;
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100977 } else {
978 job = NULL;
979 }
980
981 status = job_status (NULL, job_class, job);
982 if (! status)
983 goto error;
984
985 nih_message ("%s", status);
986
987 return 0;
988
989error:
990 err = nih_error_get ();
991 nih_error ("%s", err->message);
992 nih_free (err);
993
994 return 1;
Scott James Remnant4cd63672007-03-05 16:15:39 +0000995}
996
Scott James Remnantcf2e8332009-07-06 20:32:07 +0100997
Scott James Remnant4cd63672007-03-05 16:15:39 +0000998/**
999 * list_action:
Scott James Remnant4f19cb92007-03-09 16:48:41 +00001000 * @command: NihCommand invoked,
1001 * @args: command-line arguments.
Scott James Remnant4cd63672007-03-05 16:15:39 +00001002 *
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001003 * This function is called for the "list" command.
Scott James Remnant4cd63672007-03-05 16:15:39 +00001004 *
Scott James Remnant4f19cb92007-03-09 16:48:41 +00001005 * Returns: command exit status.
Scott James Remnant4cd63672007-03-05 16:15:39 +00001006 **/
1007int
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001008list_action (NihCommand * command,
Scott James Remnant4cd63672007-03-05 16:15:39 +00001009 char * const *args)
1010{
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001011 nih_local NihDBusProxy *upstart = NULL;
1012 nih_local char ** job_class_paths = NULL;
1013 NihError * err;
1014 NihDBusError * dbus_err;
1015
Scott James Remnant4cd63672007-03-05 16:15:39 +00001016 nih_assert (command != NULL);
1017 nih_assert (args != NULL);
1018
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001019 upstart = upstart_open (NULL);
1020 if (! upstart)
Scott James Remnant4f19cb92007-03-09 16:48:41 +00001021 return 1;
Scott James Remnant4cd63672007-03-05 16:15:39 +00001022
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001023 /* Obtain a list of jobs */
1024 if (upstart_get_all_jobs_sync (NULL, upstart, &job_class_paths) < 0)
1025 goto error;
1026
1027 for (char **job_class_path = job_class_paths;
1028 job_class_path && *job_class_path; job_class_path++) {
1029 nih_local NihDBusProxy *job_class = NULL;
1030 nih_local char ** job_paths = NULL;
1031
1032 job_class = nih_dbus_proxy_new (NULL, upstart->connection,
1033 upstart->name, *job_class_path,
1034 NULL, NULL);
1035 if (! job_class)
1036 goto error;
1037
Scott James Remnant10a35f22009-07-08 20:05:46 +01001038 job_class->auto_start = FALSE;
1039
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001040 /* Obtain a list of instances, catch an error from the
1041 * command and assume the job just went away.
1042 */
1043 if (job_class_get_all_instances_sync (NULL, job_class,
1044 &job_paths) < 0) {
1045 dbus_err = (NihDBusError *)nih_error_get ();
1046 if ((dbus_err->number != NIH_DBUS_ERROR)
1047 || strcmp (dbus_err->name, DBUS_ERROR_UNKNOWN_METHOD))
1048 goto error;
1049
1050 nih_free (dbus_err);
1051 continue;
1052 }
1053
1054 /* Handle no running instances by assuming that the
1055 * job is just stopped, again catch an error and assume
1056 * the job went away.
1057 */
1058 if (! *job_paths) {
1059 nih_local char *status = NULL;
1060
1061 status = job_status (NULL, job_class, NULL);
1062 if (! status) {
1063 dbus_err = (NihDBusError *)nih_error_get ();
1064 if ((dbus_err->number != NIH_DBUS_ERROR)
1065 || strcmp (dbus_err->name, DBUS_ERROR_UNKNOWN_METHOD))
1066 goto error;
1067
1068 nih_free (dbus_err);
1069 continue;
1070 }
1071
1072 nih_message ("%s", status);
1073 }
1074
1075 /* Otherwise iterate the instances and output the status
1076 * of each.
1077 */
1078 for (char **job_path = job_paths; job_path && *job_path;
1079 job_path++) {
1080 nih_local NihDBusProxy *job = NULL;
1081 nih_local char * status = NULL;
1082
1083 job = nih_dbus_proxy_new (NULL, upstart->connection,
1084 upstart->name, *job_path,
1085 NULL, NULL);
1086 if (! job)
1087 goto error;
1088
Scott James Remnant10a35f22009-07-08 20:05:46 +01001089 job->auto_start = FALSE;
1090
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001091 status = job_status (NULL, job_class, job);
1092 if (! status) {
1093 dbus_err = (NihDBusError *)nih_error_get ();
1094 if ((dbus_err->number != NIH_DBUS_ERROR)
1095 || strcmp (dbus_err->name, DBUS_ERROR_UNKNOWN_METHOD))
1096 goto error;
1097
1098 nih_free (dbus_err);
1099 continue;
1100 }
1101
1102 nih_message ("%s", status);
1103 }
1104 }
1105
1106 return 0;
1107
1108error:
1109 err = nih_error_get ();
1110 nih_error ("%s", err->message);
1111 nih_free (err);
1112
1113 return 1;
Scott James Remnant4cd63672007-03-05 16:15:39 +00001114}
1115
James Hunteec19232011-06-01 12:13:42 +01001116/**
1117 * show_config_action:
1118 * @command: NihCommand invoked,
1119 * @args: command-line arguments.
1120 *
1121 * This function is called for the "show-config" command.
1122 *
1123 * Returns: command exit status.
1124 **/
1125int
1126show_config_action (NihCommand * command,
1127 char * const *args)
1128{
1129 nih_local NihDBusProxy *upstart = NULL;
1130 nih_local char **job_class_paths = NULL;
1131 const char *upstart_job_class = NULL;
1132 NihError *err;
1133
1134 nih_assert (command != NULL);
1135 nih_assert (args != NULL);
1136
1137 upstart = upstart_open (NULL);
1138 if (! upstart)
1139 return 1;
1140
1141 if (args[0]) {
1142 /* Single job specified */
1143 upstart_job_class = args[0];
1144 job_class_paths = NIH_MUST (nih_alloc (NULL, 2*sizeof (char *)));
1145 job_class_paths[1] = NULL;
1146
1147 if (upstart_get_job_by_name_sync (NULL, upstart, upstart_job_class,
1148 job_class_paths) < 0)
1149 goto error;
1150 } else {
1151 /* Obtain a list of jobs */
1152 if (upstart_get_all_jobs_sync (NULL, upstart, &job_class_paths) < 0)
1153 goto error;
1154 }
1155
1156 for (char **job_class_path = job_class_paths;
1157 job_class_path && *job_class_path; job_class_path++) {
1158 nih_local NihDBusProxy *job_class = NULL;
1159 nih_local char *job_class_name = NULL;
1160
1161 job_class = nih_dbus_proxy_new (NULL, upstart->connection,
1162 upstart->name, *job_class_path,
1163 NULL, NULL);
1164 if (! job_class)
1165 goto error;
1166
1167 job_class->auto_start = FALSE;
1168
1169 if (job_class_get_name_sync (NULL, job_class, &job_class_name) < 0)
1170 goto error;
1171
1172 nih_message ("%s", job_class_name);
1173
1174 job_class_show_emits (NULL, job_class, job_class_name);
1175 job_class_show_conditions (job_class, job_class_name);
1176 }
1177
1178 return 0;
1179
1180error:
1181 err = nih_error_get ();
1182 nih_error ("%s", err->message);
1183 nih_free (err);
1184
1185 return 1;
1186}
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001187
Scott James Remnant4cd63672007-03-05 16:15:39 +00001188/**
1189 * emit_action:
Scott James Remnant4f19cb92007-03-09 16:48:41 +00001190 * @command: NihCommand invoked,
1191 * @args: command-line arguments.
Scott James Remnant4cd63672007-03-05 16:15:39 +00001192 *
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001193 * This function is called for the "emit" command.
Scott James Remnant4cd63672007-03-05 16:15:39 +00001194 *
Scott James Remnant4f19cb92007-03-09 16:48:41 +00001195 * Returns: command exit status.
Scott James Remnant4cd63672007-03-05 16:15:39 +00001196 **/
1197int
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001198emit_action (NihCommand * command,
Scott James Remnant4cd63672007-03-05 16:15:39 +00001199 char * const *args)
1200{
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001201 nih_local NihDBusProxy *upstart = NULL;
1202 DBusPendingCall * pending_call;
1203 int ret = 1;
1204 NihError * err;
1205
Scott James Remnant4cd63672007-03-05 16:15:39 +00001206 nih_assert (command != NULL);
1207 nih_assert (args != NULL);
1208
1209 if (! args[0]) {
1210 fprintf (stderr, _("%s: missing event name\n"), program_name);
1211 nih_main_suggest_help ();
1212 return 1;
1213 }
1214
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001215 upstart = upstart_open (NULL);
1216 if (! upstart)
Scott James Remnant4f19cb92007-03-09 16:48:41 +00001217 return 1;
Scott James Remnant4cd63672007-03-05 16:15:39 +00001218
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001219 pending_call = upstart_emit_event (upstart, args[0], &args[1], (! no_wait),
1220 (UpstartEmitEventReply)reply_handler,
1221 error_handler, &ret,
1222 NIH_DBUS_TIMEOUT_NEVER);
1223 if (! pending_call)
1224 goto error;
1225
1226 dbus_pending_call_block (pending_call);
1227 dbus_pending_call_unref (pending_call);
1228
1229 return ret;
1230
1231error:
1232 err = nih_error_get ();
1233 nih_error ("%s", err->message);
1234 nih_free (err);
1235
1236 return 1;
Scott James Remnant4cd63672007-03-05 16:15:39 +00001237}
1238
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001239
Scott James Remnant4cd63672007-03-05 16:15:39 +00001240/**
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001241 * reload_configuration_action:
Scott James Remnant4f19cb92007-03-09 16:48:41 +00001242 * @command: NihCommand invoked,
1243 * @args: command-line arguments.
Scott James Remnant4cd63672007-03-05 16:15:39 +00001244 *
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001245 * This function is called for the "reload-configuration" command.
Scott James Remnant4cd63672007-03-05 16:15:39 +00001246 *
Scott James Remnant4f19cb92007-03-09 16:48:41 +00001247 * Returns: command exit status.
Scott James Remnant4cd63672007-03-05 16:15:39 +00001248 **/
Scott James Remnant4f19cb92007-03-09 16:48:41 +00001249int
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001250reload_configuration_action (NihCommand * command,
1251 char * const *args)
Scott James Remnant4cd63672007-03-05 16:15:39 +00001252{
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001253 nih_local NihDBusProxy *upstart = NULL;
1254 NihError * err;
1255
Scott James Remnant4f19cb92007-03-09 16:48:41 +00001256 nih_assert (command != NULL);
1257 nih_assert (args != NULL);
Scott James Remnant4cd63672007-03-05 16:15:39 +00001258
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001259 upstart = upstart_open (NULL);
1260 if (! upstart)
Scott James Remnant4f19cb92007-03-09 16:48:41 +00001261 return 1;
Scott James Remnant4cd63672007-03-05 16:15:39 +00001262
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001263 if (upstart_reload_configuration_sync (NULL, upstart) < 0)
1264 goto error;
1265
1266 return 0;
1267
1268error:
1269 err = nih_error_get ();
1270 nih_error ("%s", err->message);
1271 nih_free (err);
1272
1273 return 1;
Scott James Remnant4cd63672007-03-05 16:15:39 +00001274}
1275
Scott James Remnant4cd63672007-03-05 16:15:39 +00001276
Scott James Remnant509f8a62007-03-11 17:39:27 +00001277/**
1278 * version_action:
1279 * @command: NihCommand invoked,
1280 * @args: command-line arguments.
1281 *
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001282 * This function is called for the "version" command.
Scott James Remnant509f8a62007-03-11 17:39:27 +00001283 *
1284 * Returns: command exit status.
1285 **/
1286int
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001287version_action (NihCommand * command,
Scott James Remnant509f8a62007-03-11 17:39:27 +00001288 char * const *args)
1289{
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001290 nih_local NihDBusProxy *upstart = NULL;
1291 nih_local char * version = NULL;
1292 NihError * err;
1293
Scott James Remnant509f8a62007-03-11 17:39:27 +00001294 nih_assert (command != NULL);
1295 nih_assert (args != NULL);
1296
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001297 upstart = upstart_open (NULL);
1298 if (! upstart)
Scott James Remnant509f8a62007-03-11 17:39:27 +00001299 return 1;
1300
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001301 if (upstart_get_version_sync (NULL, upstart, &version) < 0)
1302 goto error;
1303
1304 nih_message ("%s", version);
1305
1306 return 0;
1307
1308error:
1309 err = nih_error_get ();
1310 nih_error ("%s", err->message);
1311 nih_free (err);
1312
1313 return 1;
Scott James Remnant509f8a62007-03-11 17:39:27 +00001314}
1315
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001316
Scott James Remnant509f8a62007-03-11 17:39:27 +00001317/**
1318 * log_priority_action:
1319 * @command: NihCommand invoked,
1320 * @args: command-line arguments.
1321 *
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001322 * This function is called for the "log-priority" command.
Scott James Remnant509f8a62007-03-11 17:39:27 +00001323 *
1324 * Returns: command exit status.
1325 **/
1326int
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001327log_priority_action (NihCommand * command,
Scott James Remnant509f8a62007-03-11 17:39:27 +00001328 char * const *args)
1329{
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001330 nih_local NihDBusProxy *upstart = NULL;
1331 NihError * err;
Scott James Remnant509f8a62007-03-11 17:39:27 +00001332
1333 nih_assert (command != NULL);
1334 nih_assert (args != NULL);
1335
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001336 upstart = upstart_open (NULL);
1337 if (! upstart)
Scott James Remnant509f8a62007-03-11 17:39:27 +00001338 return 1;
Scott James Remnant509f8a62007-03-11 17:39:27 +00001339
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001340 if (args[0]) {
1341 if (upstart_set_log_priority_sync (NULL, upstart, args[0]) < 0)
1342 goto error;
Scott James Remnant509f8a62007-03-11 17:39:27 +00001343 } else {
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001344 nih_local char *log_priority = NULL;
Scott James Remnant509f8a62007-03-11 17:39:27 +00001345
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001346 if (upstart_get_log_priority_sync (NULL, upstart,
1347 &log_priority) < 0)
1348 goto error;
1349
1350 nih_message ("%s", log_priority);
1351 }
Scott James Remnant509f8a62007-03-11 17:39:27 +00001352
1353 return 0;
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001354
1355error:
1356 err = nih_error_get ();
1357 nih_error ("%s", err->message);
1358 nih_free (err);
1359
1360 return 1;
1361}
1362
1363
1364static void
1365start_reply_handler (char ** job_path,
1366 NihDBusMessage *message,
1367 const char * instance)
1368{
1369 nih_assert (message != NULL);
1370 nih_assert (instance != NULL);
1371
1372 /* Return the job path */
1373 *job_path = NIH_MUST (nih_strdup (NULL, instance));
1374}
1375
1376static void
1377reply_handler (int * ret,
1378 NihDBusMessage *message)
1379{
1380 nih_assert (message != NULL);
1381
1382 *ret = 0;
1383}
1384
1385static void
1386error_handler (void * data,
1387 NihDBusMessage *message)
1388{
1389 NihError *err;
1390
1391 nih_assert (message != NULL);
1392
1393 err = nih_error_get ();
1394 nih_error ("%s", err->message);
1395 nih_free (err);
Scott James Remnant509f8a62007-03-11 17:39:27 +00001396}
1397
James Hunteec19232011-06-01 12:13:42 +01001398/**
1399 * job_class_parse_events:
1400 * @condition_data: type of condition we are parsing (used as an indicator to
1401 * user) and name of job,
1402 * @variant_array: pointer to array of variants.
1403 *
1404 * The array of variants encodes the event operator tree in
1405 * Reverse Polish Notation (RPN).
1406 *
1407 * Each variant is itself an array. There are two types:
1408 *
1409 * - An "Operator" (array length == 1).
1410 *
1411 * Operators are: "/AND" and "/OR".
1412 *
1413 * - An "Event" (array length >= 1).
1414 *
1415 * Each Event comprises a name (array element zero), followed by zero or
1416 * more "Event Matches". If the first Event Match is of the form "JOB=name",
1417 * or is a single token "name" (crucially not containining "="), then
1418 * 'name' refers to the job which emitted the event.
1419 **/
1420void
1421job_class_parse_events (const ConditionHandlerData *data, char ** const *variant_array)
1422{
1423 char ** const *variant;
1424 char **arg;
1425 char *token;
1426 nih_local NihList *rpn_stack = NULL;
1427 char *name = NULL;
1428 const char *stanza_name;
1429 const char *job_class_name;
1430
1431 nih_assert (data);
1432
1433 stanza_name = ((ConditionHandlerData *)data)->condition_name;
1434 job_class_name = ((ConditionHandlerData *)data)->job_class_name;
1435
1436 if (! variant_array || ! *variant_array || ! **variant_array)
1437 return;
1438
1439 STACK_CREATE (rpn_stack);
1440 STACK_SHOW (rpn_stack);
1441
1442 for (variant = variant_array; variant && *variant && **variant; variant++, name = NULL) {
1443
1444 /* token is either the first token beyond the stanza name (ie the event name),
1445 * or an operator.
1446 */
1447 token = **variant;
1448
1449 if (IS_OPERATOR (token)) {
1450 /* Used to hold result of combining top two stack elements. */
1451 nih_local char *new_token = NULL;
1452
1453 nih_local NihList *first = NULL;
1454 nih_local NihList *second = NULL;
1455
1456 if (enumerate_events) {
1457 /* We only care about operands in this mode. */
1458 continue;
1459 }
1460
1461 first = NIH_MUST (nih_list_new (NULL));
1462 second = NIH_MUST (nih_list_new (NULL));
1463
1464 /* Found an operator, so pop 2 values off stack,
1465 * combine them and push back onto stack.
1466 */
1467 STACK_POP (rpn_stack, first);
1468 STACK_POP (rpn_stack, second);
1469
1470 new_token = NIH_MUST (nih_strdup (NULL, ""));
1471 new_token = NIH_MUST (nih_strcat_sprintf (&new_token,
1472 NULL,
1473 "(%s %s %s)",
1474 ((NihListEntry *)second)->str,
1475 IS_OP_AND (token) ? "and" : "or",
1476 ((NihListEntry *)first)->str));
1477
1478 STACK_PUSH_NEW_ELEM (rpn_stack, new_token);
1479 } else {
1480 /* Save operand token (event or job), add
1481 * arguments (job names and env vars) and push
1482 * onto stack. If we are enumerating_events,
1483 * this records the environment only.
1484 */
1485 nih_local char *element = NULL;
1486 int i;
1487
1488 element = NIH_MUST (nih_strdup (NULL,
1489 enumerate_events ? "" : token));
1490
1491 /* Handle arguments (job names and env vars). */
1492 arg = (*variant)+1;
1493
1494 for (i=0; arg[i] && *arg[i]; i++) {
1495 if (enumerate_events && IS_JOB_EVENT (token)) {
1496 if (!name) {
1497 GET_JOB_NAME (name, i, arg[i]);
1498 if (name)
1499 continue;
1500 }
1501 }
1502
1503 element = NIH_MUST (nih_strcat (&element, NULL, " "));
1504 element = NIH_MUST (nih_strcat (&element, NULL, arg[i]));
1505 }
1506
1507 if (enumerate_events) {
1508 nih_message (" %s %s (job:%s%s, env:%s)",
1509 stanza_name,
1510 token,
1511 name ? " " : "",
1512 name ? name : "",
1513 element);
1514 } else {
1515 STACK_PUSH_NEW_ELEM (rpn_stack, element);
1516 }
1517
1518 }
1519 }
1520
1521 if (enumerate_events)
1522 return;
1523
1524 /* Handle case where a single event was specified (there
1525 * was no operator to pop the entry off the stack).
1526 */
1527 if (! STACK_EMPTY (rpn_stack)) {
1528 if (! enumerate_events) {
1529 /* Our job is done: show the user what we found. */
1530 nih_message (" %s %s", stanza_name,
1531 STACK_PEEK (rpn_stack));
1532 }
1533 }
1534}
1535
1536/**
1537 * job_class_show_conditions:
1538 * @job_class_proxy: D-Bus proxy for job class.
1539 * @job_class_name: Name of config whose conditions we wish to display.
1540 *
1541 * Register D-Bus call-backs to display job classes start on and stop on
1542 * conditions.
1543 **/
1544void
1545job_class_show_conditions (NihDBusProxy *job_class_proxy, const char *job_class_name)
1546{
1547 DBusPendingCall *pending_call;
1548 NihError *err;
1549 ConditionHandlerData start_data, stop_data;
1550
1551 nih_assert (job_class_proxy);
1552 nih_assert (job_class_name);
1553
1554 start_data.condition_name = "start on";
1555 start_data.job_class_name = job_class_name;
1556
1557 stop_data.condition_name = "stop on";
1558 stop_data.job_class_name = job_class_name;
1559
1560 pending_call = job_class_get_start_on (job_class_proxy,
1561 job_class_condition_handler,
1562 job_class_condition_err_handler,
1563 &start_data,
1564 NIH_DBUS_TIMEOUT_NEVER);
1565
1566 if (!pending_call)
1567 goto error;
1568
1569 /* wait for completion */
1570 dbus_pending_call_block (pending_call);
1571 dbus_pending_call_unref (pending_call);
1572
1573 pending_call = job_class_get_stop_on (job_class_proxy,
1574 job_class_condition_handler,
1575 job_class_condition_err_handler,
1576 &stop_data,
1577 NIH_DBUS_TIMEOUT_NEVER);
1578
1579 if (!pending_call)
1580 goto error;
1581
1582 /* wait for completion */
1583 dbus_pending_call_block (pending_call);
1584 dbus_pending_call_unref (pending_call);
1585
1586 return;
1587
1588error:
1589 err = nih_error_get ();
1590 nih_error ("%s", err->message);
1591 nih_free (err);
1592}
1593
1594/**
1595 * job_class_show_emits:
1596 * @parent: parent object,
1597 * @job_class_proxy: D-Bus proxy for job class,
1598 * @job_class_name: Name of job class that emits an event.
1599 *
1600 * Display events job class emits to user.
1601 **/
1602void
1603job_class_show_emits (const void *parent, NihDBusProxy *job_class_proxy, const char *job_class_name)
1604{
1605 NihError *err;
1606 nih_local char **job_emits = NULL;
1607
1608 nih_assert (job_class_proxy);
1609
1610 if (job_class_get_emits_sync (parent, job_class_proxy, &job_emits) < 0) {
1611 goto error;
1612 }
1613
1614 if (job_emits && *job_emits) {
1615 char **p = job_emits;
1616 while (*p) {
1617 nih_message (" emits %s", *p);
1618 p++;
1619 }
1620 }
1621
1622 return;
1623
1624error:
1625 err = nih_error_get ();
1626 nih_error ("%s", err->message);
1627 nih_free (err);
1628}
1629
1630/**
1631 * job_class_condition_handler:
1632 * @data: data passed via job_class_get_start_on() or job_class_get_stop_on(),
1633 * @message: D-Bus message received,
1634 * @value: array of variants generated by D-Bus call we are registering
1635 * with.
1636 *
1637 * Handler for D-Bus message encoding a job classes "start on" or
1638 * "stop on" condtions.
1639 **/
1640void
1641job_class_condition_handler (void *data, NihDBusMessage *message, char ** const *value)
1642{
1643 job_class_parse_events ((const ConditionHandlerData *)data, value);
1644}
1645
1646/**
1647 * job_class_condition_err_handler:
1648 *
1649 * @data data passed via job_class_get_start_on() or job_class_get_stop_on(),
1650 * @message: D-Bus message received.
1651 *
1652 * Error handler for D-Bus message encoding a job classes "start on" or
1653 * "stop on" conditions.
1654 **/
1655void
1656job_class_condition_err_handler (void *data, NihDBusMessage *message)
1657{
1658 /* no remedial action possible */
1659}
Scott James Remnant4cd63672007-03-05 16:15:39 +00001660
1661#ifndef TEST
Scott James Remnant3bcd15e2006-08-19 19:50:12 +01001662/**
1663 * options:
1664 *
1665 * Command-line options accepted for all arguments.
1666 **/
Scott James Remnant5befd932006-08-19 19:24:54 +01001667static NihOption options[] = {
James Hunt5f0b3542011-06-01 10:42:05 +01001668 { 0, "session", N_("use D-Bus session bus to connect to init daemon (for testing)"),
1669 NULL, NULL, NULL, dbus_bus_type_setter },
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001670 { 0, "system", N_("use D-Bus system bus to connect to init daemon"),
James Hunt5f0b3542011-06-01 10:42:05 +01001671 NULL, NULL, NULL, dbus_bus_type_setter },
1672 { 0, "dest", N_("destination well-known name on D-Bus bus"),
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001673 NULL, "NAME", &dest_name, NULL },
Scott James Remnant4f19cb92007-03-09 16:48:41 +00001674
1675 NIH_OPTION_LAST
1676};
1677
1678
1679/**
1680 * start_options:
1681 *
1682 * Command-line options accepted for the start command.
1683 **/
1684NihOption start_options[] = {
Scott James Remnant4f19cb92007-03-09 16:48:41 +00001685 { 'n', "no-wait", N_("do not wait for job to start before exiting"),
1686 NULL, NULL, &no_wait, NULL },
Scott James Remnantcbd0cf82007-02-03 17:05:39 +00001687
1688 NIH_OPTION_LAST
1689};
1690
1691/**
Scott James Remnant4f19cb92007-03-09 16:48:41 +00001692 * stop_options:
Scott James Remnantcbd0cf82007-02-03 17:05:39 +00001693 *
Scott James Remnant4f19cb92007-03-09 16:48:41 +00001694 * Command-line options accepted for the stop command.
Scott James Remnantcbd0cf82007-02-03 17:05:39 +00001695 **/
Scott James Remnant4f19cb92007-03-09 16:48:41 +00001696NihOption stop_options[] = {
Scott James Remnant4f19cb92007-03-09 16:48:41 +00001697 { 'n', "no-wait", N_("do not wait for job to stop before exiting"),
1698 NULL, NULL, &no_wait, NULL },
1699
1700 NIH_OPTION_LAST
1701};
1702
1703/**
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001704 * restart_options:
1705 *
1706 * Command-line options accepted for the restart command.
1707 **/
1708NihOption restart_options[] = {
1709 { 'n', "no-wait", N_("do not wait for job to restart before exiting"),
1710 NULL, NULL, &no_wait, NULL },
1711
1712 NIH_OPTION_LAST
1713};
1714
1715/**
Scott James Remnant004d8c02010-02-04 11:08:07 -08001716 * reload_options:
1717 *
1718 * Command-line options accepted for the reload command.
1719 **/
1720NihOption reload_options[] = {
1721 NIH_OPTION_LAST
1722};
1723
1724/**
Scott James Remnant4f19cb92007-03-09 16:48:41 +00001725 * status_options:
1726 *
1727 * Command-line options accepted for the status command.
1728 **/
1729NihOption status_options[] = {
Scott James Remnantcbd0cf82007-02-03 17:05:39 +00001730 NIH_OPTION_LAST
1731};
1732
1733/**
1734 * list_options:
1735 *
1736 * Command-line options accepted for the list command.
1737 **/
1738NihOption list_options[] = {
1739 NIH_OPTION_LAST
1740};
1741
1742/**
Scott James Remnantcbd0cf82007-02-03 17:05:39 +00001743 * emit_options:
1744 *
Scott James Remnante8f3ef92007-02-06 20:20:33 +00001745 * Command-line options accepted for the emit command.
Scott James Remnantcbd0cf82007-02-03 17:05:39 +00001746 **/
1747NihOption emit_options[] = {
Scott James Remnant4f19cb92007-03-09 16:48:41 +00001748 { 'n', "no-wait", N_("do not wait for event to finish before exiting"),
1749 NULL, NULL, &no_wait, NULL },
Scott James Remnant08146b92007-02-06 20:45:38 +00001750
Scott James Remnantcbd0cf82007-02-03 17:05:39 +00001751 NIH_OPTION_LAST
1752};
1753
1754/**
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001755 * reload_configuration_options:
Scott James Remnant4f19cb92007-03-09 16:48:41 +00001756 *
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001757 * Command-line options accepted for the reload-configuration command.
Scott James Remnant4f19cb92007-03-09 16:48:41 +00001758 **/
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001759NihOption reload_configuration_options[] = {
Scott James Remnant509f8a62007-03-11 17:39:27 +00001760 NIH_OPTION_LAST
1761};
1762
1763/**
1764 * version_options:
1765 *
1766 * Command-line options accepted for the version command.
1767 **/
1768NihOption version_options[] = {
1769 NIH_OPTION_LAST
1770};
1771
1772/**
1773 * log_priority_options:
1774 *
1775 * Command-line options accepted for the log-priority command.
1776 **/
1777NihOption log_priority_options[] = {
Scott James Remnant5befd932006-08-19 19:24:54 +01001778 NIH_OPTION_LAST
1779};
1780
1781
Scott James Remnant48622982006-10-13 15:15:50 +01001782/**
James Hunteec19232011-06-01 12:13:42 +01001783 * show_config_options:
1784 *
1785 * Command-line options accepted for the show-config command.
1786 **/
1787NihOption show_config_options[] = {
1788 { 'e', "enumerate",
1789 N_("enumerate list of events and jobs causing job "
1790 "created from job config to start/stop"),
1791 NULL, NULL, &enumerate_events, NULL },
1792
1793 NIH_OPTION_LAST
1794};
1795
1796/**
Scott James Remnant48622982006-10-13 15:15:50 +01001797 * job_group:
1798 *
1799 * Group of commands related to jobs.
1800 **/
1801static NihCommandGroup job_commands = { N_("Job") };
1802
1803/**
1804 * event_group:
1805 *
1806 * Group of commands related to events.
1807 **/
1808static NihCommandGroup event_commands = { N_("Event") };
1809
1810/**
1811 * commands:
1812 *
1813 * Commands accepts as the first non-option argument, or program name.
1814 **/
1815static NihCommand commands[] = {
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001816 { "start", N_("JOB [KEY=VALUE]..."),
1817 N_("Start job."),
1818 N_("JOB is the name of the job that is to be started, this may "
1819 "be followed by zero or more environment variables to be "
1820 "defined in the new job.\n"
1821 "\n"
1822 "The environment may also serve to distinguish between job "
1823 "instances, and thus decide whether a new instance will be "
1824 "started or an error returned if an existing instance is "
1825 "already running."),
Scott James Remnant48622982006-10-13 15:15:50 +01001826 &job_commands, start_options, start_action },
1827
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001828 { "stop", N_("JOB [KEY=VALUE]..."),
1829 N_("Stop job."),
1830 N_("JOB is the name of the job that is to be stopped, this may "
1831 "be followed by zero or more environment variables to be "
1832 "passed to the job's pre-stop and post-stop processes.\n"
1833 "\n"
1834 "The environment also serves to distinguish between job "
1835 "instances, and thus decide which of multiple instances will "
1836 "be stopped."),
Scott James Remnant4f19cb92007-03-09 16:48:41 +00001837 &job_commands, stop_options, stop_action },
Scott James Remnant48622982006-10-13 15:15:50 +01001838
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001839 { "restart", N_("JOB [KEY=VALUE]..."),
1840 N_("Restart job."),
1841 N_("JOB is the name of the job that is to be restarted, this may "
1842 "be followed by zero or more environment variables to be "
1843 "defined in the job after restarting.\n"
1844 "\n"
1845 "The environment also serves to distinguish between job "
1846 "instances, and thus decide which of multiple instances will "
1847 "be restarted."),
1848 &job_commands, restart_options, restart_action },
1849
Scott James Remnant004d8c02010-02-04 11:08:07 -08001850 { "reload", N_("JOB [KEY=VALUE]..."),
1851 N_("Send HUP signal to job."),
1852 N_("JOB is the name of the job that is to be sent the signal, "
1853 "this may be followed by zero or more environment variables "
1854 "to distinguish between job instances.\n"),
1855 &job_commands, reload_options, reload_action },
1856
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001857 { "status", N_("JOB [KEY=VALUE]..."),
1858 N_("Query status of job."),
1859 N_("JOB is the name of the job that is to be queried, this may "
1860 "be followed by zero or more environment variables to "
1861 "distguish between job instances.\n" ),
Scott James Remnant4f19cb92007-03-09 16:48:41 +00001862 &job_commands, status_options, status_action },
Scott James Remnant48622982006-10-13 15:15:50 +01001863
1864 { "list", NULL,
1865 N_("List known jobs."),
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001866 N_("The known jobs and their current status will be output."),
Scott James Remnant48622982006-10-13 15:15:50 +01001867 &job_commands, list_options, list_action },
1868
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001869 { "emit", N_("EVENT [KEY=VALUE]..."),
Scott James Remnant48622982006-10-13 15:15:50 +01001870 N_("Emit an event."),
Scott James Remnant08146b92007-02-06 20:45:38 +00001871 N_("EVENT is the name of an event the init daemon should emit, "
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001872 "this may be followed by zero or more environment variables "
1873 "to be included in the event.\n"),
Scott James Remnant48622982006-10-13 15:15:50 +01001874 &event_commands, emit_options, emit_action },
1875
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001876 { "reload-configuration", NULL,
1877 N_("Reload the configuration of the init daemon."),
Scott James Remnant48622982006-10-13 15:15:50 +01001878 NULL,
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001879 NULL, reload_configuration_options, reload_configuration_action },
Scott James Remnant509f8a62007-03-11 17:39:27 +00001880 { "version", NULL,
1881 N_("Request the version of the init daemon."),
1882 NULL,
1883 NULL, version_options, version_action },
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001884 { "log-priority", N_("[PRIORITY]"),
Scott James Remnant509f8a62007-03-11 17:39:27 +00001885 N_("Change the minimum priority of log messages from the init "
1886 "daemon"),
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001887 N_("PRIORITY may be one of:\n"
1888 " `debug' (messages useful for debugging upstart are logged, "
1889 "equivalent to --debug on kernel command-line);\n"
1890 " `info' (messages about job goal and state changes, as well "
Scott James Remnant509f8a62007-03-11 17:39:27 +00001891 "as event emissions are logged, equivalent to --verbose on the "
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001892 "kernel command-line);\n"
1893 " `message' (informational and debugging messages are suppressed, "
Scott James Remnant509f8a62007-03-11 17:39:27 +00001894 "the default); "
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001895 " `warn' (ordinary messages are suppressed whilst still "
1896 "logging warnings and errors);\n"
1897 " `error' (only errors are logged, equivalent to --quiet on "
1898 "the kernel command-line) or\n"
1899 " `fatal' (only fatal errors are logged).\n"
1900 "\n"
1901 "Without arguments, this outputs the current log priority."),
Scott James Remnantbea9e8d2007-03-11 17:41:58 +00001902 NULL, log_priority_options, log_priority_action },
Scott James Remnant509f8a62007-03-11 17:39:27 +00001903
James Hunteec19232011-06-01 12:13:42 +01001904 { "show-config", N_("[CONF]"),
1905 N_("Show emits, start on and stop on details for job configurations."),
1906 N_("If CONF specified, show configuration details for single job "
1907 "configuration, else show details for all jobs configurations.\n"),
1908 NULL, show_config_options, show_config_action },
1909
Scott James Remnant48622982006-10-13 15:15:50 +01001910 NIH_COMMAND_LAST
1911};
1912
1913
Scott James Remnant5befd932006-08-19 19:24:54 +01001914int
1915main (int argc,
1916 char *argv[])
1917{
Scott James Remnant48622982006-10-13 15:15:50 +01001918 int ret;
Scott James Remnant3bcd15e2006-08-19 19:50:12 +01001919
Scott James Remnant5befd932006-08-19 19:24:54 +01001920 nih_main_init (argv[0]);
1921
Scott James Remnant66384202007-01-06 14:23:18 +00001922 ret = nih_command_parser (NULL, argc, argv, options, commands);
Scott James Remnante5d3f012007-02-07 01:59:57 +00001923 if (ret < 0)
1924 exit (1);
Scott James Remnant66384202007-01-06 14:23:18 +00001925
Scott James Remnantcf2e8332009-07-06 20:32:07 +01001926 dbus_shutdown ();
1927
Scott James Remnant66384202007-01-06 14:23:18 +00001928 return ret;
Scott James Remnant48622982006-10-13 15:15:50 +01001929}
Scott James Remnant4cd63672007-03-05 16:15:39 +00001930#endif