1/*++
2/* NAME
3/*	unix_connect 3
4/* SUMMARY
5/*	connect to UNIX-domain listener
6/* SYNOPSIS
7/*	#include <connect.h>
8/*
9/*	int	unix_connect(addr, block_mode, timeout)
10/*	const char *addr;
11/*	int	block_mode;
12/*	int	timeout;
13/* DESCRIPTION
14/*	unix_connect() connects to a listener in the UNIX domain at the
15/*	specified address, and returns the resulting file descriptor.
16/*
17/*	Arguments:
18/* .IP addr
19/*	Null-terminated string with connection destination.
20/* .IP block_mode
21/*	Either NON_BLOCKING for a non-blocking socket, or BLOCKING for
22/*	blocking mode.
23/* .IP timeout
24/*	Bounds the number of seconds that the operation may take. Specify
25/*	a value <= 0 to disable the time limit.
26/* DIAGNOSTICS
27/*	The result is -1 in case the connection could not be made.
28/*	Fatal errors: other system call failures.
29/* LICENSE
30/* .ad
31/* .fi
32/*	The Secure Mailer license must be distributed with this software.
33/* AUTHOR(S)
34/*	Wietse Venema
35/*	IBM T.J. Watson Research
36/*	P.O. Box 704
37/*	Yorktown Heights, NY 10598, USA
38/*--*/
39
40/* System interfaces. */
41
42#include <sys_defs.h>
43#include <sys/socket.h>
44#include <sys/un.h>
45#include <string.h>
46#include <unistd.h>
47#include <errno.h>
48
49/* Utility library. */
50
51#include "msg.h"
52#include "iostuff.h"
53#include "sane_connect.h"
54#include "connect.h"
55#include "timed_connect.h"
56
57/* unix_connect - connect to UNIX-domain listener */
58
59int     unix_connect(const char *addr, int block_mode, int timeout)
60{
61#undef sun
62    struct sockaddr_un sun;
63    int     len = strlen(addr);
64    int     sock;
65
66    /*
67     * Translate address information to internal form.
68     */
69    if (len >= (int) sizeof(sun.sun_path))
70	msg_fatal("unix-domain name too long: %s", addr);
71    memset((char *) &sun, 0, sizeof(sun));
72    sun.sun_family = AF_UNIX;
73#ifdef HAS_SUN_LEN
74    sun.sun_len = len + 1;
75#endif
76    memcpy(sun.sun_path, addr, len + 1);
77
78    /*
79     * Create a client socket.
80     */
81    if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
82	return (-1);
83
84    /*
85     * Timed connect.
86     */
87    if (timeout > 0) {
88	non_blocking(sock, NON_BLOCKING);
89	if (timed_connect(sock, (struct sockaddr *) & sun, sizeof(sun), timeout) < 0) {
90	    close(sock);
91	    return (-1);
92	}
93	if (block_mode != NON_BLOCKING)
94	    non_blocking(sock, block_mode);
95	return (sock);
96    }
97
98    /*
99     * Maybe block until connected.
100     */
101    else {
102	non_blocking(sock, block_mode);
103	if (sane_connect(sock, (struct sockaddr *) & sun, sizeof(sun)) < 0
104	    && errno != EINPROGRESS) {
105	    close(sock);
106	    return (-1);
107	}
108	return (sock);
109    }
110}
111