Subject: Re: bin/21058: Teach unexpand -t
To: None <netbsd-bugs@netbsd.org>
From: Martin Weber <Ephaeton@gmx.net>
List: netbsd-bugs
Date: 04/08/2003 07:47:38
On Tue, Apr 08, 2003 at 12:35:34AM +0200, Christian Biere wrote:
> (..)
> You don't check whether strtoul() sets errno to ERANGE and you allow
> negative values for tabsize.

I assumed that if you get along in specifying a value which would overflow
or specify a negative value then, well, you asked for it :p

-------- take 3 --------
--- /usr/src/usr.bin/unexpand/unexpand.c	1999-02-11 16:29:14.000000000 +0100
+++ unexpand.c	2003-04-08 07:41:23.000000000 +0200
@@ -49,6 +49,8 @@
 /*
  * unexpand - put tabs into a file replacing blanks
  */
+#include <errno.h>
+#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -58,25 +60,33 @@
 char	linebuf[BUFSIZ];
 
 int	main __P((int, char **));
-void tabify __P((int));
+void tabify __P((int, int));
 
 int
 main(argc, argv)
 	int argc;
 	char *argv[];
 {
-	int all, c;
-	char *cp;
+	int all, c, tabsize;
+	char *cp, *ep;
 
-	all = 0;
-	while ((c = getopt(argc, argv, "a")) != -1) {
+	tabsize = all = 0;
+	while ((c = getopt(argc, argv, "at:")) != -1) {
 		switch (c) {
 		case 'a':
 			all++;
 			break;
+		case 't':
+			errno=0;
+			tabsize=(int) strtoul(optarg, &ep, 10);
+			if (*ep != '\0' || tabsize<=0 || errno==ERANGE ) {
+				fprintf(stderr, "unexpand: Invalid tabstop argument!\n");
+				exit(EXIT_FAILURE);
+			}
+			break;
 		case '?':
 		default:
-			fprintf(stderr, "usage: unexpand [-a] [file ...]\n");
+			fprintf(stderr, "usage: unexpand [-a] [-t tabstop] [file ...]\n");
 			exit(EXIT_FAILURE);
 			/* NOTREACHED */
 		}
@@ -97,7 +107,7 @@
 				continue;
 			if (cp > linebuf)
 				cp[-1] = 0;
-			tabify(all);
+			tabify(all, tabsize);
 			printf("%s", linebuf);
 		}
 	} while (argc > 0);
@@ -106,8 +116,9 @@
 }
 
 void
-tabify(c)
+tabify(c, sz)
 	int c;
+	int sz;
 {
 	char *cp, *dp;
 	int dcol;
@@ -124,17 +135,17 @@
 			break;
 
 		case '\t':
-			dcol += 8;
-			dcol &= ~07;
+			dcol += sz;
+			dcol = (dcol/sz) * sz;
 			break;
 
 		default:
-			while (((ocol + 8) &~ 07) <= dcol) {
+			while ((((ocol + sz)/sz)*sz) <= dcol) {
 				if (ocol + 1 == dcol)
 					break;
 				*dp++ = '\t';
-				ocol += 8;
-				ocol &= ~07;
+				ocol += sz;
+				ocol=(ocol/sz) * sz;
 			}
 			while (ocol < dcol) {
 				*dp++ = ' ';
--------------

-Martin