* examples/Makefile.am: add echosrv.c.
* examples/echosrv.c: New file. * include/mailutils/Makefile.am: Add server.h. * include/mailutils/server.h: New file. * include/mailutils/acl.h (mu_acl_t): Move to types.hin * include/mailutils/types.hin (mu_acl_t,mu_server_t) (mu_tcp_server_t): New types. * mailbox/Makefile.am: Add server.c and tcpsrv.c. * mailbox/server.c: New file. * mailbox/tcpsrv.c: New file. * mailbox/acl.c: Include <sys/wait.h> Rename all `sin' and `sun' to avoid name clashes. * mailbox/errors (MU_ERR_LOCK_EXT_FAIL): Do not abbreviate anything in error description.
Showing
12 changed files
with
946 additions
and
15 deletions
1 | 2007-12-09 Sergey Poznyakoff <gray@gnu.org.ua> | 1 | 2007-12-09 Sergey Poznyakoff <gray@gnu.org.ua> |
2 | 2 | ||
3 | * examples/Makefile.am: add echosrv.c. | ||
4 | * examples/echosrv.c: New file. | ||
5 | * include/mailutils/Makefile.am: Add server.h. | ||
6 | * include/mailutils/server.h: New file. | ||
7 | * include/mailutils/acl.h (mu_acl_t): Move to types.hin | ||
8 | * include/mailutils/types.hin (mu_acl_t,mu_server_t) | ||
9 | (mu_tcp_server_t): New types. | ||
10 | * mailbox/Makefile.am: Add server.c and tcpsrv.c. | ||
11 | * mailbox/server.c: New file. | ||
12 | * mailbox/tcpsrv.c: New file. | ||
13 | * mailbox/acl.c: Include <sys/wait.h> | ||
14 | Rename all `sin' and `sun' to avoid name clashes. | ||
15 | * mailbox/errors (MU_ERR_LOCK_EXT_FAIL): Do not abbreviate | ||
16 | anything in error description. | ||
17 | |||
3 | * auth/ldap.c (_construct_attr_array): Use mu_vartab_* to expand | 18 | * auth/ldap.c (_construct_attr_array): Use mu_vartab_* to expand |
4 | filter. | 19 | filter. |
5 | * imap4d/preauth.c: Fix misleading comment. | 20 | * imap4d/preauth.c: Fix misleading comment. | ... | ... |
examples/echosrv.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2007 Free Software Foundation, Inc. | ||
3 | |||
4 | This library is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Lesser General Public | ||
6 | License as published by the Free Software Foundation; either | ||
7 | version 3 of the License, or (at your option) any later version. | ||
8 | |||
9 | This library is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General | ||
15 | Public License along with this library; If not, see | ||
16 | <http://www.gnu.org/licenses/>. */ | ||
17 | |||
18 | #ifdef HAVE_CONFIG_H | ||
19 | # include <config.h> | ||
20 | #endif | ||
21 | #include <stdlib.h> | ||
22 | #include <stdio.h> | ||
23 | #include <unistd.h> | ||
24 | #include <sys/time.h> | ||
25 | #include <sys/types.h> | ||
26 | #include <sys/socket.h> | ||
27 | #include <netinet/in.h> | ||
28 | #include <arpa/inet.h> | ||
29 | #include <signal.h> | ||
30 | #include <sys/wait.h> | ||
31 | #include "getopt.h" | ||
32 | |||
33 | #include <mailutils/mailutils.h> | ||
34 | #include <mailutils/server.h> | ||
35 | |||
36 | #define MU_ASSERT(expr) \ | ||
37 | do \ | ||
38 | { \ | ||
39 | int rc = expr; \ | ||
40 | if (rc) \ | ||
41 | { \ | ||
42 | mu_error (#expr " failed: %s", mu_strerror (rc)); \ | ||
43 | abort (); \ | ||
44 | } \ | ||
45 | } \ | ||
46 | while (0); | ||
47 | |||
48 | mu_server_t server; | ||
49 | |||
50 | int | ||
51 | echo_conn (int fd, struct sockaddr_in *s, void *server_data, void *call_data, | ||
52 | mu_tcp_server_t srv) | ||
53 | { | ||
54 | struct sockaddr_in srv_addr; | ||
55 | pid_t pid; | ||
56 | char *buf = NULL; | ||
57 | size_t size = 0; | ||
58 | FILE *in, *out; | ||
59 | |||
60 | mu_tcp_server_get_sockaddr (srv, &srv_addr); | ||
61 | |||
62 | pid = fork (); | ||
63 | if (pid == -1) | ||
64 | { | ||
65 | mu_error ("fork failed: %s", mu_strerror (errno)); | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | if (pid) | ||
70 | { | ||
71 | mu_diag_output (MU_DIAG_INFO, "%lu: opened connection %s:%d => %s:%d", | ||
72 | (unsigned long) pid, | ||
73 | inet_ntoa (srv_addr.sin_addr), ntohs (srv_addr.sin_port), | ||
74 | inet_ntoa (s->sin_addr), ntohs (s->sin_port)); | ||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | mu_tcp_server_shutdown (srv); | ||
79 | |||
80 | in = fdopen (fd, "r"); | ||
81 | out = fdopen (fd, "w"); | ||
82 | setvbuf (in, NULL, _IOLBF, 0); | ||
83 | setvbuf (out, NULL, _IOLBF, 0); | ||
84 | |||
85 | pid = getpid (); | ||
86 | while (getline (&buf, &size, in) > 0) | ||
87 | { | ||
88 | int len = strlen (buf); | ||
89 | if (len > 0) | ||
90 | { | ||
91 | buf[--len] = 0; | ||
92 | if (buf[len-1] == '\r') | ||
93 | buf[--len] = 0; | ||
94 | } | ||
95 | fprintf (out, "%lu: you said: \"%s\"\r\n", (unsigned long) pid, buf); | ||
96 | } | ||
97 | free (buf); | ||
98 | exit (0); | ||
99 | } | ||
100 | |||
101 | int | ||
102 | tcp_conn_handler (int fd, void *conn_data, void *server_data) | ||
103 | { | ||
104 | mu_tcp_server_t tcpsrv = (mu_tcp_server_t) conn_data; | ||
105 | int rc = mu_tcp_server_accept (tcpsrv, server_data); | ||
106 | if (rc && rc != EINTR) | ||
107 | { | ||
108 | mu_tcp_server_shutdown (tcpsrv); | ||
109 | return MU_SERVER_CLOSE_CONN; | ||
110 | } | ||
111 | return MU_SERVER_SUCCESS; | ||
112 | } | ||
113 | |||
114 | void | ||
115 | tcp_conn_free (void *conn_data, void *server_data) | ||
116 | { | ||
117 | mu_tcp_server_t tcpsrv = (mu_tcp_server_t) conn_data; | ||
118 | mu_tcp_server_destroy (&tcpsrv); | ||
119 | } | ||
120 | |||
121 | void | ||
122 | create_server (char *arg) | ||
123 | { | ||
124 | char *p, *q; | ||
125 | struct sockaddr_in s; | ||
126 | mu_tcp_server_t tcpsrv; | ||
127 | unsigned n; | ||
128 | |||
129 | p = strchr (arg, ':'); | ||
130 | if (!*p) | ||
131 | { | ||
132 | mu_error ("invalid specification: %s\n", arg); | ||
133 | exit (1); | ||
134 | } | ||
135 | *p++ = 0; | ||
136 | s.sin_family = AF_INET; | ||
137 | if (inet_aton (arg, &s.sin_addr) == 0) | ||
138 | { | ||
139 | mu_error ("invalid IP address: %s\n", arg); | ||
140 | exit (1); | ||
141 | } | ||
142 | n = strtoul (p, &q, 0); | ||
143 | if (*q) | ||
144 | { | ||
145 | mu_error ("invalid port number: %s\n", p); | ||
146 | exit (1); | ||
147 | } | ||
148 | s.sin_port = htons (n); | ||
149 | |||
150 | MU_ASSERT (mu_tcp_server_create (&tcpsrv, &s)); | ||
151 | MU_ASSERT (mu_tcp_server_open (tcpsrv)); | ||
152 | MU_ASSERT (mu_tcp_server_set_conn (tcpsrv, echo_conn)); | ||
153 | MU_ASSERT (mu_server_add_connection (server, | ||
154 | mu_tcp_server_get_fd (tcpsrv), | ||
155 | tcpsrv, | ||
156 | tcp_conn_handler, tcp_conn_free)); | ||
157 | } | ||
158 | |||
159 | static int cleanup_needed; | ||
160 | |||
161 | RETSIGTYPE | ||
162 | sig_child (int sig) | ||
163 | { | ||
164 | cleanup_needed = 1; | ||
165 | signal (sig, sig_child); | ||
166 | } | ||
167 | |||
168 | int | ||
169 | server_idle (void *server_data) | ||
170 | { | ||
171 | if (cleanup_needed) | ||
172 | { | ||
173 | int status; | ||
174 | pid_t pid; | ||
175 | |||
176 | cleanup_needed = 0; | ||
177 | while ((pid = waitpid (-1, &status, WNOHANG)) > 0) | ||
178 | { | ||
179 | if (WIFEXITED (status)) | ||
180 | mu_diag_output (MU_DIAG_INFO, "%lu: finished with code %d", | ||
181 | (unsigned long) pid, | ||
182 | WEXITSTATUS (status)); | ||
183 | else if (WIFSIGNALED (status)) | ||
184 | mu_diag_output (MU_DIAG_ERR, "%lu: terminated on signal %d", | ||
185 | (unsigned long) pid, | ||
186 | WTERMSIG (status)); | ||
187 | else | ||
188 | mu_diag_output (MU_DIAG_ERR, "%lu: terminated (cause unknown)"); | ||
189 | } | ||
190 | } | ||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | int | ||
195 | run () | ||
196 | { | ||
197 | int rc; | ||
198 | signal (SIGCHLD, sig_child); | ||
199 | rc = mu_server_run (server); | ||
200 | if (rc) | ||
201 | mu_error ("%s", mu_strerror (rc)); | ||
202 | mu_server_destroy (&server); | ||
203 | return rc ? 1 : 0; | ||
204 | } | ||
205 | |||
206 | int | ||
207 | main (int argc, char **argv) | ||
208 | { | ||
209 | int rc; | ||
210 | |||
211 | mu_set_program_name (argv[0]); | ||
212 | while ((rc = getopt (argc, argv, "Dd:")) != EOF) | ||
213 | { | ||
214 | switch (rc) | ||
215 | { | ||
216 | case 'D': | ||
217 | mu_debug_line_info = 1; | ||
218 | break; | ||
219 | |||
220 | case 'd': | ||
221 | mu_global_debug_from_string (optarg, "command line"); | ||
222 | break; | ||
223 | |||
224 | default: | ||
225 | exit (1); | ||
226 | } | ||
227 | } | ||
228 | |||
229 | argc -= optind; | ||
230 | argv += optind; | ||
231 | |||
232 | MU_ASSERT (mu_server_create (&server)); | ||
233 | mu_server_set_idle (server, server_idle); | ||
234 | while (argc--) | ||
235 | create_server (*argv++); | ||
236 | return run (); | ||
237 | } | ||
238 |
... | @@ -21,8 +21,6 @@ | ... | @@ -21,8 +21,6 @@ |
21 | #include <mailutils/types.h> | 21 | #include <mailutils/types.h> |
22 | #include <mailutils/iterator.h> | 22 | #include <mailutils/iterator.h> |
23 | 23 | ||
24 | typedef struct _mu_acl *mu_acl_t; | ||
25 | |||
26 | typedef enum mu_acl_action | 24 | typedef enum mu_acl_action |
27 | { | 25 | { |
28 | mu_acl_accept, | 26 | mu_acl_accept, | ... | ... |
include/mailutils/server.h
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2007 Free Software Foundation, Inc. | ||
3 | |||
4 | This library is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Lesser General Public | ||
6 | License as published by the Free Software Foundation; either | ||
7 | version 3 of the License, or (at your option) any later version. | ||
8 | |||
9 | This library is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General | ||
15 | Public License along with this library; If not, see | ||
16 | <http://www.gnu.org/licenses/>. */ | ||
17 | |||
18 | #ifndef _MAILUTILS_SERVER_H | ||
19 | #define _MAILUTILS_SERVER_H | ||
20 | |||
21 | #include <mailutils/types.h> | ||
22 | |||
23 | typedef int (*mu_conn_loop_fp) (int fd, void *conn_data, void *server_data); | ||
24 | typedef void (*mu_conn_free_fp) (void *conn_data, void *server_data); | ||
25 | typedef int (*mu_server_idle_fp) (void *server_data); | ||
26 | typedef void (*mu_server_free_fp) (void *server_data); | ||
27 | |||
28 | #define MU_SERVER_SUCCESS 0 | ||
29 | #define MU_SERVER_CLOSE_CONN 1 | ||
30 | #define MU_SERVER_SHUTDOWN 2 | ||
31 | |||
32 | int mu_server_run (mu_server_t srv); | ||
33 | int mu_server_create (mu_server_t *psrv); | ||
34 | int mu_server_destroy (mu_server_t *psrv); | ||
35 | int mu_server_set_idle (mu_server_t srv, mu_server_idle_fp fp); | ||
36 | int mu_server_set_data (mu_server_t srv, void *data, mu_server_free_fp fp); | ||
37 | int mu_server_add_connection (mu_server_t srv, | ||
38 | int fd, void *data, | ||
39 | mu_conn_loop_fp loop, mu_conn_free_fp free); | ||
40 | struct timeval; | ||
41 | int mu_server_set_timeout (mu_server_t srv, struct timeval *to); | ||
42 | int mu_server_count (mu_server_t srv, size_t *pcount); | ||
43 | |||
44 | |||
45 | /* TCP server */ | ||
46 | struct sockaddr_in; | ||
47 | typedef int (*mu_tcp_server_conn_fp) (int fd, struct sockaddr_in *s, | ||
48 | void *server_data, void *call_data, | ||
49 | mu_tcp_server_t srv); | ||
50 | typedef int (*mu_tcp_server_intr_fp) (void *data, void *call_data); | ||
51 | typedef void (*mu_tcp_server_free_fp) (void *data); | ||
52 | |||
53 | |||
54 | int mu_tcp_server_create (mu_tcp_server_t *psrv, struct sockaddr_in *addr); | ||
55 | int mu_tcp_server_destroy (mu_tcp_server_t *psrv); | ||
56 | int mu_tcp_server_set_debug (mu_tcp_server_t srv, mu_debug_t debug); | ||
57 | int mu_tcp_server_get_debug (mu_tcp_server_t srv, mu_debug_t *pdebug); | ||
58 | int mu_tcp_server_set_backlog (mu_tcp_server_t srv, int backlog); | ||
59 | int mu_tcp_server_set_ident (mu_tcp_server_t srv, const char *ident); | ||
60 | int mu_tcp_server_set_acl (mu_tcp_server_t srv, mu_acl_t acl); | ||
61 | int mu_tcp_server_set_conn (mu_tcp_server_t srv, mu_tcp_server_conn_fp conn); | ||
62 | int mu_tcp_server_set_intr (mu_tcp_server_t srv, mu_tcp_server_intr_fp intr); | ||
63 | int mu_tcp_server_set_data (mu_tcp_server_t srv, | ||
64 | void *data, mu_tcp_server_free_fp free); | ||
65 | int mu_tcp_server_open (mu_tcp_server_t srv); | ||
66 | int mu_tcp_server_shutdown (mu_tcp_server_t srv); | ||
67 | int mu_tcp_server_accept (mu_tcp_server_t srv, void *call_data); | ||
68 | int mu_tcp_server_loop (mu_tcp_server_t srv, void *call_data); | ||
69 | int mu_tcp_server_get_fd (mu_tcp_server_t srv); | ||
70 | int mu_tcp_server_get_sockaddr (mu_tcp_server_t srv, struct sockaddr_in *s); | ||
71 | |||
72 | #endif |
... | @@ -66,6 +66,9 @@ struct _mu_ticket; | ... | @@ -66,6 +66,9 @@ struct _mu_ticket; |
66 | struct _mu_url; | 66 | struct _mu_url; |
67 | struct _mu_wicket; | 67 | struct _mu_wicket; |
68 | struct _mu_assoc; | 68 | struct _mu_assoc; |
69 | struct _mu_acl; | ||
70 | struct _mu_server; | ||
71 | struct _mu_tcp_server; | ||
69 | 72 | ||
70 | typedef MU_OFF_TYPE mu_off_t; | 73 | typedef MU_OFF_TYPE mu_off_t; |
71 | 74 | ||
... | @@ -102,6 +105,9 @@ typedef void *mu_transport_t; | ... | @@ -102,6 +105,9 @@ typedef void *mu_transport_t; |
102 | typedef struct _mu_assoc *mu_assoc_t; | 105 | typedef struct _mu_assoc *mu_assoc_t; |
103 | typedef char *mu_message_qid_t; | 106 | typedef char *mu_message_qid_t; |
104 | typedef int mu_log_level_t; | 107 | typedef int mu_log_level_t; |
108 | typedef struct _mu_acl *mu_acl_t; | ||
109 | typedef struct _mu_server *mu_server_t; | ||
110 | typedef struct _mu_tcp_server *mu_tcp_server_t; | ||
105 | 111 | ||
106 | #define MU_FOLDER_ATTRIBUTE_DIRECTORY 0x001 | 112 | #define MU_FOLDER_ATTRIBUTE_DIRECTORY 0x001 |
107 | #define MU_FOLDER_ATTRIBUTE_FILE 0x002 | 113 | #define MU_FOLDER_ATTRIBUTE_FILE 0x002 | ... | ... |
... | @@ -97,12 +97,14 @@ libmailutils_la_SOURCES = \ | ... | @@ -97,12 +97,14 @@ libmailutils_la_SOURCES = \ |
97 | refcount.c\ | 97 | refcount.c\ |
98 | rfc2047.c\ | 98 | rfc2047.c\ |
99 | sha1.c\ | 99 | sha1.c\ |
100 | server.c\ | ||
100 | socket_stream.c\ | 101 | socket_stream.c\ |
101 | stream.c\ | 102 | stream.c\ |
102 | syslog.c\ | 103 | syslog.c\ |
103 | system.c\ | 104 | system.c\ |
104 | tcp.c\ | ||
105 | ticket.c\ | 105 | ticket.c\ |
106 | tcp.c\ | ||
107 | tcpsrv.c\ | ||
106 | url.c\ | 108 | url.c\ |
107 | vartab.c\ | 109 | vartab.c\ |
108 | version.c\ | 110 | version.c\ | ... | ... |
... | @@ -24,6 +24,7 @@ | ... | @@ -24,6 +24,7 @@ |
24 | #include <arpa/inet.h> | 24 | #include <arpa/inet.h> |
25 | 25 | ||
26 | #include <sys/types.h> | 26 | #include <sys/types.h> |
27 | #include <sys/wait.h> | ||
27 | #include <unistd.h> | 28 | #include <unistd.h> |
28 | #include <stdlib.h> | 29 | #include <stdlib.h> |
29 | #include <string.h> | 30 | #include <string.h> |
... | @@ -74,8 +75,8 @@ prepare_sa (struct sockaddr *sa) | ... | @@ -74,8 +75,8 @@ prepare_sa (struct sockaddr *sa) |
74 | { | 75 | { |
75 | case AF_INET: | 76 | case AF_INET: |
76 | { | 77 | { |
77 | struct sockaddr_in *sin = (struct sockaddr_in *)sa; | 78 | struct sockaddr_in *s_in = (struct sockaddr_in *)sa; |
78 | sin->sin_addr.s_addr = ntohl (sin->sin_addr.s_addr); | 79 | s_in->sin_addr.s_addr = ntohl (s_in->sin_addr.s_addr); |
79 | break; | 80 | break; |
80 | } | 81 | } |
81 | 82 | ||
... | @@ -313,16 +314,16 @@ debug_sockaddr (mu_debug_t dbg, mu_log_level_t lvl, struct sockaddr *sa) | ... | @@ -313,16 +314,16 @@ debug_sockaddr (mu_debug_t dbg, mu_log_level_t lvl, struct sockaddr *sa) |
313 | { | 314 | { |
314 | case AF_INET: | 315 | case AF_INET: |
315 | { | 316 | { |
316 | struct sockaddr_in *sin = (struct sockaddr_in *)sa; | 317 | struct sockaddr_in *s_in = (struct sockaddr_in *)sa; |
317 | mu_debug_printf (dbg, lvl, "{AF_INET %s:%d}", | 318 | mu_debug_printf (dbg, lvl, "{AF_INET %s:%d}", |
318 | inet_ntoa (sin->sin_addr), ntohs (sin->sin_port)); | 319 | inet_ntoa (s_in->sin_addr), ntohs (s_in->sin_port)); |
319 | break; | 320 | break; |
320 | } | 321 | } |
321 | 322 | ||
322 | case AF_UNIX: | 323 | case AF_UNIX: |
323 | { | 324 | { |
324 | struct sockaddr_un *sun = (struct sockaddr_un *)sa; | 325 | struct sockaddr_un *s_un = (struct sockaddr_un *)sa; |
325 | mu_debug_printf (dbg, lvl, "{AF_UNIX %s}", sun->sun_path); | 326 | mu_debug_printf (dbg, lvl, "{AF_UNIX %s}", s_un->sun_path); |
326 | break; | 327 | break; |
327 | } | 328 | } |
328 | 329 | ||
... | @@ -439,25 +440,25 @@ spawn_prog (const char *cmdline, int *pstatus, struct run_closure *rp) | ... | @@ -439,25 +440,25 @@ spawn_prog (const char *cmdline, int *pstatus, struct run_closure *rp) |
439 | { | 440 | { |
440 | case AF_INET: | 441 | case AF_INET: |
441 | { | 442 | { |
442 | struct sockaddr_in *sin = (struct sockaddr_in *)rp->sa; | 443 | struct sockaddr_in *s_in = (struct sockaddr_in *)rp->sa; |
443 | struct in_addr addr = sin->sin_addr; | 444 | struct in_addr addr = s_in->sin_addr; |
444 | char buf[UINTMAX_STRSIZE_BOUND]; | 445 | char buf[UINTMAX_STRSIZE_BOUND]; |
445 | unsigned n; | 446 | unsigned n; |
446 | 447 | ||
447 | mu_vartab_define (vtab, "family", "AF_INET", 1); | 448 | mu_vartab_define (vtab, "family", "AF_INET", 1); |
448 | addr.s_addr = htonl (addr.s_addr); | 449 | addr.s_addr = htonl (addr.s_addr); |
449 | mu_vartab_define (vtab, "address", inet_ntoa (addr), 0); | 450 | mu_vartab_define (vtab, "address", inet_ntoa (addr), 0); |
450 | n = ntohs (sin->sin_port); | 451 | n = ntohs (s_in->sin_port); |
451 | mu_vartab_define (vtab, "port", umaxtostr (n, buf), 0); | 452 | mu_vartab_define (vtab, "port", umaxtostr (n, buf), 0); |
452 | } | 453 | } |
453 | break; | 454 | break; |
454 | 455 | ||
455 | case AF_UNIX: | 456 | case AF_UNIX: |
456 | { | 457 | { |
457 | struct sockaddr_un *sun = (struct sockaddr_un *)rp->sa; | 458 | struct sockaddr_un *s_un = (struct sockaddr_un *)rp->sa; |
458 | 459 | ||
459 | mu_vartab_define (vtab, "family", "AF_UNIX", 1); | 460 | mu_vartab_define (vtab, "family", "AF_UNIX", 1); |
460 | mu_vartab_define (vtab, "address", sun->sun_path, 1); | 461 | mu_vartab_define (vtab, "address", s_un->sun_path, 1); |
461 | } | 462 | } |
462 | break; | 463 | break; |
463 | } | 464 | } | ... | ... |
... | @@ -35,7 +35,7 @@ MU_ERR_LOCK_CONFLICT _("Conflict with previous locker") | ... | @@ -35,7 +35,7 @@ MU_ERR_LOCK_CONFLICT _("Conflict with previous locker") |
35 | MU_ERR_LOCK_BAD_LOCK _("Lock file check failed") | 35 | MU_ERR_LOCK_BAD_LOCK _("Lock file check failed") |
36 | MU_ERR_LOCK_BAD_FILE _("File check failed") | 36 | MU_ERR_LOCK_BAD_FILE _("File check failed") |
37 | MU_ERR_LOCK_NOT_HELD _("Lock not held on file") | 37 | MU_ERR_LOCK_NOT_HELD _("Lock not held on file") |
38 | MU_ERR_LOCK_EXT_FAIL _("Failed to exec external locker") | 38 | MU_ERR_LOCK_EXT_FAIL _("Failed to execute external locker") |
39 | MU_ERR_LOCK_EXT_ERR _("External locker failed") | 39 | MU_ERR_LOCK_EXT_ERR _("External locker failed") |
40 | MU_ERR_LOCK_EXT_KILLED _("External locker killed") | 40 | MU_ERR_LOCK_EXT_KILLED _("External locker killed") |
41 | 41 | ... | ... |
mailbox/server.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2007 Free Software Foundation, Inc. | ||
3 | |||
4 | This library is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Lesser General Public | ||
6 | License as published by the Free Software Foundation; either | ||
7 | version 3 of the License, or (at your option) any later version. | ||
8 | |||
9 | This library is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General | ||
15 | Public License along with this library; If not, see | ||
16 | <http://www.gnu.org/licenses/>. */ | ||
17 | |||
18 | #ifdef HAVE_CONFIG_H | ||
19 | #include <config.h> | ||
20 | #endif | ||
21 | #include <sys/select.h> | ||
22 | #include <sys/time.h> | ||
23 | #include <sys/types.h> | ||
24 | #include <unistd.h> | ||
25 | #include <stdlib.h> | ||
26 | #include <mailutils/server.h> | ||
27 | #include <mailutils/errno.h> | ||
28 | |||
29 | |||
30 | struct _mu_connection | ||
31 | { | ||
32 | struct _mu_connection *next, *prev; | ||
33 | int fd; | ||
34 | mu_conn_loop_fp f_loop; | ||
35 | mu_conn_free_fp f_free; | ||
36 | void *data; | ||
37 | }; | ||
38 | |||
39 | #define MU_SERVER_TIMEOUT 0x1 | ||
40 | |||
41 | struct _mu_server | ||
42 | { | ||
43 | int nfd; | ||
44 | fd_set fdset; | ||
45 | int flags; | ||
46 | struct timeval timeout; | ||
47 | struct _mu_connection *head, *tail; | ||
48 | mu_server_idle_fp f_idle; | ||
49 | mu_server_free_fp f_free; | ||
50 | void *server_data; | ||
51 | }; | ||
52 | |||
53 | void | ||
54 | recompute_nfd (mu_server_t srv) | ||
55 | { | ||
56 | struct _mu_connection *p; | ||
57 | int nfd = 0; | ||
58 | for (p = srv->head; p; p = p->next) | ||
59 | if (p->fd > nfd) | ||
60 | nfd = p->fd; | ||
61 | srv->nfd = nfd + 1; | ||
62 | } | ||
63 | |||
64 | void | ||
65 | destroy_connection (mu_server_t srv, struct _mu_connection *conn) | ||
66 | { | ||
67 | if (conn->f_free) | ||
68 | conn->f_free (conn->data, srv->server_data); | ||
69 | free (conn); | ||
70 | } | ||
71 | |||
72 | void | ||
73 | remove_connection (mu_server_t srv, struct _mu_connection *conn) | ||
74 | { | ||
75 | struct _mu_connection *p; | ||
76 | |||
77 | close (conn->fd); | ||
78 | FD_CLR (conn->fd, &srv->fdset); | ||
79 | |||
80 | p = conn->prev; | ||
81 | if (p) | ||
82 | p->next = conn->next; | ||
83 | else /* we're at head */ | ||
84 | srv->head = conn->next; | ||
85 | |||
86 | p = conn->next; | ||
87 | if (p) | ||
88 | p->prev = conn->prev; | ||
89 | else /* we're at tail */ | ||
90 | srv->tail = conn->prev; | ||
91 | |||
92 | if (conn->fd == srv->nfd - 1) | ||
93 | recompute_nfd (srv); | ||
94 | |||
95 | destroy_connection (srv, conn); | ||
96 | } | ||
97 | |||
98 | int | ||
99 | connection_loop (mu_server_t srv, fd_set *fdset) | ||
100 | { | ||
101 | struct _mu_connection *conn; | ||
102 | for (conn = srv->head; conn;) | ||
103 | { | ||
104 | struct _mu_connection *next = conn->next; | ||
105 | if (FD_ISSET (conn->fd, fdset)) | ||
106 | { | ||
107 | int rc = conn->f_loop (conn->fd, conn->data, srv->server_data); | ||
108 | switch (rc) | ||
109 | { | ||
110 | case 0: | ||
111 | break; | ||
112 | |||
113 | case MU_SERVER_CLOSE_CONN: | ||
114 | default: | ||
115 | remove_connection (srv, conn); | ||
116 | break; | ||
117 | |||
118 | case MU_SERVER_SHUTDOWN: | ||
119 | return 1; | ||
120 | } | ||
121 | } | ||
122 | conn = next; | ||
123 | } | ||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | void | ||
128 | make_fdset (mu_server_t srv) | ||
129 | { | ||
130 | struct _mu_connection *p; | ||
131 | int nfd = 0; | ||
132 | |||
133 | FD_ZERO (&srv->fdset); | ||
134 | for (p = srv->head; p; p = p->next) | ||
135 | { | ||
136 | FD_SET (p->fd, &srv->fdset); | ||
137 | if (p->fd > nfd) | ||
138 | nfd = p->fd; | ||
139 | } | ||
140 | srv->nfd = nfd + 1; | ||
141 | } | ||
142 | |||
143 | int | ||
144 | mu_server_run (mu_server_t srv) | ||
145 | { | ||
146 | int status = 0; | ||
147 | |||
148 | if (!srv) | ||
149 | return EINVAL; | ||
150 | if (!srv->head) | ||
151 | return MU_ERR_NOENT; | ||
152 | |||
153 | make_fdset (srv); | ||
154 | |||
155 | while (1) | ||
156 | { | ||
157 | int rc; | ||
158 | fd_set rdset; | ||
159 | struct timeval *to; | ||
160 | |||
161 | rdset = srv->fdset; | ||
162 | to = (srv->flags & MU_SERVER_TIMEOUT) ? &srv->timeout : NULL; | ||
163 | rc = select (srv->nfd, &rdset, NULL, NULL, to); | ||
164 | if (rc == -1 && errno == EINTR) | ||
165 | { | ||
166 | if (srv->f_idle && srv->f_idle (srv->server_data)) | ||
167 | break; | ||
168 | continue; | ||
169 | } | ||
170 | if (rc < 0) | ||
171 | return errno; | ||
172 | |||
173 | if (connection_loop (srv, &rdset)) | ||
174 | { | ||
175 | status = MU_ERR_FAILURE; | ||
176 | break; | ||
177 | } | ||
178 | } | ||
179 | return status; | ||
180 | } | ||
181 | |||
182 | int | ||
183 | mu_server_create (mu_server_t *psrv) | ||
184 | { | ||
185 | mu_server_t srv = calloc (1, sizeof (*srv)); | ||
186 | if (!srv) | ||
187 | return ENOMEM; | ||
188 | *psrv = srv; | ||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | int | ||
193 | mu_server_destroy (mu_server_t *psrv) | ||
194 | { | ||
195 | mu_server_t srv; | ||
196 | struct _mu_connection *p; | ||
197 | |||
198 | if (!psrv) | ||
199 | return EINVAL; | ||
200 | srv = *psrv; | ||
201 | if (!srv) | ||
202 | return 0; | ||
203 | |||
204 | for (p = srv->head; p; p = p->next) | ||
205 | destroy_connection (srv, p); | ||
206 | |||
207 | if (srv->f_free) | ||
208 | srv->f_free (srv->server_data); | ||
209 | |||
210 | free (srv); | ||
211 | *psrv = NULL; | ||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | int | ||
216 | mu_server_count (mu_server_t srv, size_t *pcount) | ||
217 | { | ||
218 | size_t n = 0; | ||
219 | struct _mu_connection *p; | ||
220 | |||
221 | if (!srv) | ||
222 | return EINVAL; | ||
223 | for (p = srv->head; p; p = p->next) | ||
224 | n++; | ||
225 | *pcount = n; | ||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | int | ||
230 | mu_server_set_idle (mu_server_t srv, mu_server_idle_fp fp) | ||
231 | { | ||
232 | if (!srv) | ||
233 | return EINVAL; | ||
234 | srv->f_idle = fp; | ||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | int | ||
239 | mu_server_set_data (mu_server_t srv, void *data, mu_server_free_fp fp) | ||
240 | { | ||
241 | if (!srv) | ||
242 | return EINVAL; | ||
243 | srv->server_data = data; | ||
244 | srv->f_free = fp; | ||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | int | ||
249 | mu_server_set_timeout (mu_server_t srv, struct timeval *to) | ||
250 | { | ||
251 | if (!srv) | ||
252 | return EINVAL; | ||
253 | if (!to) | ||
254 | srv->flags &= ~MU_SERVER_TIMEOUT; | ||
255 | else | ||
256 | { | ||
257 | srv->timeout = *to; | ||
258 | srv->flags |= MU_SERVER_TIMEOUT; | ||
259 | } | ||
260 | return 0; | ||
261 | } | ||
262 | |||
263 | int | ||
264 | mu_server_add_connection (mu_server_t srv, | ||
265 | int fd, void *data, | ||
266 | mu_conn_loop_fp loop, mu_conn_free_fp free) | ||
267 | { | ||
268 | struct _mu_connection *p; | ||
269 | |||
270 | if (!srv || !loop) | ||
271 | return EINVAL; | ||
272 | |||
273 | p = malloc (sizeof (*p)); | ||
274 | if (!p) | ||
275 | return ENOMEM; | ||
276 | p->fd = fd; | ||
277 | p->f_loop = loop; | ||
278 | p->f_free = free; | ||
279 | p->data = data; | ||
280 | |||
281 | p->next = NULL; | ||
282 | p->prev = srv->tail; | ||
283 | if (srv->tail) | ||
284 | srv->tail->next = p; | ||
285 | else | ||
286 | srv->head = p; | ||
287 | srv->tail = p; | ||
288 | return 0; | ||
289 | } |
mailbox/tcpsrv.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2007 Free Software Foundation, Inc. | ||
3 | |||
4 | This library is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Lesser General Public | ||
6 | License as published by the Free Software Foundation; either | ||
7 | version 3 of the License, or (at your option) any later version. | ||
8 | |||
9 | This library is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General | ||
15 | Public License along with this library; If not, see | ||
16 | <http://www.gnu.org/licenses/>. */ | ||
17 | |||
18 | #ifdef HAVE_CONFIG_H | ||
19 | #include <config.h> | ||
20 | #endif | ||
21 | #include <sys/time.h> | ||
22 | #include <sys/types.h> | ||
23 | #include <sys/socket.h> | ||
24 | #include <netinet/in.h> | ||
25 | #include <arpa/inet.h> | ||
26 | #include <unistd.h> | ||
27 | #include <stdlib.h> | ||
28 | #include <string.h> | ||
29 | #include <mailutils/acl.h> | ||
30 | #include <mailutils/server.h> | ||
31 | #include <mailutils/debug.h> | ||
32 | #include <mailutils/diag.h> | ||
33 | #include <mailutils/errno.h> | ||
34 | |||
35 | |||
36 | struct _mu_tcp_server | ||
37 | { | ||
38 | char *ident; | ||
39 | struct sockaddr_in addr; | ||
40 | int backlog; | ||
41 | int fd; | ||
42 | mu_debug_t debug; | ||
43 | mu_acl_t acl; | ||
44 | mu_tcp_server_conn_fp f_conn; | ||
45 | mu_tcp_server_intr_fp f_intr; | ||
46 | mu_tcp_server_free_fp f_free; | ||
47 | void *data; | ||
48 | }; | ||
49 | |||
50 | #define IDENTSTR(s) ((s)->ident ? (s)->ident : "default") | ||
51 | |||
52 | int | ||
53 | mu_tcp_server_create (mu_tcp_server_t *psrv, | ||
54 | struct sockaddr_in *addr) | ||
55 | { | ||
56 | struct _mu_tcp_server *srv; | ||
57 | mu_log_level_t level; | ||
58 | |||
59 | srv = calloc (1, sizeof *srv); | ||
60 | if (!srv) | ||
61 | return ENOMEM; | ||
62 | srv->addr = *addr; | ||
63 | level = mu_global_debug_level ("mailbox"); | ||
64 | if (level) | ||
65 | { | ||
66 | mu_debug_create (&srv->debug, NULL); | ||
67 | mu_debug_set_level (srv->debug, level); | ||
68 | } | ||
69 | srv->fd = -1; | ||
70 | srv->backlog = 4; | ||
71 | *psrv = srv; | ||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | int | ||
76 | mu_tcp_server_destroy (mu_tcp_server_t *psrv) | ||
77 | { | ||
78 | mu_tcp_server_t srv; | ||
79 | if (!psrv) | ||
80 | return EINVAL; | ||
81 | srv = *psrv; | ||
82 | if (!srv) | ||
83 | return 0; | ||
84 | if (srv->f_free) | ||
85 | srv->f_free (srv->data); | ||
86 | close (srv->fd); | ||
87 | free (srv->ident); | ||
88 | free (srv); | ||
89 | *psrv = NULL; | ||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | int | ||
94 | mu_tcp_server_set_debug (mu_tcp_server_t srv, mu_debug_t debug) | ||
95 | { | ||
96 | if (!srv) | ||
97 | return EINVAL; | ||
98 | mu_debug_destroy (&srv->debug, NULL); | ||
99 | srv->debug = debug; | ||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | int | ||
104 | mu_tcp_server_get_debug (mu_tcp_server_t srv, mu_debug_t *pdebug) | ||
105 | { | ||
106 | if (!srv) | ||
107 | return EINVAL; | ||
108 | *pdebug = srv->debug; | ||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | int | ||
113 | mu_tcp_server_set_backlog (mu_tcp_server_t srv, int backlog) | ||
114 | { | ||
115 | if (!srv) | ||
116 | return EINVAL; | ||
117 | srv->backlog = backlog; | ||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | int | ||
122 | mu_tcp_server_set_ident (mu_tcp_server_t srv, const char *ident) | ||
123 | { | ||
124 | if (!srv) | ||
125 | return EINVAL; | ||
126 | if (srv->ident) | ||
127 | free (srv->ident); | ||
128 | srv->ident = strdup (ident); | ||
129 | if (!srv->ident) | ||
130 | return ENOMEM; | ||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | int | ||
135 | mu_tcp_server_set_acl (mu_tcp_server_t srv, mu_acl_t acl) | ||
136 | { | ||
137 | if (!srv) | ||
138 | return EINVAL; | ||
139 | srv->acl = acl; | ||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | int | ||
144 | mu_tcp_server_set_conn (mu_tcp_server_t srv, mu_tcp_server_conn_fp conn) | ||
145 | { | ||
146 | if (!srv) | ||
147 | return EINVAL; | ||
148 | srv->f_conn = conn; | ||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | int | ||
153 | mu_tcp_server_set_intr (mu_tcp_server_t srv, mu_tcp_server_intr_fp intr) | ||
154 | { | ||
155 | if (!srv) | ||
156 | return EINVAL; | ||
157 | srv->f_intr = intr; | ||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | int | ||
162 | mu_tcp_server_set_data (mu_tcp_server_t srv, | ||
163 | void *data, mu_tcp_server_free_fp free) | ||
164 | { | ||
165 | if (!srv) | ||
166 | return EINVAL; | ||
167 | srv->data = data; | ||
168 | srv->f_free = free; | ||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | int | ||
173 | mu_tcp_server_open (mu_tcp_server_t srv) | ||
174 | { | ||
175 | int fd; | ||
176 | int t; | ||
177 | |||
178 | if (!srv || srv->fd != -1) | ||
179 | return EINVAL; | ||
180 | |||
181 | MU_DEBUG3 (srv->debug, MU_DEBUG_TRACE0, | ||
182 | "opening server \"%s\" %s:%d\n", IDENTSTR (srv), | ||
183 | inet_ntoa (srv->addr.sin_addr), ntohs (srv->addr.sin_port)); | ||
184 | |||
185 | fd = socket (PF_INET, SOCK_STREAM, 0); | ||
186 | if (fd == -1) | ||
187 | { | ||
188 | MU_DEBUG2 (srv->debug, MU_DEBUG_ERROR, | ||
189 | "%s: socket: %s\n", IDENTSTR (srv), mu_strerror (errno)); | ||
190 | return errno; | ||
191 | } | ||
192 | |||
193 | t = 1; | ||
194 | setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &t, sizeof (t)); | ||
195 | |||
196 | if (bind (fd, (struct sockaddr *) &srv->addr, sizeof (srv->addr)) == -1) | ||
197 | { | ||
198 | MU_DEBUG2 (srv->debug, MU_DEBUG_ERROR, | ||
199 | "%s: bind: %s\n", IDENTSTR (srv), mu_strerror (errno)); | ||
200 | close (fd); | ||
201 | return errno; | ||
202 | } | ||
203 | |||
204 | if (listen (fd, srv->backlog) == -1) | ||
205 | { | ||
206 | MU_DEBUG2 (srv->debug, MU_DEBUG_ERROR, | ||
207 | "%s: listen: %s\n", IDENTSTR (srv), mu_strerror (errno)); | ||
208 | close (fd); | ||
209 | return errno; | ||
210 | } | ||
211 | |||
212 | srv->fd = fd; | ||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | int | ||
217 | mu_tcp_server_shutdown (mu_tcp_server_t srv) | ||
218 | { | ||
219 | if (!srv || srv->fd != -1) | ||
220 | return EINVAL; | ||
221 | MU_DEBUG4 (srv->debug, MU_DEBUG_TRACE0, | ||
222 | "closing server \"%s\" %s:%d, fd %d\n", IDENTSTR (srv), | ||
223 | inet_ntoa (srv->addr.sin_addr), ntohs (srv->addr.sin_port), | ||
224 | srv->fd); | ||
225 | close (srv->fd); | ||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | int | ||
230 | mu_tcp_server_accept (mu_tcp_server_t srv, void *call_data) | ||
231 | { | ||
232 | int rc; | ||
233 | int connfd; | ||
234 | struct sockaddr_in client; | ||
235 | socklen_t size = sizeof (client); | ||
236 | |||
237 | if (!srv || srv->fd == -1) | ||
238 | return EINVAL; | ||
239 | |||
240 | connfd = accept (srv->fd, (struct sockaddr *) &client, &size); | ||
241 | if (connfd == -1) | ||
242 | { | ||
243 | int ec = errno; | ||
244 | if (ec == EINTR) | ||
245 | { | ||
246 | if (srv->f_intr && srv->f_intr (srv->data, call_data)) | ||
247 | mu_tcp_server_shutdown (srv); | ||
248 | } | ||
249 | return ec; | ||
250 | } | ||
251 | |||
252 | if (srv->acl) | ||
253 | { | ||
254 | mu_acl_result_t res; | ||
255 | int rc = mu_acl_check_sockaddr (srv->acl, (struct sockaddr *) &client, | ||
256 | size, &res); | ||
257 | if (rc) | ||
258 | MU_DEBUG2 (srv->debug, MU_DEBUG_ERROR, | ||
259 | "%s: mu_acl_check_sockaddr: %s\n", | ||
260 | IDENTSTR (srv), strerror (rc)); | ||
261 | if (res == mu_acl_result_deny) | ||
262 | { | ||
263 | mu_diag_output (MU_DIAG_INFO, "Denying connection from %s:%d", | ||
264 | inet_ntoa (client.sin_addr), | ||
265 | ntohs (client.sin_port)); | ||
266 | close (connfd); | ||
267 | return 0; | ||
268 | } | ||
269 | } | ||
270 | rc = srv->f_conn (connfd, &client, srv->data, call_data, srv); | ||
271 | if (rc) | ||
272 | mu_tcp_server_shutdown (srv); | ||
273 | close (connfd); | ||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | int | ||
278 | mu_tcp_server_loop (mu_tcp_server_t srv, void *call_data) | ||
279 | { | ||
280 | if (!srv) | ||
281 | return EINVAL; | ||
282 | while (srv->fd != -1) | ||
283 | { | ||
284 | int rc = mu_tcp_server_accept (srv, call_data); | ||
285 | if (rc && rc != EINTR) | ||
286 | { | ||
287 | mu_tcp_server_shutdown (srv); | ||
288 | return rc; | ||
289 | } | ||
290 | } | ||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | int | ||
295 | mu_tcp_server_get_fd (mu_tcp_server_t srv) | ||
296 | { | ||
297 | return srv->fd; | ||
298 | } | ||
299 | |||
300 | int | ||
301 | mu_tcp_server_get_sockaddr (mu_tcp_server_t srv, struct sockaddr_in *s) | ||
302 | { | ||
303 | if (!srv || !s) | ||
304 | return EINVAL; | ||
305 | memcpy (s, &srv->addr, sizeof (*s)); | ||
306 | return 0; | ||
307 | } | ||
308 |
-
Please register or sign in to post a comment