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