1363203Sgshapiro/*
2363203Sgshapiro * Copyright (c) 2016 Proofpoint, Inc. and its suppliers.
3363203Sgshapiro *	All rights reserved.
4363203Sgshapiro *
5363203Sgshapiro * By using this file, you agree to the terms and conditions set
6363203Sgshapiro * forth in the LICENSE file which can be found at the top level of
7363203Sgshapiro * the sendmail distribution.
8363203Sgshapiro *
9363203Sgshapiro */
10363203Sgshapiro
11363203Sgshapiro#include <sm/gen.h>
12363203Sgshapiro
13363203Sgshapiro#include <sys/types.h>
14363203Sgshapiro#include <signal.h>
15363203Sgshapiro#include <stdio.h>
16363203Sgshapiro#include <stdlib.h>
17363203Sgshapiro#include <unistd.h>
18363203Sgshapiro#include <stdbool.h>
19363203Sgshapiro#include <errno.h>
20363203Sgshapiro#include <fcntl.h>
21363203Sgshapiro#include <string.h>	/* for memset() */
22363203Sgshapiro
23363233Sgshapiro#include <sm/conf.h>	/* FDSET_CAST */
24363233Sgshapiro#include <sm/fdset.h>
25363233Sgshapiro#include <sm/assert.h>
26363233Sgshapiro#include <sm/notify.h>
27363233Sgshapiro
28363203Sgshapiro#if SM_NOTIFY_DEBUG
29363203Sgshapiro#define SM_DBG(p)	fprintf p
30363203Sgshapiro#else
31363203Sgshapiro#define SM_DBG(p)
32363203Sgshapiro#endif
33363203Sgshapiro
34363203Sgshapirostatic int	Notifypipe[2];
35363203Sgshapiro#define NotifyRDpipe Notifypipe[0]
36363203Sgshapiro#define NotifyWRpipe Notifypipe[1]
37363203Sgshapiro
38363203Sgshapiro#define CLOSEFD(fd) do { \
39363203Sgshapiro		if ((fd) != -1) {	\
40363203Sgshapiro			(void) close(fd);	\
41363203Sgshapiro			fd = - 1;	\
42363203Sgshapiro		}	\
43363203Sgshapiro	} while (0)	\
44363203Sgshapiro
45363203Sgshapiro
46363203Sgshapiro/*
47363203Sgshapiro**  SM_NOTIFY_INIT -- initialize notify system
48363203Sgshapiro**
49363203Sgshapiro**	Parameters:
50363203Sgshapiro**		flags -- ignored
51363203Sgshapiro**
52363203Sgshapiro**	Returns:
53363203Sgshapiro**		0: success
54363203Sgshapiro**		<0: -errno
55363203Sgshapiro*/
56363203Sgshapiro
57363203Sgshapiroint
58363203Sgshapirosm_notify_init(flags)
59363203Sgshapiro	int flags;
60363203Sgshapiro{
61363203Sgshapiro	if (pipe(Notifypipe) < 0)
62363203Sgshapiro		return -errno;
63363203Sgshapiro	return 0;
64363203Sgshapiro}
65363203Sgshapiro
66363203Sgshapiro/*
67363203Sgshapiro**  SM_NOTIFY_START -- start notify system
68363203Sgshapiro**
69363203Sgshapiro**	Parameters:
70363203Sgshapiro**		owner -- owner.
71363203Sgshapiro**		flags -- currently ignored.
72363203Sgshapiro**
73363203Sgshapiro**	Returns:
74363203Sgshapiro**		0: success
75363203Sgshapiro**		<0: -errno
76363203Sgshapiro*/
77363203Sgshapiro
78363203Sgshapiroint
79363203Sgshapirosm_notify_start(owner, flags)
80363203Sgshapiro	bool owner;
81363203Sgshapiro	int flags;
82363203Sgshapiro{
83363203Sgshapiro	int r;
84363203Sgshapiro
85363203Sgshapiro	r = 0;
86363203Sgshapiro	if (owner)
87363203Sgshapiro		CLOSEFD(NotifyWRpipe);
88363203Sgshapiro	else
89363203Sgshapiro		CLOSEFD(NotifyRDpipe);
90363203Sgshapiro	return r;
91363203Sgshapiro}
92363203Sgshapiro
93363203Sgshapiro/*
94363203Sgshapiro**  SM_NOTIFY_STOP -- stop notify system
95363203Sgshapiro**
96363203Sgshapiro**	Parameters:
97363203Sgshapiro**		owner -- owner.
98363203Sgshapiro**		flags -- currently ignored.
99363203Sgshapiro**
100363203Sgshapiro**	Returns:
101363203Sgshapiro**		0: success
102363203Sgshapiro**		<0: -errno
103363203Sgshapiro*/
104363203Sgshapiro
105363203Sgshapiroint
106363203Sgshapirosm_notify_stop(owner, flags)
107363203Sgshapiro	bool owner;
108363203Sgshapiro	int flags;
109363203Sgshapiro{
110363203Sgshapiro	if (owner)
111363203Sgshapiro		CLOSEFD(NotifyRDpipe);
112363203Sgshapiro	else
113363203Sgshapiro		CLOSEFD(NotifyWRpipe);
114363203Sgshapiro	return 0;
115363203Sgshapiro}
116363203Sgshapiro
117363203Sgshapiro/*
118363203Sgshapiro**  SM_NOTIFY_SND -- send notification
119363203Sgshapiro**
120363203Sgshapiro**	Parameters:
121363203Sgshapiro**		buf -- where to write data
122363203Sgshapiro**		buflen -- len of buffer
123363203Sgshapiro**
124363203Sgshapiro**	Returns:
125363203Sgshapiro**		0: success
126363203Sgshapiro**		<0: -errno
127363203Sgshapiro*/
128363203Sgshapiro
129363203Sgshapiroint
130363203Sgshapirosm_notify_snd(buf, buflen)
131363203Sgshapiro	char *buf;
132363203Sgshapiro	size_t buflen;
133363203Sgshapiro{
134363203Sgshapiro	int r;
135363203Sgshapiro	int save_errno;
136363203Sgshapiro
137363203Sgshapiro	SM_REQUIRE(buf != NULL);
138363203Sgshapiro	SM_REQUIRE(buflen > 0);
139363203Sgshapiro	if (NotifyWRpipe < 0)
140363203Sgshapiro		return -EINVAL;
141363203Sgshapiro
142363203Sgshapiro	r = write(NotifyWRpipe, buf, buflen);
143363203Sgshapiro	save_errno = errno;
144363203Sgshapiro	SM_DBG((stderr, "write=%d, fd=%d, e=%d\n", r, NotifyWRpipe, save_errno));
145363203Sgshapiro	return r >= 0 ? 0 : -save_errno;
146363203Sgshapiro}
147363203Sgshapiro
148363203Sgshapiro/*
149363203Sgshapiro**  SM_NOTIFY_RCV -- receive notification
150363203Sgshapiro**
151363203Sgshapiro**	Parameters:
152363203Sgshapiro**		buf -- where to write data
153363203Sgshapiro**		buflen -- len of buffer
154363203Sgshapiro**		tmo -- timeout
155363203Sgshapiro**
156363203Sgshapiro**	Returns:
157363203Sgshapiro**		0: success
158363203Sgshapiro**		<0: -errno
159363203Sgshapiro*/
160363203Sgshapiro
161363203Sgshapiroint
162363203Sgshapirosm_notify_rcv(buf, buflen, tmo)
163363203Sgshapiro	char *buf;
164363203Sgshapiro	size_t buflen;
165363203Sgshapiro	int tmo;
166363203Sgshapiro{
167363203Sgshapiro	int r;
168363203Sgshapiro	int save_errno;
169363203Sgshapiro	fd_set readfds;
170363203Sgshapiro	struct timeval timeout;
171363203Sgshapiro
172363203Sgshapiro	SM_REQUIRE(buf != NULL);
173363203Sgshapiro	SM_REQUIRE(buflen > 0);
174363203Sgshapiro	if (NotifyRDpipe < 0)
175363203Sgshapiro		return -EINVAL;
176363203Sgshapiro	FD_ZERO(&readfds);
177363203Sgshapiro	SM_FD_SET(NotifyRDpipe, &readfds);
178363203Sgshapiro	timeout.tv_sec = tmo;
179363203Sgshapiro	timeout.tv_usec = 0;
180363203Sgshapiro
181363203Sgshapiro	do {
182363203Sgshapiro		r = select(NotifyRDpipe + 1, FDSET_CAST &readfds, NULL, NULL, &timeout);
183363203Sgshapiro		save_errno = errno;
184363203Sgshapiro		SM_DBG((stderr, "select=%d, fd=%d, e=%d\n", r, NotifyRDpipe, save_errno));
185363203Sgshapiro	} while (r < 0 && save_errno == EINTR);
186363203Sgshapiro
187363203Sgshapiro	if (r <= 0)
188363203Sgshapiro	{
189363203Sgshapiro		SM_DBG((stderr, "select=%d, e=%d\n", r, save_errno));
190363203Sgshapiro		return -ETIMEDOUT;
191363203Sgshapiro	}
192363203Sgshapiro
193363203Sgshapiro	/* bogus... need to check again? */
194363203Sgshapiro	if (!FD_ISSET(NotifyRDpipe, &readfds))
195363203Sgshapiro		return -ETIMEDOUT;
196363203Sgshapiro
197363203Sgshapiro	r = read(NotifyRDpipe, buf, buflen);
198363203Sgshapiro	save_errno = errno;
199363203Sgshapiro	SM_DBG((stderr, "read=%d, e=%d\n", r, save_errno));
200363203Sgshapiro	if (r == 0)
201363203Sgshapiro		return -1;	/* ??? */
202363203Sgshapiro	if (r < 0)
203363203Sgshapiro		return -save_errno;
204363203Sgshapiro	return r;
205363203Sgshapiro}
206