From owner-freebsd-bugs Fri Jan 31 15:50:05 1997 Return-Path: Received: (from root@localhost) by freefall.freebsd.org (8.8.5/8.8.5) id PAA19874 for bugs-outgoing; Fri, 31 Jan 1997 15:50:05 -0800 (PST) Received: (from gnats@localhost) by freefall.freebsd.org (8.8.5/8.8.5) id PAA19868; Fri, 31 Jan 1997 15:50:03 -0800 (PST) Resent-Date: Fri, 31 Jan 1997 15:50:03 -0800 (PST) Resent-Message-Id: <199701312350.PAA19868@freefall.freebsd.org> Resent-From: gnats (GNATS Management) Resent-To: freebsd-bugs Resent-Reply-To: FreeBSD-gnats@freefall.FreeBSD.org, arnej@imf.unit.no Received: from who.cdrom.com (who.cdrom.com [204.216.27.3]) by freefall.freebsd.org (8.8.5/8.8.5) with ESMTP id PAA19715 for ; Fri, 31 Jan 1997 15:47:01 -0800 (PST) Received: from romberg.imf.unit.no (romberg.imf.unit.no [129.241.15.150]) by who.cdrom.com (8.7.5/8.6.11) with ESMTP id PAA06854 for ; Fri, 31 Jan 1997 15:46:59 -0800 (PST) Received: from frida.imf.unit.no (frida.imf.unit.no [129.241.15.136]) by romberg.imf.unit.no (8.8.3/8.7.3) with ESMTP id AAA02427; Sat, 1 Feb 1997 00:42:47 +0100 (MET) Received: (from arnej@localhost) by frida.imf.unit.no (8.8.4/8.8.4) id AAA07077; Sat, 1 Feb 1997 00:42:46 +0100 (CET) Message-Id: <199701312342.AAA07077@frida.imf.unit.no> Date: Sat, 1 Feb 1997 00:42:46 +0100 (CET) From: Arne Henrik Juul Reply-To: 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 X-Send-Pr-Version: 3.2 Subject: bin/2630: xargs does excessive and inconsistent argument splitting Sender: owner-bugs@freebsd.org X-Loop: FreeBSD.org Precedence: bulk >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: