1 /* $NetBSD: mail_flow.c,v 1.1.1.2 2013/01/02 18:59:01 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 #include <warn_stat.h> 59 60 /* Global library. */ 61 62 #include <mail_flow.h> 63 64 /* Master library. */ 65 66 #include <master_proto.h> 67 68 #define BUFFER_SIZE 1024 69 70 /* mail_flow_get - read N tokens */ 71 72 ssize_t mail_flow_get(ssize_t len) 73 { 74 const char *myname = "mail_flow_get"; 75 char buf[BUFFER_SIZE]; 76 struct stat st; 77 ssize_t count; 78 ssize_t n = 0; 79 80 /* 81 * Sanity check. 82 */ 83 if (len <= 0) 84 msg_panic("%s: bad length %ld", myname, (long) len); 85 86 /* 87 * Silence some wild claims. 88 */ 89 if (fstat(MASTER_FLOW_WRITE, &st) < 0) 90 msg_fatal("fstat flow pipe write descriptor: %m"); 91 92 /* 93 * Read and discard N bytes. XXX AIX read() can return 0 when an open 94 * pipe is empty. 95 */ 96 for (count = len; count > 0; count -= n) 97 if ((n = read(MASTER_FLOW_READ, buf, count > BUFFER_SIZE ? 98 BUFFER_SIZE : count)) <= 0) 99 return (-1); 100 if (msg_verbose) 101 msg_info("%s: %ld %ld", myname, (long) len, (long) (len - count)); 102 return (len - count); 103 } 104 105 /* mail_flow_put - put N tokens */ 106 107 ssize_t mail_flow_put(ssize_t len) 108 { 109 const char *myname = "mail_flow_put"; 110 char buf[BUFFER_SIZE]; 111 ssize_t count; 112 ssize_t n = 0; 113 114 /* 115 * Sanity check. 116 */ 117 if (len <= 0) 118 msg_panic("%s: bad length %ld", myname, (long) len); 119 120 /* 121 * Write or discard N bytes. 122 */ 123 memset(buf, 0, len > BUFFER_SIZE ? BUFFER_SIZE : len); 124 125 for (count = len; count > 0; count -= n) 126 if ((n = write(MASTER_FLOW_WRITE, buf, count > BUFFER_SIZE ? 127 BUFFER_SIZE : count)) < 0) 128 return (-1); 129 if (msg_verbose) 130 msg_info("%s: %ld %ld", myname, (long) len, (long) (len - count)); 131 return (len - count); 132 } 133 134 /* mail_flow_count - return number of available tokens */ 135 136 ssize_t mail_flow_count(void) 137 { 138 const char *myname = "mail_flow_count"; 139 ssize_t count; 140 141 if ((count = peekfd(MASTER_FLOW_READ)) < 0) 142 msg_warn("%s: %m", myname); 143 return (count); 144 } 145