Initial Import from SVN
This commit is contained in:
39
src/cmd/xargs/Makefile
Normal file
39
src/cmd/xargs/Makefile
Normal file
@@ -0,0 +1,39 @@
|
||||
#
|
||||
# Public Domain. 1995/03/13 - Steven Schultz
|
||||
#
|
||||
TOPSRC = $(shell cd ../../..; pwd)
|
||||
include $(TOPSRC)/target.mk
|
||||
|
||||
CFLAGS += -Werror
|
||||
|
||||
SRCS = xargs.c
|
||||
OBJS = xargs.o
|
||||
MAN = xargs.0
|
||||
MANSRC = xargs.1
|
||||
|
||||
all: xargs ${MAN}
|
||||
|
||||
xargs: ${OBJS}
|
||||
${CC} ${LDFLAGS} -o xargs.elf ${OBJS} ${LIBS}
|
||||
${OBJDUMP} -S xargs.elf > xargs.dis
|
||||
${SIZE} xargs.elf
|
||||
${ELF2AOUT} xargs.elf $@ && rm xargs.elf
|
||||
|
||||
${MAN}: ${MANSRC}
|
||||
${MANROFF} ${MANSRC} > ${MAN}
|
||||
|
||||
clean:
|
||||
rm -f *.o *.elf ${MAN} xargs *.elf *.dis tags *~
|
||||
|
||||
depend: ${SRCS}
|
||||
mkdep ${CFLAGS} ${SRCS}
|
||||
|
||||
install: all
|
||||
install xargs ${DESTDIR}/bin/
|
||||
cp xargs.0 ${DESTDIR}/share/man/cat1/
|
||||
|
||||
lint: ${SRCS}
|
||||
lint -hax ${SRCS}
|
||||
|
||||
tags: ${SRCS}
|
||||
ctags ${SRCS}
|
||||
169
src/cmd/xargs/xargs.1
Normal file
169
src/cmd/xargs/xargs.1
Normal file
@@ -0,0 +1,169 @@
|
||||
.\" Copyright (c) 1990, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" This code is derived from software contributed to Berkeley by
|
||||
.\" John B. Roll Jr. and the Institute of Electrical and Electronics
|
||||
.\" Engineers, Inc.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)xargs.1 8.1 (Berkeley) 6/6/93
|
||||
.\"
|
||||
.TH XARGS 1 "June 6, 1993"
|
||||
.SH NAME
|
||||
xargs \- construct argument list(s) and execute utility
|
||||
.SH SYNOPSIS
|
||||
.B xargs
|
||||
[
|
||||
.B \-t
|
||||
][[
|
||||
.B \-x
|
||||
]
|
||||
.B \-n
|
||||
.BI number
|
||||
][
|
||||
.B \-s
|
||||
.BI size
|
||||
][
|
||||
.BI utility
|
||||
[
|
||||
.BI arguments ...
|
||||
]]
|
||||
.PP
|
||||
.SH DESCRIPTION
|
||||
The
|
||||
.B xargs
|
||||
utility reads space, tab, newline and end-of-file delimited arguments
|
||||
from the standard input and executes the specified
|
||||
.BI utility
|
||||
with them as
|
||||
arguments.
|
||||
.PP
|
||||
The utility and any arguments specified on the command line are given
|
||||
to the
|
||||
.BI utility
|
||||
upon each invocation, followed by some number of the arguments read
|
||||
from standard input.
|
||||
The
|
||||
.BI utility
|
||||
is repeatedly executed until standard input is exhausted.
|
||||
.PP
|
||||
Spaces, tabs and newlines may be embedded in arguments using single
|
||||
(``\ '\ '')
|
||||
.EK
|
||||
or double (``"'') quotes or backslashes (``\e'').
|
||||
Single quotes escape all non-single quote characters, excluding newlines,
|
||||
up to the matching single quote.
|
||||
Double quotes escape all non-double quote characters, excluding newlines,
|
||||
up to the matching double quote.
|
||||
Any single character, including newlines, may be escaped by a backslash.
|
||||
.PP
|
||||
The options are as follows:
|
||||
.TP 10n
|
||||
.BR \-n " number"
|
||||
Set the maximum number of arguments taken from standard input for each
|
||||
invocation of the utility.
|
||||
An invocation of
|
||||
.BI utility
|
||||
will use less than
|
||||
.BI number
|
||||
standard input arguments if the number of bytes accumulated (see the
|
||||
.B s
|
||||
option) exceeds the specified
|
||||
.BI size
|
||||
or there are fewer than
|
||||
.BI number
|
||||
arguments remaining for the last invocation of
|
||||
.BI utility .
|
||||
The current default value for
|
||||
.BI number
|
||||
is 5000.
|
||||
.TP
|
||||
.BR \-s " size"
|
||||
Set the maximum number of bytes for the command line length provided to
|
||||
.BI utility .
|
||||
The sum of the length of the utility name and the arguments passed to
|
||||
.BI utility
|
||||
(including
|
||||
.I /dev/null
|
||||
terminators) will be less than or equal to this number.
|
||||
The current default value for
|
||||
.BI size
|
||||
is
|
||||
ARG_MAX
|
||||
- 2048.
|
||||
.TP
|
||||
.BR \-t
|
||||
Echo the command to be executed to standard error immediately before it
|
||||
is executed.
|
||||
.TP
|
||||
.BR \-x
|
||||
Force
|
||||
.B xargs
|
||||
to terminate immediately if a command line containing
|
||||
.BI number
|
||||
arguments will not fit in the specified (or default) command line length.
|
||||
.PP
|
||||
If no
|
||||
.BI utility
|
||||
is specified,
|
||||
echo(1)
|
||||
is used.
|
||||
.PP
|
||||
Undefined behavior may occur if
|
||||
.BI utility
|
||||
reads from the standard input.
|
||||
.PP
|
||||
The
|
||||
.B xargs
|
||||
utility exits immediately (without processing any further input) if a
|
||||
command line cannot be assembled,
|
||||
.BI 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
|
||||
The
|
||||
.B xargs
|
||||
utility exits with a value of 0 if no error occurs.
|
||||
If
|
||||
.BI utility
|
||||
cannot be invoked,
|
||||
.B xargs
|
||||
exits with a value of 127.
|
||||
If any other error occurs,
|
||||
.B xargs
|
||||
exits with a value of 1.
|
||||
.SH SEE ALSO
|
||||
echo(1), find(1)
|
||||
.PP
|
||||
.SH STANDARDS
|
||||
The
|
||||
.B xargs
|
||||
utility is expected to be
|
||||
IEEE Std 1003.2("POSIX") compliant.
|
||||
323
src/cmd/xargs/xargs.c
Normal file
323
src/cmd/xargs/xargs.c
Normal file
@@ -0,0 +1,323 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* John B. Roll Jr.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <paths.h>
|
||||
|
||||
#if __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is defined for pdp11s. ARG_MAX is usually defined in
|
||||
* an include file. I have left it here until such times as
|
||||
* the system limits stuff in machparam etc is changed to the
|
||||
* same names as 4.4. Note that
|
||||
* this is much smaller than the normal value cos it's only a
|
||||
* small computer (sigh).
|
||||
*/
|
||||
|
||||
#define ARG_MAX NCARGS
|
||||
|
||||
int tflag, rval;
|
||||
|
||||
void
|
||||
#if __STDC__
|
||||
fatal(const char *fmt, ...)
|
||||
#else
|
||||
fatal(fmt, va_alist)
|
||||
char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
#if __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
va_start(ap);
|
||||
#endif
|
||||
(void)fprintf(stderr, "xargs: ");
|
||||
(void)vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
(void)fprintf(stderr, "\n");
|
||||
exit(1);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
void
|
||||
run(argv)
|
||||
char **argv;
|
||||
{
|
||||
int noinvoke;
|
||||
register char **p;
|
||||
pid_t pid;
|
||||
int status;
|
||||
|
||||
if (tflag) {
|
||||
(void)fprintf(stderr, "%s", *argv);
|
||||
for (p = argv + 1; *p; ++p)
|
||||
(void)fprintf(stderr, " %s", *p);
|
||||
(void)fprintf(stderr, "\n");
|
||||
(void)fflush(stderr);
|
||||
}
|
||||
noinvoke = 0;
|
||||
switch(pid = vfork()) {
|
||||
case -1:
|
||||
fatal("vfork: %s", strerror(errno));
|
||||
case 0:
|
||||
execvp(argv[0], argv);
|
||||
(void)fprintf(stderr,
|
||||
"xargs: %s: %s\n", argv[0], strerror(errno));
|
||||
noinvoke = 1;
|
||||
_exit(1);
|
||||
}
|
||||
pid = waitpid(pid, &status, 0);
|
||||
if (pid == -1)
|
||||
fatal("waitpid: %s", strerror(errno));
|
||||
/* If we couldn't invoke the utility, exit 127. */
|
||||
if (noinvoke)
|
||||
exit(127);
|
||||
/* If utility signaled or exited with a value of 255, exit 1-125. */
|
||||
if (WIFSIGNALED(status) || WEXITSTATUS(status) == 255)
|
||||
exit(1);
|
||||
if (WEXITSTATUS(status))
|
||||
rval = 1;
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"usage: xargs [-t] [-n number [-x]] [-s size] [utility [argument ...]]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
register int ch;
|
||||
register char *p, *bbp, *ebp, **bxp, **exp, **xp;
|
||||
int cnt, indouble, insingle, nargs, nflag, nline, xflag;
|
||||
char **av, *argp;
|
||||
|
||||
/*
|
||||
* POSIX.2 limits the exec line length to ARG_MAX - 2K. Running that
|
||||
* caused some E2BIG errors, so it was changed to ARG_MAX - 4K. Given
|
||||
* that the smallest argument is 2 bytes in length, this means that
|
||||
* the number of arguments is limited to:
|
||||
*
|
||||
* (ARG_MAX - 4K - LENGTH(utility + arguments)) / 2.
|
||||
*
|
||||
* We arbitrarily limit the number of arguments to 5000. This is
|
||||
* allowed by POSIX.2 as long as the resulting minimum exec line is
|
||||
* at least LINE_MAX. Realloc'ing as necessary is possible, but
|
||||
* probably not worthwhile.
|
||||
*/
|
||||
nargs = 5000;
|
||||
nline = ARG_MAX - 4 * 1024;
|
||||
nflag = xflag = 0;
|
||||
while ((ch = getopt(argc, argv, "n:s:tx")) != EOF)
|
||||
switch(ch) {
|
||||
case 'n':
|
||||
nflag = 1;
|
||||
if ((nargs = atoi(optarg)) <= 0)
|
||||
fatal("illegal argument count");
|
||||
break;
|
||||
case 's':
|
||||
nline = atoi(optarg);
|
||||
break;
|
||||
case 't':
|
||||
tflag = 1;
|
||||
break;
|
||||
case 'x':
|
||||
xflag = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (xflag && !nflag)
|
||||
usage();
|
||||
|
||||
/*
|
||||
* Allocate pointers for the utility name, the utility arguments,
|
||||
* the maximum arguments to be read from stdin and the trailing
|
||||
* NULL.
|
||||
*/
|
||||
if (!(av = bxp =
|
||||
(char **)malloc((u_int)(1 + argc + nargs + 1) * sizeof(char **))))
|
||||
fatal("%s", strerror(errno));
|
||||
|
||||
/*
|
||||
* Use the user's name for the utility as argv[0], just like the
|
||||
* shell. Echo is the default. Set up pointers for the user's
|
||||
* arguments.
|
||||
*/
|
||||
if (!*argv)
|
||||
cnt = strlen(*bxp++ = _PATH_ECHO);
|
||||
else {
|
||||
cnt = 0;
|
||||
do {
|
||||
cnt += strlen(*bxp++ = *argv) + 1;
|
||||
} while (*++argv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up begin/end/traversing pointers into the array. The -n
|
||||
* count doesn't include the trailing NULL pointer, so the malloc
|
||||
* added in an extra slot.
|
||||
*/
|
||||
exp = (xp = bxp) + nargs;
|
||||
|
||||
/*
|
||||
* Allocate buffer space for the arguments read from stdin and the
|
||||
* trailing NULL. Buffer space is defined as the default or specified
|
||||
* space, minus the length of the utility name and arguments. Set up
|
||||
* begin/end/traversing pointers into the array. The -s count does
|
||||
* include the trailing NULL, so the malloc didn't add in an extra
|
||||
* slot.
|
||||
*/
|
||||
nline -= cnt;
|
||||
if (nline <= 0)
|
||||
fatal("insufficient space for command");
|
||||
|
||||
if (!(bbp = (char *)malloc((u_int)nline + 1)))
|
||||
fatal("%s", strerror(errno));
|
||||
ebp = (argp = p = bbp) + nline - 1;
|
||||
|
||||
for (insingle = indouble = 0;;) {
|
||||
switch(ch = getchar()) {
|
||||
case EOF:
|
||||
/* No arguments since last exec. */
|
||||
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':
|
||||
/* Quotes escape tabs and spaces. */
|
||||
if (insingle || indouble)
|
||||
goto addch;
|
||||
goto arg2;
|
||||
case '\n':
|
||||
/* Empty lines are skipped. */
|
||||
if (argp == p)
|
||||
continue;
|
||||
|
||||
/* Quotes do not escape newlines. */
|
||||
arg1: if (insingle || indouble)
|
||||
fatal("unterminated quote");
|
||||
|
||||
arg2: *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)
|
||||
fatal("insufficient space for arguments");
|
||||
*xp = NULL;
|
||||
run(av);
|
||||
if (ch == EOF)
|
||||
exit(rval);
|
||||
p = bbp;
|
||||
xp = bxp;
|
||||
} else
|
||||
++p;
|
||||
argp = p;
|
||||
break;
|
||||
case '\'':
|
||||
if (indouble)
|
||||
goto addch;
|
||||
insingle = !insingle;
|
||||
break;
|
||||
case '"':
|
||||
if (insingle)
|
||||
goto addch;
|
||||
indouble = !indouble;
|
||||
break;
|
||||
case '\\':
|
||||
/* Backslash escapes anything, is escaped by quotes. */
|
||||
if (!insingle && !indouble && (ch = getchar()) == EOF)
|
||||
fatal("backslash at EOF");
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
addch: if (p < ebp) {
|
||||
*p++ = ch;
|
||||
break;
|
||||
}
|
||||
|
||||
/* If only one argument, not enough buffer space. */
|
||||
if (bxp == xp)
|
||||
fatal("insufficient space for argument");
|
||||
/* Didn't hit argument limit, so if xflag object. */
|
||||
if (xflag)
|
||||
fatal("insufficient space for arguments");
|
||||
|
||||
*xp = NULL;
|
||||
run(av);
|
||||
xp = bxp;
|
||||
cnt = ebp - argp;
|
||||
bcopy(argp, bbp, cnt);
|
||||
p = (argp = bbp) + cnt;
|
||||
*p++ = ch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
Reference in New Issue
Block a user