summaryrefslogtreecommitdiff
path: root/src/rm.c
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2006-02-20 12:48:11 +0000
committerJim Meyering <jim@meyering.net>2006-02-20 12:48:11 +0000
commit1a301edfc791c80e30bfcc876d75a401468da819 (patch)
tree4b432ba1512a7c731ba94c5878fee9522195d449 /src/rm.c
parentda3340fab1c5f29f163e71411608aa398ff0c13f (diff)
downloadcoreutils-1a301edfc791c80e30bfcc876d75a401468da819.tar.xz
(INTERACTIVE_OPTION): New enum value.
(interactive_type): New enum. (long_opts): Let interactive take an optional argument. (interactive_args, interactive_types): New option arguments. (usage): Document -I, --interactive=WHEN. Use program_name instead of a basename. (main): New -I option, new behavior to --interactive. [From Eric Blake]
Diffstat (limited to 'src/rm.c')
-rw-r--r--src/rm.c91
1 files changed, 85 insertions, 6 deletions
diff --git a/src/rm.c b/src/rm.c
index 6411b70ef..4ba63c0e6 100644
--- a/src/rm.c
+++ b/src/rm.c
@@ -49,6 +49,7 @@
#include <assert.h>
#include "system.h"
+#include "argmatch.h"
#include "dirname.h"
#include "error.h"
#include "lstat.h"
@@ -56,6 +57,7 @@
#include "quotearg.h"
#include "remove.h"
#include "root-dev-ino.h"
+#include "yesno.h"
/* The official name of this program (e.g., no `g' prefix). */
#define PROGRAM_NAME "rm"
@@ -70,16 +72,24 @@ char *program_name;
non-character as a pseudo short option, starting with CHAR_MAX + 1. */
enum
{
- NO_PRESERVE_ROOT = CHAR_MAX + 1,
+ INTERACTIVE_OPTION = CHAR_MAX + 1,
+ NO_PRESERVE_ROOT,
PRESERVE_ROOT,
PRESUME_INPUT_TTY_OPTION
};
+enum interactive_type
+ {
+ interactive_never, /* 0: no option or --interactive=never */
+ interactive_once, /* 1: -I or --interactive=once */
+ interactive_always /* 2: default, -i or --interactive=always */
+ };
+
static struct option const long_opts[] =
{
{"directory", no_argument, NULL, 'd'},
{"force", no_argument, NULL, 'f'},
- {"interactive", no_argument, NULL, 'i'},
+ {"interactive", optional_argument, NULL, INTERACTIVE_OPTION},
{"no-preserve-root", no_argument, NULL, NO_PRESERVE_ROOT},
{"preserve-root", no_argument, NULL, PRESERVE_ROOT},
@@ -97,6 +107,20 @@ static struct option const long_opts[] =
{NULL, 0, NULL, 0}
};
+static char const *const interactive_args[] =
+{
+ "never", "no", "none",
+ "once",
+ "always", "yes", NULL
+};
+static enum interactive_type const interactive_types[] =
+{
+ interactive_never, interactive_never, interactive_never,
+ interactive_once,
+ interactive_always, interactive_always
+};
+ARGMATCH_VERIFY (interactive_args, interactive_types);
+
/* Advise the user about invalid usages like "rm -foo" if the file
"-foo" exists, assuming ARGC and ARGV are as with `main'. */
@@ -132,13 +156,19 @@ usage (int status)
program_name);
else
{
- char *base = base_name (program_name);
printf (_("Usage: %s [OPTION]... FILE...\n"), program_name);
fputs (_("\
Remove (unlink) the FILE(s).\n\
\n\
-f, --force ignore nonexistent files, never prompt\n\
- -i, --interactive prompt before any removal\n\
+ -i prompt before every removal\n\
+"), stdout);
+ fputs (_("\
+ -I prompt once before removing more than three files, or\n\
+ when removing recursively. Less intrusive than -i,\n\
+ while still giving protection against most mistakes\n\
+ --interactive[=WHEN] prompt according to WHEN: never, once (-I), or\n\
+ always (-i). Without WHEN, prompt always\n\
"), stdout);
fputs (_("\
--no-preserve-root do not treat `/' specially (the default)\n\
@@ -161,7 +191,7 @@ use one of these commands:\n\
\n\
%s ./-foo\n\
"),
- base, base);
+ program_name, program_name);
fputs (_("\
\n\
Note that if you use rm to remove a file, it is usually possible to recover\n\
@@ -193,6 +223,7 @@ main (int argc, char **argv)
{
bool preserve_root = false;
struct rm_options x;
+ bool prompt_once = false;
int c;
initialize_main (&argc, &argv);
@@ -205,7 +236,7 @@ main (int argc, char **argv)
rm_option_init (&x);
- while ((c = getopt_long (argc, argv, "dfirvR", long_opts, NULL)) != -1)
+ while ((c = getopt_long (argc, argv, "dfirvIR", long_opts, NULL)) != -1)
{
switch (c)
{
@@ -219,11 +250,19 @@ main (int argc, char **argv)
case 'f':
x.interactive = false;
x.ignore_missing_files = true;
+ prompt_once = false;
break;
case 'i':
x.interactive = true;
x.ignore_missing_files = false;
+ prompt_once = false;
+ break;
+
+ case 'I':
+ x.interactive = false;
+ x.ignore_missing_files = false;
+ prompt_once = true;
break;
case 'r':
@@ -231,6 +270,36 @@ main (int argc, char **argv)
x.recursive = true;
break;
+ case INTERACTIVE_OPTION:
+ {
+ int i;
+ if (optarg)
+ i = XARGMATCH ("--interactive", optarg, interactive_args,
+ interactive_types);
+ else
+ i = interactive_always;
+ switch (i)
+ {
+ case interactive_never:
+ x.interactive = false;
+ prompt_once = false;
+ break;
+
+ case interactive_once:
+ x.interactive = false;
+ x.ignore_missing_files = false;
+ prompt_once = true;
+ break;
+
+ case interactive_always:
+ x.interactive = true;
+ x.ignore_missing_files = false;
+ prompt_once = false;
+ break;
+ }
+ break;
+ }
+
case NO_PRESERVE_ROOT:
preserve_root = false;
break;
@@ -279,6 +348,16 @@ main (int argc, char **argv)
size_t n_files = argc - optind;
char const *const *file = (char const *const *) argv + optind;
+ if (prompt_once && (x.recursive || 3 < n_files))
+ {
+ fprintf (stderr,
+ (x.recursive
+ ? _("%s: remove all arguments recursively? ")
+ : _("%s: remove all arguments? ")),
+ program_name);
+ if (!yesno ())
+ exit (EXIT_SUCCESS);
+ }
enum RM_status status = rm (n_files, file, &x);
assert (VALID_STATUS (status));
exit (status == RM_ERROR ? EXIT_FAILURE : EXIT_SUCCESS);