rawlog.c revision d4545f88331bb06244505cef10e96174c5c19ed4
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2002-2010 Dovecot authors, see the included COPYING file */
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen struct ostream *client_output, *server_output;
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainenstatic void rawlog_proxy_destroy(struct rawlog_proxy *proxy)
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen const char *timestamp = t_strdup_printf("%ld.%06lu ",
8b12e7b44abca3bd51a1c46e19ca504f3b55e723Timo Sirainen for (i = 0; i < size; i++) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen ret = write_full(fd, str_data(str), str_len(str));
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainenstatic int proxy_write_data(struct rawlog_proxy *proxy, int fd,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if ((proxy->flags & RAWLOG_FLAG_LOG_BOUNDARIES) != 0) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if ((proxy->flags & RAWLOG_FLAG_LOG_TIMESTAMPS) != 0) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (write_with_timestamps(fd, prev_lf, data, size) < 0)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if ((proxy->flags & RAWLOG_FLAG_LOG_BOUNDARIES) != 0) {
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainenstatic void proxy_write_in(struct rawlog_proxy *proxy,
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen if (proxy_write_data(proxy, proxy->fd_in, &proxy->prev_lf_in,
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen /* failed, disable logging */
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainenstatic void proxy_write_out(struct rawlog_proxy *proxy,
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen if (proxy_write_data(proxy, proxy->fd_out, &proxy->prev_lf_out,
55773f17bccf6361d6599ffcbe072d7c9fe205bfTimo Sirainen /* failed, disable logging */
5df33e9ee65eec194105b338c55dedbf8422f695Timo Sirainenstatic void server_input(struct rawlog_proxy *proxy)
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen if (o_stream_get_buffer_used_size(proxy->client_output) >
55773f17bccf6361d6599ffcbe072d7c9fe205bfTimo Sirainen /* client's output buffer is already quite full.
55773f17bccf6361d6599ffcbe072d7c9fe205bfTimo Sirainen don't send more until we're below threshold. */
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen ret = net_receive(proxy->server_fd, buf, sizeof(buf));
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen (void)o_stream_send(proxy->client_output, buf, ret);
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen } else if (ret <= 0)
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainenstatic void client_input(struct rawlog_proxy *proxy)
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen if (o_stream_get_buffer_used_size(proxy->server_output) >
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen /* proxy's output buffer is already quite full.
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen don't send more until we're below threshold. */
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen ret = net_receive(proxy->client_in_fd, buf, sizeof(buf));
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen (void)o_stream_send(proxy->server_output, buf, ret);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen } else if (ret < 0)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic int server_output(struct rawlog_proxy *proxy)
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen if (o_stream_flush(proxy->server_output) < 0) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen o_stream_get_buffer_used_size(proxy->server_output) <
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen /* there's again space in proxy's output buffer, so we can
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen read more from client. */
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen proxy->client_io = io_add(proxy->client_in_fd, IO_READ,
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainenstatic int client_output(struct rawlog_proxy *proxy)
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen if (o_stream_flush(proxy->client_output) < 0) {
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen o_stream_get_buffer_used_size(proxy->client_output) <
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen /* there's again space in client's output buffer, so we can
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen read more from proxy. */
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen io_add(proxy->server_fd, IO_READ, server_input, proxy);
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainenstatic void proxy_open_logs(struct rawlog_proxy *proxy, const char *path)
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen if (strftime(timestamp, sizeof(timestamp), "%Y%m%d-%H%M%S", tm) <= 0)
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen if ((proxy->flags & RAWLOG_FLAG_LOG_INPUT) != 0) {
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen fname = t_strdup_printf("%s/%s-%s.in", path, timestamp,
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen proxy->fd_in = open(fname, O_CREAT|O_EXCL|O_WRONLY, 0600);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen i_error("rawlog_open: open() failed for %s: %m", fname);
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen if ((proxy->flags & RAWLOG_FLAG_LOG_OUTPUT) != 0) {
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen fname = t_strdup_printf("%s/%s-%s.out", path, timestamp,
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen proxy->fd_out = open(fname, O_CREAT|O_EXCL|O_WRONLY, 0600);
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen i_error("rawlog_open: open() failed for %s: %m", fname);
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainenrawlog_proxy_create(int client_in_fd, int client_out_fd, int server_fd,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen proxy->server_output = o_stream_create_fd(server_fd, (size_t)-1, FALSE);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen proxy->server_io = io_add(server_fd, IO_READ, server_input, proxy);
644268f7848a7c4221146d0b11feb8ed5bbed233Timo Sirainen o_stream_set_flush_callback(proxy->server_output, server_output, proxy);
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen o_stream_create_fd(client_out_fd, (size_t)-1, FALSE);
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen proxy->client_io = io_add(proxy->client_in_fd, IO_READ,
d2b94d25f842cd1b7acaf4dd7de858f7c6a821c9Timo Sirainen o_stream_set_flush_callback(proxy->client_output, client_output, proxy);
38d7db318188c4ac9cdc8c6cdb936b36a5258e19Timo Sirainen proxy->prev_lf_in = proxy->prev_lf_out = TRUE;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic void rawlog_open(enum rawlog_flags flags)
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen /* see if we want rawlog */
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen path = t_strconcat(home, "/dovecot.rawlog", NULL);
d2b94d25f842cd1b7acaf4dd7de858f7c6a821c9Timo Sirainen i_info("rawlog: %s is not a directory", path);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen /* we'll chroot soon. skip over the chroot in the path. */
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen if (socketpair(AF_UNIX, SOCK_STREAM, 0, sfd) < 0)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen process_title_set(t_strdup_printf("[%s:%s rawlog]", getenv("USER"),
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen rawlog_proxy_create(0, 1, sfd[0], path, flags);
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen flags = RAWLOG_FLAG_LOG_INPUT | RAWLOG_FLAG_LOG_OUTPUT;
7a54d58280aad8a64f266c61273ea1e8dff511a3Timo Sirainen while ((c = getopt(argc, argv, "iobt")) > 0) {
e54512a5189192fe72d1e2c53927c98c5ac920b4Timo Sirainen i_fatal("Usage: rawlog [-i | -o] [-b] [-t] <binary> <arguments>");
dd0dea1fdd913a04bae16e82dd66d67571a5f6c2Timo Sirainen /* hide the executable path, it's ugly */
49be238e250e99af8c69321264a461d8f6ceef62Timo Sirainen i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m", executable);
8b5b1f6cb19253dfd7821fcef8e9b7e95e6caf3aTimo Sirainen /* not reached */