master.c revision 45312f52ff3a3d4c137447be4c7556500c2f8bf2
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
8e361d2906b0e44f7175a20981f8d2280645b58bTimo Sirainenstatic unsigned int master_tag_counter;
8e361d2906b0e44f7175a20981f8d2280645b58bTimo Sirainenstatic unsigned int master_pos;
d6af1e63bc7824f1cc5b9b73a1c5f8f8789788d6Timo Sirainenstatic char master_buf[sizeof(struct master_login_reply)];
d6af1e63bc7824f1cc5b9b73a1c5f8f8789788d6Timo Sirainenstatic void client_call_master_callback(struct client *client,
d56384d5226c8860079d0d0b08b83404e8c42986Timo Sirainenstatic void request_handle(struct master_login_reply *reply)
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen if (reply->tag == 0 && !process_per_connection) {
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen /* this means we have to start listening again.
d6af1e63bc7824f1cc5b9b73a1c5f8f8789788d6Timo Sirainen we've reached maximum number of login processes. */
d6af1e63bc7824f1cc5b9b73a1c5f8f8789788d6Timo Sirainen client = hash_table_lookup(master_requests, POINTER_CAST(reply->tag));
d6af1e63bc7824f1cc5b9b73a1c5f8f8789788d6Timo Sirainen i_fatal("Master sent reply with unknown tag %u", reply->tag);
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen hash_table_remove(master_requests, POINTER_CAST(reply->tag));
6a9f9a5101b665fd2ef80c9e048a5eace78e01efTimo Sirainen /* NOTE: client may be destroyed now */
6a9f9a5101b665fd2ef80c9e048a5eace78e01efTimo Sirainenvoid master_request_login(struct client *client, master_callback_t *callback,
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen const unsigned char *data;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen reply.status = MASTER_LOGIN_STATUS_INTERNAL_ERROR;
1f57716285d4c5bc9bf2fd5569e3c85fd496afd9Timo Sirainen data = i_stream_get_data(client->input, &size);
1f57716285d4c5bc9bf2fd5569e3c85fd496afd9Timo Sirainen cmd_tag_size = client->auth_command_tag == NULL ? 0 :
1f57716285d4c5bc9bf2fd5569e3c85fd496afd9Timo Sirainen buf = buffer_create_dynamic(pool_datastack_create(),
1f57716285d4c5bc9bf2fd5569e3c85fd496afd9Timo Sirainen buffer_write(buf, sizeof(*req), client->auth_command_tag, cmd_tag_size);
1f57716285d4c5bc9bf2fd5569e3c85fd496afd9Timo Sirainen buffer_write(buf, sizeof(*req) + cmd_tag_size, data, size);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen req = buffer_get_space_unsafe(buf, 0, sizeof(*req));
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen#if (LOGIN_MAX_INBUF_SIZE*2) != MASTER_LOGIN_MAX_DATA_SIZE
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen i_assert(req->data_size <= LOGIN_MAX_INBUF_SIZE);
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen ret = fd_send(master_fd, client->fd, buf->data, buf->used);
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen i_fatal("fd_send(%d) failed: %m", client->fd);
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen hash_table_insert(master_requests, POINTER_CAST(req->tag), client);
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainenvoid master_request_abort(struct client *client)
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen /* we're still going to get the reply from the master, so just
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen remember that we want to ignore it */
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen hash_table_update(master_requests, POINTER_CAST(client->master_tag),
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen reply.status = MASTER_LOGIN_STATUS_INTERNAL_ERROR;
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainenvoid master_notify_state_change(enum master_login_state state)
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen /* sending -1 as fd does the notification */
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen if (fd_send(master_fd, -1, &req, sizeof(req)) != sizeof(req))
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen /* may call this function again through main_unref() */
switch (fork()) {
if (setsid() < 0)
const char *line;
env_clean();
path);
return fd;
int ret;
if (ret < 0) {
master_close();
master_pos = 0;
main_ref();
master_pos = 0;
void master_deinit(void)