xref: /netbsd-src/external/ibm-public/postfix/dist/src/master/mail_flow.c (revision daf6c4152fcddc27c445489775ed1f66ab4ea9a9)
1 /*	$NetBSD: mail_flow.c,v 1.1.1.1 2009/06/23 10:08:49 tron Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	mail_flow 3
6 /* SUMMARY
7 /*	global mail flow control
8 /* SYNOPSIS
9 /*	#include <mail_flow.h>
10 /*
11 /*	ssize_t	mail_flow_get(count)
12 /*	ssize_t	count;
13 /*
14 /*	ssize_t	mail_flow_put(count)
15 /*	ssize_t	count;
16 /*
17 /*	ssize_t	mail_flow_count()
18 /* DESCRIPTION
19 /*	This module implements a simple flow control mechanism that
20 /*	is based on tokens that are consumed by mail receiving processes
21 /*	and that are produced by mail sending processes.
22 /*
23 /*	mail_flow_get() attempts to read specified number of tokens. The
24 /*	result is > 0 for success, < 0 for failure. In the latter case,
25 /*	the process is expected to slow down a little.
26 /*
27 /*	mail_flow_put() produces the specified number of tokens. The
28 /*	token producing process is expected to produce new tokens
29 /*	whenever it falls idle and no more tokens are available.
30 /*
31 /*	mail_flow_count() returns the number of available tokens.
32 /* BUGS
33 /*	The producer needs to wake up periodically to ensure that
34 /*	tokens are not lost due to leakage.
35 /* LICENSE
36 /* .ad
37 /* .fi
38 /*	The Secure Mailer license must be distributed with this software.
39 /* AUTHOR(S)
40 /*	Wietse Venema
41 /*	IBM T.J. Watson Research
42 /*	P.O. Box 704
43 /*	Yorktown Heights, NY 10598, USA
44 /*--*/
45 
46 /* System library. */
47 
48 #include <sys_defs.h>
49 #include <sys/stat.h>
50 #include <unistd.h>
51 #include <stdlib.h>
52 #include <string.h>
53 
54 /* Utility library. */
55 
56 #include <msg.h>
57 #include <iostuff.h>
58 
59 /* Global library. */
60 
61 #include <mail_flow.h>
62 
63 /* Master library. */
64 
65 #include <master_proto.h>
66 
67 #define BUFFER_SIZE	1024
68 
69 /* mail_flow_get - read N tokens */
70 
71 ssize_t mail_flow_get(ssize_t len)
72 {
73     const char *myname = "mail_flow_get";
74     char    buf[BUFFER_SIZE];
75     struct stat st;
76     ssize_t count;
77     ssize_t n = 0;
78 
79     /*
80      * Sanity check.
81      */
82     if (len <= 0)
83 	msg_panic("%s: bad length %ld", myname, (long) len);
84 
85     /*
86      * Silence some wild claims.
87      */
88     if (fstat(MASTER_FLOW_WRITE, &st) < 0)
89 	msg_fatal("fstat flow pipe write descriptor: %m");
90 
91     /*
92      * Read and discard N bytes. XXX AIX read() can return 0 when an open
93      * pipe is empty.
94      */
95     for (count = len; count > 0; count -= n)
96 	if ((n = read(MASTER_FLOW_READ, buf, count > BUFFER_SIZE ?
97 		      BUFFER_SIZE : count)) <= 0)
98 	    return (-1);
99     if (msg_verbose)
100 	msg_info("%s: %ld %ld", myname, (long) len, (long) (len - count));
101     return (len - count);
102 }
103 
104 /* mail_flow_put - put N tokens */
105 
106 ssize_t mail_flow_put(ssize_t len)
107 {
108     const char *myname = "mail_flow_put";
109     char    buf[BUFFER_SIZE];
110     ssize_t count;
111     ssize_t n = 0;
112 
113     /*
114      * Sanity check.
115      */
116     if (len <= 0)
117 	msg_panic("%s: bad length %ld", myname, (long) len);
118 
119     /*
120      * Write or discard N bytes.
121      */
122     memset(buf, 0, len > BUFFER_SIZE ? BUFFER_SIZE : len);
123 
124     for (count = len; count > 0; count -= n)
125 	if ((n = write(MASTER_FLOW_WRITE, buf, count > BUFFER_SIZE ?
126 		       BUFFER_SIZE : count)) < 0)
127 	    return (-1);
128     if (msg_verbose)
129 	msg_info("%s: %ld %ld", myname, (long) len, (long) (len - count));
130     return (len - count);
131 }
132 
133 /* mail_flow_count - return number of available tokens */
134 
135 ssize_t mail_flow_count(void)
136 {
137     const char *myname = "mail_flow_count";
138     ssize_t count;
139 
140     if ((count = peekfd(MASTER_FLOW_READ)) < 0)
141 	msg_warn("%s: %m", myname);
142     return (count);
143 }
144