1175282Sobrien/*
2175282Sobrien * Copyright (C) 1996-2005 The Free Software Foundation, Inc.
3175282Sobrien *
4175282Sobrien * This program is free software; you can redistribute it and/or modify
5175282Sobrien * it under the terms of the GNU General Public License as published by
6175282Sobrien * the Free Software Foundation; either version 2, or (at your option)
7175282Sobrien * any later version.
8175282Sobrien *
9175282Sobrien * This program is distributed in the hope that it will be useful,
10175282Sobrien * but WITHOUT ANY WARRANTY; without even the implied warranty of
11175282Sobrien * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12175282Sobrien * GNU General Public License for more details.
13175282Sobrien */
14175282Sobrien
1525839Speter/* Code for the buffer data structure.  */
1625839Speter
17102852Speter/* $FreeBSD$ */
18102852Speter
1925839Speter#include <assert.h>
2025839Speter#include "cvs.h"
2125839Speter#include "buffer.h"
2225839Speter
2325839Speter#if defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT)
2425839Speter
25102840Speter#ifdef HAVE_WINSOCK_H
26102840Speter# include <winsock.h>
27102840Speter#else
28102840Speter# include <sys/socket.h>
29102840Speter#endif
30102840Speter
3125839Speter/* OS/2 doesn't have EIO.  FIXME: this whole notion of turning
3225839Speter   a different error into EIO strikes me as pretty dubious.  */
3325839Speter#if !defined (EIO)
3425839Speter#define EIO EBADPOS
3525839Speter#endif
3625839Speter
3725839Speter/* Linked list of available buffer_data structures.  */
3825839Speterstatic struct buffer_data *free_buffer_data;
3925839Speter
4025839Speter/* Local functions.  */
4134461Speterstatic void buf_default_memory_error PROTO ((struct buffer *));
4225839Speterstatic void allocate_buffer_datas PROTO((void));
4325839Speterstatic struct buffer_data *get_buffer_data PROTO((void));
4425839Speter
4525839Speter/* Initialize a buffer structure.  */
4625839Speter
4725839Speterstruct buffer *
4825839Speterbuf_initialize (input, output, flush, block, shutdown, memory, closure)
4925839Speter     int (*input) PROTO((void *, char *, int, int, int *));
5025839Speter     int (*output) PROTO((void *, const char *, int, int *));
5125839Speter     int (*flush) PROTO((void *));
5225839Speter     int (*block) PROTO((void *, int));
53102840Speter     int (*shutdown) PROTO((struct buffer *));
5425839Speter     void (*memory) PROTO((struct buffer *));
5525839Speter     void *closure;
5625839Speter{
5725839Speter    struct buffer *buf;
5825839Speter
5925839Speter    buf = (struct buffer *) xmalloc (sizeof (struct buffer));
6025839Speter    buf->data = NULL;
6125839Speter    buf->last = NULL;
6225839Speter    buf->nonblocking = 0;
6325839Speter    buf->input = input;
6425839Speter    buf->output = output;
6525839Speter    buf->flush = flush;
6625839Speter    buf->block = block;
6725839Speter    buf->shutdown = shutdown;
6834461Speter    buf->memory_error = memory ? memory : buf_default_memory_error;
6925839Speter    buf->closure = closure;
7025839Speter    return buf;
7125839Speter}
7225839Speter
7334461Speter/* Free a buffer structure.  */
7434461Speter
7534461Spetervoid
7634461Speterbuf_free (buf)
7734461Speter     struct buffer *buf;
7834461Speter{
79128269Speter    if (buf->closure != NULL)
80128269Speter    {
81128269Speter	free (buf->closure);
82128269Speter	buf->closure = NULL;
83128269Speter    }
8434461Speter    if (buf->data != NULL)
8534461Speter    {
8634461Speter	buf->last->next = free_buffer_data;
8734461Speter	free_buffer_data = buf->data;
8834461Speter    }
8934461Speter    free (buf);
9034461Speter}
9134461Speter
9225839Speter/* Initialize a buffer structure which is not to be used for I/O.  */
9325839Speter
9425839Speterstruct buffer *
9525839Speterbuf_nonio_initialize (memory)
9625839Speter     void (*memory) PROTO((struct buffer *));
9725839Speter{
9825839Speter    return (buf_initialize
9925839Speter	    ((int (*) PROTO((void *, char *, int, int, int *))) NULL,
10025839Speter	     (int (*) PROTO((void *, const char *, int, int *))) NULL,
10125839Speter	     (int (*) PROTO((void *))) NULL,
10225839Speter	     (int (*) PROTO((void *, int))) NULL,
103102840Speter	     (int (*) PROTO((struct buffer *))) NULL,
10425839Speter	     memory,
10525839Speter	     (void *) NULL));
10625839Speter}
10725839Speter
10834461Speter/* Default memory error handler.  */
10934461Speter
11034461Speterstatic void
11134461Speterbuf_default_memory_error (buf)
11234461Speter     struct buffer *buf;
11334461Speter{
11434461Speter    error (1, 0, "out of memory");
11534461Speter}
11634461Speter
11725839Speter/* Allocate more buffer_data structures.  */
11825839Speter
11925839Speterstatic void
12025839Speterallocate_buffer_datas ()
12125839Speter{
12225839Speter    struct buffer_data *alc;
12325839Speter    char *space;
12425839Speter    int i;
12525839Speter
12625839Speter    /* Allocate buffer_data structures in blocks of 16.  */
12725839Speter#define ALLOC_COUNT (16)
12825839Speter
129175282Sobrien    alc = xmalloc (ALLOC_COUNT * sizeof (struct buffer_data));
13025839Speter    space = (char *) valloc (ALLOC_COUNT * BUFFER_DATA_SIZE);
131175282Sobrien    if (!space)
132175282Sobrien    {
133175282Sobrien	free (alc);
13425839Speter	return;
135175282Sobrien    }
13625839Speter    for (i = 0; i < ALLOC_COUNT; i++, alc++, space += BUFFER_DATA_SIZE)
13725839Speter    {
13825839Speter	alc->next = free_buffer_data;
13925839Speter	free_buffer_data = alc;
14025839Speter	alc->text = space;
14125839Speter    }
14225839Speter}
14325839Speter
14425839Speter/* Get a new buffer_data structure.  */
14525839Speter
14625839Speterstatic struct buffer_data *
14725839Speterget_buffer_data ()
14825839Speter{
14925839Speter    struct buffer_data *ret;
15025839Speter
15125839Speter    if (free_buffer_data == NULL)
15225839Speter    {
15325839Speter	allocate_buffer_datas ();
15425839Speter	if (free_buffer_data == NULL)
15525839Speter	    return NULL;
15625839Speter    }
15725839Speter
15825839Speter    ret = free_buffer_data;
15925839Speter    free_buffer_data = ret->next;
16025839Speter    return ret;
16125839Speter}
16225839Speter
16325839Speter
164128269Speter
165128269Speter/* See whether a buffer and its file descriptor is empty.  */
16625839Speterint
167128269Speterbuf_empty (buf)
168128269Speter    struct buffer *buf;
169128269Speter{
170128269Speter	/* Try and read any data on the file descriptor first.
171128269Speter	 * We already know the descriptor is non-blocking.
172128269Speter	 */
173128269Speter	buf_input_data (buf, NULL);
174128269Speter	return buf_empty_p (buf);
175128269Speter}
176128269Speter
177128269Speter
178128269Speter
179128269Speter/* See whether a buffer is empty.  */
180128269Speterint
18125839Speterbuf_empty_p (buf)
18225839Speter    struct buffer *buf;
18325839Speter{
18425839Speter    struct buffer_data *data;
18525839Speter
18625839Speter    for (data = buf->data; data != NULL; data = data->next)
18725839Speter	if (data->size > 0)
18825839Speter	    return 0;
18925839Speter    return 1;
19025839Speter}
19125839Speter
192128269Speter
193128269Speter
19425839Speter#ifdef SERVER_FLOWCONTROL
19525839Speter/*
19625839Speter * Count how much data is stored in the buffer..
197109660Speter * Note that each buffer is a xmalloc'ed chunk BUFFER_DATA_SIZE.
19825839Speter */
19925839Speter
20025839Speterint
20125839Speterbuf_count_mem (buf)
20225839Speter    struct buffer *buf;
20325839Speter{
20425839Speter    struct buffer_data *data;
20525839Speter    int mem = 0;
20625839Speter
20725839Speter    for (data = buf->data; data != NULL; data = data->next)
20825839Speter	mem += BUFFER_DATA_SIZE;
20925839Speter
21025839Speter    return mem;
21125839Speter}
21225839Speter#endif /* SERVER_FLOWCONTROL */
21325839Speter
21425839Speter/* Add data DATA of length LEN to BUF.  */
21525839Speter
21625839Spetervoid
21725839Speterbuf_output (buf, data, len)
21825839Speter    struct buffer *buf;
21925839Speter    const char *data;
22025839Speter    int len;
22125839Speter{
22225839Speter    if (buf->data != NULL
22325839Speter	&& (((buf->last->text + BUFFER_DATA_SIZE)
22425839Speter	     - (buf->last->bufp + buf->last->size))
22525839Speter	    >= len))
22625839Speter    {
22725839Speter	memcpy (buf->last->bufp + buf->last->size, data, len);
22825839Speter	buf->last->size += len;
22925839Speter	return;
23025839Speter    }
23125839Speter
23225839Speter    while (1)
23325839Speter    {
23425839Speter	struct buffer_data *newdata;
23525839Speter
23625839Speter	newdata = get_buffer_data ();
23725839Speter	if (newdata == NULL)
23825839Speter	{
23925839Speter	    (*buf->memory_error) (buf);
24025839Speter	    return;
24125839Speter	}
24225839Speter
24325839Speter	if (buf->data == NULL)
24425839Speter	    buf->data = newdata;
24525839Speter	else
24625839Speter	    buf->last->next = newdata;
24725839Speter	newdata->next = NULL;
24825839Speter	buf->last = newdata;
24925839Speter
25025839Speter	newdata->bufp = newdata->text;
25125839Speter
25225839Speter	if (len <= BUFFER_DATA_SIZE)
25325839Speter	{
25425839Speter	    newdata->size = len;
25525839Speter	    memcpy (newdata->text, data, len);
25625839Speter	    return;
25725839Speter	}
25825839Speter
25925839Speter	newdata->size = BUFFER_DATA_SIZE;
26025839Speter	memcpy (newdata->text, data, BUFFER_DATA_SIZE);
26125839Speter
26225839Speter	data += BUFFER_DATA_SIZE;
26325839Speter	len -= BUFFER_DATA_SIZE;
26425839Speter    }
26525839Speter
26625839Speter    /*NOTREACHED*/
26725839Speter}
26825839Speter
26925839Speter/* Add a '\0' terminated string to BUF.  */
27025839Speter
27125839Spetervoid
27225839Speterbuf_output0 (buf, string)
27325839Speter    struct buffer *buf;
27425839Speter    const char *string;
27525839Speter{
27625839Speter    buf_output (buf, string, strlen (string));
27725839Speter}
27825839Speter
27925839Speter/* Add a single character to BUF.  */
28025839Speter
28125839Spetervoid
28225839Speterbuf_append_char (buf, ch)
28325839Speter    struct buffer *buf;
28425839Speter    int ch;
28525839Speter{
28625839Speter    if (buf->data != NULL
28725839Speter	&& (buf->last->text + BUFFER_DATA_SIZE
28825839Speter	    != buf->last->bufp + buf->last->size))
28925839Speter    {
29025839Speter	*(buf->last->bufp + buf->last->size) = ch;
29125839Speter	++buf->last->size;
29225839Speter    }
29325839Speter    else
29425839Speter    {
29525839Speter	char b;
29625839Speter
29725839Speter	b = ch;
29825839Speter	buf_output (buf, &b, 1);
29925839Speter    }
30025839Speter}
30125839Speter
30225839Speter/*
30325839Speter * Send all the output we've been saving up.  Returns 0 for success or
30425839Speter * errno code.  If the buffer has been set to be nonblocking, this
30525839Speter * will just write until the write would block.
30625839Speter */
30725839Speter
30825839Speterint
30925839Speterbuf_send_output (buf)
31025839Speter     struct buffer *buf;
31125839Speter{
31225839Speter    if (buf->output == NULL)
31325839Speter	abort ();
31425839Speter
31525839Speter    while (buf->data != NULL)
31625839Speter    {
31725839Speter	struct buffer_data *data;
31825839Speter
31925839Speter	data = buf->data;
32025839Speter
32125839Speter	if (data->size > 0)
32225839Speter	{
32325839Speter	    int status, nbytes;
32425839Speter
32525839Speter	    status = (*buf->output) (buf->closure, data->bufp, data->size,
32625839Speter				     &nbytes);
32725839Speter	    if (status != 0)
32825839Speter	    {
32925839Speter		/* Some sort of error.  Discard the data, and return.  */
33025839Speter
33125839Speter		buf->last->next = free_buffer_data;
33225839Speter		free_buffer_data = buf->data;
33325839Speter		buf->data = NULL;
33425839Speter		buf->last = NULL;
33525839Speter
33625839Speter	        return status;
33725839Speter	    }
33825839Speter
33925839Speter	    if (nbytes != data->size)
34025839Speter	    {
34125839Speter		/* Not all the data was written out.  This is only
34225839Speter                   permitted in nonblocking mode.  Adjust the buffer,
34325839Speter                   and return.  */
34425839Speter
34525839Speter		assert (buf->nonblocking);
34625839Speter
34725839Speter		data->size -= nbytes;
34825839Speter		data->bufp += nbytes;
34925839Speter
35025839Speter		return 0;
35125839Speter	    }
35225839Speter	}
35325839Speter
35425839Speter	buf->data = data->next;
35525839Speter	data->next = free_buffer_data;
35625839Speter	free_buffer_data = data;
35725839Speter    }
35825839Speter
35925839Speter    buf->last = NULL;
36025839Speter
36125839Speter    return 0;
36225839Speter}
36325839Speter
36425839Speter/*
36525839Speter * Flush any data queued up in the buffer.  If BLOCK is nonzero, then
36625839Speter * if the buffer is in nonblocking mode, put it into blocking mode for
36725839Speter * the duration of the flush.  This returns 0 on success, or an error
36825839Speter * code.
36925839Speter */
37025839Speter
37125839Speterint
37225839Speterbuf_flush (buf, block)
37325839Speter     struct buffer *buf;
37425839Speter     int block;
37525839Speter{
37625839Speter    int nonblocking;
37725839Speter    int status;
37825839Speter
37925839Speter    if (buf->flush == NULL)
38025839Speter        abort ();
38125839Speter
38225839Speter    nonblocking = buf->nonblocking;
38325839Speter    if (nonblocking && block)
38425839Speter    {
38525839Speter        status = set_block (buf);
38625839Speter	if (status != 0)
38725839Speter	    return status;
38825839Speter    }
38925839Speter
39025839Speter    status = buf_send_output (buf);
39125839Speter    if (status == 0)
39225839Speter        status = (*buf->flush) (buf->closure);
39325839Speter
39425839Speter    if (nonblocking && block)
39525839Speter    {
39625839Speter        int blockstat;
39725839Speter
39825839Speter        blockstat = set_nonblock (buf);
39925839Speter	if (status == 0)
40025839Speter	    status = blockstat;
40125839Speter    }
40225839Speter
40325839Speter    return status;
40425839Speter}
40525839Speter
40625839Speter/*
40725839Speter * Set buffer BUF to nonblocking I/O.  Returns 0 for success or errno
40825839Speter * code.
40925839Speter */
41025839Speter
41125839Speterint
41225839Speterset_nonblock (buf)
41325839Speter     struct buffer *buf;
41425839Speter{
41525839Speter    int status;
41625839Speter
41725839Speter    if (buf->nonblocking)
41825839Speter	return 0;
41925839Speter    if (buf->block == NULL)
42025839Speter        abort ();
42125839Speter    status = (*buf->block) (buf->closure, 0);
42225839Speter    if (status != 0)
42325839Speter	return status;
42425839Speter    buf->nonblocking = 1;
42525839Speter    return 0;
42625839Speter}
42725839Speter
42825839Speter/*
42925839Speter * Set buffer BUF to blocking I/O.  Returns 0 for success or errno
43025839Speter * code.
43125839Speter */
43225839Speter
43325839Speterint
43425839Speterset_block (buf)
43525839Speter     struct buffer *buf;
43625839Speter{
43725839Speter    int status;
43825839Speter
43925839Speter    if (! buf->nonblocking)
44025839Speter	return 0;
44125839Speter    if (buf->block == NULL)
44225839Speter        abort ();
44325839Speter    status = (*buf->block) (buf->closure, 1);
44425839Speter    if (status != 0)
44525839Speter	return status;
44625839Speter    buf->nonblocking = 0;
44725839Speter    return 0;
44825839Speter}
44925839Speter
45025839Speter/*
45125839Speter * Send a character count and some output.  Returns errno code or 0 for
45225839Speter * success.
45325839Speter *
45425839Speter * Sending the count in binary is OK since this is only used on a pipe
45525839Speter * within the same system.
45625839Speter */
45725839Speter
45825839Speterint
45925839Speterbuf_send_counted (buf)
46025839Speter     struct buffer *buf;
46125839Speter{
46225839Speter    int size;
46325839Speter    struct buffer_data *data;
46425839Speter
46525839Speter    size = 0;
46625839Speter    for (data = buf->data; data != NULL; data = data->next)
46725839Speter	size += data->size;
46825839Speter
46925839Speter    data = get_buffer_data ();
47025839Speter    if (data == NULL)
47125839Speter    {
47225839Speter	(*buf->memory_error) (buf);
47325839Speter	return ENOMEM;
47425839Speter    }
47525839Speter
47625839Speter    data->next = buf->data;
47725839Speter    buf->data = data;
47825839Speter    if (buf->last == NULL)
47925839Speter	buf->last = data;
48025839Speter
48125839Speter    data->bufp = data->text;
48225839Speter    data->size = sizeof (int);
48325839Speter
48425839Speter    *((int *) data->text) = size;
48525839Speter
48625839Speter    return buf_send_output (buf);
48725839Speter}
48825839Speter
48925839Speter/*
49025839Speter * Send a special count.  COUNT should be negative.  It will be
49125839Speter * handled speciallyi by buf_copy_counted.  This function returns 0 or
49225839Speter * an errno code.
49325839Speter *
49425839Speter * Sending the count in binary is OK since this is only used on a pipe
49525839Speter * within the same system.
49625839Speter */
49725839Speter
49825839Speterint
49925839Speterbuf_send_special_count (buf, count)
50025839Speter     struct buffer *buf;
50125839Speter     int count;
50225839Speter{
50325839Speter    struct buffer_data *data;
50425839Speter
50525839Speter    data = get_buffer_data ();
50625839Speter    if (data == NULL)
50725839Speter    {
50825839Speter	(*buf->memory_error) (buf);
50925839Speter	return ENOMEM;
51025839Speter    }
51125839Speter
51225839Speter    data->next = buf->data;
51325839Speter    buf->data = data;
51425839Speter    if (buf->last == NULL)
51525839Speter	buf->last = data;
51625839Speter
51725839Speter    data->bufp = data->text;
51825839Speter    data->size = sizeof (int);
51925839Speter
52025839Speter    *((int *) data->text) = count;
52125839Speter
52225839Speter    return buf_send_output (buf);
52325839Speter}
52425839Speter
52525839Speter/* Append a list of buffer_data structures to an buffer.  */
52625839Speter
52725839Spetervoid
52825839Speterbuf_append_data (buf, data, last)
52925839Speter     struct buffer *buf;
53025839Speter     struct buffer_data *data;
53125839Speter     struct buffer_data *last;
53225839Speter{
53325839Speter    if (data != NULL)
53425839Speter    {
53525839Speter	if (buf->data == NULL)
53625839Speter	    buf->data = data;
53725839Speter	else
53825839Speter	    buf->last->next = data;
53925839Speter	buf->last = last;
54025839Speter    }
54125839Speter}
54225839Speter
54334461Speter/* Append the data on one buffer to another.  This removes the data
54434461Speter   from the source buffer.  */
54534461Speter
54634461Spetervoid
54734461Speterbuf_append_buffer (to, from)
54834461Speter     struct buffer *to;
54934461Speter     struct buffer *from;
55034461Speter{
55134461Speter    buf_append_data (to, from->data, from->last);
55234461Speter    from->data = NULL;
55334461Speter    from->last = NULL;
55434461Speter}
55534461Speter
55625839Speter/*
55725839Speter * Copy the contents of file F into buffer_data structures.  We can't
55825839Speter * copy directly into an buffer, because we want to handle failure and
55925839Speter * succeess differently.  Returns 0 on success, or -2 if out of
56025839Speter * memory, or a status code on error.  Since the caller happens to
56125839Speter * know the size of the file, it is passed in as SIZE.  On success,
56225839Speter * this function sets *RETP and *LASTP, which may be passed to
56325839Speter * buf_append_data.
56425839Speter */
56525839Speter
56625839Speterint
56725839Speterbuf_read_file (f, size, retp, lastp)
56825839Speter    FILE *f;
56925839Speter    long size;
57025839Speter    struct buffer_data **retp;
57125839Speter    struct buffer_data **lastp;
57225839Speter{
57325839Speter    int status;
57425839Speter
57525839Speter    *retp = NULL;
57625839Speter    *lastp = NULL;
57725839Speter
57825839Speter    while (size > 0)
57925839Speter    {
58025839Speter	struct buffer_data *data;
58125839Speter	int get;
58225839Speter
58325839Speter	data = get_buffer_data ();
58425839Speter	if (data == NULL)
58525839Speter	{
58625839Speter	    status = -2;
58725839Speter	    goto error_return;
58825839Speter	}
58925839Speter
59025839Speter	if (*retp == NULL)
59125839Speter	    *retp = data;
59225839Speter	else
59325839Speter	    (*lastp)->next = data;
59425839Speter	data->next = NULL;
59525839Speter	*lastp = data;
59625839Speter
59725839Speter	data->bufp = data->text;
59825839Speter	data->size = 0;
59925839Speter
60025839Speter	if (size > BUFFER_DATA_SIZE)
60125839Speter	    get = BUFFER_DATA_SIZE;
60225839Speter	else
60325839Speter	    get = size;
60425839Speter
60525839Speter	errno = EIO;
60625839Speter	if (fread (data->text, get, 1, f) != 1)
60725839Speter	{
60825839Speter	    status = errno;
60925839Speter	    goto error_return;
61025839Speter	}
61125839Speter
61225839Speter	data->size += get;
61325839Speter	size -= get;
61425839Speter    }
61525839Speter
61625839Speter    return 0;
61725839Speter
61825839Speter  error_return:
61925839Speter    if (*retp != NULL)
62025839Speter    {
62125839Speter	(*lastp)->next = free_buffer_data;
62225839Speter	free_buffer_data = *retp;
62325839Speter    }
62425839Speter    return status;
62525839Speter}
62625839Speter
62725839Speter/*
62825839Speter * Copy the contents of file F into buffer_data structures.  We can't
62925839Speter * copy directly into an buffer, because we want to handle failure and
63025839Speter * succeess differently.  Returns 0 on success, or -2 if out of
63125839Speter * memory, or a status code on error.  On success, this function sets
63225839Speter * *RETP and *LASTP, which may be passed to buf_append_data.
63325839Speter */
63425839Speter
63525839Speterint
63625839Speterbuf_read_file_to_eof (f, retp, lastp)
63725839Speter     FILE *f;
63825839Speter     struct buffer_data **retp;
63925839Speter     struct buffer_data **lastp;
64025839Speter{
64125839Speter    int status;
64225839Speter
64325839Speter    *retp = NULL;
64425839Speter    *lastp = NULL;
64525839Speter
64625839Speter    while (!feof (f))
64725839Speter    {
64825839Speter	struct buffer_data *data;
64925839Speter	int get, nread;
65025839Speter
65125839Speter	data = get_buffer_data ();
65225839Speter	if (data == NULL)
65325839Speter	{
65425839Speter	    status = -2;
65525839Speter	    goto error_return;
65625839Speter	}
65725839Speter
65825839Speter	if (*retp == NULL)
65925839Speter	    *retp = data;
66025839Speter	else
66125839Speter	    (*lastp)->next = data;
66225839Speter	data->next = NULL;
66325839Speter	*lastp = data;
66425839Speter
66525839Speter	data->bufp = data->text;
66625839Speter	data->size = 0;
66725839Speter
66825839Speter	get = BUFFER_DATA_SIZE;
66925839Speter
67025839Speter	errno = EIO;
67125839Speter	nread = fread (data->text, 1, get, f);
67225839Speter	if (nread == 0 && !feof (f))
67325839Speter	{
67425839Speter	    status = errno;
67525839Speter	    goto error_return;
67625839Speter	}
67725839Speter
67825839Speter	data->size = nread;
67925839Speter    }
68025839Speter
68125839Speter    return 0;
68225839Speter
68325839Speter  error_return:
68425839Speter    if (*retp != NULL)
68525839Speter    {
68625839Speter	(*lastp)->next = free_buffer_data;
68725839Speter	free_buffer_data = *retp;
68825839Speter    }
68925839Speter    return status;
69025839Speter}
69125839Speter
69225839Speter/* Return the number of bytes in a chain of buffer_data structures.  */
69325839Speter
69425839Speterint
69525839Speterbuf_chain_length (buf)
69625839Speter     struct buffer_data *buf;
69725839Speter{
69825839Speter    int size = 0;
69925839Speter    while (buf)
70025839Speter    {
70125839Speter	size += buf->size;
70225839Speter	buf = buf->next;
70325839Speter    }
70425839Speter    return size;
70525839Speter}
70625839Speter
70734461Speter/* Return the number of bytes in a buffer.  */
70834461Speter
70934461Speterint
71034461Speterbuf_length (buf)
71134461Speter    struct buffer *buf;
71234461Speter{
71334461Speter    return buf_chain_length (buf->data);
71434461Speter}
71534461Speter
71625839Speter/*
71725839Speter * Read an arbitrary amount of data into an input buffer.  The buffer
71825839Speter * will be in nonblocking mode, and we just grab what we can.  Return
71925839Speter * 0 on success, or -1 on end of file, or -2 if out of memory, or an
72025839Speter * error code.  If COUNTP is not NULL, *COUNTP is set to the number of
72125839Speter * bytes read.
72225839Speter */
72325839Speter
72425839Speterint
72525839Speterbuf_input_data (buf, countp)
72625839Speter     struct buffer *buf;
72725839Speter     int *countp;
72825839Speter{
72925839Speter    if (buf->input == NULL)
73025839Speter	abort ();
73125839Speter
73225839Speter    if (countp != NULL)
73325839Speter	*countp = 0;
73425839Speter
73525839Speter    while (1)
73625839Speter    {
73725839Speter	int get;
73825839Speter	int status, nbytes;
73925839Speter
74025839Speter	if (buf->data == NULL
74125839Speter	    || (buf->last->bufp + buf->last->size
74225839Speter		== buf->last->text + BUFFER_DATA_SIZE))
74325839Speter	{
74425839Speter	    struct buffer_data *data;
74525839Speter
74625839Speter	    data = get_buffer_data ();
74725839Speter	    if (data == NULL)
74825839Speter	    {
74925839Speter		(*buf->memory_error) (buf);
75025839Speter		return -2;
75125839Speter	    }
75225839Speter
75325839Speter	    if (buf->data == NULL)
75425839Speter		buf->data = data;
75525839Speter	    else
75625839Speter		buf->last->next = data;
75725839Speter	    data->next = NULL;
75825839Speter	    buf->last = data;
75925839Speter
76025839Speter	    data->bufp = data->text;
76125839Speter	    data->size = 0;
76225839Speter	}
76325839Speter
76425839Speter	get = ((buf->last->text + BUFFER_DATA_SIZE)
76525839Speter	       - (buf->last->bufp + buf->last->size));
76625839Speter
76725839Speter	status = (*buf->input) (buf->closure,
76825839Speter				buf->last->bufp + buf->last->size,
76925839Speter				0, get, &nbytes);
77025839Speter	if (status != 0)
77125839Speter	    return status;
77225839Speter
77325839Speter	buf->last->size += nbytes;
77425839Speter	if (countp != NULL)
77525839Speter	    *countp += nbytes;
77625839Speter
77725839Speter	if (nbytes < get)
77825839Speter	{
77925839Speter	    /* If we did not fill the buffer, then presumably we read
78025839Speter               all the available data.  */
78125839Speter	    return 0;
78225839Speter	}
78325839Speter    }
78425839Speter
78525839Speter    /*NOTREACHED*/
78625839Speter}
78725839Speter
78825839Speter/*
78925839Speter * Read a line (characters up to a \012) from an input buffer.  (We
79025839Speter * use \012 rather than \n for the benefit of non Unix clients for
79125839Speter * which \n means something else).  This returns 0 on success, or -1
79225839Speter * on end of file, or -2 if out of memory, or an error code.  If it
79325839Speter * succeeds, it sets *LINE to an allocated buffer holding the contents
79425839Speter * of the line.  The trailing \012 is not included in the buffer.  If
79525839Speter * LENP is not NULL, then *LENP is set to the number of bytes read;
79625839Speter * strlen may not work, because there may be embedded null bytes.
79725839Speter */
79825839Speter
79925839Speterint
80025839Speterbuf_read_line (buf, line, lenp)
80125839Speter     struct buffer *buf;
80225839Speter     char **line;
80325839Speter     int *lenp;
80425839Speter{
80525839Speter    if (buf->input == NULL)
80625839Speter        abort ();
80725839Speter
80825839Speter    *line = NULL;
80925839Speter
81025839Speter    while (1)
81125839Speter    {
81225839Speter	int len, finallen = 0;
81325839Speter	struct buffer_data *data;
81425839Speter	char *nl;
81525839Speter
81625839Speter	/* See if there is a newline in BUF.  */
81725839Speter	len = 0;
81825839Speter	for (data = buf->data; data != NULL; data = data->next)
81925839Speter	{
82025839Speter	    nl = memchr (data->bufp, '\012', data->size);
82125839Speter	    if (nl != NULL)
82225839Speter	    {
82325839Speter	        finallen = nl - data->bufp;
82425839Speter	        len += finallen;
82525839Speter		break;
82625839Speter	    }
82725839Speter	    len += data->size;
82825839Speter	}
82925839Speter
83025839Speter	/* If we found a newline, copy the line into a memory buffer,
83125839Speter           and remove it from BUF.  */
83225839Speter	if (data != NULL)
83325839Speter	{
83425839Speter	    char *p;
83525839Speter	    struct buffer_data *nldata;
83625839Speter
837109660Speter	    p = xmalloc (len + 1);
83825839Speter	    if (p == NULL)
83925839Speter		return -2;
84025839Speter	    *line = p;
84125839Speter
84225839Speter	    nldata = data;
84325839Speter	    data = buf->data;
84425839Speter	    while (data != nldata)
84525839Speter	    {
84625839Speter		struct buffer_data *next;
84725839Speter
84825839Speter		memcpy (p, data->bufp, data->size);
84925839Speter		p += data->size;
85025839Speter		next = data->next;
85125839Speter		data->next = free_buffer_data;
85225839Speter		free_buffer_data = data;
85325839Speter		data = next;
85425839Speter	    }
85525839Speter
85625839Speter	    memcpy (p, data->bufp, finallen);
85725839Speter	    p[finallen] = '\0';
85825839Speter
85925839Speter	    data->size -= finallen + 1;
86025839Speter	    data->bufp = nl + 1;
86125839Speter	    buf->data = data;
86225839Speter
86325839Speter	    if (lenp != NULL)
86425839Speter	        *lenp = len;
86525839Speter
86625839Speter	    return 0;
86725839Speter	}
86825839Speter
86925839Speter	/* Read more data until we get a newline.  */
87025839Speter	while (1)
87125839Speter	{
87225839Speter	    int size, status, nbytes;
87325839Speter	    char *mem;
87425839Speter
87525839Speter	    if (buf->data == NULL
87625839Speter		|| (buf->last->bufp + buf->last->size
87725839Speter		    == buf->last->text + BUFFER_DATA_SIZE))
87825839Speter	    {
87925839Speter		data = get_buffer_data ();
88025839Speter		if (data == NULL)
88125839Speter		{
88225839Speter		    (*buf->memory_error) (buf);
88325839Speter		    return -2;
88425839Speter		}
88525839Speter
88625839Speter		if (buf->data == NULL)
88725839Speter		    buf->data = data;
88825839Speter		else
88925839Speter		    buf->last->next = data;
89025839Speter		data->next = NULL;
89125839Speter		buf->last = data;
89225839Speter
89325839Speter		data->bufp = data->text;
89425839Speter		data->size = 0;
89525839Speter	    }
89625839Speter
89725839Speter	    mem = buf->last->bufp + buf->last->size;
89825839Speter	    size = (buf->last->text + BUFFER_DATA_SIZE) - mem;
89925839Speter
90025839Speter	    /* We need to read at least 1 byte.  We can handle up to
90125839Speter               SIZE bytes.  This will only be efficient if the
90225839Speter               underlying communication stream does its own buffering,
90325839Speter               or is clever about getting more than 1 byte at a time.  */
90425839Speter	    status = (*buf->input) (buf->closure, mem, 1, size, &nbytes);
90525839Speter	    if (status != 0)
90625839Speter		return status;
90725839Speter
90825839Speter	    buf->last->size += nbytes;
90925839Speter
91025839Speter	    /* Optimize slightly to avoid an unnecessary call to
91125839Speter               memchr.  */
91225839Speter	    if (nbytes == 1)
91325839Speter	    {
91425839Speter		if (*mem == '\012')
91525839Speter		    break;
91625839Speter	    }
91725839Speter	    else
91825839Speter	    {
91925839Speter		if (memchr (mem, '\012', nbytes) != NULL)
92025839Speter		    break;
92125839Speter	    }
92225839Speter	}
92325839Speter    }
92425839Speter}
92525839Speter
92625839Speter/*
92725839Speter * Extract data from the input buffer BUF.  This will read up to WANT
92825839Speter * bytes from the buffer.  It will set *RETDATA to point at the bytes,
92925839Speter * and set *GOT to the number of bytes to be found there.  Any buffer
93025839Speter * call which uses BUF may change the contents of the buffer at *DATA,
93125839Speter * so the data should be fully processed before any further calls are
93225839Speter * made.  This returns 0 on success, or -1 on end of file, or -2 if
93325839Speter * out of memory, or an error code.
93425839Speter */
93525839Speter
93625839Speterint
93725839Speterbuf_read_data (buf, want, retdata, got)
93825839Speter     struct buffer *buf;
93925839Speter     int want;
94025839Speter     char **retdata;
94125839Speter     int *got;
94225839Speter{
94325839Speter    if (buf->input == NULL)
94425839Speter	abort ();
94525839Speter
94625839Speter    while (buf->data != NULL && buf->data->size == 0)
94725839Speter    {
94825839Speter	struct buffer_data *next;
94925839Speter
95025839Speter	next = buf->data->next;
95125839Speter	buf->data->next = free_buffer_data;
95225839Speter	free_buffer_data = buf->data;
95325839Speter	buf->data = next;
95425839Speter	if (next == NULL)
95525839Speter	    buf->last = NULL;
95625839Speter    }
95725839Speter
95825839Speter    if (buf->data == NULL)
95925839Speter    {
96025839Speter	struct buffer_data *data;
96125839Speter	int get, status, nbytes;
96225839Speter
96325839Speter	data = get_buffer_data ();
96425839Speter	if (data == NULL)
96525839Speter	{
96625839Speter	    (*buf->memory_error) (buf);
96725839Speter	    return -2;
96825839Speter	}
96925839Speter
97025839Speter	buf->data = data;
97125839Speter	buf->last = data;
97225839Speter	data->next = NULL;
97325839Speter	data->bufp = data->text;
97425839Speter	data->size = 0;
97525839Speter
97625839Speter	if (want < BUFFER_DATA_SIZE)
97725839Speter	    get = want;
97825839Speter	else
97925839Speter	    get = BUFFER_DATA_SIZE;
98025839Speter	status = (*buf->input) (buf->closure, data->bufp, get,
98125839Speter				BUFFER_DATA_SIZE, &nbytes);
98225839Speter	if (status != 0)
98325839Speter	    return status;
98425839Speter
98525839Speter	data->size = nbytes;
98625839Speter    }
98725839Speter
98825839Speter    *retdata = buf->data->bufp;
98925839Speter    if (want < buf->data->size)
99025839Speter    {
99125839Speter        *got = want;
99225839Speter	buf->data->size -= want;
99325839Speter	buf->data->bufp += want;
99425839Speter    }
99525839Speter    else
99625839Speter    {
99725839Speter        *got = buf->data->size;
99825839Speter	buf->data->size = 0;
99925839Speter    }
100025839Speter
100125839Speter    return 0;
100225839Speter}
100325839Speter
100425839Speter/*
100525839Speter * Copy lines from an input buffer to an output buffer.  This copies
100625839Speter * all complete lines (characters up to a newline) from INBUF to
100725839Speter * OUTBUF.  Each line in OUTBUF is preceded by the character COMMAND
100825839Speter * and a space.
100925839Speter */
101025839Speter
101125839Spetervoid
101225839Speterbuf_copy_lines (outbuf, inbuf, command)
101325839Speter     struct buffer *outbuf;
101425839Speter     struct buffer *inbuf;
101525839Speter     int command;
101625839Speter{
101725839Speter    while (1)
101825839Speter    {
101925839Speter	struct buffer_data *data;
102025839Speter	struct buffer_data *nldata;
102125839Speter	char *nl;
102225839Speter	int len;
102325839Speter
102425839Speter	/* See if there is a newline in INBUF.  */
102525839Speter	nldata = NULL;
102625839Speter	nl = NULL;
102725839Speter	for (data = inbuf->data; data != NULL; data = data->next)
102825839Speter	{
102925839Speter	    nl = memchr (data->bufp, '\n', data->size);
103025839Speter	    if (nl != NULL)
103125839Speter	    {
103225839Speter		nldata = data;
103325839Speter		break;
103425839Speter	    }
103525839Speter	}
103625839Speter
103725839Speter	if (nldata == NULL)
103825839Speter	{
103925839Speter	    /* There are no more lines in INBUF.  */
104025839Speter	    return;
104125839Speter	}
104225839Speter
104325839Speter	/* Put in the command.  */
104425839Speter	buf_append_char (outbuf, command);
104525839Speter	buf_append_char (outbuf, ' ');
104625839Speter
104725839Speter	if (inbuf->data != nldata)
104825839Speter	{
104925839Speter	    /*
105025839Speter	     * Simply move over all the buffers up to the one containing
105125839Speter	     * the newline.
105225839Speter	     */
105325839Speter	    for (data = inbuf->data; data->next != nldata; data = data->next)
105425839Speter		;
105525839Speter	    data->next = NULL;
105625839Speter	    buf_append_data (outbuf, inbuf->data, data);
105725839Speter	    inbuf->data = nldata;
105825839Speter	}
105925839Speter
106025839Speter	/*
106125839Speter	 * If the newline is at the very end of the buffer, just move
106225839Speter	 * the buffer onto OUTBUF.  Otherwise we must copy the data.
106325839Speter	 */
106425839Speter	len = nl + 1 - nldata->bufp;
106525839Speter	if (len == nldata->size)
106625839Speter	{
106725839Speter	    inbuf->data = nldata->next;
106825839Speter	    if (inbuf->data == NULL)
106925839Speter		inbuf->last = NULL;
107025839Speter
107125839Speter	    nldata->next = NULL;
107225839Speter	    buf_append_data (outbuf, nldata, nldata);
107325839Speter	}
107425839Speter	else
107525839Speter	{
107625839Speter	    buf_output (outbuf, nldata->bufp, len);
107725839Speter	    nldata->bufp += len;
107825839Speter	    nldata->size -= len;
107925839Speter	}
108025839Speter    }
108125839Speter}
108225839Speter
108325839Speter/*
108425839Speter * Copy counted data from one buffer to another.  The count is an
108525839Speter * integer, host size, host byte order (it is only used across a
108625839Speter * pipe).  If there is enough data, it should be moved over.  If there
108725839Speter * is not enough data, it should remain on the original buffer.  A
108825839Speter * negative count is a special case.  if one is seen, *SPECIAL is set
108925839Speter * to the (negative) count value and no additional data is gathered
109025839Speter * from the buffer; normally *SPECIAL is set to 0.  This function
109125839Speter * returns the number of bytes it needs to see in order to actually
109225839Speter * copy something over.
109325839Speter */
109425839Speter
109525839Speterint
109625839Speterbuf_copy_counted (outbuf, inbuf, special)
109725839Speter     struct buffer *outbuf;
109825839Speter     struct buffer *inbuf;
109925839Speter     int *special;
110025839Speter{
110125839Speter    *special = 0;
110225839Speter
110325839Speter    while (1)
110425839Speter    {
110525839Speter	struct buffer_data *data;
110625839Speter	int need;
110725839Speter	union
110825839Speter	{
110925839Speter	    char intbuf[sizeof (int)];
111025839Speter	    int i;
111125839Speter	} u;
111225839Speter	char *intp;
111325839Speter	int count;
111425839Speter	struct buffer_data *start;
111525839Speter	int startoff;
111625839Speter	struct buffer_data *stop;
111725839Speter	int stopwant;
111825839Speter
111925839Speter	/* See if we have enough bytes to figure out the count.  */
112025839Speter	need = sizeof (int);
112125839Speter	intp = u.intbuf;
112225839Speter	for (data = inbuf->data; data != NULL; data = data->next)
112325839Speter	{
112425839Speter	    if (data->size >= need)
112525839Speter	    {
112625839Speter		memcpy (intp, data->bufp, need);
112725839Speter		break;
112825839Speter	    }
112925839Speter	    memcpy (intp, data->bufp, data->size);
113025839Speter	    intp += data->size;
113125839Speter	    need -= data->size;
113225839Speter	}
113325839Speter	if (data == NULL)
113425839Speter	{
113525839Speter	    /* We don't have enough bytes to form an integer.  */
113625839Speter	    return need;
113725839Speter	}
113825839Speter
113925839Speter	count = u.i;
114025839Speter	start = data;
114125839Speter	startoff = need;
114225839Speter
114325839Speter	if (count < 0)
114425839Speter	{
114525839Speter	    /* A negative COUNT is a special case meaning that we
114625839Speter               don't need any further information.  */
114725839Speter	    stop = start;
114825839Speter	    stopwant = 0;
114925839Speter	}
115025839Speter	else
115125839Speter	{
115225839Speter	    /*
115325839Speter	     * We have an integer in COUNT.  We have gotten all the
115425839Speter	     * data from INBUF in all buffers before START, and we
115525839Speter	     * have gotten STARTOFF bytes from START.  See if we have
115625839Speter	     * enough bytes remaining in INBUF.
115725839Speter	     */
115825839Speter	    need = count - (start->size - startoff);
115925839Speter	    if (need <= 0)
116025839Speter	    {
116125839Speter		stop = start;
116225839Speter		stopwant = count;
116325839Speter	    }
116425839Speter	    else
116525839Speter	    {
116625839Speter		for (data = start->next; data != NULL; data = data->next)
116725839Speter		{
116825839Speter		    if (need <= data->size)
116925839Speter			break;
117025839Speter		    need -= data->size;
117125839Speter		}
117225839Speter		if (data == NULL)
117325839Speter		{
117425839Speter		    /* We don't have enough bytes.  */
117525839Speter		    return need;
117625839Speter		}
117725839Speter		stop = data;
117825839Speter		stopwant = need;
117925839Speter	    }
118025839Speter	}
118125839Speter
118225839Speter	/*
118325839Speter	 * We have enough bytes.  Free any buffers in INBUF before
118425839Speter	 * START, and remove STARTOFF bytes from START, so that we can
118525839Speter	 * forget about STARTOFF.
118625839Speter	 */
118725839Speter	start->bufp += startoff;
118825839Speter	start->size -= startoff;
118925839Speter
119025839Speter	if (start->size == 0)
119125839Speter	    start = start->next;
119225839Speter
119325839Speter	if (stop->size == stopwant)
119425839Speter	{
119525839Speter	    stop = stop->next;
119625839Speter	    stopwant = 0;
119725839Speter	}
119825839Speter
119925839Speter	while (inbuf->data != start)
120025839Speter	{
120125839Speter	    data = inbuf->data;
120225839Speter	    inbuf->data = data->next;
120325839Speter	    data->next = free_buffer_data;
120425839Speter	    free_buffer_data = data;
120525839Speter	}
120625839Speter
120725839Speter	/* If COUNT is negative, set *SPECIAL and get out now.  */
120825839Speter	if (count < 0)
120925839Speter	{
121025839Speter	    *special = count;
121125839Speter	    return 0;
121225839Speter	}
121325839Speter
121425839Speter	/*
121525839Speter	 * We want to copy over the bytes from START through STOP.  We
121625839Speter	 * only want STOPWANT bytes from STOP.
121725839Speter	 */
121825839Speter
121925839Speter	if (start != stop)
122025839Speter	{
122125839Speter	    /* Attach the buffers from START through STOP to OUTBUF.  */
122225839Speter	    for (data = start; data->next != stop; data = data->next)
122325839Speter		;
122425839Speter	    inbuf->data = stop;
122525839Speter	    data->next = NULL;
122625839Speter	    buf_append_data (outbuf, start, data);
122725839Speter	}
122825839Speter
122925839Speter	if (stopwant > 0)
123025839Speter	{
123125839Speter	    buf_output (outbuf, stop->bufp, stopwant);
123225839Speter	    stop->bufp += stopwant;
123325839Speter	    stop->size -= stopwant;
123425839Speter	}
123525839Speter    }
123625839Speter
123725839Speter    /*NOTREACHED*/
123825839Speter}
123925839Speter
124025839Speter/* Shut down a buffer.  This returns 0 on success, or an errno code.  */
124125839Speter
124225839Speterint
124325839Speterbuf_shutdown (buf)
124425839Speter     struct buffer *buf;
124525839Speter{
124625839Speter    if (buf->shutdown)
1247102840Speter	return (*buf->shutdown) (buf);
124825839Speter    return 0;
124925839Speter}
125025839Speter
1251128269Speter
1252128269Speter
125325839Speter/* The simplest type of buffer is one built on top of a stdio FILE.
125425839Speter   For simplicity, and because it is all that is required, we do not
125525839Speter   implement setting this type of buffer into nonblocking mode.  The
125625839Speter   closure field is just a FILE *.  */
125725839Speter
125825839Speterstatic int stdio_buffer_input PROTO((void *, char *, int, int, int *));
125925839Speterstatic int stdio_buffer_output PROTO((void *, const char *, int, int *));
126025839Speterstatic int stdio_buffer_flush PROTO((void *));
1261102840Speterstatic int stdio_buffer_shutdown PROTO((struct buffer *buf));
126225839Speter
1263128269Speter
1264128269Speter
126525839Speter/* Initialize a buffer built on a stdio FILE.  */
1266102840Speterstruct stdio_buffer_closure
1267102840Speter{
1268102840Speter    FILE *fp;
1269102840Speter    int child_pid;
1270102840Speter};
1271102840Speter
1272128269Speter
1273128269Speter
127432785Speterstruct buffer *
1275102840Speterstdio_buffer_initialize (fp, child_pid, input, memory)
127625839Speter     FILE *fp;
1277102840Speter     int child_pid;
127825839Speter     int input;
127925839Speter     void (*memory) PROTO((struct buffer *));
128025839Speter{
1281109660Speter    struct stdio_buffer_closure *bc = xmalloc (sizeof (*bc));
1282102840Speter
1283102840Speter    bc->fp = fp;
1284102840Speter    bc->child_pid = child_pid;
1285102840Speter
128625839Speter    return buf_initialize (input ? stdio_buffer_input : NULL,
128725839Speter			   input ? NULL : stdio_buffer_output,
128825839Speter			   input ? NULL : stdio_buffer_flush,
128925839Speter			   (int (*) PROTO((void *, int))) NULL,
1290102840Speter			   stdio_buffer_shutdown,
129125839Speter			   memory,
1292102840Speter			   (void *) bc);
129325839Speter}
129425839Speter
1295107487Speter/* Return the file associated with a stdio buffer. */
1296107487SpeterFILE *
1297107487Speterstdio_buffer_get_file (buf)
1298107487Speter    struct buffer *buf;
1299107487Speter{
1300107487Speter    struct stdio_buffer_closure *bc;
1301107487Speter
1302107487Speter    assert(buf->shutdown == stdio_buffer_shutdown);
1303107487Speter
1304107487Speter    bc = (struct stdio_buffer_closure *) buf->closure;
1305107487Speter
1306107487Speter    return(bc->fp);
1307107487Speter}
1308107487Speter
130925839Speter/* The buffer input function for a buffer built on a stdio FILE.  */
131025839Speter
131125839Speterstatic int
131225839Speterstdio_buffer_input (closure, data, need, size, got)
131325839Speter     void *closure;
131425839Speter     char *data;
131525839Speter     int need;
131625839Speter     int size;
131725839Speter     int *got;
131825839Speter{
1319102840Speter    struct stdio_buffer_closure *bc = (struct stdio_buffer_closure *) closure;
132025839Speter    int nbytes;
132125839Speter
132225839Speter    /* Since stdio does its own buffering, we don't worry about
132325839Speter       getting more bytes than we need.  */
132425839Speter
132525839Speter    if (need == 0 || need == 1)
132625839Speter    {
132725839Speter        int ch;
132825839Speter
1329102840Speter	ch = getc (bc->fp);
133025839Speter
133125839Speter	if (ch == EOF)
133225839Speter	{
1333102840Speter	    if (feof (bc->fp))
133425839Speter		return -1;
133525839Speter	    else if (errno == 0)
133625839Speter		return EIO;
133725839Speter	    else
133825839Speter		return errno;
133925839Speter	}
134025839Speter
134125839Speter	*data = ch;
134225839Speter	*got = 1;
134325839Speter	return 0;
134425839Speter    }
134525839Speter
1346102840Speter    nbytes = fread (data, 1, need, bc->fp);
134725839Speter
134825839Speter    if (nbytes == 0)
134925839Speter    {
135025839Speter	*got = 0;
1351102840Speter	if (feof (bc->fp))
135225839Speter	    return -1;
135325839Speter	else if (errno == 0)
135425839Speter	    return EIO;
135525839Speter	else
135625839Speter	    return errno;
135725839Speter    }
135825839Speter
135925839Speter    *got = nbytes;
136025839Speter
136125839Speter    return 0;
136225839Speter}
136325839Speter
136425839Speter/* The buffer output function for a buffer built on a stdio FILE.  */
136525839Speter
136625839Speterstatic int
136725839Speterstdio_buffer_output (closure, data, have, wrote)
136825839Speter     void *closure;
136925839Speter     const char *data;
137025839Speter     int have;
137125839Speter     int *wrote;
137225839Speter{
1373102840Speter    struct stdio_buffer_closure *bc = (struct stdio_buffer_closure *) closure;
137425839Speter
137525839Speter    *wrote = 0;
137625839Speter
137725839Speter    while (have > 0)
137825839Speter    {
137925839Speter	int nbytes;
138025839Speter
1381102840Speter	nbytes = fwrite (data, 1, have, bc->fp);
138225839Speter
138325839Speter	if (nbytes != have)
138425839Speter	{
138525839Speter	    if (errno == 0)
138625839Speter		return EIO;
138725839Speter	    else
138825839Speter		return errno;
138925839Speter	}
139025839Speter
139125839Speter	*wrote += nbytes;
139225839Speter	have -= nbytes;
139325839Speter	data += nbytes;
139425839Speter    }
139525839Speter
139625839Speter    return 0;
139725839Speter}
139825839Speter
1399128269Speter
1400128269Speter
140125839Speter/* The buffer flush function for a buffer built on a stdio FILE.  */
140225839Speterstatic int
140325839Speterstdio_buffer_flush (closure)
140425839Speter     void *closure;
140525839Speter{
1406102840Speter    struct stdio_buffer_closure *bc = (struct stdio_buffer_closure *) closure;
140725839Speter
1408102840Speter    if (fflush (bc->fp) != 0)
140925839Speter    {
141025839Speter	if (errno == 0)
141125839Speter	    return EIO;
141225839Speter	else
141325839Speter	    return errno;
141425839Speter    }
141525839Speter
141625839Speter    return 0;
141725839Speter}
141825839Speter
1419102840Speter
1420102840Speter
1421102840Speterstatic int
1422102840Speterstdio_buffer_shutdown (buf)
1423102840Speter    struct buffer *buf;
1424102840Speter{
1425128269Speter    struct stdio_buffer_closure *bc = buf->closure;
1426102840Speter    struct stat s;
1427175282Sobrien    int closefp, statted;
1428102840Speter
1429175282Sobrien    /* Must be a pipe or a socket. What could go wrong?
1430175282Sobrien     * Well, apparently for disconnected clients under AIX, the
1431175282Sobrien     * fstat() will return -1 on the server if the client has gone
1432175282Sobrien     * away.
1433175282Sobrien     */
1434175282Sobrien    if (fstat(fileno(bc->fp), &s) == -1) statted = 0;
1435175282Sobrien    else statted = 1;
1436175282Sobrien    closefp = statted;
1437102840Speter
1438102840Speter    /* Flush the buffer if we can */
1439102840Speter    if (buf->flush)
1440102840Speter    {
1441102840Speter	buf_flush (buf, 1);
1442102840Speter	buf->flush = NULL;
1443102840Speter    }
1444102840Speter
1445102840Speter    if (buf->input)
1446102840Speter    {
1447128269Speter	/* There used to be a check here for unread data in the buffer of on
1448128269Speter	 * the pipe, but it was deemed unnecessary and possibly dangerous.  In
1449128269Speter	 * some sense it could be second-guessing the caller who requested it
1450128269Speter	 * closed, as well.
1451128269Speter	 */
1452102840Speter
1453102840Speter# ifdef SHUTDOWN_SERVER
1454102840Speter	if (current_parsed_root->method != server_method)
1455102840Speter# endif
1456102840Speter# ifndef NO_SOCKET_TO_FD
1457102840Speter	{
1458102840Speter	    /* shutdown() sockets */
1459175282Sobrien	    if (statted && S_ISSOCK (s.st_mode))
1460128269Speter		shutdown (fileno (bc->fp), 0);
1461102840Speter	}
1462102840Speter# endif /* NO_SOCKET_TO_FD */
1463102840Speter# ifdef START_RSH_WITH_POPEN_RW
1464102840Speter	/* Can't be set with SHUTDOWN_SERVER defined */
1465102840Speter	else if (pclose (bc->fp) == EOF)
1466102840Speter	{
1467175282Sobrien	    error (0, errno, "closing connection to %s",
1468102840Speter		   current_parsed_root->hostname);
1469102840Speter	    closefp = 0;
1470102840Speter	}
1471102840Speter# endif /* START_RSH_WITH_POPEN_RW */
1472102840Speter
1473102840Speter	buf->input = NULL;
1474102840Speter    }
1475102840Speter    else if (buf->output)
1476102840Speter    {
1477102840Speter# ifdef SHUTDOWN_SERVER
1478102840Speter	/* FIXME:  Should have a SHUTDOWN_SERVER_INPUT &
1479102840Speter	 * SHUTDOWN_SERVER_OUTPUT
1480102840Speter	 */
1481102840Speter	if (current_parsed_root->method == server_method)
1482128269Speter	    SHUTDOWN_SERVER (fileno (bc->fp));
1483102840Speter	else
1484102840Speter# endif
1485102840Speter# ifndef NO_SOCKET_TO_FD
1486102840Speter	/* shutdown() sockets */
1487175282Sobrien	if (statted && S_ISSOCK (s.st_mode))
1488128269Speter	    shutdown (fileno (bc->fp), 1);
1489102840Speter# else
1490102840Speter	{
1491102840Speter	/* I'm not sure I like this empty block, but the alternative
1492102840Speter	 * is a another nested NO_SOCKET_TO_FD switch above.
1493102840Speter	 */
1494102840Speter	}
1495102840Speter# endif /* NO_SOCKET_TO_FD */
1496102840Speter
1497102840Speter	buf->output = NULL;
1498102840Speter    }
1499102840Speter
1500175282Sobrien    if (statted && closefp && fclose (bc->fp) == EOF)
1501128269Speter    {
1502175282Sobrien	if (server_active)
1503128269Speter	{
1504128269Speter            /* Syslog this? */
1505128269Speter	}
1506128269Speter# ifdef CLIENT_SUPPORT
1507175282Sobrien	/* We are already closing the connection.
1508175282Sobrien	 * On error, print a warning and try to
1509175282Sobrien	 * continue to avoid infinte loops.
1510175282Sobrien	 */
1511128269Speter	else
1512175282Sobrien            error (0, errno,
1513128269Speter                   "closing down connection to %s",
1514128269Speter                   current_parsed_root->hostname);
1515128269Speter# endif /* CLIENT_SUPPORT */
1516128269Speter    }
1517102840Speter
1518102840Speter    /* If we were talking to a process, make sure it exited */
1519128269Speter    if (bc->child_pid)
1520128269Speter    {
1521128269Speter	int w;
1522102840Speter
1523128269Speter	do
1524128269Speter	    w = waitpid (bc->child_pid, (int *) 0, 0);
1525128269Speter	while (w == -1 && errno == EINTR);
1526175282Sobrien
1527175282Sobrien	/* We are already closing the connection.
1528175282Sobrien	 * On error, print a warning and try to
1529175282Sobrien	 * continue to avoid infinte loops.
1530175282Sobrien	 */
1531128269Speter	if (w == -1)
1532175282Sobrien	    error (0, errno, "waiting for process %d", bc->child_pid);
1533128269Speter    }
1534102840Speter    return 0;
1535102840Speter}
1536102840Speter
1537102840Speter
1538102840Speter
153932785Speter/* Certain types of communication input and output data in packets,
154032785Speter   where each packet is translated in some fashion.  The packetizing
154132785Speter   buffer type supports that, given a buffer which handles lower level
154232785Speter   I/O and a routine to translate the data in a packet.
154332785Speter
154432785Speter   This code uses two bytes for the size of a packet, so packets are
154532785Speter   restricted to 65536 bytes in total.
154632785Speter
154732785Speter   The translation functions should just translate; they may not
154832785Speter   significantly increase or decrease the amount of data.  The actual
154932785Speter   size of the initial data is part of the translated data.  The
155032785Speter   output translation routine may add up to PACKET_SLOP additional
155132785Speter   bytes, and the input translation routine should shrink the data
155232785Speter   correspondingly.  */
155332785Speter
155432785Speter#define PACKET_SLOP (100)
155532785Speter
155632785Speter/* This structure is the closure field of a packetizing buffer.  */
155732785Speter
155832785Speterstruct packetizing_buffer
155932785Speter{
156032785Speter    /* The underlying buffer.  */
156132785Speter    struct buffer *buf;
156232785Speter    /* The input translation function.  Exactly one of inpfn and outfn
156332785Speter       will be NULL.  The input translation function should
156432785Speter       untranslate the data in INPUT, storing the result in OUTPUT.
156532785Speter       SIZE is the amount of data in INPUT, and is also the size of
156632785Speter       OUTPUT.  This should return 0 on success, or an errno code.  */
156732785Speter    int (*inpfn) PROTO((void *fnclosure, const char *input, char *output,
156832785Speter			int size));
156932785Speter    /* The output translation function.  This should translate the
157032785Speter       data in INPUT, storing the result in OUTPUT.  The first two
157132785Speter       bytes in INPUT will be the size of the data, and so will SIZE.
157232785Speter       This should set *TRANSLATED to the amount of translated data in
157332785Speter       OUTPUT.  OUTPUT is large enough to hold SIZE + PACKET_SLOP
157432785Speter       bytes.  This should return 0 on success, or an errno code.  */
157532785Speter    int (*outfn) PROTO((void *fnclosure, const char *input, char *output,
157632785Speter			int size, int *translated));
157732785Speter    /* A closure for the translation function.  */
157832785Speter    void *fnclosure;
157932785Speter    /* For an input buffer, we may have to buffer up data here.  */
158032785Speter    /* This is non-zero if the buffered data has been translated.
158132785Speter       Otherwise, the buffered data has not been translated, and starts
158232785Speter       with the two byte packet size.  */
158332785Speter    int translated;
158432785Speter    /* The amount of buffered data.  */
158532785Speter    int holdsize;
158632785Speter    /* The buffer allocated to hold the data.  */
158732785Speter    char *holdbuf;
158832785Speter    /* The size of holdbuf.  */
158932785Speter    int holdbufsize;
159032785Speter    /* If translated is set, we need another data pointer to track
159132785Speter       where we are in holdbuf.  If translated is clear, then this
159232785Speter       pointer is not used.  */
159332785Speter    char *holddata;
159432785Speter};
159532785Speter
159632785Speterstatic int packetizing_buffer_input PROTO((void *, char *, int, int, int *));
159732785Speterstatic int packetizing_buffer_output PROTO((void *, const char *, int, int *));
159832785Speterstatic int packetizing_buffer_flush PROTO((void *));
159932785Speterstatic int packetizing_buffer_block PROTO((void *, int));
1600102840Speterstatic int packetizing_buffer_shutdown PROTO((struct buffer *));
160132785Speter
160232785Speter/* Create a packetizing buffer.  */
160332785Speter
160432785Speterstruct buffer *
160532785Speterpacketizing_buffer_initialize (buf, inpfn, outfn, fnclosure, memory)
160632785Speter     struct buffer *buf;
160732785Speter     int (*inpfn) PROTO ((void *, const char *, char *, int));
160832785Speter     int (*outfn) PROTO ((void *, const char *, char *, int, int *));
160932785Speter     void *fnclosure;
161032785Speter     void (*memory) PROTO((struct buffer *));
161132785Speter{
161232785Speter    struct packetizing_buffer *pb;
161332785Speter
161432785Speter    pb = (struct packetizing_buffer *) xmalloc (sizeof *pb);
161532785Speter    memset (pb, 0, sizeof *pb);
161632785Speter
161732785Speter    pb->buf = buf;
161832785Speter    pb->inpfn = inpfn;
161932785Speter    pb->outfn = outfn;
162032785Speter    pb->fnclosure = fnclosure;
162132785Speter
162232785Speter    if (inpfn != NULL)
162332785Speter    {
162432785Speter	/* Add PACKET_SLOP to handle larger translated packets, and
162532785Speter           add 2 for the count.  This buffer is increased if
162632785Speter           necessary.  */
162732785Speter	pb->holdbufsize = BUFFER_DATA_SIZE + PACKET_SLOP + 2;
162832785Speter	pb->holdbuf = xmalloc (pb->holdbufsize);
162932785Speter    }
163032785Speter
163132785Speter    return buf_initialize (inpfn != NULL ? packetizing_buffer_input : NULL,
163232785Speter			   inpfn != NULL ? NULL : packetizing_buffer_output,
163332785Speter			   inpfn != NULL ? NULL : packetizing_buffer_flush,
163432785Speter			   packetizing_buffer_block,
163532785Speter			   packetizing_buffer_shutdown,
163632785Speter			   memory,
163732785Speter			   pb);
163832785Speter}
163932785Speter
164032785Speter/* Input data from a packetizing buffer.  */
164132785Speter
164232785Speterstatic int
164332785Speterpacketizing_buffer_input (closure, data, need, size, got)
164432785Speter     void *closure;
164532785Speter     char *data;
164632785Speter     int need;
164732785Speter     int size;
164832785Speter     int *got;
164932785Speter{
165032785Speter    struct packetizing_buffer *pb = (struct packetizing_buffer *) closure;
165132785Speter
165232785Speter    *got = 0;
165332785Speter
165432785Speter    if (pb->holdsize > 0 && pb->translated)
165532785Speter    {
165632785Speter	int copy;
165732785Speter
165832785Speter	copy = pb->holdsize;
165932785Speter
166032785Speter	if (copy > size)
166132785Speter	{
166232785Speter	    memcpy (data, pb->holddata, size);
166332785Speter	    pb->holdsize -= size;
166432785Speter	    pb->holddata += size;
166532785Speter	    *got = size;
166632785Speter	    return 0;
166732785Speter	}
166832785Speter
166932785Speter	memcpy (data, pb->holddata, copy);
167032785Speter	pb->holdsize = 0;
167132785Speter	pb->translated = 0;
167232785Speter
167332785Speter	data += copy;
167432785Speter	need -= copy;
167532785Speter	size -= copy;
167632785Speter	*got = copy;
167732785Speter    }
167832785Speter
167932785Speter    while (need > 0 || *got == 0)
168032785Speter    {
168132785Speter	int get, status, nread, count, tcount;
168232785Speter	char *bytes;
168332785Speter	char stackoutbuf[BUFFER_DATA_SIZE + PACKET_SLOP];
168432785Speter	char *inbuf, *outbuf;
168532785Speter
168632785Speter	/* If we don't already have the two byte count, get it.  */
168732785Speter	if (pb->holdsize < 2)
168832785Speter	{
168932785Speter	    get = 2 - pb->holdsize;
169032785Speter	    status = buf_read_data (pb->buf, get, &bytes, &nread);
169132785Speter	    if (status != 0)
169232785Speter	    {
169332785Speter		/* buf_read_data can return -2, but a buffer input
169432785Speter                   function is only supposed to return -1, 0, or an
169532785Speter                   error code.  */
169632785Speter		if (status == -2)
169732785Speter		    status = ENOMEM;
169832785Speter		return status;
169932785Speter	    }
170032785Speter
170132785Speter	    if (nread == 0)
170232785Speter	    {
170332785Speter		/* The buffer is in nonblocking mode, and we didn't
170432785Speter                   manage to read anything.  */
170532785Speter		return 0;
170632785Speter	    }
170732785Speter
170832785Speter	    if (get == 1)
170932785Speter		pb->holdbuf[1] = bytes[0];
171032785Speter	    else
171132785Speter	    {
171232785Speter		pb->holdbuf[0] = bytes[0];
171332785Speter		if (nread < 2)
171432785Speter		{
171532785Speter		    /* We only got one byte, but we needed two.  Stash
171632785Speter                       the byte we got, and try again.  */
171732785Speter		    pb->holdsize = 1;
171832785Speter		    continue;
171932785Speter		}
172032785Speter		pb->holdbuf[1] = bytes[1];
172132785Speter	    }
172232785Speter	    pb->holdsize = 2;
172332785Speter	}
172432785Speter
172532785Speter	/* Read the packet.  */
172632785Speter
172732785Speter	count = (((pb->holdbuf[0] & 0xff) << 8)
172832785Speter		 + (pb->holdbuf[1] & 0xff));
172932785Speter
173032785Speter	if (count + 2 > pb->holdbufsize)
173132785Speter	{
173232785Speter	    char *n;
173332785Speter
173432785Speter	    /* We didn't allocate enough space in the initialize
173532785Speter               function.  */
173632785Speter
1737109660Speter	    n = xrealloc (pb->holdbuf, count + 2);
173832785Speter	    if (n == NULL)
173932785Speter	    {
174032785Speter		(*pb->buf->memory_error) (pb->buf);
174132785Speter		return ENOMEM;
174232785Speter	    }
174332785Speter	    pb->holdbuf = n;
174432785Speter	    pb->holdbufsize = count + 2;
174532785Speter	}
174632785Speter
174732785Speter	get = count - (pb->holdsize - 2);
174832785Speter
174932785Speter	status = buf_read_data (pb->buf, get, &bytes, &nread);
175032785Speter	if (status != 0)
175132785Speter	{
175232785Speter	    /* buf_read_data can return -2, but a buffer input
175332785Speter               function is only supposed to return -1, 0, or an error
175432785Speter               code.  */
175532785Speter	    if (status == -2)
175632785Speter		status = ENOMEM;
175732785Speter	    return status;
175832785Speter	}
175932785Speter
176032785Speter	if (nread == 0)
176132785Speter	{
176232785Speter	    /* We did not get any data.  Presumably the buffer is in
176332785Speter               nonblocking mode.  */
176432785Speter	    return 0;
176532785Speter	}
176632785Speter
176732785Speter	if (nread < get)
176832785Speter	{
176932785Speter	    /* We did not get all the data we need to fill the packet.
177032785Speter               buf_read_data does not promise to return all the bytes
177132785Speter               requested, so we must try again.  */
177232785Speter	    memcpy (pb->holdbuf + pb->holdsize, bytes, nread);
177332785Speter	    pb->holdsize += nread;
177432785Speter	    continue;
177532785Speter	}
177632785Speter
177732785Speter	/* We have a complete untranslated packet of COUNT bytes.  */
177832785Speter
177932785Speter	if (pb->holdsize == 2)
178032785Speter	{
178132785Speter	    /* We just read the entire packet (the 2 bytes in
178232785Speter               PB->HOLDBUF are the size).  Save a memcpy by
178332785Speter               translating directly from BYTES.  */
178432785Speter	    inbuf = bytes;
178532785Speter	}
178632785Speter	else
178732785Speter	{
178832785Speter	    /* We already had a partial packet in PB->HOLDBUF.  We
178932785Speter               need to copy the new data over to make the input
179032785Speter               contiguous.  */
179132785Speter	    memcpy (pb->holdbuf + pb->holdsize, bytes, nread);
179232785Speter	    inbuf = pb->holdbuf + 2;
179332785Speter	}
179432785Speter
179532785Speter	if (count <= sizeof stackoutbuf)
179632785Speter	    outbuf = stackoutbuf;
179732785Speter	else
179832785Speter	{
1799109660Speter	    outbuf = xmalloc (count);
180032785Speter	    if (outbuf == NULL)
180132785Speter	    {
180232785Speter		(*pb->buf->memory_error) (pb->buf);
180332785Speter		return ENOMEM;
180432785Speter	    }
180532785Speter	}
180632785Speter
180732785Speter	status = (*pb->inpfn) (pb->fnclosure, inbuf, outbuf, count);
180832785Speter	if (status != 0)
180932785Speter	    return status;
181032785Speter
181132785Speter	/* The first two bytes in the translated buffer are the real
181232785Speter           length of the translated data.  */
181332785Speter	tcount = ((outbuf[0] & 0xff) << 8) + (outbuf[1] & 0xff);
181432785Speter
181532785Speter	if (tcount > count)
181632785Speter	    error (1, 0, "Input translation failure");
181732785Speter
181832785Speter	if (tcount > size)
181932785Speter	{
182032785Speter	    /* We have more data than the caller has provided space
182132785Speter               for.  We need to save some of it for the next call.  */
182232785Speter
182332785Speter	    memcpy (data, outbuf + 2, size);
182432785Speter	    *got += size;
182532785Speter
182632785Speter	    pb->holdsize = tcount - size;
182732785Speter	    memcpy (pb->holdbuf, outbuf + 2 + size, tcount - size);
182832785Speter	    pb->holddata = pb->holdbuf;
182932785Speter	    pb->translated = 1;
183032785Speter
183132785Speter	    if (outbuf != stackoutbuf)
183232785Speter		free (outbuf);
183332785Speter
183432785Speter	    return 0;
183532785Speter	}
183632785Speter
183732785Speter	memcpy (data, outbuf + 2, tcount);
183832785Speter
183932785Speter	if (outbuf != stackoutbuf)
184032785Speter	    free (outbuf);
184132785Speter
184232785Speter	pb->holdsize = 0;
184332785Speter
184432785Speter	data += tcount;
184532785Speter	need -= tcount;
184632785Speter	size -= tcount;
184732785Speter	*got += tcount;
184832785Speter    }
184932785Speter
185032785Speter    return 0;
185132785Speter}
185232785Speter
185332785Speter/* Output data to a packetizing buffer.  */
185432785Speter
185532785Speterstatic int
185632785Speterpacketizing_buffer_output (closure, data, have, wrote)
185732785Speter     void *closure;
185832785Speter     const char *data;
185932785Speter     int have;
186032785Speter     int *wrote;
186132785Speter{
186232785Speter    struct packetizing_buffer *pb = (struct packetizing_buffer *) closure;
186332785Speter    char inbuf[BUFFER_DATA_SIZE + 2];
186432785Speter    char stack_outbuf[BUFFER_DATA_SIZE + PACKET_SLOP + 4];
1865175282Sobrien    struct buffer_data *outdata = NULL;
186632785Speter    char *outbuf;
186732785Speter    int size, status, translated;
186832785Speter
186932785Speter    if (have > BUFFER_DATA_SIZE)
187032785Speter    {
1871109660Speter	/* It would be easy to xmalloc a buffer, but I don't think this
187232785Speter           case can ever arise.  */
187332785Speter	abort ();
187432785Speter    }
187532785Speter
187632785Speter    inbuf[0] = (have >> 8) & 0xff;
187732785Speter    inbuf[1] = have & 0xff;
187832785Speter    memcpy (inbuf + 2, data, have);
187932785Speter
188032785Speter    size = have + 2;
188132785Speter
188232785Speter    /* The output function is permitted to add up to PACKET_SLOP
188332785Speter       bytes, and we need 2 bytes for the size of the translated data.
188432785Speter       If we can guarantee that the result will fit in a buffer_data,
188532785Speter       we translate directly into one to avoid a memcpy in buf_output.  */
188632785Speter    if (size + PACKET_SLOP + 2 > BUFFER_DATA_SIZE)
188732785Speter	outbuf = stack_outbuf;
188832785Speter    else
188932785Speter    {
189032785Speter	outdata = get_buffer_data ();
189132785Speter	if (outdata == NULL)
189232785Speter	{
189332785Speter	    (*pb->buf->memory_error) (pb->buf);
189432785Speter	    return ENOMEM;
189532785Speter	}
189632785Speter
189732785Speter	outdata->next = NULL;
189832785Speter	outdata->bufp = outdata->text;
189932785Speter
190032785Speter	outbuf = outdata->text;
190132785Speter    }
190232785Speter
190332785Speter    status = (*pb->outfn) (pb->fnclosure, inbuf, outbuf + 2, size,
190432785Speter			   &translated);
190532785Speter    if (status != 0)
190632785Speter	return status;
190732785Speter
190832785Speter    /* The output function is permitted to add up to PACKET_SLOP
190932785Speter       bytes.  */
191032785Speter    if (translated > size + PACKET_SLOP)
191132785Speter	abort ();
191232785Speter
191332785Speter    outbuf[0] = (translated >> 8) & 0xff;
191432785Speter    outbuf[1] = translated & 0xff;
191532785Speter
191632785Speter    if (outbuf == stack_outbuf)
191732785Speter	buf_output (pb->buf, outbuf, translated + 2);
191832785Speter    else
191932785Speter    {
1920175282Sobrien	/* if ((have + PACKET_SLOP + 4) > BUFFER_DATA_SIZE), then
1921175282Sobrien	   outdata may be NULL. */
1922175282Sobrien	if (outdata == NULL)
1923175282Sobrien	    abort ();
1924175282Sobrien
192532785Speter	outdata->size = translated + 2;
192632785Speter	buf_append_data (pb->buf, outdata, outdata);
192732785Speter    }
192832785Speter
192932785Speter    *wrote = have;
193032785Speter
193132785Speter    /* We will only be here because buf_send_output was called on the
193232785Speter       packetizing buffer.  That means that we should now call
193332785Speter       buf_send_output on the underlying buffer.  */
193432785Speter    return buf_send_output (pb->buf);
193532785Speter}
193632785Speter
1937128269Speter
1938128269Speter
193932785Speter/* Flush data to a packetizing buffer.  */
194032785Speterstatic int
194132785Speterpacketizing_buffer_flush (closure)
194232785Speter     void *closure;
194332785Speter{
194432785Speter    struct packetizing_buffer *pb = (struct packetizing_buffer *) closure;
194532785Speter
194632785Speter    /* Flush the underlying buffer.  Note that if the original call to
194732785Speter       buf_flush passed 1 for the BLOCK argument, then the buffer will
194832785Speter       already have been set into blocking mode, so we should always
194932785Speter       pass 0 here.  */
195032785Speter    return buf_flush (pb->buf, 0);
195132785Speter}
195232785Speter
1953128269Speter
1954128269Speter
195532785Speter/* The block routine for a packetizing buffer.  */
195632785Speterstatic int
195732785Speterpacketizing_buffer_block (closure, block)
195832785Speter     void *closure;
195932785Speter     int block;
196032785Speter{
196132785Speter    struct packetizing_buffer *pb = (struct packetizing_buffer *) closure;
196232785Speter
196332785Speter    if (block)
196432785Speter	return set_block (pb->buf);
196532785Speter    else
196632785Speter	return set_nonblock (pb->buf);
196732785Speter}
196832785Speter
196932785Speter/* Shut down a packetizing buffer.  */
197032785Speter
197132785Speterstatic int
1972102840Speterpacketizing_buffer_shutdown (buf)
1973102840Speter    struct buffer *buf;
197432785Speter{
1975102840Speter    struct packetizing_buffer *pb = (struct packetizing_buffer *) buf->closure;
197632785Speter
197732785Speter    return buf_shutdown (pb->buf);
197832785Speter}
197932785Speter
198025839Speter#endif /* defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT) */
1981