opnsense-src/contrib/sendmail/libsm/notify.c
Gregory Neil Shapiro 2fb4f839f3 Merge commit '28fbd2825d216dafca4d991ad96d05b312f4f9a3'
Merge vendor sendmail 8.17.1 into HEAD
2023-01-15 21:20:22 +00:00

240 lines
4.2 KiB
C

/*
* Copyright (c) 2016 Proofpoint, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*
*/
#include <sm/gen.h>
#if _FFR_DMTRIGGER
#include <sm/conf.h> /* FDSET_CAST */
#include <sm/fdset.h>
#include <sm/assert.h>
#include <sm/notify.h>
#include <sm/time.h>
#include <sm/string.h>
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h> /* for memset() */
#if SM_NOTIFY_DEBUG
#define SM_DBG(p) fprintf p
#else
#define SM_DBG(p)
#endif
static int Notifypipe[2];
#define NotifyRDpipe Notifypipe[0]
#define NotifyWRpipe Notifypipe[1]
#define CLOSEFD(fd) do { \
if ((fd) != -1) { \
(void) close(fd); \
fd = - 1; \
} \
} while (0) \
/*
** SM_NOTIFY_INIT -- initialize notify system
**
** Parameters:
** flags -- ignored
**
** Returns:
** 0: success
** <0: -errno
*/
int
sm_notify_init(flags)
int flags;
{
if (pipe(Notifypipe) < 0)
return -errno;
return 0;
}
/*
** SM_NOTIFY_START -- start notify system
**
** Parameters:
** owner -- owner.
** flags -- currently ignored.
**
** Returns:
** 0: success
** <0: -errno
*/
int
sm_notify_start(owner, flags)
bool owner;
int flags;
{
int r;
r = 0;
if (owner)
CLOSEFD(NotifyWRpipe);
else
CLOSEFD(NotifyRDpipe);
return r;
}
/*
** SM_NOTIFY_STOP -- stop notify system
**
** Parameters:
** owner -- owner.
** flags -- currently ignored.
**
** Returns:
** 0: success
** <0: -errno
*/
int
sm_notify_stop(owner, flags)
bool owner;
int flags;
{
if (owner)
CLOSEFD(NotifyRDpipe);
else
CLOSEFD(NotifyWRpipe);
return 0;
}
/*
** SM_NOTIFY_SND -- send notification
**
** Parameters:
** buf -- where to write data
** buflen -- len of buffer
**
** Returns:
** 0: success
** <0: -errno
*/
#define MAX_NETSTR 1024
#define NETSTRPRE 5
int
sm_notify_snd(buf, buflen)
char *buf;
size_t buflen;
{
int r;
int save_errno;
size_t len;
char netstr[MAX_NETSTR];
SM_REQUIRE(buf != NULL);
SM_REQUIRE(buflen > 0);
if (NotifyWRpipe < 0)
return -EINVAL;
if (buflen >= MAX_NETSTR - 7)
return -E2BIG; /* XXX "TOO LARGE"? */
len = sm_snprintf(netstr, sizeof(netstr), "%04d:%s,", (int)buflen, buf);
r = write(NotifyWRpipe, netstr, len);
save_errno = errno;
SM_DBG((stderr, "write=%d, fd=%d, e=%d\n", r, NotifyWRpipe, save_errno));
return r >= 0 ? 0 : -save_errno;
}
/*
** SM_NOTIFY_RCV -- receive notification
**
** Parameters:
** buf -- where to write data
** buflen -- len of buffer
** tmo -- timeout (micro seconds)
**
** Returns:
** 0: success
** <0: -errno
*/
int
sm_notify_rcv(buf, buflen, tmo)
char *buf;
size_t buflen;
long tmo;
{
int r, len;
int save_errno;
fd_set readfds;
struct timeval timeout, *tval;
SM_REQUIRE(buf != NULL);
SM_REQUIRE(buflen > NETSTRPRE + 2);
if (NotifyRDpipe < 0)
return -EINVAL;
FD_ZERO(&readfds);
SM_FD_SET(NotifyRDpipe, &readfds);
if (tmo < 0)
tval = NULL;
else
{
timeout.tv_sec = (long) (tmo / SM_MICROS);
timeout.tv_usec = tmo % SM_MICROS;
tval = &timeout;
}
do {
r = select(NotifyRDpipe + 1, FDSET_CAST &readfds, NULL, NULL, tval);
save_errno = errno;
SM_DBG((stderr, "select=%d, fd=%d, e=%d\n", r, NotifyRDpipe, save_errno));
} while (r < 0 && save_errno == EINTR);
if (r <= 0)
{
SM_DBG((stderr, "select=%d, e=%d\n", r, save_errno));
return -ETIMEDOUT;
}
/* bogus... need to check again? */
if (!FD_ISSET(NotifyRDpipe, &readfds))
return -ETIMEDOUT;
r = read(NotifyRDpipe, buf, NETSTRPRE);
if (NETSTRPRE != r)
return -1; /* ??? */
if (sm_io_sscanf(buf, "%4u:", &len) != 1)
return -EINVAL; /* ??? */
if (len >= MAX_NETSTR)
return -E2BIG; /* ??? */
if (len >= buflen - 1)
return -E2BIG; /* ??? */
if (len <= 0)
return -EINVAL; /* ??? */
r = read(NotifyRDpipe, buf, len + 1);
save_errno = errno;
SM_DBG((stderr, "read=%d, e=%d\n", r, save_errno));
if (r == 0)
return -1; /* ??? */
if (r < 0)
return -save_errno;
if (len + 1 != r)
return -1; /* ??? */
if (buf[len] != ',')
return -EINVAL; /* ??? */
buf[len] = '\0';
return r;
}
#endif /* _FFR_DMTRIGGER */