Subject: Re: upgrade to mv
To: None <greywolf@starwolf.com>
From: Masao Uebayashi <masao@plala.or.jp>
List: tech-userlevel
Date: 08/16/2001 02:13:24
----Next_Part(Thu_Aug_16_02:13:24_2001_163)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
> What really needs to happen is for xargs(1) to be brought in-line with
> spec.
I'am looking into xargs(1)'s source and tring to implement the insert
mode (-I/-i) feature. The following patch at least works for me. But
I've not written the manual, but the spec is supposed to be compliant
to the SUSv2's -I/-i.
http://thibs.menloschool.org/help/susv2/xcu/xargs.html
(-E/-e implementation also seems not that hard.)
Regards,
Masao
----Next_Part(Thu_Aug_16_02:13:24_2001_163)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="xargs.patch"
Index: xargs.c
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/xargs/xargs.c,v
retrieving revision 1.12
diff -u -r1.12 xargs.c
--- xargs.c 1999/12/22 14:41:01 1.12
+++ xargs.c 2001/08/15 17:08:31
@@ -65,23 +65,23 @@
#include <unistd.h>
#include "pathnames.h"
-static int pflag, tflag, zflag, rval;
+static int Iflag, pflag, tflag, zflag, rval;
static FILE *promptfile;
static regex_t yesexpr;
-static void run __P((char **));
-int main __P((int, char **));
-static void usage __P((void));
+int main(int, char **);
+static void run(char **);
+static void usage(void);
int
-main(argc, argv)
- int argc;
- char **argv;
+main(int argc, char *argv[])
{
- int ch;
char *p, *bbp, *ebp, **bxp, **exp, **xp;
- int cnt, indouble, insingle, nargs, nflag, nline, xflag;
char **av, *argp;
+ char *rpltmp, **rplarg, **rplp;
+ int ch, cnt, indouble, iflag, insingle, nargs, nflag, nline, xflag;
+ extern int optind;
+ extern char *optarg;
setlocale(LC_ALL, "");
@@ -100,12 +100,24 @@
*/
nargs = 5000;
nline = ARG_MAX - 4 * 1024;
- nflag = xflag = 0;
- while ((ch = getopt(argc, argv, "0n:ps:tx")) != -1)
+ iflag = nflag = xflag = 0;
+ while ((ch = getopt(argc, argv, "0I:i:n:ps:tx")) != -1)
switch(ch) {
case '0':
zflag = 1;
break;
+ case 'I':
+ Iflag = 1;
+ /* Template of replaced string. */
+ rpltmp = optarg;
+ break;
+ case 'i':
+ iflag = 1;
+ if (optarg != NULL)
+ rpltmp = optarg;
+ else
+ rpltmp = "{}";
+ break;
case 'n':
nflag = 1;
if ((nargs = atoi(optarg)) <= 0)
@@ -115,7 +127,8 @@
pflag = tflag = 1;
break;
case 's':
- nline = atoi(optarg);
+ if ((nline = atoi(optarg)) <= 0)
+ errx(1, "illegal argument count");
break;
case 't':
tflag = 1;
@@ -138,8 +151,8 @@
* the maximum arguments to be read from stdin and the trailing
* NULL.
*/
- if (!(av = bxp =
- malloc((u_int)(1 + argc + nargs + 1) * sizeof(char **))))
+ if ((av = bxp =
+ malloc((u_int)(1 + (argc - 1) + nargs + 1) * sizeof(char **))) == NULL)
err(1, "malloc");
/*
@@ -147,13 +160,15 @@
* shell. Echo is the default. Set up pointers for the user's
* arguments.
*/
- if (!*argv)
- cnt = strlen(*bxp++ = _PATH_ECHO);
- else {
+ if (*argv == NULL) {
+ cnt = strlen(*bxp = _PATH_ECHO);
+ bxp++;
+ } else {
cnt = 0;
do {
- cnt += strlen(*bxp++ = *argv) + 1;
- } while (*++argv);
+ cnt += strlen(*bxp = *argv) + 1;
+ bxp++;
+ } while (*++argv != NULL);
}
/*
@@ -161,7 +176,8 @@
* count doesn't include the trailing NULL pointer, so the malloc
* added in an extra slot.
*/
- exp = (xp = bxp) + nargs;
+ xp = bxp;
+ exp = bxp + nargs;
/*
* Allocate buffer space for the arguments read from stdin and the
@@ -175,9 +191,26 @@
if (nline <= 0)
errx(1, "insufficient space for command");
- if (!(bbp = malloc((u_int)nline + 1)))
+ if ((bbp = malloc((u_int)nline + 1)) == NULL)
err(1, "malloc");
- ebp = (argp = p = bbp) + nline - 1;
+ argp = p = bbp;
+ ebp = bbp + nline - 1;
+
+ if (Iflag || iflag) {
+ int n = 0;
+ /* It's senseless to replace the utility's name. */
+ for (xp = av + 1; xp < bxp; ++xp) {
+ /* printf("TRY: %s\t%s\n", rpltmp, *xp); */
+ if (strcmp((const char *)rpltmp, (const char *)*xp) == 0) {
+ /* printf("RPL: %s\t%s\n", rpltmp, *xp); */
+ *xp = bbp;
+ ++n;
+ }
+ if (n == 5)
+ break;
+ }
+ xp = bxp;
+ }
if (pflag) {
int error;
@@ -188,7 +221,7 @@
!= 0) {
char msg[NL_TEXTMAX];
- (void)regerror(error, NULL, msg, sizeof (msg));
+ (void)regerror(error, NULL, msg, sizeof(msg));
err(1, "cannot compile yesexpr: %s", msg);
}
}
@@ -218,6 +251,7 @@
goto arg2;
goto addch;
case '\n':
+ /* Read newline as normal character. (zflag is not documented?) */
if (zflag)
goto addch;
/* Empty lines are skipped. */
@@ -225,12 +259,21 @@
continue;
/* Quotes do not escape newlines. */
-arg1: if (insingle || indouble)
- errx(1, "unterminated quote");
+arg1: if (insingle || indouble)
+ errx(1, "unterminated quote");
-arg2: *p = '\0';
+arg2: *p = '\0';
*xp++ = argp;
+ /* Run a command per line. */
+ if (Iflag || iflag) {
+ *bxp = NULL;
+ run(av);
+ argp = p = bbp;
+ xp = bxp;
+ break;
+ }
+
/*
* If max'd out on args or buffer, or reached EOF,
* run the command. If xflag and max'd out on buffer
@@ -267,12 +310,14 @@
errx(1, "backslash at EOF");
/* FALLTHROUGH */
default:
-addch: if (p < ebp) {
+addch: if (p < ebp) {
*p++ = ch;
break;
}
- /* If only one argument, not enough buffer space. */
+ /*
+ * Buffer is full. If only one argument, not enough buffer space.
+ */
if (bxp == xp)
errx(1, "insufficient space for argument");
/* Didn't hit argument limit, so if xflag object. */
@@ -281,10 +326,12 @@
*xp = NULL;
run(av);
+
xp = bxp;
cnt = ebp - argp;
memmove(bbp, argp, cnt);
- p = (argp = bbp) + cnt;
+ argp = bbp;
+ p = bbp + cnt;
*p++ = ch;
break;
}
@@ -292,8 +339,7 @@
}
static void
-run(argv)
- char **argv;
+run(char **argv)
{
volatile int noinvoke;
char **p;
@@ -302,14 +348,14 @@
if (tflag) {
(void)fprintf(stderr, "%s", *argv);
- for (p = argv + 1; *p; ++p)
+ for (p = argv + 1; *p != NULL; ++p)
(void)fprintf(stderr, " %s", *p);
if (pflag) {
char buf[LINE_MAX + 1];
(void)fprintf(stderr, "?...");
fflush(stderr);
- if (fgets(buf, sizeof (buf), promptfile) == NULL) {
+ if (fgets(buf, sizeof(buf), promptfile) == NULL) {
rval = 1;
return;
}
@@ -350,17 +396,15 @@
if (WEXITSTATUS (status) == 255) {
warnx ("%s exited with status 255", argv[0]);
exit(124);
- } else if (WEXITSTATUS (status) != 0) {
+ } else if (WEXITSTATUS (status) != 0)
rval = 123;
- }
} else if (WIFSIGNALED (status)) {
- if (WTERMSIG(status) < NSIG) {
+ if (WTERMSIG(status) < NSIG)
warnx("%s terminated by SIG%s", argv[0],
sys_signame[WTERMSIG(status)]);
- } else {
+ else
warnx("%s terminated by signal %d", argv[0],
WTERMSIG(status));
- }
exit(125);
}
}
----Next_Part(Thu_Aug_16_02:13:24_2001_163)----