summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2015-11-28 19:54:54 +0100
committerMatthias Schiffer <mschiffer@universe-factory.net>2015-11-30 09:53:42 +0100
commit52ea48e47a75e98b33a95a237dbf84f3eb0c59c4 (patch)
treea41039670f50fdb7efd632438df066a5f690cf0f
parent1a2b9b054035605db496f0766d6955e8c0f82f4b (diff)
downloadunitd-52ea48e47a75e98b33a95a237dbf84f3eb0c59c4.tar
unitd-52ea48e47a75e98b33a95a237dbf84f3eb0c59c4.zip
Rip out inittab and init script handling
-rw-r--r--CMakeLists.txt2
-rw-r--r--askconsole.c64
-rw-r--r--inittab.c336
-rw-r--r--procd.h3
-rw-r--r--rcS.c183
-rw-r--r--rcS.h24
-rw-r--r--service/service.c4
-rw-r--r--state.c16
8 files changed, 68 insertions, 564 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 30b1410..7419ca5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,7 +7,7 @@ ADD_DEFINITIONS(-Os -ggdb -Wall -Werror --std=gnu99 -Wmissing-declarations)
SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
-SET(SOURCES procd.c signal.c watchdog.c state.c inittab.c rcS.c ubus.c system.c early.c
+SET(SOURCES procd.c signal.c watchdog.c state.c askconsole.c ubus.c system.c early.c
service/service.c service/instance.c service/trigger.c service/watch.c
utils/utils.c)
diff --git a/askconsole.c b/askconsole.c
new file mode 100644
index 0000000..703024e
--- /dev/null
+++ b/askconsole.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2015 Matthias Schiffer <mschiffer@universe-factory.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "procd.h"
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+
+
+static void askconsole(struct uloop_process *proc) {
+ char *const ask[] = {
+ "/sbin/askfirst",
+ "/bin/ash",
+ "--login",
+ NULL,
+ };
+
+ pid_t p;
+
+ proc->pid = fork();
+ if (!proc->pid) {
+ p = setsid();
+
+ fcntl(STDERR_FILENO, F_SETFL, fcntl(STDERR_FILENO, F_GETFL) & ~O_NONBLOCK);
+
+ ioctl(STDIN_FILENO, TIOCSCTTY, 1);
+ tcsetpgrp(STDIN_FILENO, p);
+
+ execvp(ask[0], ask);
+ ERROR("Failed to execute %s\n", ask[0]);
+ exit(-1);
+ }
+
+ if (proc->pid > 0) {
+ DEBUG(4, "Launched askconsole, pid=%d\n",
+ (int) proc->pid);
+ uloop_process_add(proc);
+ }
+}
+
+static void child_exit(struct uloop_process *proc, int ret)
+{
+ DEBUG(4, "pid:%d\n", proc->pid);
+ askconsole(proc);
+}
+
+void procd_askconsole(void) {
+ struct uloop_process *proc = malloc(sizeof(*proc));
+ proc->cb = child_exit;
+ askconsole(proc);
+}
diff --git a/inittab.c b/inittab.c
deleted file mode 100644
index 4675aca..0000000
--- a/inittab.c
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
- * Copyright (C) 2015 Matthias Schiffer <mschiffer@universe-factory.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 2.1
- * as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <regex.h>
-#include <ctype.h>
-
-#include <libubox/utils.h>
-#include <libubox/list.h>
-
-#include "utils/utils.h"
-#include "procd.h"
-#include "rcS.h"
-
-#define TAG_ID 0
-#define TAG_RUNLVL 1
-#define TAG_ACTION 2
-#define TAG_PROCESS 3
-
-#define MAX_ARGS 8
-
-struct init_action;
-char *console = NULL;
-
-struct init_handler {
- const char *name;
- void (*cb) (struct init_action *a);
- int multi;
-};
-
-struct init_action {
- struct list_head list;
-
- char *id;
- char *argv[MAX_ARGS];
- char *line;
-
- struct init_handler *handler;
- struct uloop_process proc;
-
- int respawn;
- struct uloop_timeout tout;
-};
-
-static const char *tab = "/etc/inittab";
-static char *ask = "/sbin/askfirst";
-
-static LIST_HEAD(actions);
-
-static int dev_open(const char *dev)
-{
- int fd = -1;
-
- if (dev) {
- if (chdir("/dev"))
- ERROR("failed to change dir to /dev\n");
- fd = open(dev, O_RDWR);
- if (chdir("/"))
- ERROR("failed to change dir to /\n");
- }
-
- return fd;
-}
-
-static int dev_exist(const char *dev)
-{
- int res;
-
- res = dev_open(dev);
- if (res != -1)
- close(res);
-
- return (res != -1);
-}
-
-static void fork_worker(struct init_action *a)
-{
- int fd;
- pid_t p;
-
- a->proc.pid = fork();
- if (!a->proc.pid) {
- p = setsid();
-
- fd = dev_open(a->id);
- if (fd != -1)
- {
- dup2(fd, STDIN_FILENO);
- dup2(fd, STDOUT_FILENO);
- dup2(fd, STDERR_FILENO);
- if (fd > STDERR_FILENO)
- close(fd);
- }
-
- ioctl(STDIN_FILENO, TIOCSCTTY, 1);
- tcsetpgrp(STDIN_FILENO, p);
-
- execvp(a->argv[0], a->argv);
- ERROR("Failed to execute %s\n", a->argv[0]);
- exit(-1);
- }
-
- if (a->proc.pid > 0) {
- DEBUG(4, "Launched new %s action, pid=%d\n",
- a->handler->name,
- (int) a->proc.pid);
- uloop_process_add(&a->proc);
- }
-}
-
-static void child_exit(struct uloop_process *proc, int ret)
-{
- struct init_action *a = container_of(proc, struct init_action, proc);
-
- DEBUG(4, "pid:%d\n", proc->pid);
- uloop_timeout_set(&a->tout, a->respawn);
-}
-
-static void respawn(struct uloop_timeout *tout)
-{
- struct init_action *a = container_of(tout, struct init_action, tout);
- fork_worker(a);
-}
-
-static void rcdone(struct runqueue *q)
-{
- procd_state_next();
-}
-
-static void runrc(struct init_action *a)
-{
- if (!a->argv[1] || !a->argv[2]) {
- ERROR("valid format is rcS <S|K> <param>\n");
- return;
- }
-
- /* proceed even if no init or shutdown scripts run */
- if (rcS(a->argv[1], a->argv[2], rcdone))
- rcdone(NULL);
-}
-
-static void askfirst(struct init_action *a)
-{
- int i;
-
- if (!dev_exist(a->id) || (console && !strcmp(console, a->id))) {
- DEBUG(4, "Skipping %s\n", a->id);
- return;
- }
-
- a->tout.cb = respawn;
- for (i = MAX_ARGS - 1; i >= 1; i--)
- a->argv[i] = a->argv[i - 1];
- a->argv[0] = ask;
- a->respawn = 500;
-
- a->proc.cb = child_exit;
- fork_worker(a);
-}
-
-static void askconsole(struct init_action *a)
-{
- char line[256], *tty, *split;
- int i;
-
- tty = get_cmdline_val("console", line, sizeof(line));
- if (tty != NULL) {
- split = strchr(tty, ',');
- if (split != NULL)
- *split = '\0';
-
- if (!dev_exist(tty)) {
- DEBUG(4, "skipping %s\n", tty);
- return;
- }
-
- console = strdup(tty);
- a->id = strdup(tty);
- }
- else {
- console = NULL;
- a->id = NULL;
- }
-
- a->tout.cb = respawn;
- for (i = MAX_ARGS - 1; i >= 1; i--)
- a->argv[i] = a->argv[i - 1];
- a->argv[0] = ask;
- a->respawn = 500;
-
- a->proc.cb = child_exit;
- fork_worker(a);
-}
-
-static void rcrespawn(struct init_action *a)
-{
- a->tout.cb = respawn;
- a->respawn = 500;
-
- a->proc.cb = child_exit;
- fork_worker(a);
-}
-
-static struct init_handler handlers[] = {
- {
- .name = "sysinit",
- .cb = runrc,
- }, {
- .name = "shutdown",
- .cb = runrc,
- }, {
- .name = "askfirst",
- .cb = askfirst,
- .multi = 1,
- }, {
- .name = "askconsole",
- .cb = askconsole,
- .multi = 1,
- }, {
- .name = "respawn",
- .cb = rcrespawn,
- .multi = 1,
- }
-};
-
-static int add_action(struct init_action *a, const char *name)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(handlers); i++)
- if (!strcmp(handlers[i].name, name)) {
- a->handler = &handlers[i];
- list_add_tail(&a->list, &actions);
- return 0;
- }
- ERROR("Unknown init handler %s\n", name);
- return -1;
-}
-
-void procd_inittab_run(const char *handler)
-{
- struct init_action *a;
-
- list_for_each_entry(a, &actions, list)
- if (!strcmp(a->handler->name, handler)) {
- if (a->handler->multi) {
- a->handler->cb(a);
- continue;
- }
- a->handler->cb(a);
- break;
- }
-}
-
-void procd_inittab(void)
-{
-#define LINE_LEN 128
- FILE *fp = fopen(tab, "r");
- struct init_action *a;
- regex_t pat_inittab;
- regmatch_t matches[5];
- char *line;
-
- if (!fp) {
- ERROR("Failed to open %s\n", tab);
- return;
- }
-
- regcomp(&pat_inittab, "([a-zA-Z0-9]*):([a-zA-Z0-9]*):([a-zA-Z0-9]*):(.*)", REG_EXTENDED);
- line = malloc(LINE_LEN);
- a = malloc(sizeof(struct init_action));
- memset(a, 0, sizeof(struct init_action));
-
- while (fgets(line, LINE_LEN, fp)) {
- char *tags[TAG_PROCESS + 1];
- char *tok;
- int i;
- int len = strlen(line);
-
- while (isspace(line[len - 1]))
- len--;
- line[len] = 0;
-
- if (*line == '#')
- continue;
-
- if (regexec(&pat_inittab, line, 5, matches, 0))
- continue;
-
- DEBUG(4, "Parsing inittab - %s", line);
-
- for (i = TAG_ID; i <= TAG_PROCESS; i++) {
- line[matches[i].rm_eo] = '\0';
- tags[i] = &line[matches[i + 1].rm_so];
- };
-
- tok = strtok(tags[TAG_PROCESS], " ");
- for (i = 0; i < (MAX_ARGS - 1) && tok; i++) {
- a->argv[i] = tok;
- tok = strtok(NULL, " ");
- }
- a->argv[i] = NULL;
- a->id = tags[TAG_ID];
- a->line = line;
-
- if (add_action(a, tags[TAG_ACTION]))
- continue;
- line = malloc(LINE_LEN);
- a = malloc(sizeof(struct init_action));
- memset(a, 0, sizeof(struct init_action));
- }
-
- fclose(fp);
- free(line);
- free(a);
- regfree(&pat_inittab);
-}
diff --git a/procd.h b/procd.h
index eeb2889..f11e4c5 100644
--- a/procd.h
+++ b/procd.h
@@ -45,8 +45,7 @@ void procd_preinit(void);
void procd_coldplug(void);
void procd_signal(void);
void procd_signal_preinit(void);
-void procd_inittab(void);
-void procd_inittab_run(const char *action);
+void procd_askconsole(void);
void procd_bcast_event(char *event, struct blob_attr *msg);
struct trigger;
diff --git a/rcS.c b/rcS.c
deleted file mode 100644
index fae30c7..0000000
--- a/rcS.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * runqueue-example.c
- *
- * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
- * Copyright (C) 2015 Matthias Schiffer <mschiffer@universe-factory.net>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <libubox/uloop.h>
-#include <libubox/runqueue.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <glob.h>
-
-#include <libubox/ustream.h>
-
-#include "procd.h"
-#include "rcS.h"
-
-static struct runqueue q, r;
-
-struct initd {
- struct ustream_fd fd;
- struct runqueue_process proc;
- char *file;
- char *param;
-};
-
-static void pipe_cb(struct ustream *s, int bytes)
-{
- char *newline, *str;
- int len;
-
- do {
- str = ustream_get_read_buf(s, NULL);
- if (!str)
- break;
- newline = strchr(str, '\n');
- if (!newline)
- break;
- *newline = 0;
- len = newline + 1 - str;
- syslog(LOG_NOTICE, "%s", str);
-#ifdef SHOW_BOOT_ON_CONSOLE
- fprintf(stderr, "%s\n", str);
-#endif
- ustream_consume(s, len);
- } while (1);
-}
-
-static void q_initd_run(struct runqueue *q, struct runqueue_task *t)
-{
- struct initd *s = container_of(t, struct initd, proc.task);
- int pipefd[2];
- pid_t pid;
-
- DEBUG(2, "start %s %s \n", s->file, s->param);
- if (pipe(pipefd) == -1) {
- ERROR("Failed to create pipe\n");
- return;
- }
-
- pid = fork();
- if (pid < 0)
- return;
-
- if (pid) {
- close(pipefd[1]);
- s->fd.stream.string_data = true,
- s->fd.stream.notify_read = pipe_cb,
- runqueue_process_add(q, &s->proc, pid);
- ustream_fd_init(&s->fd, pipefd[0]);
- return;
- }
- close(pipefd[0]);
- dup2(pipefd[1], STDOUT_FILENO);
- dup2(pipefd[1], STDERR_FILENO);
-
- execlp(s->file, s->file, s->param, NULL);
- exit(1);
-}
-
-static void q_initd_complete(struct runqueue *q, struct runqueue_task *p)
-{
- struct initd *s = container_of(p, struct initd, proc.task);
-
- DEBUG(2, "stop %s %s \n", s->file, s->param);
- ustream_free(&s->fd.stream);
- close(s->fd.fd.fd);
- free(s);
-}
-
-static void add_initd(struct runqueue *q, char *file, char *param)
-{
- static const struct runqueue_task_type initd_type = {
- .run = q_initd_run,
- .cancel = runqueue_process_cancel_cb,
- .kill = runqueue_process_kill_cb,
- };
- struct initd *s;
- char *p, *f;
-
- s = calloc_a(sizeof(*s), &f, strlen(file) + 1, &p, strlen(param) + 1);
- if (!s) {
- ERROR("Out of memory in %s.\n", file);
- return;
- }
- s->proc.task.type = &initd_type;
- s->proc.task.complete = q_initd_complete;
- if (!strcmp(param, "stop") || !strcmp(param, "shutdown"))
- s->proc.task.run_timeout = 15000;
- s->param = p;
- s->file = f;
- strcpy(s->param, param);
- strcpy(s->file, file);
- runqueue_task_add(q, &s->proc.task, false);
-}
-
-static int _rc(struct runqueue *q, char *path, const char *file, char *pattern, char *param)
-{
- char *dir = alloca(2 + strlen(path) + strlen(file) + strlen(pattern));
- glob_t gl;
- int j;
-
- if (!dir) {
- ERROR("Out of memory in %s.\n", file);
- return -1;
- }
-
- DEBUG(2, "running %s/%s%s %s\n", path, file, pattern, param);
- sprintf(dir, "%s/%s%s", path, file, pattern);
- if (glob(dir, GLOB_NOESCAPE | GLOB_MARK, NULL, &gl)) {
- DEBUG(2, "glob failed on %s\n", dir);
- return -1;
- }
-
- for (j = 0; j < gl.gl_pathc; j++)
- add_initd(q, gl.gl_pathv[j], param);
-
- globfree(&gl);
-
- return 0;
-}
-
-int rcS(char *pattern, char *param, void (*q_empty)(struct runqueue *))
-{
- runqueue_init(&q);
- q.empty_cb = q_empty;
- q.max_running_tasks = 1;
-
- return _rc(&q, "/etc/rc.d", pattern, "*", param);
-}
-
-int rc(const char *file, char *param)
-{
- return _rc(&r, "/etc/init.d", file, "", param);
-}
-
-static void r_empty(struct runqueue *q)
-{
-
-}
-
-static void __attribute__((constructor)) rc_init() {
- runqueue_init(&r);
- r.empty_cb = r_empty;
- r.max_running_tasks = 8;
-}
diff --git a/rcS.h b/rcS.h
deleted file mode 100644
index a5be019..0000000
--- a/rcS.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
- * Copyright (C) 2015 Matthias Schiffer <mschiffer@universe-factory.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 2.1
- * as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef __PROCD_RCS_H
-#define __PROCD_RCS_H
-
-#include <libubox/runqueue.h>
-
-extern int rcS(char *pattern, char *param, void (*q_empty)(struct runqueue *));
-extern int rc(const char *file, char *param);
-
-#endif
diff --git a/service/service.c b/service/service.c
index 90f4d7c..a983cee 100644
--- a/service/service.c
+++ b/service/service.c
@@ -21,8 +21,6 @@
#include "service.h"
#include "instance.h"
-#include "../rcS.h"
-
struct avl_tree services;
static struct blob_buf b;
static struct ubus_context *ctx;
@@ -132,8 +130,6 @@ service_update(struct service *s, struct blob_attr **tb, bool add)
vlist_flush(&s->instances);
}
- rc(s->name, "running");
-
return 0;
}
diff --git a/state.c b/state.c
index 1faa7a0..4455d2f 100644
--- a/state.c
+++ b/state.c
@@ -30,10 +30,8 @@
enum {
STATE_NONE = 0,
STATE_EARLY,
- STATE_INIT,
STATE_RUNNING,
STATE_SHUTDOWN,
- STATE_HALT,
__STATE_MAX,
};
@@ -106,19 +104,13 @@ static void state_enter(void)
service_start_early("ubus", ubus_cmd);
break;
- case STATE_INIT:
+ case STATE_RUNNING:
LOG("- init -\n");
- procd_inittab();
- procd_inittab_run("respawn");
- procd_inittab_run("askconsole");
- procd_inittab_run("askfirst");
- procd_inittab_run("sysinit");
+ procd_askconsole();
// switch to syslog log channel
ulog_open(ULOG_SYSLOG, LOG_DAEMON, "procd");
- break;
- case STATE_RUNNING:
LOG("- init complete -\n");
break;
@@ -126,11 +118,7 @@ static void state_enter(void)
/* Redirect output to the console for the users' benefit */
set_console();
LOG("- shutdown -\n");
- procd_inittab_run("shutdown");
sync();
- break;
-
- case STATE_HALT:
// To prevent killed processes from interrupting the sleep
signal(SIGCHLD, SIG_IGN);
LOG("- SIGTERM processes -\n");