diff options
author | rgrimes <rgrimes@FreeBSD.org> | 1994-05-27 12:33:43 +0000 |
---|---|---|
committer | rgrimes <rgrimes@FreeBSD.org> | 1994-05-27 12:33:43 +0000 |
commit | f9ab90d9d6d02989a075d0f0074496d5b1045e4b (patch) | |
tree | add7e996bac5289cdc55e6935750c352505560a9 /usr.bin/xargs | |
parent | be22b15ae2ff8d7fe06b6e14fddf0c5b444a95da (diff) | |
download | FreeBSD-src-f9ab90d9d6d02989a075d0f0074496d5b1045e4b.zip FreeBSD-src-f9ab90d9d6d02989a075d0f0074496d5b1045e4b.tar.gz |
BSD 4.4 Lite Usr.bin Sources
Diffstat (limited to 'usr.bin/xargs')
-rw-r--r-- | usr.bin/xargs/Makefile | 5 | ||||
-rw-r--r-- | usr.bin/xargs/pathnames.h | 36 | ||||
-rw-r--r-- | usr.bin/xargs/xargs.1 | 161 | ||||
-rw-r--r-- | usr.bin/xargs/xargs.c | 325 |
4 files changed, 527 insertions, 0 deletions
diff --git a/usr.bin/xargs/Makefile b/usr.bin/xargs/Makefile new file mode 100644 index 0000000..0bfb074 --- /dev/null +++ b/usr.bin/xargs/Makefile @@ -0,0 +1,5 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= xargs + +.include <bsd.prog.mk> diff --git a/usr.bin/xargs/pathnames.h b/usr.bin/xargs/pathnames.h new file mode 100644 index 0000000..3f05b3d --- /dev/null +++ b/usr.bin/xargs/pathnames.h @@ -0,0 +1,36 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * 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. + * + * @(#)pathnames.h 8.1 (Berkeley) 6/6/93 + */ + +#define _PATH_ECHO "/bin/echo" diff --git a/usr.bin/xargs/xargs.1 b/usr.bin/xargs/xargs.1 new file mode 100644 index 0000000..e703c43 --- /dev/null +++ b/usr.bin/xargs/xargs.1 @@ -0,0 +1,161 @@ +.\" 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 +.\" +.Dd June 6, 1993 +.Dt XARGS 1 +.Os +.Sh NAME +.Nm xargs +.Nd "construct argument list(s) and execute utility" +.Sh SYNOPSIS +.Nm xargs +.Op Fl t +.Oo Op Fl x +.Fl n Ar number +.Oc +.Op Fl s Ar size +.Op Ar utility Op Ar arguments ... +.Sh DESCRIPTION +The +.Nm xargs +utility reads space, tab, newline and end-of-file delimited arguments +from the standard input and executes the specified +.Ar utility +with them as +arguments. +.Pp +The utility and any arguments specified on the command line are given +to the +.Ar utility +upon each invocation, followed by some number of the arguments read +from standard input. +The +.Ar 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: +.Bl -tag -width indent +.It Fl n Ar number +Set the maximum number of arguments taken from standard input for each +invocation of the utility. +An invocation of +.Ar utility +will use less than +.Ar number +standard input arguments if the number of bytes accumulated (see the +.Fl s +option) exceeds the specified +.Ar size +or there are fewer than +.Ar number +arguments remaining for the last invocation of +.Ar utility . +The current default value for +.Ar number +is 5000. +.It Fl s Ar size +Set the maximum number of bytes for the command line length provided to +.Ar utility . +The sum of the length of the utility name and the arguments passed to +.Ar utility +(including +.Dv NULL +terminators) will be less than or equal to this number. +The current default value for +.Ar size +is +.Dv ARG_MAX +- 2048. +.It Fl t +Echo the command to be executed to standard error immediately before it +is executed. +.It Fl x +Force +.Nm xargs +to terminate immediately if a command line containing +.Ar number +arguments will not fit in the specified (or default) command line length. +.El +.Pp +If no +.Ar utility +is specified, +.Xr echo 1 +is used. +.Pp +Undefined behavior may occur if +.Ar utility +reads from the standard input. +.Pp +The +.Nm xargs +utility exits immediately (without processing any further input) if a +command line cannot be assembled, +.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 +The +.Nm xargs +utility exits with a value of 0 if no error occurs. +If +.Ar utility +cannot be invoked, +.Nm xargs +exits with a value of 127. +If any other error occurs, +.Nm xargs +exits with a value of 1. +.Sh SEE ALSO +.Xr echo 1 , +.Xr find 1 +.Sh STANDARDS +The +.Nm xargs +utility is expected to be +.St -p1003.2 +compliant. diff --git a/usr.bin/xargs/xargs.c b/usr.bin/xargs/xargs.c new file mode 100644 index 0000000..e28e840 --- /dev/null +++ b/usr.bin/xargs/xargs.c @@ -0,0 +1,325 @@ +/*- + * 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. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1990, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)xargs.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include <sys/types.h> +#include <sys/wait.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <limits.h> +#include "pathnames.h" + +int tflag, rval; + +void err __P((const char *, ...)); +void run __P((char **)); +void usage __P((void)); + +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) + err("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 = + malloc((u_int)(1 + argc + nargs + 1) * sizeof(char **)))) + err("%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) + err("insufficient space for command"); + + if (!(bbp = malloc((u_int)nline + 1))) + err("%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) + err("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) + err("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) + err("backslash at EOF"); + /* FALLTHROUGH */ + default: +addch: if (p < ebp) { + *p++ = ch; + break; + } + + /* If only one argument, not enough buffer space. */ + if (bxp == xp) + err("insufficient space for argument"); + /* Didn't hit argument limit, so if xflag object. */ + if (xflag) + err("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 */ +} + +void +run(argv) + char **argv; +{ + volatile 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: + err("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) + err("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); +} + +#if __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +void +#if __STDC__ +err(const char *fmt, ...) +#else +err(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 */ +} |