Make maidag hanlde mailer URLs.
This makes it possible to `deliver' mails to mailers without explicitly specifying `remote+mailer' mailbox URLs. In particular, it is handy for implementing mailing lists using `prog' mailers (as with Mailman). * maidag/deliver.c (notify_action): Do nothing if biff_user_name is empty. (deliver_to_user): Remove `name' argument. Allow for auth==NULL. (is_remote_url): Use case-sensitive comparison. (is_mailer_url): New function. (deliver_url): Handle mailer URLs as if they were corresponding `remote+' mailbox URLs. This allows to handle mailing lists. * maidag/lmtp.c (lmtp_groups): New global. (lmtp_set_privs): New function. Sets primary and supplementary group privileges. (maidag_lmtp_server): Call lmtp_set_privs. * maidag/maidag.c (lmtp_group): Remove. It is superceded by lmtp_groups. (maidag_cfg_param): Allow to specify supplementary groups. * maidag/maidag.h (lmtp_group): Replace with lmtp_groups.
Showing
5 changed files
with
241 additions
and
80 deletions
1 | 2008-10-28 Sergey Poznyakoff <gray@gnu.org.ua> | 1 | 2008-10-28 Sergey Poznyakoff <gray@gnu.org.ua> |
2 | 2 | ||
3 | Make maidag hanlde mailer URLs. | ||
4 | |||
5 | This makes it possible to `deliver' mails to mailers without | ||
6 | explicitly specifying `remote+mailer' mailbox URLs. In | ||
7 | particular, it is handy for implementing mailing lists using | ||
8 | `prog' mailers (as with Mailman). | ||
9 | |||
10 | * maidag/deliver.c (notify_action): Do nothing if biff_user_name | ||
11 | is empty. | ||
12 | (deliver_to_user): Remove `name' argument. Allow for auth==NULL. | ||
13 | (is_remote_url): Use case-sensitive comparison. | ||
14 | (is_mailer_url): New function. | ||
15 | (deliver_url): Handle mailer URLs as if they were corresponding | ||
16 | `remote+' mailbox URLs. This allows to handle mailing lists. | ||
17 | * maidag/lmtp.c (lmtp_groups): New global. | ||
18 | (lmtp_set_privs): New function. Sets primary and | ||
19 | supplementary group privileges. | ||
20 | (maidag_lmtp_server): Call lmtp_set_privs. | ||
21 | * maidag/maidag.c (lmtp_group): Remove. It is superceded by | ||
22 | lmtp_groups. | ||
23 | (maidag_cfg_param): Allow to specify supplementary groups. | ||
24 | * maidag/maidag.h (lmtp_group): Replace with lmtp_groups. | ||
25 | |||
3 | Change mailer creation mechanism. | 26 | Change mailer creation mechanism. |
4 | 27 | ||
5 | * include/mailutils/mailer.h (mu_mailer_create_from_url): New | 28 | * include/mailutils/mailer.h (mu_mailer_create_from_url): New | ... | ... |
... | @@ -87,7 +87,7 @@ static const char *biff_user_name; | ... | @@ -87,7 +87,7 @@ static const char *biff_user_name; |
87 | static int | 87 | static int |
88 | notify_action (mu_observer_t obs, size_t type, void *data, void *action_data) | 88 | notify_action (mu_observer_t obs, size_t type, void *data, void *action_data) |
89 | { | 89 | { |
90 | if (type == MU_EVT_MESSAGE_APPEND) | 90 | if (type == MU_EVT_MESSAGE_APPEND && biff_user_name) |
91 | { | 91 | { |
92 | mu_message_qid_t qid = data; | 92 | mu_message_qid_t qid = data; |
93 | mu_mailbox_t mbox = mu_observer_get_owner (obs); | 93 | mu_mailbox_t mbox = mu_observer_get_owner (obs); |
... | @@ -144,7 +144,7 @@ attach_notify (mu_mailbox_t mbox) | ... | @@ -144,7 +144,7 @@ attach_notify (mu_mailbox_t mbox) |
144 | 144 | ||
145 | int | 145 | int |
146 | deliver_to_user (mu_mailbox_t imbx, mu_mailbox_t mbox, mu_message_t msg, | 146 | deliver_to_user (mu_mailbox_t imbx, mu_mailbox_t mbox, mu_message_t msg, |
147 | struct mu_auth_data *auth, const char *name, | 147 | struct mu_auth_data *auth, |
148 | char **errp) | 148 | char **errp) |
149 | { | 149 | { |
150 | int status; | 150 | int status; |
... | @@ -184,59 +184,61 @@ deliver_to_user (mu_mailbox_t imbx, mu_mailbox_t mbox, mu_message_t msg, | ... | @@ -184,59 +184,61 @@ deliver_to_user (mu_mailbox_t imbx, mu_mailbox_t mbox, mu_message_t msg, |
184 | } | 184 | } |
185 | 185 | ||
186 | #if defined(USE_MAILBOX_QUOTAS) | 186 | #if defined(USE_MAILBOX_QUOTAS) |
187 | { | 187 | if (auth) |
188 | mu_off_t n; | 188 | { |
189 | mu_off_t msg_size; | 189 | mu_off_t n; |
190 | mu_off_t mbsize; | 190 | mu_off_t msg_size; |
191 | 191 | mu_off_t mbsize; | |
192 | if ((status = mu_mailbox_get_size (mbox, &mbsize))) | 192 | |
193 | { | 193 | if ((status = mu_mailbox_get_size (mbox, &mbsize))) |
194 | maidag_error (_("Cannot get size of mailbox %s: %s"), | 194 | { |
195 | path, mu_strerror (status)); | 195 | maidag_error (_("Cannot get size of mailbox %s: %s"), |
196 | if (status == ENOSYS) | 196 | path, mu_strerror (status)); |
197 | mbsize = 0; /* Try to continue anyway */ | 197 | if (status == ENOSYS) |
198 | else | 198 | mbsize = 0; /* Try to continue anyway */ |
199 | return EX_TEMPFAIL; | 199 | else |
200 | } | 200 | return EX_TEMPFAIL; |
201 | } | ||
201 | 202 | ||
202 | switch (check_quota (auth, mbsize, &n)) | 203 | switch (check_quota (auth, mbsize, &n)) |
203 | { | 204 | { |
204 | case MQUOTA_EXCEEDED: | 205 | case MQUOTA_EXCEEDED: |
205 | maidag_error (_("%s: mailbox quota exceeded for this recipient"), name); | 206 | maidag_error (_("%s: mailbox quota exceeded for this recipient"), |
206 | if (errp) | 207 | auth->name); |
207 | asprintf (errp, "%s: mailbox quota exceeded for this recipient", | 208 | if (errp) |
208 | name); | 209 | asprintf (errp, "%s: mailbox quota exceeded for this recipient", |
209 | exit_code = EX_QUOTA(); | 210 | auth->name); |
210 | failed++; | 211 | exit_code = EX_QUOTA(); |
211 | break; | 212 | failed++; |
212 | 213 | break; | |
213 | case MQUOTA_UNLIMITED: | 214 | |
214 | break; | 215 | case MQUOTA_UNLIMITED: |
215 | 216 | break; | |
216 | default: | 217 | |
217 | if ((status = mu_mailbox_get_size (imbx, &msg_size))) | 218 | default: |
218 | { | 219 | if ((status = mu_mailbox_get_size (imbx, &msg_size))) |
219 | maidag_error (_("Cannot get message size (input message %s): %s"), | 220 | { |
220 | path, mu_strerror (status)); | 221 | maidag_error (_("Cannot get message size (input message %s): %s"), |
221 | exit_code = EX_UNAVAILABLE; | 222 | path, mu_strerror (status)); |
222 | failed++; | 223 | exit_code = EX_UNAVAILABLE; |
223 | } | 224 | failed++; |
224 | else if (msg_size > n) | 225 | } |
225 | { | 226 | else if (msg_size > n) |
226 | maidag_error (_("%s: message would exceed maximum mailbox size for " | 227 | { |
227 | "this recipient"), | 228 | maidag_error (_("%s: message would exceed maximum mailbox size for " |
228 | name); | 229 | "this recipient"), |
229 | if (errp) | 230 | auth->name); |
230 | asprintf (errp, | 231 | if (errp) |
231 | "%s: message would exceed maximum mailbox size " | 232 | asprintf (errp, |
232 | "for this recipient", | 233 | "%s: message would exceed maximum mailbox size " |
233 | name); | 234 | "for this recipient", |
234 | exit_code = EX_QUOTA(); | 235 | auth->name); |
235 | failed++; | 236 | exit_code = EX_QUOTA(); |
236 | } | 237 | failed++; |
237 | break; | 238 | } |
238 | } | 239 | break; |
239 | } | 240 | } |
241 | } | ||
240 | #endif | 242 | #endif |
241 | 243 | ||
242 | if (!failed && switch_user_id (auth, 1) == 0) | 244 | if (!failed && switch_user_id (auth, 1) == 0) |
... | @@ -271,9 +273,24 @@ is_remote_url (mu_url_t url) | ... | @@ -271,9 +273,24 @@ is_remote_url (mu_url_t url) |
271 | { | 273 | { |
272 | const char *scheme; | 274 | const char *scheme; |
273 | int rc = mu_url_sget_scheme (url, &scheme); | 275 | int rc = mu_url_sget_scheme (url, &scheme); |
274 | return rc == 0 && strncasecmp (scheme, "remote+", 7) == 0; | 276 | return rc == 0 && strncmp (scheme, "remote+", 7) == 0; |
275 | } | 277 | } |
276 | 278 | ||
279 | static int | ||
280 | is_mailer_url (mu_url_t url) | ||
281 | { | ||
282 | mu_record_t record = NULL; | ||
283 | int (*pfn) (mu_mailer_t) = NULL; | ||
284 | |||
285 | return mu_registrar_lookup_url (url, MU_FOLDER_ATTRIBUTE_FILE, | ||
286 | &record, NULL) == 0 | ||
287 | && mu_record_get_mailer (record, &pfn) == 0 | ||
288 | && pfn; | ||
289 | } | ||
290 | |||
291 | #define REMOTE_PREFIX "remote+" | ||
292 | #define REMOTE_PREFIX_LEN (sizeof(REMOTE_PREFIX)-1) | ||
293 | |||
277 | int | 294 | int |
278 | deliver_url (mu_url_t url, mu_mailbox_t imbx, const char *name, char **errp) | 295 | deliver_url (mu_url_t url, mu_mailbox_t imbx, const char *name, char **errp) |
279 | { | 296 | { |
... | @@ -282,9 +299,7 @@ deliver_url (mu_url_t url, mu_mailbox_t imbx, const char *name, char **errp) | ... | @@ -282,9 +299,7 @@ deliver_url (mu_url_t url, mu_mailbox_t imbx, const char *name, char **errp) |
282 | mu_message_t msg; | 299 | mu_message_t msg; |
283 | int status; | 300 | int status; |
284 | 301 | ||
285 | if (is_remote_url (url)) | 302 | if (name) |
286 | auth = NULL; | ||
287 | else | ||
288 | { | 303 | { |
289 | auth = mu_get_auth_by_name (name); | 304 | auth = mu_get_auth_by_name (name); |
290 | if (!auth) | 305 | if (!auth) |
... | @@ -292,9 +307,10 @@ deliver_url (mu_url_t url, mu_mailbox_t imbx, const char *name, char **errp) | ... | @@ -292,9 +307,10 @@ deliver_url (mu_url_t url, mu_mailbox_t imbx, const char *name, char **errp) |
292 | maidag_error (_("%s: no such user"), name); | 307 | maidag_error (_("%s: no such user"), name); |
293 | if (errp) | 308 | if (errp) |
294 | asprintf (errp, "%s: no such user", name); | 309 | asprintf (errp, "%s: no such user", name); |
295 | exit_code = EX_UNAVAILABLE; | 310 | exit_code = EX_NOUSER; |
296 | return EX_UNAVAILABLE; | 311 | return EX_NOUSER; |
297 | } | 312 | } |
313 | |||
298 | if (current_uid) | 314 | if (current_uid) |
299 | auth->change_uid = 0; | 315 | auth->change_uid = 0; |
300 | 316 | ||
... | @@ -314,16 +330,59 @@ deliver_url (mu_url_t url, mu_mailbox_t imbx, const char *name, char **errp) | ... | @@ -314,16 +330,59 @@ deliver_url (mu_url_t url, mu_mailbox_t imbx, const char *name, char **errp) |
314 | return EX_TEMPFAIL; | 330 | return EX_TEMPFAIL; |
315 | } | 331 | } |
316 | 332 | ||
317 | if (url) | 333 | if (!url) |
318 | status = mu_mailbox_create_from_url (&mbox, url); | 334 | { |
319 | else | 335 | status = mu_url_create (&url, auth->mailbox); |
320 | status = mu_mailbox_create (&mbox, auth->mailbox); | 336 | if (status) |
337 | { | ||
338 | maidag_error (_("Cannot create URL for %s: %s"), | ||
339 | auth->mailbox, mu_strerror (status)); | ||
340 | return exit_code = EX_UNAVAILABLE; | ||
341 | } | ||
342 | status = mu_url_parse (url); | ||
343 | if (status) | ||
344 | { | ||
345 | maidag_error (_("Error parsing URL %s: %s"), | ||
346 | auth->mailbox, mu_strerror (status)); | ||
347 | return exit_code = EX_UNAVAILABLE; | ||
348 | } | ||
349 | } | ||
350 | |||
351 | if (is_mailer_url (url)) | ||
352 | { | ||
353 | const char *scheme; | ||
354 | size_t len; | ||
355 | char *new_scheme; | ||
356 | |||
357 | mu_url_sget_scheme (url, &scheme); | ||
358 | len = REMOTE_PREFIX_LEN + strlen (scheme); | ||
359 | new_scheme = malloc (len + 1); | ||
360 | if (!new_scheme) | ||
361 | { | ||
362 | mu_error (_("Not enough memory")); | ||
363 | exit (EX_SOFTWARE); | ||
364 | } | ||
365 | strcat (strcpy (new_scheme, REMOTE_PREFIX), scheme); | ||
366 | status = mu_url_set_scheme (url, new_scheme); | ||
367 | free (new_scheme); | ||
368 | if (status) | ||
369 | { | ||
370 | errno = status; | ||
371 | maidag_error (_("Cannot modify URL %s: %s"), | ||
372 | mu_url_to_string (url), | ||
373 | mu_strerror (status)); | ||
374 | mu_auth_data_free (auth); | ||
375 | return EX_TEMPFAIL; | ||
376 | } | ||
377 | } | ||
378 | status = mu_mailbox_create_from_url (&mbox, url); | ||
321 | 379 | ||
322 | if (status) | 380 | if (status) |
323 | { | 381 | { |
324 | maidag_error (_("Cannot open mailbox %s: %s"), | 382 | maidag_error (_("Cannot open mailbox %s: %s"), |
325 | url ? mu_url_to_string (url): auth->mailbox, | 383 | mu_url_to_string (url), |
326 | mu_strerror (status)); | 384 | mu_strerror (status)); |
385 | mu_url_destroy (&url); | ||
327 | mu_auth_data_free (auth); | 386 | mu_auth_data_free (auth); |
328 | return EX_TEMPFAIL; | 387 | return EX_TEMPFAIL; |
329 | } | 388 | } |
... | @@ -335,7 +394,7 @@ deliver_url (mu_url_t url, mu_mailbox_t imbx, const char *name, char **errp) | ... | @@ -335,7 +394,7 @@ deliver_url (mu_url_t url, mu_mailbox_t imbx, const char *name, char **errp) |
335 | will be created */ | 394 | will be created */ |
336 | if (switch_user_id (auth, 1)) | 395 | if (switch_user_id (auth, 1)) |
337 | return EX_TEMPFAIL; | 396 | return EX_TEMPFAIL; |
338 | status = deliver_to_user (imbx, mbox, msg, auth, name, errp); | 397 | status = deliver_to_user (imbx, mbox, msg, auth, errp); |
339 | if (switch_user_id (auth, 0)) | 398 | if (switch_user_id (auth, 0)) |
340 | return EX_TEMPFAIL; | 399 | return EX_TEMPFAIL; |
341 | 400 | ||
... | @@ -371,7 +430,18 @@ deliver (mu_mailbox_t imbx, char *dest_id, char **errp) | ... | @@ -371,7 +430,18 @@ deliver (mu_mailbox_t imbx, char *dest_id, char **errp) |
371 | } | 430 | } |
372 | status = mu_url_sget_user (url, &name); | 431 | status = mu_url_sget_user (url, &name); |
373 | if (status == MU_ERR_NOENT) | 432 | if (status == MU_ERR_NOENT) |
374 | name = NULL; | 433 | { |
434 | if (!is_mailer_url (url) && !is_remote_url (url)) | ||
435 | { | ||
436 | maidag_error (_("no user name")); | ||
437 | if (errp) | ||
438 | asprintf (errp, "no user such"); | ||
439 | exit_code = EX_NOUSER; | ||
440 | return EX_NOUSER; | ||
441 | } | ||
442 | else | ||
443 | name = NULL; | ||
444 | } | ||
375 | else if (status) | 445 | else if (status) |
376 | { | 446 | { |
377 | maidag_error (_("%s: cannot get user name from url: %s"), | 447 | maidag_error (_("%s: cannot get user name from url: %s"), | ... | ... |
... | @@ -25,6 +25,7 @@ | ... | @@ -25,6 +25,7 @@ |
25 | #include <signal.h> | 25 | #include <signal.h> |
26 | #include <mu_umaxtostr.h> | 26 | #include <mu_umaxtostr.h> |
27 | 27 | ||
28 | mu_list_t lmtp_groups; | ||
28 | static int lmtp_transcript; | 29 | static int lmtp_transcript; |
29 | 30 | ||
30 | void | 31 | void |
... | @@ -572,22 +573,67 @@ lmtp_connection (int fd, struct sockaddr *sa, int salen, void *data, | ... | @@ -572,22 +573,67 @@ lmtp_connection (int fd, struct sockaddr *sa, int salen, void *data, |
572 | return 0; | 573 | return 0; |
573 | } | 574 | } |
574 | 575 | ||
575 | int | 576 | static int |
576 | maidag_lmtp_server () | 577 | lmtp_set_privs () |
577 | { | 578 | { |
578 | struct group *gr = getgrnam (lmtp_group); | 579 | gid_t gid; |
579 | 580 | ||
580 | if (gr == NULL) | 581 | if (lmtp_groups) |
581 | { | 582 | { |
582 | mu_error (_("Error getting mail group")); | 583 | gid_t *gidset = NULL; |
583 | return EX_UNAVAILABLE; | 584 | size_t size = 0; |
585 | size_t j = 0; | ||
586 | mu_iterator_t itr; | ||
587 | int rc; | ||
588 | |||
589 | mu_list_count (lmtp_groups, &size); | ||
590 | gidset = calloc (size, sizeof (gidset[0])); | ||
591 | if (!gidset) | ||
592 | { | ||
593 | mu_error (_("Not enough memory")); | ||
594 | return EX_UNAVAILABLE; | ||
595 | } | ||
596 | if (mu_list_get_iterator (lmtp_groups, &itr) == 0) | ||
597 | { | ||
598 | for (mu_iterator_first (itr); | ||
599 | !mu_iterator_is_done (itr); mu_iterator_next (itr)) | ||
600 | mu_iterator_current (itr, | ||
601 | (void **)(gidset + j++)); | ||
602 | mu_iterator_destroy (&itr); | ||
603 | } | ||
604 | gid = gidset[0]; | ||
605 | rc = setgroups (j, gidset); | ||
606 | free (gidset); | ||
607 | if (rc) | ||
608 | { | ||
609 | mu_error(_("setgroups failed: %s"), mu_strerror (errno)); | ||
610 | return EX_UNAVAILABLE; | ||
611 | } | ||
584 | } | 612 | } |
585 | 613 | else | |
586 | if (setgid (gr->gr_gid) == -1) | 614 | { |
615 | struct group *gr = getgrnam ("mail"); | ||
616 | if (gr == NULL) | ||
617 | { | ||
618 | mu_error (_("Error getting group `mail'")); | ||
619 | return EX_UNAVAILABLE; | ||
620 | } | ||
621 | gid = gr->gr_gid; | ||
622 | } | ||
623 | if (setgid (gid) == -1) | ||
587 | { | 624 | { |
588 | mu_error (_("Error setting mail group")); | 625 | mu_error (_("Error setting mail group")); |
589 | return EX_UNAVAILABLE; | 626 | return EX_UNAVAILABLE; |
590 | } | 627 | } |
628 | return 0; | ||
629 | } | ||
630 | |||
631 | int | ||
632 | maidag_lmtp_server () | ||
633 | { | ||
634 | int rc = lmtp_set_privs (); | ||
635 | if (rc) | ||
636 | return rc; | ||
591 | 637 | ||
592 | if (mu_m_server_mode (server) == MODE_DAEMON) | 638 | if (mu_m_server_mode (server) == MODE_DAEMON) |
593 | { | 639 | { | ... | ... |
... | @@ -48,7 +48,6 @@ int lmtp_mode; | ... | @@ -48,7 +48,6 @@ int lmtp_mode; |
48 | int url_option; | 48 | int url_option; |
49 | char *lmtp_url_string; | 49 | char *lmtp_url_string; |
50 | int reuse_lmtp_address = 1; | 50 | int reuse_lmtp_address = 1; |
51 | char *lmtp_group = "mail"; | ||
52 | 51 | ||
53 | const char *program_version = "maidag (" PACKAGE_STRING ")"; | 52 | const char *program_version = "maidag (" PACKAGE_STRING ")"; |
54 | static char doc[] = | 53 | static char doc[] = |
... | @@ -256,6 +255,28 @@ cb_debug (mu_debug_t debug, void *data, mu_config_value_t *val) | ... | @@ -256,6 +255,28 @@ cb_debug (mu_debug_t debug, void *data, mu_config_value_t *val) |
256 | return 0; | 255 | return 0; |
257 | } | 256 | } |
258 | 257 | ||
258 | static int | ||
259 | cb2_group (mu_debug_t debug, const char *gname, void *data) | ||
260 | { | ||
261 | mu_list_t *plist = data; | ||
262 | struct group *group; | ||
263 | |||
264 | if (!*plist) | ||
265 | mu_list_create (plist); | ||
266 | group = getgrnam (gname); | ||
267 | if (!group) | ||
268 | mu_cfg_format_error (debug, MU_DEBUG_ERROR, _("Unknown group: %s"), gname); | ||
269 | else | ||
270 | mu_list_append (*plist, (void*)group->gr_gid); | ||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | static int | ||
275 | cb_group (mu_debug_t debug, void *data, mu_config_value_t *arg) | ||
276 | { | ||
277 | return mu_cfg_string_value_cb (debug, arg, cb2_group, data); | ||
278 | } | ||
279 | |||
259 | struct mu_cfg_param maidag_cfg_param[] = { | 280 | struct mu_cfg_param maidag_cfg_param[] = { |
260 | { "exit-multiple-delivery-success", mu_cfg_bool, &multiple_delivery, 0, NULL, | 281 | { "exit-multiple-delivery-success", mu_cfg_bool, &multiple_delivery, 0, NULL, |
261 | N_("In case of multiple delivery, exit with code 0 if at least one " | 282 | N_("In case of multiple delivery, exit with code 0 if at least one " |
... | @@ -298,8 +319,9 @@ struct mu_cfg_param maidag_cfg_param[] = { | ... | @@ -298,8 +319,9 @@ struct mu_cfg_param maidag_cfg_param[] = { |
298 | /* LMTP support */ | 319 | /* LMTP support */ |
299 | { "lmtp", mu_cfg_bool, &lmtp_mode, 0, NULL, | 320 | { "lmtp", mu_cfg_bool, &lmtp_mode, 0, NULL, |
300 | N_("Run in LMTP mode.") }, | 321 | N_("Run in LMTP mode.") }, |
301 | { "group", mu_cfg_string, &lmtp_group, 0, NULL, | 322 | { "group", mu_cfg_callback, &lmtp_groups, 0, cb_group, |
302 | N_("In LMTP mode, change to this group after startup.") }, | 323 | N_("In LMTP mode, retain these supplementary groups."), |
324 | N_("groups: list of string") }, | ||
303 | { "listen", mu_cfg_string, &lmtp_url_string, 0, NULL, | 325 | { "listen", mu_cfg_string, &lmtp_url_string, 0, NULL, |
304 | N_("In LMTP mode, listen on the given URL. Valid URLs are:\n" | 326 | N_("In LMTP mode, listen on the given URL. Valid URLs are:\n" |
305 | " tcp://<address: string>:<port: number> (note that port is " | 327 | " tcp://<address: string>:<port: number> (note that port is " | ... | ... |
... | @@ -126,7 +126,7 @@ extern int lmtp_mode; | ... | @@ -126,7 +126,7 @@ extern int lmtp_mode; |
126 | extern int url_option; | 126 | extern int url_option; |
127 | extern char *lmtp_url_string; | 127 | extern char *lmtp_url_string; |
128 | extern int reuse_lmtp_address; | 128 | extern int reuse_lmtp_address; |
129 | extern char *lmtp_group; | 129 | extern mu_list_t lmtp_groups; |
130 | extern mu_acl_t maidag_acl; | 130 | extern mu_acl_t maidag_acl; |
131 | 131 | ||
132 | void close_fds (void); | 132 | void close_fds (void); | ... | ... |
-
Please register or sign in to post a comment