Home | History | Annotate | Line # | Download | only in global
      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 
     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 
    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