]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/sendmail/libsm/notify.c
Merge sendmail 8.16.1 to HEAD: See contrib/sendmail/RELEASE_NOTES for details
[FreeBSD/FreeBSD.git] / contrib / sendmail / libsm / notify.c
1 /*
2  * Copyright (c) 2016 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 #include <sys/types.h>
14 #include <signal.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <unistd.h>
18 #include <stdbool.h>
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <string.h>     /* for memset() */
22
23 #include <sm/conf.h>    /* FDSET_CAST */
24 #include <sm/fdset.h>
25 #include <sm/assert.h>
26 #include <sm/notify.h>
27
28 #if SM_NOTIFY_DEBUG
29 #define SM_DBG(p)       fprintf p
30 #else
31 #define SM_DBG(p)       
32 #endif
33
34 static int      Notifypipe[2];
35 #define NotifyRDpipe Notifypipe[0]
36 #define NotifyWRpipe Notifypipe[1]
37
38 #define CLOSEFD(fd) do { \
39                 if ((fd) != -1) {       \
40                         (void) close(fd);       \
41                         fd = - 1;       \
42                 }       \
43         } while (0)     \
44
45
46 /*
47 **  SM_NOTIFY_INIT -- initialize notify system
48 **
49 **      Parameters:
50 **              flags -- ignored
51 **
52 **      Returns:
53 **              0: success
54 **              <0: -errno
55 */
56
57 int
58 sm_notify_init(flags)
59         int flags;
60 {
61         if (pipe(Notifypipe) < 0)
62                 return -errno;
63         return 0;
64 }
65
66 /*
67 **  SM_NOTIFY_START -- start notify system
68 **
69 **      Parameters:
70 **              owner -- owner.
71 **              flags -- currently ignored.
72 **
73 **      Returns:
74 **              0: success
75 **              <0: -errno
76 */
77
78 int
79 sm_notify_start(owner, flags)
80         bool owner;
81         int flags;
82 {
83         int r;
84
85         r = 0;
86         if (owner)
87                 CLOSEFD(NotifyWRpipe);
88         else
89                 CLOSEFD(NotifyRDpipe);
90         return r;
91 }
92
93 /*
94 **  SM_NOTIFY_STOP -- stop notify system
95 **
96 **      Parameters:
97 **              owner -- owner.
98 **              flags -- currently ignored.
99 **
100 **      Returns:
101 **              0: success
102 **              <0: -errno
103 */
104
105 int
106 sm_notify_stop(owner, flags)
107         bool owner;
108         int flags;
109 {
110         if (owner)
111                 CLOSEFD(NotifyRDpipe);
112         else
113                 CLOSEFD(NotifyWRpipe);
114         return 0;
115 }
116
117 /*
118 **  SM_NOTIFY_SND -- send notification
119 **
120 **      Parameters:
121 **              buf -- where to write data
122 **              buflen -- len of buffer
123 **
124 **      Returns:
125 **              0: success
126 **              <0: -errno
127 */
128
129 int
130 sm_notify_snd(buf, buflen)
131         char *buf;
132         size_t buflen;
133 {
134         int r;
135         int save_errno;
136
137         SM_REQUIRE(buf != NULL);
138         SM_REQUIRE(buflen > 0);
139         if (NotifyWRpipe < 0)
140                 return -EINVAL;
141
142         r = write(NotifyWRpipe, buf, buflen);
143         save_errno = errno;
144         SM_DBG((stderr, "write=%d, fd=%d, e=%d\n", r, NotifyWRpipe, save_errno));
145         return r >= 0 ? 0 : -save_errno;
146 }
147
148 /*
149 **  SM_NOTIFY_RCV -- receive notification
150 **
151 **      Parameters:
152 **              buf -- where to write data
153 **              buflen -- len of buffer
154 **              tmo -- timeout
155 **
156 **      Returns:
157 **              0: success
158 **              <0: -errno
159 */
160
161 int
162 sm_notify_rcv(buf, buflen, tmo)
163         char *buf;
164         size_t buflen;
165         int tmo;
166 {
167         int r;
168         int save_errno;
169         fd_set readfds;
170         struct timeval timeout;
171
172         SM_REQUIRE(buf != NULL);
173         SM_REQUIRE(buflen > 0);
174         if (NotifyRDpipe < 0)
175                 return -EINVAL;
176         FD_ZERO(&readfds);
177         SM_FD_SET(NotifyRDpipe, &readfds);
178         timeout.tv_sec = tmo;
179         timeout.tv_usec = 0;
180
181         do {
182                 r = select(NotifyRDpipe + 1, FDSET_CAST &readfds, NULL, NULL, &timeout);
183                 save_errno = errno;
184                 SM_DBG((stderr, "select=%d, fd=%d, e=%d\n", r, NotifyRDpipe, save_errno));
185         } while (r < 0 && save_errno == EINTR);
186
187         if (r <= 0)
188         {
189                 SM_DBG((stderr, "select=%d, e=%d\n", r, save_errno));
190                 return -ETIMEDOUT;
191         }
192
193         /* bogus... need to check again? */
194         if (!FD_ISSET(NotifyRDpipe, &readfds))
195                 return -ETIMEDOUT;
196
197         r = read(NotifyRDpipe, buf, buflen);
198         save_errno = errno;
199         SM_DBG((stderr, "read=%d, e=%d\n", r, save_errno));
200         if (r == 0)
201                 return -1;      /* ??? */
202         if (r < 0)
203                 return -save_errno;
204         return r;
205 }