mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-30 13:48:06 +00:00
postfix-2.6-20081203
This commit is contained in:
committed by
Viktor Dukhovni
parent
3aba869192
commit
c1d7325cd1
@@ -14745,8 +14745,8 @@ Apologies for any names omitted.
|
||||
Feature: smtp_sasl_tls_verified_security_options is no
|
||||
longer #ifdef SNAPSHOT.
|
||||
|
||||
Feature: elliptic curve support. This requires OpenSSL version
|
||||
0.9.9 or later. Victor Duchovni. Files: TLS_README,
|
||||
Feature: elliptic curve support. This requires OpenSSL
|
||||
version 0.9.9 or later. Victor Duchovni. Files: TLS_README,
|
||||
smtpd/smtpd.c, smtp/smtp.c, tls/tls_dh.c, tls/tls_certkey.c,
|
||||
tls/tls_server.c, tls/tls_client.c, tls/tls.h, tls/tls_misc.c.
|
||||
|
||||
@@ -14757,3 +14757,29 @@ Apologies for any names omitted.
|
||||
20081109
|
||||
|
||||
Cleanup: confusing names of variables. File: smtpd/smtpd.c.
|
||||
|
||||
20081126
|
||||
|
||||
Bugfix: pcre_table(5) incorrectly claimed that the 'x' flag
|
||||
supports #comment after text. File: proto/pcre_table.
|
||||
|
||||
20081202
|
||||
|
||||
Cleanup: vstream_bufstat() provides a more systematic
|
||||
approach to get information about VSTREAM buffers. The
|
||||
vstream_peek() function is now a backwards compatibility
|
||||
wrapper. Files: util/vstream.[hc].
|
||||
|
||||
Cleanup: the SMTP server should warn about "lost connection
|
||||
after QUIT" only when the "." reply was pipelined together
|
||||
with the "QUIT" reply. File: smtpd/smtpd.c.
|
||||
|
||||
Cleanup: the SMTP client's code was duplicating buffer
|
||||
management that was already done in the VSTREAM module.
|
||||
File: smtp/smtp_proto.c.
|
||||
|
||||
20081203
|
||||
|
||||
Cleanup: adjust the VSTREAM buffer strategy when reusing
|
||||
an SMTP connection with a large TCP MSS value. File:
|
||||
smtp/smtp_proto.c.
|
||||
|
@@ -4,10 +4,10 @@ PPoossttffiixx AArrcchhiitteeccttuurree OOvveerrvviiee
|
||||
|
||||
IInnttrroodduuccttiioonn
|
||||
|
||||
This document presents an overview of the Postfix architecture, and is the
|
||||
place where you find a pointer to every Postfix command or server program. The
|
||||
text gives the general context in which each command or server program is used,
|
||||
and provides pointers to documents with specific usage examples and background
|
||||
This document presents an overview of the Postfix architecture, and provides
|
||||
pointers to descriptions of every Postfix command or server program. The text
|
||||
gives the general context in which each command or server program is used, and
|
||||
provides pointers to documents with specific usage examples and background
|
||||
information.
|
||||
|
||||
Topics covered by this document:
|
||||
@@ -63,7 +63,7 @@ programs, while unnumbered names inside shaded areas represent Postfix queues.
|
||||
section), and postmaster notifications about problems with Postfix.
|
||||
|
||||
* The cleanup(8) server implements the final processing stage before mail is
|
||||
queued. It adds missing From: and other message headers, transforms
|
||||
queued. It adds missing From: and other message headers, and transforms
|
||||
addresses as described in the ADDRESS_REWRITING_README document.
|
||||
Optionally, the cleanup(8) server can be configured to do light-weight
|
||||
content inspection with regular expressions as described in the
|
||||
|
@@ -21,7 +21,7 @@ Architecture Overview </h1>
|
||||
<h2> Introduction </h2>
|
||||
|
||||
<p> This document presents an overview of the Postfix architecture,
|
||||
and is the place where you find a pointer to every Postfix command
|
||||
and provides pointers to descriptions of every Postfix command
|
||||
or server program. The text gives the general context in which
|
||||
each command or server program is used, and provides pointers to
|
||||
documents with specific usage examples and background information.
|
||||
@@ -173,7 +173,8 @@ notifications about problems with Postfix. </p>
|
||||
|
||||
<li> <p> The <a href="cleanup.8.html">cleanup(8)</a> server implements the final processing
|
||||
stage before mail is queued. It adds missing From: and other message
|
||||
headers, transforms addresses as described in the <a href="ADDRESS_REWRITING_README.html">ADDRESS_REWRITING_README</a>
|
||||
headers, and transforms addresses as described in the
|
||||
<a href="ADDRESS_REWRITING_README.html">ADDRESS_REWRITING_README</a>
|
||||
document. Optionally, the <a href="cleanup.8.html">cleanup(8)</a> server can be configured to
|
||||
do light-weight content inspection with regular expressions as
|
||||
described in the <a href="BUILTIN_FILTER_README.html">BUILTIN_FILTER_README</a> document. The <a href="cleanup.8.html">cleanup(8)</a>
|
||||
|
@@ -110,12 +110,12 @@ PCRE_TABLE(5) PCRE_TABLE(5)
|
||||
|
||||
<b>x</b> (default: off)
|
||||
Toggles the pcre extended flag. When this flag is
|
||||
on, whitespace in the pattern (other than in a
|
||||
character class) and characters between a <b>#</b> outside
|
||||
a character class and the next newline character
|
||||
are ignored. An escaping backslash can be used to
|
||||
include a whitespace or <b>#</b> character as part of the
|
||||
pattern.
|
||||
on, whitespace characters in the pattern (other
|
||||
than in a character class) are ignored. To include
|
||||
a whitespace character as part of the pattern,
|
||||
escape it with backslash.
|
||||
|
||||
Note: do not use <b>#</b><i>comment</i> after patterns.
|
||||
|
||||
<b>A</b> (default: off)
|
||||
Toggles the PCRE_ANCHORED flag. When this flag is
|
||||
|
@@ -100,11 +100,11 @@ default, which is inconvenient for multi-line message header
|
||||
matching.
|
||||
.IP "\fBx\fR (default: off)"
|
||||
Toggles the pcre extended flag. When this flag is on, whitespace
|
||||
in the pattern (other than in a character class) and
|
||||
characters between a \fB#\fR outside a character class and
|
||||
the next newline character are ignored. An escaping backslash
|
||||
can be used to include a whitespace or \fB#\fR character
|
||||
as part of the pattern.
|
||||
characters in the pattern (other than in a character class)
|
||||
are ignored. To include a whitespace character as part of
|
||||
the pattern, escape it with backslash.
|
||||
.sp
|
||||
Note: do not use \fB#\fIcomment\fR after patterns.
|
||||
.IP "\fBA\fR (default: off)"
|
||||
Toggles the PCRE_ANCHORED flag. When this flag is on,
|
||||
the pattern is forced to be "anchored", that is, it is
|
||||
|
@@ -21,7 +21,7 @@ Architecture Overview </h1>
|
||||
<h2> Introduction </h2>
|
||||
|
||||
<p> This document presents an overview of the Postfix architecture,
|
||||
and is the place where you find a pointer to every Postfix command
|
||||
and provides pointers to descriptions of every Postfix command
|
||||
or server program. The text gives the general context in which
|
||||
each command or server program is used, and provides pointers to
|
||||
documents with specific usage examples and background information.
|
||||
@@ -173,7 +173,8 @@ notifications about problems with Postfix. </p>
|
||||
|
||||
<li> <p> The cleanup(8) server implements the final processing
|
||||
stage before mail is queued. It adds missing From: and other message
|
||||
headers, transforms addresses as described in the ADDRESS_REWRITING_README
|
||||
headers, and transforms addresses as described in the
|
||||
ADDRESS_REWRITING_README
|
||||
document. Optionally, the cleanup(8) server can be configured to
|
||||
do light-weight content inspection with regular expressions as
|
||||
described in the BUILTIN_FILTER_README document. The cleanup(8)
|
||||
|
@@ -90,11 +90,11 @@
|
||||
# matching.
|
||||
# .IP "\fBx\fR (default: off)"
|
||||
# Toggles the pcre extended flag. When this flag is on, whitespace
|
||||
# in the pattern (other than in a character class) and
|
||||
# characters between a \fB#\fR outside a character class and
|
||||
# the next newline character are ignored. An escaping backslash
|
||||
# can be used to include a whitespace or \fB#\fR character
|
||||
# as part of the pattern.
|
||||
# characters in the pattern (other than in a character class)
|
||||
# are ignored. To include a whitespace character as part of
|
||||
# the pattern, escape it with backslash.
|
||||
# .sp
|
||||
# Note: do not use \fB#\fIcomment\fR after patterns.
|
||||
# .IP "\fBA\fR (default: off)"
|
||||
# Toggles the PCRE_ANCHORED flag. When this flag is on,
|
||||
# the pattern is forced to be "anchored", that is, it is
|
||||
|
@@ -20,7 +20,7 @@
|
||||
* Patches change both the patchlevel and the release date. Snapshots have no
|
||||
* patchlevel; they change the release date only.
|
||||
*/
|
||||
#define MAIL_RELEASE_DATE "20081109"
|
||||
#define MAIL_RELEASE_DATE "20081203"
|
||||
#define MAIL_VERSION_NUMBER "2.6"
|
||||
|
||||
#ifdef SNAPSHOT
|
||||
|
@@ -208,7 +208,6 @@ typedef struct SMTP_SESSION {
|
||||
int error_mask; /* error classes */
|
||||
struct MIME_STATE *mime_state; /* mime state machine */
|
||||
|
||||
int sndbufsize; /* PIPELINING buffer size */
|
||||
int send_proto_helo; /* XFORWARD support */
|
||||
|
||||
time_t expire_time; /* session reuse expiration time */
|
||||
|
@@ -274,6 +274,7 @@ int smtp_helo(SMTP_STATE *state)
|
||||
0, 0,
|
||||
};
|
||||
SOCKOPT_SIZE optlen;
|
||||
int sndbufsize;
|
||||
const char *ehlo_words;
|
||||
int discard_mask;
|
||||
static const NAME_MASK pix_bug_table[] = {
|
||||
@@ -559,27 +560,24 @@ int smtp_helo(SMTP_STATE *state)
|
||||
* if we do.
|
||||
*/
|
||||
if (session->features & SMTP_FEATURE_PIPELINING) {
|
||||
optlen = sizeof(session->sndbufsize);
|
||||
optlen = sizeof(sndbufsize);
|
||||
if (getsockopt(vstream_fileno(session->stream), SOL_SOCKET,
|
||||
SO_SNDBUF, (char *) &session->sndbufsize, &optlen) < 0)
|
||||
SO_SNDBUF, (char *) &sndbufsize, &optlen) < 0)
|
||||
msg_fatal("%s: getsockopt: %m", myname);
|
||||
if (session->sndbufsize > VSTREAM_BUFSIZE)
|
||||
session->sndbufsize = VSTREAM_BUFSIZE;
|
||||
if (session->sndbufsize == 0) {
|
||||
session->sndbufsize = VSTREAM_BUFSIZE;
|
||||
if (sndbufsize > VSTREAM_BUFSIZE)
|
||||
sndbufsize = VSTREAM_BUFSIZE;
|
||||
if (sndbufsize < VSTREAM_BUFSIZE) {
|
||||
sndbufsize = VSTREAM_BUFSIZE;
|
||||
if (setsockopt(vstream_fileno(session->stream), SOL_SOCKET,
|
||||
SO_SNDBUF, (char *) &session->sndbufsize, optlen) < 0)
|
||||
SO_SNDBUF, (char *) &sndbufsize, optlen) < 0)
|
||||
msg_fatal("%s: setsockopt: %m", myname);
|
||||
}
|
||||
if (msg_verbose)
|
||||
msg_info("Using %s PIPELINING, TCP send buffer size is %d",
|
||||
(state->misc_flags &
|
||||
SMTP_MISC_FLAG_USE_LMTP) ? "LMTP" : "ESMTP",
|
||||
session->sndbufsize);
|
||||
} else {
|
||||
session->sndbufsize = 0;
|
||||
sndbufsize);
|
||||
}
|
||||
|
||||
#ifdef USE_TLS
|
||||
|
||||
/*
|
||||
@@ -1081,7 +1079,6 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state,
|
||||
int except;
|
||||
int rec_type;
|
||||
NOCLOBBER int prev_type = 0;
|
||||
NOCLOBBER int sndbuffree;
|
||||
NOCLOBBER int mail_from_rejected;
|
||||
NOCLOBBER int downgrading;
|
||||
int mime_errs;
|
||||
@@ -1131,20 +1128,6 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state,
|
||||
#define CANT_RSET_THIS_SESSION \
|
||||
(session->features |= SMTP_FEATURE_RSET_REJECTED)
|
||||
|
||||
/*
|
||||
* Sanity check. We don't want smtp_chat() to inadvertently flush the
|
||||
* output buffer. That means someone broke pipelining support.
|
||||
*/
|
||||
if (session->sndbufsize > VSTREAM_BUFSIZE)
|
||||
msg_panic("bad sndbufsize %d > VSTREAM_BUFSIZE %d",
|
||||
session->sndbufsize, VSTREAM_BUFSIZE);
|
||||
|
||||
/*
|
||||
* Miscellaneous initialization. Some of this might be done in
|
||||
* smtp_xfer() but that just complicates interfaces and data structures.
|
||||
*/
|
||||
sndbuffree = session->sndbufsize;
|
||||
|
||||
/*
|
||||
* Pipelining support requires two loops: one loop for sending and one
|
||||
* for receiving. Each loop has its own independent state. Most of the
|
||||
@@ -1432,8 +1415,12 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state,
|
||||
*/
|
||||
if (SENDER_IN_WAIT_STATE
|
||||
|| (SENDER_IS_AHEAD
|
||||
&& (VSTRING_LEN(next_command) + 2 > sndbuffree
|
||||
|| time((time_t *) 0) - vstream_ftime(session->stream) > 10))) {
|
||||
&& ((session->features & SMTP_FEATURE_PIPELINING) == 0
|
||||
|| (VSTRING_LEN(next_command) + 2
|
||||
+ vstream_bufstat(session->stream, VSTREAM_BST_OUT_PEND)
|
||||
> VSTREAM_BUFSIZE)
|
||||
|| time((time_t *) 0)
|
||||
- vstream_ftime(session->stream) > 10))) {
|
||||
while (SENDER_IS_AHEAD) {
|
||||
|
||||
/*
|
||||
@@ -1707,10 +1694,8 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state,
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point, the sender and receiver are fully synchronized,
|
||||
* so that the entire TCP send buffer becomes available again.
|
||||
* At this point, the sender and receiver are fully synchronized.
|
||||
*/
|
||||
sndbuffree = session->sndbufsize;
|
||||
|
||||
/*
|
||||
* We know the server response to every command that was sent.
|
||||
@@ -1874,8 +1859,6 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state,
|
||||
* Copy the next command to the buffer and update the sender state.
|
||||
*/
|
||||
if (except == 0) {
|
||||
if (sndbuffree > 0)
|
||||
sndbuffree -= VSTRING_LEN(next_command) + 2;
|
||||
smtp_chat_cmd(session, "%s", vstring_str(next_command));
|
||||
} else {
|
||||
DONT_CACHE_THIS_SESSION;
|
||||
|
@@ -213,6 +213,11 @@ static SMTP_SESSION *smtp_reuse_common(SMTP_STATE *state, int fd,
|
||||
return (state->session = 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Avoid poor performance when TCP MSS > VSTREAM_BUFSIZE.
|
||||
*/
|
||||
vstream_tweak_sock(session->stream);
|
||||
|
||||
/*
|
||||
* Update the list of used cached addresses.
|
||||
*/
|
||||
|
@@ -585,7 +585,6 @@ SMTP_SESSION *smtp_session_alloc(VSTREAM *stream, const char *dest,
|
||||
} else
|
||||
session->namaddrport = mystrdup(session->namaddr);
|
||||
|
||||
session->sndbufsize = 0;
|
||||
session->send_proto_helo = 0;
|
||||
|
||||
if (flags & SMTP_MISC_FLAG_CONN_STORE)
|
||||
@@ -695,13 +694,12 @@ int smtp_session_passivate(SMTP_SESSION *session, VSTRING *dest_prop,
|
||||
* XXX Be sure to use unsigned types in the format string. Sign characters
|
||||
* would be rejected by the alldig() test on the reading end.
|
||||
*/
|
||||
vstring_sprintf(endp_prop, "%u\n%s\n%s\n%s\n%u\n%u\n%lu\n%u",
|
||||
vstring_sprintf(endp_prop, "%u\n%s\n%s\n%s\n%u\n%u\n%lu",
|
||||
session->reuse_count,
|
||||
session->dest, session->host,
|
||||
session->addr, session->port,
|
||||
session->features & SMTP_FEATURE_ENDPOINT_MASK,
|
||||
(long) session->expire_time,
|
||||
session->sndbufsize);
|
||||
(long) session->expire_time);
|
||||
|
||||
/*
|
||||
* Append the passivated SASL attributes.
|
||||
@@ -740,7 +738,6 @@ SMTP_SESSION *smtp_session_activate(int fd, VSTRING *dest_prop,
|
||||
unsigned features; /* server features */
|
||||
time_t expire_time; /* session re-use expiration time */
|
||||
unsigned reuse_count; /* # times reused */
|
||||
unsigned sndbufsize; /* PIPELINING buffer size */
|
||||
|
||||
/*
|
||||
* XXX it would be nice to have a VSTRING to VSTREAM adapter so that we
|
||||
@@ -790,12 +787,6 @@ SMTP_SESSION *smtp_session_activate(int fd, VSTRING *dest_prop,
|
||||
expire_time = strtoul(prop, 0, 10);
|
||||
#endif
|
||||
|
||||
if ((prop = mystrtok(&endp_props, "\n")) == 0 || !alldig(prop)) {
|
||||
msg_warn("%s: bad cached session sndbufsize property", myname);
|
||||
return (0);
|
||||
}
|
||||
sndbufsize = atoi(prop);
|
||||
|
||||
if (dest_prop && VSTRING_LEN(dest_prop)) {
|
||||
dest_props = STR(dest_prop);
|
||||
if ((prop = mystrtok(&dest_props, "\n")) == 0 || !alldig(prop)) {
|
||||
@@ -815,14 +806,12 @@ SMTP_SESSION *smtp_session_activate(int fd, VSTRING *dest_prop,
|
||||
session->features = (features | SMTP_FEATURE_FROM_CACHE);
|
||||
CACHE_THIS_SESSION_UNTIL(expire_time);
|
||||
session->reuse_count = ++reuse_count;
|
||||
session->sndbufsize = sndbufsize;
|
||||
|
||||
if (msg_verbose)
|
||||
msg_info("%s: dest=%s host=%s addr=%s port=%u features=0x%x, "
|
||||
"ttl=%ld, reuse=%d, sndbuf=%u",
|
||||
"ttl=%ld, reuse=%d",
|
||||
myname, dest, host, addr, ntohs(port), features,
|
||||
(long) (expire_time - time((time_t *) 0)), reuse_count,
|
||||
sndbufsize);
|
||||
(long) (expire_time - time((time_t *) 0)), reuse_count);
|
||||
|
||||
/*
|
||||
* Re-activate the SASL attributes.
|
||||
|
@@ -1266,7 +1266,7 @@ MILTERS *smtpd_milters;
|
||||
* TLS initialization status.
|
||||
*/
|
||||
static TLS_APPL_STATE *smtpd_tls_ctx;
|
||||
static int require_server_cert;
|
||||
static int ask_client_cert;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3286,7 +3286,8 @@ static int quit_cmd(SMTPD_STATE *state, int unused_argc, SMTPD_TOKEN *unused_arg
|
||||
* XXX When this was added in Postfix 2.1 we used vstream_fflush(). As of
|
||||
* Postfix 2.3 we use smtp_flush() for better error reporting.
|
||||
*/
|
||||
smtp_flush(state->client);
|
||||
if (vstream_bufstat(state->client, VSTREAM_BST_OUT_PEND) > 0)
|
||||
smtp_flush(state->client);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -3857,7 +3858,7 @@ static void smtpd_start_tls(SMTPD_STATE *state)
|
||||
ADD_EXCLUDE(cipher_exclusions, var_smtpd_tls_excl_ciph);
|
||||
if (enforce_tls)
|
||||
ADD_EXCLUDE(cipher_exclusions, var_smtpd_tls_mand_excl);
|
||||
if (require_server_cert)
|
||||
if (ask_client_cert)
|
||||
ADD_EXCLUDE(cipher_exclusions, "aNULL");
|
||||
}
|
||||
|
||||
@@ -4645,7 +4646,7 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
|
||||
const char *cert_file;
|
||||
int have_server_cert;
|
||||
int no_server_cert_ok;
|
||||
int ask_client_cert;
|
||||
int require_server_cert;
|
||||
|
||||
/*
|
||||
* Can't use anonymous ciphers if we want client certificates.
|
||||
|
@@ -130,6 +130,13 @@ extern char *gai_strerror(int);
|
||||
* Routines and data structures to hide some of the complexity of the
|
||||
* addrinfo API. They still don't hide that we may get results for address
|
||||
* families that we aren't interested in.
|
||||
*
|
||||
* Note: the getnameinfo() and inet_ntop() system library functions use unsafe
|
||||
* APIs with separate pointer and length arguments. To avoid buffer overflow
|
||||
* problems with these functions, Postfix uses pointers to structures
|
||||
* internally. This way the compiler can enforce that callers provide
|
||||
* buffers with the appropriate length, instead of having to trust that
|
||||
* callers will never mess up some length calculation.
|
||||
*/
|
||||
typedef struct {
|
||||
char buf[MAI_HOSTNAME_STRSIZE];
|
||||
|
@@ -101,6 +101,10 @@
|
||||
/* const char *format;
|
||||
/* va_list *ap;
|
||||
/*
|
||||
/* ssize_t vstream_bufstat(stream, command)
|
||||
/* VSTREAM *stream;
|
||||
/* int command;
|
||||
/*
|
||||
/* ssize_t vstream_peek(stream)
|
||||
/* VSTREAM *stream;
|
||||
/*
|
||||
@@ -320,8 +324,18 @@
|
||||
/* vstream_vfprintf() provides an alternate interface
|
||||
/* for formatting an argument list according to a format string.
|
||||
/*
|
||||
/* vstream_bufstat() provides input and output buffer status
|
||||
/* information. The command is one of the following:
|
||||
/* .IP VSTREAM_BST_IN_PEND
|
||||
/* Return the number of characters that can be read without
|
||||
/* refilling the read buffer.
|
||||
/* .IP VSTREAM_BST_OUT_PEND
|
||||
/* Return the number of characters that are waiting in the
|
||||
/* write buffer.
|
||||
/* .PP
|
||||
/* vstream_peek() returns the number of characters that can be
|
||||
/* read from the named stream without refilling the read buffer.
|
||||
/* This is an alias for vstream_bufstat(stream, VSTREAM_BST_IN_PEND).
|
||||
/*
|
||||
/* vstream_setjmp() saves processing context and makes that context
|
||||
/* available for use with vstream_longjmp(). Normally, vstream_setjmp()
|
||||
@@ -703,8 +717,10 @@ static int vstream_buf_get_ready(VBUF *bp)
|
||||
* allocation gives the application a chance to override the default
|
||||
* buffering policy.
|
||||
*/
|
||||
if (bp->data == 0)
|
||||
vstream_buf_alloc(bp, VSTREAM_BUFSIZE);
|
||||
if (stream->req_bufsize == 0)
|
||||
stream->req_bufsize = VSTREAM_BUFSIZE;
|
||||
if (bp->len < stream->req_bufsize)
|
||||
vstream_buf_alloc(bp, stream->req_bufsize);
|
||||
|
||||
/*
|
||||
* If the stream is double-buffered and the write buffer is not empty,
|
||||
@@ -1306,6 +1322,47 @@ VSTREAM *vstream_vfprintf(VSTREAM *vp, const char *format, va_list ap)
|
||||
return (vp);
|
||||
}
|
||||
|
||||
/* vstream_bufstat - get stream buffer status */
|
||||
|
||||
ssize_t vstream_bufstat(VSTREAM *vp, int command)
|
||||
{
|
||||
VBUF *bp;
|
||||
|
||||
switch (command & VSTREAM_BST_MASK_DIR) {
|
||||
case VSTREAM_BST_FLAG_IN:
|
||||
if (vp->buf.flags & VSTREAM_FLAG_READ) {
|
||||
bp = &vp->buf;
|
||||
} else if (vp->buf.flags & VSTREAM_FLAG_DOUBLE) {
|
||||
bp = &vp->read_buf;
|
||||
} else {
|
||||
bp = 0;
|
||||
}
|
||||
switch (command & ~VSTREAM_BST_MASK_DIR) {
|
||||
case VSTREAM_BST_FLAG_PEND:
|
||||
return (bp ? -bp->cnt : 0);
|
||||
/* Add other requests below. */
|
||||
}
|
||||
break;
|
||||
case VSTREAM_BST_FLAG_OUT:
|
||||
if (vp->buf.flags & VSTREAM_FLAG_WRITE) {
|
||||
bp = &vp->buf;
|
||||
} else if (vp->buf.flags & VSTREAM_FLAG_DOUBLE) {
|
||||
bp = &vp->write_buf;
|
||||
} else {
|
||||
bp = 0;
|
||||
}
|
||||
switch (command & ~VSTREAM_BST_MASK_DIR) {
|
||||
case VSTREAM_BST_FLAG_PEND:
|
||||
return (bp ? bp->len - bp->cnt : 0);
|
||||
/* Add other requests below. */
|
||||
}
|
||||
break;
|
||||
}
|
||||
msg_panic("vstream_bufstat: unknown command: %d", command);
|
||||
}
|
||||
|
||||
#undef vstream_peek /* API binary compatibility. */
|
||||
|
||||
/* vstream_peek - peek at a stream */
|
||||
|
||||
ssize_t vstream_peek(VSTREAM *vp)
|
||||
|
@@ -154,6 +154,17 @@ extern int vstream_pclose(VSTREAM *);
|
||||
extern VSTREAM *vstream_vfprintf(VSTREAM *, const char *, va_list);
|
||||
|
||||
extern ssize_t vstream_peek(VSTREAM *);
|
||||
extern ssize_t vstream_bufstat(VSTREAM *, int);
|
||||
|
||||
#define VSTREAM_BST_FLAG_IN (1<<0)
|
||||
#define VSTREAM_BST_FLAG_OUT (1<<1)
|
||||
#define VSTREAM_BST_FLAG_PEND (1<<2)
|
||||
|
||||
#define VSTREAM_BST_MASK_DIR (VSTREAM_BST_FLAG_IN | VSTREAM_BST_FLAG_OUT)
|
||||
#define VSTREAM_BST_IN_PEND (VSTREAM_BST_FLAG_IN | VSTREAM_BST_FLAG_PEND)
|
||||
#define VSTREAM_BST_OUT_PEND (VSTREAM_BST_FLAG_OUT | VSTREAM_BST_FLAG_PEND)
|
||||
|
||||
#define vstream_peek(vp) vstream_bufstat((vp), VSTREAM_BST_IN_PEND)
|
||||
|
||||
/*
|
||||
* Exception handling. We use pointer to jmp_buf to avoid a lot of unused
|
||||
|
Reference in New Issue
Block a user