1 /* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */
2
3 #include "lib.h"
4 #include "llist.h"
5 #include "strescape.h"
6 #include "istream.h"
7 #include "ostream.h"
8 #include "master-service.h"
9 #include "mail-session.h"
10 #include "mail-user.h"
11 #include "mail-command.h"
12 #include "fifo-input-connection.h"
13
14 #include <unistd.h>
15
16 #define MAX_INBUF_SIZE (PIPE_BUF*2)
17
18 struct fifo_input_connection {
19 struct fifo_input_connection *prev, *next;
20
21 int fd;
22 struct istream *input;
23 struct io *io;
24 };
25
26 static struct fifo_input_connection *fifo_conns = NULL;
27
28 static int
fifo_input_connection_request(const char * const * args,const char ** error_r)29 fifo_input_connection_request(const char *const *args, const char **error_r)
30 {
31 const char *cmd = args[0];
32
33 if (cmd == NULL) {
34 *error_r = "Missing command";
35 return -1;
36 }
37 args++;
38
39 if (strcmp(cmd, "CONNECT") == 0)
40 return mail_session_connect_parse(args, error_r);
41 if (strcmp(cmd, "DISCONNECT") == 0)
42 return mail_session_disconnect_parse(args, error_r);
43 if (strcmp(cmd, "UPDATE-SESSION") == 0)
44 return mail_session_update_parse(args, error_r);
45 if (strcmp(cmd, "ADD-USER") == 0)
46 return mail_user_add_parse(args, error_r);
47 if (strcmp(cmd, "UPDATE-CMD") == 0)
48 return mail_command_update_parse(args, error_r);
49
50 *error_r = "Unknown command";
51 return -1;
52 }
53
fifo_input_connection_input(struct fifo_input_connection * conn)54 static void fifo_input_connection_input(struct fifo_input_connection *conn)
55 {
56 const char *line, *const *args, *error;
57
58 switch (i_stream_read(conn->input)) {
59 case -2:
60 i_error("BUG: Mail server sent too much data");
61 fifo_input_connection_destroy(&conn);
62 return;
63 case -1:
64 fifo_input_connection_destroy(&conn);
65 return;
66 }
67
68 while ((line = i_stream_next_line(conn->input)) != NULL) T_BEGIN {
69 args = t_strsplit_tabescaped(line);
70 if (fifo_input_connection_request(args, &error) < 0)
71 i_error("FIFO input error: %s", error);
72 } T_END;
73 }
74
fifo_input_connection_create(int fd)75 struct fifo_input_connection *fifo_input_connection_create(int fd)
76 {
77 struct fifo_input_connection *conn;
78
79 conn = i_new(struct fifo_input_connection, 1);
80 conn->fd = fd;
81 conn->input = i_stream_create_fd(fd, MAX_INBUF_SIZE);
82 conn->io = io_add(fd, IO_READ, fifo_input_connection_input, conn);
83 DLLIST_PREPEND(&fifo_conns, conn);
84 return conn;
85 }
86
fifo_input_connection_destroy(struct fifo_input_connection ** _conn)87 void fifo_input_connection_destroy(struct fifo_input_connection **_conn)
88 {
89 struct fifo_input_connection *conn = *_conn;
90
91 *_conn = NULL;
92
93 DLLIST_REMOVE(&fifo_conns, conn);
94 io_remove(&conn->io);
95 i_stream_destroy(&conn->input);
96 if (close(conn->fd) < 0)
97 i_error("close(conn) failed: %m");
98 i_free(conn);
99 }
100
fifo_input_connections_destroy_all(void)101 void fifo_input_connections_destroy_all(void)
102 {
103 while (fifo_conns != NULL) {
104 struct fifo_input_connection *conn = fifo_conns;
105
106 fifo_input_connection_destroy(&conn);
107 }
108 }
109