1/*++
2/* NAME
3/*	pass_accept 3
4/* SUMMARY
5/*	start UNIX-domain file descriptor listener
6/* SYNOPSIS
7/*	#include <listen.h>
8/*
9/*	int	pass_accept(listen_fd)
10/*	int	listen_fd;
11/*
12/*	int	pass_accept_attr(listen_fd, attr)
13/*	int	listen_fd;
14/*	HTABLE	**attr;
15/* DESCRIPTION
16/*	This module implements a listener that receives one attribute list
17/*	and file descriptor over each a local connection that is made to it.
18/*
19/*	Arguments:
20/* .IP attr
21/*	Pointer to attribute list pointer.  In case of error, or
22/*	no attributes, the attribute list pointer is set to null.
23/* .IP listen_fd
24/*	File descriptor returned by LOCAL_LISTEN().
25/* DIAGNOSTICS
26/*	Warnings: I/O errors, timeout.
27/* LICENSE
28/* .ad
29/* .fi
30/*	The Secure Mailer license must be distributed with this software.
31/* AUTHOR(S)
32/*	Wietse Venema
33/*	IBM T.J. Watson Research
34/*	P.O. Box 704
35/*	Yorktown Heights, NY 10598, USA
36/*--*/
37
38/* System library. */
39
40#include <sys_defs.h>
41#include <errno.h>
42#include <unistd.h>
43
44/* Utility library. */
45
46#include <msg.h>
47#include <listen.h>
48#include <attr.h>
49
50#define PASS_ACCEPT_TMOUT	100
51
52/* pass_accept - accept descriptor */
53
54int     pass_accept(int listen_fd)
55{
56    const char *myname = "pass_accept";
57    int     accept_fd;
58    int     recv_fd = -1;
59
60    accept_fd = LOCAL_ACCEPT(listen_fd);
61    if (accept_fd < 0) {
62	if (errno != EAGAIN)
63	    msg_warn("%s: cannot accept connection: %m", myname);
64	return (-1);
65    } else {
66	if (read_wait(accept_fd, PASS_ACCEPT_TMOUT) < 0)
67	    msg_warn("%s: timeout receiving file descriptor: %m", myname);
68	else if ((recv_fd = LOCAL_RECV_FD(accept_fd)) < 0)
69	    msg_warn("%s: cannot receive file descriptor: %m", myname);
70	if (close(accept_fd) < 0)
71	    msg_warn("%s: close: %m", myname);
72	return (recv_fd);
73    }
74}
75
76/* pass_accept_attr - accept descriptor and attribute list */
77
78int     pass_accept_attr(int listen_fd, HTABLE **attr)
79{
80    const char *myname = "pass_accept_attr";
81    int     accept_fd;
82    int     recv_fd = -1;
83
84    *attr = 0;
85    accept_fd = LOCAL_ACCEPT(listen_fd);
86    if (accept_fd < 0) {
87	if (errno != EAGAIN)
88	    msg_warn("%s: cannot accept connection: %m", myname);
89	return (-1);
90    } else {
91	if (read_wait(accept_fd, PASS_ACCEPT_TMOUT) < 0)
92	    msg_warn("%s: timeout receiving file descriptor: %m", myname);
93	else if ((recv_fd = LOCAL_RECV_FD(accept_fd)) < 0)
94	    msg_warn("%s: cannot receive file descriptor: %m", myname);
95	else if (read_wait(accept_fd, PASS_ACCEPT_TMOUT) < 0
96	     || recv_pass_attr(accept_fd, attr, PASS_ACCEPT_TMOUT, 0) < 0) {
97	    msg_warn("%s: cannot receive connection attributes: %m", myname);
98	    if (close(recv_fd) < 0)
99		msg_warn("%s: close: %m", myname);
100	    recv_fd = -1;
101	}
102	if (close(accept_fd) < 0)
103	    msg_warn("%s: close: %m", myname);
104	return (recv_fd);
105    }
106}
107