commit dd397daae5b0314ad124195a67d02f0bf5cad009
parent 4edeed89d479ba3a582913a577fbe315d53464fc
Author: sin <sin@2f30.org>
Date:   Fri, 23 Aug 2013 11:40:57 +0100
Refactor rule/event/path handling
Diffstat:
| M | smdev.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);
 	}
 }