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