summaryrefslogtreecommitdiffstats
path: root/usr.bin/xargs
diff options
context:
space:
mode:
authorjmallett <jmallett@FreeBSD.org>2002-05-05 06:42:44 +0000
committerjmallett <jmallett@FreeBSD.org>2002-05-05 06:42:44 +0000
commite6d711b45aaff94c6116189ffc64a692ef2e1f0d (patch)
treebf58852562149a008e8a638271e9a0f4feefb925 /usr.bin/xargs
parent7e1b68b6e0ebd9125f75b4f5f6c9367c93f1a0be (diff)
downloadFreeBSD-src-e6d711b45aaff94c6116189ffc64a692ef2e1f0d.zip
FreeBSD-src-e6d711b45aaff94c6116189ffc64a692ef2e1f0d.tar.gz
Modify the -p implementation to use a user's locale, so they can respond to
the prompt in their native language. Also make the prompt fit what POSIX asks for (?...). This should not affect use of -p with yes(1) [as every locale I know of matches 'y' as YESEXPR as well], but that's what -t is for anyway. -p is meant to be really used interactively. Submitted by: tjr, jmallett
Diffstat (limited to 'usr.bin/xargs')
-rw-r--r--usr.bin/xargs/xargs.14
-rw-r--r--usr.bin/xargs/xargs.c72
2 files changed, 63 insertions, 13 deletions
diff --git a/usr.bin/xargs/xargs.1 b/usr.bin/xargs/xargs.1
index d846b48..e33dc6a 100644
--- a/usr.bin/xargs/xargs.1
+++ b/usr.bin/xargs/xargs.1
@@ -194,10 +194,12 @@ is 5000.
.It Fl p
Echo each command to be executed and ask the user whether it should be
executed.
-A response of
+An affirmative response,
.Ql y
+in the POSIX locale,
causes the command to be executed, any other response causes it to be
skipped.
+No commands are executed if the process is not attached to a terminal.
.It Fl R Ar replacements
This option specifies the maximum number of arguments that
.Fl I
diff --git a/usr.bin/xargs/xargs.c b/usr.bin/xargs/xargs.c
index 06c8736..8c4d11a 100644
--- a/usr.bin/xargs/xargs.c
+++ b/usr.bin/xargs/xargs.c
@@ -56,6 +56,10 @@ __FBSDID("$FreeBSD$");
#include <err.h>
#include <errno.h>
+#include <langinfo.h>
+#include <locale.h>
+#include <paths.h>
+#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -65,6 +69,7 @@ __FBSDID("$FreeBSD$");
static void parse_input(int, char **);
static void prerun(int, char **);
+static int prompt(void);
static void run(char **);
static void usage(void);
void strnsubst(char **, const char *, const char *, size_t);
@@ -90,6 +95,8 @@ main(int argc, char **argv)
eofstr = "";
Jflag = nflag = 0;
+ (void)setlocale(LC_MESSAGES, "");
+
/*
* 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
@@ -454,26 +461,40 @@ run(char **argv)
{
volatile int childerr;
char **avec;
- FILE *ttyfp;
pid_t pid;
- int ch, status;
+ int status;
+ /*
+ * If the user wants to be notified of each command before it is
+ * executed, notify them. If they want the notification to be
+ * followed by a prompt, then prompt them.
+ */
if (tflag || pflag) {
(void)fprintf(stderr, "%s", *argv);
for (avec = argv + 1; *avec != NULL; ++avec)
(void)fprintf(stderr, " %s", *avec);
- if (pflag && (ttyfp = fopen("/dev/tty", "r")) != NULL) {
- (void)fprintf(stderr, "?");
- (void)fflush(stderr);
- ch = getc(ttyfp);
- fclose(ttyfp);
- if (ch != 'y')
+ /*
+ * If the user has asked to be prompted, do so.
+ */
+ if (pflag)
+ /*
+ * If they asked not to exec, return without execution
+ * but if they asked to, go to the execution. If we
+ * could not open their tty, break the switch and drop
+ * back to -t behaviour.
+ */
+ switch (prompt()) {
+ case 0:
return;
- } else {
- (void)fprintf(stderr, "\n");
- (void)fflush(stderr);
- }
+ case 1:
+ goto exec;
+ case 2:
+ break;
+ }
+ (void)fprintf(stderr, "\n");
+ (void)fflush(stderr);
}
+exec:
childerr = 0;
switch(pid = vfork()) {
case -1:
@@ -496,6 +517,33 @@ run(char **argv)
rval = 1;
}
+/*
+ * Prompt the user about running a command.
+ */
+static int
+prompt(void)
+{
+ regex_t cre;
+ size_t rsize;
+ int match;
+ char *response;
+ FILE *ttyfp;
+
+ if ((ttyfp = fopen(_PATH_TTY, "r")) == NULL)
+ return (2); /* Indicate that the TTY failed to open. */
+ (void)fprintf(stderr, "?...");
+ (void)fflush(stderr);
+ if ((response = fgetln(ttyfp, &rsize)) == NULL ||
+ regcomp(&cre, nl_langinfo(YESEXPR), REG_BASIC) != 0) {
+ (void)fclose(ttyfp);
+ return (0);
+ }
+ match = regexec(&cre, response, 0, NULL, 0);
+ (void)fclose(ttyfp);
+ regfree(&cre);
+ return (match == 0);
+}
+
static void
usage(void)
{
OpenPOWER on IntegriCloud