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 @@
+12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012

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 @@
+12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012
 
12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456
 789012345678901234567890123456789012 
12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012
 
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);
 }
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to