From kappa@capella.park.rambler.ru  Wed Mar 29 17:19:31 2006
Return-Path: <kappa@capella.park.rambler.ru>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id AA78B16A400
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 29 Mar 2006 17:19:31 +0000 (UTC)
	(envelope-from kappa@capella.park.rambler.ru)
Received: from relay0.rambler.ru (relay0.rambler.ru [81.19.66.187])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 3AC0543D53
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 29 Mar 2006 17:19:30 +0000 (GMT)
	(envelope-from kappa@capella.park.rambler.ru)
Received: from relay0.rambler.ru (localhost [127.0.0.1])
	by relay0.rambler.ru (Postfix) with ESMTP id 3C49F5F7F
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 29 Mar 2006 21:19:29 +0400 (MSD)
Received: from capella.park.rambler.ru (capella.park.rambler.ru [81.19.65.30])
	by relay0.rambler.ru (Postfix) with ESMTP id 19A405F57
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 29 Mar 2006 21:19:29 +0400 (MSD)
Received: by capella.park.rambler.ru (Postfix, from userid 1001)
	id 4C1CF40D3; Wed, 29 Mar 2006 21:19:29 +0400 (MSD)
Message-Id: <20060329171929.4C1CF40D3@capella.park.rambler.ru>
Date: Wed, 29 Mar 2006 21:19:29 +0400 (MSD)
From: Alex Kapranoff <kappa@rambler-co.ru>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: [patch] apply(1) dies when there are two %1 in command
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         95079
>Category:       bin
>Synopsis:       [patch] apply(1) dies when there are two %1 in command
>Confidential:   no
>Severity:       non-critical
>Priority:       high
>Responsible:    jh
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Wed Mar 29 17:20:17 GMT 2006
>Closed-Date:    Tue Feb 01 18:24:05 UTC 2011
>Last-Modified:  Tue Feb 01 18:24:05 UTC 2011
>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@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:
Responsible-Changed-From-To: freebsd-bugs->jh 
Responsible-Changed-By: jh 
Responsible-Changed-When: Sun Feb 21 16:25:21 UTC 2010 
Responsible-Changed-Why:  
Take. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=95079 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/95079: commit references a PR
Date: Fri,  5 Mar 2010 15:23:11 +0000 (UTC)

 Author: jh
 Date: Fri Mar  5 15:23:01 2010
 New Revision: 204761
 URL: http://svn.freebsd.org/changeset/base/204761
 
 Log:
   - Use errx(3) instead of err(3) when checking if snprintf(3) succeeded.
     snprintf(3) doesn't set errno in the tested cases.
   - If the same argument reference (for example %1) was specified more than
     once, the command didn't necessarily fit to the final command buffer. Fix
     this using a dynamic sbuf buffer. Add a few regression tests for the case.
   
   PR:		bin/95079
   No objections:	freebsd-hackers
 
 Added:
   head/tools/regression/usr.bin/apply/
   head/tools/regression/usr.bin/apply/Makefile   (contents, props changed)
   head/tools/regression/usr.bin/apply/regress.00.in   (contents, props changed)
   head/tools/regression/usr.bin/apply/regress.00.out   (contents, props changed)
   head/tools/regression/usr.bin/apply/regress.01.out   (contents, props changed)
   head/tools/regression/usr.bin/apply/regress.01.sh   (contents, props changed)
   head/tools/regression/usr.bin/apply/regress.sh   (contents, props changed)
   head/tools/regression/usr.bin/apply/regress.t   (contents, props changed)
 Modified:
   head/tools/regression/usr.bin/Makefile
   head/usr.bin/apply/Makefile
   head/usr.bin/apply/apply.c
 
 Modified: head/tools/regression/usr.bin/Makefile
 ==============================================================================
 --- head/tools/regression/usr.bin/Makefile	Fri Mar  5 15:19:53 2010	(r204760)
 +++ head/tools/regression/usr.bin/Makefile	Fri Mar  5 15:23:01 2010	(r204761)
 @@ -1,6 +1,7 @@
  # $FreeBSD$
  
 -SUBDIR=	calendar comm file2c join jot m4 printf sed tr uudecode uuencode xargs
 +SUBDIR=	apply calendar comm file2c join jot m4 printf sed tr	\
 +	uudecode uuencode xargs
  .if !defined(AUTOMATED)
  SUBDIR+= lastcomm
  .endif
 
 Added: head/tools/regression/usr.bin/apply/Makefile
 ==============================================================================
 --- /dev/null	00:00:00 1970	(empty, because file is newly added)
 +++ head/tools/regression/usr.bin/apply/Makefile	Fri Mar  5 15:23:01 2010	(r204761)
 @@ -0,0 +1,4 @@
 +# $FreeBSD$
 +
 +all:
 +	@m4 ${.CURDIR}/../regress.m4 ${.CURDIR}/regress.sh | sh /dev/stdin ${.CURDIR}
 
 Added: head/tools/regression/usr.bin/apply/regress.00.in
 ==============================================================================
 --- /dev/null	00:00:00 1970	(empty, because file is newly added)
 +++ head/tools/regression/usr.bin/apply/regress.00.in	Fri Mar  5 15:23:01 2010	(r204761)
 @@ -0,0 +1 @@
 +123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 12
 
 Added: head/tools/regression/usr.bin/apply/regress.00.out
 ==============================================================================
 --- /dev/null	00:00:00 1970	(empty, because file is newly added)
 +++ head/tools/regression/usr.bin/apply/regress.00.out	Fri Mar  5 15:23:01 2010	(r204761)
 @@ -0,0 +1 @@
 +123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 12 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456
  789012345678901234567890123456789012 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123 456789012345678901234567890123456789012 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
  012345678901234567890123456789012345678901234567890123456789!
  0123456789012
 
 Added: head/tools/regression/usr.bin/apply/regress.01.out
 ==============================================================================
 --- /dev/null	00:00:00 1970	(empty, because file is newly added)
 +++ head/tools/regression/usr.bin/apply/regress.01.out	Fri Mar  5 15:23:01 2010	(r204761)
 @@ -0,0 +1 @@
 +apply: Argument list too long
 
 Added: head/tools/regression/usr.bin/apply/regress.01.sh
 ==============================================================================
 --- /dev/null	00:00:00 1970	(empty, because file is newly added)
 +++ head/tools/regression/usr.bin/apply/regress.01.sh	Fri Mar  5 15:23:01 2010	(r204761)
 @@ -0,0 +1,15 @@
 +#!/bin/sh
 +# $FreeBSD$
 +
 +SHELL=/bin/sh; export SHELL
 +
 +ARG_MAX=$(getconf ARG_MAX)
 +ARG_MAX_HALF=$((ARG_MAX / 2))
 +
 +apply 'echo %1 %1 %1' $(jot $ARG_MAX_HALF 1 1 | tr -d '\n') 2>&1
 +
 +if [ $? -eq 0 ]; then
 +	return 1
 +else
 +	return 0
 +fi
 
 Added: head/tools/regression/usr.bin/apply/regress.sh
 ==============================================================================
 --- /dev/null	00:00:00 1970	(empty, because file is newly added)
 +++ head/tools/regression/usr.bin/apply/regress.sh	Fri Mar  5 15:23:01 2010	(r204761)
 @@ -0,0 +1,10 @@
 +# $FreeBSD$
 +
 +echo 1..2
 +
 +REGRESSION_START($1)
 +
 +REGRESSION_TEST(`00', `apply "echo %1 %1 %1 %1" $(cat regress.00.in)')
 +REGRESSION_TEST(`01', `sh regress.01.sh')
 +
 +REGRESSION_END()
 
 Added: head/tools/regression/usr.bin/apply/regress.t
 ==============================================================================
 --- /dev/null	00:00:00 1970	(empty, because file is newly added)
 +++ head/tools/regression/usr.bin/apply/regress.t	Fri Mar  5 15:23:01 2010	(r204761)
 @@ -0,0 +1,6 @@
 +#!/bin/sh
 +# $FreeBSD$
 +
 +cd `dirname $0`
 +
 +m4 ../regress.m4 regress.sh | sh
 
 Modified: head/usr.bin/apply/Makefile
 ==============================================================================
 --- head/usr.bin/apply/Makefile	Fri Mar  5 15:19:53 2010	(r204760)
 +++ head/usr.bin/apply/Makefile	Fri Mar  5 15:23:01 2010	(r204761)
 @@ -2,5 +2,7 @@
  # $FreeBSD$
  
  PROG=	apply
 +DPADD=	${LIBSBUF}
 +LDADD=	-lsbuf
  
  .include <bsd.prog.mk>
 
 Modified: head/usr.bin/apply/apply.c
 ==============================================================================
 --- head/usr.bin/apply/apply.c	Fri Mar  5 15:19:53 2010	(r204760)
 +++ head/usr.bin/apply/apply.c	Fri Mar  5 15:23:01 2010	(r204761)
 @@ -44,10 +44,12 @@ static char sccsid[] = "@(#)apply.c	8.4 
  __FBSDID("$FreeBSD$");
  
  #include <sys/types.h>
 +#include <sys/sbuf.h>
  #include <sys/wait.h>
  
  #include <ctype.h>
  #include <err.h>
 +#include <errno.h>
  #include <paths.h>
  #include <signal.h>
  #include <stdio.h>
 @@ -61,10 +63,13 @@ static int	exec_shell(const char *, char
  static void	usage(void);
  
  int
 -main(int argc, char *argv[]) {
 +main(int argc, char *argv[])
 +{
 +	struct sbuf *cmdbuf;
 +	long arg_max;
  	int ch, debug, i, magic, n, nargs, offset, rval;
 -	size_t clen, cmdsize, l;
 -	char *c, *cmd, *name, *p, *q, *shell, *slashp, *tmpshell;
 +	size_t cmdsize;
 +	char *cmd, *name, *p, *shell, *slashp, *tmpshell;
  
  	debug = 0;
  	magic = '%';		/* Default magic char is `%'. */
 @@ -144,13 +149,13 @@ main(int argc, char *argv[]) {
  		p = cmd;
  		offset = snprintf(cmd, cmdsize, EXEC "%s", argv[0]);
  		if ((size_t)offset >= cmdsize)
 -			err(1, "snprintf() failed");
 +			errx(1, "snprintf() failed");
  		p += offset;
  		cmdsize -= offset;
  		for (i = 1; i <= nargs; i++) {
  			offset = snprintf(p, cmdsize, " %c%d", magic, i);
  			if ((size_t)offset >= cmdsize)
 -				err(1, "snprintf() failed");
 +				errx(1, "snprintf() failed");
  			p += offset;
  			cmdsize -= offset;
  		}
 @@ -164,61 +169,53 @@ main(int argc, char *argv[]) {
  	} else {
  		offset = snprintf(cmd, cmdsize, EXEC "%s", argv[0]);
  		if ((size_t)offset >= cmdsize)
 -			err(1, "snprintf() failed");
 +			errx(1, "snprintf() failed");
  		nargs = n;
  	}
  
 -	/*
 -	 * Grab some space in which to build the command.  Allocate
 -	 * as necessary later, but no reason to build it up slowly
 -	 * for the normal case.
 -	 */
 -	if ((c = malloc(clen = 1024)) == NULL)
 +	cmdbuf = sbuf_new(NULL, NULL, 1024, SBUF_AUTOEXTEND);
 +	if (cmdbuf == NULL)
  		err(1, NULL);
  
 +	arg_max = sysconf(_SC_ARG_MAX);
 +
  	/*
  	 * (argc) and (argv) are still offset by one to make it simpler to
  	 * expand %digit references.  At the end of the loop check for (argc)
  	 * equals 1 means that all the (argv) has been consumed.
  	 */
  	for (rval = 0; argc > nargs; argc -= nargs, argv += nargs) {
 -		/*
 -		 * Find a max value for the command length, and ensure
 -		 * there's enough space to build it.
 -		 */
 -		for (l = strlen(cmd), i = 0; i < nargs; i++)
 -			l += strlen(argv[i+1]);
 -		if (l > clen && (c = realloc(c, clen = l)) == NULL)
 -			err(1, NULL);
 -
 +		sbuf_clear(cmdbuf);
  		/* Expand command argv references. */
 -		for (p = cmd, q = c; *p != '\0'; ++p)
 +		for (p = cmd; *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;
 -			} else
 -				*q++ = *p;
 +				if (sbuf_cat(cmdbuf, argv[(++p)[0] - '0'])
 +				    == -1)
 +					errc(1, ENOMEM, "sbuf");
 +			} else {
 +				if (sbuf_putc(cmdbuf, *p) == -1)
 +					errc(1, ENOMEM, "sbuf");
 +			}
 +			if (sbuf_len(cmdbuf) > arg_max)
 +				errc(1, E2BIG, NULL);
 +		}
  
  		/* Terminate the command string. */
 -		*q = '\0';
 +		sbuf_finish(cmdbuf);
  
  		/* Run the command. */
  		if (debug)
 -			(void)printf("%s\n", c);
 +			(void)printf("%s\n", sbuf_data(cmdbuf));
  		else
 -			if (exec_shell(c, shell, name))
 +			if (exec_shell(sbuf_data(cmdbuf), shell, name))
  				rval = 1;
  	}
  
  	if (argc != 1)
  		errx(1, "expecting additional argument%s after \"%s\"",
 -	    (nargs - argc) ? "s" : "", argv[argc - 1]);
 +		    (nargs - argc) ? "s" : "", argv[argc - 1]);
  	free(cmd);
 -	free(c);
 +	sbuf_delete(cmdbuf);
  	free(shell);
  	exit(rval);
  }
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->patched 
State-Changed-By: jh 
State-Changed-When: Fri Mar 5 15:45:25 UTC 2010 
State-Changed-Why:  
Patched in head (r204761). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=95079 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/95079: commit references a PR
Date: Fri, 30 Jul 2010 12:05:32 +0000 (UTC)

 Author: jh
 Date: Fri Jul 30 12:04:29 2010
 New Revision: 210642
 URL: http://svn.freebsd.org/changeset/base/210642
 
 Log:
   MFC r204761:
   
   - Use errx(3) instead of err(3) when checking if snprintf(3) succeeded.
     snprintf(3) doesn't set errno in the tested cases.
   - If the same argument reference (for example %1) was specified more than
     once, the command didn't necessarily fit to the final command buffer. Fix
     this using a dynamic sbuf buffer. Add a few regression tests for the case.
   
   PR:		bin/95079
 
 Added:
   stable/8/tools/regression/usr.bin/apply/
      - copied from r204761, head/tools/regression/usr.bin/apply/
 Modified:
   stable/8/tools/regression/usr.bin/Makefile
   stable/8/usr.bin/apply/Makefile
   stable/8/usr.bin/apply/apply.c
 Directory Properties:
   stable/8/tools/regression/usr.bin/   (props changed)
   stable/8/tools/regression/usr.bin/pkill/pgrep-_g.t   (props changed)
   stable/8/tools/regression/usr.bin/pkill/pgrep-_s.t   (props changed)
   stable/8/tools/regression/usr.bin/pkill/pkill-_g.t   (props changed)
   stable/8/tools/regression/usr.bin/sed/   (props changed)
   stable/8/usr.bin/apply/   (props changed)
 
 Modified: stable/8/tools/regression/usr.bin/Makefile
 ==============================================================================
 --- stable/8/tools/regression/usr.bin/Makefile	Fri Jul 30 11:58:18 2010	(r210641)
 +++ stable/8/tools/regression/usr.bin/Makefile	Fri Jul 30 12:04:29 2010	(r210642)
 @@ -1,5 +1,5 @@
  # $FreeBSD$
  
 -SUBDIR=	calendar file2c join jot m4 printf sed tr uudecode uuencode xargs lastcomm
 +SUBDIR=	apply calendar file2c join jot m4 printf sed tr uudecode uuencode xargs lastcomm
  
  .include <bsd.subdir.mk>
 
 Modified: stable/8/usr.bin/apply/Makefile
 ==============================================================================
 --- stable/8/usr.bin/apply/Makefile	Fri Jul 30 11:58:18 2010	(r210641)
 +++ stable/8/usr.bin/apply/Makefile	Fri Jul 30 12:04:29 2010	(r210642)
 @@ -3,5 +3,7 @@
  
  PROG=	apply
  WARNS?=	4
 +DPADD=	${LIBSBUF}
 +LDADD=	-lsbuf
  
  .include <bsd.prog.mk>
 
 Modified: stable/8/usr.bin/apply/apply.c
 ==============================================================================
 --- stable/8/usr.bin/apply/apply.c	Fri Jul 30 11:58:18 2010	(r210641)
 +++ stable/8/usr.bin/apply/apply.c	Fri Jul 30 12:04:29 2010	(r210642)
 @@ -44,10 +44,12 @@ static char sccsid[] = "@(#)apply.c	8.4 
  __FBSDID("$FreeBSD$");
  
  #include <sys/types.h>
 +#include <sys/sbuf.h>
  #include <sys/wait.h>
  
  #include <ctype.h>
  #include <err.h>
 +#include <errno.h>
  #include <paths.h>
  #include <signal.h>
  #include <stdio.h>
 @@ -61,10 +63,13 @@ static int	exec_shell(const char *, char
  static void	usage(void);
  
  int
 -main(int argc, char *argv[]) {
 +main(int argc, char *argv[])
 +{
 +	struct sbuf *cmdbuf;
 +	long arg_max;
  	int ch, debug, i, magic, n, nargs, offset, rval;
 -	size_t clen, cmdsize, l;
 -	char *c, *cmd, *name, *p, *q, *shell, *slashp, *tmpshell;
 +	size_t cmdsize;
 +	char *cmd, *name, *p, *shell, *slashp, *tmpshell;
  
  	debug = 0;
  	magic = '%';		/* Default magic char is `%'. */
 @@ -144,13 +149,13 @@ main(int argc, char *argv[]) {
  		p = cmd;
  		offset = snprintf(cmd, cmdsize, EXEC "%s", argv[0]);
  		if ((size_t)offset >= cmdsize)
 -			err(1, "snprintf() failed");
 +			errx(1, "snprintf() failed");
  		p += offset;
  		cmdsize -= offset;
  		for (i = 1; i <= nargs; i++) {
  			offset = snprintf(p, cmdsize, " %c%d", magic, i);
  			if ((size_t)offset >= cmdsize)
 -				err(1, "snprintf() failed");
 +				errx(1, "snprintf() failed");
  			p += offset;
  			cmdsize -= offset;
  		}
 @@ -164,61 +169,53 @@ main(int argc, char *argv[]) {
  	} else {
  		offset = snprintf(cmd, cmdsize, EXEC "%s", argv[0]);
  		if ((size_t)offset >= cmdsize)
 -			err(1, "snprintf() failed");
 +			errx(1, "snprintf() failed");
  		nargs = n;
  	}
  
 -	/*
 -	 * Grab some space in which to build the command.  Allocate
 -	 * as necessary later, but no reason to build it up slowly
 -	 * for the normal case.
 -	 */
 -	if ((c = malloc(clen = 1024)) == NULL)
 +	cmdbuf = sbuf_new(NULL, NULL, 1024, SBUF_AUTOEXTEND);
 +	if (cmdbuf == NULL)
  		err(1, NULL);
  
 +	arg_max = sysconf(_SC_ARG_MAX);
 +
  	/*
  	 * (argc) and (argv) are still offset by one to make it simpler to
  	 * expand %digit references.  At the end of the loop check for (argc)
  	 * equals 1 means that all the (argv) has been consumed.
  	 */
  	for (rval = 0; argc > nargs; argc -= nargs, argv += nargs) {
 -		/*
 -		 * Find a max value for the command length, and ensure
 -		 * there's enough space to build it.
 -		 */
 -		for (l = strlen(cmd), i = 0; i < nargs; i++)
 -			l += strlen(argv[i+1]);
 -		if (l > clen && (c = realloc(c, clen = l)) == NULL)
 -			err(1, NULL);
 -
 +		sbuf_clear(cmdbuf);
  		/* Expand command argv references. */
 -		for (p = cmd, q = c; *p != '\0'; ++p)
 +		for (p = cmd; *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;
 -			} else
 -				*q++ = *p;
 +				if (sbuf_cat(cmdbuf, argv[(++p)[0] - '0'])
 +				    == -1)
 +					errc(1, ENOMEM, "sbuf");
 +			} else {
 +				if (sbuf_putc(cmdbuf, *p) == -1)
 +					errc(1, ENOMEM, "sbuf");
 +			}
 +			if (sbuf_len(cmdbuf) > arg_max)
 +				errc(1, E2BIG, NULL);
 +		}
  
  		/* Terminate the command string. */
 -		*q = '\0';
 +		sbuf_finish(cmdbuf);
  
  		/* Run the command. */
  		if (debug)
 -			(void)printf("%s\n", c);
 +			(void)printf("%s\n", sbuf_data(cmdbuf));
  		else
 -			if (exec_shell(c, shell, name))
 +			if (exec_shell(sbuf_data(cmdbuf), shell, name))
  				rval = 1;
  	}
  
  	if (argc != 1)
  		errx(1, "expecting additional argument%s after \"%s\"",
 -	    (nargs - argc) ? "s" : "", argv[argc - 1]);
 +		    (nargs - argc) ? "s" : "", argv[argc - 1]);
  	free(cmd);
 -	free(c);
 +	sbuf_delete(cmdbuf);
  	free(shell);
  	exit(rval);
  }
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->closed 
State-Changed-By: jh 
State-Changed-When: Tue Feb 1 18:24:04 UTC 2011 
State-Changed-Why:  
Fixed in head and stable/8. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=95079 
>Unformatted:
