1 /* $NetBSD: mail_connect.c,v 1.2 2017/02/14 01:16:45 christos 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 /* By default this function provides no errno logging.
28 /*
29 /* mail_connect_wait() is like mail_connect(), but keeps trying until
30 /* the connection succeeds. However, mail_connect_wait() terminates
31 /* with a fatal error when the service is down. This is to ensure that
32 /* processes terminate when the mail system shuts down.
33 /*
34 /* Arguments:
35 /* .IP class
36 /* Name of a class of local transport channel endpoints,
37 /* either \fIpublic\fR (accessible by any local user) or
38 /* \fIprivate\fR (administrative access only).
39 /* .IP service
40 /* The name of a local transport endpoint within the named class.
41 /* .IP block_mode
42 /* NON_BLOCKING for a non-blocking connection, or BLOCKING.
43 /* SEE ALSO
44 /* timed_ipc(3), enforce IPC timeouts.
45 /* LICENSE
46 /* .ad
47 /* .fi
48 /* The Secure Mailer license must be distributed with this software.
49 /* AUTHOR(S)
50 /* Wietse Venema
51 /* IBM T.J. Watson Research
52 /* P.O. Box 704
53 /* Yorktown Heights, NY 10598, USA
54 /*--*/
55
56 /* System library. */
57
58 #include <sys_defs.h>
59 #include <fcntl.h>
60 #include <unistd.h>
61 #include <stdlib.h>
62 #include <stdarg.h>
63 #include <errno.h>
64
65 /* Utility library. */
66
67 #include <msg.h>
68 #include <vstream.h>
69 #include <connect.h>
70 #include <mymalloc.h>
71 #include <iostuff.h>
72 #include <stringops.h>
73
74 /* Global library. */
75
76 #include "timed_ipc.h"
77 #include "mail_proto.h"
78
79 /* mail_connect - connect to mail subsystem */
80
mail_connect(const char * class,const char * name,int block_mode)81 VSTREAM *mail_connect(const char *class, const char *name, int block_mode)
82 {
83 char *path;
84 VSTREAM *stream;
85 int fd;
86 char *sock_name;
87
88 path = mail_pathname(class, name);
89 if ((fd = LOCAL_CONNECT(path, block_mode, 0)) < 0) {
90 if (msg_verbose)
91 msg_info("connect to subsystem %s: %m", path);
92 stream = 0;
93 } else {
94 if (msg_verbose)
95 msg_info("connect to subsystem %s", path);
96 stream = vstream_fdopen(fd, O_RDWR);
97 timed_ipc_setup(stream);
98 sock_name = concatenate(path, " socket", (char *) 0);
99 vstream_control(stream,
100 CA_VSTREAM_CTL_PATH(sock_name),
101 CA_VSTREAM_CTL_END);
102 myfree(sock_name);
103 }
104 myfree(path);
105 return (stream);
106 }
107
108 /* mail_connect_wait - connect to mail service until it succeeds */
109
mail_connect_wait(const char * class,const char * name)110 VSTREAM *mail_connect_wait(const char *class, const char *name)
111 {
112 VSTREAM *stream;
113 int count = 0;
114
115 /*
116 * XXX Solaris workaround for ECONNREFUSED on a busy socket.
117 */
118 while ((stream = mail_connect(class, name, BLOCKING)) == 0) {
119 if (count++ >= 10) {
120 msg_fatal("connect #%d to subsystem %s/%s: %m",
121 count, class, name);
122 } else {
123 msg_warn("connect #%d to subsystem %s/%s: %m",
124 count, class, name);
125 }
126 sleep(10); /* XXX make configurable */
127 }
128 return (stream);
129 }
130