static bool client_handle_input(struct client *client) { const char *line, *cmd, *error; int ret; if (client->url != NULL || client->to_delay != NULL) { /* we're still processing a URL. wait until it's finished. */ io_remove(&client->io); client->io = NULL; client->waiting_input = TRUE; return TRUE; } if (client->io == NULL) { client->io = io_add(client->fd_in, IO_READ, client_input, client); } client->waiting_input = FALSE; timeout_reset(client->to_idle); switch (i_stream_read(client->input)) { case -1: /* disconnected */ if (client->ctrl_output != NULL) (void)o_stream_send_str(client->ctrl_output, "DISCONNECTED\n"); client_destroy(client); return FALSE; case -2: /* line too long, kill it */ client_abort(client, "Session aborted: Input line too long"); return FALSE; } while ((line = i_stream_next_line(client->input)) != NULL) { const char *const *args = t_strsplit_tabescaped(line); if (args[0] == NULL) continue; cmd = args[0]; args++; if (client->mail_user == NULL) ret = client_handle_user_command(client, cmd, args, &error); else ret = client_handle_command(client, cmd, args, &error); if (ret <= 0) { if (ret == 0) break; i_error("Client input error: %s", error); client_abort(client, "Session aborted: Unexpected input"); return FALSE; } } return TRUE; }
static void client_connection_input(struct client_connection *conn) { const char *line; bool ok = TRUE; int ret; if (!conn->handshaked) { if ((line = i_stream_read_next_line(conn->input)) == NULL) { if (conn->input->eof || conn->input->stream_errno != 0) { client_log_disconnect_error(conn); client_connection_destroy(&conn); } return; } if (!version_string_verify(line, "doveadm-server", DOVEADM_SERVER_PROTOCOL_VERSION_MAJOR)) { i_error("doveadm client not compatible with this server " "(mixed old and new binaries?)"); client_connection_destroy(&conn); return; } conn->handshaked = TRUE; } if (!conn->authenticated) { if ((ret = client_connection_authenticate(conn)) <= 0) { if (ret < 0) { o_stream_nsend(conn->output, "-\n", 2); client_connection_destroy(&conn); } return; } o_stream_nsend(conn->output, "+\n", 2); conn->authenticated = TRUE; } while (ok && !conn->input->closed && (line = i_stream_read_next_line(conn->input)) != NULL) { T_BEGIN { char **args; args = p_strsplit(pool_datastack_create(), line, "\t"); ok = client_handle_command(conn, args); } T_END; } if (conn->input->eof || conn->input->stream_errno != 0 || !ok) client_connection_destroy(&conn); }