1/* 2 * Copyright (c) 2020 Proofpoint, Inc. and its suppliers. 3 * All rights reserved. 4 * 5 * By using this file, you agree to the terms and conditions set 6 * forth in the LICENSE file which can be found at the top level of 7 * the sendmail distribution. 8 * 9 */ 10 11#include <sm/gen.h> 12 13#if _FFR_DMTRIGGER && _FFR_NOTIFY < 2 14#include <sm/conf.h> /* FDSET_CAST */ 15#include <sm/fdset.h> 16#include <sm/assert.h> 17#include <sm/notify.h> 18#include "notify.h" 19#include <sm/time.h> 20#include <sm/string.h> 21 22#include <sys/types.h> 23#include <signal.h> 24#include <stdio.h> 25#include <stdlib.h> 26#include <unistd.h> 27#include <stdbool.h> 28#include <errno.h> 29#include <fcntl.h> 30#include <string.h> /* for memset() */ 31 32static int Notifypipe[2]; 33#define NotifyRDpipe Notifypipe[0] 34#define NotifyWRpipe Notifypipe[1] 35 36#define CLOSEFD(fd) do { \ 37 if ((fd) != -1) { \ 38 (void) close(fd); \ 39 fd = - 1; \ 40 } \ 41 } while (0) \ 42 43 44/* 45** SM_NOTIFY_INIT -- initialize notify system 46** 47** Parameters: 48** flags -- ignored 49** 50** Returns: 51** 0: success 52** <0: -errno 53*/ 54 55int 56sm_notify_init(flags) 57 int flags; 58{ 59 if (pipe(Notifypipe) < 0) 60 return -errno; 61 return 0; 62} 63 64/* 65** SM_NOTIFY_START -- start notify system 66** 67** Parameters: 68** owner -- owner. 69** flags -- currently ignored. 70** 71** Returns: 72** 0: success 73** <0: -errno 74*/ 75 76int 77sm_notify_start(owner, flags) 78 bool owner; 79 int flags; 80{ 81 int r; 82 83 r = 0; 84 if (owner) 85 CLOSEFD(NotifyWRpipe); 86 else 87 CLOSEFD(NotifyRDpipe); 88 return r; 89} 90 91/* 92** SM_NOTIFY_STOP -- stop notify system 93** 94** Parameters: 95** owner -- owner. 96** flags -- currently ignored. 97** 98** Returns: 99** 0: success 100** <0: -errno 101*/ 102 103int 104sm_notify_stop(owner, flags) 105 bool owner; 106 int flags; 107{ 108 if (owner) 109 CLOSEFD(NotifyRDpipe); 110 else 111 CLOSEFD(NotifyWRpipe); 112 return 0; 113} 114 115/* 116** SM_NOTIFY_SND -- send notification 117** 118** Parameters: 119** buf -- where to write data 120** buflen -- len of buffer 121** 122** Returns: 123** 0: success 124** <0: -errno 125*/ 126 127int 128sm_notify_snd(buf, buflen) 129 char *buf; 130 size_t buflen; 131{ 132 int r; 133 int save_errno; 134 size_t len; 135 char netstr[MAX_NETSTR]; 136 137 SM_REQUIRE(buf != NULL); 138 SM_REQUIRE(buflen > 0); 139 if (NotifyWRpipe < 0) 140 return -EINVAL; 141 if (buflen >= MAX_NETSTR - 7) 142 return -E2BIG; /* XXX "TOO LARGE"? */ 143 144 len = sm_snprintf(netstr, sizeof(netstr), "%04d:%s,", (int)buflen, buf); 145 r = write(NotifyWRpipe, netstr, len); 146 save_errno = errno; 147 SM_DBG((stderr, "pid=%ld, write=%d, fd=%d, e=%d\n", (long)getpid(), r, NotifyWRpipe, save_errno)); 148 return r >= 0 ? 0 : -save_errno; 149} 150 151/* 152** SM_NOTIFY_RCV -- receive notification 153** 154** Parameters: 155** buf -- where to write data 156** buflen -- len of buffer 157** tmo -- timeout (micro seconds) 158** 159** Returns: 160** 0: EOF (XXX need to provide info about client) 161** >0: length of received data 162** <0: -errno 163*/ 164 165int 166sm_notify_rcv(buf, buflen, tmo) 167 char *buf; 168 size_t buflen; 169 long tmo; 170{ 171 int r, len; 172 int save_errno; 173 fd_set readfds; 174 struct timeval timeout, *tval; 175 176 SM_REQUIRE(buf != NULL); 177 SM_REQUIRE(buflen > NETSTRPRE + 2); 178 if (NotifyRDpipe < 0) 179 return -EINVAL; 180 FD_ZERO(&readfds); 181 SM_FD_SET(NotifyRDpipe, &readfds); 182 SM_MICROS2TVAL(tmo, tval, timeout); 183 184 do { 185 r = select(NotifyRDpipe + 1, FDSET_CAST &readfds, NULL, NULL, tval); 186 save_errno = errno; 187 SM_DBG((stderr, "pid=%ld, select=%d, fd=%d, e=%d\n", (long)getpid(), r, NotifyRDpipe, save_errno)); 188 } while (r < 0 && save_errno == EINTR); 189 190 RDNETSTR(r, NotifyRDpipe, (void)0); 191} 192#endif /* _FFR_DMTRIGGER && _FFR_NOTIFY < 2 */ 193