xref: /netbsd-src/external/ibm-public/postfix/dist/src/global/mail_connect.c (revision e89934bbf778a6d6d6894877c4da59d0c7835b0f)
1*e89934bbSchristos /*	$NetBSD: mail_connect.c,v 1.2 2017/02/14 01:16:45 christos Exp $	*/
241fbaed0Stron 
341fbaed0Stron /*++
441fbaed0Stron /* NAME
541fbaed0Stron /*	mail_connect 3
641fbaed0Stron /* SUMMARY
741fbaed0Stron /*	intra-mail system connection management
841fbaed0Stron /* SYNOPSIS
941fbaed0Stron /*	#include <mail_proto.h>
1041fbaed0Stron /*
1141fbaed0Stron /*	VSTREAM *mail_connect(class, name, block_mode)
1241fbaed0Stron /*	const char *class;
1341fbaed0Stron /*	const char *name;
1441fbaed0Stron /*	int	block_mode;
1541fbaed0Stron /*
1641fbaed0Stron /*	VSTREAM *mail_connect_wait(class, name)
1741fbaed0Stron /*	const char *class;
1841fbaed0Stron /*	const char *name;
1941fbaed0Stron /* DESCRIPTION
2041fbaed0Stron /*	This module does low-level connection management for intra-mail
2141fbaed0Stron /*	communication.  All reads and writes are subject to a time limit
2241fbaed0Stron /*	(controlled by the global variable \fIvar_ipc_timeout\fR). This
2341fbaed0Stron /*	protects against deadlock conditions that should never happen.
2441fbaed0Stron /*
2541fbaed0Stron /*	mail_connect() attempts to connect to the UNIX-domain socket of
2641fbaed0Stron /*	the named subsystem. The result is a null pointer in case of failure.
27e262b48eSchristos /*	By default this function provides no errno logging.
2841fbaed0Stron /*
2941fbaed0Stron /*	mail_connect_wait() is like mail_connect(), but keeps trying until
3041fbaed0Stron /*	the connection succeeds. However, mail_connect_wait() terminates
3141fbaed0Stron /*	with a fatal error when the service is down. This is to ensure that
3241fbaed0Stron /*	processes terminate when the mail system shuts down.
3341fbaed0Stron /*
3441fbaed0Stron /*	Arguments:
3541fbaed0Stron /* .IP class
3641fbaed0Stron /*	Name of a class of local transport channel endpoints,
3741fbaed0Stron /*	either \fIpublic\fR (accessible by any local user) or
3841fbaed0Stron /*	\fIprivate\fR (administrative access only).
3941fbaed0Stron /* .IP service
4041fbaed0Stron /*	The name of a local transport endpoint within the named class.
4141fbaed0Stron /* .IP block_mode
4241fbaed0Stron /*	NON_BLOCKING for a non-blocking connection, or BLOCKING.
4341fbaed0Stron /* SEE ALSO
4441fbaed0Stron /*	timed_ipc(3), enforce IPC timeouts.
4541fbaed0Stron /* LICENSE
4641fbaed0Stron /* .ad
4741fbaed0Stron /* .fi
4841fbaed0Stron /*	The Secure Mailer license must be distributed with this software.
4941fbaed0Stron /* AUTHOR(S)
5041fbaed0Stron /*	Wietse Venema
5141fbaed0Stron /*	IBM T.J. Watson Research
5241fbaed0Stron /*	P.O. Box 704
5341fbaed0Stron /*	Yorktown Heights, NY 10598, USA
5441fbaed0Stron /*--*/
5541fbaed0Stron 
5641fbaed0Stron /* System library. */
5741fbaed0Stron 
5841fbaed0Stron #include <sys_defs.h>
5941fbaed0Stron #include <fcntl.h>
6041fbaed0Stron #include <unistd.h>
6141fbaed0Stron #include <stdlib.h>
6241fbaed0Stron #include <stdarg.h>
6341fbaed0Stron #include <errno.h>
6441fbaed0Stron 
6541fbaed0Stron /* Utility library. */
6641fbaed0Stron 
6741fbaed0Stron #include <msg.h>
6841fbaed0Stron #include <vstream.h>
6941fbaed0Stron #include <connect.h>
7041fbaed0Stron #include <mymalloc.h>
7141fbaed0Stron #include <iostuff.h>
7241fbaed0Stron #include <stringops.h>
7341fbaed0Stron 
7441fbaed0Stron /* Global library. */
7541fbaed0Stron 
7641fbaed0Stron #include "timed_ipc.h"
7741fbaed0Stron #include "mail_proto.h"
7841fbaed0Stron 
7941fbaed0Stron /* mail_connect - connect to mail subsystem */
8041fbaed0Stron 
mail_connect(const char * class,const char * name,int block_mode)8141fbaed0Stron VSTREAM *mail_connect(const char *class, const char *name, int block_mode)
8241fbaed0Stron {
8341fbaed0Stron     char   *path;
8441fbaed0Stron     VSTREAM *stream;
8541fbaed0Stron     int     fd;
8641fbaed0Stron     char   *sock_name;
8741fbaed0Stron 
8841fbaed0Stron     path = mail_pathname(class, name);
8941fbaed0Stron     if ((fd = LOCAL_CONNECT(path, block_mode, 0)) < 0) {
9041fbaed0Stron 	if (msg_verbose)
9141fbaed0Stron 	    msg_info("connect to subsystem %s: %m", path);
9241fbaed0Stron 	stream = 0;
9341fbaed0Stron     } else {
9441fbaed0Stron 	if (msg_verbose)
9541fbaed0Stron 	    msg_info("connect to subsystem %s", path);
9641fbaed0Stron 	stream = vstream_fdopen(fd, O_RDWR);
9741fbaed0Stron 	timed_ipc_setup(stream);
9841fbaed0Stron 	sock_name = concatenate(path, " socket", (char *) 0);
9941fbaed0Stron 	vstream_control(stream,
100e262b48eSchristos 			CA_VSTREAM_CTL_PATH(sock_name),
101e262b48eSchristos 			CA_VSTREAM_CTL_END);
10241fbaed0Stron 	myfree(sock_name);
10341fbaed0Stron     }
10441fbaed0Stron     myfree(path);
10541fbaed0Stron     return (stream);
10641fbaed0Stron }
10741fbaed0Stron 
10841fbaed0Stron /* mail_connect_wait - connect to mail service until it succeeds */
10941fbaed0Stron 
mail_connect_wait(const char * class,const char * name)11041fbaed0Stron VSTREAM *mail_connect_wait(const char *class, const char *name)
11141fbaed0Stron {
11241fbaed0Stron     VSTREAM *stream;
11341fbaed0Stron     int     count = 0;
11441fbaed0Stron 
11541fbaed0Stron     /*
11641fbaed0Stron      * XXX Solaris workaround for ECONNREFUSED on a busy socket.
11741fbaed0Stron      */
11841fbaed0Stron     while ((stream = mail_connect(class, name, BLOCKING)) == 0) {
11941fbaed0Stron 	if (count++ >= 10) {
12041fbaed0Stron 	    msg_fatal("connect #%d to subsystem %s/%s: %m",
12141fbaed0Stron 		      count, class, name);
12241fbaed0Stron 	} else {
12341fbaed0Stron 	    msg_warn("connect #%d to subsystem %s/%s: %m",
12441fbaed0Stron 		     count, class, name);
12541fbaed0Stron 	}
12641fbaed0Stron 	sleep(10);				/* XXX make configurable */
12741fbaed0Stron     }
12841fbaed0Stron     return (stream);
12941fbaed0Stron }
130