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 32 static 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 55 int 56 sm_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 76 int 77 sm_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 103 int 104 sm_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 127 int 128 sm_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 165 int 166 sm_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