bin/95079: [patch] apply(1) dies when there are two %1 in command

Alex Kapranoff kappa at rambler-co.ru
Wed Mar 29 17:20:19 UTC 2006


>Number:         95079
>Category:       bin
>Synopsis:       [patch] apply(1) dies when there are two %1 in command
>Confidential:   no
>Severity:       non-critical
>Priority:       high
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Wed Mar 29 17:20:17 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator:     Alex Kapranoff
>Release:        FreeBSD 5.2-CURRENT i386
>Organization:
Inner Mongolia
>Environment:
FreeBSD capella.park.rambler.ru 6.1-PRERELEASE FreeBSD 6.1-PRERELEASE #0: Fri Mar 17 16:20:26 MSK 2006     root at capella.park.rambler.ru:/usr/obj/usr/src/sys/CAPELLA2  i386

>Description:
	apply(1) was not designed to handle situations when user wants
	to use the same argument in the command more than once.

>How-To-Repeat:
% ls
00045qqf.png     LinkPotProto.zip
% apply 'echo %1 %1' *
00045qqf.png 00045qqf.png
apply: snprintf() failed: Unknown error: 0
%

>Fix:

manpage patch includes an example.

diff -ru /usr/src/usr.bin/apply/apply.1 ./apply.1
--- /usr/src/usr.bin/apply/apply.1	Mon Jul 25 12:12:13 2005
+++ ./apply.1	Wed Mar 29 21:12:44 2006
@@ -123,7 +123,9 @@
 5 times; and
 .It Li "apply \'ln %1 /usr/joe\'" *
 links all files in the current directory to the directory
-.Pa /usr/joe .
+.Pa /usr/joe ;
+.It Li "apply \'diff %1 %1.bak\'" *
+compares all files in the current directory to their backup copies.
 .El
 .Sh HISTORY
 The
diff -ru /usr/src/usr.bin/apply/apply.c ./apply.c
--- /usr/src/usr.bin/apply/apply.c	Wed Apr 28 00:41:25 2004
+++ ./apply.c	Wed Mar 29 21:06:28 2006
@@ -66,6 +66,8 @@
 	size_t clen, cmdsize, l;
 	char *c, *cmd, *name, *p, *q, *shell, *slashp, *tmpshell;
 
+	int cn[10];
+
 	debug = 0;
 	magic = '%';		/* Default magic char is `%'. */
 	nargs = -1;
@@ -99,13 +101,15 @@
 	/*
 	 * The command to run is argv[0], and the args are argv[1..].
 	 * Look for %digit references in the command, remembering the
-	 * largest one.
+	 * largest one and count each %digit.
 	 */
+	bzero(cn, sizeof cn);
 	for (n = 0, p = argv[0]; *p != '\0'; ++p)
 		if (p[0] == magic && isdigit(p[1]) && p[1] != '0') {
 			++p;
 			if (p[0] - '0' > n)
 				n = p[0] - '0';
+			++cn[p[0] - '0'];
 		}
 
 	/*
@@ -187,19 +191,15 @@
 		 * there's enough space to build it.
 		 */
 		for (l = strlen(cmd), i = 0; i < nargs; i++)
-			l += strlen(argv[i+1]);
+			l += strlen(argv[i+1]) * cn[i];
 		if (l > clen && (c = realloc(c, clen = l)) == NULL)
 			err(1, NULL);
 
 		/* Expand command argv references. */
 		for (p = cmd, q = c; *p != '\0'; ++p)
 			if (p[0] == magic && isdigit(p[1]) && p[1] != '0') {
-				offset = snprintf(q, l, "%s",
-				    argv[(++p)[0] - '0']);
-				if ((size_t)offset >= l)
-					err(1, "snprintf() failed");
-				q += offset;
-				l -= offset;
+                                strlcpy(q, argv[(++p)[0] - '0'], c + clen - q);
+                                q += strlen(q);
 			} else
 				*q++ = *p;
 
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list