Index | Thread | Search

From:
Florian Obser <florian@openbsd.org>
Subject:
watch(1): construct cmdstr in a less clever way
To:
tech <tech@openbsd.org>
Date:
Tue, 20 May 2025 14:38:57 +0200

Download raw body.

Thread
OK?

diff --git watch.c watch.c
index 5989c69cdd8..b6d6e95ae73 100644
--- watch.c
+++ watch.c
@@ -77,6 +77,7 @@ int xflag = 0;
 #define	WCWIDTH(_x)	((wcwidth((_x)) > 0)? wcwidth((_x)) : 1)
 
 static char	 *cmdstr;
+static size_t	  cmdlen;
 static char	**cmdv;
 
 typedef wchar_t BUFFER[MAXLINE][MAXCOLUMN + 1];
@@ -114,8 +115,9 @@ set_interval(const char *str)
 int
 main(int argc, char *argv[])
 {
-	int i, ch, cmdsiz = 0;
-	char *s;
+	size_t len, rest;
+	int i, ch;
+	char *p;
 
 	while ((ch = getopt(argc, argv, "cls:wx")) != -1)
 		switch (ch) {
@@ -153,24 +155,30 @@ main(int argc, char *argv[])
 	if ((cmdv = calloc(argc + 1, sizeof(char *))) == NULL)
 		err(1, "calloc");
 
-	cmdstr = "";
+	cmdlen = 0;
 	for (i = 0; i < argc; i++) {
 		cmdv[i] = argv[i];
-		while (strlen(cmdstr) + strlen(argv[i]) + 3 > cmdsiz) {
-			if (cmdsiz == 0) {
-				cmdsiz = 128;
-				s = calloc(cmdsiz, 1);
-			} else {
-				cmdsiz *= 2;
-				s = realloc(cmdstr, cmdsiz);
-			}
-			if (s == NULL)
-				err(1, "malloc");
-			cmdstr = s;
-		}
+		cmdlen += strlen(argv[i]);
 		if (i != 0)
-			strlcat(cmdstr, " ", cmdsiz);
-		strlcat(cmdstr, argv[i], cmdsiz);
+			cmdlen++;
+	}
+
+	if ((cmdstr = calloc(cmdlen + 1, sizeof(char))) == NULL)
+		err(1, "calloc");
+
+	p = cmdstr;
+	rest = cmdlen + 1;
+
+	for (i = 0; i < argc; i++) {
+		if (i == 0)
+			len = snprintf(p, rest, "%s", argv[i]);
+		else
+			len = snprintf(p, rest, " %s", argv[i]);
+
+		if ((size_t)len >= rest)
+			errx(1, "overflow");
+		rest -= len;
+		p += len;
 	}
 	cmdv[i++] = NULL;
 
@@ -272,7 +280,7 @@ display(BUFFER * cur, BUFFER * prev, highlight_mode_t hm)
 	erase();
 
 	move(0, 0);
-	if ((int)strlen(cmdstr) > COLS - 47)
+	if (cmdlen > COLS - 47)
 		printw("\"%-.*s..\" ", COLS - 49, cmdstr);
 	else
 		printw("\"%s\" ", cmdstr);

-- 
In my defence, I have been left unsupervised.