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