From patchwork Tue Jan 20 00:21:30 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Owen Kirby X-Patchwork-Id: 430750 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from arrakis.dune.hu (arrakis.dune.hu [78.24.191.176]) (using TLSv1.1 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 151451402BD for ; Tue, 20 Jan 2015 11:21:46 +1100 (AEDT) Received: from arrakis.dune.hu (localhost [127.0.0.1]) by arrakis.dune.hu (Postfix) with ESMTP id 218E728054B; Tue, 20 Jan 2015 01:19:22 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on arrakis.dune.hu X-Spam-Level: X-Spam-Status: No, score=-1.5 required=5.0 tests=BAYES_00 autolearn=unavailable version=3.3.2 Received: from arrakis.dune.hu (localhost [127.0.0.1]) by arrakis.dune.hu (Postfix) with ESMTP id D35E828054B for ; Tue, 20 Jan 2015 01:19:16 +0100 (CET) X-policyd-weight: using cached result; rate: -5.5 Received: from mail-pa0-f43.google.com (mail-pa0-f43.google.com [209.85.220.43]) by arrakis.dune.hu (Postfix) with ESMTPS for ; Tue, 20 Jan 2015 01:19:16 +0100 (CET) Received: by mail-pa0-f43.google.com with SMTP id eu11so4500408pac.2 for ; Mon, 19 Jan 2015 16:21:34 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:message-id:date:from:user-agent:mime-version:to :subject:content-type:content-transfer-encoding; bh=4BeydyTbRMlor+sJcQ5hqxIJ8ahWNb7/3Mdiz4LHNdM=; b=BzOTot5hdeEB6/CFKn4LxXSJqFnlI1KwRxR4+r8X2uurXSMTnNPsvMgDbtJY0lQfn2 vx1ne94R/HYs2VGTYdSfcACyFq/kXgs8AQUB6+9rDd+XmxZF/gpp6dPvLyw4FMnnrjL3 ffu79QqUpmfwAwOqLFbQr31gqst73nHhXW91OimfGCMuelpjmuAWCcZnEXFWuMfjscUL Ju23r9LPKsom0ROtM9AleA+3KCzOJdGkznygsds8qgrQ98sjdUht2WeWCasJ34q0HfMb kh4etjLcGY1dAL+mMLUhRAptPkDQozeLFK8uj0WRp/uWXNeBh/rN8/QHg6SEZTzTdMul J5wQ== X-Gm-Message-State: ALoCoQkks5yXgLCiY8L9rFSyd5zh34NyqMfDpJYePbZ911yuEkajAERrU2jHmm1BpnQZU2LOxj3Z X-Received: by 10.66.148.161 with SMTP id tt1mr43118559pab.85.1421713293722; Mon, 19 Jan 2015 16:21:33 -0800 (PST) Received: from [172.16.16.147] ([184.71.143.130]) by mx.google.com with ESMTPSA id wy1sm1185864pbc.5.2015.01.19.16.21.31 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 19 Jan 2015 16:21:32 -0800 (PST) Message-ID: <54BD9F8A.2020907@exegin.com> Date: Mon, 19 Jan 2015 16:21:30 -0800 From: Owen Kirby User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.3.0 MIME-Version: 1.0 To: "openwrt-devel@lists.openwrt.org" , John Crispin Subject: [OpenWrt-Devel] [PATCH v2] procd: delay inittab workers until the tty exists. X-BeenThere: openwrt-devel@lists.openwrt.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: OpenWrt Development List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: openwrt-devel-bounces@lists.openwrt.org Sender: "openwrt-devel" Add hotplug support for tty devices in /etc/inittab that are specified by the askfirst keyword so that terminals attached after boot time get console processes started. This was tested on an AT91 target using the gadget serial subsystem and on an WNDR3800 with a USB serial adapter. One possible weirdness I encountered was that the baud rates and control modes sometimes need adjusting with a hotplug script after reconnecting the adapter. This is also only implemented for askfirst, but it might also make sense to do the same thing for respawn and askconsole. Signed-off-by: Owen Kirby --- inittab.c | 35 ++++++++++++++++++++++++++++++++--- plug/hotplug.c | 40 +++++++++++++++++++++++++++++++++++----- plug/hotplug.h | 15 +++++++++++++++ 3 files changed, 82 insertions(+), 8 deletions(-) diff --git a/inittab.c b/inittab.c index 623103d..c9310e5 100644 --- a/inittab.c +++ b/inittab.c @@ -26,6 +26,7 @@ #include #include +#include "plug/hotplug.h" #include "utils/utils.h" #include "procd.h" #include "rcS.h" @@ -55,6 +56,7 @@ struct init_action { struct init_handler *handler; struct uloop_process proc; + struct hotplug_event event; int respawn; struct uloop_timeout tout; @@ -90,6 +92,29 @@ static int dev_exist(const char *dev) return (res != -1); } +static void dev_hotplug(struct hotplug_event *event, struct blob_attr *msg) +{ + struct init_action *a = container_of(event, struct init_action, event); + char *action = hotplug_msg_find_var(msg, "ACTION"); + char *subsystem = hotplug_msg_find_var(msg, "SUBSYSTEM"); + char *devname = hotplug_msg_find_var(msg, "DEVNAME"); + + if (!action || !subsystem || !devname) + return; + if (strcmp(subsystem, "tty") || strcmp(devname, a->id)) + return; + + DEBUG(4, "inittab hotplug: ACTION=\"%s\", SUBSYSTEM=\"%s\", DEVNAME=\"%s\"\n", + action, subsystem, devname); + if (!strcmp(action, "add")) { + uloop_timeout_set(&a->tout, a->respawn); + } + else if (!strcmp(action, "remove")) { + uloop_process_delete(&a->proc); + uloop_timeout_cancel(&a->tout); + } +} + static void fork_worker(struct init_action *a) { int fd; @@ -130,7 +155,7 @@ 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); + uloop_timeout_set(&a->tout, a->respawn); } static void respawn(struct uloop_timeout *tout) @@ -157,7 +182,7 @@ static void askfirst(struct init_action *a) { int i; - if (!dev_exist(a->id) || (console && !strcmp(console, a->id))) { + if (console && !strcmp(console, a->id)) { DEBUG(4, "Skipping %s\n", a->id); return; } @@ -168,8 +193,12 @@ static void askfirst(struct init_action *a) a->argv[0] = ask; a->respawn = 500; + a->event.cb = dev_hotplug; + hotplug_event_add(&a->event); + a->proc.cb = child_exit; - fork_worker(a); + if (dev_exist(a->id)) + fork_worker(a); } static void askconsole(struct init_action *a) diff --git a/plug/hotplug.c b/plug/hotplug.c index 061833a..3aa87c0 100644 --- a/plug/hotplug.c +++ b/plug/hotplug.c @@ -44,13 +44,14 @@ struct cmd_queue { }; static LIST_HEAD(cmd_queue); +static LIST_HEAD(events); static struct uloop_process queue_proc; static struct uloop_timeout last_event; static struct blob_buf b; static char *rule_file; static struct blob_buf script; -static char *hotplug_msg_find_var(struct blob_attr *msg, const char *name) +char *hotplug_msg_find_var(struct blob_attr *msg, const char *name) { struct blob_attr *cur; int rem; @@ -393,24 +394,30 @@ static struct json_script_ctx jctx = { .handle_file = rule_handle_file, }; -static void hotplug_handler_debug(struct blob_attr *data) +static void hotplug_handler_debug(struct hotplug_event *e, struct blob_attr *msg) { char *str; if (debug < 3) return; - str = blobmsg_format_json(data, true); + str = blobmsg_format_json(msg, true); DEBUG(3, "%s\n", str); free(str); } +static void hotplug_handler_script(struct hotplug_event *e, struct blob_attr *msg) +{ + json_script_run(&jctx, rule_file, msg); +} + static void hotplug_handler(struct uloop_fd *u, unsigned int ev) { int i = 0; static char buf[4096]; int len = recv(u->fd, buf, sizeof(buf), MSG_DONTWAIT); void *index; + struct hotplug_event *e, *tmp; if (len < 1) return; @@ -427,10 +434,16 @@ static void hotplug_handler(struct uloop_fd *u, unsigned int ev) i += l; } blobmsg_close_table(&b, index); - hotplug_handler_debug(b.head); - json_script_run(&jctx, rule_file, blob_data(b.head)); + list_for_each_entry_safe(e, tmp, &events, list) + e->cb(e, blob_data(b.head)); } +static struct hotplug_event script_event = { + .cb = hotplug_handler_script, +}; +static struct hotplug_event debug_event = { + .cb = hotplug_handler_debug, +}; static struct uloop_fd hotplug_fd = { .cb = hotplug_handler, }; @@ -470,6 +483,8 @@ void hotplug(char *rules) json_script_init(&jctx); queue_proc.cb = queue_proc_cb; uloop_fd_add(&hotplug_fd, ULOOP_READ); + hotplug_event_add(&debug_event); + hotplug_event_add(&script_event); } int hotplug_run(char *rules) @@ -486,3 +501,18 @@ void hotplug_shutdown(void) uloop_fd_delete(&hotplug_fd); close(hotplug_fd.fd); } + +int hotplug_event_add(struct hotplug_event *e) +{ + list_add_tail(&e->list, &events); + + return 0; +} + +int hotplug_event_delete(struct hotplug_event *e) +{ + list_del(&e->list); + + return 0; +} + diff --git a/plug/hotplug.h b/plug/hotplug.h index 2a44442..4870476 100644 --- a/plug/hotplug.h +++ b/plug/hotplug.h @@ -16,10 +16,25 @@ #define __PROCD_HOTPLUG_H #include +#include +#include "../utils/utils.h" + +struct hotplug_event; + +typedef void (*hotplug_event_handler)(struct hotplug_event *event, struct blob_attr *msg); + +struct hotplug_event { + struct list_head list; + + hotplug_event_handler cb; +}; void hotplug(char *rules); int hotplug_run(char *rules); void hotplug_shutdown(void); void hotplug_last_event(uloop_timeout_handler handler); +char *hotplug_msg_find_var(struct blob_attr *msg, const char *name); +int hotplug_event_add(struct hotplug_event *event); +int hotplug_event_delete(struct hotplug_event *event); #endif