@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 Jolla Ltd.
+ * Copyright (C) 2019-2020 Jolla Ltd.
* Copyright (C) 2019 Franz-Josef Haider <franz.haider@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
@@ -30,17 +30,34 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <stdio.h>
+#include <glib.h>
+#include <glib-unix.h>
#include <gbinder.h>
+#include <gutil_log.h>
#include <systemd/sd-daemon.h>
+#include <stdio.h>
#define BINDER_DEVICE "/dev/hwbinder"
#define NETD_IFACE "android.system.net.netd@1.1::INetd"
#define NETD_SLOT "default"
+#define RET_OK 0
+#define RET_CMDLINE 1
+#define RET_ERR 2
+
+static
+gboolean
+netd_signal(
+ gpointer user_data)
+{
+ GINFO("Signal caught, exiting...");
+ g_main_loop_quit((GMainLoop*) user_data);
+ return G_SOURCE_CONTINUE;
+}
+
static
GBinderLocalReply*
-netd_reply(
+netd_handler(
GBinderLocalObject* obj,
GBinderRemoteRequest* req,
guint code,
@@ -48,44 +65,91 @@
int* status,
void* user_data)
{
- fprintf(stderr, "netd_reply called with on interface: %s, code: %d, flags: %d\n",
- gbinder_remote_request_interface(req), code, flags);
+ GDEBUG("%s %d", gbinder_remote_request_interface(req), code);
return NULL;
}
static
-void
-add_service_done(
- GBinderServiceManager* sm,
- int status,
- void* user_data)
+gboolean
+netd_opt_verbose(
+ const gchar* name,
+ const gchar* value,
+ gpointer data,
+ GError** error)
{
- if (status == GBINDER_STATUS_OK) {
- sd_notify(0, "READY=1");
- } else {
- g_main_loop_quit(user_data);
- }
+ gutil_log_default.level = (gutil_log_default.level < GLOG_LEVEL_DEBUG) ?
+ GLOG_LEVEL_DEBUG : GLOG_LEVEL_VERBOSE;
+ return TRUE;
}
-int main(int argc, char **argv) {
- GMainLoop *loop;
- GBinderServiceManager *svcmgr;
- GBinderLocalObject *obj;
-
- loop = g_main_loop_new(NULL, TRUE);
-
- svcmgr = gbinder_servicemanager_new(BINDER_DEVICE);
-
- obj = gbinder_servicemanager_new_local_object(svcmgr, NETD_IFACE, netd_reply, loop);
- gbinder_servicemanager_add_service(svcmgr, NETD_SLOT, obj, add_service_done, loop);
+static
+int
+netd_run(
+ const char* dev)
+{
+ GBinderServiceManager* svcmgr = gbinder_servicemanager_new(dev);
- g_main_loop_run(loop);
+ if (svcmgr) {
+ GMainLoop* loop = g_main_loop_new(NULL, TRUE);
+ guint sigterm = g_unix_signal_add(SIGTERM, netd_signal, loop);
+ guint sigint = g_unix_signal_add(SIGINT, netd_signal, loop);
+ GBinderLocalObject* obj = gbinder_servicemanager_new_local_object
+ (svcmgr, NETD_IFACE, netd_handler, NULL);
+ GBinderServiceName* name = gbinder_servicename_new
+ (svcmgr, obj, NETD_SLOT);
- gbinder_local_object_unref(obj);
- gbinder_servicemanager_unref(svcmgr);
+ /* Do we need to wait until the name is actually registered? */
+ sd_notify(0, "READY=1");
- g_main_loop_unref(loop);
+ /* Run the event loop */
+ g_main_loop_run(loop);
- return 0;
+ /* Exiting on signal */
+ g_source_remove(sigterm);
+ g_source_remove(sigint);
+ g_main_loop_unref(loop);
+
+ gbinder_servicename_unref(name);
+ gbinder_servicemanager_unref(svcmgr);
+ gbinder_local_object_drop(obj);
+ return RET_OK;
+ } else {
+ /* libgbinder prints the error in this case */
+ return RET_ERR;
+ }
}
+int main(int argc, char* argv[])
+{
+ int ret = RET_CMDLINE;
+ char* dev = NULL;
+ GError* error = NULL;
+ GOptionContext* options = g_option_context_new(NULL);
+ GOptionEntry entries[] = {
+ { "verbose", 'v', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
+ netd_opt_verbose, "Enable debug output", NULL },
+ { "device", 'd', 0, G_OPTION_ARG_STRING, &dev,
+ "Binder device [" BINDER_DEVICE "]", "DEVICE" },
+ { NULL }
+ };
+
+ gutil_log_default.name = "dummy_netd";
+ gutil_log_timestamp = FALSE;
+ g_option_context_add_main_entries(options, entries, NULL);
+ if (g_option_context_parse(options, &argc, &argv, &error)) {
+ if (argc > 1) {
+ char* help = g_option_context_get_help(options, TRUE, NULL);
+
+ fprintf(stderr, "%s", help);
+ g_free(help);
+ } else {
+ ret = netd_run((dev && dev[0]) ? dev : BINDER_DEVICE);
+ }
+ } else {
+ GERR("%s", error->message);
+ g_error_free(error);
+ }
+ g_option_context_free(options);
+ g_free(dev);
+ return ret;
+}
|