masqmail

annotate src/listen.c @ 378:5781ba87df95

Removed ident. This had been discussed on the mailing list in Oct 2011. Ident is hardly useful in typical setups for masqmail. Probably Oliver had used it in his setup; that would make sense. Now, I know of nobody who needs it.
author markus schnalke <meillo@marmaro.de>
date Sat, 14 Jan 2012 21:36:58 +0100
parents b27f66555ba8
children a2909de1818b
rev   line source
meillo@367 1 /*
meillo@367 2 ** MasqMail
meillo@367 3 ** Copyright (C) 1999/2000 Oliver Kurth
meillo@367 4 **
meillo@367 5 ** This program is free software; you can redistribute it and/or modify
meillo@367 6 ** it under the terms of the GNU General Public License as published by
meillo@367 7 ** the Free Software Foundation; either version 2 of the License, or
meillo@367 8 ** (at your option) any later version.
meillo@367 9 **
meillo@367 10 ** This program is distributed in the hope that it will be useful,
meillo@367 11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
meillo@367 12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
meillo@367 13 ** GNU General Public License for more details.
meillo@367 14 **
meillo@367 15 ** You should have received a copy of the GNU General Public License
meillo@367 16 ** along with this program; if not, write to the Free Software
meillo@367 17 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
meillo@0 18 */
meillo@0 19
meillo@0 20 #include <sys/wait.h>
meillo@0 21 #include <sys/types.h>
meillo@0 22
meillo@15 23 #include "masqmail.h"
meillo@15 24
meillo@0 25 static int volatile sighup_seen = 0;
meillo@0 26
meillo@10 27 static void
meillo@10 28 sighup_handler(int sig)
meillo@0 29 {
meillo@10 30 sighup_seen = 1;
meillo@10 31 signal(SIGHUP, sighup_handler);
meillo@0 32 }
meillo@0 33
meillo@10 34 static void
meillo@10 35 sigchld_handler(int sig)
meillo@0 36 {
meillo@10 37 pid_t pid;
meillo@10 38 int status;
meillo@10 39
meillo@10 40 pid = waitpid(0, &status, 0);
meillo@10 41 if (pid > 0) {
meillo@262 42 if (WEXITSTATUS(status) != 0)
meillo@10 43 logwrite(LOG_WARNING, "process %d exited with %d\n", pid, WEXITSTATUS(status));
meillo@10 44 if (WIFSIGNALED(status))
meillo@10 45 logwrite(LOG_WARNING, "process with pid %d got signal: %d\n", pid, WTERMSIG(status));
meillo@10 46 }
meillo@10 47 signal(SIGCHLD, sigchld_handler);
meillo@0 48 }
meillo@0 49
meillo@10 50 void
meillo@10 51 accept_connect(int listen_sock, int sock, struct sockaddr_in *sock_addr)
meillo@0 52 {
meillo@10 53 pid_t pid;
meillo@10 54 int dup_sock = dup(sock);
meillo@10 55 FILE *out, *in;
meillo@10 56 gchar *rem_host;
meillo@10 57 gchar *ident = NULL;
meillo@0 58
meillo@10 59 rem_host = g_strdup(inet_ntoa(sock_addr->sin_addr));
meillo@10 60 logwrite(LOG_NOTICE, "connect from host %s, port %hd\n", rem_host, ntohs(sock_addr->sin_port));
meillo@0 61
meillo@207 62 /* start child for connection: */
meillo@10 63 signal(SIGCHLD, sigchld_handler);
meillo@10 64 pid = fork();
meillo@10 65 if (pid == 0) {
meillo@10 66 close(listen_sock);
meillo@10 67 out = fdopen(sock, "w");
meillo@10 68 in = fdopen(dup_sock, "r");
meillo@0 69
meillo@10 70 smtp_in(in, out, rem_host, ident);
meillo@0 71
meillo@262 72 _exit(0);
meillo@10 73 } else if (pid < 0) {
meillo@10 74 logwrite(LOG_WARNING, "could not fork for incoming smtp connection: %s\n", strerror(errno));
meillo@10 75 }
meillo@0 76
meillo@10 77 close(sock);
meillo@10 78 close(dup_sock);
meillo@0 79 }
meillo@0 80
meillo@10 81 void
meillo@366 82 listen_port(GList *iface_list, gint qival, char *argv[])
meillo@0 83 {
meillo@10 84 int i;
meillo@10 85 fd_set active_fd_set, read_fd_set;
meillo@10 86 struct timeval tm;
meillo@10 87 time_t time_before, time_now;
meillo@10 88 struct sockaddr_in clientname;
meillo@10 89 size_t size;
meillo@10 90 GList *node, *node_next;
meillo@10 91 int sel_ret;
meillo@0 92
meillo@10 93 /* Create the sockets and set them up to accept connections. */
meillo@10 94 FD_ZERO(&active_fd_set);
meillo@10 95 for (node = g_list_first(iface_list); node; node = node_next) {
meillo@10 96 interface *iface = (interface *) (node->data);
meillo@10 97 int sock;
meillo@0 98
meillo@10 99 node_next = g_list_next(node);
meillo@10 100 if ((sock = make_server_socket(iface)) < 0) {
meillo@10 101 iface_list = g_list_remove_link(iface_list, node);
meillo@10 102 g_list_free_1(node);
meillo@10 103 continue;
meillo@10 104 }
meillo@10 105 if (listen(sock, 1) < 0) {
meillo@10 106 logwrite(LOG_ALERT, "listen: (terminating): %s\n", strerror(errno));
meillo@262 107 exit(1);
meillo@10 108 }
meillo@10 109 logwrite(LOG_NOTICE, "listening on interface %s:%d\n", iface->address, iface->port);
meillo@10 110 DEBUG(5) debugf("sock = %d\n", sock);
meillo@10 111 FD_SET(sock, &active_fd_set);
meillo@10 112 }
meillo@0 113
meillo@10 114 /* setup handler for HUP signal: */
meillo@10 115 signal(SIGHUP, sighup_handler);
meillo@10 116 signal(SIGCHLD, sigchld_handler);
meillo@0 117
meillo@15 118 /* now that we have our socket(s), we can give up root privileges */
meillo@10 119 if (!conf.run_as_user) {
meillo@332 120 set_euidgid(conf.mail_uid, conf.mail_gid, NULL, NULL);
meillo@10 121 }
meillo@0 122
meillo@10 123 /* sel_ret = 0; */
meillo@10 124 time(&time_before);
meillo@10 125 time_before -= qival;
meillo@10 126 sel_ret = -1;
meillo@0 127
meillo@10 128 while (1) {
meillo@0 129
meillo@367 130 /*
meillo@367 131 ** if we were interrupted by an incoming connection (or a
meillo@367 132 ** signal) we have to recalculate the time until the next
meillo@367 133 ** queue run should occur. select may put a value into tm,
meillo@367 134 ** but doc for select() says we should not use it.
meillo@367 135 */
meillo@10 136 if (qival > 0) {
meillo@10 137 time(&time_now);
meillo@10 138 if (sel_ret == 0) { /* we are either just starting or did a queue run */
meillo@10 139 tm.tv_sec = qival;
meillo@10 140 tm.tv_usec = 0;
meillo@10 141 time_before = time_now;
meillo@10 142 } else {
meillo@10 143 tm.tv_sec = qival - (time_now - time_before);
meillo@10 144 tm.tv_usec = 0;
meillo@0 145
meillo@10 146 /* race condition, very unlikely (but possible): */
meillo@10 147 if (tm.tv_sec < 0)
meillo@10 148 tm.tv_sec = 0;
meillo@10 149 }
meillo@10 150 }
meillo@367 151 /*
meillo@367 152 ** Block until input arrives on one or more active sockets,
meillo@367 153 ** or signal arrives, or queuing interval time elapsed
meillo@367 154 ** (if qival > 0)
meillo@367 155 */
meillo@10 156 read_fd_set = active_fd_set;
meillo@10 157 if ((sel_ret = select(FD_SETSIZE, &read_fd_set, NULL, NULL, qival > 0 ? &tm : NULL)) < 0) {
meillo@10 158 if (errno != EINTR) {
meillo@10 159 logwrite(LOG_ALERT, "select: (terminating): %s\n", strerror(errno));
meillo@262 160 exit(1);
meillo@10 161 } else {
meillo@10 162 if (sighup_seen) {
meillo@10 163 logwrite(LOG_NOTICE, "HUP signal received. Restarting daemon\n");
meillo@0 164
meillo@10 165 for (i = 0; i < FD_SETSIZE; i++)
meillo@10 166 if (FD_ISSET(i, &active_fd_set))
meillo@10 167 close(i);
meillo@0 168
meillo@10 169 execv(argv[0], &(argv[0]));
meillo@10 170 logwrite(LOG_ALERT, "restarting failed: %s\n", strerror(errno));
meillo@262 171 exit(1);
meillo@10 172 }
meillo@10 173 }
meillo@10 174 } else if (sel_ret > 0) {
meillo@10 175 for (i = 0; i < FD_SETSIZE; i++) {
meillo@10 176 if (FD_ISSET(i, &read_fd_set)) {
meillo@10 177 int sock = i;
meillo@10 178 int new;
meillo@10 179 size = sizeof(clientname);
meillo@10 180 new = accept(sock, (struct sockaddr *) &clientname, &size);
meillo@10 181 if (new < 0) {
meillo@10 182 logwrite(LOG_ALERT, "accept: (ignoring): %s\n", strerror(errno));
meillo@10 183 } else
meillo@10 184 accept_connect(sock, new, &clientname);
meillo@10 185 }
meillo@10 186 }
meillo@10 187 } else {
meillo@367 188 /*
meillo@367 189 ** If select returns 0, the interval time has elapsed.
meillo@367 190 ** We start a new queue runner process
meillo@367 191 */
meillo@10 192 int pid;
meillo@10 193 signal(SIGCHLD, sigchld_handler);
meillo@10 194 if ((pid = fork()) == 0) {
meillo@10 195 queue_run();
meillo@10 196
meillo@262 197 _exit(0);
meillo@10 198 } else if (pid < 0) {
meillo@10 199 logwrite(LOG_ALERT, "could not fork for queue run");
meillo@10 200 }
meillo@10 201 }
meillo@0 202 }
meillo@0 203 }