about summary refs log tree commit diff
path: root/src/usr.bin/apply
diff options
context:
space:
mode:
authorChristian Neukirchen <chneukirchen@gmail.com>2014-07-30 18:25:14 +0200
committerChristian Neukirchen <chneukirchen@gmail.com>2014-07-31 16:00:16 +0200
commitd6872925c8b6b13b59a1ece32416aa8ef9c12c70 (patch)
treef9d4d6c4152241476dbd1eb3c8765908c065b147 /src/usr.bin/apply
downloadoutils-d6872925c8b6b13b59a1ece32416aa8ef9c12c70.tar.gz
outils-d6872925c8b6b13b59a1ece32416aa8ef9c12c70.tar.xz
outils-d6872925c8b6b13b59a1ece32416aa8ef9c12c70.zip
initial import of OpenBSD tools
Diffstat (limited to 'src/usr.bin/apply')
-rw-r--r--src/usr.bin/apply/Makefile5
-rw-r--r--src/usr.bin/apply/apply.1145
-rw-r--r--src/usr.bin/apply/apply.c245
3 files changed, 395 insertions, 0 deletions
diff --git a/src/usr.bin/apply/Makefile b/src/usr.bin/apply/Makefile
new file mode 100644
index 0000000..68ce192
--- /dev/null
+++ b/src/usr.bin/apply/Makefile
@@ -0,0 +1,5 @@
+#	$OpenBSD: Makefile,v 1.3 1997/09/21 11:48:16 deraadt Exp $
+
+PROG=	apply
+
+.include <bsd.prog.mk>
diff --git a/src/usr.bin/apply/apply.1 b/src/usr.bin/apply/apply.1
new file mode 100644
index 0000000..ddcc3e7
--- /dev/null
+++ b/src/usr.bin/apply/apply.1
@@ -0,0 +1,145 @@
+.\"	$OpenBSD: apply.1,v 1.23 2007/05/31 19:20:07 jmc Exp $
+.\"	$NetBSD: apply.1,v 1.4 1996/03/18 23:16:57 jtc Exp $
+.\"
+.\" Copyright (c) 1983, 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. 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.
+.\"
+.\"     @(#)apply.1	8.2 (Berkeley) 4/4/94
+.\"
+.Dd $Mdocdate: May 31 2007 $
+.Dt APPLY 1
+.Os
+.Sh NAME
+.Nm apply
+.Nd apply a command to a set of arguments
+.Sh SYNOPSIS
+.Nm apply
+.Op Fl Ar #
+.Op Fl d
+.Op Fl a Ar magic
+.Ar command argument ...
+.Sh DESCRIPTION
+.Nm
+runs the named
+.Ar command
+on each given
+.Ar argument
+in turn.
+.Pp
+Character sequences of the form
+.Dq Li \&%d
+in
+.Ar command ,
+where
+.Sq d
+is a digit from 1 to 9, are replaced by the
+.Li d Ns 'th
+following unused
+.Ar argument .
+In this case, the largest digit number of arguments are discarded for
+each execution of
+.Ar command .
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl Ns Ar #
+Normally arguments are taken singly; the optional number
+.Fl Ns Ar #
+specifies the number of arguments to be passed to
+.Ar command .
+If the number is zero,
+.Ar command
+is run, without arguments, once for each
+.Ar argument .
+.Pp
+If any sequences of
+.Dq Li \&%d
+occur in
+.Ar command ,
+the
+.Fl Ns Ar #
+option is ignored.
+.It Fl a Ar magic
+Use
+.Ar magic
+as the magic character instead of the default
+.Ql % .
+.It Fl d
+Debug mode.
+Print commands to the standard output but do not actually execute them.
+.El
+.Sh ENVIRONMENT
+.Bl -tag -width SHELL
+.It Ev SHELL
+Pathname of shell to use.
+If this variable is not defined, the Bourne shell is used.
+.El
+.Sh FILES
+.Bl -tag -width /bin/sh -compact
+.It Pa /bin/sh
+default shell
+.El
+.Sh EXAMPLES
+Operate similar to
+.Xr ls 1 :
+.Pp
+.Dl "$ apply echo *"
+.Pp
+Compare the
+.Pa a*
+files to the
+.Pa b*
+files:
+.Pp
+.Dl "$ apply -2 cmp a1 b1 a2 b2 a3 b3"
+.Pp
+Run
+.Xr who 1
+five times:
+.Pp
+.Dl "$ apply -0 who 1 2 3 4 5"
+.Pp
+Link all files in the current directory to the directory
+.Pa /home/joe :
+.Pp
+.Dl "$ apply 'ln %1 /home/joe'" *
+.Sh SEE ALSO
+.Xr sh 1 ,
+.Xr xargs 1
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
+.Sh AUTHORS
+Rob Pike
+.Sh BUGS
+Shell metacharacters in
+.Ar command
+may have bizarre effects; it is best to enclose complicated
+commands in single quotes
+.Pq '' .
diff --git a/src/usr.bin/apply/apply.c b/src/usr.bin/apply/apply.c
new file mode 100644
index 0000000..6218c6c
--- /dev/null
+++ b/src/usr.bin/apply/apply.c
@@ -0,0 +1,245 @@
+/*	$OpenBSD: apply.c,v 1.26 2013/11/25 18:03:17 deraadt Exp $	*/
+/*	$NetBSD: apply.c,v 1.3 1995/03/25 03:38:23 glass Exp $	*/
+
+/*-
+ * Copyright (c) 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry.
+ *
+ * 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. 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/wait.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <paths.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+__dead	void	usage(void);
+static	int	mysystem(const char *);
+
+int
+main(int argc, char *argv[])
+{
+	int ch, clen, debug, i, l, magic, n, nargs, rval;
+	char *c, *c2, *cmd, *p, *q;
+	size_t len;
+
+	debug = 0;
+	magic = '%';		/* Default magic char is `%'. */
+	nargs = -1;
+	while ((ch = getopt(argc, argv, "a:d0123456789")) != -1)
+		switch (ch) {
+		case 'a':
+			if (optarg[1] != '\0')
+				errx(1,
+				    "illegal magic character specification.");
+			magic = optarg[0];
+			break;
+		case 'd':
+			debug = 1;
+			break;
+		case '0': case '1': case '2': case '3': case '4':
+		case '5': case '6': case '7': case '8': case '9':
+			if (nargs != -1)
+				errx(1,
+				    "only one -# argument may be specified.");
+			nargs = ch - '0';
+			break;
+		default:
+			usage();
+		}
+	argc -= optind;
+	argv += optind;
+
+	if (argc < 2)
+		usage();
+
+	/*
+	 * The command to run is argv[0], and the args are argv[1..].
+	 * Look for %digit references in the command, remembering the
+	 * largest one.
+	 */
+	for (n = 0, p = argv[0]; *p != '\0'; ++p)
+		if (p[0] == magic &&
+		    isdigit((unsigned char)p[1]) && p[1] != '0') {
+			++p;
+			if (p[0] - '0' > n)
+				n = p[0] - '0';
+		}
+
+	/*
+	 * If there were any %digit references, then use those, otherwise
+	 * build a new command string with sufficient %digit references at
+	 * the end to consume (nargs) arguments each time round the loop.
+	 * Allocate enough space to hold the maximum command.
+	 */
+	if (n == 0) {
+		len = sizeof("exec ") - 1 +
+		    strlen(argv[0]) + 9 * (sizeof(" %1") - 1) + 1;
+		if ((cmd = malloc(len)) == NULL)
+			err(1, NULL);
+
+		/* If nargs not set, default to a single argument. */
+		if (nargs == -1)
+			nargs = 1;
+
+		l = snprintf(cmd, len, "exec %s", argv[0]);
+		if (l >= len || l == -1)
+			errx(1, "error building exec string");
+		len -= l;
+		p = cmd + l;
+		
+		for (i = 1; i <= nargs; i++) {
+			l = snprintf(p, len, " %c%d", magic, i);
+			if (l >= len || l == -1)
+				errx(1, "error numbering arguments");
+			len -= l;
+			p += l;
+		}
+
+		/*
+		 * If nargs set to the special value 0, eat a single
+		 * argument for each command execution.
+		 */
+		if (nargs == 0)
+			nargs = 1;
+	} else {
+		if (asprintf(&cmd, "exec %s", argv[0]) == -1)
+			err(1, NULL);		
+		nargs = n;
+	}
+
+	/*
+	 * Grab some space in which to build the command.  Allocate
+	 * as necessary later, but no reason to build it up slowly
+	 * for the normal case.
+	 */
+	if ((c = malloc(clen = 1024)) == NULL)
+		err(1, NULL);
+
+	/*
+	 * (argc) and (argv) are still offset by one to make it simpler to
+	 * expand %digit references.  At the end of the loop check for (argc)
+	 * equals 1 means that all the (argv) has been consumed.
+	 */
+	for (rval = 0; argc > nargs; argc -= nargs, argv += nargs) {
+		/*
+		 * Find a max value for the command length, and ensure
+		 * there's enough space to build it.
+		 */
+		for (l = strlen(cmd), i = 0; i < nargs; i++)
+			l += strlen(argv[i+1]);
+		if (l > clen) {
+			if ((c2 = realloc(c, l)) == NULL)
+				err(1, NULL);
+			c = c2;
+			clen = l;
+		}
+
+		/* Expand command argv references. */
+		for (p = cmd, q = c; *p != '\0'; ++p)
+			if (p[0] == magic &&
+			    isdigit((unsigned char)p[1]) && p[1] != '0') {
+				strlcpy(q, argv[(++p)[0] - '0'], c + clen - q);
+				q += strlen(q);
+			} else
+				*q++ = *p;
+
+		/* Terminate the command string. */
+		*q = '\0';
+
+		/* Run the command. */
+		if (debug)
+			(void)printf("%s\n", c);
+		else if (mysystem(c))
+			rval = 1;
+	}
+
+	if (argc != 1)
+		errx(1, "expecting additional argument%s after \"%s\"",
+		    (nargs - argc) ? "s" : "", argv[argc - 1]);
+	exit(rval);
+}
+
+/*
+ * mysystem --
+ * 	Private version of system(3).  Use the user's SHELL environment
+ *	variable as the shell to execute.
+ */
+static int
+mysystem(const char *command)
+{
+	static const char *name, *shell;
+	pid_t pid;
+	int pstat;
+	sigset_t mask, omask;
+	sig_t intsave, quitsave;
+
+	if (shell == NULL) {
+		if ((shell = getenv("SHELL")) == NULL)
+			shell = _PATH_BSHELL;
+		if ((name = strrchr(shell, '/')) == NULL)
+			name = shell;
+		else
+			++name;
+	}
+	if (!command)		/* just checking... */
+		return(1);
+
+	sigemptyset(&mask);
+	sigaddset(&mask, SIGCHLD);
+	sigprocmask(SIG_BLOCK, &mask, &omask);
+	switch(pid = fork()) {
+	case -1:			/* error */
+		err(1, "fork");
+	case 0:				/* child */
+		sigprocmask(SIG_SETMASK, &omask, NULL);
+		execl(shell, name, "-c", command, (char *)NULL);
+		err(1, "%s", shell);
+	}
+	intsave = signal(SIGINT, SIG_IGN);
+	quitsave = signal(SIGQUIT, SIG_IGN);
+	pid = waitpid(pid, &pstat, 0);
+	sigprocmask(SIG_SETMASK, &omask, NULL);
+	(void)signal(SIGINT, intsave);
+	(void)signal(SIGQUIT, quitsave);
+	return(pid == -1 ? -1 : pstat);
+}
+
+__dead void
+usage(void)
+{
+	(void)fprintf(stderr,
+	    "usage: apply [-#] [-d] [-a magic] command argument ...\n");
+	exit(1);
+}