Date: Sat, 1 Feb 1997 00:42:46 +0100 (CET) From: Arne Henrik Juul <arnej@imf.unit.no> To: FreeBSD-gnats-submit@freebsd.org Cc: arnej@imf.unit.no, jarle@runit.sintef.no, he@runit.sintef.no, tegge@idt.unit.no Subject: bin/2630: xargs does excessive and inconsistent argument splitting Message-ID: <199701312342.AAA07077@frida.imf.unit.no> Resent-Message-ID: <199701312350.PAA19868@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 2630
>Category: bin
>Synopsis: xargs does excessive and inconsistent argument splitting
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Fri Jan 31 15:50:02 PST 1997
>Last-Modified:
>Originator: Arne Henrik Juul
>Organization:
Norwegian University of Technology and Science
>Release: FreeBSD 2.2-GAMMA i386
>Environment:
This PR probably applies to most *BSD versions.
>Description:
I was surprised when some command-line usage of xargs
gave me trouble because it generated an empty argument.
Further investigation shows that the BSD version of
xargs (in net- and freebsd) splits the input in a very
different way from everyone else, and it's also a bit
inconsistent: Leading blanks, or any double blanks
will make xargs generate empty arguments, but a trailing
blank will not. I think it should be modified to be
more like what everybody else does, and my expections were.
At the very least the behaviour should be more consistent.
The xargs specification is very loose and informal, but
spec1170 says arguments should be 'separated by non-quoted
blanks', which I read to support (or at least allow) my
preferred behaviour.
Even worse is that quoted empty strings will be treated
the same way: A trailing "" string will be ignored.
>How-To-Repeat:
Run these commands (preferrably on different xargs implementations).
cat > echoargs << 'eof'
#!/bin/sh
for x do echo "arg: '$x'"; done
eof
chmod +x echoargs
echo xargs is:
which xargs
echo test leading, embedded double, and trailing space
echo ' 1 2 3 ' | xargs ./echoargs
echo test leading, embedded, and trailing quoted empty string
echo '"" 2 "" 4 ""' | xargs ./echoargs
>Fix:
This is a simple patch to make xargs behave like I think it
should. It is tested, but not very much. It should be noted
that this patch has an analogous effect on leading and double
NULLs in the -0 case. The -0 case can be argued both ways, I
guess, but I haven't seen anything close to a spec for it, so
I left it at this.
Index: xargs.c
===================================================================
RCS file: /usr/cvs/src/usr.bin/xargs/xargs.c,v
retrieving revision 1.3
diff -u -r1.3 xargs.c
--- xargs.c 1996/11/01 18:46:05 1.3
+++ xargs.c 1997/01/31 23:03:09
@@ -67,7 +67,7 @@
{
register int ch;
register char *p, *bbp, *ebp, **bxp, **exp, **xp;
- int cnt, indouble, insingle, nargs, nflag, nline, xflag;
+ int cnt, indouble, insingle, nargs, nflag, nline, xflag, wasquoted;
char **av, *argp, **ep = env;
/*
@@ -172,12 +172,6 @@
if (p == bbp)
exit(rval);
- /* Nothing since end of last argument. */
- if (argp == p) {
- *xp = NULL;
- run(av);
- exit(rval);
- }
goto arg1;
case ' ':
case '\t':
@@ -193,24 +187,23 @@
if (zflag)
goto addch;
- /* Empty lines are skipped. */
- if (argp == p)
- continue;
-
/* Quotes do not escape newlines. */
arg1: if (insingle || indouble)
err("unterminated quote");
-
-arg2: *p = '\0';
- *xp++ = argp;
+arg2:
+ /* Do not make empty args unless they are quoted */
+ if (argp != p || wasquoted) {
+ *p++ = '\0';
+ *xp++ = argp;
+ }
/*
* If max'd out on args or buffer, or reached EOF,
* run the command. If xflag and max'd out on buffer
* but not on args, object.
*/
- if (xp == exp || p == ebp || ch == EOF) {
- if (xflag && xp != exp && p == ebp)
+ if (xp == exp || p > ebp || ch == EOF) {
+ if (xflag && xp != exp && p > ebp)
err("insufficient space for arguments");
*xp = NULL;
run(av);
@@ -218,19 +211,21 @@
exit(rval);
p = bbp;
xp = bxp;
- } else
- ++p;
+ }
argp = p;
+ wasquoted = 0;
break;
case '\'':
if (indouble || zflag)
goto addch;
insingle = !insingle;
+ wasquoted = 1;
break;
case '"':
if (insingle || zflag)
goto addch;
indouble = !indouble;
+ wasquoted = 1;
break;
case '\\':
if (zflag)
>Audit-Trail:
>Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199701312342.AAA07077>
