Home | History | Annotate | Line # | Download | only in util
      1 /*	$NetBSD: stream_recv_fd.c,v 1.2 2025/02/25 19:15:52 christos 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 
     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 
     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