shithub: neindaw

Download patch

ref: a85496cea4c5c62a2038b1b488f541e9030ff379
parent: a6875be771d0b79f59abe6529231d294094b4a23
author: Sigrid Solveig Haflínudóttir <ftrvxmtrx@gmail.com>
date: Tue Aug 24 09:30:23 EDT 2021

piper: do not keep ctl files open

--- a/cfg/cfg.c
+++ b/cfg/cfg.c
@@ -20,6 +20,7 @@
 	int index;
 
 	uvlong qidpath;
+	int fd;
 
 	int ivalue;
 	double value;
@@ -28,7 +29,6 @@
 	double max;
 	double step;
 
-	int ctl;
 	int flags;
 
 	char *group;
@@ -35,6 +35,7 @@
 	char *name;
 	char *unit;
 
+	char *ctlpath;
 	char *path;
 	UI **child;
 	int numchild;
@@ -81,17 +82,31 @@
 }
 
 static int
-readctl(UI *ui)
+initctl(UI *ui, char *path)
 {
 	Biobuf b;
 	char *s, *k;
-	int i;
+	int i, fd;
+	Dir *d;
 
+	if ((fd = open(path, OREAD)) < 0) {
+		fprint(2, "%r\n");
+		return -1;
+	}
+	if ((d = dirfstat(fd)) == nil) {
+		fprint(2, "%r\n");
+		close(fd);
+		return -1;
+	}
+	free(d);
+
+	ui->ctlpath = path;
+	ui->qidpath = d->qid.path;
 	ui->type = -1;
 	ui->show = 1; /* show everything by default */
-	seek(ui->ctl, 0, 0);
-	Binit(&b, ui->ctl, OREAD);
 
+	Binit(&b, fd, OREAD);
+
 	if ((s = Brdstr(&b, '\n', 1)) != nil && (k = strtok(s, "\t")) != nil) {
 		for (i = 0; i < nelem(uitypenames); i++) {
 			if (strcmp(k, uitypenames[i]) == 0) {
@@ -104,8 +119,6 @@
 		case UITGroup:
 		case UIHGroup:
 		case UIVGroup:
-			close(ui->ctl);
-			ui->ctl = -1;
 			break;
 		case UIButton:
 		case UICheckBox:
@@ -129,8 +142,9 @@
 		}
 	}
 	free(s);
-
+	close(fd);
 	Bterm(&b);
+
 	return 0;
 }
 
@@ -138,7 +152,7 @@
 newui(char *path)
 {
 	UI *ui;
-	Dir *dirs, *d;
+	Dir *dirs;
 	char *s, *name, tmp[64];
 	long i, n;
 	int f;
@@ -150,7 +164,7 @@
 		return nil;
 	ui = calloc(1, sizeof(*ui));
 	ui->path = strdup(path);
-	ui->ctl = -1;
+	ui->fd = -1;
 
 	if ((s = strrchr(ui->path, '/')) == nil && fd2path(f, tmp, sizeof(tmp)) == 0) {
 		if ((s = strrchr(tmp, '/')) == nil)
@@ -171,11 +185,8 @@
 		} else if (strcmp(name, "clone") == 0) {
 			ui->flags |= Hasclone;
 		} else if (strcmp(name, "ctl") == 0) {
-			ui->ctl = open(s, ORDWR);
-			if (readctl(ui) == 0 && ui->ctl >= 0 && (d = dirfstat(ui->ctl)) != nil) {
-				ui->qidpath = d->qid.path;
-				free(d);
-			}
+			if (initctl(ui, s) == 0)
+				s = nil;
 		} else if (dirs[i].mode & DMDIR) {
 			ui->child = realloc(ui->child, (ui->numchild+1) * sizeof(*ui->child));
 			ui->child[ui->numchild++] = newui(s);
@@ -187,7 +198,29 @@
 	return ui;
 }
 
+static int
+uiwrite(UI *ui, char *s, int n)
+{
+	if (ui->ctlpath == nil)
+		return -1;
+
+	if (ui->fd < 0 && (ui->fd = open(ui->ctlpath, OWRITE)) < 0) {
+		fprint(2, "%r\n");
+		return -1;
+	}
+
+	return write(ui->fd, s, n);
+}
+
 static void
+uidone(UI *ui)
+{
+	if (ui->fd >= 0)
+		close(ui->fd);
+	ui->fd = -1;
+}
+
+static void
 process_ui(UI *w)
 {
 	UI *c, *slider;
@@ -217,19 +250,24 @@
 			break;
 		case UIButton:
 			if (mu_button(c->label) & MU_RES_SUBMIT) {
-				if (write(c->ctl, "1", 1) > 0)
+				if (uiwrite(c, "1", 1) > 0)
 					c->value = 1;
+				uidone(c);
 			} else if (c->value) {
 				id = mu_get_id(c->label, strlen(c->label));
 				if (mu_ctx.focus != id || mu_ctx.mouse_down != MU_MOUSE_LEFT) {
-					if (write(c->ctl, "0", 1) > 0)
+					if (uiwrite(c, "0", 1) > 0)
 						c->value = 0;
+					uidone(c);
 				}
 			}
 			break;
 		case UICheckBox:
-			if (mu_checkbox(&c->ivalue, c->label) & MU_RES_CHANGE && write(c->ctl, c->ivalue ? "1" : "0", 1) < 0)
-				c->value = c->ivalue;
+			if (mu_checkbox(&c->ivalue, c->label) & MU_RES_CHANGE) {
+				if (uiwrite(c, c->ivalue ? "1" : "0", 1) < 0)
+					c->value = c->ivalue;
+				uidone(c);
+			}
 			break;
 		case UIVSlider: /* FIXME no vslider in µui yet */
 		case UIHSlider:
@@ -254,8 +292,9 @@
 			snprint(tmp, sizeof(tmp), "%%g%s", c->unit == nil ? "" : c->unit);
 			if (mu_slider_ex(&v, c->min, c->max, c->step, tmp, MU_OPT_ALIGNCENTER) & MU_RES_CHANGE) {
 				n = snprint(tmp, sizeof(tmp), "%g", v);
-				if (write(c->ctl, tmp, n) > 0)
+				if (uiwrite(c, tmp, n) > 0)
 					c->value = v;
+				uidone(c);
 			}
 			mu_pop_id();
 		case UINEntry: