Introduction
Introduction Statistics Contact Development Disclaimer Help
Introduce struct Event and add primitive hotplugging support - smdev - suckless…
git clone git://git.suckless.org/smdev
Log
Files
Refs
README
LICENSE
---
commit cf0ac2f526b5e82d94a1cd02428ebd8bfb5cb00b
parent 18552e102e3d739d8c03379716b8acbc9ddbc8f7
Author: sin <[email protected]>
Date: Thu, 22 Aug 2013 10:45:24 +0100
Introduce struct Event and add primitive hotplugging support
This unifies the way we handle hotplug events versus static
population of the /dev directory. We also remove the assumption
for createdev() to only work correctly if the current directory
is set to the corresponding sysfs entry.
Diffstat:
M config.h | 10 +++++-----
M smdev.c | 144 ++++++++++++++++++++---------…
2 files changed, 97 insertions(+), 57 deletions(-)
---
diff --git a/config.h b/config.h
@@ -1,11 +1,11 @@
/* See LICENSE file for copyright and license details. */
struct Rule {
- const char *devregex;
- const char *user;
- const char *group;
+ char *devregex;
+ char *user;
+ char *group;
int mode;
- const char *path;
- const char *cmd;
+ char *path;
+ char *cmd;
} Rules[] = {
{ "null", "root", "root", 0666, NULL, "@chmod 666 $SMDEV" },
{ "zero", "root", "root", 0666, NULL, NULL },
diff --git a/smdev.c b/smdev.c
@@ -15,9 +15,18 @@
#include "mkpath.h"
#include "util.h"
-static int matchrule(const struct Rule *Rule, const char *devname);
-static int create_dev(const char *path);
-static void sysrecurse(const char *path);
+struct Event {
+ int min;
+ int maj;
+ char *action;
+ char *devpath;
+ char *devname;
+};
+
+static int dohotplug(void);
+static int matchrule(struct Rule *Rule, char *devname);
+static int createdev(struct Event *ev);
+static void populatedev(const char *path);
static void
usage(void)
@@ -38,17 +47,43 @@ main(int argc, char *argv[])
usage();
} ARGEND;
- if (!sflag)
- usage();
-
umask(0);
- recurse("/sys/devices", sysrecurse);
+ if (sflag)
+ recurse("/sys/devices", populatedev);
+ else
+ if (dohotplug() < 0)
+ return 1;
+ return 0;
+}
+
+static int
+dohotplug(void)
+{
+ char *min, *maj;
+ struct Event ev;
+
+ min = getenv("MINOR");
+ maj = getenv("MAJOR");
+ ev.action = getenv("ACTION");
+ ev.devpath = getenv("DEVPATH");
+ ev.devname = getenv("DEVNAME");
+ if (!min || !maj || !ev.action || !ev.devpath ||
+ !ev.devname)
+ return -1;
+
+ ev.min = estrtol(min, 10);
+ ev.maj = estrtol(maj, 10);
+
+ if (!strcmp(ev.action, "add"))
+ return createdev(&ev);
+ else
+ eprintf("Unsupported action '%s'\n", ev.action);
return 0;
}
static int
-matchrule(const struct Rule *Rule, const char *devname)
+matchrule(struct Rule *Rule, char *devname)
{
regex_t match;
regmatch_t off;
@@ -67,37 +102,23 @@ matchrule(const struct Rule *Rule, const char *devname)
}
static int
-create_dev(const char *path)
+createdev(struct Event *ev)
{
struct Rule *Rule;
struct passwd *pw;
struct group *gr;
- char buf[BUFSIZ], *p;
- const char *devname;
- char origdevname[PATH_MAX];
- int maj, min, type;
- int i, ret;
-
- p = strrchr(path, '/');
- if (!p)
- return -1;
- p++;
- devname = p;
- snprintf(origdevname, sizeof(origdevname), "/dev/%s", devname);
+ char devpath[PATH_MAX], *devname;
+ char buf[BUFSIZ];
+ int type;
+ int i;
- snprintf(buf, sizeof(buf), "%s/dev", path);
- ret = devtomajmin(buf, &maj, &min);
- if (ret < 0)
- return -1;
-
- snprintf(buf, sizeof(buf), "%d:%d", maj, min);
+ snprintf(buf, sizeof(buf), "%d:%d", ev->maj, ev->min);
type = devtype(buf);
if (type < 0)
return -1;
- if (chdir("/dev") < 0)
- eprintf("chdir /dev:");
-
+ devname = ev->devname;
+ snprintf(devpath, sizeof(devpath), "/dev/%s", devname);
for (i = 0; i < LEN(Rules); i++) {
Rule = &Rules[i];
@@ -108,40 +129,53 @@ create_dev(const char *path)
if (Rule->path[0] != '=' && Rule->path[0] != '>')
eprintf("Invalid path '%s'\n", Rule->path);
if (Rule->path[strlen(Rule->path) - 1] == '/') {
+ snprintf(buf, sizeof(buf), "/dev/%s", &Rule->p…
umask(022);
- if (mkpath(&Rule->path[1], 0755) < 0)
- eprintf("mkdir %s:", &Rule->path[1]);
+ if (mkpath(buf, 0755) < 0)
+ eprintf("mkdir %s:", buf);
umask(0);
- if (chdir(&Rule->path[1]) < 0)
- eprintf("chdir %s:", &Rule->path[1]);
+ snprintf(devpath, sizeof(devpath), "/dev/%s%s",
+ &Rule->path[1], devname);
} else {
devname = &Rule->path[1];
+ snprintf(devpath, sizeof(devpath), "/dev/%s", …
}
}
/* Create the actual dev nodes */
- ret = mknod(devname, Rules[i].mode | type, makedev(maj, min));
- if (ret < 0 && errno != EEXIST)
- eprintf("mknod %s:", devname);
+ if (mknod(devpath, Rules[i].mode | type,
+ makedev(ev->maj, ev->min)) < 0 &&
+ errno != EEXIST)
+ eprintf("mknod %s:", devpath);
+
+ errno = 0;
pw = getpwnam(Rules[i].user);
- if (!pw)
+ if (errno)
eprintf("getpwnam %s:", Rules[i].user);
+ else if (!pw)
+ enprintf(1, "getpwnam %s: no such user\n",
+ Rules[i].user);
+
+ errno = 0;
gr = getgrnam(Rules[i].group);
- if (!gr)
+ if (errno)
eprintf("getgrnam %s:", Rules[i].group);
- ret = chown(devname, pw->pw_uid, gr->gr_gid);
- if (ret < 0)
- eprintf("chown %s:", devname);
+ else if (!gr)
+ enprintf(1, "getgrnam %s: no such group\n",
+ Rules[i].group);
+
+ if (chown(devpath, pw->pw_uid, gr->gr_gid) < 0)
+ eprintf("chown %s:", devpath);
/* Create symlinks */
if (Rule->path && Rule->path[0] == '>') {
- snprintf(buf, sizeof(buf), "%s%s", &Rule->path[1], dev…
- if (symlink(buf, origdevname))
+ snprintf(buf, sizeof(buf), "/dev/%s", ev->devname);
+ if (symlink(devpath, buf))
eprintf("symlink %s -> %s:",
- origdevname, buf);
+ ev->devname, devpath);
}
- snprintf(buf, sizeof(buf), "SMDEV=%s", devname);
+ snprintf(buf, sizeof(buf), "SMDEV=%s", devpath);
if (putenv(buf) < 0)
eprintf("putenv:");
@@ -162,21 +196,27 @@ create_dev(const char *path)
break;
}
- if (chdir(path) < 0)
- eprintf("chdir %s:", path);
-
return 0;
}
static void
-sysrecurse(const char *path)
+populatedev(const char *path)
{
+ char tmppath[PATH_MAX];
char *cwd;
+ struct Event ev;
- recurse(path, sysrecurse);
+ recurse(path, populatedev);
if (!strcmp(path, "dev")) {
cwd = agetcwd();
- create_dev(cwd);
+ ev.action = "add";
+ ev.devpath = cwd + strlen("/sys");
+ ev.devname = basename(cwd);
+ snprintf(tmppath, sizeof(tmppath), "/sys%s/dev",
+ ev.devpath);
+ if (devtomajmin(tmppath, &ev.maj, &ev.min) < 0)
+ return;
+ createdev(&ev);
free(cwd);
}
}
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.