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