Commit b8e3963d authored by Niels Möller's avatar Niels Möller
Browse files

Replaced werror with wwrite for constant messages.

Rev: src/blowfish.c:1.2
Rev: src/channel.c:1.23
Rev: src/client.c:1.46
Rev: src/client_keyexchange.c:1.21
Rev: src/client_userauth.c:1.11
Rev: src/connection.c:1.22
Rev: src/debug.c:1.22
Rev: src/des.c:1.3
Rev: src/disconnect.c:1.11
Rev: src/lsh_keygen.c:1.5
Rev: src/reaper.c:1.7
Rev: src/server.c:1.37
Rev: src/server_keyexchange.c:1.21
Rev: src/sexp_parser.c:1.5
parent 459be67b
...@@ -75,7 +75,7 @@ make_blowfish_instance(struct crypto_algorithm *algorithm, int mode, ...@@ -75,7 +75,7 @@ make_blowfish_instance(struct crypto_algorithm *algorithm, int mode,
case 0: case 0:
return &self->super; return &self->super;
default: default:
werror("Detected a weak blowfish key!\n"); wwrite("Detected a weak blowfish key!\n");
KILL(self); KILL(self);
return NULL; return NULL;
} }
......
...@@ -386,7 +386,7 @@ static int do_channel_open(struct packet_handler *c, ...@@ -386,7 +386,7 @@ static int do_channel_open(struct packet_handler *c,
if ( (local_channel_number if ( (local_channel_number
= register_channel(closure->super.table, channel)) < 0) = register_channel(closure->super.table, channel)) < 0)
{ {
werror("Could not allocate a channel number for pened channel!\n"); wwrite("Could not allocate a channel number for pened channel!\n");
return A_WRITE(connection->write, return A_WRITE(connection->write,
format_open_failure(remote_channel_number, format_open_failure(remote_channel_number,
SSH_OPEN_RESOURCE_SHORTAGE, SSH_OPEN_RESOURCE_SHORTAGE,
...@@ -540,7 +540,7 @@ static int do_channel_data(struct packet_handler *c, ...@@ -540,7 +540,7 @@ static int do_channel_data(struct packet_handler *c,
{ {
if (channel->flags & CHANNEL_SENT_CLOSE) if (channel->flags & CHANNEL_SENT_CLOSE)
{ {
werror("Ignoring data on channel which is closing\n"); wwrite("Ignoring data on channel which is closing\n");
return LSH_OK | LSH_GOON; return LSH_OK | LSH_GOON;
} }
else else
...@@ -550,7 +550,7 @@ static int do_channel_data(struct packet_handler *c, ...@@ -550,7 +550,7 @@ static int do_channel_data(struct packet_handler *c,
if (data->length > channel->rec_window_size) if (data->length > channel->rec_window_size)
{ {
/* Truncate data to fit window */ /* Truncate data to fit window */
werror("Channel data overflow. Extra data ignored.\n"); wwrite("Channel data overflow. Extra data ignored.\n");
data->length = channel->rec_window_size; data->length = channel->rec_window_size;
} }
...@@ -623,7 +623,7 @@ static int do_channel_extended_data(struct packet_handler *c, ...@@ -623,7 +623,7 @@ static int do_channel_extended_data(struct packet_handler *c,
{ {
if (channel->flags & CHANNEL_SENT_CLOSE) if (channel->flags & CHANNEL_SENT_CLOSE)
{ {
werror("Ignoring extended data on channel which is closing\n"); wwrite("Ignoring extended data on channel which is closing\n");
return LSH_OK | LSH_GOON; return LSH_OK | LSH_GOON;
} }
else else
...@@ -633,7 +633,7 @@ static int do_channel_extended_data(struct packet_handler *c, ...@@ -633,7 +633,7 @@ static int do_channel_extended_data(struct packet_handler *c,
if (data->length > channel->rec_window_size) if (data->length > channel->rec_window_size)
{ {
/* Truncate data to fit window */ /* Truncate data to fit window */
werror("Channel extended data overflow. " wwrite("Channel extended data overflow. "
"Extra data ignored.\n"); "Extra data ignored.\n");
data->length = channel->rec_window_size; data->length = channel->rec_window_size;
} }
...@@ -702,7 +702,7 @@ static int do_channel_eof(struct packet_handler *c, ...@@ -702,7 +702,7 @@ static int do_channel_eof(struct packet_handler *c,
if (channel->flags & (CHANNEL_RECEIVED_EOF | CHANNEL_RECEIVED_CLOSE)) if (channel->flags & (CHANNEL_RECEIVED_EOF | CHANNEL_RECEIVED_CLOSE))
{ {
werror("Receiving EOF on channel on closed channel.\n"); wwrite("Receiving EOF on channel on closed channel.\n");
return LSH_FAIL | LSH_DIE; return LSH_FAIL | LSH_DIE;
} }
...@@ -767,7 +767,7 @@ static int do_channel_close(struct packet_handler *c, ...@@ -767,7 +767,7 @@ static int do_channel_close(struct packet_handler *c,
if (channel->flags & CHANNEL_RECEIVED_CLOSE) if (channel->flags & CHANNEL_RECEIVED_CLOSE)
{ {
werror("Receiving multiple CLOSE on channel.\n"); wwrite("Receiving multiple CLOSE on channel.\n");
return LSH_FAIL | LSH_DIE; return LSH_FAIL | LSH_DIE;
} }
...@@ -775,7 +775,7 @@ static int do_channel_close(struct packet_handler *c, ...@@ -775,7 +775,7 @@ static int do_channel_close(struct packet_handler *c,
if (! (channel->flags & (CHANNEL_RECEIVED_EOF | CHANNEL_SENT_EOF))) if (! (channel->flags & (CHANNEL_RECEIVED_EOF | CHANNEL_SENT_EOF)))
{ {
werror("Unexpected channel CLOSE.\n"); wwrite("Unexpected channel CLOSE.\n");
} }
if (! (channel->flags & (CHANNEL_RECEIVED_EOF)) if (! (channel->flags & (CHANNEL_RECEIVED_EOF))
......
...@@ -150,9 +150,9 @@ static struct read_handler *do_line(struct line_handler **h, ...@@ -150,9 +150,9 @@ static struct read_handler *do_line(struct line_handler **h,
} }
else else
{ {
werror("Unsupported protocol version: "); wwrite("Unsupported protocol version: ");
werror_safe(length, line); werror_safe(length, line);
werror("\n"); wwrite("\n");
/* FIXME: Clean up properly */ /* FIXME: Clean up properly */
KILL(closure); KILL(closure);
...@@ -209,7 +209,7 @@ static int client_close_die(struct close_callback *closure UNUSED, ...@@ -209,7 +209,7 @@ static int client_close_die(struct close_callback *closure UNUSED,
{ {
verbose("Connection died, for reason %d.\n", reason); verbose("Connection died, for reason %d.\n", reason);
if (reason != CLOSE_EOF) if (reason != CLOSE_EOF)
werror("Connection died.\n"); wwrite("Connection died.\n");
/* FIXME: Return value is not used. */ /* FIXME: Return value is not used. */
return 4711; return 4711;
...@@ -427,7 +427,7 @@ static int do_exit_signal(struct channel_request *c, ...@@ -427,7 +427,7 @@ static int do_exit_signal(struct channel_request *c,
werror("Remote process was killed by %s.\n", werror("Remote process was killed by %s.\n",
signal ? strsignal(signal) : "an unknown signal"); signal ? strsignal(signal) : "an unknown signal");
if (core) if (core)
werror("(core dumped remotely)\n"); wwrite("(core dumped remotely)\n");
ALIST_SET(channel->request_types, ATOM_EXIT_STATUS, NULL); ALIST_SET(channel->request_types, ATOM_EXIT_STATUS, NULL);
ALIST_SET(channel->request_types, ATOM_EXIT_SIGNAL, NULL); ALIST_SET(channel->request_types, ATOM_EXIT_SIGNAL, NULL);
......
...@@ -111,7 +111,7 @@ static int do_handle_dh_reply(struct packet_handler *c, ...@@ -111,7 +111,7 @@ static int do_handle_dh_reply(struct packet_handler *c,
if (!INSTALL_KEYS(closure->install, connection, hash)) if (!INSTALL_KEYS(closure->install, connection, hash))
{ {
werror("Installing new keys failed. Hanging up.\n"); wwrite("Installing new keys failed. Hanging up.\n");
KILL(hash); KILL(hash);
/* FIXME: Send a disconnect message */ /* FIXME: Send a disconnect message */
return LSH_FAIL | LSH_DIE; return LSH_FAIL | LSH_DIE;
......
...@@ -132,7 +132,7 @@ static int do_userauth_success(struct packet_handler *c, ...@@ -132,7 +132,7 @@ static int do_userauth_success(struct packet_handler *c,
&& (msg_number == SSH_MSG_USERAUTH_SUCCESS) && (msg_number == SSH_MSG_USERAUTH_SUCCESS)
&& parse_eod(&buffer)) && parse_eod(&buffer))
{ {
werror("User authentication successful.\n"); wwrite("User authentication successful.\n");
lsh_string_free(packet); lsh_string_free(packet);
...@@ -175,7 +175,7 @@ static int do_userauth_failure(struct packet_handler *c, ...@@ -175,7 +175,7 @@ static int do_userauth_failure(struct packet_handler *c,
if (partial_success) if (partial_success)
{ /* Doesn't help us */ { /* Doesn't help us */
werror("Received SSH_MSH_USERAUTH_FAILURE " wwrite("Received SSH_MSH_USERAUTH_FAILURE "
"indicating partial success.\n"); "indicating partial success.\n");
KILL(methods); KILL(methods);
......
...@@ -47,7 +47,7 @@ static int handle_connection(struct abstract_write *w, ...@@ -47,7 +47,7 @@ static int handle_connection(struct abstract_write *w,
if (!packet->length) if (!packet->length)
{ {
werror("connection.c: Received empty packet!\n"); wwrite("connection.c: Received empty packet!\n");
return LSH_FAIL | LSH_DIE; return LSH_FAIL | LSH_DIE;
} }
...@@ -60,7 +60,7 @@ static int handle_connection(struct abstract_write *w, ...@@ -60,7 +60,7 @@ static int handle_connection(struct abstract_write *w,
case KEX_STATE_INIT: case KEX_STATE_INIT:
if (msg == SSH_MSG_NEWKEYS) if (msg == SSH_MSG_NEWKEYS)
{ {
werror("Unexpected NEWKEYS message!\n"); wwrite("Unexpected NEWKEYS message!\n");
lsh_string_free(packet); lsh_string_free(packet);
return LSH_FAIL | LSH_DIE; return LSH_FAIL | LSH_DIE;
} }
...@@ -80,7 +80,7 @@ static int handle_connection(struct abstract_write *w, ...@@ -80,7 +80,7 @@ static int handle_connection(struct abstract_write *w,
if ( (msg == SSH_MSG_NEWKEYS) if ( (msg == SSH_MSG_NEWKEYS)
|| (msg == SSH_MSG_KEXINIT)) || (msg == SSH_MSG_KEXINIT))
{ {
werror("Unexpected KEXINIT or NEWKEYS message!\n"); wwrite("Unexpected KEXINIT or NEWKEYS message!\n");
lsh_string_free(packet); lsh_string_free(packet);
return LSH_FAIL | LSH_DIE; return LSH_FAIL | LSH_DIE;
} }
......
...@@ -117,9 +117,9 @@ static int do_rec_debug(struct packet_handler *self UNUSED, ...@@ -117,9 +117,9 @@ static int do_rec_debug(struct packet_handler *self UNUSED,
if (always_display) if (always_display)
{ {
werror("Received debug: "); wwrite("Received debug: ");
werror_utf8(length, msg); werror_utf8(length, msg);
werror("\n"); wwrite("\n");
} }
else else
{ {
......
...@@ -88,7 +88,7 @@ make_des_instance(struct crypto_algorithm *algorithm UNUSED, int mode, ...@@ -88,7 +88,7 @@ make_des_instance(struct crypto_algorithm *algorithm UNUSED, int mode,
case -1: case -1:
fatal("Internal error! Bad parity in make_des_instance.\n"); fatal("Internal error! Bad parity in make_des_instance.\n");
case -2: case -2:
werror("Detected weak DES key.\n"); wwrite("Detected weak DES key.\n");
KILL(self); KILL(self);
return NULL; return NULL;
default: default:
......
...@@ -62,7 +62,7 @@ static int do_disconnect(struct packet_handler *closure UNUSED, ...@@ -62,7 +62,7 @@ static int do_disconnect(struct packet_handler *closure UNUSED,
werror_utf8(length, msg); werror_utf8(length, msg);
} }
else else
werror("Invalid disconnect message!\n"); wwrite("Invalid disconnect message!\n");
lsh_string_free(packet); lsh_string_free(packet);
/* FIXME: Mark the file as closed, somehow (probably a variable in /* FIXME: Mark the file as closed, somehow (probably a variable in
......
...@@ -46,7 +46,7 @@ static void usage(void) NORETURN; ...@@ -46,7 +46,7 @@ static void usage(void) NORETURN;
static void usage(void) static void usage(void)
{ {
werror("Usage: lsh_keygen [-o style] [-l nist-level] [-a dss] [-q] [-d] [-v]\n"); wwrite("Usage: lsh_keygen [-o style] [-l nist-level] [-a dss] [-q] [-d] [-v]\n");
exit(1); exit(1);
} }
...@@ -76,7 +76,7 @@ int main(int argc, char **argv) ...@@ -76,7 +76,7 @@ int main(int argc, char **argv)
if ( (l<0) || (l > 8)) if ( (l<0) || (l > 8))
{ {
werror("lsh_keygen: nist-level should be in the range 0-8.\n"); wwrite("lsh_keygen: nist-level should be in the range 0-8.\n");
usage(); usage();
} }
break; break;
...@@ -84,7 +84,7 @@ int main(int argc, char **argv) ...@@ -84,7 +84,7 @@ int main(int argc, char **argv)
case 'a': case 'a':
if (strcmp(optarg, "dss")) if (strcmp(optarg, "dss"))
{ {
werror("lsh_keygen: Sorry, doesn't support any algorithm but dss.\n"); wwrite("lsh_keygen: Sorry, doesn't support any algorithm but dss.\n");
usage(); usage();
} }
break; break;
...@@ -99,7 +99,7 @@ int main(int argc, char **argv) ...@@ -99,7 +99,7 @@ int main(int argc, char **argv)
style = SEXP_INTERNATIONAL; style = SEXP_INTERNATIONAL;
else else
{ {
werror("lsh_keygen: Style must be one of\n" wwrite("lsh_keygen: Style must be one of\n"
" 'transport', 'canonical', 'advanced' or 'international'\n"); " 'transport', 'canonical', 'advanced' or 'international'\n");
usage(); usage();
} }
...@@ -140,20 +140,20 @@ int main(int argc, char **argv) ...@@ -140,20 +140,20 @@ int main(int argc, char **argv)
/* Sanity check. */ /* Sanity check. */
if (!mpz_probab_prime_p(public.p, 10)) if (!mpz_probab_prime_p(public.p, 10))
{ {
werror("p not a prime!\n"); wwrite("p not a prime!\n");
return 1; return 1;
} }
if (!mpz_probab_prime_p(public.q, 10)) if (!mpz_probab_prime_p(public.q, 10))
{ {
werror("q not a prime!\n"); wwrite("q not a prime!\n");
return 1; return 1;
} }
mpz_fdiv_r(t, public.p, public.q); mpz_fdiv_r(t, public.p, public.q);
if (mpz_cmp_ui(t, 1)) if (mpz_cmp_ui(t, 1))
{ {
werror("q doesn't divide p-1 !\n"); wwrite("q doesn't divide p-1 !\n");
return 1; return 1;
} }
...@@ -170,7 +170,7 @@ int main(int argc, char **argv) ...@@ -170,7 +170,7 @@ int main(int argc, char **argv)
{ {
/* Now, output a private key spki structure. */ /* Now, output a private key spki structure. */
struct abstract_write *output = make_blocking_write(STDOUT_FILENO); struct abstract_write *output = make_blocking_write(STDOUT_FILENO, 0);
struct lsh_string *key = sexp_format struct lsh_string *key = sexp_format
(sexp_l(2, sexp_z("private-key"), (sexp_l(2, sexp_z("private-key"),
......
...@@ -129,7 +129,7 @@ static void reap(struct reaper *r) ...@@ -129,7 +129,7 @@ static void reap(struct reaper *r)
else switch(errno) else switch(errno)
{ {
case EINTR: case EINTR:
werror("reaper.c: waitpid() returned EINTR.\n"); wwrite("reaper.c: waitpid() returned EINTR.\n");
break; break;
case ECHILD: case ECHILD:
/* No more child processes */ /* No more child processes */
......
...@@ -209,9 +209,9 @@ static struct read_handler *do_line(struct line_handler **h, ...@@ -209,9 +209,9 @@ static struct read_handler *do_line(struct line_handler **h,
} }
else else
{ {
werror("Unsupported protocol version: "); wwrite("Unsupported protocol version: ");
werror_safe(length, line); werror_safe(length, line);
werror("\n"); wwrite("\n");
/* FIXME: Clean up properly */ /* FIXME: Clean up properly */
KILL(closure); KILL(closure);
...@@ -276,7 +276,7 @@ static int server_die(struct close_callback *c, int reason) ...@@ -276,7 +276,7 @@ static int server_die(struct close_callback *c, int reason)
verbose("Connection died, for reason %d.\n", reason); verbose("Connection died, for reason %d.\n", reason);
if (reason != CLOSE_EOF) if (reason != CLOSE_EOF)
werror("Connection died.\n"); wwrite("Connection died.\n");
KILL_RESOURCE_LIST(closure->connection->resources); KILL_RESOURCE_LIST(closure->connection->resources);
...@@ -370,7 +370,7 @@ static int do_receive(struct ssh_channel *c, ...@@ -370,7 +370,7 @@ static int do_receive(struct ssh_channel *c,
case CHANNEL_DATA: case CHANNEL_DATA:
return A_WRITE(&closure->in->buffer->super, data); return A_WRITE(&closure->in->buffer->super, data);
case CHANNEL_STDERR_DATA: case CHANNEL_STDERR_DATA:
werror("Ignoring unexpected stderr data.\n"); wwrite("Ignoring unexpected stderr data.\n");
lsh_string_free(data); lsh_string_free(data);
return LSH_OK | LSH_GOON; return LSH_OK | LSH_GOON;
default: default:
...@@ -745,14 +745,14 @@ static int do_spawn_shell(struct channel_request *c, ...@@ -745,14 +745,14 @@ static int do_spawn_shell(struct channel_request *c,
if (!session->user->shell) if (!session->user->shell)
{ {
werror("No login shell!\n"); wwrite("No login shell!\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (getuid() != session->user->uid) if (getuid() != session->user->uid)
if (!change_uid(session->user)) if (!change_uid(session->user))
{ {
werror("Changing uid failed!\n"); wwrite("Changing uid failed!\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -760,7 +760,7 @@ static int do_spawn_shell(struct channel_request *c, ...@@ -760,7 +760,7 @@ static int do_spawn_shell(struct channel_request *c,
if (!change_dir(session->user)) if (!change_dir(session->user))
{ {
werror("Could not change to home (or root) directory!\n"); wwrite("Could not change to home (or root) directory!\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -792,7 +792,7 @@ static int do_spawn_shell(struct channel_request *c, ...@@ -792,7 +792,7 @@ static int do_spawn_shell(struct channel_request *c,
if (dup2(in[0], STDIN_FILENO) < 0) if (dup2(in[0], STDIN_FILENO) < 0)
{ {
werror("Can't dup stdin!\n"); wwrite("Can't dup stdin!\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
close(in[0]); close(in[0]);
...@@ -800,14 +800,14 @@ static int do_spawn_shell(struct channel_request *c, ...@@ -800,14 +800,14 @@ static int do_spawn_shell(struct channel_request *c,
if (dup2(out[1], STDOUT_FILENO) < 0) if (dup2(out[1], STDOUT_FILENO) < 0)
{ {
werror("Can't dup stdout!\n"); wwrite("Can't dup stdout!\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
close(out[0]); close(out[0]);
close(out[1]); close(out[1]);
if ((old_stderr = dup(STDERR_FILENO)) < 0) if ((old_stderr = dup(STDERR_FILENO)) < 0)
werror("Couldn't safe old file_no.\n"); wwrite("Couldn't save old file_no.\n");
io_set_close_on_exec(old_stderr); io_set_close_on_exec(old_stderr);
debug("Child: Duping stderr (bye).\n"); debug("Child: Duping stderr (bye).\n");
......
...@@ -102,7 +102,7 @@ static int do_handle_dh_init(struct packet_handler *c, ...@@ -102,7 +102,7 @@ static int do_handle_dh_init(struct packet_handler *c,
if (!INSTALL_KEYS(closure->install, connection, hash)) if (!INSTALL_KEYS(closure->install, connection, hash))
{ {
werror("Installing new keys failed. Hanging up.\n"); wwrite("Installing new keys failed. Hanging up.\n");
KILL(hash); KILL(hash);
/* FIXME: Send a disconnect message */ /* FIXME: Send a disconnect message */
return LSH_FAIL | LSH_DIE; return LSH_FAIL | LSH_DIE;
......
...@@ -88,7 +88,7 @@ static struct lsh_string *sexp_parse_token(struct simple_buffer *buffer) ...@@ -88,7 +88,7 @@ static struct lsh_string *sexp_parse_token(struct simple_buffer *buffer)
if (!length) if (!length)
{ {
werror("sexp: Invalid token.\n"); wwrite("sexp: Invalid token.\n");
return NULL; return NULL;
} }
...@@ -109,7 +109,7 @@ static int sexp_parse_decimal(struct simple_buffer *buffer, UINT32 *value) ...@@ -109,7 +109,7 @@ static int sexp_parse_decimal(struct simple_buffer *buffer, UINT32 *value)
if ((*HERE == '0') && (length != 1)) if ((*HERE == '0') && (length != 1))
{ {
/* No leading zeros allowed */ /* No leading zeros allowed */
werror("sexp: Unexpected leading zeroes\n"); wwrite("sexp: Unexpected leading zeroes\n");
return 0; return 0;
} }
if (length > 8) if (length > 8)
...@@ -133,7 +133,7 @@ sexp_parse_literal(struct simple_buffer *buffer, UINT32 length) ...@@ -133,7 +133,7 @@ sexp_parse_literal(struct simple_buffer *buffer, UINT32 length)
if (LEFT < length) if (LEFT < length)
{ {
werror("sexp: Unexpected EOF in literal.\n"); wwrite("sexp: Unexpected EOF in literal.\n");
return NULL; return NULL;
} }
...@@ -224,7 +224,7 @@ static int sexp_dequote(struct simple_buffer *buffer) ...@@ -224,7 +224,7 @@ static int sexp_dequote(struct simple_buffer *buffer)
if (LEFT < 2) if (LEFT < 2)
{ {
werror("sexp: Unexpected eof in octal escape sequence.\n"); wwrite("sexp: Unexpected eof in octal escape sequence.\n");
return QUOTE_INVALID; return QUOTE_INVALID;
} }
...@@ -263,7 +263,7 @@ sexp_parse_quoted_length(struct simple_buffer *buffer, UINT32 length) ...@@ -263,7 +263,7 @@ sexp_parse_quoted_length(struct simple_buffer *buffer, UINT32 length)
if (c < 0) if (c < 0)
{ {
if (c == QUOTE_END) if (c == QUOTE_END)
werror("sexp: Quoted string is too short.\n"); wwrite("sexp: Quoted string is too short.\n");
lsh_string_free(res); lsh_string_free(res);
return NULL; return NULL;
} }
...@@ -292,7 +292,7 @@ sexp_parse_quoted(struct simple_buffer *buffer) ...@@ -292,7 +292,7 @@ sexp_parse_quoted(struct simple_buffer *buffer)
p = memchr(p, '"', (HERE + LEFT) - p); p = memchr(p, '"', (HERE + LEFT) - p);
if (!p) if (!p)
{ {
werror("sexp: Unexpected EOF in quoted string.\n"); wwrite("sexp: Unexpected EOF in quoted string.\n");
return NULL; return NULL;
} }
if (p[-1] != '\\') if (p[-1] != '\\')
...@@ -341,7 +341,7 @@ static int sexp_dehex(struct simple_buffer *buffer) ...@@ -341,7 +341,7 @@ static int sexp_dehex(struct simple_buffer *buffer)
if (!LEFT) if (!LEFT)
{