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