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