xref: /freebsd/contrib/sendmail/libsm/notify.c (revision d39bd2c1388b520fcba9abed1932acacead60fba)
15b0945b5SGregory Neil Shapiro /*
2*d39bd2c1SGregory Neil Shapiro  * Copyright (c) 2020 Proofpoint, Inc. and its suppliers.
35b0945b5SGregory Neil Shapiro  *	All rights reserved.
45b0945b5SGregory Neil Shapiro  *
55b0945b5SGregory Neil Shapiro  * By using this file, you agree to the terms and conditions set
65b0945b5SGregory Neil Shapiro  * forth in the LICENSE file which can be found at the top level of
75b0945b5SGregory Neil Shapiro  * the sendmail distribution.
85b0945b5SGregory Neil Shapiro  *
95b0945b5SGregory Neil Shapiro  */
105b0945b5SGregory Neil Shapiro 
115b0945b5SGregory Neil Shapiro #include <sm/gen.h>
125b0945b5SGregory Neil Shapiro 
13*d39bd2c1SGregory Neil Shapiro #if _FFR_DMTRIGGER && _FFR_NOTIFY < 2
142fb4f839SGregory Neil Shapiro #include <sm/conf.h>	/* FDSET_CAST */
152fb4f839SGregory Neil Shapiro #include <sm/fdset.h>
162fb4f839SGregory Neil Shapiro #include <sm/assert.h>
172fb4f839SGregory Neil Shapiro #include <sm/notify.h>
18*d39bd2c1SGregory Neil Shapiro #include "notify.h"
192fb4f839SGregory Neil Shapiro #include <sm/time.h>
202fb4f839SGregory Neil Shapiro #include <sm/string.h>
212fb4f839SGregory Neil Shapiro 
225b0945b5SGregory Neil Shapiro #include <sys/types.h>
235b0945b5SGregory Neil Shapiro #include <signal.h>
245b0945b5SGregory Neil Shapiro #include <stdio.h>
255b0945b5SGregory Neil Shapiro #include <stdlib.h>
265b0945b5SGregory Neil Shapiro #include <unistd.h>
275b0945b5SGregory Neil Shapiro #include <stdbool.h>
285b0945b5SGregory Neil Shapiro #include <errno.h>
295b0945b5SGregory Neil Shapiro #include <fcntl.h>
305b0945b5SGregory Neil Shapiro #include <string.h>	/* for memset() */
315b0945b5SGregory Neil Shapiro 
325b0945b5SGregory Neil Shapiro static int	Notifypipe[2];
335b0945b5SGregory Neil Shapiro #define NotifyRDpipe Notifypipe[0]
345b0945b5SGregory Neil Shapiro #define NotifyWRpipe Notifypipe[1]
355b0945b5SGregory Neil Shapiro 
365b0945b5SGregory Neil Shapiro #define CLOSEFD(fd) do { \
375b0945b5SGregory Neil Shapiro 		if ((fd) != -1) {	\
385b0945b5SGregory Neil Shapiro 			(void) close(fd);	\
395b0945b5SGregory Neil Shapiro 			fd = - 1;	\
405b0945b5SGregory Neil Shapiro 		}	\
415b0945b5SGregory Neil Shapiro 	} while (0)	\
425b0945b5SGregory Neil Shapiro 
435b0945b5SGregory Neil Shapiro 
445b0945b5SGregory Neil Shapiro /*
455b0945b5SGregory Neil Shapiro **  SM_NOTIFY_INIT -- initialize notify system
465b0945b5SGregory Neil Shapiro **
475b0945b5SGregory Neil Shapiro **	Parameters:
485b0945b5SGregory Neil Shapiro **		flags -- ignored
495b0945b5SGregory Neil Shapiro **
505b0945b5SGregory Neil Shapiro **	Returns:
515b0945b5SGregory Neil Shapiro **		0: success
525b0945b5SGregory Neil Shapiro **		<0: -errno
535b0945b5SGregory Neil Shapiro */
545b0945b5SGregory Neil Shapiro 
555b0945b5SGregory Neil Shapiro int
sm_notify_init(flags)565b0945b5SGregory Neil Shapiro sm_notify_init(flags)
575b0945b5SGregory Neil Shapiro 	int flags;
585b0945b5SGregory Neil Shapiro {
595b0945b5SGregory Neil Shapiro 	if (pipe(Notifypipe) < 0)
605b0945b5SGregory Neil Shapiro 		return -errno;
615b0945b5SGregory Neil Shapiro 	return 0;
625b0945b5SGregory Neil Shapiro }
635b0945b5SGregory Neil Shapiro 
645b0945b5SGregory Neil Shapiro /*
655b0945b5SGregory Neil Shapiro **  SM_NOTIFY_START -- start notify system
665b0945b5SGregory Neil Shapiro **
675b0945b5SGregory Neil Shapiro **	Parameters:
685b0945b5SGregory Neil Shapiro **		owner -- owner.
695b0945b5SGregory Neil Shapiro **		flags -- currently ignored.
705b0945b5SGregory Neil Shapiro **
715b0945b5SGregory Neil Shapiro **	Returns:
725b0945b5SGregory Neil Shapiro **		0: success
735b0945b5SGregory Neil Shapiro **		<0: -errno
745b0945b5SGregory Neil Shapiro */
755b0945b5SGregory Neil Shapiro 
765b0945b5SGregory Neil Shapiro int
sm_notify_start(owner,flags)775b0945b5SGregory Neil Shapiro sm_notify_start(owner, flags)
785b0945b5SGregory Neil Shapiro 	bool owner;
795b0945b5SGregory Neil Shapiro 	int flags;
805b0945b5SGregory Neil Shapiro {
815b0945b5SGregory Neil Shapiro 	int r;
825b0945b5SGregory Neil Shapiro 
835b0945b5SGregory Neil Shapiro 	r = 0;
845b0945b5SGregory Neil Shapiro 	if (owner)
855b0945b5SGregory Neil Shapiro 		CLOSEFD(NotifyWRpipe);
865b0945b5SGregory Neil Shapiro 	else
875b0945b5SGregory Neil Shapiro 		CLOSEFD(NotifyRDpipe);
885b0945b5SGregory Neil Shapiro 	return r;
895b0945b5SGregory Neil Shapiro }
905b0945b5SGregory Neil Shapiro 
915b0945b5SGregory Neil Shapiro /*
925b0945b5SGregory Neil Shapiro **  SM_NOTIFY_STOP -- stop notify system
935b0945b5SGregory Neil Shapiro **
945b0945b5SGregory Neil Shapiro **	Parameters:
955b0945b5SGregory Neil Shapiro **		owner -- owner.
965b0945b5SGregory Neil Shapiro **		flags -- currently ignored.
975b0945b5SGregory Neil Shapiro **
985b0945b5SGregory Neil Shapiro **	Returns:
995b0945b5SGregory Neil Shapiro **		0: success
1005b0945b5SGregory Neil Shapiro **		<0: -errno
1015b0945b5SGregory Neil Shapiro */
1025b0945b5SGregory Neil Shapiro 
1035b0945b5SGregory Neil Shapiro int
sm_notify_stop(owner,flags)1045b0945b5SGregory Neil Shapiro sm_notify_stop(owner, flags)
1055b0945b5SGregory Neil Shapiro 	bool owner;
1065b0945b5SGregory Neil Shapiro 	int flags;
1075b0945b5SGregory Neil Shapiro {
1085b0945b5SGregory Neil Shapiro 	if (owner)
1095b0945b5SGregory Neil Shapiro 		CLOSEFD(NotifyRDpipe);
1105b0945b5SGregory Neil Shapiro 	else
1115b0945b5SGregory Neil Shapiro 		CLOSEFD(NotifyWRpipe);
1125b0945b5SGregory Neil Shapiro 	return 0;
1135b0945b5SGregory Neil Shapiro }
1145b0945b5SGregory Neil Shapiro 
1155b0945b5SGregory Neil Shapiro /*
1165b0945b5SGregory Neil Shapiro **  SM_NOTIFY_SND -- send notification
1175b0945b5SGregory Neil Shapiro **
1185b0945b5SGregory Neil Shapiro **	Parameters:
1195b0945b5SGregory Neil Shapiro **		buf -- where to write data
1205b0945b5SGregory Neil Shapiro **		buflen -- len of buffer
1215b0945b5SGregory Neil Shapiro **
1225b0945b5SGregory Neil Shapiro **	Returns:
1235b0945b5SGregory Neil Shapiro **		0: success
1245b0945b5SGregory Neil Shapiro **		<0: -errno
1255b0945b5SGregory Neil Shapiro */
1265b0945b5SGregory Neil Shapiro 
1275b0945b5SGregory Neil Shapiro int
sm_notify_snd(buf,buflen)1285b0945b5SGregory Neil Shapiro sm_notify_snd(buf, buflen)
1295b0945b5SGregory Neil Shapiro 	char *buf;
1305b0945b5SGregory Neil Shapiro 	size_t buflen;
1315b0945b5SGregory Neil Shapiro {
1325b0945b5SGregory Neil Shapiro 	int r;
1335b0945b5SGregory Neil Shapiro 	int save_errno;
1342fb4f839SGregory Neil Shapiro 	size_t len;
1352fb4f839SGregory Neil Shapiro 	char netstr[MAX_NETSTR];
1365b0945b5SGregory Neil Shapiro 
1375b0945b5SGregory Neil Shapiro 	SM_REQUIRE(buf != NULL);
1385b0945b5SGregory Neil Shapiro 	SM_REQUIRE(buflen > 0);
1395b0945b5SGregory Neil Shapiro 	if (NotifyWRpipe < 0)
1405b0945b5SGregory Neil Shapiro 		return -EINVAL;
1412fb4f839SGregory Neil Shapiro 	if (buflen >= MAX_NETSTR - 7)
1422fb4f839SGregory Neil Shapiro 		return -E2BIG;	/* XXX "TOO LARGE"? */
1435b0945b5SGregory Neil Shapiro 
1442fb4f839SGregory Neil Shapiro 	len = sm_snprintf(netstr, sizeof(netstr), "%04d:%s,", (int)buflen, buf);
1452fb4f839SGregory Neil Shapiro 	r = write(NotifyWRpipe, netstr, len);
1465b0945b5SGregory Neil Shapiro 	save_errno = errno;
147*d39bd2c1SGregory Neil Shapiro 	SM_DBG((stderr, "pid=%ld, write=%d, fd=%d, e=%d\n", (long)getpid(), r, NotifyWRpipe, save_errno));
1485b0945b5SGregory Neil Shapiro 	return r >= 0 ? 0 : -save_errno;
1495b0945b5SGregory Neil Shapiro }
1505b0945b5SGregory Neil Shapiro 
1515b0945b5SGregory Neil Shapiro /*
1525b0945b5SGregory Neil Shapiro **  SM_NOTIFY_RCV -- receive notification
1535b0945b5SGregory Neil Shapiro **
1545b0945b5SGregory Neil Shapiro **	Parameters:
1555b0945b5SGregory Neil Shapiro **		buf -- where to write data
1565b0945b5SGregory Neil Shapiro **		buflen -- len of buffer
1572fb4f839SGregory Neil Shapiro **		tmo -- timeout (micro seconds)
1585b0945b5SGregory Neil Shapiro **
1595b0945b5SGregory Neil Shapiro **	Returns:
160*d39bd2c1SGregory Neil Shapiro **		0: EOF (XXX need to provide info about client)
161*d39bd2c1SGregory Neil Shapiro **		>0: length of received data
1625b0945b5SGregory Neil Shapiro **		<0: -errno
1635b0945b5SGregory Neil Shapiro */
1645b0945b5SGregory Neil Shapiro 
1655b0945b5SGregory Neil Shapiro int
sm_notify_rcv(buf,buflen,tmo)1665b0945b5SGregory Neil Shapiro sm_notify_rcv(buf, buflen, tmo)
1675b0945b5SGregory Neil Shapiro 	char *buf;
1685b0945b5SGregory Neil Shapiro 	size_t buflen;
1692fb4f839SGregory Neil Shapiro 	long tmo;
1705b0945b5SGregory Neil Shapiro {
1712fb4f839SGregory Neil Shapiro 	int r, len;
1725b0945b5SGregory Neil Shapiro 	int save_errno;
1735b0945b5SGregory Neil Shapiro 	fd_set readfds;
1742fb4f839SGregory Neil Shapiro 	struct timeval timeout, *tval;
1755b0945b5SGregory Neil Shapiro 
1765b0945b5SGregory Neil Shapiro 	SM_REQUIRE(buf != NULL);
1772fb4f839SGregory Neil Shapiro 	SM_REQUIRE(buflen > NETSTRPRE + 2);
1785b0945b5SGregory Neil Shapiro 	if (NotifyRDpipe < 0)
1795b0945b5SGregory Neil Shapiro 		return -EINVAL;
1805b0945b5SGregory Neil Shapiro 	FD_ZERO(&readfds);
1815b0945b5SGregory Neil Shapiro 	SM_FD_SET(NotifyRDpipe, &readfds);
182*d39bd2c1SGregory Neil Shapiro 	SM_MICROS2TVAL(tmo, tval, timeout);
1835b0945b5SGregory Neil Shapiro 
1845b0945b5SGregory Neil Shapiro 	do {
1852fb4f839SGregory Neil Shapiro 		r = select(NotifyRDpipe + 1, FDSET_CAST &readfds, NULL, NULL, tval);
1865b0945b5SGregory Neil Shapiro 		save_errno = errno;
187*d39bd2c1SGregory Neil Shapiro 		SM_DBG((stderr, "pid=%ld, select=%d, fd=%d, e=%d\n", (long)getpid(), r, NotifyRDpipe, save_errno));
1885b0945b5SGregory Neil Shapiro 	} while (r < 0 && save_errno == EINTR);
1895b0945b5SGregory Neil Shapiro 
190*d39bd2c1SGregory Neil Shapiro 	RDNETSTR(r, NotifyRDpipe, (void)0);
1915b0945b5SGregory Neil Shapiro }
192*d39bd2c1SGregory Neil Shapiro #endif /* _FFR_DMTRIGGER && _FFR_NOTIFY < 2 */
193