diff options
Diffstat (limited to 'src/global/mail_connect.c')
-rw-r--r-- | src/global/mail_connect.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/src/global/mail_connect.c b/src/global/mail_connect.c new file mode 100644 index 0000000..4fdfe78 --- /dev/null +++ b/src/global/mail_connect.c @@ -0,0 +1,127 @@ +/*++ +/* NAME +/* mail_connect 3 +/* SUMMARY +/* intra-mail system connection management +/* SYNOPSIS +/* #include <mail_proto.h> +/* +/* VSTREAM *mail_connect(class, name, block_mode) +/* const char *class; +/* const char *name; +/* int block_mode; +/* +/* VSTREAM *mail_connect_wait(class, name) +/* const char *class; +/* const char *name; +/* DESCRIPTION +/* This module does low-level connection management for intra-mail +/* communication. All reads and writes are subject to a time limit +/* (controlled by the global variable \fIvar_ipc_timeout\fR). This +/* protects against deadlock conditions that should never happen. +/* +/* mail_connect() attempts to connect to the UNIX-domain socket of +/* the named subsystem. The result is a null pointer in case of failure. +/* By default this function provides no errno logging. +/* +/* mail_connect_wait() is like mail_connect(), but keeps trying until +/* the connection succeeds. However, mail_connect_wait() terminates +/* with a fatal error when the service is down. This is to ensure that +/* processes terminate when the mail system shuts down. +/* +/* Arguments: +/* .IP class +/* Name of a class of local transport channel endpoints, +/* either \fIpublic\fR (accessible by any local user) or +/* \fIprivate\fR (administrative access only). +/* .IP service +/* The name of a local transport endpoint within the named class. +/* .IP block_mode +/* NON_BLOCKING for a non-blocking connection, or BLOCKING. +/* SEE ALSO +/* timed_ipc(3), enforce IPC timeouts. +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +/* System library. */ + +#include <sys_defs.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdarg.h> +#include <errno.h> + +/* Utility library. */ + +#include <msg.h> +#include <vstream.h> +#include <connect.h> +#include <mymalloc.h> +#include <iostuff.h> +#include <stringops.h> + +/* Global library. */ + +#include "timed_ipc.h" +#include "mail_proto.h" + +/* mail_connect - connect to mail subsystem */ + +VSTREAM *mail_connect(const char *class, const char *name, int block_mode) +{ + char *path; + VSTREAM *stream; + int fd; + char *sock_name; + + path = mail_pathname(class, name); + if ((fd = LOCAL_CONNECT(path, block_mode, 0)) < 0) { + if (msg_verbose) + msg_info("connect to subsystem %s: %m", path); + stream = 0; + } else { + if (msg_verbose) + msg_info("connect to subsystem %s", path); + stream = vstream_fdopen(fd, O_RDWR); + timed_ipc_setup(stream); + sock_name = concatenate(path, " socket", (char *) 0); + vstream_control(stream, + CA_VSTREAM_CTL_PATH(sock_name), + CA_VSTREAM_CTL_END); + myfree(sock_name); + } + myfree(path); + return (stream); +} + +/* mail_connect_wait - connect to mail service until it succeeds */ + +VSTREAM *mail_connect_wait(const char *class, const char *name) +{ + VSTREAM *stream; + int count = 0; + + /* + * XXX Solaris workaround for ECONNREFUSED on a busy socket. + */ + while ((stream = mail_connect(class, name, BLOCKING)) == 0) { + if (count++ >= 10) { + msg_fatal("connect #%d to subsystem %s/%s: %m", + count, class, name); + } else { + msg_warn("connect #%d to subsystem %s/%s: %m", + count, class, name); + } + sleep(10); /* XXX make configurable */ + } + return (stream); +} |