char *cmdline;
struct istream *input;
+ bool streaming;
};
static HASH_TABLE(char *, struct doveadm_server *) servers;
return 0;
}
+static void
+doveadm_cmd_print_callback(const unsigned char *data,
+ size_t size, bool finished,
+ struct doveadm_mail_server_cmd *servercmd)
+{
+ string_t *str = t_str_new(size);
+ if (!finished) {
+ servercmd->streaming = TRUE;
+ str_append_tabunescaped(str, data, size);
+ doveadm_print_stream(str->data, str->used);
+ } else if (servercmd->streaming) {
+ servercmd->streaming = FALSE;
+ if (size > 0) {
+ str_append_tabunescaped(str, data, size);
+ doveadm_print_stream(str->data, str->used);
+ }
+ doveadm_print_stream("", 0);
+ } else {
+ str_append_tabunescaped(str, data, size);
+ doveadm_print(str_c(str));
+ }
+}
+
static void doveadm_cmd_callback(const struct doveadm_server_reply *reply,
void *context)
{
servercmd->input = cmd_ctx->cmd_input;
if (servercmd->input != NULL)
i_stream_ref(servercmd->input);
+ server_connection_set_print(conn, doveadm_cmd_print_callback,
+ servercmd);
server_connection_cmd(conn, cmd_ctx->proxy_ttl,
str_c(cmd), cmd_ctx->cmd_input,
doveadm_cmd_callback, servercmd);
#include "ostream.h"
#include "ostream-dot.h"
#include "str.h"
-#include "strescape.h"
#include "iostream-ssl.h"
#include "master-service.h"
#include "doveadm.h"
-#include "doveadm-print.h"
#include "doveadm-util.h"
#include "doveadm-server.h"
#include "server-connection.h"
server_cmd_callback_t *callback;
void *context;
+ server_connection_print_t *print_callback;
+ void *print_context;
+
enum server_reply_state state;
bool authenticate_sent:1;
bool authenticated:1;
- bool streaming:1;
bool ssl_done:1;
};
callback(reply, conn->context);
}
-static void stream_data(string_t *str, const unsigned char *data, size_t size)
-{
- str_truncate(str, 0);
- str_append_tabunescaped(str, data, size);
- doveadm_print_stream(str->data, str->used);
-}
-
-static void server_flush_field(struct server_connection *conn, string_t *str,
- const unsigned char *data, size_t size)
-{
- if (conn->streaming) {
- conn->streaming = FALSE;
- if (size > 0)
- stream_data(str, data, size);
- doveadm_print_stream("", 0);
- } else {
- str_truncate(str, 0);
- str_append_tabunescaped(str, data, size);
- doveadm_print(str_c(str));
- }
-}
-
static void
server_handle_input(struct server_connection *conn,
const unsigned char *data, size_t size)
{
- string_t *str;
size_t i, start;
if (printing_conn == conn) {
size--;
}
- str = t_str_new(128);
for (i = start = 0; i < size; i++) {
if (data[i] == '\n') {
if (i != start) {
return;
}
if (data[i] == '\t') {
- server_flush_field(conn, str, data + start, i - start);
+ if (conn->print_callback != NULL) T_BEGIN {
+ conn->print_callback(data + start, i - start,
+ TRUE, conn->print_context);
+ } T_END;
start = i + 1;
}
}
- if (start != size) {
- conn->streaming = TRUE;
- stream_data(str, data + start, size - start);
- }
+ if (start != size && conn->print_callback != NULL) T_BEGIN {
+ conn->print_callback(data + start, size - start, FALSE,
+ conn->print_context);
+ } T_END;
i_stream_skip(conn->conn.input, size);
}
return 0;
}
+#undef server_connection_set_print
+void server_connection_set_print(struct server_connection *conn,
+ server_connection_print_t *callback,
+ void *context)
+{
+ conn->print_callback = callback;
+ conn->print_context = context;
+}
+
static void server_connection_destroy(struct server_connection **_conn)
{
struct server_connection *conn = *_conn;
typedef void server_cmd_callback_t(const struct doveadm_server_reply *reply,
void *context);
+/* Called when a field needs to be printed. If finished=FALSE, the next
+ call will continue printing this same field. */
+typedef void server_connection_print_t(const unsigned char *data,
+ size_t size, bool finished,
+ void *context);
+
int server_connection_create(struct doveadm_server *server,
struct server_connection **conn_r,
const char **error_r);
void server_connection_get_dest(struct server_connection *conn,
struct ip_addr *ip_r, in_port_t *port_r);
+void server_connection_set_print(struct server_connection *conn,
+ server_connection_print_t *callback,
+ void *context);
+#define server_connection_set_print(conn, callback, context) \
+ server_connection_set_print(conn, \
+ (server_connection_print_t *)callback, \
+ TRUE ? context : CALLBACK_TYPECHECK(callback, \
+ void (*)(const unsigned char *, size_t, bool, typeof(context))))
+
void server_connection_cmd(struct server_connection *conn, int proxy_ttl,
const char *line, struct istream *cmd_input,
server_cmd_callback_t *callback, void *context);