Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 13 Feb 2002 16:16:34 +1100
From:      Tim Robbins <tim@robbins.dropbear.id.au>
To:        freebsd-standards@FreeBSD.ORG
Subject:   xargs(1) -E, -p options and exit status
Message-ID:  <20020213161634.A4626@descent.robbins.dropbear.id.au>

next in thread | raw e-mail | index | archive | help
This patch corrects the exit status of xargs as well as adds the
P1003.1-2001 -E and -p options. I have not added -L and -I options because
jmallett is already working on those.

It's worth pointing out that the versions of xargs in -STABLE and -CURRENT
are NOT POSIX.2 compliant as they claim. Revision 1.7 to xargs.c totally
broke the documented 127 exit status by switching from vfork() to fork().

tim@descent$ echo 'hello' | xargs /no
xargs: /no: No such file or directory
tim@descent$ echo $?
1

Additionally, it would never exit 126 as required by P1003.2.


Tim


Index: xargs/xargs.1
===================================================================
RCS file: /home/ncvs/src/usr.bin/xargs/xargs.1,v
retrieving revision 1.15
diff -u -r1.15 xargs.1
--- xargs/xargs.1	2001/07/05 08:51:08	1.15
+++ xargs/xargs.1	2002/02/13 05:15:34
@@ -44,14 +44,14 @@
 .Nd "construct argument list(s) and execute utility"
 .Sh SYNOPSIS
 .Nm
-.Op Fl 0
+.Op Fl 0pt
+.Op Fl E Ar eofstr
 .Op Fl J Ar replstr
 .Oo
 .Fl n Ar number
 .Op Fl x
 .Oc
 .Op Fl s Ar size
-.Op Fl t
 .Op Ar utility Op Ar argument ...
 .Sh DESCRIPTION
 The
@@ -92,6 +92,10 @@
 .Fl print0
 function in
 .Xr find 1 .
+.It Fl E Ar eofstr
+Use
+.Ar eofstr
+as a logical EOF marker.
 .It Fl J Ar replstr
 If this option is specified,
 .Nm
@@ -142,6 +146,13 @@
 The current default value for
 .Ar number
 is 5000.
+.It Fl p
+Echo each command to be executed and ask the user whether it should be
+executed.
+A response of
+.Ql y
+causes the command to be executed, any other response causes it to be
+skipped.
 .It Fl s Ar size
 Set the maximum number of bytes for the command line length provided to
 .Ar utility .
@@ -184,15 +195,19 @@
 .Ar utility
 cannot be invoked, an invocation of the utility is terminated by a signal
 or an invocation of the utility exits with a value of 255.
-.Pp
+.Sh DIAGNOSTICS
 The
 .Nm
 utility exits with a value of 0 if no error occurs.
 If
+.Ar utility
+cannot be found,
+.Nm
+exits with a value of 127, otherwise if
 .Ar utility
-cannot be invoked,
+cannot be executed,
 .Nm
-exits with a value of 127.
+exits with a value of 126.
 If any other error occurs,
 .Nm
 exits with a value of 1.
Index: xargs/xargs.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/xargs/xargs.c,v
retrieving revision 1.11
diff -u -r1.11 xargs.c
--- xargs/xargs.c	2001/12/11 22:36:26	1.11
+++ xargs/xargs.c	2002/02/13 05:15:36
@@ -52,6 +52,7 @@
 #include <sys/wait.h>
 
 #include <err.h>
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -59,7 +60,7 @@
 
 #include "pathnames.h"
 
-int tflag, rval;
+int pflag, tflag, rval;
 int zflag;
 
 void run __P((char **));
@@ -74,14 +75,16 @@
 {
 	int ch;
 	char *p, *bbp, **bxp, *ebp, **exp, **xp;
-	int cnt, jfound, indouble, insingle;
+	int cnt, jfound, indouble, insingle, foundeof;
 	int nargs, nflag, nline, xflag, wasquoted;
 	char **av, **avj, *argp, **ep, *replstr;
+	const char *eofstr;
 	long arg_max;
 
 	ep = env;
 	jfound = 0;
 	replstr = NULL;			/* set if user requests -J */
+	eofstr = "";
 
 	/*
 	 * POSIX.2 limits the exec line length to ARG_MAX - 2K.  Running that
@@ -105,8 +108,11 @@
 		nline -= strlen(*ep++) + 1 + sizeof(*ep);
 	}
 	nflag = xflag = wasquoted = 0;
-	while ((ch = getopt(argc, argv, "0J:n:s:tx")) != -1)
+	while ((ch = getopt(argc, argv, "0E:J:n:ps:tx")) != -1)
 		switch(ch) {
+		case 'E':
+			eofstr = optarg;
+			break;
 		case 'J':
 			replstr = optarg;
 			break;
@@ -115,6 +121,9 @@
 			if ((nargs = atoi(optarg)) <= 0)
 				errx(1, "illegal argument count");
 			break;
+		case 'p':
+			pflag = 1;
+			break;
 		case 's':
 			nline = atoi(optarg);
 			break;
@@ -216,8 +225,11 @@
 				 errx(1, "unterminated quote");
 
 arg2:
+			foundeof = *eofstr != '\0' &&
+			    strcmp(argp, eofstr) == 0;
+
 			/* Do not make empty args unless they are quoted */
-			if (argp != p || wasquoted) {
+			if ((argp != p || wasquoted) && !foundeof) {
 				*p++ = '\0';
 				*xp++ = argp;
 			}
@@ -227,7 +239,7 @@
 			 * run the command.  If xflag and max'd out on buffer
 			 * but not on args, object.
 			 */
-			if (xp == exp || p > ebp || ch == EOF) {
+			if (xp == exp || p > ebp || ch == EOF || foundeof) {
 				if (xflag && xp != exp && p > ebp)
 					errx(1, "insufficient space for arguments");
 				if (jfound) {
@@ -236,7 +248,7 @@
 				}
 				*xp = NULL;
 				run(av);
-				if (ch == EOF)
+				if (ch == EOF || foundeof)
 					exit(rval);
 				p = bbp;
 				xp = bxp;
@@ -296,34 +308,51 @@
 run(argv)
 	char **argv;
 {
-	volatile int noinvoke;
 	char **p;
+	FILE *ttyfp;
 	pid_t pid;
-	int status;
+	int ch, status, sverrno;
 
-	if (tflag) {
+	if (tflag || pflag) {
 		(void)fprintf(stderr, "%s", *argv);
 		for (p = argv + 1; *p; ++p)
 			(void)fprintf(stderr, " %s", *p);
-		(void)fprintf(stderr, "\n");
-		(void)fflush(stderr);
+		if (pflag) {
+			if ((ttyfp = fopen("/dev/tty", "r")) != NULL) {
+				(void)fprintf(stderr, "?");
+				(void)fflush(stderr);
+				ch = getc(ttyfp);
+				fclose(ttyfp);
+				if (ch != 'y')
+					return;
+			}
+		} else {
+			(void)fprintf(stderr, "\n");
+			(void)fflush(stderr);
+		}
 	}
-	noinvoke = 0;
 	switch(pid = fork()) {
 	case -1:
 		err(1, "fork");
 	case 0:
 		execvp(argv[0], argv);
+		sverrno = errno;
 		warn("%s", argv[0]);
-		noinvoke = 1;
-		_exit(1);
+		/*
+		 * XXX Parent needs to know whether the utility couldn't be
+		 * found, or if it was found but could not be invoked.
+		 */
+		_exit(sverrno == ENOENT ? 254 : 253);
 	}
 	pid = waitpid(pid, &status, 0);
 	if (pid == -1)
 		err(1, "waitpid");
-	/* If we couldn't invoke the utility, exit 127. */
-	if (noinvoke)
+	/* Exit 127 if the utility could not be found */
+	if (WEXITSTATUS(status) == 254)
 		exit(127);
+	/* Exit 126 if the utility was found but not could be invoked */
+	if (WEXITSTATUS(status) == 253)
+		exit(126);
 	/* If utility signaled or exited with a value of 255, exit 1-125. */
 	if (WIFSIGNALED(status) || WEXITSTATUS(status) == 255)
 		exit(1);
@@ -335,7 +364,7 @@
 usage()
 {
 	fprintf(stderr,
-	    "usage: xargs [-0t] [-J replstr] [-n number [-x]] [-s size]\n"
-	    "           [utility [argument ...]]\n");
+"usage: xargs [-0pt] [-E eofstr] [-J replstr] [-n number [-x]] [-s size]\n"
+"             [utility [argument ...]]\n");
 	exit(1);
 }

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-standards" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020213161634.A4626>