initial import: starts and connects to ubus
authorFelix Fietkau <nbd@openwrt.org>
Fri, 1 Jun 2012 07:50:29 +0000 (09:50 +0200)
committerFelix Fietkau <nbd@openwrt.org>
Fri, 1 Jun 2012 07:50:29 +0000 (09:50 +0200)
.gitignore [new file with mode: 0644]
CMakeLists.txt [new file with mode: 0644]
main.c [new file with mode: 0644]
procd.h [new file with mode: 0644]
service.h [new file with mode: 0644]
ubus.c [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..98a2b57
--- /dev/null
@@ -0,0 +1,8 @@
+procd
+.*
+Makefile
+CMakeCache.txt
+CMakeFiles
+*.cmake
+install_manifest.txt
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..b696b32
--- /dev/null
@@ -0,0 +1,27 @@
+cmake_minimum_required(VERSION 2.6)
+
+PROJECT(procd C)
+ADD_DEFINITIONS(-Os -Wall -Werror --std=gnu99 -Wmissing-declarations)
+
+SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
+
+IF(APPLE)
+  INCLUDE_DIRECTORIES(/opt/local/include)
+  LINK_DIRECTORIES(/opt/local/lib)
+ENDIF()
+
+SET(SOURCES main.c ubus.c)
+
+SET(LIBS ubox ubus)
+
+IF(DEBUG)
+  ADD_DEFINITIONS(-DDEBUG -g3)
+ENDIF()
+
+ADD_EXECUTABLE(procd ${SOURCES})
+
+TARGET_LINK_LIBRARIES(procd ${LIBS})
+
+INSTALL(TARGETS procd
+       RUNTIME DESTINATION sbin
+)
diff --git a/main.c b/main.c
new file mode 100644 (file)
index 0000000..e081109
--- /dev/null
+++ b/main.c
@@ -0,0 +1,37 @@
+#include <getopt.h>
+#include "procd.h"
+
+int debug = 0;
+
+static int usage(const char *prog)
+{
+       fprintf(stderr, "Usage: %s [options]\n"
+               "Options:\n"
+               "    -s <path>:         Path to ubus socket\n"
+               "    -d:                Enable debug messages\n"
+               "\n", prog);
+       return 1;
+}
+
+int main(int argc, char **argv)
+{
+       int ch;
+
+       while ((ch = getopt(argc, argv, "ds:")) != -1) {
+               switch (ch) {
+               case 's':
+                       ubus_socket = optarg;
+                       break;
+               case 'd':
+                       debug++;
+                       break;
+               default:
+                       return usage(argv[0]);
+               }
+       }
+       uloop_init();
+       procd_connect_ubus();
+       uloop_run();
+
+       return 0;
+}
diff --git a/procd.h b/procd.h
new file mode 100644 (file)
index 0000000..cc063b3
--- /dev/null
+++ b/procd.h
@@ -0,0 +1,16 @@
+#ifndef __PROCD_H
+#define __PROCD_H
+
+#include <libubox/uloop.h>
+#include <stdio.h>
+
+#define DPRINTF(fmt, ...) do { \
+       if (debug) \
+               fprintf(stderr, "DEBUG %s(%d): " fmt, __func__, __LINE__, ## __VA_ARGS__); \
+       } while (0)
+
+extern int debug;
+extern char *ubus_socket;
+void procd_connect_ubus(void);
+
+#endif
diff --git a/service.h b/service.h
new file mode 100644 (file)
index 0000000..5b86b3a
--- /dev/null
+++ b/service.h
@@ -0,0 +1,19 @@
+#include <libubox/avl.h>
+#include <libubox/vlist.h>
+
+struct service {
+       struct avl_node avl;
+       const char *name;
+
+       struct vlist_tree instances;
+};
+
+struct service_instance {
+       struct vlist_node node;
+       const char *name;
+
+       struct blob_attr *config;
+       struct uloop_process proc;
+};
+
+
diff --git a/ubus.c b/ubus.c
new file mode 100644 (file)
index 0000000..bba59b4
--- /dev/null
+++ b/ubus.c
@@ -0,0 +1,84 @@
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include <libubus.h>
+
+#include "procd.h"
+
+char *ubus_socket = NULL;
+static struct ubus_context *ctx;
+static struct uloop_process ubus_proc;
+static bool ubus_connected = false;
+
+static void procd_ubus_connection_lost(struct ubus_context *old_ctx);
+
+static void ubus_proc_cb(struct uloop_process *proc, int ret)
+{
+       /* nothing to do here */
+}
+
+static void procd_restart_ubus(void)
+{
+       char *argv[] = { "ubusd", NULL, ubus_socket, NULL };
+
+       if (ubus_proc.pending) {
+               DPRINTF("Killing existing ubus instance, pid=%d\n", (int) ubus_proc.pid);
+               kill(ubus_proc.pid, SIGKILL);
+               uloop_process_delete(&ubus_proc);
+       }
+
+       if (ubus_socket)
+               argv[1] = "-s";
+
+       ubus_proc.pid = fork();
+       if (!ubus_proc.pid) {
+               execvp(argv[0], argv);
+               exit(-1);
+       }
+
+       if (ubus_proc.pid <= 0) {
+               DPRINTF("Failed to start new ubus instance\n");
+               return;
+       }
+
+       DPRINTF("Launched new ubus instance, pid=%d\n", (int) ubus_proc.pid);
+       uloop_process_add(&ubus_proc);
+}
+
+static void procd_ubus_try_connect(void)
+{
+       if (ctx) {
+               ubus_connected = !ubus_reconnect(ctx, ubus_socket);
+               return;
+       }
+
+       ctx = ubus_connect(ubus_socket);
+       if (!ctx) {
+               DPRINTF("Connection to ubus failed\n");
+               return;
+       }
+
+       ctx->connection_lost = procd_ubus_connection_lost;
+       ubus_connected = true;
+}
+
+static void procd_ubus_connection_lost(struct ubus_context *old_ctx)
+{
+       procd_ubus_try_connect();
+       while (!ubus_connected) {
+               procd_restart_ubus();
+               sleep(1);
+               procd_ubus_try_connect();
+       }
+
+       DPRINTF("Connected to ubus, id=%08x\n", ctx->local_id);
+       ubus_add_uloop(ctx);
+}
+
+void procd_connect_ubus(void)
+{
+       ubus_proc.cb = ubus_proc_cb;
+       procd_ubus_connection_lost(NULL);
+}
+