aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2012-12-07 14:57:32 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2012-12-07 15:16:14 +0200
commit5a7b73860974384d8e00065105435403b0842ab0 (patch)
tree3f029c22f0a29a842002279bb4b5561af61a8aa8
parentc12cd5695cf1a6c2c44100a68762ab66356f43b8 (diff)
downloadeclat-5a7b73860974384d8e00065105435403b0842ab0.tar.gz
eclat-5a7b73860974384d8e00065105435403b0842ab0.tar.bz2
Re-implement confirmation support.
* doc/eclat-delete-volume.1: Update. * doc/eclat-release-address.1: Update. * doc/eclat.1: Update. * doc/eclat.conf.5: New section "CONFIRMATION" * lib/getyn.c (eclat_vgetyn): Negative default stands for no default at all. * lib/confirm.c (eclat_confirm_mode): Remove. (eclat_confirm): Change signature. Act according to the first argument. * lib/libeclat.h (eclat_confirm_mode): New enum. (eclat_confirm): Change signature. * src/cmdline.opt: Change handling of -Y and -N options. * src/config.c: New statement "confirm". * src/cretags.c: Remove call to eclat_confirm. This is done by the caller. * src/delvol.c: Likewise. * src/reladdr.c: Likewise. * src/eclat.c (confirm_mode): New variable. (command) <flags>: New member. (cmdtab): Mark commands with appropriate flags. (main): Call eclat_confirm to confirm the command. * src/eclat.h (confirm_mode): New extern. (set_command_confirmation): New proto. * etc/eclat.cfin: Set a reasonably safe confirmation default. * lib/forlan.c (strtots): Remove unused variable.
-rw-r--r--doc/eclat-delete-volume.114
-rw-r--r--doc/eclat-release-address.115
-rw-r--r--doc/eclat.134
-rw-r--r--doc/eclat.conf.588
-rw-r--r--etc/eclat.cfin3
-rw-r--r--lib/confirm.c28
-rw-r--r--lib/forlan.c1
-rw-r--r--lib/getyn.c14
-rw-r--r--lib/libeclat.h12
-rw-r--r--src/cmdline.opt4
-rw-r--r--src/config.c74
-rw-r--r--src/cretags.c1
-rw-r--r--src/delvol.c2
-rw-r--r--src/eclat.c66
-rw-r--r--src/eclat.h4
-rw-r--r--src/reladdr.c3
16 files changed, 286 insertions, 77 deletions
diff --git a/doc/eclat-delete-volume.1 b/doc/eclat-delete-volume.1
index a9d7489..f467d91 100644
--- a/doc/eclat-delete-volume.1
+++ b/doc/eclat-delete-volume.1
@@ -29,20 +29,6 @@ in
.BR eclat (1)),
this command treats the \fBVOL\-ID\fR as volume names and translates
it to the AWS IDs using the \fBVolumeId\fR map.
-.PP
-Since this operation is destructive and may result in a loss of data
-if used carelessly,
-.B eclat
-will ask you for confirmation before actually deleting the volume.
-You can disable this feature by using the \fB\-Y\fR (\fB\-\-yes\fR)
-eclat option, e.g.:
-.nf
-.sp 2
-$ \fBeclat -Y delete-volume vol-d1234aef
-.fi
-.PP
-The use of one of this option is mandatory if this command is invoked
-from a shell script.
.SH "SEE ALSO"
.BR eclat (1),
.BR eclat\-create\-volume (1),
diff --git a/doc/eclat-release-address.1 b/doc/eclat-release-address.1
index 9ecefa5..b34b113 100644
--- a/doc/eclat-release-address.1
+++ b/doc/eclat-release-address.1
@@ -21,17 +21,10 @@ eclat release\-address [\fB\-\-vpc\fR] [\fB\-v\fR] IP\-OR\-ALLOCID
eclat release\-address \fB\-\-help\fR
.SH DESCRIPTION
-This command releases IP address. This is a destructive operation,
-beacause normally the released IP address cannot be recovered for your
-account. Therefore, before actually doing this,
-.B eclat
-will ask you for confirmation interactively. You can disable this by
-using the \fB\-Y\fR (\fB\-\-yes\fR) or \fB\-N\fR (\fB\-\-no\fR)
-option, for positive and negative answer, correspondingly.
-.PP
-The use of one of this options is mandatory if
-.B eclat
-is started from a shell script.
+This command releases an Elastic IP address. The address must have been
+previously allocated using the
+.B allocate-address
+command.
.SH OPTIONS
.TP
\fB\-v\fR, \fB\-\-vpc\fR
diff --git a/doc/eclat.1 b/doc/eclat.1
index 3b8a9ed..9fdabd0 100644
--- a/doc/eclat.1
+++ b/doc/eclat.1
@@ -13,7 +13,7 @@
.\"
.\" You should have received a copy of the GNU General Public License
.\" along with Eclat. If not, see <http://www.gnu.org/licenses/>.
-.TH ECLAT 1 "December 6, 2012" "ECLAT" "Eclat User Reference"
+.TH ECLAT 1 "December 7, 2012" "ECLAT" "Eclat User Reference"
.SH NAME
eclat \- EC2 Command Line Administrator Tool
.SH SYNOPSIS
@@ -322,13 +322,15 @@ Set AWS region name.
.SS Modifiers
.TP
\fB\-N\fR, \fB\-\-no\fR
-Some potentially dangerous and unrecoverable operations (such as
-.BR release-address )
-require confirmation. If started from the command line,
-.B eclat
-will ask for confirmation interactively. This option disables this
-behavior and instructs the program to assume negative answer to all
-confirmations. See also \fB\-Y\fR option below.
+.B Eclat
+can be configured to ask for confirmation before running
+a potentially dangerous and unrecoverable operation (see the
+section
+.B CONFIRMATION
+in
+.BR eclat.conf (5)).
+This option overrides this setting, assuming negative answer.
+See also \fB\-Y\fR option below.
.TP
\fB\-s\fR, \fB\-\-sort\fR
Sort the returned XML teee prior to outputting it.
@@ -337,13 +339,15 @@ Sort the returned XML teee prior to outputting it.
Use SSL (HTTPS) connection
.TP
\fB\-Y\fR, \fB\-\-yes\fR
-Some potentially dangerous and unrecoverable operations (such as
-.BR release-address )
-require confirmation. If started from the command line,
-.B eclat
-will ask for confirmation interactively. This option disables this
-behavior and instructs the program to assume positive answer to all
-confirmations. See also \fB\-N\fR option above.
+.B Eclat
+can be configured to ask for confirmation before running
+a potentially dangerous and unrecoverable operation (see the
+section
+.B CONFIRMATION
+in
+.BR eclat.conf (5)).
+This option overrides this setting, assuming positive answer.
+See also \fB\-N\fR option above.
.SS Mapping
.TP
\fB\-M\fR, \fB\-\-map\fR=\fIMAPNAME\fR
diff --git a/doc/eclat.conf.5 b/doc/eclat.conf.5
index 2a14e2e..d7599b7 100644
--- a/doc/eclat.conf.5
+++ b/doc/eclat.conf.5
@@ -13,7 +13,7 @@
.\"
.\" You should have received a copy of the GNU General Public License
.\" along with Eclat. If not, see <http://www.gnu.org/licenses/>.
-.TH ECLAT.CONF 5 "October 16, 2012" "ECLAT" "Eclat User Reference"
+.TH ECLAT.CONF 5 "December 7, 2012" "ECLAT" "Eclat User Reference"
.SH NAME
eclat.conf \- configuration file for
.BR eclat (1).
@@ -533,6 +533,92 @@ expansion.
.IP \n+[step].
If the format cannot determined by the above steps, an error is reported
and the program terminates.
+.SH CONFIRMATION
+Many
+.B eclat
+commands result in modification of your EC2 resources. Some of them
+are destructive, in the sense that such modifications cannot be undone
+(e.g. deleting of a volume or termination of an instance). To reduce
+the possibility of careless usage,
+.B eclat
+can be configured to interactively ask for a confirmation when such a
+command is requested. This is configured by the
+.B confirm
+statement:
+.PP
+.nf
+.in +2
+\fBconfirm\fR \fImode\fR \fBcommand\fR;
+\fBconfirm\fR \fImode\fR (\fBcommand\fR[, \fBcommand\fR...]);
+\fBconfirm\fR \fImode\fR \fIclass\fR;
+.fi
+.PP
+The \fImode\fR argument specifies the requested confirmation mode.
+Its valid values are:
+.TP
+.B tty
+Ask for confirmation if the controlling terminal is a tty, i.e. if
+.B eclat
+is started from the command line.
+.TP
+.B always
+Always ask for confirmation. If the controlling terminal is not a
+tty, abort the command.
+.TP
+.B positive
+Never ask. Assume positive confirmation. This is the default.
+.TP
+.B negative
+Never ask, assuming negative confirmation.
+.PP
+The second argument specifies the commands to which this mode is
+applied. It can be a single command name or tag, a comma-separated
+list of command names or tags, or a \fBclass\fR of commands. Valid
+values for \fIclass\fR are:
+.TP
+.B all
+All commands that modify EC2 resources.
+.TP
+.B destructive
+Commands that destructively modify resources.
+.PP
+Consider the following example:
+.PP
+.nf
+.in +2
+confirm tty destructive;
+confirm tty (StopInstance, StartInstance);
+.fi
+.PP
+It instructs
+.B eclat
+to ask for confirmation if one of the destructive commands is
+requested, or if the command is start-instance or stop-instance.
+.PP
+Here is an example of how this modifies the behavior of
+.B release-address
+command:
+.PP
+.nf
+.if +2
+$ \fBeclat release-address 192.168.0.1\fR
+Proceed with release-address [Y/n] _
+.fi
+.PP
+If the response begins with \fBY\fR (case-insensitive), it is taken
+for a positive answer, and the command will be executed. Otherwise,
+.B eclat
+exits returning code 16 to the shell.
+.PP
+The current confirmation setting can be overridden using the \fB\-Y\fR
+(\fB\-\-yes\fR) or \fB\-N\fR (\fB\-\-no\fR) command line option. The
+former forces \fBpositive\fN and the latter \fBnegative\fR
+confirmation mode for the requested command, e.g.:
+.PP
+.nf
+.in +2
+$ \fBeclat -Y delete-volume vol-d1234aef\fR
+.fi
.SH MAPS
Maps provide a way to translate arbitrary symbolic names to the Amazon
resource identifiers. See the section
diff --git a/etc/eclat.cfin b/etc/eclat.cfin
index 006f6d9..755187a 100644
--- a/etc/eclat.cfin
+++ b/etc/eclat.cfin
@@ -28,5 +28,6 @@ region sa-east-1 ec2.sa-east-1.amazonaws.com;
format-file "FORMATDIR/FORMATNAME.forlan";
-
+# Ask for confirmation before running a destructive command.
+confirm tty destructive;
diff --git a/lib/confirm.c b/lib/confirm.c
index bd283a1..18eb409 100644
--- a/lib/confirm.c
+++ b/lib/confirm.c
@@ -17,22 +17,32 @@
#include "libeclat.h"
#include <sysexits.h>
-int eclat_confirm_mode = -1;
-
int
-eclat_confirm(const char *prompt, ...)
+eclat_confirm(enum eclat_confirm_mode mode, const char *prompt, ...)
{
int rc;
va_list ap;
-
- if (!isatty(0) || eclat_confirm_mode >= 0) {
- if (eclat_confirm_mode == -1)
- die(EX_USAGE, "stdin not a terminal and no default response provided; use -Y or -N option to override");
- return eclat_confirm_mode;
+
+ switch (mode) {
+ case eclat_confirm_unspecified:
+ case eclat_confirm_positive:
+ return 1;
+ case eclat_confirm_negative:
+ return 0;
+ case eclat_confirm_tty:
+ if (!isatty(0))
+ return 1;
+ break;
+ case eclat_confirm_always:
+ if (!isatty(0))
+ die(EX_USAGE,
+ "confirmation required, "
+ "but stdin is not a terminal");
+ break;
}
va_start(ap, prompt);
- rc = eclat_vgetyn(!!eclat_confirm_mode, prompt, ap);
+ rc = eclat_vgetyn(-1, prompt, ap);
va_end(ap);
return rc;
diff --git a/lib/forlan.c b/lib/forlan.c
index 7a9dab1..828fb09 100644
--- a/lib/forlan.c
+++ b/lib/forlan.c
@@ -58,7 +58,6 @@ static unsigned long
strtots(const char *input)
{
struct tm tm;
- time_t t;
/* 2012-06-21T10:36:48.000Z */
memset(&tm, 0, sizeof(tm));
diff --git a/lib/getyn.c b/lib/getyn.c
index 8ec8a07..ee49d3f 100644
--- a/lib/getyn.c
+++ b/lib/getyn.c
@@ -21,10 +21,14 @@
int
eclat_vgetyn(int dfl, const char *prompt, va_list ap)
{
- static char *hint[] = { "y/N", "Y/n" };
+ static char *hint[] = { "y/n", "y/N", "Y/n" };
int state = 0;
int c, resp;
-
+
+ if (dfl < -1)
+ dfl = -1;
+ else if (dfl > 1)
+ dfl = 1;
do {
switch (state) {
case 1:
@@ -43,7 +47,9 @@ eclat_vgetyn(int dfl, const char *prompt, va_list ap)
case 'N':
return 0;
case '\n':
- return dfl;
+ if (dfl >= 0)
+ return dfl;
+ /* fall through */
default:
err("Please, reply 'y' or 'n'");
}
@@ -52,7 +58,7 @@ eclat_vgetyn(int dfl, const char *prompt, va_list ap)
break;
case 0:
vfprintf(stdout, prompt, ap);
- fprintf(stdout, " [%s] ", hint[dfl]);
+ fprintf(stdout, " [%s] ", hint[dfl+1]);
fflush(stdout);
state = 1;
break;
diff --git a/lib/libeclat.h b/lib/libeclat.h
index 35d2538..a558dae 100644
--- a/lib/libeclat.h
+++ b/lib/libeclat.h
@@ -110,8 +110,16 @@ char *eclat_getans(char *prompt, char *dfl, int pass);
int eclat_getyn(int dfl, const char *prompt, ...);
int eclat_vgetyn(int dfl, const char *prompt, va_list ap);
-extern int eclat_confirm_mode;
-int eclat_confirm(const char *prompt, ...);
+enum eclat_confirm_mode
+{
+ eclat_confirm_unspecified,
+ eclat_confirm_positive,
+ eclat_confirm_negative,
+ eclat_confirm_tty,
+ eclat_confirm_always
+};
+
+int eclat_confirm(enum eclat_confirm_mode mode, const char *prompt, ...);
#define ECLAT_MAP_OPEN 0x01
diff --git a/src/cmdline.opt b/src/cmdline.opt
index 2d75f24..54ec85f 100644
--- a/src/cmdline.opt
+++ b/src/cmdline.opt
@@ -156,13 +156,13 @@ END
OPTION(yes,Y,,
[<assume `yes' to all questions>])
BEGIN
- eclat_confirm_mode = 1;
+ confirm_mode = eclat_confirm_positive;
END
OPTION(no,N,,
[<assume `no' to all questions>])
BEGIN
- eclat_confirm_mode = 0;
+ confirm_mode = eclat_confirm_negative;
END
GROUP(Identifier translation)
diff --git a/src/config.c b/src/config.c
index f58747c..48bece7 100644
--- a/src/config.c
+++ b/src/config.c
@@ -149,6 +149,76 @@ cb_define_format(enum grecs_callback_command cmd,
return 0;
}
+static int
+cb_confirm(enum grecs_callback_command cmd,
+ grecs_locus_t *locus,
+ void *varptr,
+ grecs_value_t *value,
+ void *cb_data)
+{
+ struct grecs_list_entry *ep;
+ grecs_value_t *argval;
+ enum eclat_confirm_mode cfmode;
+ char *s;
+
+ if (cmd != grecs_callback_set_value) {
+ grecs_error(locus, 0, "Unexpected block statement");
+ return 1;
+ }
+ if (!value || value->type != GRECS_TYPE_ARRAY || value->v.arg.c != 2) {
+ grecs_error(locus, 0, "expected two values");
+ return 1;
+ }
+
+ if (value->v.arg.v[0]->type != GRECS_TYPE_STRING) {
+ grecs_error(locus, 0, "first argument not a string");
+ return 1;
+ }
+
+ switch (value->v.arg.v[1]->type) {
+ case GRECS_TYPE_STRING:
+ set_command_confirmation(value->v.arg.v[1]->v.string, cfmode,
+ &value->v.arg.v[1]->locus);
+ return 0;
+
+ case GRECS_TYPE_LIST:
+ break;
+
+ default:
+ grecs_error(locus, 0, "second argument not a list");
+ return 1;
+ }
+
+ s = value->v.arg.v[0]->v.string;
+ if (strcmp(s, "positive") == 0)
+ cfmode = eclat_confirm_positive;
+ else if (strcmp(s, "negative") == 0)
+ cfmode = eclat_confirm_negative;
+ else if (strcmp(s, "tty") == 0)
+ cfmode = eclat_confirm_tty;
+ else if (strcmp(s, "always") == 0)
+ cfmode = eclat_confirm_always;
+ else {
+ grecs_error(&value->v.arg.v[0]->locus, 0,
+ "unrecognized confirmation mode");
+ return 1;
+ }
+
+ for (ep = value->v.arg.v[1]->v.list->head; ep; ep = ep->next) {
+ argval = ep->data;
+ if (argval->type != GRECS_TYPE_STRING) {
+ grecs_error(&argval->locus, 0,
+ "list element not a string");
+ continue;
+ }
+
+ set_command_confirmation(argval->v.string, cfmode,
+ &argval->locus);
+ }
+
+ return 0;
+}
+
static struct grecs_keyword ssl_kw[] = {
{ "enable", NULL,
"Use SSL",
@@ -218,6 +288,10 @@ static struct grecs_keyword eclat_kw[] = {
grecs_type_string, GRECS_DFLT, &format_file },
{ "map", "name: string", "Configure a map",
grecs_type_section, GRECS_INAC },
+ { "confirm",
+ "<mode: { positive | negative | tty | always }> <commands: list>",
+ "Set confirmation mode",
+ grecs_type_string, GRECS_LIST, NULL, 0, cb_confirm },
{ NULL }
};
diff --git a/src/cretags.c b/src/cretags.c
index f0d3e1f..3554442 100644
--- a/src/cretags.c
+++ b/src/cretags.c
@@ -107,6 +107,7 @@ process_tags(CURL *curl, int argc, char **argv, const char *action)
}
}
free(bufptr);
+
return eclat_send_query(curl, q);
}
diff --git a/src/delvol.c b/src/delvol.c
index 675bd56..5180042 100644
--- a/src/delvol.c
+++ b/src/delvol.c
@@ -32,8 +32,6 @@ eclat_delete_volume(CURL *curl, int argc, char **argv)
if (argc != 1)
die(EX_USAGE, "bad number of arguments");
translate_ids(argc, argv, "VolumeId");
- if (!eclat_confirm("Really delete volume %s", argv[0]))
- exit(EX_CANCELLED);
q = eclat_query_create(use_ssl ? EC2_QF_HTTPS : 0, endpoint, "/");
eclat_query_add_param(q, "Action", "DeleteVolume");
eclat_query_add_param(q, "VolumeId", argv[0]);
diff --git a/src/eclat.c b/src/eclat.c
index 8eb2402..ef9dfd5 100644
--- a/src/eclat.c
+++ b/src/eclat.c
@@ -36,6 +36,7 @@ char *format_name_option;
int sort_option;
char *format_file;
char *test_map_name;
+enum eclat_confirm_mode confirm_mode;
FILE *xml_dump_file;
@@ -197,18 +198,26 @@ node_ident_cmp(struct grecs_node const *a, struct grecs_node const *b)
#include "cmdline.h"
+#define CMD_MOD 0x01
+#define CMD_DESTR 0x02
+
struct command {
const char *ident;
const char *tag;
eclat_command_handler_t handler;
+ int flags;
+ enum eclat_confirm_mode confirm;
char *fmt;
struct grecs_locus locus;
};
struct command cmdtab[] = {
- { "start-instances", "StartInstances", eclat_start_instance },
- { "stop-instances", "StopInstances", eclat_stop_instance },
- { "reboot-instances", "RebootInstances", eclat_reboot_instance },
+ { "start-instances", "StartInstances", eclat_start_instance,
+ CMD_MOD },
+ { "stop-instances", "StopInstances", eclat_stop_instance,
+ CMD_MOD },
+ { "reboot-instances", "RebootInstances", eclat_reboot_instance,
+ CMD_MOD },
{ "describe-addresses", "DescribeAddresses",
eclat_describe_addresses },
{ "describe-tags", "DescribeTags", eclat_describe_tags },
@@ -221,17 +230,17 @@ struct command cmdtab[] = {
{ "describe-volumes", "DescribeVolumes",
eclat_describe_volumes },
{ "allocate-address", "AllocateAddress",
- eclat_allocate_address },
+ eclat_allocate_address, CMD_MOD },
{ "release-address", "ReleaseAddress",
- eclat_release_address },
+ eclat_release_address, CMD_MOD|CMD_DESTR },
{ "associate-address", "AssociateAddress",
- eclat_associate_address },
+ eclat_associate_address, CMD_MOD },
{ "disassociate-address", "DisassociateAddress",
- eclat_disassociate_address },
+ eclat_disassociate_address, CMD_MOD },
{ "create-tags", "CreateTags",
- eclat_create_tags },
+ eclat_create_tags, CMD_MOD },
{ "delete-tags", "DeleteTags",
- eclat_delete_tags },
+ eclat_delete_tags, CMD_MOD|CMD_DESTR },
{ "get-console-output", "GetConsoleOutput",
eclat_get_console_output },
{ "describe-security-groups", "DescribeSecurityGroups",
@@ -241,15 +250,15 @@ struct command cmdtab[] = {
{ "describe-snapshots", "DescribeSnapshots",
eclat_describe_snapshots },
{ "delete-snapshot", "DeleteSnapshot",
- eclat_delete_snapshot },
+ eclat_delete_snapshot, CMD_MOD|CMD_DESTR },
{ "describe-avaialbility-zones", "DescribeAvaialbilityZones",
eclat_describe_avaialbility_zones },
{ "describe-regions", "DescribeRegions",
eclat_describe_regions },
{ "create-volume", "CreateVolume",
- eclat_create_volume },
+ eclat_create_volume, CMD_MOD },
{ "delete-volume", "DeleteVolume",
- eclat_delete_volume },
+ eclat_delete_volume, CMD_MOD|CMD_DESTR },
};
size_t cmdcnt = sizeof(cmdtab) / sizeof(cmdtab[0]);
@@ -362,6 +371,33 @@ find_command_tag(const char *tag)
}
void
+set_command_confirmation(const char *name, enum eclat_confirm_mode cfmode,
+ grecs_locus_t *locus)
+{
+ struct command *cp;
+ int flag = 0;
+
+ if (strcmp(name, "all") == 0)
+ flag = CMD_MOD;
+ else if (strcmp(name, "destructive") == 0)
+ flag = CMD_DESTR;
+ else {
+ cp = find_command_tag(name);
+
+ if (!cp)
+ grecs_error(locus, 0, "unknown command or class");
+ else
+ cp->confirm = cfmode;
+ return;
+ }
+
+ for (cp = cmdtab; cp < cmdtab + cmdcnt; cp++) {
+ if (cp->flags & flag)
+ cp->confirm = cfmode;
+ }
+}
+
+void
set_command_format(const char *name, const char *format, grecs_locus_t *locus)
{
struct command *cp = find_command_tag(name);
@@ -725,6 +761,12 @@ main(int argc, char **argv)
}
}
+ if (confirm_mode == eclat_confirm_unspecified)
+ confirm_mode = command->confirm;
+ if (!eclat_confirm(confirm_mode,
+ "Proceed with %s", command->ident))
+ die(EX_CANCELLED, "command not confirmed");
+
rc = command->handler(curl, argc, argv);
if (rc)
exit(rc);
diff --git a/src/eclat.h b/src/eclat.h
index ceca4d4..40c4014 100644
--- a/src/eclat.h
+++ b/src/eclat.h
@@ -52,6 +52,7 @@ extern char *secret_key;
extern char *format_file;
extern int translate_option;
extern char *custom_map;
+extern enum eclat_confirm_mode confirm_mode;
typedef int (*config_finish_hook_t) (void*);
@@ -130,3 +131,6 @@ forlan_eval_env_t find_format(const char *name);
void generic_parse_options(const char *pname, const char *docstring,
int argc, char *argv[], int *index);
extern struct grecs_proginfo *generic_proginfo;
+
+void set_command_confirmation(const char *name, enum eclat_confirm_mode cfmode,
+ grecs_locus_t *locus);
diff --git a/src/reladdr.c b/src/reladdr.c
index 5dc4ead..a98c0fb 100644
--- a/src/reladdr.c
+++ b/src/reladdr.c
@@ -30,9 +30,6 @@ eclat_release_address(CURL *curl, int argc, char **argv)
if (argc != 1)
die(EX_USAGE, "wrong number of arguments to release-address");
- if (!eclat_confirm("Really release %s %s",
- vpc ? "allocation ID" : "IP", argv[0]))
- exit(EX_CANCELLED);
q = eclat_query_create(use_ssl ? EC2_QF_HTTPS : 0, endpoint, "/");
eclat_query_add_param(q, "Action", "ReleaseAddress");

Return to:

Send suggestions and report system problems to the System administrator.