buffer.c revision 128269
125839Speter/* Code for the buffer data structure.  */
225839Speter
3102852Speter/* $FreeBSD: head/contrib/cvs/src/buffer.c 128269 2004-04-15 01:17:28Z peter $ */
4102852Speter
525839Speter#include <assert.h>
625839Speter#include "cvs.h"
725839Speter#include "buffer.h"
825839Speter
925839Speter#if defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT)
1025839Speter
11102840Speter#ifdef HAVE_WINSOCK_H
12102840Speter# include <winsock.h>
13102840Speter#else
14102840Speter# include <sys/socket.h>
15102840Speter#endif
16102840Speter
1725839Speter/* OS/2 doesn't have EIO.  FIXME: this whole notion of turning
1825839Speter   a different error into EIO strikes me as pretty dubious.  */
1925839Speter#if !defined (EIO)
2025839Speter#define EIO EBADPOS
2125839Speter#endif
2225839Speter
2325839Speter/* Linked list of available buffer_data structures.  */
2425839Speterstatic struct buffer_data *free_buffer_data;
2525839Speter
2625839Speter/* Local functions.  */
2734461Speterstatic void buf_default_memory_error PROTO ((struct buffer *));
2825839Speterstatic void allocate_buffer_datas PROTO((void));
2925839Speterstatic struct buffer_data *get_buffer_data PROTO((void));
3025839Speter
3125839Speter/* Initialize a buffer structure.  */
3225839Speter
3325839Speterstruct buffer *
3425839Speterbuf_initialize (input, output, flush, block, shutdown, memory, closure)
3525839Speter     int (*input) PROTO((void *, char *, int, int, int *));
3625839Speter     int (*output) PROTO((void *, const char *, int, int *));
3725839Speter     int (*flush) PROTO((void *));
3825839Speter     int (*block) PROTO((void *, int));
39102840Speter     int (*shutdown) PROTO((struct buffer *));
4025839Speter     void (*memory) PROTO((struct buffer *));
4125839Speter     void *closure;
4225839Speter{
4325839Speter    struct buffer *buf;
4425839Speter
4525839Speter    buf = (struct buffer *) xmalloc (sizeof (struct buffer));
4625839Speter    buf->data = NULL;
4725839Speter    buf->last = NULL;
4825839Speter    buf->nonblocking = 0;
4925839Speter    buf->input = input;
5025839Speter    buf->output = output;
5125839Speter    buf->flush = flush;
5225839Speter    buf->block = block;
5325839Speter    buf->shutdown = shutdown;
5434461Speter    buf->memory_error = memory ? memory : buf_default_memory_error;
5525839Speter    buf->closure = closure;
5625839Speter    return buf;
5725839Speter}
5825839Speter
5934461Speter/* Free a buffer structure.  */
6034461Speter
6134461Spetervoid
6234461Speterbuf_free (buf)
6334461Speter     struct buffer *buf;
6434461Speter{
65128269Speter    if (buf->closure != NULL)
66128269Speter    {
67128269Speter	free (buf->closure);
68128269Speter	buf->closure = NULL;
69128269Speter    }
7034461Speter    if (buf->data != NULL)
7134461Speter    {
7234461Speter	buf->last->next = free_buffer_data;
7334461Speter	free_buffer_data = buf->data;
7434461Speter    }
7534461Speter    free (buf);
7634461Speter}
7734461Speter
7825839Speter/* Initialize a buffer structure which is not to be used for I/O.  */
7925839Speter
8025839Speterstruct buffer *
8125839Speterbuf_nonio_initialize (memory)
8225839Speter     void (*memory) PROTO((struct buffer *));
8325839Speter{
8425839Speter    return (buf_initialize
8525839Speter	    ((int (*) PROTO((void *, char *, int, int, int *))) NULL,
8625839Speter	     (int (*) PROTO((void *, const char *, int, int *))) NULL,
8725839Speter	     (int (*) PROTO((void *))) NULL,
8825839Speter	     (int (*) PROTO((void *, int))) NULL,
89102840Speter	     (int (*) PROTO((struct buffer *))) NULL,
9025839Speter	     memory,
9125839Speter	     (void *) NULL));
9225839Speter}
9325839Speter
9434461Speter/* Default memory error handler.  */
9534461Speter
9634461Speterstatic void
9734461Speterbuf_default_memory_error (buf)
9834461Speter     struct buffer *buf;
9934461Speter{
10034461Speter    error (1, 0, "out of memory");
10134461Speter}
10234461Speter
10325839Speter/* Allocate more buffer_data structures.  */
10425839Speter
10525839Speterstatic void
10625839Speterallocate_buffer_datas ()
10725839Speter{
10825839Speter    struct buffer_data *alc;
10925839Speter    char *space;
11025839Speter    int i;
11125839Speter
11225839Speter    /* Allocate buffer_data structures in blocks of 16.  */
11325839Speter#define ALLOC_COUNT (16)
11425839Speter
11525839Speter    alc = ((struct buffer_data *)
116109660Speter	   xmalloc (ALLOC_COUNT * sizeof (struct buffer_data)));
11725839Speter    space = (char *) valloc (ALLOC_COUNT * BUFFER_DATA_SIZE);
11825839Speter    if (alc == NULL || space == NULL)
11925839Speter	return;
12025839Speter    for (i = 0; i < ALLOC_COUNT; i++, alc++, space += BUFFER_DATA_SIZE)
12125839Speter    {
12225839Speter	alc->next = free_buffer_data;
12325839Speter	free_buffer_data = alc;
12425839Speter	alc->text = space;
12525839Speter    }
12625839Speter}
12725839Speter
12825839Speter/* Get a new buffer_data structure.  */
12925839Speter
13025839Speterstatic struct buffer_data *
13125839Speterget_buffer_data ()
13225839Speter{
13325839Speter    struct buffer_data *ret;
13425839Speter
13525839Speter    if (free_buffer_data == NULL)
13625839Speter    {
13725839Speter	allocate_buffer_datas ();
13825839Speter	if (free_buffer_data == NULL)
13925839Speter	    return NULL;
14025839Speter    }
14125839Speter
14225839Speter    ret = free_buffer_data;
14325839Speter    free_buffer_data = ret->next;
14425839Speter    return ret;
14525839Speter}
14625839Speter
14725839Speter
148128269Speter
149128269Speter/* See whether a buffer and its file descriptor is empty.  */
15025839Speterint
151128269Speterbuf_empty (buf)
152128269Speter    struct buffer *buf;
153128269Speter{
154128269Speter	/* Try and read any data on the file descriptor first.
155128269Speter	 * We already know the descriptor is non-blocking.
156128269Speter	 */
157128269Speter	buf_input_data (buf, NULL);
158128269Speter	return buf_empty_p (buf);
159128269Speter}
160128269Speter
161128269Speter
162128269Speter
163128269Speter/* See whether a buffer is empty.  */
164128269Speterint
16525839Speterbuf_empty_p (buf)
16625839Speter    struct buffer *buf;
16725839Speter{
16825839Speter    struct buffer_data *data;
16925839Speter
17025839Speter    for (data = buf->data; data != NULL; data = data->next)
17125839Speter	if (data->size > 0)
17225839Speter	    return 0;
17325839Speter    return 1;
17425839Speter}
17525839Speter
176128269Speter
177128269Speter
17825839Speter#ifdef SERVER_FLOWCONTROL
17925839Speter/*
18025839Speter * Count how much data is stored in the buffer..
181109660Speter * Note that each buffer is a xmalloc'ed chunk BUFFER_DATA_SIZE.
18225839Speter */
18325839Speter
18425839Speterint
18525839Speterbuf_count_mem (buf)
18625839Speter    struct buffer *buf;
18725839Speter{
18825839Speter    struct buffer_data *data;
18925839Speter    int mem = 0;
19025839Speter
19125839Speter    for (data = buf->data; data != NULL; data = data->next)
19225839Speter	mem += BUFFER_DATA_SIZE;
19325839Speter
19425839Speter    return mem;
19525839Speter}
19625839Speter#endif /* SERVER_FLOWCONTROL */
19725839Speter
19825839Speter/* Add data DATA of length LEN to BUF.  */
19925839Speter
20025839Spetervoid
20125839Speterbuf_output (buf, data, len)
20225839Speter    struct buffer *buf;
20325839Speter    const char *data;
20425839Speter    int len;
20525839Speter{
20625839Speter    if (buf->data != NULL
20725839Speter	&& (((buf->last->text + BUFFER_DATA_SIZE)
20825839Speter	     - (buf->last->bufp + buf->last->size))
20925839Speter	    >= len))
21025839Speter    {
21125839Speter	memcpy (buf->last->bufp + buf->last->size, data, len);
21225839Speter	buf->last->size += len;
21325839Speter	return;
21425839Speter    }
21525839Speter
21625839Speter    while (1)
21725839Speter    {
21825839Speter	struct buffer_data *newdata;
21925839Speter
22025839Speter	newdata = get_buffer_data ();
22125839Speter	if (newdata == NULL)
22225839Speter	{
22325839Speter	    (*buf->memory_error) (buf);
22425839Speter	    return;
22525839Speter	}
22625839Speter
22725839Speter	if (buf->data == NULL)
22825839Speter	    buf->data = newdata;
22925839Speter	else
23025839Speter	    buf->last->next = newdata;
23125839Speter	newdata->next = NULL;
23225839Speter	buf->last = newdata;
23325839Speter
23425839Speter	newdata->bufp = newdata->text;
23525839Speter
23625839Speter	if (len <= BUFFER_DATA_SIZE)
23725839Speter	{
23825839Speter	    newdata->size = len;
23925839Speter	    memcpy (newdata->text, data, len);
24025839Speter	    return;
24125839Speter	}
24225839Speter
24325839Speter	newdata->size = BUFFER_DATA_SIZE;
24425839Speter	memcpy (newdata->text, data, BUFFER_DATA_SIZE);
24525839Speter
24625839Speter	data += BUFFER_DATA_SIZE;
24725839Speter	len -= BUFFER_DATA_SIZE;
24825839Speter    }
24925839Speter
25025839Speter    /*NOTREACHED*/
25125839Speter}
25225839Speter
25325839Speter/* Add a '\0' terminated string to BUF.  */
25425839Speter
25525839Spetervoid
25625839Speterbuf_output0 (buf, string)
25725839Speter    struct buffer *buf;
25825839Speter    const char *string;
25925839Speter{
26025839Speter    buf_output (buf, string, strlen (string));
26125839Speter}
26225839Speter
26325839Speter/* Add a single character to BUF.  */
26425839Speter
26525839Spetervoid
26625839Speterbuf_append_char (buf, ch)
26725839Speter    struct buffer *buf;
26825839Speter    int ch;
26925839Speter{
27025839Speter    if (buf->data != NULL
27125839Speter	&& (buf->last->text + BUFFER_DATA_SIZE
27225839Speter	    != buf->last->bufp + buf->last->size))
27325839Speter    {
27425839Speter	*(buf->last->bufp + buf->last->size) = ch;
27525839Speter	++buf->last->size;
27625839Speter    }
27725839Speter    else
27825839Speter    {
27925839Speter	char b;
28025839Speter
28125839Speter	b = ch;
28225839Speter	buf_output (buf, &b, 1);
28325839Speter    }
28425839Speter}
28525839Speter
28625839Speter/*
28725839Speter * Send all the output we've been saving up.  Returns 0 for success or
28825839Speter * errno code.  If the buffer has been set to be nonblocking, this
28925839Speter * will just write until the write would block.
29025839Speter */
29125839Speter
29225839Speterint
29325839Speterbuf_send_output (buf)
29425839Speter     struct buffer *buf;
29525839Speter{
29625839Speter    if (buf->output == NULL)
29725839Speter	abort ();
29825839Speter
29925839Speter    while (buf->data != NULL)
30025839Speter    {
30125839Speter	struct buffer_data *data;
30225839Speter
30325839Speter	data = buf->data;
30425839Speter
30525839Speter	if (data->size > 0)
30625839Speter	{
30725839Speter	    int status, nbytes;
30825839Speter
30925839Speter	    status = (*buf->output) (buf->closure, data->bufp, data->size,
31025839Speter				     &nbytes);
31125839Speter	    if (status != 0)
31225839Speter	    {
31325839Speter		/* Some sort of error.  Discard the data, and return.  */
31425839Speter
31525839Speter		buf->last->next = free_buffer_data;
31625839Speter		free_buffer_data = buf->data;
31725839Speter		buf->data = NULL;
31825839Speter		buf->last = NULL;
31925839Speter
32025839Speter	        return status;
32125839Speter	    }
32225839Speter
32325839Speter	    if (nbytes != data->size)
32425839Speter	    {
32525839Speter		/* Not all the data was written out.  This is only
32625839Speter                   permitted in nonblocking mode.  Adjust the buffer,
32725839Speter                   and return.  */
32825839Speter
32925839Speter		assert (buf->nonblocking);
33025839Speter
33125839Speter		data->size -= nbytes;
33225839Speter		data->bufp += nbytes;
33325839Speter
33425839Speter		return 0;
33525839Speter	    }
33625839Speter	}
33725839Speter
33825839Speter	buf->data = data->next;
33925839Speter	data->next = free_buffer_data;
34025839Speter	free_buffer_data = data;
34125839Speter    }
34225839Speter
34325839Speter    buf->last = NULL;
34425839Speter
34525839Speter    return 0;
34625839Speter}
34725839Speter
34825839Speter/*
34925839Speter * Flush any data queued up in the buffer.  If BLOCK is nonzero, then
35025839Speter * if the buffer is in nonblocking mode, put it into blocking mode for
35125839Speter * the duration of the flush.  This returns 0 on success, or an error
35225839Speter * code.
35325839Speter */
35425839Speter
35525839Speterint
35625839Speterbuf_flush (buf, block)
35725839Speter     struct buffer *buf;
35825839Speter     int block;
35925839Speter{
36025839Speter    int nonblocking;
36125839Speter    int status;
36225839Speter
36325839Speter    if (buf->flush == NULL)
36425839Speter        abort ();
36525839Speter
36625839Speter    nonblocking = buf->nonblocking;
36725839Speter    if (nonblocking && block)
36825839Speter    {
36925839Speter        status = set_block (buf);
37025839Speter	if (status != 0)
37125839Speter	    return status;
37225839Speter    }
37325839Speter
37425839Speter    status = buf_send_output (buf);
37525839Speter    if (status == 0)
37625839Speter        status = (*buf->flush) (buf->closure);
37725839Speter
37825839Speter    if (nonblocking && block)
37925839Speter    {
38025839Speter        int blockstat;
38125839Speter
38225839Speter        blockstat = set_nonblock (buf);
38325839Speter	if (status == 0)
38425839Speter	    status = blockstat;
38525839Speter    }
38625839Speter
38725839Speter    return status;
38825839Speter}
38925839Speter
39025839Speter/*
39125839Speter * Set buffer BUF to nonblocking I/O.  Returns 0 for success or errno
39225839Speter * code.
39325839Speter */
39425839Speter
39525839Speterint
39625839Speterset_nonblock (buf)
39725839Speter     struct buffer *buf;
39825839Speter{
39925839Speter    int status;
40025839Speter
40125839Speter    if (buf->nonblocking)
40225839Speter	return 0;
40325839Speter    if (buf->block == NULL)
40425839Speter        abort ();
40525839Speter    status = (*buf->block) (buf->closure, 0);
40625839Speter    if (status != 0)
40725839Speter	return status;
40825839Speter    buf->nonblocking = 1;
40925839Speter    return 0;
41025839Speter}
41125839Speter
41225839Speter/*
41325839Speter * Set buffer BUF to blocking I/O.  Returns 0 for success or errno
41425839Speter * code.
41525839Speter */
41625839Speter
41725839Speterint
41825839Speterset_block (buf)
41925839Speter     struct buffer *buf;
42025839Speter{
42125839Speter    int status;
42225839Speter
42325839Speter    if (! buf->nonblocking)
42425839Speter	return 0;
42525839Speter    if (buf->block == NULL)
42625839Speter        abort ();
42725839Speter    status = (*buf->block) (buf->closure, 1);
42825839Speter    if (status != 0)
42925839Speter	return status;
43025839Speter    buf->nonblocking = 0;
43125839Speter    return 0;
43225839Speter}
43325839Speter
43425839Speter/*
43525839Speter * Send a character count and some output.  Returns errno code or 0 for
43625839Speter * success.
43725839Speter *
43825839Speter * Sending the count in binary is OK since this is only used on a pipe
43925839Speter * within the same system.
44025839Speter */
44125839Speter
44225839Speterint
44325839Speterbuf_send_counted (buf)
44425839Speter     struct buffer *buf;
44525839Speter{
44625839Speter    int size;
44725839Speter    struct buffer_data *data;
44825839Speter
44925839Speter    size = 0;
45025839Speter    for (data = buf->data; data != NULL; data = data->next)
45125839Speter	size += data->size;
45225839Speter
45325839Speter    data = get_buffer_data ();
45425839Speter    if (data == NULL)
45525839Speter    {
45625839Speter	(*buf->memory_error) (buf);
45725839Speter	return ENOMEM;
45825839Speter    }
45925839Speter
46025839Speter    data->next = buf->data;
46125839Speter    buf->data = data;
46225839Speter    if (buf->last == NULL)
46325839Speter	buf->last = data;
46425839Speter
46525839Speter    data->bufp = data->text;
46625839Speter    data->size = sizeof (int);
46725839Speter
46825839Speter    *((int *) data->text) = size;
46925839Speter
47025839Speter    return buf_send_output (buf);
47125839Speter}
47225839Speter
47325839Speter/*
47425839Speter * Send a special count.  COUNT should be negative.  It will be
47525839Speter * handled speciallyi by buf_copy_counted.  This function returns 0 or
47625839Speter * an errno code.
47725839Speter *
47825839Speter * Sending the count in binary is OK since this is only used on a pipe
47925839Speter * within the same system.
48025839Speter */
48125839Speter
48225839Speterint
48325839Speterbuf_send_special_count (buf, count)
48425839Speter     struct buffer *buf;
48525839Speter     int count;
48625839Speter{
48725839Speter    struct buffer_data *data;
48825839Speter
48925839Speter    data = get_buffer_data ();
49025839Speter    if (data == NULL)
49125839Speter    {
49225839Speter	(*buf->memory_error) (buf);
49325839Speter	return ENOMEM;
49425839Speter    }
49525839Speter
49625839Speter    data->next = buf->data;
49725839Speter    buf->data = data;
49825839Speter    if (buf->last == NULL)
49925839Speter	buf->last = data;
50025839Speter
50125839Speter    data->bufp = data->text;
50225839Speter    data->size = sizeof (int);
50325839Speter
50425839Speter    *((int *) data->text) = count;
50525839Speter
50625839Speter    return buf_send_output (buf);
50725839Speter}
50825839Speter
50925839Speter/* Append a list of buffer_data structures to an buffer.  */
51025839Speter
51125839Spetervoid
51225839Speterbuf_append_data (buf, data, last)
51325839Speter     struct buffer *buf;
51425839Speter     struct buffer_data *data;
51525839Speter     struct buffer_data *last;
51625839Speter{
51725839Speter    if (data != NULL)
51825839Speter    {
51925839Speter	if (buf->data == NULL)
52025839Speter	    buf->data = data;
52125839Speter	else
52225839Speter	    buf->last->next = data;
52325839Speter	buf->last = last;
52425839Speter    }
52525839Speter}
52625839Speter
52734461Speter/* Append the data on one buffer to another.  This removes the data
52834461Speter   from the source buffer.  */
52934461Speter
53034461Spetervoid
53134461Speterbuf_append_buffer (to, from)
53234461Speter     struct buffer *to;
53334461Speter     struct buffer *from;
53434461Speter{
53534461Speter    buf_append_data (to, from->data, from->last);
53634461Speter    from->data = NULL;
53734461Speter    from->last = NULL;
53834461Speter}
53934461Speter
54025839Speter/*
54125839Speter * Copy the contents of file F into buffer_data structures.  We can't
54225839Speter * copy directly into an buffer, because we want to handle failure and
54325839Speter * succeess differently.  Returns 0 on success, or -2 if out of
54425839Speter * memory, or a status code on error.  Since the caller happens to
54525839Speter * know the size of the file, it is passed in as SIZE.  On success,
54625839Speter * this function sets *RETP and *LASTP, which may be passed to
54725839Speter * buf_append_data.
54825839Speter */
54925839Speter
55025839Speterint
55125839Speterbuf_read_file (f, size, retp, lastp)
55225839Speter    FILE *f;
55325839Speter    long size;
55425839Speter    struct buffer_data **retp;
55525839Speter    struct buffer_data **lastp;
55625839Speter{
55725839Speter    int status;
55825839Speter
55925839Speter    *retp = NULL;
56025839Speter    *lastp = NULL;
56125839Speter
56225839Speter    while (size > 0)
56325839Speter    {
56425839Speter	struct buffer_data *data;
56525839Speter	int get;
56625839Speter
56725839Speter	data = get_buffer_data ();
56825839Speter	if (data == NULL)
56925839Speter	{
57025839Speter	    status = -2;
57125839Speter	    goto error_return;
57225839Speter	}
57325839Speter
57425839Speter	if (*retp == NULL)
57525839Speter	    *retp = data;
57625839Speter	else
57725839Speter	    (*lastp)->next = data;
57825839Speter	data->next = NULL;
57925839Speter	*lastp = data;
58025839Speter
58125839Speter	data->bufp = data->text;
58225839Speter	data->size = 0;
58325839Speter
58425839Speter	if (size > BUFFER_DATA_SIZE)
58525839Speter	    get = BUFFER_DATA_SIZE;
58625839Speter	else
58725839Speter	    get = size;
58825839Speter
58925839Speter	errno = EIO;
59025839Speter	if (fread (data->text, get, 1, f) != 1)
59125839Speter	{
59225839Speter	    status = errno;
59325839Speter	    goto error_return;
59425839Speter	}
59525839Speter
59625839Speter	data->size += get;
59725839Speter	size -= get;
59825839Speter    }
59925839Speter
60025839Speter    return 0;
60125839Speter
60225839Speter  error_return:
60325839Speter    if (*retp != NULL)
60425839Speter    {
60525839Speter	(*lastp)->next = free_buffer_data;
60625839Speter	free_buffer_data = *retp;
60725839Speter    }
60825839Speter    return status;
60925839Speter}
61025839Speter
61125839Speter/*
61225839Speter * Copy the contents of file F into buffer_data structures.  We can't
61325839Speter * copy directly into an buffer, because we want to handle failure and
61425839Speter * succeess differently.  Returns 0 on success, or -2 if out of
61525839Speter * memory, or a status code on error.  On success, this function sets
61625839Speter * *RETP and *LASTP, which may be passed to buf_append_data.
61725839Speter */
61825839Speter
61925839Speterint
62025839Speterbuf_read_file_to_eof (f, retp, lastp)
62125839Speter     FILE *f;
62225839Speter     struct buffer_data **retp;
62325839Speter     struct buffer_data **lastp;
62425839Speter{
62525839Speter    int status;
62625839Speter
62725839Speter    *retp = NULL;
62825839Speter    *lastp = NULL;
62925839Speter
63025839Speter    while (!feof (f))
63125839Speter    {
63225839Speter	struct buffer_data *data;
63325839Speter	int get, nread;
63425839Speter
63525839Speter	data = get_buffer_data ();
63625839Speter	if (data == NULL)
63725839Speter	{
63825839Speter	    status = -2;
63925839Speter	    goto error_return;
64025839Speter	}
64125839Speter
64225839Speter	if (*retp == NULL)
64325839Speter	    *retp = data;
64425839Speter	else
64525839Speter	    (*lastp)->next = data;
64625839Speter	data->next = NULL;
64725839Speter	*lastp = data;
64825839Speter
64925839Speter	data->bufp = data->text;
65025839Speter	data->size = 0;
65125839Speter
65225839Speter	get = BUFFER_DATA_SIZE;
65325839Speter
65425839Speter	errno = EIO;
65525839Speter	nread = fread (data->text, 1, get, f);
65625839Speter	if (nread == 0 && !feof (f))
65725839Speter	{
65825839Speter	    status = errno;
65925839Speter	    goto error_return;
66025839Speter	}
66125839Speter
66225839Speter	data->size = nread;
66325839Speter    }
66425839Speter
66525839Speter    return 0;
66625839Speter
66725839Speter  error_return:
66825839Speter    if (*retp != NULL)
66925839Speter    {
67025839Speter	(*lastp)->next = free_buffer_data;
67125839Speter	free_buffer_data = *retp;
67225839Speter    }
67325839Speter    return status;
67425839Speter}
67525839Speter
67625839Speter/* Return the number of bytes in a chain of buffer_data structures.  */
67725839Speter
67825839Speterint
67925839Speterbuf_chain_length (buf)
68025839Speter     struct buffer_data *buf;
68125839Speter{
68225839Speter    int size = 0;
68325839Speter    while (buf)
68425839Speter    {
68525839Speter	size += buf->size;
68625839Speter	buf = buf->next;
68725839Speter    }
68825839Speter    return size;
68925839Speter}
69025839Speter
69134461Speter/* Return the number of bytes in a buffer.  */
69234461Speter
69334461Speterint
69434461Speterbuf_length (buf)
69534461Speter    struct buffer *buf;
69634461Speter{
69734461Speter    return buf_chain_length (buf->data);
69834461Speter}
69934461Speter
70025839Speter/*
70125839Speter * Read an arbitrary amount of data into an input buffer.  The buffer
70225839Speter * will be in nonblocking mode, and we just grab what we can.  Return
70325839Speter * 0 on success, or -1 on end of file, or -2 if out of memory, or an
70425839Speter * error code.  If COUNTP is not NULL, *COUNTP is set to the number of
70525839Speter * bytes read.
70625839Speter */
70725839Speter
70825839Speterint
70925839Speterbuf_input_data (buf, countp)
71025839Speter     struct buffer *buf;
71125839Speter     int *countp;
71225839Speter{
71325839Speter    if (buf->input == NULL)
71425839Speter	abort ();
71525839Speter
71625839Speter    if (countp != NULL)
71725839Speter	*countp = 0;
71825839Speter
71925839Speter    while (1)
72025839Speter    {
72125839Speter	int get;
72225839Speter	int status, nbytes;
72325839Speter
72425839Speter	if (buf->data == NULL
72525839Speter	    || (buf->last->bufp + buf->last->size
72625839Speter		== buf->last->text + BUFFER_DATA_SIZE))
72725839Speter	{
72825839Speter	    struct buffer_data *data;
72925839Speter
73025839Speter	    data = get_buffer_data ();
73125839Speter	    if (data == NULL)
73225839Speter	    {
73325839Speter		(*buf->memory_error) (buf);
73425839Speter		return -2;
73525839Speter	    }
73625839Speter
73725839Speter	    if (buf->data == NULL)
73825839Speter		buf->data = data;
73925839Speter	    else
74025839Speter		buf->last->next = data;
74125839Speter	    data->next = NULL;
74225839Speter	    buf->last = data;
74325839Speter
74425839Speter	    data->bufp = data->text;
74525839Speter	    data->size = 0;
74625839Speter	}
74725839Speter
74825839Speter	get = ((buf->last->text + BUFFER_DATA_SIZE)
74925839Speter	       - (buf->last->bufp + buf->last->size));
75025839Speter
75125839Speter	status = (*buf->input) (buf->closure,
75225839Speter				buf->last->bufp + buf->last->size,
75325839Speter				0, get, &nbytes);
75425839Speter	if (status != 0)
75525839Speter	    return status;
75625839Speter
75725839Speter	buf->last->size += nbytes;
75825839Speter	if (countp != NULL)
75925839Speter	    *countp += nbytes;
76025839Speter
76125839Speter	if (nbytes < get)
76225839Speter	{
76325839Speter	    /* If we did not fill the buffer, then presumably we read
76425839Speter               all the available data.  */
76525839Speter	    return 0;
76625839Speter	}
76725839Speter    }
76825839Speter
76925839Speter    /*NOTREACHED*/
77025839Speter}
77125839Speter
77225839Speter/*
77325839Speter * Read a line (characters up to a \012) from an input buffer.  (We
77425839Speter * use \012 rather than \n for the benefit of non Unix clients for
77525839Speter * which \n means something else).  This returns 0 on success, or -1
77625839Speter * on end of file, or -2 if out of memory, or an error code.  If it
77725839Speter * succeeds, it sets *LINE to an allocated buffer holding the contents
77825839Speter * of the line.  The trailing \012 is not included in the buffer.  If
77925839Speter * LENP is not NULL, then *LENP is set to the number of bytes read;
78025839Speter * strlen may not work, because there may be embedded null bytes.
78125839Speter */
78225839Speter
78325839Speterint
78425839Speterbuf_read_line (buf, line, lenp)
78525839Speter     struct buffer *buf;
78625839Speter     char **line;
78725839Speter     int *lenp;
78825839Speter{
78925839Speter    if (buf->input == NULL)
79025839Speter        abort ();
79125839Speter
79225839Speter    *line = NULL;
79325839Speter
79425839Speter    while (1)
79525839Speter    {
79625839Speter	int len, finallen = 0;
79725839Speter	struct buffer_data *data;
79825839Speter	char *nl;
79925839Speter
80025839Speter	/* See if there is a newline in BUF.  */
80125839Speter	len = 0;
80225839Speter	for (data = buf->data; data != NULL; data = data->next)
80325839Speter	{
80425839Speter	    nl = memchr (data->bufp, '\012', data->size);
80525839Speter	    if (nl != NULL)
80625839Speter	    {
80725839Speter	        finallen = nl - data->bufp;
80825839Speter	        len += finallen;
80925839Speter		break;
81025839Speter	    }
81125839Speter	    len += data->size;
81225839Speter	}
81325839Speter
81425839Speter	/* If we found a newline, copy the line into a memory buffer,
81525839Speter           and remove it from BUF.  */
81625839Speter	if (data != NULL)
81725839Speter	{
81825839Speter	    char *p;
81925839Speter	    struct buffer_data *nldata;
82025839Speter
821109660Speter	    p = xmalloc (len + 1);
82225839Speter	    if (p == NULL)
82325839Speter		return -2;
82425839Speter	    *line = p;
82525839Speter
82625839Speter	    nldata = data;
82725839Speter	    data = buf->data;
82825839Speter	    while (data != nldata)
82925839Speter	    {
83025839Speter		struct buffer_data *next;
83125839Speter
83225839Speter		memcpy (p, data->bufp, data->size);
83325839Speter		p += data->size;
83425839Speter		next = data->next;
83525839Speter		data->next = free_buffer_data;
83625839Speter		free_buffer_data = data;
83725839Speter		data = next;
83825839Speter	    }
83925839Speter
84025839Speter	    memcpy (p, data->bufp, finallen);
84125839Speter	    p[finallen] = '\0';
84225839Speter
84325839Speter	    data->size -= finallen + 1;
84425839Speter	    data->bufp = nl + 1;
84525839Speter	    buf->data = data;
84625839Speter
84725839Speter	    if (lenp != NULL)
84825839Speter	        *lenp = len;
84925839Speter
85025839Speter	    return 0;
85125839Speter	}
85225839Speter
85325839Speter	/* Read more data until we get a newline.  */
85425839Speter	while (1)
85525839Speter	{
85625839Speter	    int size, status, nbytes;
85725839Speter	    char *mem;
85825839Speter
85925839Speter	    if (buf->data == NULL
86025839Speter		|| (buf->last->bufp + buf->last->size
86125839Speter		    == buf->last->text + BUFFER_DATA_SIZE))
86225839Speter	    {
86325839Speter		data = get_buffer_data ();
86425839Speter		if (data == NULL)
86525839Speter		{
86625839Speter		    (*buf->memory_error) (buf);
86725839Speter		    return -2;
86825839Speter		}
86925839Speter
87025839Speter		if (buf->data == NULL)
87125839Speter		    buf->data = data;
87225839Speter		else
87325839Speter		    buf->last->next = data;
87425839Speter		data->next = NULL;
87525839Speter		buf->last = data;
87625839Speter
87725839Speter		data->bufp = data->text;
87825839Speter		data->size = 0;
87925839Speter	    }
88025839Speter
88125839Speter	    mem = buf->last->bufp + buf->last->size;
88225839Speter	    size = (buf->last->text + BUFFER_DATA_SIZE) - mem;
88325839Speter
88425839Speter	    /* We need to read at least 1 byte.  We can handle up to
88525839Speter               SIZE bytes.  This will only be efficient if the
88625839Speter               underlying communication stream does its own buffering,
88725839Speter               or is clever about getting more than 1 byte at a time.  */
88825839Speter	    status = (*buf->input) (buf->closure, mem, 1, size, &nbytes);
88925839Speter	    if (status != 0)
89025839Speter		return status;
89125839Speter
89225839Speter	    buf->last->size += nbytes;
89325839Speter
89425839Speter	    /* Optimize slightly to avoid an unnecessary call to
89525839Speter               memchr.  */
89625839Speter	    if (nbytes == 1)
89725839Speter	    {
89825839Speter		if (*mem == '\012')
89925839Speter		    break;
90025839Speter	    }
90125839Speter	    else
90225839Speter	    {
90325839Speter		if (memchr (mem, '\012', nbytes) != NULL)
90425839Speter		    break;
90525839Speter	    }
90625839Speter	}
90725839Speter    }
90825839Speter}
90925839Speter
91025839Speter/*
91125839Speter * Extract data from the input buffer BUF.  This will read up to WANT
91225839Speter * bytes from the buffer.  It will set *RETDATA to point at the bytes,
91325839Speter * and set *GOT to the number of bytes to be found there.  Any buffer
91425839Speter * call which uses BUF may change the contents of the buffer at *DATA,
91525839Speter * so the data should be fully processed before any further calls are
91625839Speter * made.  This returns 0 on success, or -1 on end of file, or -2 if
91725839Speter * out of memory, or an error code.
91825839Speter */
91925839Speter
92025839Speterint
92125839Speterbuf_read_data (buf, want, retdata, got)
92225839Speter     struct buffer *buf;
92325839Speter     int want;
92425839Speter     char **retdata;
92525839Speter     int *got;
92625839Speter{
92725839Speter    if (buf->input == NULL)
92825839Speter	abort ();
92925839Speter
93025839Speter    while (buf->data != NULL && buf->data->size == 0)
93125839Speter    {
93225839Speter	struct buffer_data *next;
93325839Speter
93425839Speter	next = buf->data->next;
93525839Speter	buf->data->next = free_buffer_data;
93625839Speter	free_buffer_data = buf->data;
93725839Speter	buf->data = next;
93825839Speter	if (next == NULL)
93925839Speter	    buf->last = NULL;
94025839Speter    }
94125839Speter
94225839Speter    if (buf->data == NULL)
94325839Speter    {
94425839Speter	struct buffer_data *data;
94525839Speter	int get, status, nbytes;
94625839Speter
94725839Speter	data = get_buffer_data ();
94825839Speter	if (data == NULL)
94925839Speter	{
95025839Speter	    (*buf->memory_error) (buf);
95125839Speter	    return -2;
95225839Speter	}
95325839Speter
95425839Speter	buf->data = data;
95525839Speter	buf->last = data;
95625839Speter	data->next = NULL;
95725839Speter	data->bufp = data->text;
95825839Speter	data->size = 0;
95925839Speter
96025839Speter	if (want < BUFFER_DATA_SIZE)
96125839Speter	    get = want;
96225839Speter	else
96325839Speter	    get = BUFFER_DATA_SIZE;
96425839Speter	status = (*buf->input) (buf->closure, data->bufp, get,
96525839Speter				BUFFER_DATA_SIZE, &nbytes);
96625839Speter	if (status != 0)
96725839Speter	    return status;
96825839Speter
96925839Speter	data->size = nbytes;
97025839Speter    }
97125839Speter
97225839Speter    *retdata = buf->data->bufp;
97325839Speter    if (want < buf->data->size)
97425839Speter    {
97525839Speter        *got = want;
97625839Speter	buf->data->size -= want;
97725839Speter	buf->data->bufp += want;
97825839Speter    }
97925839Speter    else
98025839Speter    {
98125839Speter        *got = buf->data->size;
98225839Speter	buf->data->size = 0;
98325839Speter    }
98425839Speter
98525839Speter    return 0;
98625839Speter}
98725839Speter
98825839Speter/*
98925839Speter * Copy lines from an input buffer to an output buffer.  This copies
99025839Speter * all complete lines (characters up to a newline) from INBUF to
99125839Speter * OUTBUF.  Each line in OUTBUF is preceded by the character COMMAND
99225839Speter * and a space.
99325839Speter */
99425839Speter
99525839Spetervoid
99625839Speterbuf_copy_lines (outbuf, inbuf, command)
99725839Speter     struct buffer *outbuf;
99825839Speter     struct buffer *inbuf;
99925839Speter     int command;
100025839Speter{
100125839Speter    while (1)
100225839Speter    {
100325839Speter	struct buffer_data *data;
100425839Speter	struct buffer_data *nldata;
100525839Speter	char *nl;
100625839Speter	int len;
100725839Speter
100825839Speter	/* See if there is a newline in INBUF.  */
100925839Speter	nldata = NULL;
101025839Speter	nl = NULL;
101125839Speter	for (data = inbuf->data; data != NULL; data = data->next)
101225839Speter	{
101325839Speter	    nl = memchr (data->bufp, '\n', data->size);
101425839Speter	    if (nl != NULL)
101525839Speter	    {
101625839Speter		nldata = data;
101725839Speter		break;
101825839Speter	    }
101925839Speter	}
102025839Speter
102125839Speter	if (nldata == NULL)
102225839Speter	{
102325839Speter	    /* There are no more lines in INBUF.  */
102425839Speter	    return;
102525839Speter	}
102625839Speter
102725839Speter	/* Put in the command.  */
102825839Speter	buf_append_char (outbuf, command);
102925839Speter	buf_append_char (outbuf, ' ');
103025839Speter
103125839Speter	if (inbuf->data != nldata)
103225839Speter	{
103325839Speter	    /*
103425839Speter	     * Simply move over all the buffers up to the one containing
103525839Speter	     * the newline.
103625839Speter	     */
103725839Speter	    for (data = inbuf->data; data->next != nldata; data = data->next)
103825839Speter		;
103925839Speter	    data->next = NULL;
104025839Speter	    buf_append_data (outbuf, inbuf->data, data);
104125839Speter	    inbuf->data = nldata;
104225839Speter	}
104325839Speter
104425839Speter	/*
104525839Speter	 * If the newline is at the very end of the buffer, just move
104625839Speter	 * the buffer onto OUTBUF.  Otherwise we must copy the data.
104725839Speter	 */
104825839Speter	len = nl + 1 - nldata->bufp;
104925839Speter	if (len == nldata->size)
105025839Speter	{
105125839Speter	    inbuf->data = nldata->next;
105225839Speter	    if (inbuf->data == NULL)
105325839Speter		inbuf->last = NULL;
105425839Speter
105525839Speter	    nldata->next = NULL;
105625839Speter	    buf_append_data (outbuf, nldata, nldata);
105725839Speter	}
105825839Speter	else
105925839Speter	{
106025839Speter	    buf_output (outbuf, nldata->bufp, len);
106125839Speter	    nldata->bufp += len;
106225839Speter	    nldata->size -= len;
106325839Speter	}
106425839Speter    }
106525839Speter}
106625839Speter
106725839Speter/*
106825839Speter * Copy counted data from one buffer to another.  The count is an
106925839Speter * integer, host size, host byte order (it is only used across a
107025839Speter * pipe).  If there is enough data, it should be moved over.  If there
107125839Speter * is not enough data, it should remain on the original buffer.  A
107225839Speter * negative count is a special case.  if one is seen, *SPECIAL is set
107325839Speter * to the (negative) count value and no additional data is gathered
107425839Speter * from the buffer; normally *SPECIAL is set to 0.  This function
107525839Speter * returns the number of bytes it needs to see in order to actually
107625839Speter * copy something over.
107725839Speter */
107825839Speter
107925839Speterint
108025839Speterbuf_copy_counted (outbuf, inbuf, special)
108125839Speter     struct buffer *outbuf;
108225839Speter     struct buffer *inbuf;
108325839Speter     int *special;
108425839Speter{
108525839Speter    *special = 0;
108625839Speter
108725839Speter    while (1)
108825839Speter    {
108925839Speter	struct buffer_data *data;
109025839Speter	int need;
109125839Speter	union
109225839Speter	{
109325839Speter	    char intbuf[sizeof (int)];
109425839Speter	    int i;
109525839Speter	} u;
109625839Speter	char *intp;
109725839Speter	int count;
109825839Speter	struct buffer_data *start;
109925839Speter	int startoff;
110025839Speter	struct buffer_data *stop;
110125839Speter	int stopwant;
110225839Speter
110325839Speter	/* See if we have enough bytes to figure out the count.  */
110425839Speter	need = sizeof (int);
110525839Speter	intp = u.intbuf;
110625839Speter	for (data = inbuf->data; data != NULL; data = data->next)
110725839Speter	{
110825839Speter	    if (data->size >= need)
110925839Speter	    {
111025839Speter		memcpy (intp, data->bufp, need);
111125839Speter		break;
111225839Speter	    }
111325839Speter	    memcpy (intp, data->bufp, data->size);
111425839Speter	    intp += data->size;
111525839Speter	    need -= data->size;
111625839Speter	}
111725839Speter	if (data == NULL)
111825839Speter	{
111925839Speter	    /* We don't have enough bytes to form an integer.  */
112025839Speter	    return need;
112125839Speter	}
112225839Speter
112325839Speter	count = u.i;
112425839Speter	start = data;
112525839Speter	startoff = need;
112625839Speter
112725839Speter	if (count < 0)
112825839Speter	{
112925839Speter	    /* A negative COUNT is a special case meaning that we
113025839Speter               don't need any further information.  */
113125839Speter	    stop = start;
113225839Speter	    stopwant = 0;
113325839Speter	}
113425839Speter	else
113525839Speter	{
113625839Speter	    /*
113725839Speter	     * We have an integer in COUNT.  We have gotten all the
113825839Speter	     * data from INBUF in all buffers before START, and we
113925839Speter	     * have gotten STARTOFF bytes from START.  See if we have
114025839Speter	     * enough bytes remaining in INBUF.
114125839Speter	     */
114225839Speter	    need = count - (start->size - startoff);
114325839Speter	    if (need <= 0)
114425839Speter	    {
114525839Speter		stop = start;
114625839Speter		stopwant = count;
114725839Speter	    }
114825839Speter	    else
114925839Speter	    {
115025839Speter		for (data = start->next; data != NULL; data = data->next)
115125839Speter		{
115225839Speter		    if (need <= data->size)
115325839Speter			break;
115425839Speter		    need -= data->size;
115525839Speter		}
115625839Speter		if (data == NULL)
115725839Speter		{
115825839Speter		    /* We don't have enough bytes.  */
115925839Speter		    return need;
116025839Speter		}
116125839Speter		stop = data;
116225839Speter		stopwant = need;
116325839Speter	    }
116425839Speter	}
116525839Speter
116625839Speter	/*
116725839Speter	 * We have enough bytes.  Free any buffers in INBUF before
116825839Speter	 * START, and remove STARTOFF bytes from START, so that we can
116925839Speter	 * forget about STARTOFF.
117025839Speter	 */
117125839Speter	start->bufp += startoff;
117225839Speter	start->size -= startoff;
117325839Speter
117425839Speter	if (start->size == 0)
117525839Speter	    start = start->next;
117625839Speter
117725839Speter	if (stop->size == stopwant)
117825839Speter	{
117925839Speter	    stop = stop->next;
118025839Speter	    stopwant = 0;
118125839Speter	}
118225839Speter
118325839Speter	while (inbuf->data != start)
118425839Speter	{
118525839Speter	    data = inbuf->data;
118625839Speter	    inbuf->data = data->next;
118725839Speter	    data->next = free_buffer_data;
118825839Speter	    free_buffer_data = data;
118925839Speter	}
119025839Speter
119125839Speter	/* If COUNT is negative, set *SPECIAL and get out now.  */
119225839Speter	if (count < 0)
119325839Speter	{
119425839Speter	    *special = count;
119525839Speter	    return 0;
119625839Speter	}
119725839Speter
119825839Speter	/*
119925839Speter	 * We want to copy over the bytes from START through STOP.  We
120025839Speter	 * only want STOPWANT bytes from STOP.
120125839Speter	 */
120225839Speter
120325839Speter	if (start != stop)
120425839Speter	{
120525839Speter	    /* Attach the buffers from START through STOP to OUTBUF.  */
120625839Speter	    for (data = start; data->next != stop; data = data->next)
120725839Speter		;
120825839Speter	    inbuf->data = stop;
120925839Speter	    data->next = NULL;
121025839Speter	    buf_append_data (outbuf, start, data);
121125839Speter	}
121225839Speter
121325839Speter	if (stopwant > 0)
121425839Speter	{
121525839Speter	    buf_output (outbuf, stop->bufp, stopwant);
121625839Speter	    stop->bufp += stopwant;
121725839Speter	    stop->size -= stopwant;
121825839Speter	}
121925839Speter    }
122025839Speter
122125839Speter    /*NOTREACHED*/
122225839Speter}
122325839Speter
122425839Speter/* Shut down a buffer.  This returns 0 on success, or an errno code.  */
122525839Speter
122625839Speterint
122725839Speterbuf_shutdown (buf)
122825839Speter     struct buffer *buf;
122925839Speter{
123025839Speter    if (buf->shutdown)
1231102840Speter	return (*buf->shutdown) (buf);
123225839Speter    return 0;
123325839Speter}
123425839Speter
1235128269Speter
1236128269Speter
123725839Speter/* The simplest type of buffer is one built on top of a stdio FILE.
123825839Speter   For simplicity, and because it is all that is required, we do not
123925839Speter   implement setting this type of buffer into nonblocking mode.  The
124025839Speter   closure field is just a FILE *.  */
124125839Speter
124225839Speterstatic int stdio_buffer_input PROTO((void *, char *, int, int, int *));
124325839Speterstatic int stdio_buffer_output PROTO((void *, const char *, int, int *));
124425839Speterstatic int stdio_buffer_flush PROTO((void *));
1245102840Speterstatic int stdio_buffer_shutdown PROTO((struct buffer *buf));
124625839Speter
1247128269Speter
1248128269Speter
124925839Speter/* Initialize a buffer built on a stdio FILE.  */
1250102840Speterstruct stdio_buffer_closure
1251102840Speter{
1252102840Speter    FILE *fp;
1253102840Speter    int child_pid;
1254102840Speter};
1255102840Speter
1256128269Speter
1257128269Speter
125832785Speterstruct buffer *
1259102840Speterstdio_buffer_initialize (fp, child_pid, input, memory)
126025839Speter     FILE *fp;
1261102840Speter     int child_pid;
126225839Speter     int input;
126325839Speter     void (*memory) PROTO((struct buffer *));
126425839Speter{
1265109660Speter    struct stdio_buffer_closure *bc = xmalloc (sizeof (*bc));
1266102840Speter
1267102840Speter    bc->fp = fp;
1268102840Speter    bc->child_pid = child_pid;
1269102840Speter
127025839Speter    return buf_initialize (input ? stdio_buffer_input : NULL,
127125839Speter			   input ? NULL : stdio_buffer_output,
127225839Speter			   input ? NULL : stdio_buffer_flush,
127325839Speter			   (int (*) PROTO((void *, int))) NULL,
1274102840Speter			   stdio_buffer_shutdown,
127525839Speter			   memory,
1276102840Speter			   (void *) bc);
127725839Speter}
127825839Speter
1279107487Speter/* Return the file associated with a stdio buffer. */
1280107487SpeterFILE *
1281107487Speterstdio_buffer_get_file (buf)
1282107487Speter    struct buffer *buf;
1283107487Speter{
1284107487Speter    struct stdio_buffer_closure *bc;
1285107487Speter
1286107487Speter    assert(buf->shutdown == stdio_buffer_shutdown);
1287107487Speter
1288107487Speter    bc = (struct stdio_buffer_closure *) buf->closure;
1289107487Speter
1290107487Speter    return(bc->fp);
1291107487Speter}
1292107487Speter
129325839Speter/* The buffer input function for a buffer built on a stdio FILE.  */
129425839Speter
129525839Speterstatic int
129625839Speterstdio_buffer_input (closure, data, need, size, got)
129725839Speter     void *closure;
129825839Speter     char *data;
129925839Speter     int need;
130025839Speter     int size;
130125839Speter     int *got;
130225839Speter{
1303102840Speter    struct stdio_buffer_closure *bc = (struct stdio_buffer_closure *) closure;
130425839Speter    int nbytes;
130525839Speter
130625839Speter    /* Since stdio does its own buffering, we don't worry about
130725839Speter       getting more bytes than we need.  */
130825839Speter
130925839Speter    if (need == 0 || need == 1)
131025839Speter    {
131125839Speter        int ch;
131225839Speter
1313102840Speter	ch = getc (bc->fp);
131425839Speter
131525839Speter	if (ch == EOF)
131625839Speter	{
1317102840Speter	    if (feof (bc->fp))
131825839Speter		return -1;
131925839Speter	    else if (errno == 0)
132025839Speter		return EIO;
132125839Speter	    else
132225839Speter		return errno;
132325839Speter	}
132425839Speter
132525839Speter	*data = ch;
132625839Speter	*got = 1;
132725839Speter	return 0;
132825839Speter    }
132925839Speter
1330102840Speter    nbytes = fread (data, 1, need, bc->fp);
133125839Speter
133225839Speter    if (nbytes == 0)
133325839Speter    {
133425839Speter	*got = 0;
1335102840Speter	if (feof (bc->fp))
133625839Speter	    return -1;
133725839Speter	else if (errno == 0)
133825839Speter	    return EIO;
133925839Speter	else
134025839Speter	    return errno;
134125839Speter    }
134225839Speter
134325839Speter    *got = nbytes;
134425839Speter
134525839Speter    return 0;
134625839Speter}
134725839Speter
134825839Speter/* The buffer output function for a buffer built on a stdio FILE.  */
134925839Speter
135025839Speterstatic int
135125839Speterstdio_buffer_output (closure, data, have, wrote)
135225839Speter     void *closure;
135325839Speter     const char *data;
135425839Speter     int have;
135525839Speter     int *wrote;
135625839Speter{
1357102840Speter    struct stdio_buffer_closure *bc = (struct stdio_buffer_closure *) closure;
135825839Speter
135925839Speter    *wrote = 0;
136025839Speter
136125839Speter    while (have > 0)
136225839Speter    {
136325839Speter	int nbytes;
136425839Speter
1365102840Speter	nbytes = fwrite (data, 1, have, bc->fp);
136625839Speter
136725839Speter	if (nbytes != have)
136825839Speter	{
136925839Speter	    if (errno == 0)
137025839Speter		return EIO;
137125839Speter	    else
137225839Speter		return errno;
137325839Speter	}
137425839Speter
137525839Speter	*wrote += nbytes;
137625839Speter	have -= nbytes;
137725839Speter	data += nbytes;
137825839Speter    }
137925839Speter
138025839Speter    return 0;
138125839Speter}
138225839Speter
1383128269Speter
1384128269Speter
138525839Speter/* The buffer flush function for a buffer built on a stdio FILE.  */
138625839Speterstatic int
138725839Speterstdio_buffer_flush (closure)
138825839Speter     void *closure;
138925839Speter{
1390102840Speter    struct stdio_buffer_closure *bc = (struct stdio_buffer_closure *) closure;
139125839Speter
1392102840Speter    if (fflush (bc->fp) != 0)
139325839Speter    {
139425839Speter	if (errno == 0)
139525839Speter	    return EIO;
139625839Speter	else
139725839Speter	    return errno;
139825839Speter    }
139925839Speter
140025839Speter    return 0;
140125839Speter}
140225839Speter
1403102840Speter
1404102840Speter
1405102840Speterstatic int
1406102840Speterstdio_buffer_shutdown (buf)
1407102840Speter    struct buffer *buf;
1408102840Speter{
1409128269Speter    struct stdio_buffer_closure *bc = buf->closure;
1410102840Speter    struct stat s;
1411102840Speter    int closefp = 1;
1412102840Speter
1413102840Speter    /* Must be a pipe or a socket.  What could go wrong? */
1414128269Speter    assert (fstat (fileno (bc->fp), &s) != -1);
1415102840Speter
1416102840Speter    /* Flush the buffer if we can */
1417102840Speter    if (buf->flush)
1418102840Speter    {
1419102840Speter	buf_flush (buf, 1);
1420102840Speter	buf->flush = NULL;
1421102840Speter    }
1422102840Speter
1423102840Speter    if (buf->input)
1424102840Speter    {
1425128269Speter	/* There used to be a check here for unread data in the buffer of on
1426128269Speter	 * the pipe, but it was deemed unnecessary and possibly dangerous.  In
1427128269Speter	 * some sense it could be second-guessing the caller who requested it
1428128269Speter	 * closed, as well.
1429128269Speter	 */
1430102840Speter
1431102840Speter# ifdef SHUTDOWN_SERVER
1432102840Speter	if (current_parsed_root->method != server_method)
1433102840Speter# endif
1434102840Speter# ifndef NO_SOCKET_TO_FD
1435102840Speter	{
1436102840Speter	    /* shutdown() sockets */
1437128269Speter	    if (S_ISSOCK (s.st_mode))
1438128269Speter		shutdown (fileno (bc->fp), 0);
1439102840Speter	}
1440102840Speter# endif /* NO_SOCKET_TO_FD */
1441102840Speter# ifdef START_RSH_WITH_POPEN_RW
1442102840Speter	/* Can't be set with SHUTDOWN_SERVER defined */
1443102840Speter	else if (pclose (bc->fp) == EOF)
1444102840Speter	{
1445102840Speter	    error (1, errno, "closing connection to %s",
1446102840Speter		   current_parsed_root->hostname);
1447102840Speter	    closefp = 0;
1448102840Speter	}
1449102840Speter# endif /* START_RSH_WITH_POPEN_RW */
1450102840Speter
1451102840Speter	buf->input = NULL;
1452102840Speter    }
1453102840Speter    else if (buf->output)
1454102840Speter    {
1455102840Speter# ifdef SHUTDOWN_SERVER
1456102840Speter	/* FIXME:  Should have a SHUTDOWN_SERVER_INPUT &
1457102840Speter	 * SHUTDOWN_SERVER_OUTPUT
1458102840Speter	 */
1459102840Speter	if (current_parsed_root->method == server_method)
1460128269Speter	    SHUTDOWN_SERVER (fileno (bc->fp));
1461102840Speter	else
1462102840Speter# endif
1463102840Speter# ifndef NO_SOCKET_TO_FD
1464102840Speter	/* shutdown() sockets */
1465128269Speter	if (S_ISSOCK (s.st_mode))
1466128269Speter	    shutdown (fileno (bc->fp), 1);
1467102840Speter# else
1468102840Speter	{
1469102840Speter	/* I'm not sure I like this empty block, but the alternative
1470102840Speter	 * is a another nested NO_SOCKET_TO_FD switch above.
1471102840Speter	 */
1472102840Speter	}
1473102840Speter# endif /* NO_SOCKET_TO_FD */
1474102840Speter
1475102840Speter	buf->output = NULL;
1476102840Speter    }
1477102840Speter
1478102840Speter    if (closefp && fclose (bc->fp) == EOF)
1479128269Speter    {
1480128269Speter	if (0
1481128269Speter# ifdef SERVER_SUPPORT
1482128269Speter	    || server_active
1483128269Speter# endif /* SERVER_SUPPORT */
1484128269Speter           )
1485128269Speter	{
1486128269Speter            /* Syslog this? */
1487128269Speter	}
1488128269Speter# ifdef CLIENT_SUPPORT
1489128269Speter	else
1490128269Speter            error (1, errno,
1491128269Speter                   "closing down connection to %s",
1492128269Speter                   current_parsed_root->hostname);
1493128269Speter# endif /* CLIENT_SUPPORT */
1494128269Speter    }
1495102840Speter
1496102840Speter    /* If we were talking to a process, make sure it exited */
1497128269Speter    if (bc->child_pid)
1498128269Speter    {
1499128269Speter	int w;
1500102840Speter
1501128269Speter	do
1502128269Speter	    w = waitpid (bc->child_pid, (int *) 0, 0);
1503128269Speter	while (w == -1 && errno == EINTR);
1504128269Speter	if (w == -1)
1505128269Speter	    error (1, errno, "waiting for process %d", bc->child_pid);
1506128269Speter    }
1507102840Speter    return 0;
1508102840Speter}
1509102840Speter
1510102840Speter
1511102840Speter
151232785Speter/* Certain types of communication input and output data in packets,
151332785Speter   where each packet is translated in some fashion.  The packetizing
151432785Speter   buffer type supports that, given a buffer which handles lower level
151532785Speter   I/O and a routine to translate the data in a packet.
151632785Speter
151732785Speter   This code uses two bytes for the size of a packet, so packets are
151832785Speter   restricted to 65536 bytes in total.
151932785Speter
152032785Speter   The translation functions should just translate; they may not
152132785Speter   significantly increase or decrease the amount of data.  The actual
152232785Speter   size of the initial data is part of the translated data.  The
152332785Speter   output translation routine may add up to PACKET_SLOP additional
152432785Speter   bytes, and the input translation routine should shrink the data
152532785Speter   correspondingly.  */
152632785Speter
152732785Speter#define PACKET_SLOP (100)
152832785Speter
152932785Speter/* This structure is the closure field of a packetizing buffer.  */
153032785Speter
153132785Speterstruct packetizing_buffer
153232785Speter{
153332785Speter    /* The underlying buffer.  */
153432785Speter    struct buffer *buf;
153532785Speter    /* The input translation function.  Exactly one of inpfn and outfn
153632785Speter       will be NULL.  The input translation function should
153732785Speter       untranslate the data in INPUT, storing the result in OUTPUT.
153832785Speter       SIZE is the amount of data in INPUT, and is also the size of
153932785Speter       OUTPUT.  This should return 0 on success, or an errno code.  */
154032785Speter    int (*inpfn) PROTO((void *fnclosure, const char *input, char *output,
154132785Speter			int size));
154232785Speter    /* The output translation function.  This should translate the
154332785Speter       data in INPUT, storing the result in OUTPUT.  The first two
154432785Speter       bytes in INPUT will be the size of the data, and so will SIZE.
154532785Speter       This should set *TRANSLATED to the amount of translated data in
154632785Speter       OUTPUT.  OUTPUT is large enough to hold SIZE + PACKET_SLOP
154732785Speter       bytes.  This should return 0 on success, or an errno code.  */
154832785Speter    int (*outfn) PROTO((void *fnclosure, const char *input, char *output,
154932785Speter			int size, int *translated));
155032785Speter    /* A closure for the translation function.  */
155132785Speter    void *fnclosure;
155232785Speter    /* For an input buffer, we may have to buffer up data here.  */
155332785Speter    /* This is non-zero if the buffered data has been translated.
155432785Speter       Otherwise, the buffered data has not been translated, and starts
155532785Speter       with the two byte packet size.  */
155632785Speter    int translated;
155732785Speter    /* The amount of buffered data.  */
155832785Speter    int holdsize;
155932785Speter    /* The buffer allocated to hold the data.  */
156032785Speter    char *holdbuf;
156132785Speter    /* The size of holdbuf.  */
156232785Speter    int holdbufsize;
156332785Speter    /* If translated is set, we need another data pointer to track
156432785Speter       where we are in holdbuf.  If translated is clear, then this
156532785Speter       pointer is not used.  */
156632785Speter    char *holddata;
156732785Speter};
156832785Speter
156932785Speterstatic int packetizing_buffer_input PROTO((void *, char *, int, int, int *));
157032785Speterstatic int packetizing_buffer_output PROTO((void *, const char *, int, int *));
157132785Speterstatic int packetizing_buffer_flush PROTO((void *));
157232785Speterstatic int packetizing_buffer_block PROTO((void *, int));
1573102840Speterstatic int packetizing_buffer_shutdown PROTO((struct buffer *));
157432785Speter
157532785Speter/* Create a packetizing buffer.  */
157632785Speter
157732785Speterstruct buffer *
157832785Speterpacketizing_buffer_initialize (buf, inpfn, outfn, fnclosure, memory)
157932785Speter     struct buffer *buf;
158032785Speter     int (*inpfn) PROTO ((void *, const char *, char *, int));
158132785Speter     int (*outfn) PROTO ((void *, const char *, char *, int, int *));
158232785Speter     void *fnclosure;
158332785Speter     void (*memory) PROTO((struct buffer *));
158432785Speter{
158532785Speter    struct packetizing_buffer *pb;
158632785Speter
158732785Speter    pb = (struct packetizing_buffer *) xmalloc (sizeof *pb);
158832785Speter    memset (pb, 0, sizeof *pb);
158932785Speter
159032785Speter    pb->buf = buf;
159132785Speter    pb->inpfn = inpfn;
159232785Speter    pb->outfn = outfn;
159332785Speter    pb->fnclosure = fnclosure;
159432785Speter
159532785Speter    if (inpfn != NULL)
159632785Speter    {
159732785Speter	/* Add PACKET_SLOP to handle larger translated packets, and
159832785Speter           add 2 for the count.  This buffer is increased if
159932785Speter           necessary.  */
160032785Speter	pb->holdbufsize = BUFFER_DATA_SIZE + PACKET_SLOP + 2;
160132785Speter	pb->holdbuf = xmalloc (pb->holdbufsize);
160232785Speter    }
160332785Speter
160432785Speter    return buf_initialize (inpfn != NULL ? packetizing_buffer_input : NULL,
160532785Speter			   inpfn != NULL ? NULL : packetizing_buffer_output,
160632785Speter			   inpfn != NULL ? NULL : packetizing_buffer_flush,
160732785Speter			   packetizing_buffer_block,
160832785Speter			   packetizing_buffer_shutdown,
160932785Speter			   memory,
161032785Speter			   pb);
161132785Speter}
161232785Speter
161332785Speter/* Input data from a packetizing buffer.  */
161432785Speter
161532785Speterstatic int
161632785Speterpacketizing_buffer_input (closure, data, need, size, got)
161732785Speter     void *closure;
161832785Speter     char *data;
161932785Speter     int need;
162032785Speter     int size;
162132785Speter     int *got;
162232785Speter{
162332785Speter    struct packetizing_buffer *pb = (struct packetizing_buffer *) closure;
162432785Speter
162532785Speter    *got = 0;
162632785Speter
162732785Speter    if (pb->holdsize > 0 && pb->translated)
162832785Speter    {
162932785Speter	int copy;
163032785Speter
163132785Speter	copy = pb->holdsize;
163232785Speter
163332785Speter	if (copy > size)
163432785Speter	{
163532785Speter	    memcpy (data, pb->holddata, size);
163632785Speter	    pb->holdsize -= size;
163732785Speter	    pb->holddata += size;
163832785Speter	    *got = size;
163932785Speter	    return 0;
164032785Speter	}
164132785Speter
164232785Speter	memcpy (data, pb->holddata, copy);
164332785Speter	pb->holdsize = 0;
164432785Speter	pb->translated = 0;
164532785Speter
164632785Speter	data += copy;
164732785Speter	need -= copy;
164832785Speter	size -= copy;
164932785Speter	*got = copy;
165032785Speter    }
165132785Speter
165232785Speter    while (need > 0 || *got == 0)
165332785Speter    {
165432785Speter	int get, status, nread, count, tcount;
165532785Speter	char *bytes;
165632785Speter	char stackoutbuf[BUFFER_DATA_SIZE + PACKET_SLOP];
165732785Speter	char *inbuf, *outbuf;
165832785Speter
165932785Speter	/* If we don't already have the two byte count, get it.  */
166032785Speter	if (pb->holdsize < 2)
166132785Speter	{
166232785Speter	    get = 2 - pb->holdsize;
166332785Speter	    status = buf_read_data (pb->buf, get, &bytes, &nread);
166432785Speter	    if (status != 0)
166532785Speter	    {
166632785Speter		/* buf_read_data can return -2, but a buffer input
166732785Speter                   function is only supposed to return -1, 0, or an
166832785Speter                   error code.  */
166932785Speter		if (status == -2)
167032785Speter		    status = ENOMEM;
167132785Speter		return status;
167232785Speter	    }
167332785Speter
167432785Speter	    if (nread == 0)
167532785Speter	    {
167632785Speter		/* The buffer is in nonblocking mode, and we didn't
167732785Speter                   manage to read anything.  */
167832785Speter		return 0;
167932785Speter	    }
168032785Speter
168132785Speter	    if (get == 1)
168232785Speter		pb->holdbuf[1] = bytes[0];
168332785Speter	    else
168432785Speter	    {
168532785Speter		pb->holdbuf[0] = bytes[0];
168632785Speter		if (nread < 2)
168732785Speter		{
168832785Speter		    /* We only got one byte, but we needed two.  Stash
168932785Speter                       the byte we got, and try again.  */
169032785Speter		    pb->holdsize = 1;
169132785Speter		    continue;
169232785Speter		}
169332785Speter		pb->holdbuf[1] = bytes[1];
169432785Speter	    }
169532785Speter	    pb->holdsize = 2;
169632785Speter	}
169732785Speter
169832785Speter	/* Read the packet.  */
169932785Speter
170032785Speter	count = (((pb->holdbuf[0] & 0xff) << 8)
170132785Speter		 + (pb->holdbuf[1] & 0xff));
170232785Speter
170332785Speter	if (count + 2 > pb->holdbufsize)
170432785Speter	{
170532785Speter	    char *n;
170632785Speter
170732785Speter	    /* We didn't allocate enough space in the initialize
170832785Speter               function.  */
170932785Speter
1710109660Speter	    n = xrealloc (pb->holdbuf, count + 2);
171132785Speter	    if (n == NULL)
171232785Speter	    {
171332785Speter		(*pb->buf->memory_error) (pb->buf);
171432785Speter		return ENOMEM;
171532785Speter	    }
171632785Speter	    pb->holdbuf = n;
171732785Speter	    pb->holdbufsize = count + 2;
171832785Speter	}
171932785Speter
172032785Speter	get = count - (pb->holdsize - 2);
172132785Speter
172232785Speter	status = buf_read_data (pb->buf, get, &bytes, &nread);
172332785Speter	if (status != 0)
172432785Speter	{
172532785Speter	    /* buf_read_data can return -2, but a buffer input
172632785Speter               function is only supposed to return -1, 0, or an error
172732785Speter               code.  */
172832785Speter	    if (status == -2)
172932785Speter		status = ENOMEM;
173032785Speter	    return status;
173132785Speter	}
173232785Speter
173332785Speter	if (nread == 0)
173432785Speter	{
173532785Speter	    /* We did not get any data.  Presumably the buffer is in
173632785Speter               nonblocking mode.  */
173732785Speter	    return 0;
173832785Speter	}
173932785Speter
174032785Speter	if (nread < get)
174132785Speter	{
174232785Speter	    /* We did not get all the data we need to fill the packet.
174332785Speter               buf_read_data does not promise to return all the bytes
174432785Speter               requested, so we must try again.  */
174532785Speter	    memcpy (pb->holdbuf + pb->holdsize, bytes, nread);
174632785Speter	    pb->holdsize += nread;
174732785Speter	    continue;
174832785Speter	}
174932785Speter
175032785Speter	/* We have a complete untranslated packet of COUNT bytes.  */
175132785Speter
175232785Speter	if (pb->holdsize == 2)
175332785Speter	{
175432785Speter	    /* We just read the entire packet (the 2 bytes in
175532785Speter               PB->HOLDBUF are the size).  Save a memcpy by
175632785Speter               translating directly from BYTES.  */
175732785Speter	    inbuf = bytes;
175832785Speter	}
175932785Speter	else
176032785Speter	{
176132785Speter	    /* We already had a partial packet in PB->HOLDBUF.  We
176232785Speter               need to copy the new data over to make the input
176332785Speter               contiguous.  */
176432785Speter	    memcpy (pb->holdbuf + pb->holdsize, bytes, nread);
176532785Speter	    inbuf = pb->holdbuf + 2;
176632785Speter	}
176732785Speter
176832785Speter	if (count <= sizeof stackoutbuf)
176932785Speter	    outbuf = stackoutbuf;
177032785Speter	else
177132785Speter	{
1772109660Speter	    outbuf = xmalloc (count);
177332785Speter	    if (outbuf == NULL)
177432785Speter	    {
177532785Speter		(*pb->buf->memory_error) (pb->buf);
177632785Speter		return ENOMEM;
177732785Speter	    }
177832785Speter	}
177932785Speter
178032785Speter	status = (*pb->inpfn) (pb->fnclosure, inbuf, outbuf, count);
178132785Speter	if (status != 0)
178232785Speter	    return status;
178332785Speter
178432785Speter	/* The first two bytes in the translated buffer are the real
178532785Speter           length of the translated data.  */
178632785Speter	tcount = ((outbuf[0] & 0xff) << 8) + (outbuf[1] & 0xff);
178732785Speter
178832785Speter	if (tcount > count)
178932785Speter	    error (1, 0, "Input translation failure");
179032785Speter
179132785Speter	if (tcount > size)
179232785Speter	{
179332785Speter	    /* We have more data than the caller has provided space
179432785Speter               for.  We need to save some of it for the next call.  */
179532785Speter
179632785Speter	    memcpy (data, outbuf + 2, size);
179732785Speter	    *got += size;
179832785Speter
179932785Speter	    pb->holdsize = tcount - size;
180032785Speter	    memcpy (pb->holdbuf, outbuf + 2 + size, tcount - size);
180132785Speter	    pb->holddata = pb->holdbuf;
180232785Speter	    pb->translated = 1;
180332785Speter
180432785Speter	    if (outbuf != stackoutbuf)
180532785Speter		free (outbuf);
180632785Speter
180732785Speter	    return 0;
180832785Speter	}
180932785Speter
181032785Speter	memcpy (data, outbuf + 2, tcount);
181132785Speter
181232785Speter	if (outbuf != stackoutbuf)
181332785Speter	    free (outbuf);
181432785Speter
181532785Speter	pb->holdsize = 0;
181632785Speter
181732785Speter	data += tcount;
181832785Speter	need -= tcount;
181932785Speter	size -= tcount;
182032785Speter	*got += tcount;
182132785Speter    }
182232785Speter
182332785Speter    return 0;
182432785Speter}
182532785Speter
182632785Speter/* Output data to a packetizing buffer.  */
182732785Speter
182832785Speterstatic int
182932785Speterpacketizing_buffer_output (closure, data, have, wrote)
183032785Speter     void *closure;
183132785Speter     const char *data;
183232785Speter     int have;
183332785Speter     int *wrote;
183432785Speter{
183532785Speter    struct packetizing_buffer *pb = (struct packetizing_buffer *) closure;
183632785Speter    char inbuf[BUFFER_DATA_SIZE + 2];
183732785Speter    char stack_outbuf[BUFFER_DATA_SIZE + PACKET_SLOP + 4];
183832785Speter    struct buffer_data *outdata;
183932785Speter    char *outbuf;
184032785Speter    int size, status, translated;
184132785Speter
184232785Speter    if (have > BUFFER_DATA_SIZE)
184332785Speter    {
1844109660Speter	/* It would be easy to xmalloc a buffer, but I don't think this
184532785Speter           case can ever arise.  */
184632785Speter	abort ();
184732785Speter    }
184832785Speter
184932785Speter    inbuf[0] = (have >> 8) & 0xff;
185032785Speter    inbuf[1] = have & 0xff;
185132785Speter    memcpy (inbuf + 2, data, have);
185232785Speter
185332785Speter    size = have + 2;
185432785Speter
185532785Speter    /* The output function is permitted to add up to PACKET_SLOP
185632785Speter       bytes, and we need 2 bytes for the size of the translated data.
185732785Speter       If we can guarantee that the result will fit in a buffer_data,
185832785Speter       we translate directly into one to avoid a memcpy in buf_output.  */
185932785Speter    if (size + PACKET_SLOP + 2 > BUFFER_DATA_SIZE)
186032785Speter	outbuf = stack_outbuf;
186132785Speter    else
186232785Speter    {
186332785Speter	outdata = get_buffer_data ();
186432785Speter	if (outdata == NULL)
186532785Speter	{
186632785Speter	    (*pb->buf->memory_error) (pb->buf);
186732785Speter	    return ENOMEM;
186832785Speter	}
186932785Speter
187032785Speter	outdata->next = NULL;
187132785Speter	outdata->bufp = outdata->text;
187232785Speter
187332785Speter	outbuf = outdata->text;
187432785Speter    }
187532785Speter
187632785Speter    status = (*pb->outfn) (pb->fnclosure, inbuf, outbuf + 2, size,
187732785Speter			   &translated);
187832785Speter    if (status != 0)
187932785Speter	return status;
188032785Speter
188132785Speter    /* The output function is permitted to add up to PACKET_SLOP
188232785Speter       bytes.  */
188332785Speter    if (translated > size + PACKET_SLOP)
188432785Speter	abort ();
188532785Speter
188632785Speter    outbuf[0] = (translated >> 8) & 0xff;
188732785Speter    outbuf[1] = translated & 0xff;
188832785Speter
188932785Speter    if (outbuf == stack_outbuf)
189032785Speter	buf_output (pb->buf, outbuf, translated + 2);
189132785Speter    else
189232785Speter    {
189332785Speter	outdata->size = translated + 2;
189432785Speter	buf_append_data (pb->buf, outdata, outdata);
189532785Speter    }
189632785Speter
189732785Speter    *wrote = have;
189832785Speter
189932785Speter    /* We will only be here because buf_send_output was called on the
190032785Speter       packetizing buffer.  That means that we should now call
190132785Speter       buf_send_output on the underlying buffer.  */
190232785Speter    return buf_send_output (pb->buf);
190332785Speter}
190432785Speter
1905128269Speter
1906128269Speter
190732785Speter/* Flush data to a packetizing buffer.  */
190832785Speterstatic int
190932785Speterpacketizing_buffer_flush (closure)
191032785Speter     void *closure;
191132785Speter{
191232785Speter    struct packetizing_buffer *pb = (struct packetizing_buffer *) closure;
191332785Speter
191432785Speter    /* Flush the underlying buffer.  Note that if the original call to
191532785Speter       buf_flush passed 1 for the BLOCK argument, then the buffer will
191632785Speter       already have been set into blocking mode, so we should always
191732785Speter       pass 0 here.  */
191832785Speter    return buf_flush (pb->buf, 0);
191932785Speter}
192032785Speter
1921128269Speter
1922128269Speter
192332785Speter/* The block routine for a packetizing buffer.  */
192432785Speterstatic int
192532785Speterpacketizing_buffer_block (closure, block)
192632785Speter     void *closure;
192732785Speter     int block;
192832785Speter{
192932785Speter    struct packetizing_buffer *pb = (struct packetizing_buffer *) closure;
193032785Speter
193132785Speter    if (block)
193232785Speter	return set_block (pb->buf);
193332785Speter    else
193432785Speter	return set_nonblock (pb->buf);
193532785Speter}
193632785Speter
193732785Speter/* Shut down a packetizing buffer.  */
193832785Speter
193932785Speterstatic int
1940102840Speterpacketizing_buffer_shutdown (buf)
1941102840Speter    struct buffer *buf;
194232785Speter{
1943102840Speter    struct packetizing_buffer *pb = (struct packetizing_buffer *) buf->closure;
194432785Speter
194532785Speter    return buf_shutdown (pb->buf);
194632785Speter}
194732785Speter
194825839Speter#endif /* defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT) */
1949