Пример #1
0
/**
 * apparmor_switch:
 * @profile: AppArmor profile to switch to
 *
 * This function switches to a new AppArmor profile on exec
 *
 * Returns: zero on success, -1 on error
 **/
int
apparmor_switch (char *profile)
{
	nih_local char *filename = NULL;
	FILE           *f;

	nih_assert (profile != NULL);

	/* Silently fail if AppArmor isn't enabled. */
	if (! apparmor_available())
		return 0;

	filename = nih_sprintf (NULL, "/proc/%d/attr/exec", getpid());

	if (! filename)
		return -1;

	f = fopen (filename, "w");

	if (! f)
		return -1;

	fprintf (f, "exec %s\n", profile);

	if (fclose (f))
		return -1;

	return 0;
}
Пример #2
0
/**
 * nih_dbus_error_raise:
 * @name: D-Bus name for error,
 * @message: Human-readable error message.
 *
 * Raises an error which includes a D-Bus name so that it may be sent as
 * a reply to a method call, the error type is fixed to NIH_DBUS_ERROR.
 *
 * You may use this in D-Bus handlers and return a negative number to
 * automatically have this error returned as the method reply.  It is also
 * useful when mixing D-Bus and libnih function calls in your own methods
 * to return consistent error forms, in which case pass the name and message
 * members of the DBusError structure before freeing it.
 **/
void
nih_dbus_error_raise (const char *name,
		      const char *message)
{
	NihDBusError *err;

	nih_assert (name != NULL);
	nih_assert (message != NULL);

	err = NIH_MUST (nih_new (NULL, NihDBusError));

	err->number = NIH_DBUS_ERROR;
	err->name = NIH_MUST (nih_strdup (err, name));
	err->message = NIH_MUST (nih_strdup (err, message));

	nih_error_raise_error ((NihError *)err);
}
static int
my_com_netsplit_Nih_Test_touch_set (NihDBusObject *  object,
                                    NihDBusMessage * message,
                                    DBusMessageIter *iter)
{
	DBusMessageIter variter;
	int             value;

	nih_assert (object != NULL);
	nih_assert (message != NULL);
	nih_assert (iter != NULL);

	/* Recurse into the variant */
	if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_VARIANT) {
		nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
		                             "Invalid arguments to touch property");
		return -1;
	}

	dbus_message_iter_recurse (iter, &variter);

	/* Demarshal a int from the message */
	if (dbus_message_iter_get_arg_type (&variter) != DBUS_TYPE_BOOLEAN) {
		nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
		                             "Invalid arguments to touch property");
		return -1;
	}

	dbus_message_iter_get_basic (&variter, &value);

	dbus_message_iter_next (&variter);

	dbus_message_iter_next (iter);

	if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_INVALID) {
		nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
		                             "Invalid arguments to touch property");
		return -1;
	}

	/* Call the handler function */
	if (my_test_set_touch (object->data, message, value) < 0)
		return -1;

	return 0;
}
Пример #4
0
/**
 * nih_error_init:
 *
 * Initialise the context stack.
 **/
void
nih_error_init (void)
{
	if (! context_stack) {
		context_stack = NIH_MUST (nih_list_new (NULL));

		nih_error_push_context ();

		nih_assert (atexit (nih_error_clear) == 0);
	}
}
int
my_test_emit_bounce (DBusConnection *connection,
                     const char *    origin_path,
                     uint32_t        height,
                     int32_t         velocity)
{
	DBusMessage *   signal;
	DBusMessageIter iter;

	nih_assert (connection != NULL);
	nih_assert (origin_path != NULL);

	/* Construct the message. */
	signal = dbus_message_new_signal (origin_path, "com.netsplit.Nih.Test", "Bounce");
	if (! signal)
		return -1;

	dbus_message_iter_init_append (signal, &iter);

	/* Marshal a uint32_t onto the message */
	if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &height)) {
		dbus_message_unref (signal);
		return -1;
	}

	/* Marshal a int32_t onto the message */
	if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &velocity)) {
		dbus_message_unref (signal);
		return -1;
	}

	/* Send the signal, appending it to the outgoing queue. */
	if (! dbus_connection_send (connection, signal, NULL)) {
		dbus_message_unref (signal);
		return -1;
	}

	dbus_message_unref (signal);

	return 0;
}
int
my_test_peek_reply (NihDBusMessage *message,
                    const char *    value)
{
	DBusMessage *   reply;
	DBusMessageIter iter;

	nih_assert (message != NULL);
	nih_assert (value != NULL);

	/* If the sender doesn't care about a reply, don't bother wasting
	 * effort constructing and sending one.
	 */
	if (dbus_message_get_no_reply (message->message))
		return 0;

	/* Construct the reply message. */
	reply = dbus_message_new_method_return (message->message);
	if (! reply)
		return -1;

	dbus_message_iter_init_append (reply, &iter);

	/* Marshal a char * onto the message */
	if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value)) {
		dbus_message_unref (reply);
		return -1;
	}

	/* Send the reply, appending it to the outgoing queue. */
	if (! dbus_connection_send (message->connection, reply, NULL)) {
		dbus_message_unref (reply);
		return -1;
	}

	dbus_message_unref (reply);

	return 0;
}
Пример #7
0
/**
 * nih_dbus_error_raise_printf:
 * @name: D-Bus name for error,
 * @format: format string for human-readable message.
 *
 * Raises an error which includes a D-Bus name so that it may be sent as
 * a reply to a method call, the error type is fixed to NIH_DBUS_ERROR.
 *
 * The human-readable message for the error is parsed according to @format,
 * and allocated as a child of the error object so that it is freed.
 *
 * You may use this in D-Bus handlers and return a negative number to
 * automatically have this error returned as the method reply.  It is also
 * useful when mixing D-Bus and libnih function calls in your own methods
 * to return consistent error forms, in which case pass the name and message
 * members of the DBusError structure before freeing it.
 **/
void
nih_dbus_error_raise_printf (const char *name,
			     const char *format,
			     ...)
{
	NihDBusError *err;
	va_list       args;

	nih_assert (name != NULL);
	nih_assert (format != NULL);

	err = NIH_MUST (nih_new (NULL, NihDBusError));

	err->number = NIH_DBUS_ERROR;

	err->name = NIH_MUST (nih_strdup (err, name));

	va_start (args, format);
	err->message = NIH_MUST (nih_vsprintf (err, format, args));
	va_end (args);

	nih_error_raise_error ((NihError *)err);
}
static int
my_com_netsplit_Nih_Test_size_get (NihDBusObject *  object,
                                   NihDBusMessage * message,
                                   DBusMessageIter *iter)
{
	DBusMessageIter variter;
	uint32_t        value;

	nih_assert (object != NULL);
	nih_assert (message != NULL);
	nih_assert (iter != NULL);

	/* Call the handler function */
	if (my_test_get_size (object->data, message, &value) < 0)
		return -1;

	/* Append a variant onto the message to contain the property value. */
	if (! dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "u", &variter)) {
		nih_error_raise_no_memory ();
		return -1;
	}

	/* Marshal a uint32_t onto the message */
	if (! dbus_message_iter_append_basic (&variter, DBUS_TYPE_UINT32, &value)) {
		dbus_message_iter_abandon_container (iter, &variter);
		nih_error_raise_no_memory ();
		return -1;
	}

	/* Finish the variant */
	if (! dbus_message_iter_close_container (iter, &variter)) {
		nih_error_raise_no_memory ();
		return -1;
	}

	return 0;
}
Пример #9
0
/**
 * nih_error_clear:
 *
 * Ensure that the current context has no raised error, if it does then
 * there's a programming error so we abort after logging where the error
 * was originally raised.
 **/
static void
nih_error_clear (void)
{
	nih_assert (context_stack != NULL);

	if (! NIH_UNLIKELY (CURRENT_CONTEXT->error))
		return;

	nih_fatal ("%s:%d: Unhandled error from %s: %s",
		   CURRENT_CONTEXT->error->filename,
		   CURRENT_CONTEXT->error->line,
		   CURRENT_CONTEXT->error->function,
		   CURRENT_CONTEXT->error->message);
	abort ();
}
Пример #10
0
/**
 * _nih_error_raise_system:
 * @filename: filename where the error was raised,
 * @line: line number of @filename where the error was raised,
 * @function: function name the error was raised within.
 *
 * Raises an error with details taken from the current value of errno,
 * if an unhandled error already exists then an error message is emmitted
 * through the logging system; you should try to avoid this.
 *
 * This function should never be called directly, instead use the
 * nih_error_raise_system() macro to pass the correct arguments for @filename,
 * @line and @function.
 **/
void
_nih_error_raise_system (const char *filename,
			 int         line,
			 const char *function)
{
	NihError *error;
	int       saved_errno;

	nih_assert (filename != NULL);
	nih_assert (line > 0);
	nih_assert (function != NULL);
	nih_assert (errno > 0);
	saved_errno = errno;

	nih_error_init ();

	error = NIH_MUST (nih_new (NULL, NihError));

	error->number = saved_errno;
	error->message = NIH_MUST (nih_strdup (error, strerror (saved_errno)));

	_nih_error_raise_error (filename, line, function, error);
	errno = saved_errno;
}
Пример #11
0
/**
 * _nih_error_raise:
 * @filename: filename where the error was raised,
 * @line: line number of @filename where the error was raised,
 * @function: function name the error was raised within,
 * @number: numeric identifier,
 * @message: human-readable message.
 *
 * Raises an error with the given details in the current error context,
 * if an unhandled error already exists then an error message is emmitted
 * through the logging system; you should try to avoid this.
 *
 * @message should be a static string, as it will not be freed when the
 * error object is.
 *
 * This function should never be called directly, instead use the
 * nih_error_raise() macro to pass the correct arguments for @filename,
 * @line and @function.
 **/
void
_nih_error_raise (const char *filename,
		  int         line,
		  const char *function,
		  int         number,
		  const char *message)
{
	NihError *error;

	nih_assert (filename != NULL);
	nih_assert (line > 0);
	nih_assert (function != NULL);
	nih_assert (number > 0);
	nih_assert (message != NULL);

	nih_error_init ();

	error = NIH_MUST (nih_new (NULL, NihError));

	error->number = number;
	error->message = message;

	_nih_error_raise_error (filename, line, function, error);
}
Пример #12
0
/**
 * type_of:
 * @parent: parent object for new string,
 * @iter: D-Bus signature iterator.
 *
 * Converts the D-Bus basic type at the current element of the iterator
 * @iter into an appropriate C type to hold it.
 *
 * If @parent is not NULL, it should be a pointer to another object which
 * will be used as a parent for the returned string.  When all parents
 * of the returned string are freed, the returned string will also be
 * freed.
 *
 * Returns: newly allocated string or NULL if allocation failed.
 **/
char *
type_of (const void *       parent,
	 DBusSignatureIter *iter)
{
	int dbus_type;

	nih_assert (iter != NULL);

	dbus_type = dbus_signature_iter_get_current_type (iter);

	switch (dbus_type) {
	case DBUS_TYPE_BYTE:
		return nih_strdup (parent, "uint8_t");
	case DBUS_TYPE_BOOLEAN:
		return nih_strdup (parent, "int");
	case DBUS_TYPE_INT16:
		return nih_strdup (parent, "int16_t");
	case DBUS_TYPE_UINT16:
		return nih_strdup (parent, "uint16_t");
	case DBUS_TYPE_INT32:
		return nih_strdup (parent, "int32_t");
	case DBUS_TYPE_UINT32:
		return nih_strdup (parent, "uint32_t");
	case DBUS_TYPE_INT64:
		return nih_strdup (parent, "int64_t");
	case DBUS_TYPE_UINT64:
		return nih_strdup (parent, "uint64_t");
	case DBUS_TYPE_DOUBLE:
		return nih_strdup (parent, "double");
	case DBUS_TYPE_STRING:
		return nih_strdup (parent, "char *");
	case DBUS_TYPE_OBJECT_PATH:
		return nih_strdup (parent, "char *");
	case DBUS_TYPE_SIGNATURE:
		return nih_strdup (parent, "char *");
	case DBUS_TYPE_UNIX_FD:
		return nih_strdup (parent, "int");
	default:
		nih_assert_not_reached ();
	}
}
Пример #13
0
/**
 * make_safe_string:
 * @parent: parent,
 * @original: original string.
 *
 * Strip non-printable and non-blank bytes from specified string.
 *
 * Notes:
 *
 * Sadly, this is necessary as some hardware (such as battery devices)
 * exposes non-printable bytes in their descriptive registers to the
 * kernel. Since neither the kernel nor udev specify any encoding for
 * udev messages, these (probably bogus) bytes get passed up to userland
 * to deal with. This is sub-optimal since it implies that _every_
 * application that processes udev messages must perform its own
 * sanitizing on the messages. Let's just hope they all deal with the
 * problem in the same way...
 *
 * Note that *iff* the kernel/udev did specify an encoding model, this
 * problem could go away since one of the lower layers could then
 * detect the out-of-bound data and deal with it at source. All instances
 * of this issue seen so far seem to indicate the binary control data
 * being presented by the hardware is in fact bogus ("corruption") and
 * looks like some block of memory has not been initialized correctly.
 *
 * The approach taken here is to simulate the approach already adopted
 * by 'upower' (up_device_supply_make_safe_string()), with the exception
 * that we also allow blank characters (such as tabs).
 *
 * Returns a copy of @original stripped of all non-printable and
 * non-blank characters, or NULL if insufficient memory.
 **/
char *
make_safe_string (const void *parent, const char *original)
{
	size_t   len;
	size_t   i, j;
	char    *cleaned;

	nih_assert (original);

	len = strlen (original);

	cleaned = nih_alloc (parent, len + 1);

	if (! cleaned)
		return NULL;

	for (i=0, j=0; i < len; ) {
		/* Skip over bogus bytes */
		if (! (isprint (original[i]) || isblank (original[i]))) {
			i++;
			continue;
		}

		/* Copy what remains */
		cleaned[j] = original[i];
		i++; j++;
	}

	/* Terminate */
	cleaned[j] = '\0';

	if (i != j)
		nih_debug ("removed unexpected bytes from udev message data");

	/* Note that strictly we should realloc the string if
	 * bogus bytes were found (since it will now be shorter).
	 * However, since all the strings are short (and short-lived) we
	 * do not do this to avoid the associated overhead.
	 */
	return cleaned;
}
Пример #14
0
/**
 * type_var_layout:
 * @parent: parent object for new string,
 * @vars: list of variables to convert.
 *
 * Returns a string for the list of variables @vars, each of which should
 * be a TypeVar structure.  Each variable is declared on a new line,
 * with the names lined up to the longest type length.
 *
 * If @parent is not NULL, it should be a pointer to another object which
 * will be used as a parent for the returned string.  When all parents
 * of the returned string are freed, the returned string will also be
 * freed.
 *
 * Returns: the newly allocated string or NULL if insufficient memory.
 **/
char *
type_var_layout (const void *parent,
		 NihList *   vars)
{
	size_t max;
	size_t len;
	char * str;

	nih_assert (vars != NULL);

	/* Work out how much space to have for the types */
	max = 0;
	NIH_LIST_FOREACH (vars, iter) {
		TypeVar *var = (TypeVar *)iter;
		size_t   this_len;

		this_len = strlen (var->type);
		if (! strchr (var->type, '*'))
			this_len++;

		if (this_len > max)
			max = this_len;
	}
Пример #15
0
/**
 * session_new:
 * @parent: parent,
 * @chroot: full chroot path,
 * @user: user id.
 *
 * Create a new session.
 *
 * Return new Session, or NULL on error.
 **/
Session *
session_new (const void *parent,
	     const char *chroot,
	     uid_t       user)
{
	Session *session;

	nih_assert ((chroot != NULL) || (user != 0));

	session_init ();

	session = nih_new (parent, Session);
	if (! session)
		return NULL;

	nih_list_init (&session->entry);

	if (chroot) {
		session->chroot = nih_strdup (session, chroot);
		if (! session->chroot) {
			nih_free (session);
			return NULL;
		}
	} else {
		session->chroot = NULL;
	}

	session->user = user;

	session->conf_path = NULL;

	nih_alloc_set_destructor (session, nih_list_destroy);

	nih_list_add (sessions, &session->entry);

	return session;
}
Пример #16
0
/**
 * fgets_alloc:
 * @stream: stdio stream to read from.
 *
 * Reads from stream up to EOF or a newline, without any line-length
 * limitations.
 *
 * Returns: static string containing the entire line WITHOUT the
 * terminating newline, or NULL if end of file is reached and nothing
 * was read.
 **/
char *
fgets_alloc (const void *parent,
	     FILE *      stream)
{
        char * buf = NULL;
        size_t buf_sz = 0;
	size_t buf_len = 0;

	nih_assert (stream != NULL);

	for (;;) {
		char *ret;
		char *pos;

		if (buf_sz <= (buf_len + 1)) {
			buf_sz += 4096;
			buf = NIH_MUST (nih_realloc (buf, parent, buf_sz));
		}

		ret = fgets (buf + buf_len, buf_sz - buf_len, stream);
		if ((! ret) && (! buf_len)) {
			nih_free (buf);
			return NULL;
		} else if (! ret) {
			return buf;
		}

		buf_len += strlen (ret);
		pos = strchr (ret, '\n');
		if (pos) {
			*pos = '\0';
			break;
		}
	}

	return buf;
}
Пример #17
0
/**
 * _nih_error_raise_error:
 * @filename: filename where the error was raised,
 * @line: line number of @filename where the error was raised,
 * @function: function name the error was raised within,
 * @error: existing object to raise.
 *
 * Raises the existing error object in the current error context,
 * if an unhandled error already exists then an error message is emmitted
 * through the logging system; you should try to avoid this.
 *
 * This is normally used to raise a taken error that has not been handled,
 * or to raise a custom error object.
 *
 * The destructor of @error will be overwritten so that the context can
 * be cleared when the error is freed.
 *
 * This function should never be called directly, instead use the
 * nih_error_raise_error() macro to pass the correct arguments for @filename,
 * @line and @function.
 **/
void
_nih_error_raise_error (const char *filename,
			int         line,
			const char *function,
			NihError *  error)
{
	nih_assert (filename != NULL);
	nih_assert (line > 0);
	nih_assert (function != NULL);
	nih_assert (error != NULL);
	nih_assert (error->number > 0);
	nih_assert (error->message != NULL);

	nih_error_init ();
	nih_error_clear ();

	error->filename = filename;
	error->line = line;
	error->function = function;

	CURRENT_CONTEXT->error = error;

	nih_alloc_set_destructor (error, nih_error_destroy);
}
int
my_method_sync (const void *        parent,
                NihDBusProxy *      proxy,
                MyMethodStructure **structure)
{
	DBusMessage *      method_call;
	DBusMessageIter    iter;
	DBusError          error;
	DBusMessage *      reply;
	MyMethodStructure *structure_local;
	DBusMessageIter    structure_local_iter;
	const char *       structure_local_item0_dbus;
	char *             structure_local_item0;
	uint32_t           structure_local_item1;

	nih_assert (proxy != NULL);
	nih_assert (structure != NULL);

	/* Construct the method call message. */
	method_call = dbus_message_new_method_call (proxy->name, proxy->path, "com.netsplit.Nih.Test", "Method");
	if (! method_call)
		nih_return_no_memory_error (-1);

	dbus_message_set_auto_start (method_call, proxy->auto_start);

	dbus_message_iter_init_append (method_call, &iter);

	/* Send the message, and wait for the reply. */
	dbus_error_init (&error);

	reply = dbus_connection_send_with_reply_and_block (proxy->connection, method_call, -1, &error);
	if (! reply) {
		dbus_message_unref (method_call);

		if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) {
			nih_error_raise_no_memory ();
		} else {
			nih_dbus_error_raise (error.name, error.message);
		}

		dbus_error_free (&error);
		return -1;
	}

	dbus_message_unref (method_call);

	/* Iterate the arguments of the reply */
	dbus_message_iter_init (reply, &iter);

	do {
		__label__ enomem;

		/* Demarshal a structure from the message */
		if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRUCT) {
			dbus_message_unref (reply);
			nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
			                  _(NIH_DBUS_INVALID_ARGS_STR));
		}

		dbus_message_iter_recurse (&iter, &structure_local_iter);

		structure_local = nih_new (parent, MyMethodStructure);
		if (! structure_local) {
			*structure = NULL;
			goto enomem;
		}

		/* Demarshal a char * from the message */
		if (dbus_message_iter_get_arg_type (&structure_local_iter) != DBUS_TYPE_STRING) {
			nih_free (structure_local);
			dbus_message_unref (reply);
			nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
			                  _(NIH_DBUS_INVALID_ARGS_STR));
		}

		dbus_message_iter_get_basic (&structure_local_iter, &structure_local_item0_dbus);

		structure_local_item0 = nih_strdup (structure_local, structure_local_item0_dbus);
		if (! structure_local_item0) {
			nih_free (structure_local);
			*structure = NULL;
			goto enomem;
		}

		dbus_message_iter_next (&structure_local_iter);

		structure_local->item0 = structure_local_item0;

		/* Demarshal a uint32_t from the message */
		if (dbus_message_iter_get_arg_type (&structure_local_iter) != DBUS_TYPE_UINT32) {
			nih_free (structure_local);
			dbus_message_unref (reply);
			nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
			                  _(NIH_DBUS_INVALID_ARGS_STR));
		}

		dbus_message_iter_get_basic (&structure_local_iter, &structure_local_item1);

		dbus_message_iter_next (&structure_local_iter);

		structure_local->item1 = structure_local_item1;

		if (dbus_message_iter_get_arg_type (&structure_local_iter) != DBUS_TYPE_INVALID) {
			nih_free (structure_local);
			dbus_message_unref (reply);
			nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
			                  _(NIH_DBUS_INVALID_ARGS_STR));
		}

		dbus_message_iter_next (&iter);

		*structure = structure_local;
	enomem: __attribute__ ((unused));
	} while (! *structure);

	if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
		nih_free (structure_local);
		*structure = NULL;
		dbus_message_unref (reply);
		nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
		                  _(NIH_DBUS_INVALID_ARGS_STR));
	}

	dbus_message_unref (reply);

	return 0;
}
Пример #19
0
int
main (int argc, char *argv[])
{
	char **		args;
	int		ret;
	DBusServer *	server;
	struct stat sb;

	nih_main_init (argv[0]);

	nih_option_set_synopsis (_("Control group proxy"));
	nih_option_set_help (_("The cgroup manager proxy"));

	args = nih_option_parser (NULL, argc, argv, options, FALSE);
	if (! args)
		exit (1);

	if (geteuid() != 0) {
		nih_error("%s: Cgmanager proxy must be run as root", __func__);
		exit(1);
	}

	/*
	 * If we are called with checkmaster, then only check whether
	 * cgmanager is running.  This is used by the init script to
	 * determine whether to run cgmanager or cgproxy
	 */
	if (checkmaster) {
		if (master_running())
			exit(0);
		exit(1);
	}

	if (setup_proxy() < 0) {
		nih_fatal ("Failed to set up as proxy");
		exit(1);
	}

	/* Setup the DBus server */
	server = nih_dbus_server ( CGMANAGER_DBUS_PATH, client_connect,
			client_disconnect);
	nih_assert (server != NULL);

	if (stat("/proc/self/ns/pid", &sb) == 0) {
		mypidns = read_pid_ns_link(getpid());
		setns_pid_supported = true;
	}

	if (stat("/proc/self/ns/user", &sb) == 0) {
		myuserns = read_user_ns_link(getpid());
		setns_user_supported = true;
	}

	/* Become daemon */
	if (daemonise) {
		if (nih_main_daemonise () < 0) {
			NihError *err;

			err = nih_error_get ();
			nih_fatal ("%s: %s", _("Unable to become daemon"),
				   err->message);
			nih_free (err);

			exit (1);
		}
	}

	/*
	 * We have to send a message to force fd passing over the dbus
	 * link to be negotiated.  Else when we try to attach an fd we'll
	 * fail.
	 */
	if (!send_dummy_msg(server_conn)) {
		nih_fatal("Failed to send opening ping to cgmanager");
		exit(1);
	}

	if (sigstop)
		raise(SIGSTOP);

	ret = nih_main_loop ();

	return ret;
}
DBusHandlerResult
my_com_netsplit_Nih_Test_Method_method (NihDBusObject * object,
                                        NihDBusMessage *message)
{
	DBusMessageIter    iter;
	DBusMessage *      reply;
	MyMethodStructure *structure;
	DBusMessageIter    structure_iter;
	const char *       structure_item0;
	uint32_t           structure_item1;

	nih_assert (object != NULL);
	nih_assert (message != NULL);

	/* Iterate the arguments to the message and demarshal into arguments
	 * for our own function call.
	 */
	dbus_message_iter_init (message->message, &iter);

	if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
		reply = dbus_message_new_error (message->message, DBUS_ERROR_INVALID_ARGS,
		                                "Invalid arguments to Method method");
		if (! reply)
			return DBUS_HANDLER_RESULT_NEED_MEMORY;

		if (! dbus_connection_send (message->connection, reply, NULL)) {
			dbus_message_unref (reply);
			return DBUS_HANDLER_RESULT_NEED_MEMORY;
		}

		dbus_message_unref (reply);
		return DBUS_HANDLER_RESULT_HANDLED;
	}

	/* Call the handler function */
	nih_error_push_context ();
	if (my_method (object->data, message, &structure) < 0) {
		NihError *err;

		err = nih_error_get ();
		if (err->number == ENOMEM) {
			nih_free (err);
			nih_error_pop_context ();

			return DBUS_HANDLER_RESULT_NEED_MEMORY;
		} else if (err->number == NIH_DBUS_ERROR) {
			NihDBusError *dbus_err = (NihDBusError *)err;

			reply = NIH_MUST (dbus_message_new_error (message->message, dbus_err->name, err->message));
			nih_free (err);
			nih_error_pop_context ();

			NIH_MUST (dbus_connection_send (message->connection, reply, NULL));

			dbus_message_unref (reply);
			return DBUS_HANDLER_RESULT_HANDLED;
		} else {
			reply = NIH_MUST (dbus_message_new_error (message->message, DBUS_ERROR_FAILED, err->message));
			nih_free (err);
			nih_error_pop_context ();

			NIH_MUST (dbus_connection_send (message->connection, reply, NULL));

			dbus_message_unref (reply);
			return DBUS_HANDLER_RESULT_HANDLED;
		}
	}
	nih_error_pop_context ();

	/* If the sender doesn't care about a reply, don't bother wasting
	 * effort constructing and sending one.
	 */
	if (dbus_message_get_no_reply (message->message))
		return DBUS_HANDLER_RESULT_HANDLED;

	do {
		__label__ enomem;

		/* Construct the reply message. */
		reply = dbus_message_new_method_return (message->message);
		if (! reply)
			goto enomem;

		dbus_message_iter_init_append (reply, &iter);

		/* Marshal a structure onto the message */
		if (! dbus_message_iter_open_container (&iter, DBUS_TYPE_STRUCT, NULL, &structure_iter)) {
			dbus_message_unref (reply);
			reply = NULL;
			goto enomem;
		}

		structure_item0 = structure->item0;

		/* Marshal a char * onto the message */
		if (! dbus_message_iter_append_basic (&structure_iter, DBUS_TYPE_STRING, &structure_item0)) {
			dbus_message_iter_abandon_container (&iter, &structure_iter);
			dbus_message_unref (reply);
			reply = NULL;
			goto enomem;
		}

		structure_item1 = structure->item1;

		/* Marshal a uint32_t onto the message */
		if (! dbus_message_iter_append_basic (&structure_iter, DBUS_TYPE_UINT32, &structure_item1)) {
			dbus_message_iter_abandon_container (&iter, &structure_iter);
			dbus_message_unref (reply);
			reply = NULL;
			goto enomem;
		}

		if (! dbus_message_iter_close_container (&iter, &structure_iter)) {
			dbus_message_unref (reply);
			reply = NULL;
			goto enomem;
		}
	enomem: __attribute__ ((unused));
	} while (! reply);

	/* Send the reply, appending it to the outgoing queue. */
	NIH_MUST (dbus_connection_send (message->connection, reply, NULL));

	dbus_message_unref (reply);

	return DBUS_HANDLER_RESULT_HANDLED;
}
static DBusHandlerResult
my_com_netsplit_Nih_Foo_Bing_method (NihDBusObject * object,
                                     NihDBusMessage *message)
{
	DBusMessageIter iter;
	DBusMessage *   reply;

	nih_assert (object != NULL);
	nih_assert (message != NULL);

	/* Iterate the arguments to the message and demarshal into arguments
	 * for our own function call.
	 */
	dbus_message_iter_init (message->message, &iter);

	if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
		reply = dbus_message_new_error (message->message, DBUS_ERROR_INVALID_ARGS,
		                                "Invalid arguments to Bing method");
		if (! reply)
			return DBUS_HANDLER_RESULT_NEED_MEMORY;

		if (! dbus_connection_send (message->connection, reply, NULL)) {
			dbus_message_unref (reply);
			return DBUS_HANDLER_RESULT_NEED_MEMORY;
		}

		dbus_message_unref (reply);
		return DBUS_HANDLER_RESULT_HANDLED;
	}

	/* Call the handler function */
	nih_error_push_context ();
	if (my_foo_bing (object->data, message) < 0) {
		NihError *err;

		err = nih_error_get ();
		if (err->number == ENOMEM) {
			nih_free (err);
			nih_error_pop_context ();

			return DBUS_HANDLER_RESULT_NEED_MEMORY;
		} else if (err->number == NIH_DBUS_ERROR) {
			NihDBusError *dbus_err = (NihDBusError *)err;

			reply = NIH_MUST (dbus_message_new_error (message->message, dbus_err->name, err->message));
			nih_free (err);
			nih_error_pop_context ();

			NIH_MUST (dbus_connection_send (message->connection, reply, NULL));

			dbus_message_unref (reply);
			return DBUS_HANDLER_RESULT_HANDLED;
		} else {
			reply = NIH_MUST (dbus_message_new_error (message->message, DBUS_ERROR_FAILED, err->message));
			nih_free (err);
			nih_error_pop_context ();

			NIH_MUST (dbus_connection_send (message->connection, reply, NULL));

			dbus_message_unref (reply);
			return DBUS_HANDLER_RESULT_HANDLED;
		}
	}
	nih_error_pop_context ();

	/* If the sender doesn't care about a reply, don't bother wasting
	 * effort constructing and sending one.
	 */
	if (dbus_message_get_no_reply (message->message))
		return DBUS_HANDLER_RESULT_HANDLED;

	do {
		__label__ enomem;

		/* Construct the reply message. */
		reply = dbus_message_new_method_return (message->message);
		if (! reply)
			goto enomem;

		dbus_message_iter_init_append (reply, &iter);
	enomem: __attribute__ ((unused));
	} while (! reply);

	/* Send the reply, appending it to the outgoing queue. */
	NIH_MUST (dbus_connection_send (message->connection, reply, NULL));

	dbus_message_unref (reply);

	return DBUS_HANDLER_RESULT_HANDLED;
}
int
my_method_sync (const void *   parent,
                NihDBusProxy * proxy,
                const int32_t *value,
                size_t         value_len)
{
	DBusMessage *   method_call;
	DBusMessageIter iter;
	DBusError       error;
	DBusMessage *   reply;
	DBusMessageIter value_iter;

	nih_assert (proxy != NULL);
	nih_assert ((value_len == 0) || (value != NULL));

	/* Construct the method call message. */
	method_call = dbus_message_new_method_call (proxy->name, proxy->path, "com.netsplit.Nih.Test", "Method");
	if (! method_call)
		nih_return_no_memory_error (-1);

	dbus_message_set_auto_start (method_call, proxy->auto_start);

	dbus_message_iter_init_append (method_call, &iter);

	/* Marshal an array onto the message */
	if (! dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "i", &value_iter)) {
		dbus_message_unref (method_call);
		nih_return_no_memory_error (-1);
	}

	for (size_t value_i = 0; value_i < value_len; value_i++) {
		int32_t value_element;

		value_element = value[value_i];

		/* Marshal a int32_t onto the message */
		if (! dbus_message_iter_append_basic (&value_iter, DBUS_TYPE_INT32, &value_element)) {
			dbus_message_iter_abandon_container (&iter, &value_iter);
			dbus_message_unref (method_call);
			nih_return_no_memory_error (-1);
		}
	}

	if (! dbus_message_iter_close_container (&iter, &value_iter)) {
		dbus_message_unref (method_call);
		nih_return_no_memory_error (-1);
	}

	/* Send the message, and wait for the reply. */
	dbus_error_init (&error);

	reply = dbus_connection_send_with_reply_and_block (proxy->connection, method_call, -1, &error);
	if (! reply) {
		dbus_message_unref (method_call);

		if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) {
			nih_error_raise_no_memory ();
		} else {
			nih_dbus_error_raise (error.name, error.message);
		}

		dbus_error_free (&error);
		return -1;
	}

	dbus_message_unref (method_call);

	/* Iterate the arguments of the reply */
	dbus_message_iter_init (reply, &iter);

	if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
		dbus_message_unref (reply);
		nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
		                  _(NIH_DBUS_INVALID_ARGS_STR));
	}

	dbus_message_unref (reply);

	return 0;
}
Пример #23
0
int
main (int   argc,
      char *argv[])
{
	char **              args;
	DBusConnection *     connection;
	struct udev *        udev;
	struct udev_monitor *udev_monitor;
	int                  ret;

	nih_main_init (argv[0]);

	nih_option_set_synopsis (_("Bridge udev events into upstart"));
	nih_option_set_help (
		_("By default, upstart-udev-bridge does not detach from the "
		  "console and remains in the foreground.  Use the --daemon "
		  "option to have it detach."));

	args = nih_option_parser (NULL, argc, argv, options, FALSE);
	if (! args)
		exit (1);

	/* Initialise the connection to Upstart */
	connection = NIH_SHOULD (nih_dbus_connect (DBUS_ADDRESS_UPSTART, upstart_disconnected));
	if (! connection) {
		NihError *err;

		err = nih_error_get ();
		nih_fatal ("%s: %s", _("Could not connect to Upstart"),
			   err->message);
		nih_free (err);

		exit (1);
	}

	upstart = NIH_SHOULD (nih_dbus_proxy_new (NULL, connection,
						  NULL, DBUS_PATH_UPSTART,
						  NULL, NULL));
	if (! upstart) {
		NihError *err;

		err = nih_error_get ();
		nih_fatal ("%s: %s", _("Could not create Upstart proxy"),
			   err->message);
		nih_free (err);

		exit (1);
	}

	/* Initialise the connection to udev */
	nih_assert (udev = udev_new ());
	nih_assert (udev_monitor = udev_monitor_new_from_netlink (udev, "udev"));
	nih_assert (udev_monitor_enable_receiving (udev_monitor) == 0);
	udev_monitor_set_receive_buffer_size(udev_monitor, 128*1024*1024);

	NIH_MUST (nih_io_add_watch (NULL, udev_monitor_get_fd (udev_monitor),
				    NIH_IO_READ,
				    (NihIoWatcher)udev_monitor_watcher,
				    udev_monitor));

	/* Become daemon */
	if (daemonise) {
		if (nih_main_daemonise () < 0) {
			NihError *err;

			err = nih_error_get ();
			nih_fatal ("%s: %s", _("Unable to become daemon"),
				   err->message);
			nih_free (err);

			exit (1);
		}

		/* Send all logging output to syslog */
		openlog (program_name, LOG_PID, LOG_DAEMON);
		nih_log_set_logger (nih_logger_syslog);
	}

	/* Handle TERM and INT signals gracefully */
	nih_signal_set_handler (SIGTERM, nih_signal_handler);
	NIH_MUST (nih_signal_add_handler (NULL, SIGTERM, nih_main_term_signal, NULL));

	if (! daemonise) {
		nih_signal_set_handler (SIGINT, nih_signal_handler);
		NIH_MUST (nih_signal_add_handler (NULL, SIGINT, nih_main_term_signal, NULL));
	}

	ret = nih_main_loop ();

	return ret;
}
void
my_com_netsplit_Nih_Test_property_get_notify (DBusPendingCall *   pending_call,
                                              NihDBusPendingData *pending_data)
{
	DBusMessage *   reply;
	DBusMessageIter iter;
	DBusMessageIter variter;
	NihDBusMessage *message;
	DBusError       error;
	const char *    value_dbus;
	char *          value;

	nih_assert (pending_call != NULL);
	nih_assert (pending_data != NULL);

	nih_assert (dbus_pending_call_get_completed (pending_call));

	/* Steal the reply from the pending call. */
	reply = dbus_pending_call_steal_reply (pending_call);
	nih_assert (reply != NULL);

	/* Handle error replies */
	if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) {
		message = NIH_MUST (nih_dbus_message_new (pending_data, pending_data->connection, reply));

		dbus_error_init (&error);
		dbus_set_error_from_message (&error, message->message);

		nih_error_push_context ();
		nih_dbus_error_raise (error.name, error.message);
		pending_data->error_handler (pending_data->data, message);
		nih_error_pop_context ();

		dbus_error_free (&error);
		nih_free (message);
		dbus_message_unref (reply);
		return;
	}

	nih_assert (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN);

	do {
		__label__ enomem;

		/* Create a message context for the reply, and iterate
		 * over and recurse into the arguments.
		 */
		message = nih_dbus_message_new (pending_data, pending_data->connection, reply);
		if (! message)
			goto enomem;

		dbus_message_iter_init (message->message, &iter);

		if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_VARIANT) {
			nih_error_push_context ();
			nih_error_raise (NIH_DBUS_INVALID_ARGS,
			                 _(NIH_DBUS_INVALID_ARGS_STR));
			pending_data->error_handler (pending_data->data, message);
			nih_error_pop_context ();

			nih_free (message);
			dbus_message_unref (reply);
			return;
		}

		dbus_message_iter_recurse (&iter, &variter);

		/* Demarshal a char * from the message */
		if (dbus_message_iter_get_arg_type (&variter) != DBUS_TYPE_STRING) {
			nih_error_push_context ();
			nih_error_raise (NIH_DBUS_INVALID_ARGS,
			                 _(NIH_DBUS_INVALID_ARGS_STR));
			pending_data->error_handler (pending_data->data, message);
			nih_error_pop_context ();

			nih_free (message);
			dbus_message_unref (reply);
			return;
		}

		dbus_message_iter_get_basic (&variter, &value_dbus);

		value = nih_strdup (message, value_dbus);
		if (! value) {
			nih_free (message);
			message = NULL;
			goto enomem;
		}

		dbus_message_iter_next (&variter);

		dbus_message_iter_next (&iter);

		if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
			nih_error_push_context ();
			nih_error_raise (NIH_DBUS_INVALID_ARGS,
			                 _(NIH_DBUS_INVALID_ARGS_STR));
			pending_data->error_handler (pending_data->data, message);
			nih_error_pop_context ();

			nih_free (message);
			dbus_message_unref (reply);
			return;
		}

	enomem: __attribute__ ((unused));
	} while (! message);

	/* Call the handler function */
	nih_error_push_context ();
	((MyGetPropertyReply)pending_data->handler) (pending_data->data, message, value);
	nih_error_pop_context ();

	nih_free (message);
	dbus_message_unref (reply);
}
Пример #25
0
/**
 * session_from_dbus:
 * @parent: parent,
 * @message: D-Bus message.
 *
 * Create a new session, based on the specified D-Bus message.
 *
 * Return new Session, or NULL on error.
 **/
Session *
session_from_dbus (const void     *parent,
		   NihDBusMessage *message)
{
	const char     *sender;
	DBusError       dbus_error;
	unsigned long   unix_user;
	unsigned long   unix_process_id;
	char            root[PATH_MAX];
	Session        *session;
	struct passwd  *pwd;
	nih_local char *conf_path = NULL;

	nih_assert (message != NULL);

	/* Handle explicit command-line request and alternative request
	 * method (primarily for test framework) to disable session support.
	 */
	if (disable_sessions || getenv ("UPSTART_NO_SESSIONS"))
		return NULL;

	session_init ();

	/* Ask D-Bus nicely for the origin uid and/or pid of the caller;
	 * sadly we can't ask the bus daemon for the origin pid, so that
	 * one will just have to stay user-session only.
	 */
	dbus_error_init (&dbus_error);

	sender = dbus_message_get_sender (message->message);
	if (sender) {
		unix_user = dbus_bus_get_unix_user (message->connection, sender,
						    &dbus_error);
		if (unix_user == (unsigned long)-1) {
			dbus_error_free (&dbus_error);
			unix_user = 0;
		}

		unix_process_id = 0;

	} else {
		if (! dbus_connection_get_unix_user (message->connection,
						     &unix_user))
			unix_process_id = 0;

		if (! dbus_connection_get_unix_process_id (message->connection,
							   &unix_process_id))
			unix_process_id = 0;
	}

	/* If we retrieved a process id, look up the root path for it;
	 * if it's just '/' don't worry so much about it.
	 */
	if (unix_process_id) {
		nih_local char *symlink = NULL;
		ssize_t len;

		symlink = NIH_MUST (nih_sprintf (NULL, "/proc/%lu/root",
						 unix_process_id));
		len = readlink (symlink, root, sizeof root);
		if (len < 0)
			return NULL;

		root[len] = '\0';

		if (! strcmp (root, "/")) {
			unix_process_id = 0;
			if (! unix_user)
				return NULL;
		}

	} else if (! unix_user) {
		/* No process id or user id found, return the NULL session */
		return NULL;
	}

	if (unix_user) {
		pwd = getpwuid (unix_user);

		if (! pwd || ! pwd->pw_dir) {
			nih_error ("%lu: %s: %s", unix_user,
				   _("Unable to lookup home directory"),
				   strerror (errno));
			return NULL;
		}

		NIH_MUST (nih_strcat_sprintf (&conf_path, NULL, "%s/%s",
					pwd->pw_dir, USERCONFDIR));
	}


	/* Now find in the existing Sessions list */
	NIH_LIST_FOREACH_SAFE (sessions, iter) {
		Session *session = (Session *)iter;

		if (unix_process_id) {
			if (! session->chroot)
				continue;

			/* ignore sessions relating to other chroots */
			if (strcmp (session->chroot, root))
				continue;
		}

		/* ignore sessions relating to other users */
		if (unix_user != session->user)
			continue;

		/* Found a user with the same uid but different
		 * conf_dir to the existing session user. Either the
		 * original user has been deleted and a new user created
		 * with the same uid, or the original users home
		 * directory has changed since they first started
		 * running jobs. Whatever the reason, we (can only) honour
		 * the new value.
		 *
		 * Since multiple users with the same uid are considered
		 * to be "the same user", invalidate the old path,
		 * allowing the correct new path to be set below.
		 *
		 * Note that there may be a possibility of trouble if
		 * the scenario relates to a deleted user and that original
		 * user still has jobs running. However, if that were the
		 * case, those jobs would likely fail anyway since they
		 * would have no working directory due to the original
		 * users home directory being deleted/changed/made inaccessible.
		 */
		if (unix_user && conf_path && session->conf_path &&
				strcmp (conf_path, session->conf_path)) {
			nih_free (session->conf_path);
			session->conf_path = NULL;
		}

		if (! session->conf_path)
			session_create_conf_source (session);

		return session;
	}
static DBusHandlerResult
my_com_netsplit_Nih_Test_Peek_method (NihDBusObject * object,
                                      NihDBusMessage *message)
{
	DBusMessageIter iter;
	DBusMessage *   reply;
	uint32_t        address;

	nih_assert (object != NULL);
	nih_assert (message != NULL);

	/* Iterate the arguments to the message and demarshal into arguments
	 * for our own function call.
	 */
	dbus_message_iter_init (message->message, &iter);

	/* Demarshal a uint32_t from the message */
	if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32) {
		reply = dbus_message_new_error (message->message, DBUS_ERROR_INVALID_ARGS,
		                                "Invalid arguments to Peek method");
		if (! reply)
			return DBUS_HANDLER_RESULT_NEED_MEMORY;

		if (! dbus_connection_send (message->connection, reply, NULL)) {
			dbus_message_unref (reply);
			return DBUS_HANDLER_RESULT_NEED_MEMORY;
		}

		dbus_message_unref (reply);
		return DBUS_HANDLER_RESULT_HANDLED;
	}

	dbus_message_iter_get_basic (&iter, &address);

	dbus_message_iter_next (&iter);

	if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
		reply = dbus_message_new_error (message->message, DBUS_ERROR_INVALID_ARGS,
		                                "Invalid arguments to Peek method");
		if (! reply)
			return DBUS_HANDLER_RESULT_NEED_MEMORY;

		if (! dbus_connection_send (message->connection, reply, NULL)) {
			dbus_message_unref (reply);
			return DBUS_HANDLER_RESULT_NEED_MEMORY;
		}

		dbus_message_unref (reply);
		return DBUS_HANDLER_RESULT_HANDLED;
	}

	/* Call the handler function */
	nih_error_push_context ();
	if (my_test_peek (object->data, message, address) < 0) {
		NihError *err;

		err = nih_error_get ();
		if (err->number == ENOMEM) {
			nih_free (err);
			nih_error_pop_context ();

			return DBUS_HANDLER_RESULT_NEED_MEMORY;
		} else if (err->number == NIH_DBUS_ERROR) {
			NihDBusError *dbus_err = (NihDBusError *)err;

			reply = NIH_MUST (dbus_message_new_error (message->message, dbus_err->name, err->message));
			nih_free (err);
			nih_error_pop_context ();

			NIH_MUST (dbus_connection_send (message->connection, reply, NULL));

			dbus_message_unref (reply);
			return DBUS_HANDLER_RESULT_HANDLED;
		} else {
			reply = NIH_MUST (dbus_message_new_error (message->message, DBUS_ERROR_FAILED, err->message));
			nih_free (err);
			nih_error_pop_context ();

			NIH_MUST (dbus_connection_send (message->connection, reply, NULL));

			dbus_message_unref (reply);
			return DBUS_HANDLER_RESULT_HANDLED;
		}
	}
	nih_error_pop_context ();

	return DBUS_HANDLER_RESULT_HANDLED;
}
Пример #27
0
/**
 * warning_message:
 * @message: user message.
 *
 * Prefixes the message with details about how long until the shutdown
 * completes.
 *
 * Returns: newly allocated string.
 **/
static char *
warning_message (const char *message)
{
	nih_local char *banner = NULL;
	char *          msg;

	nih_assert (message != NULL);

	if ((runlevel == '0')
	    && init_halt && (! strcmp (init_halt, "POWEROFF"))) {
		if (delay) {
			banner = nih_sprintf (
				NULL, _n("The system is going down for "
					 "power off in %d minute!",
					 "The system is going down for "
					 "power off in %d minutes!",
					 delay), delay);
		} else {
			banner = nih_strdup (
				NULL, _("The system is going down for "
					"power off NOW!"));
		}
	} else if (runlevel == '0') {
		if (delay) {
			banner = nih_sprintf (
				NULL, _n("The system is going down for "
					 "halt in %d minute!",
					 "The system is going down for "
					 "halt in %d minutes!",
					 delay), delay);
		} else {
			banner = nih_strdup (
				NULL, _("The system is going down for "
					"halt NOW!"));
		}
	} else if (runlevel == '1') {
		if (delay) {
			banner = nih_sprintf (
				NULL, _n("The system is going down for "
					 "maintenance in %d minute!",
					 "The system is going down for "
					 "maintenance in %d minutes!",
					 delay), delay);
		} else {
			banner = nih_strdup (
				NULL, _("The system is going down for "
					"maintenance NOW!"));
		}
	} else if (runlevel == '6') {
		if (delay) {
			banner = nih_sprintf (
				NULL, _n("The system is going down for "
					 "reboot in %d minute!",
					 "The system is going down for "
					 "reboot in %d minutes!",
					 delay), delay);
		} else {
			banner = nih_strdup (
				NULL, _("The system is going down for "
					"reboot NOW!"));
		}
	}

	if (! banner)
		return NULL;

	msg = nih_sprintf (NULL, "\r%s\r\n%s", banner, message);

	return msg;
}
Пример #28
0
int
main (int   argc,
      char *argv[])
{
	char **             args;
	DBusConnection *    conn;
	int fd, optval = 1, exitval = 1, ret;
	DBusMessage *message = NULL, *reply = NULL;
	DBusMessageIter iter;
	dbus_uint32_t serial;;

	nih_main_init (argv[0]);

	nih_option_set_synopsis (_("Control group client"));

	args = nih_option_parser (NULL, argc, argv, options, FALSE);
	if (! args)
		exit (1);

	if (!controller)
		usage(argv[0]);

	if (pid == -1)
		pid = getpid();

	conn = nih_dbus_connect("unix:path=/tmp/cgmanager", NULL);
	nih_assert (conn != NULL);

	message = dbus_message_new_method_call(dbus_bus_get_unique_name(conn),
			"/org/linuxcontainers/cgmanager",
			"org.linuxcontainers.cgmanager0_0", "getPidCgroup");

	if (!dbus_connection_get_socket(conn, &fd)) {
		nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
					"Could not get socket");
		return -1;
	}
	if (setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) == -1) {
		perror("setsockopt");
		return -1;
	}

	dbus_message_iter_init_append(message, &iter);
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING,
                                              &controller)) {
                nih_error_raise_no_memory ();
                return -1;
        }
	dbus_message_iter_init_append(message, &iter);
        if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32,
                                              &pid)) {
                nih_error_raise_no_memory ();
                return -1;
        }

	if (!dbus_connection_send(conn, message, &serial)) {
		nih_error("failed to send dbus message");
		return -1;
	}
	dbus_connection_flush(conn);

	/* If we're sending our own pid, or if we're root, then
	 * we can send an SCM_CREDENTIAL
	 */
	if (pid == getpid() || geteuid() == 0) {
		if (send_pid(fd, pid)) {
			nih_error("Error sending pid over SCM_CREDENTIAL");
			goto out;
		}
	}

	while (!(reply = dbus_connection_pop_message(conn)))
		dbus_connection_read_write(conn, -1);
	if (dbus_message_get_reply_serial(reply) != serial) {
		nih_error("wrong serial on reply");
		goto out;
	}

	dbus_message_iter_init(reply, &iter);
	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) {
		nih_error("Got bad reply type: %d", dbus_message_iter_get_arg_type(&iter));
		goto out;
	}
	char *str_value;
	dbus_message_iter_get_basic(&iter, &str_value);
	printf("%s\n", str_value);
	exitval = 0;

out:
	if (message)
		dbus_message_unref(message);
	if (reply)
		dbus_message_unref(reply);
	dbus_connection_unref (conn);
	exit(exitval);
}
Пример #29
0
int
main (int argc, char *argv[])
{
	char **		args;
	int		ret;
	DBusServer *	server;
	struct stat sb;
	struct rlimit newrlimit;

	nih_main_init (argv[0]);

	nih_option_set_synopsis (_("Control group manager"));
	nih_option_set_help (_("The cgroup manager daemon"));

	args = nih_option_parser (NULL, argc, argv, options, FALSE);
	if (! args)
		exit (1);

	if (!setup_cgroup_dir()) {
		nih_fatal("Failed to set up cgmanager socket");
		exit(1);
	}

	/* Setup the DBus server */
	server = nih_dbus_server (CGMANAGER_DBUS_PATH, client_connect,
				  client_disconnect);
	nih_assert (server != NULL);

	if (!setup_base_run_path()) {
		nih_fatal("Error setting up base cgroup path");
		return -1;
	}

	if (collect_subsystems(extra_cgroup_mounts) < 0)
	{
		nih_fatal("failed to collect cgroup subsystems");
		exit(1);
	}

	if (!create_agent_symlinks()) {
		nih_fatal("Error creating release agent symlinks");
		exit(1);
	}

	if (setup_cgroup_mounts() < 0) {
		nih_fatal ("Failed to set up cgroup mounts");
		exit(1);
	}

	if (!move_self_to_root()) {
		nih_fatal ("Failed to move self to root cgroup");
		exit(1);
	}

	if (stat("/proc/self/ns/pid", &sb) == 0) {
		mypidns = read_pid_ns_link(getpid());
		setns_pid_supported = true;
	}

	if (stat("/proc/self/ns/user", &sb) == 0) {
		myuserns = read_user_ns_link(getpid());
		setns_user_supported = true;
	}

	newrlimit.rlim_cur = 10000;
	newrlimit.rlim_max = 10000;
	if (setrlimit(RLIMIT_NOFILE, &newrlimit) < 0)
		nih_warn("Failed to increase open file limit: %s",
			strerror(errno));

	/* Become daemon */
	if (daemonise) {
		if (nih_main_daemonise () < 0) {
			NihError *err;

			err = nih_error_get ();
			nih_fatal ("%s: %s", _("Unable to become daemon"),
					err->message);
			nih_free (err);

			exit (1);
		}
	}

	if (sigstop)
		raise(SIGSTOP);

	ret = nih_main_loop ();

	/* Destroy any PID file we may have created */
	if (daemonise) {
		nih_main_unlink_pidfile();
	}

	return ret;
}
void
my_com_netsplit_Nih_Test_get_all_notify (DBusPendingCall *   pending_call,
                                         NihDBusPendingData *pending_data)
{
	DBusMessage *   reply;
	DBusMessageIter iter;
	DBusMessageIter arrayiter;
	DBusMessageIter dictiter;
	DBusMessageIter variter;
	NihDBusMessage *message;
	DBusError       error;
	const char *    property;
	MyProperties *  properties;
	size_t          property_count;
	char *          name;
	const char *    name_dbus;
	uint32_t        size;

	nih_assert (pending_call != NULL);
	nih_assert (pending_data != NULL);

	nih_assert (dbus_pending_call_get_completed (pending_call));

	/* Steal the reply from the pending call. */
	reply = dbus_pending_call_steal_reply (pending_call);
	nih_assert (reply != NULL);

	/* Handle error replies */
	if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) {
		message = NIH_MUST (nih_dbus_message_new (pending_data, pending_data->connection, reply));

		dbus_error_init (&error);
		dbus_set_error_from_message (&error, message->message);

		nih_error_push_context ();
		nih_dbus_error_raise (error.name, error.message);
		pending_data->error_handler (pending_data->data, message);
		nih_error_pop_context ();

		dbus_error_free (&error);
		nih_free (message);
		dbus_message_unref (reply);
		return;
	}

	nih_assert (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN);

	/* Create a message context for the reply, and iterate
	 * over and recurse into the arguments.
	 */
	message = NIH_MUST (nih_dbus_message_new (pending_data, pending_data->connection, reply));

	/* Iterate the method arguments, recursing into the array */
	dbus_message_iter_init (reply, &iter);

	if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY) {
		nih_error_push_context ();
		nih_error_raise (NIH_DBUS_INVALID_ARGS,
		                 _(NIH_DBUS_INVALID_ARGS_STR));
		pending_data->error_handler (pending_data->data, message);
		nih_error_pop_context ();

		nih_free (message);
		dbus_message_unref (reply);
		return;
	}

	properties = NIH_MUST (nih_new (message, MyProperties));
	property_count = 0;

	dbus_message_iter_recurse (&iter, &arrayiter);

	while (dbus_message_iter_get_arg_type (&arrayiter) != DBUS_TYPE_INVALID) {
		__label__ enomem;

		if (dbus_message_iter_get_arg_type (&arrayiter) != DBUS_TYPE_DICT_ENTRY) {
			nih_error_push_context ();
			nih_error_raise (NIH_DBUS_INVALID_ARGS,
			                 _(NIH_DBUS_INVALID_ARGS_STR));
			pending_data->error_handler (pending_data->data, message);
			nih_error_pop_context ();

			nih_free (message);
			dbus_message_unref (reply);
			return;
		}

		dbus_message_iter_recurse (&arrayiter, &dictiter);

		if (dbus_message_iter_get_arg_type (&dictiter) != DBUS_TYPE_STRING) {
			nih_error_push_context ();
			nih_error_raise (NIH_DBUS_INVALID_ARGS,
			                 _(NIH_DBUS_INVALID_ARGS_STR));
			pending_data->error_handler (pending_data->data, message);
			nih_error_pop_context ();

			nih_free (message);
			dbus_message_unref (reply);
			return;
		}

		dbus_message_iter_get_basic (&dictiter, &property);

		dbus_message_iter_next (&dictiter);

		if (dbus_message_iter_get_arg_type (&dictiter) != DBUS_TYPE_VARIANT) {
			nih_error_push_context ();
			nih_error_raise (NIH_DBUS_INVALID_ARGS,
			                 _(NIH_DBUS_INVALID_ARGS_STR));
			pending_data->error_handler (pending_data->data, message);
			nih_error_pop_context ();

			nih_free (message);
			dbus_message_unref (reply);
			return;
		}

		dbus_message_iter_recurse (&dictiter, &variter);

		if (! strcmp (property, "name")) {
			/* Demarshal a char * from the message */
			if (dbus_message_iter_get_arg_type (&variter) != DBUS_TYPE_STRING) {
				nih_error_push_context ();
				nih_error_raise (NIH_DBUS_INVALID_ARGS,
				                 _(NIH_DBUS_INVALID_ARGS_STR));
				pending_data->error_handler (pending_data->data, message);
				nih_error_pop_context ();

				nih_free (message);
				dbus_message_unref (reply);
				return;
			}

			dbus_message_iter_get_basic (&variter, &name_dbus);

			name = nih_strdup (properties, name_dbus);
			if (! name) {
				goto enomem;
			}

			dbus_message_iter_next (&variter);

			properties->name = name;

			nih_assert (++property_count);
		}

		if (! strcmp (property, "size")) {
			/* Demarshal a uint32_t from the message */
			if (dbus_message_iter_get_arg_type (&variter) != DBUS_TYPE_UINT32) {
				nih_error_push_context ();
				nih_error_raise (NIH_DBUS_INVALID_ARGS,
				                 _(NIH_DBUS_INVALID_ARGS_STR));
				pending_data->error_handler (pending_data->data, message);
				nih_error_pop_context ();

				nih_free (message);
				dbus_message_unref (reply);
				return;
			}

			dbus_message_iter_get_basic (&variter, &size);

			dbus_message_iter_next (&variter);

			properties->size = size;

			nih_assert (++property_count);
		}

		dbus_message_iter_next (&dictiter);

		if (dbus_message_iter_get_arg_type (&dictiter) != DBUS_TYPE_INVALID) {
			nih_error_push_context ();
			nih_error_raise (NIH_DBUS_INVALID_ARGS,
			                 _(NIH_DBUS_INVALID_ARGS_STR));
			pending_data->error_handler (pending_data->data, message);
			nih_error_pop_context ();

			nih_free (message);
			dbus_message_unref (reply);
			return;
		}

		dbus_message_iter_next (&arrayiter);
	enomem: __attribute__ ((unused));
	}

	dbus_message_iter_next (&iter);

	if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
		nih_error_push_context ();
		nih_error_raise (NIH_DBUS_INVALID_ARGS,
		                 _(NIH_DBUS_INVALID_ARGS_STR));
		pending_data->error_handler (pending_data->data, message);
		nih_error_pop_context ();

		nih_free (message);
		dbus_message_unref (reply);
		return;
	}

	if (property_count < 2) {
		nih_error_push_context ();
		nih_error_raise (NIH_DBUS_INVALID_ARGS,
		                 _(NIH_DBUS_INVALID_ARGS_STR));
		pending_data->error_handler (pending_data->data, message);
		nih_error_pop_context ();

		nih_free (message);
		dbus_message_unref (reply);
		return;
	}

	/* Call the handler function */
	nih_error_push_context ();
	((MyGetAllReply)pending_data->handler) (pending_data->data, message, properties);
	nih_error_pop_context ();

	nih_free (message);
	dbus_message_unref (reply);
}