1/*
2 * Copyright (c) 2021 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#ifndef LIBSM_NOTIFY_H
11#define LIBSM_NOTIFY_H
12
13#if SM_NOTIFY_DEBUG
14#define SM_DBG(p)	fprintf p
15#else
16#define SM_DBG(p)
17#endif
18
19/* microseconds */
20#define SM_MICROS 1000000L
21
22#define SM_MICROS2TVAL(tmo, tval, timeout) \
23	do	\
24	{	\
25		if (tmo < 0)	\
26			tval = NULL;	\
27		else	\
28		{	\
29			timeout.tv_sec = (long) (tmo / SM_MICROS);	\
30			timeout.tv_usec = tmo % SM_MICROS;	\
31			tval = &timeout;	\
32		}	\
33	} while (0)
34
35#define MAX_NETSTR 1024
36#define NETSTRPRE 5
37
38/* flow through code, be careful how to use! */
39#define RDNETSTR(rc, fd, SM_NOTIFY_EOF)	\
40	if ((rc) <= 0)	\
41	{	\
42		SM_DBG((stderr, "pid=%ld, select=%d, e=%d\n", (long)getpid(), (rc), save_errno)); \
43		return -ETIMEDOUT;	\
44	}	\
45	\
46	/* bogus... need to check again? */	\
47	if (!FD_ISSET(fd, &readfds))	\
48	{	\
49		SM_DBG((stderr, "pid=%ld, fd=%d, isset=false\n", (long)getpid(), fd)); \
50		return -ETIMEDOUT;	\
51	}	\
52	r = read(fd, buf, NETSTRPRE);	\
53	if (0 == r)	\
54	{	\
55		SM_DBG((stderr, "pid=%ld, fd=%d, read1=EOF, e=%d\n", (long)getpid(), fd, errno));	\
56		SM_NOTIFY_EOF;	\
57		return r;	\
58	}	\
59	if (NETSTRPRE != r)	\
60	{	\
61		SM_DBG((stderr, "pid=%ld, fd=%d, read1=%d, e=%d\n", (long)getpid(), fd, r, errno));	\
62		return -1;	/* ??? */	\
63	}	\
64	\
65	if (sm_io_sscanf(buf, "%4u:", &len) != 1)	\
66	{	\
67		SM_DBG((stderr, "pid=%ld, scanf, e=%d\n", (long)getpid(), errno));	\
68		return -EINVAL;	/* ??? */	\
69	}	\
70	if (len >= MAX_NETSTR)	\
71	{	\
72		SM_DBG((stderr, "pid=%ld, 1: len=%d\n", (long)getpid(), len));	\
73		return -E2BIG;	/* ??? */	\
74	}	\
75	if (len >= buflen - 1)	\
76	{	\
77		SM_DBG((stderr, "pid=%ld, 2: len=%d\n", (long)getpid(), len));	\
78		return -E2BIG;	/* ??? */	\
79	}	\
80	if (len <= 0)	\
81	{	\
82		SM_DBG((stderr, "pid=%ld, 3: len=%d\n", (long)getpid(), len));	\
83		return -EINVAL;	/* ??? */	\
84	}	\
85	r = read(fd, buf, len + 1);	\
86	save_errno = errno;	\
87	SM_DBG((stderr, "pid=%ld, fd=%d, read=%d, len=%d, e=%d\n", (long)getpid(), fd, r, len+1, save_errno));	\
88	if (r == 0)	\
89	{	\
90		SM_DBG((stderr, "pid=%ld, fd=%d, read2=%d, e=%d\n", (long)getpid(), fd, r, save_errno));	\
91		return -1;	/* ??? */	\
92	}	\
93	if (r < 0)	\
94	{	\
95		SM_DBG((stderr, "pid=%ld, fd=%d, read3=%d, e=%d\n", (long)getpid(), fd, r, save_errno));	\
96		return -save_errno;	\
97	}	\
98	if (len + 1 != r)	\
99	{	\
100		SM_DBG((stderr, "pid=%ld, fd=%d, read4=%d, len=%d\n", (long)getpid(), fd, r, len));	\
101		return -1;	/* ??? */	\
102	}	\
103	if (buf[len] != ',')	\
104	{	\
105		SM_DBG((stderr, "pid=%ld, fd=%d, read5=%d, f=%d\n", (long)getpid(), fd, r, buf[len]));	\
106		return -EINVAL;	/* ??? */	\
107	}	\
108	buf[len] = '\0';	\
109	return r
110
111#endif /* ! LIBSM_MSG_H */
112