Mercurial > dovecot > core-2.2
changeset 13179:09eb79247e71
doveadm-server: Many fixes to make it actually work properly.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 07 Aug 2011 22:11:20 +0300 |
parents | 4babc93e87ea |
children | c0b7dde5b193 |
files | src/doveadm/client-connection.c src/doveadm/doveadm-mail-server.c src/doveadm/doveadm-mail.c src/doveadm/doveadm-mail.h src/doveadm/doveadm-print-server.c src/doveadm/server-connection.c |
diffstat | 6 files changed, 82 insertions(+), 20 deletions(-) [+] |
line wrap: on
line diff
--- a/src/doveadm/client-connection.c Sun Aug 07 22:10:23 2011 +0300 +++ b/src/doveadm/client-connection.c Sun Aug 07 22:11:20 2011 +0300 @@ -60,6 +60,8 @@ service_flags |= MAIL_STORAGE_SERVICE_FLAG_DEBUG; ctx = doveadm_mail_cmd_init(cmd, set); + ctx->full_args = (const void *)argv; + getopt_args = t_strconcat("Au:", ctx->getopt_args, NULL); while ((c = getopt(argc, argv, getopt_args)) > 0) { switch (c) { @@ -83,7 +85,7 @@ } } - argv += optind-1; + argv += optind; optind = 1; if (argv[0] != NULL && cmd->usage_args == NULL) { @@ -153,8 +155,9 @@ flags = args[0]; input.username = args[1]; cmd_name = args[2]; - args += 3; - argc -= 3; + /* leave the command name as args[0] so getopt() works */ + args += 2; + argc -= 2; doveadm_debug = FALSE; doveadm_verbose = FALSE; @@ -264,10 +267,13 @@ } if (!conn->authenticated) { if ((ret = client_connection_authenticate(conn)) <= 0) { - if (ret < 0) + if (ret < 0) { + o_stream_send(conn->output, "-\n", 2); client_connection_destroy(&conn); + } return; } + o_stream_send(conn->output, "+\n", 2); conn->authenticated = TRUE; }
--- a/src/doveadm/doveadm-mail-server.c Sun Aug 07 22:10:23 2011 +0300 +++ b/src/doveadm/doveadm-mail-server.c Sun Aug 07 22:11:20 2011 +0300 @@ -125,9 +125,9 @@ str_tabescape_write(cmd, username); str_append_c(cmd, '\t'); str_tabescape_write(cmd, cmd_ctx->cmd->name); - for (i = 0; cmd_ctx->args[i] != NULL; i++) { + for (i = 0; cmd_ctx->full_args[i] != NULL; i++) { str_append_c(cmd, '\t'); - str_tabescape_write(cmd, cmd_ctx->args[i]); + str_tabescape_write(cmd, cmd_ctx->full_args[i]); } str_append_c(cmd, '\n'); server_connection_cmd(conn, str_c(cmd), doveadm_cmd_callback, conn);
--- a/src/doveadm/doveadm-mail.c Sun Aug 07 22:10:23 2011 +0300 +++ b/src/doveadm/doveadm-mail.c Sun Aug 07 22:11:20 2011 +0300 @@ -366,6 +366,7 @@ service_flags |= MAIL_STORAGE_SERVICE_FLAG_DEBUG; ctx = doveadm_mail_cmd_init(cmd, doveadm_settings); + ctx->full_args = (const void *)argv; getopt_args = t_strconcat("AS:u:", ctx->getopt_args, NULL); username = getenv("USER");
--- a/src/doveadm/doveadm-mail.h Sun Aug 07 22:10:23 2011 +0300 +++ b/src/doveadm/doveadm-mail.h Sun Aug 07 22:11:20 2011 +0300 @@ -37,6 +37,8 @@ pool_t pool; const struct doveadm_mail_cmd *cmd; const char *const *args; + /* args including -options */ + const char *const *full_args; const char *getopt_args; const struct doveadm_settings *set;
--- a/src/doveadm/doveadm-print-server.c Sun Aug 07 22:10:23 2011 +0300 +++ b/src/doveadm/doveadm-print-server.c Sun Aug 07 22:11:20 2011 +0300 @@ -65,6 +65,9 @@ static void doveadm_print_server_flush(void) { + if (doveadm_client == NULL) + return; + o_stream_send(client_connection_get_output(doveadm_client), str_data(ctx.str), str_len(ctx.str)); str_truncate(ctx.str, 0);
--- a/src/doveadm/server-connection.c Sun Aug 07 22:10:23 2011 +0300 +++ b/src/doveadm/server-connection.c Sun Aug 07 22:11:20 2011 +0300 @@ -9,6 +9,9 @@ #include "ostream.h" #include "str.h" #include "strescape.h" +#include "master-service.h" +#include "master-service-settings.h" +#include "settings-parser.h" #include "doveadm-print.h" #include "doveadm-util.h" #include "doveadm-server.h" @@ -28,11 +31,15 @@ struct server_connection { struct doveadm_server *server; + pool_t pool; + struct doveadm_settings *set; + int fd; struct io *io; struct istream *input; struct ostream *output; + const char *delayed_cmd; server_cmd_callback_t *callback; void *context; @@ -157,21 +164,26 @@ string_t *plain = t_str_new(128); string_t *cmd = t_str_new(128); - if (*doveadm_settings->doveadm_password == '\0') { - i_error("doveadm_password not set, can't authenticate"); + if (*conn->set->doveadm_password == '\0') { + i_error("doveadm_password not set, " + "can't authenticate to remote server"); return -1; } str_append_c(plain, '\0'); str_append(plain, "doveadm"); str_append_c(plain, '\0'); - str_append(plain, doveadm_settings->doveadm_password); + str_append(plain, conn->set->doveadm_password); str_append(cmd, "PLAIN\t"); base64_encode(plain->data, plain->used, cmd); str_append_c(cmd, '\n'); o_stream_send(conn->output, cmd->data, cmd->used); + if (conn->delayed_cmd != NULL) { + o_stream_send_str(conn->output, conn->delayed_cmd); + conn->delayed_cmd = NULL; + } return 0; } @@ -209,12 +221,9 @@ server_connection_destroy(&conn); return; } - data = i_stream_get_data(conn->input, &size); - if (size == 0) - return; if (!conn->authenticated) { - if ((line = i_stream_next_line(conn->input)) != NULL) + if ((line = i_stream_next_line(conn->input)) == NULL) return; if (strcmp(line, "+") == 0) conn->authenticated = TRUE; @@ -225,6 +234,10 @@ } } + data = i_stream_get_data(conn->input, &size); + if (size == 0) + return; + switch (conn->state) { case SERVER_REPLY_STATE_DONE: i_error("doveadm server sent unexpected input"); @@ -243,22 +256,53 @@ server_connection_callback(conn, SERVER_CMD_REPLY_OK); else if (data[0] == '-' && data[1] == '\n') server_connection_callback(conn, SERVER_CMD_REPLY_FAIL); - else { + else i_error("doveadm server sent broken input"); - server_connection_destroy(&conn); - return; - } + /* we're finished, close the connection */ + server_connection_destroy(&conn); break; } } +static int server_connection_read_settings(struct server_connection *conn) +{ + const struct setting_parser_info *set_roots[] = { + &doveadm_setting_parser_info, + NULL + }; + struct master_service_settings_input input; + struct master_service_settings_output output; + const char *error; + unsigned int port; + void *set; + + memset(&input, 0, sizeof(input)); + input.roots = set_roots; + input.service = "doveadm"; + + (void)net_getsockname(conn->fd, &input.local_ip, &port); + (void)net_getpeername(conn->fd, &input.remote_ip, &port); + + if (master_service_settings_read(master_service, &input, + &output, &error) < 0) { + i_error("Error reading configuration: %s", error); + return -1; + } + set = master_service_settings_get_others(master_service)[0]; + conn->set = settings_dup(&doveadm_setting_parser_info, set, conn->pool); + return 0; +} + struct server_connection * server_connection_create(struct doveadm_server *server) { #define DOVEADM_SERVER_HANDSHAKE "VERSION\tdoveadm-server\t1\t0\n" struct server_connection *conn; + pool_t pool; - conn = i_new(struct server_connection, 1); + pool = pool_alloconly_create("doveadm server connection", 1024*16); + conn = p_new(pool, struct server_connection, 1); + conn->pool = pool; conn->server = server; conn->fd = doveadm_connect(server->name); net_set_nonblock(conn->fd, TRUE); @@ -269,6 +313,7 @@ o_stream_send_str(conn->output, DOVEADM_SERVER_HANDSHAKE); array_append(&conn->server->connections, &conn, 1); + server_connection_read_settings(conn); return conn; } @@ -301,7 +346,7 @@ io_remove(&conn->io); if (close(conn->fd) < 0) i_error("close(server) failed: %m"); - i_free(conn); + pool_unref(&conn->pool); } struct doveadm_server * @@ -313,8 +358,13 @@ void server_connection_cmd(struct server_connection *conn, const char *line, server_cmd_callback_t *callback, void *context) { + i_assert(conn->delayed_cmd == NULL); + conn->state = SERVER_REPLY_STATE_PRINT; - o_stream_send_str(conn->output, line); + if (conn->authenticated) + o_stream_send_str(conn->output, line); + else + conn->delayed_cmd = p_strdup(conn->pool, line); conn->callback = callback; conn->context = context; }