1/*++
2/* NAME
3/*	mail_connect 3
4/* SUMMARY
5/*	intra-mail system connection management
6/* SYNOPSIS
7/*	#include <mail_proto.h>
8/*
9/*	VSTREAM *mail_connect(class, name, block_mode)
10/*	const char *class;
11/*	const char *name;
12/*	int	block_mode;
13/*
14/*	VSTREAM *mail_connect_wait(class, name)
15/*	const char *class;
16/*	const char *name;
17/* DESCRIPTION
18/*	This module does low-level connection management for intra-mail
19/*	communication.  All reads and writes are subject to a time limit
20/*	(controlled by the global variable \fIvar_ipc_timeout\fR). This
21/*	protects against deadlock conditions that should never happen.
22/*
23/*	mail_connect() attempts to connect to the UNIX-domain socket of
24/*	the named subsystem. The result is a null pointer in case of failure.
25/*
26/*	mail_connect_wait() is like mail_connect(), but keeps trying until
27/*	the connection succeeds. However, mail_connect_wait() terminates
28/*	with a fatal error when the service is down. This is to ensure that
29/*	processes terminate when the mail system shuts down.
30/*
31/*	Arguments:
32/* .IP class
33/*	Name of a class of local transport channel endpoints,
34/*	either \fIpublic\fR (accessible by any local user) or
35/*	\fIprivate\fR (administrative access only).
36/* .IP service
37/*	The name of a local transport endpoint within the named class.
38/* .IP block_mode
39/*	NON_BLOCKING for a non-blocking connection, or BLOCKING.
40/* SEE ALSO
41/*	timed_ipc(3), enforce IPC timeouts.
42/* LICENSE
43/* .ad
44/* .fi
45/*	The Secure Mailer license must be distributed with this software.
46/* AUTHOR(S)
47/*	Wietse Venema
48/*	IBM T.J. Watson Research
49/*	P.O. Box 704
50/*	Yorktown Heights, NY 10598, USA
51/*--*/
52
53/* System library. */
54
55#include <sys_defs.h>
56#include <fcntl.h>
57#include <unistd.h>
58#include <stdlib.h>
59#include <stdarg.h>
60#include <errno.h>
61
62/* Utility library. */
63
64#include <msg.h>
65#include <vstream.h>
66#include <connect.h>
67#include <mymalloc.h>
68#include <iostuff.h>
69#include <stringops.h>
70
71/* Global library. */
72
73#include "timed_ipc.h"
74#include "mail_proto.h"
75
76/* mail_connect - connect to mail subsystem */
77
78VSTREAM *mail_connect(const char *class, const char *name, int block_mode)
79{
80    char   *path;
81    VSTREAM *stream;
82    int     fd;
83    char   *sock_name;
84
85    path = mail_pathname(class, name);
86    if ((fd = LOCAL_CONNECT(path, block_mode, 0)) < 0) {
87	if (msg_verbose)
88	    msg_info("connect to subsystem %s: %m", path);
89	stream = 0;
90    } else {
91	if (msg_verbose)
92	    msg_info("connect to subsystem %s", path);
93	stream = vstream_fdopen(fd, O_RDWR);
94	timed_ipc_setup(stream);
95	sock_name = concatenate(path, " socket", (char *) 0);
96	vstream_control(stream,
97			VSTREAM_CTL_PATH, sock_name,
98			VSTREAM_CTL_END);
99	myfree(sock_name);
100    }
101    myfree(path);
102    return (stream);
103}
104
105/* mail_connect_wait - connect to mail service until it succeeds */
106
107VSTREAM *mail_connect_wait(const char *class, const char *name)
108{
109    VSTREAM *stream;
110    int     count = 0;
111
112    /*
113     * XXX Solaris workaround for ECONNREFUSED on a busy socket.
114     */
115    while ((stream = mail_connect(class, name, BLOCKING)) == 0) {
116	if (count++ >= 10) {
117	    msg_fatal("connect #%d to subsystem %s/%s: %m",
118		      count, class, name);
119	} else {
120	    msg_warn("connect #%d to subsystem %s/%s: %m",
121		     count, class, name);
122	}
123	sleep(10);				/* XXX make configurable */
124    }
125    return (stream);
126}
127