Home | History | Annotate | Line # | Download | only in master
      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