1 /*	$NetBSD: unix_connect.c,v 1.1.1.1 2009/06/23 10:09:01 tron 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 
61 int     unix_connect(const char *addr, int block_mode, int timeout)
62 {
63 #undef sun
64     struct sockaddr_un sun;
65     int     len = strlen(addr);
66     int     sock;
67 
68     /*
69      * Translate address information to internal form.
70      */
71     if (len >= (int) sizeof(sun.sun_path))
72 	msg_fatal("unix-domain name too long: %s", addr);
73     memset((char *) &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