smdev

suckless mdev
git clone git://git.suckless.org/smdev
Log | Files | Refs | README | LICENSE

commit dd397daae5b0314ad124195a67d02f0bf5cad009
parent 4edeed89d479ba3a582913a577fbe315d53464fc
Author: sin <sin@2f30.org>
Date:   Fri, 23 Aug 2013 11:40:57 +0100

Refactor rule/event/path handling

Diffstat:
Msmdev.c | 187++++++++++++++++++++++++++++++++++++++++---------------------------------------
1 file changed, 95 insertions(+), 92 deletions(-)

diff --git a/smdev.c b/smdev.c @@ -30,6 +30,7 @@ struct Event { enum action action; char *devpath; char *devname; + struct Rule *Rule; }; static struct pregentry { @@ -39,10 +40,13 @@ static struct pregentry { static int dohotplug(void); static int matchrule(int ruleidx, char *devname); -static void runrule(struct Event *ev, struct Rule *Rule); +static void runrule(struct Rule *Rule); static void parsepath(struct Rule *Rule, char *devpath, size_t sz, char *devname); static int createdev(struct Event *ev); +static int doevent(struct Event *ev); +static int craftev(struct Event *ev, enum action action, + char *sysfspath); static void populatedev(const char *path); static void @@ -109,15 +113,7 @@ dohotplug(void) ev.maj = estrtol(maj, 10); ev.action = mapaction(action); - switch (ev.action) { - case ADD_ACTION: - return createdev(&ev); - default: - eprintf("Unsupported action '%s'\n", - ev.action); - } - - return 0; + return doevent(&ev); } static int @@ -144,30 +140,12 @@ matchrule(int ruleidx, char *devname) } static void -runrule(struct Event *ev, struct Rule *Rule) +runrule(struct Rule *Rule) { if (!Rule->cmd) return; - switch (Rule->cmd[0]) { - case '*': - switch (ev->action) { - case ADD_ACTION: - system(&Rule->cmd[1]); - break; - default: - eprintf("Unsupported action '%s'\n", - ev->action); - } - break; - case '@': - system(&Rule->cmd[1]); - break; - case '$': - eprintf("Unsupported action '%s'\n", ev->action); - default: - eprintf("Invalid command '%s'\n", Rule->cmd); - } + system(&Rule->cmd[1]); } static void @@ -183,8 +161,6 @@ parsepath(struct Rule *Rule, char *devpath, size_t sz, p = strchr(&Rule->path[1], '/'); if (p) { if (Rule->path[strlen(Rule->path) - 1] == '/') { - snprintf(buf, sizeof(buf), "/dev/%s", - &Rule->path[1]); snprintf(devpath, sz, "/dev/%s%s", &Rule->path[1], devname); } else { @@ -193,20 +169,14 @@ parsepath(struct Rule *Rule, char *devpath, size_t sz, eprintf("strdup:"); snprintf(buf, sizeof(buf), "/dev/%s", dirname(dirc)); free(dirc); - basec = strdup(&Rule->path[1]); if (!basec) eprintf("strdup:"); strlcpy(devname, basename(basec), sizeof(devname)); free(basec); - snprintf(devpath, sz, "%s/%s", buf, devname); } - umask(022); - if (mkpath(buf, 0755) < 0) - eprintf("mkdir %s:", buf); - umask(0); } else { strlcpy(devname, &Rule->path[1], sizeof(devname)); snprintf(devpath, sz, "/dev/%s", devname); @@ -219,11 +189,13 @@ createdev(struct Event *ev) struct Rule *Rule; struct passwd *pw; struct group *gr; + char *dirc; char devpath[PATH_MAX]; char devname[PATH_MAX]; char buf[BUFSIZ]; int type; - int i; + + Rule = ev->Rule; snprintf(buf, sizeof(buf), "%d:%d", ev->maj, ev->min); type = devtype(buf); @@ -232,78 +204,109 @@ createdev(struct Event *ev) strlcpy(devname, ev->devname, sizeof(devname)); snprintf(devpath, sizeof(devpath), "/dev/%s", devname); - for (i = 0; i < LEN(Rules); i++) { - Rule = &Rules[i]; - if (matchrule(i, devname) < 0) - continue; + if (Rule->path) { + parsepath(Rule, devpath, sizeof(devpath), + devname); + dirc = strdup(devpath); + if (!dirc) + eprintf("strdup:"); + strlcpy(buf, dirname(dirc), sizeof(buf)); + free(dirc); + umask(022); + if (mkpath(buf, 0755) < 0) + eprintf("mkdir %s:", buf); + umask(0); + } - if (Rule->path) - parsepath(Rule, devpath, sizeof(devpath), - devname); - - /* Create the actual dev nodes */ - 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 (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 (errno) - eprintf("getgrnam %s:", Rules[i].group); - 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), "/dev/%s", ev->devname); - if (symlink(devpath, buf)) - eprintf("symlink %s -> %s:", - ev->devname, devpath); - } + /* Create the actual dev nodes */ + if (mknod(devpath, Rule->mode | type, + makedev(ev->maj, ev->min)) < 0 && + errno != EEXIST) + eprintf("mknod %s:", devpath); + + errno = 0; + pw = getpwnam(Rule->user); + if (errno) + eprintf("getpwnam %s:", Rule->user); + else if (!pw) + enprintf(1, "getpwnam %s: no such user\n", + Rule->user); + + errno = 0; + gr = getgrnam(Rule->group); + if (errno) + eprintf("getgrnam %s:", Rule->group); + else if (!gr) + enprintf(1, "getgrnam %s: no such group\n", + Rule->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), "/dev/%s", ev->devname); + if (symlink(devpath, buf)) + eprintf("symlink %s -> %s:", + ev->devname, devpath); + } + + snprintf(buf, sizeof(buf), "SMDEV=%s", devpath); + if (putenv(buf) < 0) + eprintf("putenv:"); + + runrule(Rule); - snprintf(buf, sizeof(buf), "SMDEV=%s", devpath); - if (putenv(buf) < 0) - eprintf("putenv:"); + return 0; +} + +static int +doevent(struct Event *ev) +{ + int i; - runrule(ev, Rule); + for (i = 0; i < LEN(Rules); i++) { + if (matchrule(i, ev->devname) < 0) + continue; + ev->Rule = &Rules[i]; + switch (ev->action) { + case ADD_ACTION: + return createdev(ev); + default: + break; + } break; } + return 0; +} +static int +craftev(struct Event *ev, enum action action, char *sysfspath) +{ + char path[PATH_MAX]; + + ev->action = action; + ev->devpath = sysfspath + strlen("/sys"); + ev->devname = basename(sysfspath); + snprintf(path, sizeof(path), "/sys%s/dev", + ev->devpath); + if (devtomajmin(path, &ev->maj, &ev->min) < 0) + return -1; return 0; } static void populatedev(const char *path) { - char tmppath[PATH_MAX]; char *cwd; struct Event ev; recurse(path, populatedev); if (!strcmp(path, "dev")) { cwd = agetcwd(); - ev.action = ADD_ACTION; - 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); + if (!craftev(&ev, ADD_ACTION, cwd)) + doevent(&ev); free(cwd); } }