Commit 77d0b9df 77d0b9dffcee9761077828fb1725314590bff3e7 by Sergey Poznyakoff

* TODO, NEWS: Update.

* mailbox/msrv.c: New file.
* mailbox/Makefile.am: Add msrv.c.
* include/mailutils/server.h (mu_tcp_server_conn_fp): Take
sockaddr as argument
(mu_tcp_server_create,mu_tcp_server_get_sockaddr): Likewise.
(mu_m_server_*): New prototypes.
* include/mailutils/types.hin (mu_m_server_t): New type.
* mailbox/acl.c: Fix debugging output.
(mu_sockaddr_to_str, mu_sockaddr_to_astr): New functions.

* mailbox/tcpsrv.c: Handle AF_INET and AF_UNIX sockets.
* examples/echosrv.c: Update mu_tcp_server_* calls.
* examples/config/Makefile.am: Remove comsat.conf and
mailutils.rc.

* imap4d/imap4d.c, imap4d/imap4d.h, imap4d/signal.c,
maidag/lmtp.c, maidag/maidag.c, maidag/maidag.h, pop3d/extra.c,
pop3d/pop3d.c, pop3d/pop3d.h, pop3d/signal.c: Rewrite using
m-server.

* include/mailutils/cfg.h (mu_offsetof): Bug fix.
* mailbox/cfg_driver.c (dup_container): Bugfix. Offset was not
copied.
(mu_cfg_section_add_params): If identifier starts with a dot, it
is hidden, i.e. its substatements are copied directly into the
parent structure.
* mailbox/cfg_lexer.c (isword): Take care of opening braces.
(default_lexer): Several fixes.
* mailbox/cfg_parser.y (mu_cfg_parse): Initialize debugging level
from global settings.
(_scan_tree_helper): Ensure debugging object has correct locus
information before calling the section parser.
(mu_cfg_scan_tree): If no debugging object is supplied, use the
one from diag.c
* mailbox/daemon.c (mu_daemon_create_pidfile): Return a meaningful
error code.
* mailbox/debug.c (mu_debug_create): Initialize printer to NULL.
(mu_debug_vprintf): If printer is NULL, use
mu_debug_default_printer.
(mu_debug_check_level): Bugfix.

* mailbox/server.c: Minor indentation fix.
* mailbox/syslog.c (mu_diag_syslog_printer): Chop off \r as well.
* mailbox/folder.c (mu_folder_create_from_record): Bugfixes.

* include/mailutils/debug.hm4 (mu_sockaddr_to_str)
(mu_sockaddr_to_astr): New functions.

* include/mailutils/.cvsignore: Add debug.h

* po/POTFILES.in: Update.
1 parent c060b5fd
2008-01-04 Sergey Poznyakoff <gray@gnu.org.ua>
* TODO, NEWS: Update.
* mailbox/msrv.c: New file.
* mailbox/Makefile.am: Add msrv.c.
* include/mailutils/server.h (mu_tcp_server_conn_fp): Take
sockaddr as argument
(mu_tcp_server_create,mu_tcp_server_get_sockaddr): Likewise.
(mu_m_server_*): New prototypes.
* include/mailutils/types.hin (mu_m_server_t): New type.
* mailbox/acl.c: Fix debugging output.
(mu_sockaddr_to_str, mu_sockaddr_to_astr): New functions.
* mailbox/tcpsrv.c: Handle AF_INET and AF_UNIX sockets.
* examples/echosrv.c: Update mu_tcp_server_* calls.
* examples/config/Makefile.am: Remove comsat.conf and
mailutils.rc.
* imap4d/imap4d.c, imap4d/imap4d.h, imap4d/signal.c,
maidag/lmtp.c, maidag/maidag.c, maidag/maidag.h, pop3d/extra.c,
pop3d/pop3d.c, pop3d/pop3d.h, pop3d/signal.c: Rewrite using
m-server.
* include/mailutils/cfg.h (mu_offsetof): Bug fix.
* mailbox/cfg_driver.c (dup_container): Bugfix. Offset was not
copied.
(mu_cfg_section_add_params): If identifier starts with a dot, it
is hidden, i.e. its substatements are copied directly into the
parent structure.
* mailbox/cfg_lexer.c (isword): Take care of opening braces.
(default_lexer): Several fixes.
* mailbox/cfg_parser.y (mu_cfg_parse): Initialize debugging level
from global settings.
(_scan_tree_helper): Ensure debugging object has correct locus
information before calling the section parser.
(mu_cfg_scan_tree): If no debugging object is supplied, use the
one from diag.c
* mailbox/daemon.c (mu_daemon_create_pidfile): Return a meaningful
error code.
* mailbox/debug.c (mu_debug_create): Initialize printer to NULL.
(mu_debug_vprintf): If printer is NULL, use
mu_debug_default_printer.
(mu_debug_check_level): Bugfix.
* mailbox/server.c: Minor indentation fix.
* mailbox/syslog.c (mu_diag_syslog_printer): Chop off \r as well.
* mailbox/folder.c (mu_folder_create_from_record): Bugfixes.
* include/mailutils/debug.hm4 (mu_sockaddr_to_str)
(mu_sockaddr_to_astr): New functions.
* include/mailutils/.cvsignore: Add debug.h
* po/POTFILES.in: Update.
2008-01-02 Sergey Poznyakoff <gray@gnu.org.ua>
* include/mailutils/property.h: Update
......
GNU mailutils NEWS -- history of user-visible changes. 2007-12-30
GNU mailutils NEWS -- history of user-visible changes. 2008-01-04
Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
See the end of file for copying conditions.
......@@ -72,6 +72,11 @@ pop3d, maidag). The support is controlled at compile time by the
is enabled if libwrap presence is detected. A set of configuration
file statements are provided for fine tuning TCP wrappers at run-time.
** pop3d and imap4d ports.
Pop3d and imap4d can be configured to listen on several different
IP addresses/ports (or even local sockets) simultaneously.
** pop3d: Fixed APOP handling.
** imap4d supports PREAUTH mode.
......
GNU mailutils TODO list. 2007-12-28
GNU mailutils TODO list. 2008-01-03
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006,
2007 Free Software Foundation, Inc.
2007, 2008 Free Software Foundation, Inc.
* Configuration callback functions should not modify node->tag and node->label.
* Debug handling in cfg vs. argp
* Fix folder_imap_list in libproto/imap/folder.c
* Documentation
......
......@@ -18,10 +18,8 @@
## 02110-1301 USA
EXTRA_DIST = \
comsat.conf\
dot.biffrc\
gnu-imap4d.pam\
gnu-pop3d.pam\
mailutils.dict\
mailutils.rc
mailutils.dict
......
......@@ -35,15 +35,17 @@
mu_server_t server;
int
echo_conn (int fd, struct sockaddr_in *s, void *server_data, void *call_data,
echo_conn (int fd, struct sockaddr *s, int len,
void *server_data, void *call_data,
mu_tcp_server_t srv)
{
struct sockaddr_in srv_addr;
struct sockaddr_in srv_addr, *s_in = (struct sockaddr_in *)s;
int addrlen = sizeof srv_addr;
pid_t pid;
char buf[512];
FILE *in, *out;
mu_tcp_server_get_sockaddr (srv, &srv_addr);
mu_tcp_server_get_sockaddr (srv, (struct sockaddr *)&srv_addr, &addrlen);
pid = fork ();
if (pid == -1)
......@@ -57,7 +59,7 @@ echo_conn (int fd, struct sockaddr_in *s, void *server_data, void *call_data,
mu_diag_output (MU_DIAG_INFO, "%lu: opened connection %s:%d => %s:%d",
(unsigned long) pid,
inet_ntoa (srv_addr.sin_addr), ntohs (srv_addr.sin_port),
inet_ntoa (s->sin_addr), ntohs (s->sin_port));
inet_ntoa (s_in->sin_addr), ntohs (s_in->sin_port));
return 0;
}
......@@ -132,7 +134,7 @@ create_server (char *arg)
}
s.sin_port = htons (n);
MU_ASSERT (mu_tcp_server_create (&tcpsrv, &s));
MU_ASSERT (mu_tcp_server_create (&tcpsrv, (struct sockaddr*) &s, sizeof s));
MU_ASSERT (mu_tcp_server_open (tcpsrv));
MU_ASSERT (mu_tcp_server_set_conn (tcpsrv, echo_conn));
MU_ASSERT (mu_server_add_connection (server,
......
......@@ -377,7 +377,7 @@ com_verbose (char *arg)
{
mu_debug_t debug;
mu_debug_create (&debug, NULL);
mu_debug_set_level (debug, MU_DEBUG_PROT);
mu_debug_set_level (debug, MU_DEBUG_LEVEL_UPTO (MU_DEBUG_PROT));
status = mu_nntp_set_debug (nntp, debug);
}
else
......
......@@ -364,7 +364,7 @@ com_verbose (char *arg)
{
mu_debug_t debug;
mu_debug_create (&debug, NULL);
mu_debug_set_level (debug, MU_DEBUG_PROT);
mu_debug_set_level (debug, MU_DEBUG_LEVEL_UPTO (MU_DEBUG_PROT));
status = mu_pop3_set_debug (pop3, debug);
}
else
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2001, 2002, 2003, 2004,
2005, 2006, 2007 Free Software Foundation, Inc.
2005, 2006, 2007, 2008 Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -97,6 +97,7 @@
#include <mailutils/daemon.h>
#include <mailutils/pam.h>
#include <mailutils/acl.h>
#include <mailutils/server.h>
#include <mu_asprintf.h>
#include <mu_umaxtostr.h>
......
......@@ -19,21 +19,6 @@
#define __USE_MISC
#include "imap4d.h"
RETSIGTYPE
imap4d_sigchld (int signo)
{
pid_t pid;
int status;
while ((pid = waitpid (-1, &status, WNOHANG)) > 0)
--children;
#ifndef HAVE_SIGACTION
/* On some system, signal implements the unreliable semantic and
has to be rearm. */
signal (signo, imap4d_sigchld);
#endif
}
/* Default signal handler to call the imap4d_bye() function */
RETSIGTYPE
......
/* cfg.h -- general-purpose configuration file parser
Copyright (C) 2007 Free Software Foundation, Inc.
Copyright (C) 2007, 2008 Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
......@@ -135,7 +135,7 @@ struct mu_cfg_param
const char *argname;
};
#define mu_offsetof(s,f) ((size_t)&((s*)0).f)
#define mu_offsetof(s,f) ((size_t)&((s*)0)->f)
#define MU_TARGET_REF(f) &f, 0
#define MU_TARGET_OFF(s,f) NULL, mu_offsetof(s,f)
......
/* GNU Mailutils -- a suite of utilities for electronic mail -*- c -*-
Copyright (C) 1999, 2000, 2005, 2007 Free Software Foundation, Inc.
Copyright (C) 1999, 2000, 2005, 2007, 2008 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
......@@ -92,6 +92,13 @@ int mu_global_debug_from_string (const char *, const char *);
int mu_debug_level_from_string (const char *string, mu_log_level_t *plev,
mu_debug_t debug);
struct sockaddr;
void mu_sockaddr_to_str (struct sockaddr *sa, int salen,
char *bufptr, size_t buflen,
size_t *plen);
char *mu_sockaddr_to_astr (struct sockaddr *sa, int salen);
#define MU_ASSERT(expr) \
do \
......
......@@ -19,6 +19,7 @@
#define _MAILUTILS_SERVER_H
#include <mailutils/types.h>
#include <signal.h>
typedef int (*mu_conn_loop_fp) (int fd, void *conn_data, void *server_data);
typedef void (*mu_conn_free_fp) (void *conn_data, void *server_data);
......@@ -43,15 +44,16 @@ int mu_server_count (mu_server_t srv, size_t *pcount);
/* TCP server */
struct sockaddr_in;
typedef int (*mu_tcp_server_conn_fp) (int fd, struct sockaddr_in *s,
struct sockaddr;
typedef int (*mu_tcp_server_conn_fp) (int fd, struct sockaddr *s, int len,
void *server_data, void *call_data,
mu_tcp_server_t srv);
typedef int (*mu_tcp_server_intr_fp) (void *data, void *call_data);
typedef void (*mu_tcp_server_free_fp) (void *data);
int mu_tcp_server_create (mu_tcp_server_t *psrv, struct sockaddr_in *addr);
int mu_tcp_server_create (mu_tcp_server_t *psrv, struct sockaddr *addr,
int len);
int mu_tcp_server_destroy (mu_tcp_server_t *psrv);
int mu_tcp_server_set_debug (mu_tcp_server_t srv, mu_debug_t debug);
int mu_tcp_server_get_debug (mu_tcp_server_t srv, mu_debug_t *pdebug);
......@@ -67,6 +69,32 @@ int mu_tcp_server_shutdown (mu_tcp_server_t srv);
int mu_tcp_server_accept (mu_tcp_server_t srv, void *call_data);
int mu_tcp_server_loop (mu_tcp_server_t srv, void *call_data);
int mu_tcp_server_get_fd (mu_tcp_server_t srv);
int mu_tcp_server_get_sockaddr (mu_tcp_server_t srv, struct sockaddr_in *s);
int mu_tcp_server_get_sockaddr (mu_tcp_server_t srv, struct sockaddr *s,
int *size);
/* m-server */
typedef int (*mu_m_server_conn_fp) (int, void *, time_t, int);
void mu_m_server_create (mu_m_server_t *psrv, const char *ident);
void mu_m_server_set_mode (mu_m_server_t srv, int mode);
void mu_m_server_set_conn (mu_m_server_t srv, mu_m_server_conn_fp f);
void mu_m_server_set_data (mu_m_server_t srv, void *data);
void mu_m_server_set_max_children (mu_m_server_t srv, size_t num);
int mu_m_server_set_pidfile (mu_m_server_t srv, const char *pidfile);
void mu_m_server_set_default_port (mu_m_server_t srv, int port);
void mu_m_server_set_timeout (mu_m_server_t srv, time_t t);
void mu_m_server_set_mode (mu_m_server_t srv, int mode);
void mu_m_server_set_sigset (mu_m_server_t srv, sigset_t *sigset);
int mu_m_server_mode (mu_m_server_t srv);
time_t mu_m_server_timeout (mu_m_server_t srv);
void mu_m_server_get_sigset (mu_m_server_t srv, sigset_t *sigset);
void mu_m_server_begin (mu_m_server_t msrv);
int mu_m_server_run (mu_m_server_t msrv);
void mu_m_server_cfg_init (void);
#endif
......
......@@ -108,6 +108,7 @@ typedef int mu_log_level_t;
typedef struct _mu_acl *mu_acl_t;
typedef struct _mu_server *mu_server_t;
typedef struct _mu_tcp_server *mu_tcp_server_t;
typedef struct _mu_m_server *mu_m_server_t;
#define MU_FOLDER_ATTRIBUTE_DIRECTORY 0x001
#define MU_FOLDER_ATTRIBUTE_FILE 0x002
......
......@@ -25,222 +25,7 @@
#include <signal.h>
#include <mu_umaxtostr.h>
typedef union
{
struct sockaddr sa;
struct sockaddr_in s_in;
struct sockaddr_un s_un;
} all_addr_t;
static int
lmtp_open_internal (int *pfd, mu_url_t url, const char *urlstr)
{
int fd;
int rc;
int t = 1;
char buffer[64];
all_addr_t addr;
int addrsize;
mode_t saved_umask;
rc = mu_url_get_scheme (url, buffer, sizeof buffer, NULL);
if (rc)
{
mu_error (_("%s: cannot get scheme from URL: %s"),
urlstr, mu_strerror(rc));
return EX_CONFIG;
}
memset (&addr, 0, sizeof addr);
if (strcmp (buffer, "file") == 0 || strcmp (buffer, "socket") == 0)
{
size_t size;
rc = mu_url_get_path (url, NULL, 0, &size);
if (rc)
{
mu_error (_("%s: cannot get path: %s"), urlstr, mu_strerror(rc));
return EX_CONFIG;
}
if (size > sizeof addr.s_un.sun_path - 1)
{
mu_error (_("%s: file name too long"), urlstr);
return EX_TEMPFAIL;
}
mu_url_get_path (url, addr.s_un.sun_path, sizeof addr.s_un.sun_path,
NULL);
fd = socket (PF_UNIX, SOCK_STREAM, 0);
if (fd < 0)
{
mu_error ("socket: %s", mu_strerror (errno));
return EX_TEMPFAIL;
}
addr.s_un.sun_family = AF_UNIX;
addrsize = sizeof addr.s_un;
if (reuse_lmtp_address)
{
struct stat st;
if (stat (addr.s_un.sun_path, &st))
{
if (errno != ENOENT)
{
mu_error (_("file %s exists but cannot be stat'd"),
addr.s_un.sun_path);
return EX_TEMPFAIL;
}
}
else if (!S_ISSOCK (st.st_mode))
{
mu_error (_("file %s is not a socket"),
addr.s_un.sun_path);
return EX_TEMPFAIL;
}
else
unlink (addr.s_un.sun_path);
}
}
else if (strcmp (buffer, "tcp") == 0)
{
size_t size;
long n;
struct hostent *hp;
char *path = NULL;
short port = 0;
rc = mu_url_get_port (url, &n);
if (rc)
{
mu_error (_("%s: cannot get port: %s"), urlstr, mu_strerror(rc));
return EX_CONFIG;
}
if (n == 0 || (port = n) != n)
{
mu_error (_("Port out of range: %ld"), n);
return EX_CONFIG;
}
rc = mu_url_get_host (url, NULL, 0, &size);
if (rc)
{
mu_error (_("%s: cannot get host: %s"), urlstr, mu_strerror(rc));
return EX_CONFIG;
}
path = malloc (size + 1);
if (!path)
{
mu_error (_("Not enough memory"));
return EX_TEMPFAIL;
}
mu_url_get_host (url, path, size + 1, NULL);
fd = socket (PF_INET, SOCK_STREAM, 0);
if (fd < 0)
{
mu_error ("socket: %s", mu_strerror (errno));
return EX_TEMPFAIL;
}
addr.s_in.sin_family = AF_INET;
hp = gethostbyname (path);
if (hp)
{
char **ap;
int count = 0;
addr.s_in.sin_addr.s_addr = *(unsigned long*) hp->h_addr_list[0];
for (ap = hp->h_addr_list; *ap; ap++)
count++;
if (count > 1)
mu_error (_("warning: %s has several IP addresses, using %s"),
path, inet_ntoa (addr.s_in.sin_addr));
}
else if (inet_aton (path, &addr.s_in.sin_addr) == 0)
{
mu_error ("invalid IP address: %s", path);
return EX_TEMPFAIL;
}
addr.s_in.sin_port = htons (port);
addrsize = sizeof addr.s_in;
if (reuse_lmtp_address)
setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &t, sizeof(t));
}
else
{
mu_error (_("%s: invalid scheme"), urlstr);
return EX_CONFIG;
}
saved_umask = umask (0117);
if (bind (fd, &addr.sa, addrsize) == -1)
{
mu_error ("bind: %s", strerror (errno));
close (fd);
return EXIT_FAILURE;
}
umask (saved_umask);
*pfd = fd;
return 0;
}
int
lmtp_open (int *pfd, char *urlstr)
{
mu_url_t url = NULL;
int rc;
rc = mu_url_create (&url, urlstr);
if (rc)
{
mu_error (_("%s: cannot create URL: %s"),
urlstr, mu_strerror (rc));
return EX_CONFIG;
}
rc = mu_url_parse (url);
if (rc)
{
mu_error (_("%s: error parsing URL: %s"),
urlstr, mu_strerror(rc));
return EX_CONFIG;
}
rc = lmtp_open_internal (pfd, url, urlstr);
mu_url_destroy (&url);
return rc;
}
size_t children;
static int need_cleanup = 0;
void
process_cleanup ()
{
pid_t pid;
int status;
if (need_cleanup)
{
need_cleanup = 0;
while ( (pid = waitpid (-1, &status, WNOHANG)) > 0)
--children;
}
}
RETSIGTYPE
lmtp_sigchld (int signo MU_ARG_UNUSED)
{
need_cleanup = 1;
#ifndef HAVE_SIGACTION
signal (signo, lmtp_sigchld);
#endif
}
static int lmtp_transcript;
void
lmtp_reply (FILE *fp, char *code, char *enh, char *fmt, ...)
......@@ -252,7 +37,7 @@ lmtp_reply (FILE *fp, char *code, char *enh, char *fmt, ...)
vasprintf (&str, fmt, ap);
va_end (ap);
if (mu_gocs_daemon.transcript)
if (lmtp_transcript)
{
if (enh)
mu_diag_output (MU_DIAG_INFO, "LMTP reply: %s %s %s", code, enh, str);
......@@ -697,8 +482,18 @@ getcmd (char *buf, char **sp)
return cp;
}
static char *
to_fgets (char *buf, size_t size, FILE *fp, unsigned int timeout)
{
char *p;
alarm (timeout);
p = fgets (buf, size, fp);
alarm (0);
return p;
}
int
lmtp_loop (FILE *in, FILE *out)
lmtp_loop (FILE *in, FILE *out, unsigned int timeout)
{
char buf[1024];
enum lmtp_state state = state_init;
......@@ -707,7 +502,7 @@ lmtp_loop (FILE *in, FILE *out)
setvbuf (out, NULL, _IOLBF, 0);
lmtp_reply (out, "220", NULL, "At your service");
while (fgets (buf, sizeof buf, in))
while (to_fgets (buf, sizeof buf, in, timeout))
{
if (state == state_data
&& !(buf[0] == '.'
......@@ -737,7 +532,7 @@ lmtp_loop (FILE *in, FILE *out)
trimnl (buf);
if (mu_gocs_daemon.transcript)
if (lmtp_transcript)
mu_diag_output (MU_DIAG_INFO, "LMTP recieve: %s", buf);
if (next_state != state_none)
......@@ -762,144 +557,15 @@ lmtp_loop (FILE *in, FILE *out)
}
int
check_connection (int fd, all_addr_t *addr, socklen_t addrlen)
lmtp_connection (int fd, void *data, time_t timeout, int transcript)
{
switch (addr->sa.sa_family)
{
case PF_UNIX:
mu_diag_output (MU_DIAG_INFO, _("connect from socket"));
break;
case PF_INET:
if (maidag_acl)
{
mu_acl_result_t res;
int rc = mu_acl_check_sockaddr (maidag_acl, &addr->sa, addrlen,
&res);
if (rc)
{
mu_error (_("Access from %s blocked: cannot check ACLs: %s"),
inet_ntoa (addr->s_in.sin_addr), mu_strerror (rc));
return 1;
}
switch (res)
{
case mu_acl_result_undefined:
mu_diag_output (MU_DIAG_INFO,
_("%s: undefined ACL result; access allowed"),
inet_ntoa (addr->s_in.sin_addr));
break;
case mu_acl_result_accept:
break;
case mu_acl_result_deny:
mu_error (_("Access from %s blocked."),
inet_ntoa (addr->s_in.sin_addr));
return 1;
}
}
if (!mu_tcpwrapper_access (fd))
{
mu_error (_("Access from %s blocked by tcp wrappers."),
inet_ntoa (addr->s_in.sin_addr));
return 1;
}
}
/* FIXME: TCP wrappers */
lmtp_transcript = transcript;
lmtp_loop (fdopen (fd, "r"), fdopen (fd, "w"), timeout);
return 0;
}
int
lmtp_daemon (char *urlstr)
{
int rc;
int listenfd, connfd;
all_addr_t addr;
socklen_t addrlen;
pid_t pid;
if (mu_gocs_daemon.mode == MODE_DAEMON)
{
if (daemon (0, 0) < 0)
{
mu_error (_("Failed to become a daemon"));
return EX_UNAVAILABLE;
}
}
rc = lmtp_open (&listenfd, urlstr);
if (rc)
return rc;
if (listen (listenfd, 128) == -1)
{
mu_error ("listen: %s", strerror (errno));
close (listenfd);
return EX_UNAVAILABLE;
}
#ifdef HAVE_SIGACTION
{
struct sigaction act;
act.sa_handler = lmtp_sigchld;
sigemptyset (&act.sa_mask);
act.sa_flags = 0;
sigaction (SIGCHLD, &act, NULL);
}
#else
signal (SIGCHLD, lmtp_sigchld);
#endif
for (;;)
{
process_cleanup ();
if (children > mu_gocs_daemon.maxchildren)
{
mu_error (_("too many children (%lu)"),
(unsigned long) children);
pause ();
continue;
}
addrlen = sizeof addr;
connfd = accept (listenfd, (struct sockaddr *)&addr, &addrlen);
if (connfd == -1)
{
if (errno == EINTR)
continue;
mu_error ("accept: %s", strerror (errno));
continue;
/*exit (EXIT_FAILURE);*/
}
if (check_connection (connfd, &addr, addrlen))
{
close (connfd);
continue;
}
pid = fork ();
if (pid == -1)
mu_diag_output (MU_DIAG_ERROR, "fork: %s", strerror (errno));
else if (pid == 0) /* Child. */
{
int status;
close (listenfd);
status = lmtp_loop (fdopen (connfd, "r"), fdopen (connfd, "w"));
exit (status);
}
else
{
++children;
}
close (connfd);
}
}
#define DEFAULT_URL "tcp://127.0.0.1:"
int
maidag_lmtp_server ()
{
struct group *gr = getgrnam (lmtp_group);
......@@ -916,21 +582,16 @@ maidag_lmtp_server ()
return EX_UNAVAILABLE;
}
if (lmtp_url_string)
return lmtp_daemon (lmtp_url_string);
else if (mu_gocs_daemon.mode == MODE_INTERACTIVE)
return lmtp_loop (stdin, stdout);
else
if (mu_m_server_mode (server) == MODE_DAEMON)
{
const char *pstr = mu_umaxtostr (0, mu_gocs_daemon.port);
char *urls = malloc (sizeof (DEFAULT_URL) + strlen (pstr));
if (!urls)
{
mu_error (_("Not enough memory"));
return EX_TEMPFAIL;
}
strcpy (urls, DEFAULT_URL);
strcat (urls, pstr);
return lmtp_daemon (urls);
int status;
mu_m_server_begin (server);
status = mu_m_server_run (server);
mu_m_server_end (server);
mu_m_server_destroy (&server);
if (status)
return EX_CONFIG;
}
else
return lmtp_loop (stdin, stdout, 0);
}
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2007 Free Software Foundation, Inc.
Copyright (C) 2007, 2008 Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -43,20 +43,11 @@ char *message_id_header; /* Use the value of this header as message
identifier when logging Sieve actions */
/* For LMTP mode */
mu_m_server_t server;
int lmtp_mode;
char *lmtp_url_string;
int reuse_lmtp_address = 1;
char *lmtp_group = "mail";
mu_acl_t maidag_acl; /* ACLs for LMTP mode */
struct mu_gocs_daemon daemon_param = {
MODE_INTERACTIVE, /* Start in interactive (inetd) mode */
20, /* Default maximum number of children */
0, /* No standard port */
600, /* Idle timeout */
0, /* No transcript by default */
NULL /* No PID file by default */
};
const char *program_version = "maidag (" PACKAGE_STRING ")";
static char doc[] =
......@@ -74,9 +65,15 @@ static char args_doc[] = N_("[recipient...]");
#define STDERR_OPTION 256
#define MESSAGE_ID_HEADER_OPTION 257
#define LMTP_OPTION 258
#define FOREGROUND_OPTION 260
static struct argp_option options[] =
{
{ "foreground", FOREGROUND_OPTION, 0, 0, N_("Remain in foreground."), 0 },
{ "inetd", 'i', 0, 0, N_("Run in inetd mode"), 0 },
{ "daemon", 'd', N_("NUMBER"), OPTION_ARG_OPTIONAL,
N_("Runs in daemon mode with a maximum of NUMBER children"), 0 },
{ "from", 'f', N_("EMAIL"), 0,
N_("Specify the sender's name") },
{ NULL, 'r', NULL, OPTION_ALIAS, NULL },
......@@ -109,7 +106,6 @@ static struct argp argp = {
};
static const char *maidag_argp_capa[] = {
"daemon",
"auth",
"common",
"debug",
......@@ -174,6 +170,20 @@ parse_opt (int key, char *arg, struct argp_state *state)
switch (key)
{
case 'd':
mu_argp_node_list_new (&lst, "mode", "daemon");
if (arg)
mu_argp_node_list_new (&lst, "max-children", arg);
break;
case 'i':
mu_argp_node_list_new (&lst, "mode", "inetd");
break;
case FOREGROUND_OPTION:
mu_argp_node_list_new (&lst, "foreground", "yes");
break;
case MESSAGE_ID_HEADER_OPTION:
mu_argp_node_list_new (&lst, "message-id-header", arg);
break;
......@@ -291,7 +301,8 @@ struct mu_cfg_param maidag_cfg_param[] = {
N_("url") },
{ "reuse-address", mu_cfg_bool, &reuse_lmtp_address, 0, NULL,
N_("Reuse existing address (LMTP mode). Default is \"yes\".") },
{ "acl", mu_cfg_section, },
{ ".server", mu_cfg_section, NULL, 0, NULL,
N_("LMTP server configuration.") },
TCP_WRAPPERS_CONFIG
{ NULL }
};
......@@ -458,15 +469,21 @@ main (int argc, char *argv[])
mu_gocs_register ("sieve", mu_sieve_module_init);
mu_gocs_daemon = daemon_param;
mu_tcpwrapper_cfg_init ();
mu_acl_cfg_init ();
mu_m_server_cfg_init ();
/* Parse command line */
mu_argp_init (program_version, NULL);
mu_m_server_create (&server, "GNU maidag");
mu_m_server_set_conn (server, lmtp_connection);
mu_m_server_set_mode (server, MODE_INTERACTIVE);
mu_m_server_set_max_children (server, 20);
mu_m_server_set_timeout (server, 600);
if (mu_app_init (&argp, maidag_argp_capa, maidag_cfg_param,
argc, argv, 0, &arg_index, &maidag_acl))
argc, argv, 0, &arg_index, server))
exit (EX_CONFIG);
current_uid = getuid ();
......@@ -481,12 +498,8 @@ main (int argc, char *argv[])
openlog ("maidag", LOG_PID, log_facility);
mu_diag_get_debug (&debug);
mu_debug_set_print (debug, mu_diag_syslog_printer, NULL);
/* FIXME: this should be done automatically by cfg */
if (maidag_acl)
{
mu_acl_get_debug (maidag_acl, &debug);
mu_debug_set_print (debug, mu_debug_syslog_printer, NULL);
}
mu_debug_default_printer = mu_debug_syslog_printer;
}
argc -= arg_index;
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2007 Free Software Foundation, Inc.
Copyright (C) 2007, 2008 Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -84,6 +84,7 @@
#include <mailutils/nls.h>
#include <mailutils/daemon.h>
#include <mailutils/acl.h>
#include <mailutils/server.h>
#include <mu_dbm.h>
#include <mu_asprintf.h>
......@@ -120,6 +121,7 @@ extern char *sender_address;
extern char *progfile_pattern;
extern char *sieve_pattern;
extern mu_m_server_t server;
extern int lmtp_mode;
extern char *lmtp_url_string;
extern int reuse_lmtp_address;
......@@ -131,6 +133,7 @@ int switch_user_id (struct mu_auth_data *auth, int user);
int maidag_stdio_delivery (int argc, char **argv);
int maidag_lmtp_server (void);
int lmtp_connection (int fd, void *data, time_t timeout, int transcript);
void mailer_err (char *fmt, ...);
void notify_biff (mu_mailbox_t mbox, char *name, size_t size);
......
......@@ -82,6 +82,7 @@ libmailutils_la_SOURCES = \
message_stream.c\
mime.c\
monitor.c\
msrv.c\
mu_auth.c\
mu_umaxtostr.h\
mu_umaxtostr.c\
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2007 Free Software Foundation, Inc.
Copyright (C) 2007, 2008 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
......@@ -307,16 +307,17 @@ mu_acl_string_to_action (const char *str, mu_acl_action_t *pres)
return rc;
}
void
static void
debug_sockaddr (mu_debug_t dbg, mu_log_level_t lvl, struct sockaddr *sa)
{
switch (sa->sa_family)
{
case AF_INET:
{
struct sockaddr_in *s_in = (struct sockaddr_in *)sa;
struct sockaddr_in s_in = *(struct sockaddr_in *)sa;
s_in.sin_addr.s_addr = htonl (s_in.sin_addr.s_addr);
mu_debug_printf (dbg, lvl, "{AF_INET %s:%d}",
inet_ntoa (s_in->sin_addr), ntohs (s_in->sin_port));
inet_ntoa (s_in.sin_addr), ntohs (s_in.sin_port));
break;
}
......@@ -332,6 +333,77 @@ debug_sockaddr (mu_debug_t dbg, mu_log_level_t lvl, struct sockaddr *sa)
}
}
size_t
mu_stpcpy (char **pbuf, size_t *psize, const char *src)
{
size_t slen = strlen (src);
if (pbuf == NULL || *pbuf == NULL)
return slen;
else
{
char *buf = *pbuf;
size_t size = *psize;
if (size > slen)
size = slen;
memcpy (buf, src, size);
*psize -= size;
*pbuf += size;
if (*psize)
**pbuf = 0;
else
(*pbuf)[-1] = 0;
return size;
}
}
void
mu_sockaddr_to_str (struct sockaddr *sa, int salen,
char *bufptr, size_t buflen,
size_t *plen)
{
char buf[UINTMAX_STRSIZE_BOUND]; /* FIXME: too much */
size_t len = 0;
switch (sa->sa_family)
{
case AF_INET:
{
struct sockaddr_in s_in = *(struct sockaddr_in *)sa;
len += mu_stpcpy (&bufptr, &buflen, inet_ntoa (s_in.sin_addr));
len += mu_stpcpy (&bufptr, &buflen, ":");
len += mu_stpcpy (&bufptr, &buflen, umaxtostr (ntohs (s_in.sin_port),
buf));
break;
}
case AF_UNIX:
{
struct sockaddr_un *s_un = (struct sockaddr_un *)sa;
len += mu_stpcpy (&bufptr, &buflen, "socket ");
len += mu_stpcpy (&bufptr, &buflen, s_un->sun_path);
break;
}
default:
len += mu_stpcpy (&bufptr, &buflen, "{Unsupported family: ");
len += mu_stpcpy (&bufptr, &buflen, umaxtostr (sa->sa_family, buf));
}
if (plen)
*plen = len + 1;
}
char *
mu_sockaddr_to_astr (struct sockaddr *sa, int salen)
{
size_t size;
char *p;
mu_sockaddr_to_str (sa, salen, NULL, 0, &size);
p = malloc (size);
if (p)
mu_sockaddr_to_str (sa, salen, p, size, NULL);
return p;
}
int
_acl_match (mu_debug_t debug, struct _mu_acl_entry *ent, struct sockaddr *sa)
{
......@@ -348,6 +420,7 @@ _acl_match (mu_debug_t debug, struct _mu_acl_entry *ent, struct sockaddr *sa)
mu_debug_printf (debug, MU_DEBUG_TRACE0, " match ");
debug_sockaddr (debug, MU_DEBUG_TRACE0, ent->sa);
a.s_addr = ent->netmask;
a.s_addr = htonl (a.s_addr);
mu_debug_printf (debug, MU_DEBUG_TRACE0, " netmask %s? ", inet_ntoa (a));
}
......
/* cfg_driver.c -- Main driver for Mailutils configuration files
Copyright (C) 2007 Free Software Foundation, Inc.
Copyright (C) 2007, 2008 Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
......@@ -163,6 +163,7 @@ dup_container (struct mu_cfg_cont **pcont)
newcont->v.section.label = oldcont->v.section.label;
newcont->v.section.parser = oldcont->v.section.parser;
newcont->v.section.target = oldcont->v.section.target;
newcont->v.section.offset = oldcont->v.section.offset;
newcont->v.section.docstring = oldcont->v.section.docstring;
newcont->v.section.children = NULL;
mu_list_do (oldcont->v.section.children, _dup_cont_action, &dd);
......@@ -259,8 +260,41 @@ mu_cfg_section_add_params (struct mu_cfg_section *sect,
param->ident);
abort ();
}
mu_config_clone_container (container);
container->v.section.offset = param->offset;
if (param->ident[0] == '.')
{
mu_iterator_t itr;
mu_list_get_iterator (container->v.section.children, &itr);
for (mu_iterator_first (itr);
!mu_iterator_is_done (itr);
mu_iterator_next (itr))
{
struct mu_cfg_cont *c;
mu_iterator_current (itr, (void**)&c);
mu_config_clone_container (c);
if (mu_refcount_value (c->refcount) > 1)
dup_container (&c);
switch (c->type)
{
case mu_cfg_cont_section:
c->v.section.offset += param->offset;
break;
case mu_cfg_cont_param:
container->v.param.offset += param->offset;
break;
}
mu_cfg_section_add_container (sect, c);
}
mu_iterator_destroy (&itr);
continue;
}
else
{
mu_config_clone_container (container);
if (mu_refcount_value (container->refcount) > 1)
dup_container (&container);
container->v.section.offset = param->offset;
}
}
else
{
......
/* cfg_lexer.c -- default lexer for Mailutils configuration files
Copyright (C) 2007 Free Software Foundation, Inc.
Copyright (C) 2007, 2008 Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
......@@ -118,7 +118,7 @@ static int
isword (int c)
{
if (mu_cfg_tie_in)
return c && c != ';';
return c && c != ';' && c != '{';
return isalnum (c) || c == '_' || c == '-' || c == '.';
}
......@@ -137,6 +137,22 @@ copy_alpha (struct lexer_data *p)
return cbuf_finish (p);
}
static char *
copy_to (struct lexer_data *p, const char *delim)
{
while (*p->curp)
{
if (strchr (delim, *p->curp))
break;
if (*p->curp == '\n')
mu_cfg_locus.line++;
cbuf_1grow (p, *p->curp);
p->curp++;
}
cbuf_1grow (p, 0);
return cbuf_finish (p);
}
static int
continuation_line_p (struct lexer_data *p, int quote)
{
......@@ -210,6 +226,15 @@ copy_string (struct lexer_data *p)
} \
while (0)
static void
rtrim (char *arg)
{
int len = strlen (arg);
while (len > 0 && strchr (" \t\n\r", arg[len-1]))
len--;
arg[len] = 0;
}
int
default_lexer (void *dp, mu_debug_t dbg)
{
......@@ -308,9 +333,10 @@ again:
LEX_DEBUG ("EOL", NULL, NULL);
return MU_CFG_EOL_TOKEN;
}
tag = copy_alpha (p);
skipws (p);
if (*p->curp == '"')
{
mu_cfg_yylval.string = tag;
......@@ -321,8 +347,8 @@ again:
save_start = p->curp;
if (*p->curp != '{')
{
label = copy_alpha (p);
skipws (p);
label = copy_to (p, ";{");
rtrim (label);
}
else
label = NULL;
......
%{
/* cfg_parser.y -- general-purpose configuration file parser
Copyright (C) 2007 Free Software Foundation, Inc.
Copyright (C) 2007, 2008 Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
......@@ -260,8 +260,17 @@ mu_cfg_parse (mu_cfg_tree_t **ptree,
_mu_cfg_debug = debug;
else
{
mu_log_level_t level;
mu_debug_create (&_mu_cfg_debug, NULL);
mu_debug_set_print (_mu_cfg_debug, _cfg_default_printer, NULL);
level = mu_global_debug_level ("config");
if (level)
{
mu_debug_set_level (_mu_cfg_debug, level);
if (level & MU_DEBUG_LEVEL_MASK (MU_DEBUG_TRACE7))
yydebug = 1;
}
}
_mu_cfg_alloc = palloc ? palloc : malloc;
_mu_cfg_free = pfree ? pfree : free;
......@@ -1006,13 +1015,19 @@ _scan_tree_helper (const mu_cfg_node_t *node, void *data)
sec->target = (char*)sdata->list->sec->target + sec->offset;
else if (sdata->target)
sec->target = (char*)sdata->target + sec->offset;
if (sec->parser &&
sec->parser (mu_cfg_section_start, node,
sec->label, &sec->target,
sdata->call_data, sdata->tree))
if (sec->parser)
{
sdata->error++;
return MU_CFG_ITER_SKIP;
mu_debug_set_locus (sdata->tree->debug,
node->locus.file ?
node->locus.file : _("unknown file"),
node->locus.line);
if (sec->parser (mu_cfg_section_start, node,
sec->label, &sec->target,
sdata->call_data, sdata->tree))
{
sdata->error++;
return MU_CFG_ITER_SKIP;
}
}
push_section(sdata, sec);
break;
......@@ -1059,15 +1074,26 @@ int
mu_cfg_scan_tree (mu_cfg_tree_t *tree, struct mu_cfg_section *sections,
void *target, void *data)
{
mu_debug_t debug = NULL;
struct scan_tree_data dat;
dat.tree = tree;
dat.list = NULL;
dat.error = 0;
dat.call_data = data;
dat.target = target;
if (!tree->debug)
{
mu_diag_get_debug (&debug);
tree->debug = debug;
}
if (push_section (&dat, sections))
return 1;
mu_cfg_preorder (tree->node, _scan_tree_helper, _scan_tree_end_helper, &dat);
if (debug)
{
mu_debug_set_locus (debug, NULL, 0);
tree->debug = NULL;
}
pop_section (&dat);
return dat.error;
}
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
......@@ -29,6 +29,7 @@
#include <string.h>
#include <mailutils/daemon.h>
#include <mailutils/errno.h>
#include <mu_umaxtostr.h>
static char *pidfile;
......@@ -42,7 +43,7 @@ mu_daemon_create_pidfile (const char *filename)
if (filename[0] != '/')
{
return 1; /* failure */
return EINVAL; /* failure */
}
if (pidfile)
......@@ -55,7 +56,7 @@ mu_daemon_create_pidfile (const char *filename)
if ((fd = open (pidfile, O_WRONLY | O_CREAT
| O_TRUNC | O_EXCL, 0644)) == -1)
{
return 2; /* failure */
return errno; /* failure */
}
pid_string = mu_umaxtostr (0, current_pid);
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2004, 2005,
2007 Free Software Foundation, Inc.
2007, 2008 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
......@@ -41,7 +41,7 @@ mu_debug_create (mu_debug_t *pdebug, void *owner)
debug = calloc (sizeof (*debug), 1);
if (debug == NULL)
return ENOMEM;
debug->printer = mu_debug_default_printer;
debug->printer = NULL;
debug->owner = owner;
*pdebug = debug;
return 0;
......@@ -146,10 +146,13 @@ int
mu_debug_vprintf (mu_debug_t debug, mu_log_level_t level,
const char *format, va_list ap)
{
mu_debug_printer_fp printer;
if (debug == NULL || format == NULL)
return EINVAL;
if (debug->printer)
printer = debug->printer ? debug->printer : mu_debug_default_printer;
if (printer)
{
mu_off_t len;
mu_transport_t tbuf;
......@@ -186,7 +189,7 @@ mu_debug_vprintf (mu_debug_t debug, mu_log_level_t level,
{
int c = *++p;
*p = 0;
debug->printer (debug->data, level, ptr);
printer (debug->data, level, ptr);
*p = c;
ptr = p;
nseg++;
......@@ -252,7 +255,7 @@ mu_debug_check_level (mu_debug_t debug, mu_log_level_t level)
{
if (!debug)
return 0;
return debug->level & level;
return debug->level & MU_DEBUG_LEVEL_MASK (level);
}
int
......
......@@ -90,7 +90,7 @@ mu_folder_create_from_record (mu_folder_t *pfolder, const char *name,
status = mu_url_parse (url);
if (status)
{
mu_url_destroy (url);
mu_url_destroy (&url);
return status;
}
mu_record_get_url (record, &u_init);
......@@ -99,7 +99,7 @@ mu_folder_create_from_record (mu_folder_t *pfolder, const char *name,
status = u_init (url);
if (status)
{
mu_url_destroy (url);
mu_url_destroy (&url);
return status;
}
}
......
......@@ -164,7 +164,7 @@ mu_server_run (mu_server_t srv)
if (rc == -1 && errno == EINTR)
{
if (srv->f_idle && srv->f_idle (srv->server_data))
break;
break;
continue;
}
if (rc < 0)
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2007 Free Software Foundation, Inc.
Copyright (C) 2007, 2008 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
......@@ -125,7 +125,11 @@ mu_diag_syslog_printer (void *data, mu_log_level_t level, const char *buf)
{
int len = strlen (buf);
if (len > 0 && buf[len-1] == '\n')
len--;
{
len--;
if (len > 0 && buf[len-1] == '\r')
len--;
}
syslog (mu_diag_level_to_syslog (level), "%-.*s", len, buf);
return 0;
}
......
......@@ -21,7 +21,9 @@
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
......@@ -31,12 +33,14 @@
#include <mailutils/debug.h>
#include <mailutils/diag.h>
#include <mailutils/errno.h>
#include <mailutils/nls.h>
struct _mu_tcp_server
{
char *ident;
struct sockaddr_in addr;
struct sockaddr *addr;
int addrlen;
int backlog;
int fd;
mu_debug_t debug;
......@@ -50,8 +54,8 @@ struct _mu_tcp_server
#define IDENTSTR(s) ((s)->ident ? (s)->ident : "default")
int
mu_tcp_server_create (mu_tcp_server_t *psrv,
struct sockaddr_in *addr)
mu_tcp_server_create (mu_tcp_server_t *psrv, struct sockaddr *addr,
int addrlen)
{
struct _mu_tcp_server *srv;
mu_log_level_t level;
......@@ -59,8 +63,15 @@ mu_tcp_server_create (mu_tcp_server_t *psrv,
srv = calloc (1, sizeof *srv);
if (!srv)
return ENOMEM;
srv->addr = *addr;
level = mu_global_debug_level ("mailbox");
srv->addr = calloc (1, addrlen);
if (!srv->addr)
{
free (srv);
return ENOMEM;
}
memcpy (srv->addr, addr, addrlen);
srv->addrlen = addrlen;
level = mu_global_debug_level ("tcp_server");
if (level)
{
mu_debug_create (&srv->debug, NULL);
......@@ -84,6 +95,7 @@ mu_tcp_server_destroy (mu_tcp_server_t *psrv)
if (srv->f_free)
srv->f_free (srv->data);
close (srv->fd);
free (srv->addr);
free (srv->ident);
free (srv);
*psrv = NULL;
......@@ -169,31 +181,93 @@ mu_tcp_server_set_data (mu_tcp_server_t srv,
return 0;
}
static int
family_to_proto (int family)
{
switch (family)
{
case AF_UNIX:
return PF_UNIX;
case AF_INET:
return PF_INET;
default:
abort ();
}
}
int
mu_tcp_server_open (mu_tcp_server_t srv)
{
int fd;
int t;
if (!srv || srv->fd != -1)
return EINVAL;
MU_DEBUG3 (srv->debug, MU_DEBUG_TRACE0,
"opening server \"%s\" %s:%d\n", IDENTSTR (srv),
inet_ntoa (srv->addr.sin_addr), ntohs (srv->addr.sin_port));
if (mu_debug_check_level (srv->debug, MU_DEBUG_TRACE0))
{
char *p = mu_sockaddr_to_astr (srv->addr, srv->addrlen);
__MU_DEBUG2 (srv->debug, MU_DEBUG_TRACE0,
"opening server \"%s\" %s\n", IDENTSTR (srv),
p);
free (p);
}
fd = socket (PF_INET, SOCK_STREAM, 0);
fd = socket (family_to_proto (srv->addr->sa_family), SOCK_STREAM, 0);
if (fd == -1)
{
MU_DEBUG2 (srv->debug, MU_DEBUG_ERROR,
"%s: socket: %s\n", IDENTSTR (srv), mu_strerror (errno));
return errno;
}
switch (srv->addr->sa_family)
{
case AF_UNIX:
{
struct stat st;
struct sockaddr_un *s_un = (struct sockaddr_un *) srv->addr;
if (stat (s_un->sun_path, &st))
{
if (errno != ENOENT)
{
MU_DEBUG3 (srv->debug, MU_DEBUG_ERROR,
_("%s: file %s exists but cannot be stat'd: %s"),
IDENTSTR (srv),
s_un->sun_path,
mu_strerror (errno));
return EAGAIN;
}
}
else if (!S_ISSOCK (st.st_mode))
{
MU_DEBUG2 (srv->debug, MU_DEBUG_ERROR,
_("%s: file %s is not a socket"),
IDENTSTR (srv), s_un->sun_path);
return EAGAIN;
}
else if (unlink (s_un->sun_path))
{
MU_DEBUG3 (srv->debug, MU_DEBUG_ERROR,
_("%s: cannot unlink file %s: %s"),
IDENTSTR (srv), s_un->sun_path, mu_strerror (errno));
return EAGAIN;
}
}
break;
t = 1;
setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &t, sizeof (t));
if (bind (fd, (struct sockaddr *) &srv->addr, sizeof (srv->addr)) == -1)
case AF_INET:
{
int t;
t = 1;
setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &t, sizeof (t));
}
}
if (bind (fd, srv->addr, srv->addrlen) == -1)
{
MU_DEBUG2 (srv->debug, MU_DEBUG_ERROR,
"%s: bind: %s\n", IDENTSTR (srv), mu_strerror (errno));
......@@ -218,10 +292,14 @@ mu_tcp_server_shutdown (mu_tcp_server_t srv)
{
if (!srv || srv->fd != -1)
return EINVAL;
MU_DEBUG4 (srv->debug, MU_DEBUG_TRACE0,
"closing server \"%s\" %s:%d, fd %d\n", IDENTSTR (srv),
inet_ntoa (srv->addr.sin_addr), ntohs (srv->addr.sin_port),
srv->fd);
if (mu_debug_check_level (srv->debug, MU_DEBUG_TRACE0))
{
char *p = mu_sockaddr_to_astr (srv->addr, srv->addrlen);
__MU_DEBUG2 (srv->debug, MU_DEBUG_TRACE0,
"closing server \"%s\" %s\n", IDENTSTR (srv),
p);
free (p);
}
close (srv->fd);
return 0;
}
......@@ -231,13 +309,18 @@ mu_tcp_server_accept (mu_tcp_server_t srv, void *call_data)
{
int rc;
int connfd;
struct sockaddr_in client;
union
{
struct sockaddr sa;
char buffer[512];
} client;
socklen_t size = sizeof (client);
if (!srv || srv->fd == -1)
return EINVAL;
connfd = accept (srv->fd, (struct sockaddr *) &client, &size);
connfd = accept (srv->fd, &client.sa, &size);
if (connfd == -1)
{
int ec = errno;
......@@ -252,26 +335,26 @@ mu_tcp_server_accept (mu_tcp_server_t srv, void *call_data)
if (srv->acl)
{
mu_acl_result_t res;
int rc = mu_acl_check_sockaddr (srv->acl, (struct sockaddr *) &client,
size, &res);
int rc = mu_acl_check_sockaddr (srv->acl, &client.sa, size, &res);
if (rc)
MU_DEBUG2 (srv->debug, MU_DEBUG_ERROR,
"%s: mu_acl_check_sockaddr: %s\n",
IDENTSTR (srv), strerror (rc));
if (res == mu_acl_result_deny)
{
mu_diag_output (MU_DIAG_INFO, "Denying connection from %s:%d",
inet_ntoa (client.sin_addr),
ntohs (client.sin_port));
char *p = mu_sockaddr_to_astr (srv->addr, srv->addrlen);
mu_diag_output (MU_DIAG_INFO, "Denying connection from %s", p);
free (p);
close (connfd);
return 0;
}
}
rc = srv->f_conn (connfd, &client, srv->data, call_data, srv);
rc = srv->f_conn (connfd, &client.sa, size, srv->data, call_data, srv);
if (rc)
mu_tcp_server_shutdown (srv);
close (connfd);
return 0;
return rc;
}
int
......@@ -298,11 +381,22 @@ mu_tcp_server_get_fd (mu_tcp_server_t srv)
}
int
mu_tcp_server_get_sockaddr (mu_tcp_server_t srv, struct sockaddr_in *s)
mu_tcp_server_get_sockaddr (mu_tcp_server_t srv, struct sockaddr *s, int *size)
{
int len;
if (!srv || !s)
return EINVAL;
memcpy (s, &srv->addr, sizeof (*s));
if (s == 0)
len = srv->addrlen;
else
{
len = *size;
if (len < srv->addrlen)
len = srv->addrlen;
memcpy (s, srv->addr, len);
}
*size = len;
return 0;
}
......
......@@ -383,7 +383,7 @@ main (int argc, char *argv[])
tickets = mu_tilde_expansion ("~/.tickets", "/", NULL);
tickets_default = 1;
debug_level = MU_DEBUG_ERROR;
debug_level = MU_DEBUG_LEVEL_MASK (MU_DEBUG_ERROR);
log_facility = 0;
if (mu_app_init (&argp, sieve_argp_capa, sieve_cfg_param,
......