masqmail

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