diff options
-rw-r--r-- | .gitignore | 8 | ||||
-rw-r--r-- | CMakeLists.txt | 27 | ||||
-rw-r--r-- | main.c | 37 | ||||
-rw-r--r-- | procd.h | 16 | ||||
-rw-r--r-- | service.h | 19 | ||||
-rw-r--r-- | ubus.c | 84 |
6 files changed, 191 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..98a2b57 --- /dev/null +++ b/.gitignore @@ -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 index 0000000..b696b32 --- /dev/null +++ b/CMakeLists.txt @@ -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 +) @@ -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; +} @@ -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 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; +}; + + @@ -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); +} + |