fifo-input-connection.c revision 6ef83bcdc4e40d6b387857e5f7d58cd86c71ec50
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync/* Copyright (c) 2011-2017 Dovecot authors, see the included COPYING file */
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync
d34409ad02ea0d28e08a6c4b089a412fdb3b4c9cvboxsync#include "lib.h"
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync#include "llist.h"
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync#include "strescape.h"
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync#include "istream.h"
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync#include "ostream.h"
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync#include "master-service.h"
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync#include "mail-session.h"
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync#include "mail-user.h"
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync#include "mail-command.h"
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync#include "fifo-input-connection.h"
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync#include <unistd.h>
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync#define MAX_INBUF_SIZE (PIPE_BUF*2)
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync
a9b62afc62b28da7a1a77f34259f8013892d9664vboxsyncstruct fifo_input_connection {
a9b62afc62b28da7a1a77f34259f8013892d9664vboxsync struct fifo_input_connection *prev, *next;
a9b62afc62b28da7a1a77f34259f8013892d9664vboxsync
a9b62afc62b28da7a1a77f34259f8013892d9664vboxsync int fd;
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync struct istream *input;
a9b62afc62b28da7a1a77f34259f8013892d9664vboxsync struct io *io;
a9b62afc62b28da7a1a77f34259f8013892d9664vboxsync};
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsyncstatic struct fifo_input_connection *fifo_conns = NULL;
a9b62afc62b28da7a1a77f34259f8013892d9664vboxsync
a9b62afc62b28da7a1a77f34259f8013892d9664vboxsyncstatic int
a9b62afc62b28da7a1a77f34259f8013892d9664vboxsyncfifo_input_connection_request(const char *const *args, const char **error_r)
a9b62afc62b28da7a1a77f34259f8013892d9664vboxsync{
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync const char *cmd = args[0];
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync if (cmd == NULL) {
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync *error_r = "Missing command";
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync return -1;
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync }
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync args++;
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync if (strcmp(cmd, "CONNECT") == 0)
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync return mail_session_connect_parse(args, error_r);
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync if (strcmp(cmd, "DISCONNECT") == 0)
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync return mail_session_disconnect_parse(args, error_r);
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync if (strcmp(cmd, "UPDATE-SESSION") == 0)
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync return mail_session_update_parse(args, error_r);
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync if (strcmp(cmd, "ADD-USER") == 0)
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync return mail_user_add_parse(args, error_r);
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync if (strcmp(cmd, "UPDATE-CMD") == 0)
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync return mail_command_update_parse(args, error_r);
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync *error_r = "Unknown command";
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync return -1;
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync}
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsyncstatic void fifo_input_connection_input(struct fifo_input_connection *conn)
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync{
a6b9fb03568b86eb6be55f1db015eab0921f7ee0vboxsync const char *line, *const *args, *error;
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync switch (i_stream_read(conn->input)) {
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync case -2:
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync i_error("BUG: Mail server sent too much data");
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync fifo_input_connection_destroy(&conn);
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync return;
319b6c2f1a5b5420b0a7fbef89477984cec16007vboxsync case -1:
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync fifo_input_connection_destroy(&conn);
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync return;
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync }
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync while ((line = i_stream_next_line(conn->input)) != NULL) T_BEGIN {
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync args = t_strsplit_tabescaped(line);
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync if (fifo_input_connection_request(args, &error) < 0)
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync i_error("FIFO input error: %s", error);
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync } T_END;
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync}
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsyncstruct fifo_input_connection *fifo_input_connection_create(int fd)
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync{
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync struct fifo_input_connection *conn;
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync conn = i_new(struct fifo_input_connection, 1);
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync conn->fd = fd;
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync conn->input = i_stream_create_fd(fd, MAX_INBUF_SIZE);
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync conn->io = io_add(fd, IO_READ, fifo_input_connection_input, conn);
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync DLLIST_PREPEND(&fifo_conns, conn);
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync return conn;
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync}
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsyncvoid fifo_input_connection_destroy(struct fifo_input_connection **_conn)
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync{
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync struct fifo_input_connection *conn = *_conn;
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync *_conn = NULL;
cdaeb34871aa28b96c0d80b474f3c8f9805d0388vboxsync
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync DLLIST_REMOVE(&fifo_conns, conn);
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync io_remove(&conn->io);
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync i_stream_destroy(&conn->input);
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync if (close(conn->fd) < 0)
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync i_error("close(conn) failed: %m");
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync i_free(conn);
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync}
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsyncvoid fifo_input_connections_destroy_all(void)
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync{
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync while (fifo_conns != NULL) {
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync struct fifo_input_connection *conn = fifo_conns;
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync fifo_input_connection_destroy(&conn);
3c4dd6a990d38eba0aad586bb42f72d2b10b682avboxsync }
3b0af6c6de3509194973be62078331fc930175f7vboxsync}
3b0af6c6de3509194973be62078331fc930175f7vboxsync