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 }