Mercurial > masqmail
comparison src/listen.c @ 10:26e34ae9a3e3
changed indention and line wrapping to a more consistent style
author | meillo@marmaro.de |
---|---|
date | Mon, 27 Oct 2008 16:23:10 +0100 |
parents | 08114f7dcc23 |
children | f671821d8222 |
comparison
equal
deleted
inserted
replaced
9:31cc8a89cb74 | 10:26e34ae9a3e3 |
---|---|
20 #include <sys/wait.h> | 20 #include <sys/wait.h> |
21 #include <sys/types.h> | 21 #include <sys/types.h> |
22 | 22 |
23 static int volatile sighup_seen = 0; | 23 static int volatile sighup_seen = 0; |
24 | 24 |
25 static | 25 static void |
26 void sighup_handler(int sig) | 26 sighup_handler(int sig) |
27 { | 27 { |
28 sighup_seen = 1; | 28 sighup_seen = 1; |
29 signal(SIGHUP, sighup_handler); | 29 signal(SIGHUP, sighup_handler); |
30 } | 30 } |
31 | 31 |
32 static | 32 static void |
33 void sigchld_handler(int sig) | 33 sigchld_handler(int sig) |
34 { | 34 { |
35 pid_t pid; | 35 pid_t pid; |
36 int status; | 36 int status; |
37 | 37 |
38 pid = waitpid(0, &status, 0); | 38 pid = waitpid(0, &status, 0); |
39 if(pid > 0){ | 39 if (pid > 0) { |
40 if(WEXITSTATUS(status) != EXIT_SUCCESS) | 40 if (WEXITSTATUS(status) != EXIT_SUCCESS) |
41 logwrite(LOG_WARNING, "process %d exited with %d\n", | 41 logwrite(LOG_WARNING, "process %d exited with %d\n", pid, WEXITSTATUS(status)); |
42 pid, WEXITSTATUS(status)); | 42 if (WIFSIGNALED(status)) |
43 if(WIFSIGNALED(status)) | 43 logwrite(LOG_WARNING, "process with pid %d got signal: %d\n", pid, WTERMSIG(status)); |
44 logwrite(LOG_WARNING, | 44 } |
45 "process with pid %d got signal: %d\n", | 45 signal(SIGCHLD, sigchld_handler); |
46 pid, WTERMSIG(status)); | |
47 } | |
48 signal(SIGCHLD, sigchld_handler); | |
49 } | 46 } |
50 | 47 |
51 #ifdef ENABLE_SMTP_SERVER | 48 #ifdef ENABLE_SMTP_SERVER |
52 void accept_connect(int listen_sock, int sock, struct sockaddr_in* sock_addr) | 49 void |
53 { | 50 accept_connect(int listen_sock, int sock, struct sockaddr_in *sock_addr) |
54 pid_t pid; | 51 { |
55 int dup_sock = dup(sock); | 52 pid_t pid; |
56 FILE *out, *in; | 53 int dup_sock = dup(sock); |
57 gchar *rem_host; | 54 FILE *out, *in; |
58 gchar *ident = NULL; | 55 gchar *rem_host; |
59 | 56 gchar *ident = NULL; |
60 rem_host = g_strdup(inet_ntoa(sock_addr->sin_addr)); | 57 |
58 rem_host = g_strdup(inet_ntoa(sock_addr->sin_addr)); | |
61 #ifdef ENABLE_IDENT | 59 #ifdef ENABLE_IDENT |
62 { | 60 { |
63 gchar *id = NULL; | 61 gchar *id = NULL; |
64 if((id = (gchar *)ident_id(sock, 60))){ | 62 if ((id = (gchar *) ident_id(sock, 60))) { |
65 ident = g_strdup(id); | 63 ident = g_strdup(id); |
66 } | 64 } |
67 logwrite(LOG_NOTICE, "connect from host %s, port %hd ident=%s\n", | 65 logwrite(LOG_NOTICE, "connect from host %s, port %hd ident=%s\n", rem_host, |
68 rem_host, | 66 ntohs(sock_addr->sin_port), ident ? ident : "(unknown)"); |
69 ntohs (sock_addr->sin_port), | 67 } |
70 ident ? ident : "(unknown)"); | |
71 } | |
72 #else | 68 #else |
73 logwrite(LOG_NOTICE, "connect from host %s, port %hd\n", | 69 logwrite(LOG_NOTICE, "connect from host %s, port %hd\n", rem_host, ntohs(sock_addr->sin_port)); |
74 rem_host, | 70 #endif |
75 ntohs (sock_addr->sin_port)); | 71 |
76 #endif | 72 // start child for connection: |
77 | 73 signal(SIGCHLD, sigchld_handler); |
78 // start child for connection: | 74 pid = fork(); |
79 signal(SIGCHLD, sigchld_handler); | 75 if (pid == 0) { |
80 pid = fork(); | 76 close(listen_sock); |
81 if(pid == 0){ | 77 out = fdopen(sock, "w"); |
82 close(listen_sock); | 78 in = fdopen(dup_sock, "r"); |
83 out = fdopen(sock, "w"); | 79 |
84 in = fdopen(dup_sock, "r"); | 80 smtp_in(in, out, rem_host, ident); |
85 | 81 |
86 smtp_in(in, out, rem_host, ident); | 82 _exit(EXIT_SUCCESS); |
87 | 83 } else if (pid < 0) { |
88 _exit(EXIT_SUCCESS); | 84 logwrite(LOG_WARNING, "could not fork for incoming smtp connection: %s\n", strerror(errno)); |
89 }else if(pid < 0){ | 85 } |
90 logwrite(LOG_WARNING, "could not fork for incoming smtp connection: %s\n", | |
91 strerror(errno)); | |
92 } | |
93 | |
94 #ifdef ENABLE_IDENT | 86 #ifdef ENABLE_IDENT |
95 if(ident != NULL) g_free(ident); | 87 if (ident != NULL) |
96 #endif | 88 g_free(ident); |
97 | 89 #endif |
98 close(sock); | 90 |
99 close(dup_sock); | 91 close(sock); |
100 } | 92 close(dup_sock); |
101 #endif /*ifdef ENABLE_SMTP_SERVER*/ | 93 } |
102 | 94 #endif /*ifdef ENABLE_SMTP_SERVER */ |
103 void listen_port(GList *iface_list, gint qival, char *argv[]) | 95 |
104 { | 96 void |
105 int i; | 97 listen_port(GList * iface_list, gint qival, char *argv[]) |
106 fd_set active_fd_set, read_fd_set; | 98 { |
107 struct timeval tm; | 99 int i; |
108 time_t time_before, time_now; | 100 fd_set active_fd_set, read_fd_set; |
109 struct sockaddr_in clientname; | 101 struct timeval tm; |
110 size_t size; | 102 time_t time_before, time_now; |
111 GList *node, *node_next; | 103 struct sockaddr_in clientname; |
112 int sel_ret; | 104 size_t size; |
113 | 105 GList *node, *node_next; |
114 /* Create the sockets and set them up to accept connections. */ | 106 int sel_ret; |
115 FD_ZERO (&active_fd_set); | 107 |
108 /* Create the sockets and set them up to accept connections. */ | |
109 FD_ZERO(&active_fd_set); | |
116 #ifdef ENABLE_SMTP_SERVER | 110 #ifdef ENABLE_SMTP_SERVER |
117 for(node = g_list_first(iface_list); | 111 for (node = g_list_first(iface_list); node; node = node_next) { |
118 node; | 112 interface *iface = (interface *) (node->data); |
119 node = node_next){ | 113 int sock; |
120 interface *iface = (interface *)(node->data); | 114 |
121 int sock; | 115 node_next = g_list_next(node); |
122 | 116 if ((sock = make_server_socket(iface)) < 0) { |
123 node_next=g_list_next(node); | 117 iface_list = g_list_remove_link(iface_list, node); |
124 if ((sock = make_server_socket (iface))<0){ | 118 g_list_free_1(node); |
125 iface_list= g_list_remove_link(iface_list, node); | 119 continue; |
126 g_list_free_1(node); | 120 } |
127 continue; | 121 if (listen(sock, 1) < 0) { |
128 } | 122 logwrite(LOG_ALERT, "listen: (terminating): %s\n", strerror(errno)); |
129 if (listen (sock, 1) < 0){ | 123 exit(EXIT_FAILURE); |
130 logwrite(LOG_ALERT, "listen: (terminating): %s\n", strerror(errno)); | 124 } |
131 exit (EXIT_FAILURE); | 125 logwrite(LOG_NOTICE, "listening on interface %s:%d\n", iface->address, iface->port); |
132 } | 126 DEBUG(5) debugf("sock = %d\n", sock); |
133 logwrite(LOG_NOTICE, "listening on interface %s:%d\n", | 127 FD_SET(sock, &active_fd_set); |
134 iface->address, iface->port); | 128 } |
135 DEBUG(5) debugf("sock = %d\n", sock); | 129 #endif |
136 FD_SET (sock, &active_fd_set); | 130 |
137 } | 131 /* setup handler for HUP signal: */ |
138 #endif | 132 signal(SIGHUP, sighup_handler); |
139 | 133 signal(SIGCHLD, sigchld_handler); |
140 /* setup handler for HUP signal: */ | 134 |
141 signal(SIGHUP, sighup_handler); | 135 /* now that we have our socket(s), |
142 signal(SIGCHLD, sigchld_handler); | 136 we can give up root privileges */ |
143 | 137 if (!conf.run_as_user) { |
144 /* now that we have our socket(s), | 138 if (setegid(conf.mail_gid) != 0) { |
145 we can give up root privileges */ | 139 logwrite(LOG_ALERT, "could not change gid to %d: %s\n", conf.mail_gid, strerror(errno)); |
146 if(!conf.run_as_user){ | 140 exit(EXIT_FAILURE); |
147 if(setegid(conf.mail_gid) != 0){ | 141 } |
148 logwrite(LOG_ALERT, "could not change gid to %d: %s\n", | 142 if (seteuid(conf.mail_uid) != 0) { |
149 conf.mail_gid, strerror(errno)); | 143 logwrite(LOG_ALERT, "could not change uid to %d: %s\n", conf.mail_uid, strerror(errno)); |
150 exit(EXIT_FAILURE); | 144 exit(EXIT_FAILURE); |
151 } | 145 } |
152 if(seteuid(conf.mail_uid) != 0){ | 146 } |
153 logwrite(LOG_ALERT, "could not change uid to %d: %s\n", | 147 |
154 conf.mail_uid, strerror(errno)); | 148 /* sel_ret = 0; */ |
155 exit(EXIT_FAILURE); | 149 time(&time_before); |
156 } | 150 time_before -= qival; |
157 } | 151 sel_ret = -1; |
158 | 152 |
159 /* sel_ret = 0;*/ | 153 while (1) { |
160 time(&time_before); | 154 |
161 time_before -= qival; | 155 /* if we were interrupted by an incoming connection (or a signal) |
162 sel_ret = -1; | 156 we have to recalculate the time until the next queue run should |
163 | 157 occur. select may put a value into tm, but doc for select() says |
164 while (1){ | 158 we should not use it. */ |
165 | 159 if (qival > 0) { |
166 /* if we were interrupted by an incoming connection (or a signal) | 160 time(&time_now); |
167 we have to recalculate the time until the next queue run should | 161 if (sel_ret == 0) { /* we are either just starting or did a queue run */ |
168 occur. select may put a value into tm, but doc for select() says | 162 tm.tv_sec = qival; |
169 we should not use it.*/ | 163 tm.tv_usec = 0; |
170 if(qival > 0){ | 164 time_before = time_now; |
171 time(&time_now); | 165 } else { |
172 if(sel_ret == 0){ /* we are either just starting or did a queue run */ | 166 tm.tv_sec = qival - (time_now - time_before); |
173 tm.tv_sec = qival; | 167 tm.tv_usec = 0; |
174 tm.tv_usec = 0; | 168 |
175 time_before = time_now; | 169 /* race condition, very unlikely (but possible): */ |
176 }else{ | 170 if (tm.tv_sec < 0) |
177 tm.tv_sec = qival - (time_now - time_before); | 171 tm.tv_sec = 0; |
178 tm.tv_usec = 0; | 172 } |
179 | 173 } |
180 /* race condition, very unlikely (but possible): */ | 174 /* Block until input arrives on one or more active sockets, |
181 if(tm.tv_sec < 0) | 175 or signal arrives, |
182 tm.tv_sec = 0; | 176 or queuing interval time elapsed (if qival > 0) */ |
183 } | 177 read_fd_set = active_fd_set; |
184 } | 178 if ((sel_ret = select(FD_SETSIZE, &read_fd_set, NULL, NULL, qival > 0 ? &tm : NULL)) < 0) { |
185 /* Block until input arrives on one or more active sockets, | 179 if (errno != EINTR) { |
186 or signal arrives, | 180 logwrite(LOG_ALERT, "select: (terminating): %s\n", strerror(errno)); |
187 or queuing interval time elapsed (if qival > 0) */ | 181 exit(EXIT_FAILURE); |
188 read_fd_set = active_fd_set; | 182 } else { |
189 if ((sel_ret = select(FD_SETSIZE, &read_fd_set, NULL, NULL, | 183 if (sighup_seen) { |
190 qival > 0 ? &tm : NULL)) < 0){ | 184 logwrite(LOG_NOTICE, "HUP signal received. Restarting daemon\n"); |
191 if(errno != EINTR){ | 185 |
192 logwrite(LOG_ALERT, "select: (terminating): %s\n", strerror(errno)); | 186 for (i = 0; i < FD_SETSIZE; i++) |
193 exit (EXIT_FAILURE); | 187 if (FD_ISSET(i, &active_fd_set)) |
194 }else{ | 188 close(i); |
195 if(sighup_seen){ | 189 |
196 logwrite(LOG_NOTICE, "HUP signal received. Restarting daemon\n"); | 190 execv(argv[0], &(argv[0])); |
197 | 191 logwrite(LOG_ALERT, "restarting failed: %s\n", strerror(errno)); |
198 for(i = 0; i < FD_SETSIZE; i++) | 192 exit(EXIT_FAILURE); |
199 if(FD_ISSET(i, &active_fd_set)) | 193 } |
200 close(i); | 194 } |
201 | 195 } else if (sel_ret > 0) { |
202 execv(argv[0], &(argv[0])); | |
203 logwrite(LOG_ALERT, "restarting failed: %s\n", strerror(errno)); | |
204 exit(EXIT_FAILURE); | |
205 } | |
206 } | |
207 } | |
208 else if(sel_ret > 0){ | |
209 #ifdef ENABLE_SMTP_SERVER | 196 #ifdef ENABLE_SMTP_SERVER |
210 for(i = 0; i < FD_SETSIZE; i++){ | 197 for (i = 0; i < FD_SETSIZE; i++) { |
211 if (FD_ISSET (i, &read_fd_set)){ | 198 if (FD_ISSET(i, &read_fd_set)) { |
212 int sock = i; | 199 int sock = i; |
213 int new; | 200 int new; |
214 size = sizeof (clientname); | 201 size = sizeof(clientname); |
215 new = accept (sock, | 202 new = accept(sock, (struct sockaddr *) &clientname, &size); |
216 (struct sockaddr *) &clientname, | 203 if (new < 0) { |
217 &size); | 204 logwrite(LOG_ALERT, "accept: (ignoring): %s\n", strerror(errno)); |
218 if (new < 0){ | 205 } else |
219 logwrite(LOG_ALERT, "accept: (ignoring): %s\n", | 206 accept_connect(sock, new, &clientname); |
220 strerror(errno)); | 207 } |
221 }else | 208 } |
222 accept_connect(sock, new, &clientname); | |
223 } | |
224 } | |
225 #else | 209 #else |
226 ; | 210 ; |
227 #endif | 211 #endif |
228 }else{ | 212 } else { |
229 /* If select returns 0, the interval time has elapsed. | 213 /* If select returns 0, the interval time has elapsed. |
230 We start a new queue runner process */ | 214 We start a new queue runner process */ |
231 int pid; | 215 int pid; |
232 signal(SIGCHLD, sigchld_handler); | 216 signal(SIGCHLD, sigchld_handler); |
233 if((pid = fork()) == 0){ | 217 if ((pid = fork()) == 0) { |
234 queue_run(); | 218 queue_run(); |
235 | 219 |
236 _exit(EXIT_SUCCESS); | 220 _exit(EXIT_SUCCESS); |
237 } | 221 } else if (pid < 0) { |
238 else if(pid < 0){ | 222 logwrite(LOG_ALERT, "could not fork for queue run"); |
239 logwrite(LOG_ALERT, "could not fork for queue run"); | 223 } |
240 } | 224 } |
241 } | 225 } |
242 } | 226 } |
243 } |