/** * 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; }
/** * 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; }
/** * 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; }
/** * 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; }
/** * 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 (); }
/** * _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; }
/** * _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); }
/** * 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 (); } }
/** * 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; }
/** * 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; }
/** * 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; }
/** * 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; }
/** * _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; }
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; }
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); }
/** * 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; }
/** * 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; }
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); }
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); }