xref: /netbsd-src/external/ibm-public/postfix/dist/src/util/stream_recv_fd.c (revision ff6d749d9964a9b179f9760ce6992137cffbaefe)
1 /*	$NetBSD: stream_recv_fd.c,v 1.1.1.2 2011/03/02 19:32:45 tron Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	stream_recv_fd 3
6 /* SUMMARY
7 /*	receive file descriptor
8 /* SYNOPSIS
9 /*	#include <iostuff.h>
10 /*
11 /*	int	stream_recv_fd(fd)
12 /*	int	fd;
13 /* DESCRIPTION
14 /*	stream_recv_fd() receives a file descriptor via the specified
15 /*	stream. The result value is the received descriptor.
16 /*
17 /*	Arguments:
18 /* .IP fd
19 /*	File descriptor that connects the sending and receiving processes.
20 /* DIAGNOSTICS
21 /*	stream_recv_fd() returns -1 upon failure.
22 /* LICENSE
23 /* .ad
24 /* .fi
25 /*	The Secure Mailer license must be distributed with this software.
26 /* AUTHOR(S)
27 /*	Wietse Venema
28 /*	IBM T.J. Watson Research
29 /*	P.O. Box 704
30 /*	Yorktown Heights, NY 10598, USA
31 /*--*/
32 
33 /* System library. */
34 
35 #include <sys_defs.h>			/* includes <sys/types.h> */
36 
37 #ifdef STREAM_CONNECTIONS
38 
39 #include <sys/stat.h>
40 #include <unistd.h>
41 #include <errno.h>
42 #include <stropts.h>
43 #include <fcntl.h>
44 
45 #endif
46 
47 /* Utility library. */
48 
49 #include <msg.h>
50 #include <iostuff.h>
51 
52 /* stream_recv_fd - receive file descriptor */
53 
stream_recv_fd(int fd)54 int     stream_recv_fd(int fd)
55 {
56 #ifdef STREAM_CONNECTIONS
57     struct strrecvfd fdinfo;
58 
59     /*
60      * This will return EAGAIN on a non-blocking stream when someone else
61      * snatched the connection from us.
62      */
63     if (ioctl(fd, I_RECVFD, &fdinfo) < 0)
64 	return (-1);
65     return (fdinfo.fd);
66 #else
67     msg_fatal("stream connections are not implemented");
68 #endif
69 }
70 
71 #ifdef TEST
72 
73  /*
74   * Proof-of-concept program. Receive a descriptor (presumably from the
75   * stream_send_fd test program) and copy its content until EOF.
76   */
77 #include <unistd.h>
78 #include <string.h>
79 #include <stdlib.h>
80 #include <split_at.h>
81 #include <listen.h>
82 
main(int argc,char ** argv)83 int     main(int argc, char **argv)
84 {
85     char   *transport;
86     char   *endpoint;
87     int     listen_sock;
88     int     client_sock;
89     int     client_fd;
90     ssize_t read_count;
91     char    buf[1024];
92 
93     if (argc != 2
94 	|| (endpoint = split_at(transport = argv[1], ':')) == 0
95 	|| *endpoint == 0 || *transport == 0)
96 	msg_fatal("usage: %s transport:endpoint", argv[0]);
97 
98     if (strcmp(transport, "stream") == 0) {
99 	listen_sock = stream_listen(endpoint, BLOCKING, 0);
100     } else {
101 	msg_fatal("invalid transport name: %s", transport);
102     }
103     if (listen_sock < 0)
104 	msg_fatal("listen %s:%s: %m", transport, endpoint);
105 
106     client_sock = stream_accept(listen_sock);
107     if (client_sock < 0)
108 	msg_fatal("stream_accept: %m");
109 
110     while ((client_fd = stream_recv_fd(client_sock)) >= 0) {
111 	msg_info("client_fd = %d", client_fd);
112 	while ((read_count = read(client_fd, buf, sizeof(buf))) > 0)
113 	    write(1, buf, read_count);
114 	if (read_count < 0)
115 	    msg_fatal("read: %m");
116 	if (close(client_fd) != 0)
117 	    msg_fatal("close(%d): %m", client_fd);
118     }
119     exit(0);
120 }
121 
122 #endif
123