xref: /dragonfly/contrib/cvs-1.12/src/buffer.c (revision 86d7f5d3)
1*86d7f5d3SJohn Marino /*
2*86d7f5d3SJohn Marino  * Copyright (C) 1996-2005 The Free Software Foundation, Inc.
3*86d7f5d3SJohn Marino  *
4*86d7f5d3SJohn Marino  * This program is free software; you can redistribute it and/or modify
5*86d7f5d3SJohn Marino  * it under the terms of the GNU General Public License as published by
6*86d7f5d3SJohn Marino  * the Free Software Foundation; either version 2, or (at your option)
7*86d7f5d3SJohn Marino  * any later version.
8*86d7f5d3SJohn Marino  *
9*86d7f5d3SJohn Marino  * This program is distributed in the hope that it will be useful,
10*86d7f5d3SJohn Marino  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11*86d7f5d3SJohn Marino  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12*86d7f5d3SJohn Marino  * GNU General Public License for more details.
13*86d7f5d3SJohn Marino  */
14*86d7f5d3SJohn Marino 
15*86d7f5d3SJohn Marino /* Code for the buffer data structure.  */
16*86d7f5d3SJohn Marino 
17*86d7f5d3SJohn Marino #include "cvs.h"
18*86d7f5d3SJohn Marino #include "buffer.h"
19*86d7f5d3SJohn Marino #include "pagealign_alloc.h"
20*86d7f5d3SJohn Marino 
21*86d7f5d3SJohn Marino #if defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT)
22*86d7f5d3SJohn Marino 
23*86d7f5d3SJohn Marino # include <sys/socket.h>
24*86d7f5d3SJohn Marino 
25*86d7f5d3SJohn Marino /* OS/2 doesn't have EIO.  FIXME: this whole notion of turning
26*86d7f5d3SJohn Marino    a different error into EIO strikes me as pretty dubious.  */
27*86d7f5d3SJohn Marino # if !defined( EIO )
28*86d7f5d3SJohn Marino #   define EIO EBADPOS
29*86d7f5d3SJohn Marino # endif
30*86d7f5d3SJohn Marino 
31*86d7f5d3SJohn Marino /* Local functions.  */
32*86d7f5d3SJohn Marino static void buf_default_memory_error (struct buffer *);
33*86d7f5d3SJohn Marino static struct buffer_data *get_buffer_data (void);
34*86d7f5d3SJohn Marino 
35*86d7f5d3SJohn Marino 
36*86d7f5d3SJohn Marino 
37*86d7f5d3SJohn Marino /* Initialize a buffer structure.  */
38*86d7f5d3SJohn Marino struct buffer *
buf_initialize(type_buf_input input,type_buf_output output,type_buf_flush flush,type_buf_block block,type_buf_get_fd get_fd,type_buf_shutdown shutdown,type_buf_memory_error memory_error,void * closure)39*86d7f5d3SJohn Marino buf_initialize (type_buf_input input,
40*86d7f5d3SJohn Marino                 type_buf_output output,
41*86d7f5d3SJohn Marino                 type_buf_flush flush,
42*86d7f5d3SJohn Marino                 type_buf_block block,
43*86d7f5d3SJohn Marino                 type_buf_get_fd get_fd,
44*86d7f5d3SJohn Marino                 type_buf_shutdown shutdown,
45*86d7f5d3SJohn Marino                 type_buf_memory_error memory_error,
46*86d7f5d3SJohn Marino                 void *closure)
47*86d7f5d3SJohn Marino {
48*86d7f5d3SJohn Marino     struct buffer *buf;
49*86d7f5d3SJohn Marino 
50*86d7f5d3SJohn Marino     buf = xmalloc (sizeof (struct buffer));
51*86d7f5d3SJohn Marino     buf->data = NULL;
52*86d7f5d3SJohn Marino     buf->last = NULL;
53*86d7f5d3SJohn Marino     buf->nonblocking = false;
54*86d7f5d3SJohn Marino     buf->input = input;
55*86d7f5d3SJohn Marino     buf->output = output;
56*86d7f5d3SJohn Marino     buf->flush = flush;
57*86d7f5d3SJohn Marino     buf->block = block;
58*86d7f5d3SJohn Marino     buf->get_fd = get_fd;
59*86d7f5d3SJohn Marino     buf->shutdown = shutdown;
60*86d7f5d3SJohn Marino     buf->memory_error = memory_error ? memory_error : buf_default_memory_error;
61*86d7f5d3SJohn Marino     buf->closure = closure;
62*86d7f5d3SJohn Marino     return buf;
63*86d7f5d3SJohn Marino }
64*86d7f5d3SJohn Marino 
65*86d7f5d3SJohn Marino 
66*86d7f5d3SJohn Marino 
67*86d7f5d3SJohn Marino /* Free a buffer structure.  */
68*86d7f5d3SJohn Marino void
buf_free(struct buffer * buf)69*86d7f5d3SJohn Marino buf_free (struct buffer *buf)
70*86d7f5d3SJohn Marino {
71*86d7f5d3SJohn Marino     if (buf->closure != NULL)
72*86d7f5d3SJohn Marino     {
73*86d7f5d3SJohn Marino 	free (buf->closure);
74*86d7f5d3SJohn Marino 	buf->closure = NULL;
75*86d7f5d3SJohn Marino     }
76*86d7f5d3SJohn Marino     buf_free_data (buf);
77*86d7f5d3SJohn Marino     free (buf);
78*86d7f5d3SJohn Marino }
79*86d7f5d3SJohn Marino 
80*86d7f5d3SJohn Marino 
81*86d7f5d3SJohn Marino 
82*86d7f5d3SJohn Marino /* Initialize a buffer structure which is not to be used for I/O.  */
83*86d7f5d3SJohn Marino struct buffer *
buf_nonio_initialize(void (* memory)(struct buffer *))84*86d7f5d3SJohn Marino buf_nonio_initialize( void (*memory) (struct buffer *) )
85*86d7f5d3SJohn Marino {
86*86d7f5d3SJohn Marino     return buf_initialize (NULL, NULL, NULL, NULL, NULL, NULL, memory, NULL);
87*86d7f5d3SJohn Marino }
88*86d7f5d3SJohn Marino 
89*86d7f5d3SJohn Marino 
90*86d7f5d3SJohn Marino 
91*86d7f5d3SJohn Marino /* Default memory error handler.  */
92*86d7f5d3SJohn Marino static void
buf_default_memory_error(struct buffer * buf)93*86d7f5d3SJohn Marino buf_default_memory_error (struct buffer *buf)
94*86d7f5d3SJohn Marino {
95*86d7f5d3SJohn Marino     error (1, 0, "out of memory");
96*86d7f5d3SJohn Marino }
97*86d7f5d3SJohn Marino 
98*86d7f5d3SJohn Marino 
99*86d7f5d3SJohn Marino 
100*86d7f5d3SJohn Marino /* Allocate more buffer_data structures.  */
101*86d7f5d3SJohn Marino /* Get a new buffer_data structure.  */
102*86d7f5d3SJohn Marino static struct buffer_data *
get_buffer_data(void)103*86d7f5d3SJohn Marino get_buffer_data (void)
104*86d7f5d3SJohn Marino {
105*86d7f5d3SJohn Marino     struct buffer_data *ret;
106*86d7f5d3SJohn Marino 
107*86d7f5d3SJohn Marino     ret = xmalloc (sizeof (struct buffer_data));
108*86d7f5d3SJohn Marino     ret->text = pagealign_xalloc (BUFFER_DATA_SIZE);
109*86d7f5d3SJohn Marino 
110*86d7f5d3SJohn Marino     return ret;
111*86d7f5d3SJohn Marino }
112*86d7f5d3SJohn Marino 
113*86d7f5d3SJohn Marino 
114*86d7f5d3SJohn Marino 
115*86d7f5d3SJohn Marino /* See whether a buffer and its file descriptor is empty.  */
116*86d7f5d3SJohn Marino int
buf_empty(buf)117*86d7f5d3SJohn Marino buf_empty (buf)
118*86d7f5d3SJohn Marino     struct buffer *buf;
119*86d7f5d3SJohn Marino {
120*86d7f5d3SJohn Marino 	/* Try and read any data on the file descriptor first.
121*86d7f5d3SJohn Marino 	 * We already know the descriptor is non-blocking.
122*86d7f5d3SJohn Marino 	 */
123*86d7f5d3SJohn Marino 	buf_input_data (buf, NULL);
124*86d7f5d3SJohn Marino 	return buf_empty_p (buf);
125*86d7f5d3SJohn Marino }
126*86d7f5d3SJohn Marino 
127*86d7f5d3SJohn Marino 
128*86d7f5d3SJohn Marino 
129*86d7f5d3SJohn Marino /* See whether a buffer is empty.  */
130*86d7f5d3SJohn Marino int
buf_empty_p(struct buffer * buf)131*86d7f5d3SJohn Marino buf_empty_p (struct buffer *buf)
132*86d7f5d3SJohn Marino {
133*86d7f5d3SJohn Marino     struct buffer_data *data;
134*86d7f5d3SJohn Marino 
135*86d7f5d3SJohn Marino     for (data = buf->data; data != NULL; data = data->next)
136*86d7f5d3SJohn Marino 	if (data->size > 0)
137*86d7f5d3SJohn Marino 	    return 0;
138*86d7f5d3SJohn Marino     return 1;
139*86d7f5d3SJohn Marino }
140*86d7f5d3SJohn Marino 
141*86d7f5d3SJohn Marino 
142*86d7f5d3SJohn Marino 
143*86d7f5d3SJohn Marino # if defined (SERVER_FLOWCONTROL) || defined (PROXY_SUPPORT)
144*86d7f5d3SJohn Marino /*
145*86d7f5d3SJohn Marino  * Count how much data is stored in the buffer..
146*86d7f5d3SJohn Marino  * Note that each buffer is a xmalloc'ed chunk BUFFER_DATA_SIZE.
147*86d7f5d3SJohn Marino  */
148*86d7f5d3SJohn Marino int
buf_count_mem(struct buffer * buf)149*86d7f5d3SJohn Marino buf_count_mem (struct buffer *buf)
150*86d7f5d3SJohn Marino {
151*86d7f5d3SJohn Marino     struct buffer_data *data;
152*86d7f5d3SJohn Marino     int mem = 0;
153*86d7f5d3SJohn Marino 
154*86d7f5d3SJohn Marino     for (data = buf->data; data != NULL; data = data->next)
155*86d7f5d3SJohn Marino 	mem += BUFFER_DATA_SIZE;
156*86d7f5d3SJohn Marino 
157*86d7f5d3SJohn Marino     return mem;
158*86d7f5d3SJohn Marino }
159*86d7f5d3SJohn Marino # endif /* SERVER_FLOWCONTROL || PROXY_SUPPORT */
160*86d7f5d3SJohn Marino 
161*86d7f5d3SJohn Marino 
162*86d7f5d3SJohn Marino 
163*86d7f5d3SJohn Marino /* Add data DATA of length LEN to BUF.  */
164*86d7f5d3SJohn Marino void
buf_output(struct buffer * buf,const char * data,size_t len)165*86d7f5d3SJohn Marino buf_output (struct buffer *buf, const char *data, size_t len)
166*86d7f5d3SJohn Marino {
167*86d7f5d3SJohn Marino     if (buf->data != NULL
168*86d7f5d3SJohn Marino 	&& (((buf->last->text + BUFFER_DATA_SIZE)
169*86d7f5d3SJohn Marino 	     - (buf->last->bufp + buf->last->size))
170*86d7f5d3SJohn Marino 	    >= len))
171*86d7f5d3SJohn Marino     {
172*86d7f5d3SJohn Marino 	memcpy (buf->last->bufp + buf->last->size, data, len);
173*86d7f5d3SJohn Marino 	buf->last->size += len;
174*86d7f5d3SJohn Marino 	return;
175*86d7f5d3SJohn Marino     }
176*86d7f5d3SJohn Marino 
177*86d7f5d3SJohn Marino     while (1)
178*86d7f5d3SJohn Marino     {
179*86d7f5d3SJohn Marino 	struct buffer_data *newdata;
180*86d7f5d3SJohn Marino 
181*86d7f5d3SJohn Marino 	newdata = get_buffer_data ();
182*86d7f5d3SJohn Marino 	if (newdata == NULL)
183*86d7f5d3SJohn Marino 	{
184*86d7f5d3SJohn Marino 	    (*buf->memory_error) (buf);
185*86d7f5d3SJohn Marino 	    return;
186*86d7f5d3SJohn Marino 	}
187*86d7f5d3SJohn Marino 
188*86d7f5d3SJohn Marino 	if (buf->data == NULL)
189*86d7f5d3SJohn Marino 	    buf->data = newdata;
190*86d7f5d3SJohn Marino 	else
191*86d7f5d3SJohn Marino 	    buf->last->next = newdata;
192*86d7f5d3SJohn Marino 	newdata->next = NULL;
193*86d7f5d3SJohn Marino 	buf->last = newdata;
194*86d7f5d3SJohn Marino 
195*86d7f5d3SJohn Marino 	newdata->bufp = newdata->text;
196*86d7f5d3SJohn Marino 
197*86d7f5d3SJohn Marino 	if (len <= BUFFER_DATA_SIZE)
198*86d7f5d3SJohn Marino 	{
199*86d7f5d3SJohn Marino 	    newdata->size = len;
200*86d7f5d3SJohn Marino 	    memcpy (newdata->text, data, len);
201*86d7f5d3SJohn Marino 	    return;
202*86d7f5d3SJohn Marino 	}
203*86d7f5d3SJohn Marino 
204*86d7f5d3SJohn Marino 	newdata->size = BUFFER_DATA_SIZE;
205*86d7f5d3SJohn Marino 	memcpy (newdata->text, data, BUFFER_DATA_SIZE);
206*86d7f5d3SJohn Marino 
207*86d7f5d3SJohn Marino 	data += BUFFER_DATA_SIZE;
208*86d7f5d3SJohn Marino 	len -= BUFFER_DATA_SIZE;
209*86d7f5d3SJohn Marino     }
210*86d7f5d3SJohn Marino 
211*86d7f5d3SJohn Marino     /*NOTREACHED*/
212*86d7f5d3SJohn Marino }
213*86d7f5d3SJohn Marino 
214*86d7f5d3SJohn Marino 
215*86d7f5d3SJohn Marino 
216*86d7f5d3SJohn Marino /* Add a '\0' terminated string to BUF.  */
217*86d7f5d3SJohn Marino void
buf_output0(struct buffer * buf,const char * string)218*86d7f5d3SJohn Marino buf_output0 (struct buffer *buf, const char *string)
219*86d7f5d3SJohn Marino {
220*86d7f5d3SJohn Marino     buf_output (buf, string, strlen (string));
221*86d7f5d3SJohn Marino }
222*86d7f5d3SJohn Marino 
223*86d7f5d3SJohn Marino 
224*86d7f5d3SJohn Marino 
225*86d7f5d3SJohn Marino /* Add a single character to BUF.  */
226*86d7f5d3SJohn Marino void
buf_append_char(struct buffer * buf,int ch)227*86d7f5d3SJohn Marino buf_append_char (struct buffer *buf, int ch)
228*86d7f5d3SJohn Marino {
229*86d7f5d3SJohn Marino     if (buf->data != NULL
230*86d7f5d3SJohn Marino 	&& (buf->last->text + BUFFER_DATA_SIZE
231*86d7f5d3SJohn Marino 	    != buf->last->bufp + buf->last->size))
232*86d7f5d3SJohn Marino     {
233*86d7f5d3SJohn Marino 	*(buf->last->bufp + buf->last->size) = ch;
234*86d7f5d3SJohn Marino 	++buf->last->size;
235*86d7f5d3SJohn Marino     }
236*86d7f5d3SJohn Marino     else
237*86d7f5d3SJohn Marino     {
238*86d7f5d3SJohn Marino 	char b;
239*86d7f5d3SJohn Marino 
240*86d7f5d3SJohn Marino 	b = ch;
241*86d7f5d3SJohn Marino 	buf_output (buf, &b, 1);
242*86d7f5d3SJohn Marino     }
243*86d7f5d3SJohn Marino }
244*86d7f5d3SJohn Marino 
245*86d7f5d3SJohn Marino 
246*86d7f5d3SJohn Marino 
247*86d7f5d3SJohn Marino /* Free struct buffer_data's from the list starting with FIRST and ending at
248*86d7f5d3SJohn Marino  * LAST, inclusive.
249*86d7f5d3SJohn Marino  */
250*86d7f5d3SJohn Marino static inline void
buf_free_datas(struct buffer_data * first,struct buffer_data * last)251*86d7f5d3SJohn Marino buf_free_datas (struct buffer_data *first, struct buffer_data *last)
252*86d7f5d3SJohn Marino {
253*86d7f5d3SJohn Marino     struct buffer_data *b, *n, *p;
254*86d7f5d3SJohn Marino     b = first;
255*86d7f5d3SJohn Marino     do
256*86d7f5d3SJohn Marino     {
257*86d7f5d3SJohn Marino 	p = b;
258*86d7f5d3SJohn Marino 	n = b->next;
259*86d7f5d3SJohn Marino 	pagealign_free (b->text);
260*86d7f5d3SJohn Marino 	free (b);
261*86d7f5d3SJohn Marino 	b = n;
262*86d7f5d3SJohn Marino     } while (p != last);
263*86d7f5d3SJohn Marino }
264*86d7f5d3SJohn Marino 
265*86d7f5d3SJohn Marino 
266*86d7f5d3SJohn Marino 
267*86d7f5d3SJohn Marino /*
268*86d7f5d3SJohn Marino  * Send all the output we've been saving up.  Returns 0 for success or
269*86d7f5d3SJohn Marino  * errno code.  If the buffer has been set to be nonblocking, this
270*86d7f5d3SJohn Marino  * will just write until the write would block.
271*86d7f5d3SJohn Marino  */
272*86d7f5d3SJohn Marino int
buf_send_output(struct buffer * buf)273*86d7f5d3SJohn Marino buf_send_output (struct buffer *buf)
274*86d7f5d3SJohn Marino {
275*86d7f5d3SJohn Marino     assert (buf->output != NULL);
276*86d7f5d3SJohn Marino 
277*86d7f5d3SJohn Marino     while (buf->data != NULL)
278*86d7f5d3SJohn Marino     {
279*86d7f5d3SJohn Marino 	struct buffer_data *data;
280*86d7f5d3SJohn Marino 
281*86d7f5d3SJohn Marino 	data = buf->data;
282*86d7f5d3SJohn Marino 
283*86d7f5d3SJohn Marino 	if (data->size > 0)
284*86d7f5d3SJohn Marino 	{
285*86d7f5d3SJohn Marino 	    int status;
286*86d7f5d3SJohn Marino 	    size_t nbytes;
287*86d7f5d3SJohn Marino 
288*86d7f5d3SJohn Marino 	    status = (*buf->output) (buf->closure, data->bufp, data->size,
289*86d7f5d3SJohn Marino 				     &nbytes);
290*86d7f5d3SJohn Marino 	    if (status != 0)
291*86d7f5d3SJohn Marino 	    {
292*86d7f5d3SJohn Marino 		/* Some sort of error.  Discard the data, and return.  */
293*86d7f5d3SJohn Marino 		buf_free_data (buf);
294*86d7f5d3SJohn Marino 	        return status;
295*86d7f5d3SJohn Marino 	    }
296*86d7f5d3SJohn Marino 
297*86d7f5d3SJohn Marino 	    if (nbytes != data->size)
298*86d7f5d3SJohn Marino 	    {
299*86d7f5d3SJohn Marino 		/* Not all the data was written out.  This is only
300*86d7f5d3SJohn Marino                    permitted in nonblocking mode.  Adjust the buffer,
301*86d7f5d3SJohn Marino                    and return.  */
302*86d7f5d3SJohn Marino 
303*86d7f5d3SJohn Marino 		assert (buf->nonblocking);
304*86d7f5d3SJohn Marino 
305*86d7f5d3SJohn Marino 		data->size -= nbytes;
306*86d7f5d3SJohn Marino 		data->bufp += nbytes;
307*86d7f5d3SJohn Marino 
308*86d7f5d3SJohn Marino 		return 0;
309*86d7f5d3SJohn Marino 	    }
310*86d7f5d3SJohn Marino 	}
311*86d7f5d3SJohn Marino 
312*86d7f5d3SJohn Marino 	buf->data = data->next;
313*86d7f5d3SJohn Marino 	buf_free_datas (data, data);
314*86d7f5d3SJohn Marino     }
315*86d7f5d3SJohn Marino 
316*86d7f5d3SJohn Marino     buf->last = NULL;
317*86d7f5d3SJohn Marino 
318*86d7f5d3SJohn Marino     return 0;
319*86d7f5d3SJohn Marino }
320*86d7f5d3SJohn Marino 
321*86d7f5d3SJohn Marino 
322*86d7f5d3SJohn Marino 
323*86d7f5d3SJohn Marino /*
324*86d7f5d3SJohn Marino  * Flush any data queued up in the buffer.  If BLOCK is nonzero, then
325*86d7f5d3SJohn Marino  * if the buffer is in nonblocking mode, put it into blocking mode for
326*86d7f5d3SJohn Marino  * the duration of the flush.  This returns 0 on success, or an error
327*86d7f5d3SJohn Marino  * code.
328*86d7f5d3SJohn Marino  */
329*86d7f5d3SJohn Marino int
buf_flush(struct buffer * buf,bool block)330*86d7f5d3SJohn Marino buf_flush (struct buffer *buf, bool block)
331*86d7f5d3SJohn Marino {
332*86d7f5d3SJohn Marino     int nonblocking;
333*86d7f5d3SJohn Marino     int status;
334*86d7f5d3SJohn Marino 
335*86d7f5d3SJohn Marino     assert (buf->flush != NULL);
336*86d7f5d3SJohn Marino 
337*86d7f5d3SJohn Marino     nonblocking = buf->nonblocking;
338*86d7f5d3SJohn Marino     if (nonblocking && block)
339*86d7f5d3SJohn Marino     {
340*86d7f5d3SJohn Marino         status = set_block (buf);
341*86d7f5d3SJohn Marino 	if (status != 0)
342*86d7f5d3SJohn Marino 	    return status;
343*86d7f5d3SJohn Marino     }
344*86d7f5d3SJohn Marino 
345*86d7f5d3SJohn Marino     status = buf_send_output (buf);
346*86d7f5d3SJohn Marino     if (status == 0)
347*86d7f5d3SJohn Marino         status = (*buf->flush) (buf->closure);
348*86d7f5d3SJohn Marino 
349*86d7f5d3SJohn Marino     if (nonblocking && block)
350*86d7f5d3SJohn Marino     {
351*86d7f5d3SJohn Marino         int blockstat;
352*86d7f5d3SJohn Marino 
353*86d7f5d3SJohn Marino         blockstat = set_nonblock (buf);
354*86d7f5d3SJohn Marino 	if (status == 0)
355*86d7f5d3SJohn Marino 	    status = blockstat;
356*86d7f5d3SJohn Marino     }
357*86d7f5d3SJohn Marino 
358*86d7f5d3SJohn Marino     return status;
359*86d7f5d3SJohn Marino }
360*86d7f5d3SJohn Marino 
361*86d7f5d3SJohn Marino 
362*86d7f5d3SJohn Marino 
363*86d7f5d3SJohn Marino /*
364*86d7f5d3SJohn Marino  * Set buffer BUF to nonblocking I/O.  Returns 0 for success or errno
365*86d7f5d3SJohn Marino  * code.
366*86d7f5d3SJohn Marino  */
367*86d7f5d3SJohn Marino int
set_nonblock(struct buffer * buf)368*86d7f5d3SJohn Marino set_nonblock (struct buffer *buf)
369*86d7f5d3SJohn Marino {
370*86d7f5d3SJohn Marino     int status;
371*86d7f5d3SJohn Marino 
372*86d7f5d3SJohn Marino     if (buf->nonblocking)
373*86d7f5d3SJohn Marino 	return 0;
374*86d7f5d3SJohn Marino     assert (buf->block != NULL);
375*86d7f5d3SJohn Marino     status = (*buf->block) (buf->closure, 0);
376*86d7f5d3SJohn Marino     if (status != 0)
377*86d7f5d3SJohn Marino 	return status;
378*86d7f5d3SJohn Marino     buf->nonblocking = true;
379*86d7f5d3SJohn Marino     return 0;
380*86d7f5d3SJohn Marino }
381*86d7f5d3SJohn Marino 
382*86d7f5d3SJohn Marino 
383*86d7f5d3SJohn Marino 
384*86d7f5d3SJohn Marino /*
385*86d7f5d3SJohn Marino  * Set buffer BUF to blocking I/O.  Returns 0 for success or errno
386*86d7f5d3SJohn Marino  * code.
387*86d7f5d3SJohn Marino  */
388*86d7f5d3SJohn Marino int
set_block(struct buffer * buf)389*86d7f5d3SJohn Marino set_block (struct buffer *buf)
390*86d7f5d3SJohn Marino {
391*86d7f5d3SJohn Marino     int status;
392*86d7f5d3SJohn Marino 
393*86d7f5d3SJohn Marino     if (! buf->nonblocking)
394*86d7f5d3SJohn Marino 	return 0;
395*86d7f5d3SJohn Marino     assert (buf->block != NULL);
396*86d7f5d3SJohn Marino     status = (*buf->block) (buf->closure, 1);
397*86d7f5d3SJohn Marino     if (status != 0)
398*86d7f5d3SJohn Marino 	return status;
399*86d7f5d3SJohn Marino     buf->nonblocking = false;
400*86d7f5d3SJohn Marino     return 0;
401*86d7f5d3SJohn Marino }
402*86d7f5d3SJohn Marino 
403*86d7f5d3SJohn Marino 
404*86d7f5d3SJohn Marino 
405*86d7f5d3SJohn Marino /*
406*86d7f5d3SJohn Marino  * Send a character count and some output.  Returns errno code or 0 for
407*86d7f5d3SJohn Marino  * success.
408*86d7f5d3SJohn Marino  *
409*86d7f5d3SJohn Marino  * Sending the count in binary is OK since this is only used on a pipe
410*86d7f5d3SJohn Marino  * within the same system.
411*86d7f5d3SJohn Marino  */
412*86d7f5d3SJohn Marino int
buf_send_counted(struct buffer * buf)413*86d7f5d3SJohn Marino buf_send_counted (struct buffer *buf)
414*86d7f5d3SJohn Marino {
415*86d7f5d3SJohn Marino     int size;
416*86d7f5d3SJohn Marino     struct buffer_data *data;
417*86d7f5d3SJohn Marino 
418*86d7f5d3SJohn Marino     size = 0;
419*86d7f5d3SJohn Marino     for (data = buf->data; data != NULL; data = data->next)
420*86d7f5d3SJohn Marino 	size += data->size;
421*86d7f5d3SJohn Marino 
422*86d7f5d3SJohn Marino     data = get_buffer_data ();
423*86d7f5d3SJohn Marino     if (data == NULL)
424*86d7f5d3SJohn Marino     {
425*86d7f5d3SJohn Marino 	(*buf->memory_error) (buf);
426*86d7f5d3SJohn Marino 	return ENOMEM;
427*86d7f5d3SJohn Marino     }
428*86d7f5d3SJohn Marino 
429*86d7f5d3SJohn Marino     data->next = buf->data;
430*86d7f5d3SJohn Marino     buf->data = data;
431*86d7f5d3SJohn Marino     if (buf->last == NULL)
432*86d7f5d3SJohn Marino 	buf->last = data;
433*86d7f5d3SJohn Marino 
434*86d7f5d3SJohn Marino     data->bufp = data->text;
435*86d7f5d3SJohn Marino     data->size = sizeof (int);
436*86d7f5d3SJohn Marino 
437*86d7f5d3SJohn Marino     *((int *) data->text) = size;
438*86d7f5d3SJohn Marino 
439*86d7f5d3SJohn Marino     return buf_send_output (buf);
440*86d7f5d3SJohn Marino }
441*86d7f5d3SJohn Marino 
442*86d7f5d3SJohn Marino 
443*86d7f5d3SJohn Marino 
444*86d7f5d3SJohn Marino /*
445*86d7f5d3SJohn Marino  * Send a special count.  COUNT should be negative.  It will be
446*86d7f5d3SJohn Marino  * handled specially by buf_copy_counted.  This function returns 0 or
447*86d7f5d3SJohn Marino  * an errno code.
448*86d7f5d3SJohn Marino  *
449*86d7f5d3SJohn Marino  * Sending the count in binary is OK since this is only used on a pipe
450*86d7f5d3SJohn Marino  * within the same system.
451*86d7f5d3SJohn Marino  */
452*86d7f5d3SJohn Marino int
buf_send_special_count(struct buffer * buf,int count)453*86d7f5d3SJohn Marino buf_send_special_count (struct buffer *buf, int count)
454*86d7f5d3SJohn Marino {
455*86d7f5d3SJohn Marino     struct buffer_data *data;
456*86d7f5d3SJohn Marino 
457*86d7f5d3SJohn Marino     data = get_buffer_data ();
458*86d7f5d3SJohn Marino     if (data == NULL)
459*86d7f5d3SJohn Marino     {
460*86d7f5d3SJohn Marino 	(*buf->memory_error) (buf);
461*86d7f5d3SJohn Marino 	return ENOMEM;
462*86d7f5d3SJohn Marino     }
463*86d7f5d3SJohn Marino 
464*86d7f5d3SJohn Marino     data->next = buf->data;
465*86d7f5d3SJohn Marino     buf->data = data;
466*86d7f5d3SJohn Marino     if (buf->last == NULL)
467*86d7f5d3SJohn Marino 	buf->last = data;
468*86d7f5d3SJohn Marino 
469*86d7f5d3SJohn Marino     data->bufp = data->text;
470*86d7f5d3SJohn Marino     data->size = sizeof (int);
471*86d7f5d3SJohn Marino 
472*86d7f5d3SJohn Marino     *((int *) data->text) = count;
473*86d7f5d3SJohn Marino 
474*86d7f5d3SJohn Marino     return buf_send_output (buf);
475*86d7f5d3SJohn Marino }
476*86d7f5d3SJohn Marino 
477*86d7f5d3SJohn Marino 
478*86d7f5d3SJohn Marino 
479*86d7f5d3SJohn Marino /* Append a list of buffer_data structures to an buffer.  */
480*86d7f5d3SJohn Marino void
buf_append_data(struct buffer * buf,struct buffer_data * data,struct buffer_data * last)481*86d7f5d3SJohn Marino buf_append_data (struct buffer *buf, struct buffer_data *data,
482*86d7f5d3SJohn Marino                  struct buffer_data *last)
483*86d7f5d3SJohn Marino {
484*86d7f5d3SJohn Marino     if (data != NULL)
485*86d7f5d3SJohn Marino     {
486*86d7f5d3SJohn Marino 	if (buf->data == NULL)
487*86d7f5d3SJohn Marino 	    buf->data = data;
488*86d7f5d3SJohn Marino 	else
489*86d7f5d3SJohn Marino 	    buf->last->next = data;
490*86d7f5d3SJohn Marino 	buf->last = last;
491*86d7f5d3SJohn Marino     }
492*86d7f5d3SJohn Marino }
493*86d7f5d3SJohn Marino 
494*86d7f5d3SJohn Marino 
495*86d7f5d3SJohn Marino 
496*86d7f5d3SJohn Marino # ifdef PROXY_SUPPORT
497*86d7f5d3SJohn Marino /* Copy data structures and append them to a buffer.
498*86d7f5d3SJohn Marino  *
499*86d7f5d3SJohn Marino  * ERRORS
500*86d7f5d3SJohn Marino  *   Failure to allocate memory here is fatal.
501*86d7f5d3SJohn Marino  */
502*86d7f5d3SJohn Marino void
buf_copy_data(struct buffer * buf,struct buffer_data * data,struct buffer_data * last)503*86d7f5d3SJohn Marino buf_copy_data (struct buffer *buf, struct buffer_data *data,
504*86d7f5d3SJohn Marino                struct buffer_data *last)
505*86d7f5d3SJohn Marino {
506*86d7f5d3SJohn Marino     struct buffer_data *first, *new, *cur, *prev;
507*86d7f5d3SJohn Marino 
508*86d7f5d3SJohn Marino     assert (buf);
509*86d7f5d3SJohn Marino     assert (data);
510*86d7f5d3SJohn Marino 
511*86d7f5d3SJohn Marino     prev = first = NULL;
512*86d7f5d3SJohn Marino     cur = data;
513*86d7f5d3SJohn Marino     while (1)
514*86d7f5d3SJohn Marino     {
515*86d7f5d3SJohn Marino 	new = get_buffer_data ();
516*86d7f5d3SJohn Marino 	if (!new) error (1, errno, "Failed to allocate buffer data.");
517*86d7f5d3SJohn Marino 
518*86d7f5d3SJohn Marino 	if (!first) first = new;
519*86d7f5d3SJohn Marino 	memcpy (new->text, cur->bufp, cur->size);
520*86d7f5d3SJohn Marino 	new->bufp = new->text;
521*86d7f5d3SJohn Marino 	new->size = cur->size;
522*86d7f5d3SJohn Marino 	new->next = NULL;
523*86d7f5d3SJohn Marino 	if (prev) prev->next = new;
524*86d7f5d3SJohn Marino 	if (cur == last) break;
525*86d7f5d3SJohn Marino 	prev = new;
526*86d7f5d3SJohn Marino 	cur = cur->next;
527*86d7f5d3SJohn Marino     }
528*86d7f5d3SJohn Marino 
529*86d7f5d3SJohn Marino     buf_append_data (buf, first, new);
530*86d7f5d3SJohn Marino }
531*86d7f5d3SJohn Marino # endif /* PROXY_SUPPORT */
532*86d7f5d3SJohn Marino 
533*86d7f5d3SJohn Marino 
534*86d7f5d3SJohn Marino 
535*86d7f5d3SJohn Marino /* Dispose of any remaining data in the buffer.  */
536*86d7f5d3SJohn Marino void
buf_free_data(struct buffer * buffer)537*86d7f5d3SJohn Marino buf_free_data (struct buffer *buffer)
538*86d7f5d3SJohn Marino {
539*86d7f5d3SJohn Marino     if (buf_empty_p (buffer)) return;
540*86d7f5d3SJohn Marino     buf_free_datas (buffer->data, buffer->last);
541*86d7f5d3SJohn Marino     buffer->data = buffer->last = NULL;
542*86d7f5d3SJohn Marino }
543*86d7f5d3SJohn Marino 
544*86d7f5d3SJohn Marino 
545*86d7f5d3SJohn Marino 
546*86d7f5d3SJohn Marino /* Append the data in one buffer to another.  This removes the data
547*86d7f5d3SJohn Marino  * from the source buffer.
548*86d7f5d3SJohn Marino  */
549*86d7f5d3SJohn Marino void
buf_append_buffer(struct buffer * to,struct buffer * from)550*86d7f5d3SJohn Marino buf_append_buffer (struct buffer *to, struct buffer *from)
551*86d7f5d3SJohn Marino {
552*86d7f5d3SJohn Marino     struct buffer_data *n;
553*86d7f5d3SJohn Marino 
554*86d7f5d3SJohn Marino     /* Copy the data pointer to the new buf.  */
555*86d7f5d3SJohn Marino     buf_append_data (to, from->data, from->last);
556*86d7f5d3SJohn Marino 
557*86d7f5d3SJohn Marino     n = from->data;
558*86d7f5d3SJohn Marino     while (n)
559*86d7f5d3SJohn Marino     {
560*86d7f5d3SJohn Marino 	if (n == from->last) break;
561*86d7f5d3SJohn Marino 	n = n->next;
562*86d7f5d3SJohn Marino     }
563*86d7f5d3SJohn Marino 
564*86d7f5d3SJohn Marino     /* Remove from the original location.  */
565*86d7f5d3SJohn Marino     from->data = NULL;
566*86d7f5d3SJohn Marino     from->last = NULL;
567*86d7f5d3SJohn Marino }
568*86d7f5d3SJohn Marino 
569*86d7f5d3SJohn Marino 
570*86d7f5d3SJohn Marino 
571*86d7f5d3SJohn Marino /*
572*86d7f5d3SJohn Marino  * Copy the contents of file F into buffer_data structures.  We can't
573*86d7f5d3SJohn Marino  * copy directly into an buffer, because we want to handle failure and
574*86d7f5d3SJohn Marino  * success differently.  Returns 0 on success, or -2 if out of
575*86d7f5d3SJohn Marino  * memory, or a status code on error.  Since the caller happens to
576*86d7f5d3SJohn Marino  * know the size of the file, it is passed in as SIZE.  On success,
577*86d7f5d3SJohn Marino  * this function sets *RETP and *LASTP, which may be passed to
578*86d7f5d3SJohn Marino  * buf_append_data.
579*86d7f5d3SJohn Marino  */
580*86d7f5d3SJohn Marino int
buf_read_file(FILE * f,long int size,struct buffer_data ** retp,struct buffer_data ** lastp)581*86d7f5d3SJohn Marino buf_read_file (FILE *f, long int size, struct buffer_data **retp,
582*86d7f5d3SJohn Marino                struct buffer_data **lastp)
583*86d7f5d3SJohn Marino {
584*86d7f5d3SJohn Marino     int status;
585*86d7f5d3SJohn Marino 
586*86d7f5d3SJohn Marino     *retp = NULL;
587*86d7f5d3SJohn Marino     *lastp = NULL;
588*86d7f5d3SJohn Marino 
589*86d7f5d3SJohn Marino     while (size > 0)
590*86d7f5d3SJohn Marino     {
591*86d7f5d3SJohn Marino 	struct buffer_data *data;
592*86d7f5d3SJohn Marino 	int get;
593*86d7f5d3SJohn Marino 
594*86d7f5d3SJohn Marino 	data = get_buffer_data ();
595*86d7f5d3SJohn Marino 	if (data == NULL)
596*86d7f5d3SJohn Marino 	{
597*86d7f5d3SJohn Marino 	    status = -2;
598*86d7f5d3SJohn Marino 	    goto error_return;
599*86d7f5d3SJohn Marino 	}
600*86d7f5d3SJohn Marino 
601*86d7f5d3SJohn Marino 	if (*retp == NULL)
602*86d7f5d3SJohn Marino 	    *retp = data;
603*86d7f5d3SJohn Marino 	else
604*86d7f5d3SJohn Marino 	    (*lastp)->next = data;
605*86d7f5d3SJohn Marino 	data->next = NULL;
606*86d7f5d3SJohn Marino 	*lastp = data;
607*86d7f5d3SJohn Marino 
608*86d7f5d3SJohn Marino 	data->bufp = data->text;
609*86d7f5d3SJohn Marino 	data->size = 0;
610*86d7f5d3SJohn Marino 
611*86d7f5d3SJohn Marino 	if (size > BUFFER_DATA_SIZE)
612*86d7f5d3SJohn Marino 	    get = BUFFER_DATA_SIZE;
613*86d7f5d3SJohn Marino 	else
614*86d7f5d3SJohn Marino 	    get = size;
615*86d7f5d3SJohn Marino 
616*86d7f5d3SJohn Marino 	errno = EIO;
617*86d7f5d3SJohn Marino 	if (fread (data->text, get, 1, f) != 1)
618*86d7f5d3SJohn Marino 	{
619*86d7f5d3SJohn Marino 	    status = errno;
620*86d7f5d3SJohn Marino 	    goto error_return;
621*86d7f5d3SJohn Marino 	}
622*86d7f5d3SJohn Marino 
623*86d7f5d3SJohn Marino 	data->size += get;
624*86d7f5d3SJohn Marino 	size -= get;
625*86d7f5d3SJohn Marino     }
626*86d7f5d3SJohn Marino 
627*86d7f5d3SJohn Marino     return 0;
628*86d7f5d3SJohn Marino 
629*86d7f5d3SJohn Marino   error_return:
630*86d7f5d3SJohn Marino     if (*retp != NULL)
631*86d7f5d3SJohn Marino 	buf_free_datas (*retp, (*lastp)->next);
632*86d7f5d3SJohn Marino     return status;
633*86d7f5d3SJohn Marino }
634*86d7f5d3SJohn Marino 
635*86d7f5d3SJohn Marino 
636*86d7f5d3SJohn Marino 
637*86d7f5d3SJohn Marino /*
638*86d7f5d3SJohn Marino  * Copy the contents of file F into buffer_data structures.  We can't
639*86d7f5d3SJohn Marino  * copy directly into an buffer, because we want to handle failure and
640*86d7f5d3SJohn Marino  * success differently.  Returns 0 on success, or -2 if out of
641*86d7f5d3SJohn Marino  * memory, or a status code on error.  On success, this function sets
642*86d7f5d3SJohn Marino  * *RETP and *LASTP, which may be passed to buf_append_data.
643*86d7f5d3SJohn Marino  */
644*86d7f5d3SJohn Marino int
buf_read_file_to_eof(FILE * f,struct buffer_data ** retp,struct buffer_data ** lastp)645*86d7f5d3SJohn Marino buf_read_file_to_eof (FILE *f, struct buffer_data **retp,
646*86d7f5d3SJohn Marino                       struct buffer_data **lastp)
647*86d7f5d3SJohn Marino {
648*86d7f5d3SJohn Marino     int status;
649*86d7f5d3SJohn Marino 
650*86d7f5d3SJohn Marino     *retp = NULL;
651*86d7f5d3SJohn Marino     *lastp = NULL;
652*86d7f5d3SJohn Marino 
653*86d7f5d3SJohn Marino     while (!feof (f))
654*86d7f5d3SJohn Marino     {
655*86d7f5d3SJohn Marino 	struct buffer_data *data;
656*86d7f5d3SJohn Marino 	int get, nread;
657*86d7f5d3SJohn Marino 
658*86d7f5d3SJohn Marino 	data = get_buffer_data ();
659*86d7f5d3SJohn Marino 	if (data == NULL)
660*86d7f5d3SJohn Marino 	{
661*86d7f5d3SJohn Marino 	    status = -2;
662*86d7f5d3SJohn Marino 	    goto error_return;
663*86d7f5d3SJohn Marino 	}
664*86d7f5d3SJohn Marino 
665*86d7f5d3SJohn Marino 	if (*retp == NULL)
666*86d7f5d3SJohn Marino 	    *retp = data;
667*86d7f5d3SJohn Marino 	else
668*86d7f5d3SJohn Marino 	    (*lastp)->next = data;
669*86d7f5d3SJohn Marino 	data->next = NULL;
670*86d7f5d3SJohn Marino 	*lastp = data;
671*86d7f5d3SJohn Marino 
672*86d7f5d3SJohn Marino 	data->bufp = data->text;
673*86d7f5d3SJohn Marino 	data->size = 0;
674*86d7f5d3SJohn Marino 
675*86d7f5d3SJohn Marino 	get = BUFFER_DATA_SIZE;
676*86d7f5d3SJohn Marino 
677*86d7f5d3SJohn Marino 	errno = EIO;
678*86d7f5d3SJohn Marino 	nread = fread (data->text, 1, get, f);
679*86d7f5d3SJohn Marino 	if (nread == 0 && !feof (f))
680*86d7f5d3SJohn Marino 	{
681*86d7f5d3SJohn Marino 	    status = errno;
682*86d7f5d3SJohn Marino 	    goto error_return;
683*86d7f5d3SJohn Marino 	}
684*86d7f5d3SJohn Marino 
685*86d7f5d3SJohn Marino 	data->size = nread;
686*86d7f5d3SJohn Marino     }
687*86d7f5d3SJohn Marino 
688*86d7f5d3SJohn Marino     return 0;
689*86d7f5d3SJohn Marino 
690*86d7f5d3SJohn Marino   error_return:
691*86d7f5d3SJohn Marino     if (*retp != NULL)
692*86d7f5d3SJohn Marino 	buf_free_datas (*retp, (*lastp)->next);
693*86d7f5d3SJohn Marino     return status;
694*86d7f5d3SJohn Marino }
695*86d7f5d3SJohn Marino 
696*86d7f5d3SJohn Marino 
697*86d7f5d3SJohn Marino 
698*86d7f5d3SJohn Marino /* Return the number of bytes in a chain of buffer_data structures.  */
699*86d7f5d3SJohn Marino int
buf_chain_length(struct buffer_data * buf)700*86d7f5d3SJohn Marino buf_chain_length (struct buffer_data *buf)
701*86d7f5d3SJohn Marino {
702*86d7f5d3SJohn Marino     int size = 0;
703*86d7f5d3SJohn Marino     while (buf)
704*86d7f5d3SJohn Marino     {
705*86d7f5d3SJohn Marino 	size += buf->size;
706*86d7f5d3SJohn Marino 	buf = buf->next;
707*86d7f5d3SJohn Marino     }
708*86d7f5d3SJohn Marino     return size;
709*86d7f5d3SJohn Marino }
710*86d7f5d3SJohn Marino 
711*86d7f5d3SJohn Marino 
712*86d7f5d3SJohn Marino 
713*86d7f5d3SJohn Marino /* Return the number of bytes in a buffer.  */
714*86d7f5d3SJohn Marino int
buf_length(struct buffer * buf)715*86d7f5d3SJohn Marino buf_length (struct buffer *buf)
716*86d7f5d3SJohn Marino {
717*86d7f5d3SJohn Marino     return buf_chain_length (buf->data);
718*86d7f5d3SJohn Marino }
719*86d7f5d3SJohn Marino 
720*86d7f5d3SJohn Marino 
721*86d7f5d3SJohn Marino 
722*86d7f5d3SJohn Marino /*
723*86d7f5d3SJohn Marino  * Read an arbitrary amount of data into an input buffer.  The buffer
724*86d7f5d3SJohn Marino  * will be in nonblocking mode, and we just grab what we can.  Return
725*86d7f5d3SJohn Marino  * 0 on success, or -1 on end of file, or -2 if out of memory, or an
726*86d7f5d3SJohn Marino  * error code.  If COUNTP is not NULL, *COUNTP is set to the number of
727*86d7f5d3SJohn Marino  * bytes read.
728*86d7f5d3SJohn Marino  */
729*86d7f5d3SJohn Marino int
buf_input_data(struct buffer * buf,size_t * countp)730*86d7f5d3SJohn Marino buf_input_data (struct buffer *buf, size_t *countp)
731*86d7f5d3SJohn Marino {
732*86d7f5d3SJohn Marino     assert (buf->input != NULL);
733*86d7f5d3SJohn Marino 
734*86d7f5d3SJohn Marino     if (countp != NULL)
735*86d7f5d3SJohn Marino 	*countp = 0;
736*86d7f5d3SJohn Marino 
737*86d7f5d3SJohn Marino     while (1)
738*86d7f5d3SJohn Marino     {
739*86d7f5d3SJohn Marino 	int status;
740*86d7f5d3SJohn Marino 	size_t get, nbytes;
741*86d7f5d3SJohn Marino 
742*86d7f5d3SJohn Marino 	if (buf->data == NULL
743*86d7f5d3SJohn Marino 	    || (buf->last->bufp + buf->last->size
744*86d7f5d3SJohn Marino 		== buf->last->text + BUFFER_DATA_SIZE))
745*86d7f5d3SJohn Marino 	{
746*86d7f5d3SJohn Marino 	    struct buffer_data *data;
747*86d7f5d3SJohn Marino 
748*86d7f5d3SJohn Marino 	    data = get_buffer_data ();
749*86d7f5d3SJohn Marino 	    if (data == NULL)
750*86d7f5d3SJohn Marino 	    {
751*86d7f5d3SJohn Marino 		(*buf->memory_error) (buf);
752*86d7f5d3SJohn Marino 		return -2;
753*86d7f5d3SJohn Marino 	    }
754*86d7f5d3SJohn Marino 
755*86d7f5d3SJohn Marino 	    if (buf->data == NULL)
756*86d7f5d3SJohn Marino 		buf->data = data;
757*86d7f5d3SJohn Marino 	    else
758*86d7f5d3SJohn Marino 		buf->last->next = data;
759*86d7f5d3SJohn Marino 	    data->next = NULL;
760*86d7f5d3SJohn Marino 	    buf->last = data;
761*86d7f5d3SJohn Marino 
762*86d7f5d3SJohn Marino 	    data->bufp = data->text;
763*86d7f5d3SJohn Marino 	    data->size = 0;
764*86d7f5d3SJohn Marino 	}
765*86d7f5d3SJohn Marino 
766*86d7f5d3SJohn Marino 	get = ((buf->last->text + BUFFER_DATA_SIZE)
767*86d7f5d3SJohn Marino 	       - (buf->last->bufp + buf->last->size));
768*86d7f5d3SJohn Marino 
769*86d7f5d3SJohn Marino 	status = (*buf->input) (buf->closure,
770*86d7f5d3SJohn Marino 				buf->last->bufp + buf->last->size,
771*86d7f5d3SJohn Marino 				0, get, &nbytes);
772*86d7f5d3SJohn Marino 	if (status != 0)
773*86d7f5d3SJohn Marino 	    return status;
774*86d7f5d3SJohn Marino 
775*86d7f5d3SJohn Marino 	buf->last->size += nbytes;
776*86d7f5d3SJohn Marino 	if (countp != NULL)
777*86d7f5d3SJohn Marino 	    *countp += nbytes;
778*86d7f5d3SJohn Marino 
779*86d7f5d3SJohn Marino 	if (nbytes < get)
780*86d7f5d3SJohn Marino 	{
781*86d7f5d3SJohn Marino 	    /* If we did not fill the buffer, then presumably we read
782*86d7f5d3SJohn Marino                all the available data.  */
783*86d7f5d3SJohn Marino 	    return 0;
784*86d7f5d3SJohn Marino 	}
785*86d7f5d3SJohn Marino     }
786*86d7f5d3SJohn Marino 
787*86d7f5d3SJohn Marino     /*NOTREACHED*/
788*86d7f5d3SJohn Marino }
789*86d7f5d3SJohn Marino 
790*86d7f5d3SJohn Marino 
791*86d7f5d3SJohn Marino 
792*86d7f5d3SJohn Marino /*
793*86d7f5d3SJohn Marino  * Read a line (characters up to a \012) from an input buffer.  (We
794*86d7f5d3SJohn Marino  * use \012 rather than \n for the benefit of non Unix clients for
795*86d7f5d3SJohn Marino  * which \n means something else).  This returns 0 on success, or -1
796*86d7f5d3SJohn Marino  * on end of file, or -2 if out of memory, or an error code.  If it
797*86d7f5d3SJohn Marino  * succeeds, it sets *LINE to an allocated buffer holding the contents
798*86d7f5d3SJohn Marino  * of the line.  The trailing \012 is not included in the buffer.  If
799*86d7f5d3SJohn Marino  * LENP is not NULL, then *LENP is set to the number of bytes read;
800*86d7f5d3SJohn Marino  * strlen may not work, because there may be embedded null bytes.
801*86d7f5d3SJohn Marino  */
802*86d7f5d3SJohn Marino int
buf_read_line(struct buffer * buf,char ** line,size_t * lenp)803*86d7f5d3SJohn Marino buf_read_line (struct buffer *buf, char **line, size_t *lenp)
804*86d7f5d3SJohn Marino {
805*86d7f5d3SJohn Marino     return buf_read_short_line (buf, line, lenp, SIZE_MAX);
806*86d7f5d3SJohn Marino }
807*86d7f5d3SJohn Marino 
808*86d7f5d3SJohn Marino 
809*86d7f5d3SJohn Marino 
810*86d7f5d3SJohn Marino /* Like buf_read_line, but return -2 if no newline is found in MAX characters.
811*86d7f5d3SJohn Marino  */
812*86d7f5d3SJohn Marino int
buf_read_short_line(struct buffer * buf,char ** line,size_t * lenp,size_t max)813*86d7f5d3SJohn Marino buf_read_short_line (struct buffer *buf, char **line, size_t *lenp,
814*86d7f5d3SJohn Marino                      size_t max)
815*86d7f5d3SJohn Marino {
816*86d7f5d3SJohn Marino     assert (buf->input != NULL);
817*86d7f5d3SJohn Marino 
818*86d7f5d3SJohn Marino     *line = NULL;
819*86d7f5d3SJohn Marino 
820*86d7f5d3SJohn Marino     while (1)
821*86d7f5d3SJohn Marino     {
822*86d7f5d3SJohn Marino 	size_t len, finallen, predicted_len;
823*86d7f5d3SJohn Marino 	struct buffer_data *data;
824*86d7f5d3SJohn Marino 	char *nl;
825*86d7f5d3SJohn Marino 
826*86d7f5d3SJohn Marino 	/* See if there is a newline in BUF.  */
827*86d7f5d3SJohn Marino 	len = 0;
828*86d7f5d3SJohn Marino 	for (data = buf->data; data != NULL; data = data->next)
829*86d7f5d3SJohn Marino 	{
830*86d7f5d3SJohn Marino 	    nl = memchr (data->bufp, '\012', data->size);
831*86d7f5d3SJohn Marino 	    if (nl != NULL)
832*86d7f5d3SJohn Marino 	    {
833*86d7f5d3SJohn Marino 	        finallen = nl - data->bufp;
834*86d7f5d3SJohn Marino 		if (xsum (len, finallen) >= max) return -2;
835*86d7f5d3SJohn Marino 	        len += finallen;
836*86d7f5d3SJohn Marino 		break;
837*86d7f5d3SJohn Marino 	    }
838*86d7f5d3SJohn Marino 	    else if (xsum (len, data->size) >= max) return -2;
839*86d7f5d3SJohn Marino 	    len += data->size;
840*86d7f5d3SJohn Marino 	}
841*86d7f5d3SJohn Marino 
842*86d7f5d3SJohn Marino 	/* If we found a newline, copy the line into a memory buffer,
843*86d7f5d3SJohn Marino            and remove it from BUF.  */
844*86d7f5d3SJohn Marino 	if (data != NULL)
845*86d7f5d3SJohn Marino 	{
846*86d7f5d3SJohn Marino 	    char *p;
847*86d7f5d3SJohn Marino 	    struct buffer_data *nldata;
848*86d7f5d3SJohn Marino 
849*86d7f5d3SJohn Marino 	    p = xmalloc (len + 1);
850*86d7f5d3SJohn Marino 	    if (p == NULL)
851*86d7f5d3SJohn Marino 		return -2;
852*86d7f5d3SJohn Marino 	    *line = p;
853*86d7f5d3SJohn Marino 
854*86d7f5d3SJohn Marino 	    nldata = data;
855*86d7f5d3SJohn Marino 	    data = buf->data;
856*86d7f5d3SJohn Marino 	    while (data != nldata)
857*86d7f5d3SJohn Marino 	    {
858*86d7f5d3SJohn Marino 		struct buffer_data *next;
859*86d7f5d3SJohn Marino 
860*86d7f5d3SJohn Marino 		memcpy (p, data->bufp, data->size);
861*86d7f5d3SJohn Marino 		p += data->size;
862*86d7f5d3SJohn Marino 		next = data->next;
863*86d7f5d3SJohn Marino 		buf_free_datas (data, data);
864*86d7f5d3SJohn Marino 		data = next;
865*86d7f5d3SJohn Marino 	    }
866*86d7f5d3SJohn Marino 
867*86d7f5d3SJohn Marino 	    memcpy (p, data->bufp, finallen);
868*86d7f5d3SJohn Marino 	    p[finallen] = '\0';
869*86d7f5d3SJohn Marino 
870*86d7f5d3SJohn Marino 	    data->size -= finallen + 1;
871*86d7f5d3SJohn Marino 	    data->bufp = nl + 1;
872*86d7f5d3SJohn Marino 	    buf->data = data;
873*86d7f5d3SJohn Marino 
874*86d7f5d3SJohn Marino 	    if (lenp != NULL)
875*86d7f5d3SJohn Marino 	        *lenp = len;
876*86d7f5d3SJohn Marino 
877*86d7f5d3SJohn Marino 	    return 0;
878*86d7f5d3SJohn Marino 	}
879*86d7f5d3SJohn Marino 
880*86d7f5d3SJohn Marino 	/* Read more data until we get a newline or MAX characters.  */
881*86d7f5d3SJohn Marino 	predicted_len = 0;
882*86d7f5d3SJohn Marino 	while (1)
883*86d7f5d3SJohn Marino 	{
884*86d7f5d3SJohn Marino 	    int status;
885*86d7f5d3SJohn Marino 	    size_t size, nbytes;
886*86d7f5d3SJohn Marino 	    char *mem;
887*86d7f5d3SJohn Marino 
888*86d7f5d3SJohn Marino 	    if (buf->data == NULL
889*86d7f5d3SJohn Marino 		|| (buf->last->bufp + buf->last->size
890*86d7f5d3SJohn Marino 		    == buf->last->text + BUFFER_DATA_SIZE))
891*86d7f5d3SJohn Marino 	    {
892*86d7f5d3SJohn Marino 		data = get_buffer_data ();
893*86d7f5d3SJohn Marino 		if (data == NULL)
894*86d7f5d3SJohn Marino 		{
895*86d7f5d3SJohn Marino 		    (*buf->memory_error) (buf);
896*86d7f5d3SJohn Marino 		    return -2;
897*86d7f5d3SJohn Marino 		}
898*86d7f5d3SJohn Marino 
899*86d7f5d3SJohn Marino 		if (buf->data == NULL)
900*86d7f5d3SJohn Marino 		    buf->data = data;
901*86d7f5d3SJohn Marino 		else
902*86d7f5d3SJohn Marino 		    buf->last->next = data;
903*86d7f5d3SJohn Marino 		data->next = NULL;
904*86d7f5d3SJohn Marino 		buf->last = data;
905*86d7f5d3SJohn Marino 
906*86d7f5d3SJohn Marino 		data->bufp = data->text;
907*86d7f5d3SJohn Marino 		data->size = 0;
908*86d7f5d3SJohn Marino 	    }
909*86d7f5d3SJohn Marino 
910*86d7f5d3SJohn Marino 	    mem = buf->last->bufp + buf->last->size;
911*86d7f5d3SJohn Marino 	    size = (buf->last->text + BUFFER_DATA_SIZE) - mem;
912*86d7f5d3SJohn Marino 
913*86d7f5d3SJohn Marino 	    /* We need to read at least 1 byte.  We can handle up to
914*86d7f5d3SJohn Marino                SIZE bytes.  This will only be efficient if the
915*86d7f5d3SJohn Marino                underlying communication stream does its own buffering,
916*86d7f5d3SJohn Marino                or is clever about getting more than 1 byte at a time.  */
917*86d7f5d3SJohn Marino 	    status = (*buf->input) (buf->closure, mem, 1, size, &nbytes);
918*86d7f5d3SJohn Marino 	    if (status != 0)
919*86d7f5d3SJohn Marino 		return status;
920*86d7f5d3SJohn Marino 
921*86d7f5d3SJohn Marino 	    predicted_len += nbytes;
922*86d7f5d3SJohn Marino 	    buf->last->size += nbytes;
923*86d7f5d3SJohn Marino 
924*86d7f5d3SJohn Marino 	    /* Optimize slightly to avoid an unnecessary call to memchr.  */
925*86d7f5d3SJohn Marino 	    if (nbytes == 1)
926*86d7f5d3SJohn Marino 	    {
927*86d7f5d3SJohn Marino 		if (*mem == '\012')
928*86d7f5d3SJohn Marino 		    break;
929*86d7f5d3SJohn Marino 	    }
930*86d7f5d3SJohn Marino 	    else
931*86d7f5d3SJohn Marino 	    {
932*86d7f5d3SJohn Marino 		if (memchr (mem, '\012', nbytes) != NULL)
933*86d7f5d3SJohn Marino 		    break;
934*86d7f5d3SJohn Marino 	    }
935*86d7f5d3SJohn Marino 	    if (xsum (len, predicted_len) >= max) return -2;
936*86d7f5d3SJohn Marino 	}
937*86d7f5d3SJohn Marino     }
938*86d7f5d3SJohn Marino }
939*86d7f5d3SJohn Marino 
940*86d7f5d3SJohn Marino 
941*86d7f5d3SJohn Marino 
942*86d7f5d3SJohn Marino /*
943*86d7f5d3SJohn Marino  * Extract data from the input buffer BUF.  This will read up to WANT
944*86d7f5d3SJohn Marino  * bytes from the buffer.  It will set *RETDATA to point at the bytes,
945*86d7f5d3SJohn Marino  * and set *GOT to the number of bytes to be found there.  Any buffer
946*86d7f5d3SJohn Marino  * call which uses BUF may change the contents of the buffer at *DATA,
947*86d7f5d3SJohn Marino  * so the data should be fully processed before any further calls are
948*86d7f5d3SJohn Marino  * made.  This returns 0 on success, or -1 on end of file, or -2 if
949*86d7f5d3SJohn Marino  * out of memory, or an error code.
950*86d7f5d3SJohn Marino  */
951*86d7f5d3SJohn Marino int
buf_read_data(struct buffer * buf,size_t want,char ** retdata,size_t * got)952*86d7f5d3SJohn Marino buf_read_data (struct buffer *buf, size_t want, char **retdata, size_t *got)
953*86d7f5d3SJohn Marino {
954*86d7f5d3SJohn Marino     assert (buf->input != NULL);
955*86d7f5d3SJohn Marino 
956*86d7f5d3SJohn Marino     while (buf->data != NULL && buf->data->size == 0)
957*86d7f5d3SJohn Marino     {
958*86d7f5d3SJohn Marino 	struct buffer_data *next;
959*86d7f5d3SJohn Marino 
960*86d7f5d3SJohn Marino 	next = buf->data->next;
961*86d7f5d3SJohn Marino 	buf_free_datas (buf->data, buf->data);
962*86d7f5d3SJohn Marino 	buf->data = next;
963*86d7f5d3SJohn Marino 	if (next == NULL)
964*86d7f5d3SJohn Marino 	    buf->last = NULL;
965*86d7f5d3SJohn Marino     }
966*86d7f5d3SJohn Marino 
967*86d7f5d3SJohn Marino     if (buf->data == NULL)
968*86d7f5d3SJohn Marino     {
969*86d7f5d3SJohn Marino 	struct buffer_data *data;
970*86d7f5d3SJohn Marino 	int status;
971*86d7f5d3SJohn Marino 	size_t get, nbytes;
972*86d7f5d3SJohn Marino 
973*86d7f5d3SJohn Marino 	data = get_buffer_data ();
974*86d7f5d3SJohn Marino 	if (data == NULL)
975*86d7f5d3SJohn Marino 	{
976*86d7f5d3SJohn Marino 	    (*buf->memory_error) (buf);
977*86d7f5d3SJohn Marino 	    return -2;
978*86d7f5d3SJohn Marino 	}
979*86d7f5d3SJohn Marino 
980*86d7f5d3SJohn Marino 	buf->data = data;
981*86d7f5d3SJohn Marino 	buf->last = data;
982*86d7f5d3SJohn Marino 	data->next = NULL;
983*86d7f5d3SJohn Marino 	data->bufp = data->text;
984*86d7f5d3SJohn Marino 	data->size = 0;
985*86d7f5d3SJohn Marino 
986*86d7f5d3SJohn Marino 	if (want < BUFFER_DATA_SIZE)
987*86d7f5d3SJohn Marino 	    get = want;
988*86d7f5d3SJohn Marino 	else
989*86d7f5d3SJohn Marino 	    get = BUFFER_DATA_SIZE;
990*86d7f5d3SJohn Marino 	status = (*buf->input) (buf->closure, data->bufp, get,
991*86d7f5d3SJohn Marino 				BUFFER_DATA_SIZE, &nbytes);
992*86d7f5d3SJohn Marino 	if (status != 0)
993*86d7f5d3SJohn Marino 	    return status;
994*86d7f5d3SJohn Marino 
995*86d7f5d3SJohn Marino 	data->size = nbytes;
996*86d7f5d3SJohn Marino     }
997*86d7f5d3SJohn Marino 
998*86d7f5d3SJohn Marino     *retdata = buf->data->bufp;
999*86d7f5d3SJohn Marino     if (want < buf->data->size)
1000*86d7f5d3SJohn Marino     {
1001*86d7f5d3SJohn Marino         *got = want;
1002*86d7f5d3SJohn Marino 	buf->data->size -= want;
1003*86d7f5d3SJohn Marino 	buf->data->bufp += want;
1004*86d7f5d3SJohn Marino     }
1005*86d7f5d3SJohn Marino     else
1006*86d7f5d3SJohn Marino     {
1007*86d7f5d3SJohn Marino         *got = buf->data->size;
1008*86d7f5d3SJohn Marino 	buf->data->size = 0;
1009*86d7f5d3SJohn Marino     }
1010*86d7f5d3SJohn Marino 
1011*86d7f5d3SJohn Marino     return 0;
1012*86d7f5d3SJohn Marino }
1013*86d7f5d3SJohn Marino 
1014*86d7f5d3SJohn Marino 
1015*86d7f5d3SJohn Marino 
1016*86d7f5d3SJohn Marino /*
1017*86d7f5d3SJohn Marino  * Copy lines from an input buffer to an output buffer.
1018*86d7f5d3SJohn Marino  * This copies all complete lines (characters up to a
1019*86d7f5d3SJohn Marino  * newline) from INBUF to OUTBUF.  Each line in OUTBUF is preceded by the
1020*86d7f5d3SJohn Marino  * character COMMAND and a space.
1021*86d7f5d3SJohn Marino  */
1022*86d7f5d3SJohn Marino void
buf_copy_lines(struct buffer * outbuf,struct buffer * inbuf,int command)1023*86d7f5d3SJohn Marino buf_copy_lines (struct buffer *outbuf, struct buffer *inbuf, int command)
1024*86d7f5d3SJohn Marino {
1025*86d7f5d3SJohn Marino     while (1)
1026*86d7f5d3SJohn Marino     {
1027*86d7f5d3SJohn Marino 	struct buffer_data *data;
1028*86d7f5d3SJohn Marino 	struct buffer_data *nldata;
1029*86d7f5d3SJohn Marino 	char *nl;
1030*86d7f5d3SJohn Marino 	int len;
1031*86d7f5d3SJohn Marino 
1032*86d7f5d3SJohn Marino 	/* See if there is a newline in INBUF.  */
1033*86d7f5d3SJohn Marino 	nldata = NULL;
1034*86d7f5d3SJohn Marino 	nl = NULL;
1035*86d7f5d3SJohn Marino 	for (data = inbuf->data; data != NULL; data = data->next)
1036*86d7f5d3SJohn Marino 	{
1037*86d7f5d3SJohn Marino 	    nl = memchr (data->bufp, '\n', data->size);
1038*86d7f5d3SJohn Marino 	    if (nl != NULL)
1039*86d7f5d3SJohn Marino 	    {
1040*86d7f5d3SJohn Marino 		nldata = data;
1041*86d7f5d3SJohn Marino 		break;
1042*86d7f5d3SJohn Marino 	    }
1043*86d7f5d3SJohn Marino 	}
1044*86d7f5d3SJohn Marino 
1045*86d7f5d3SJohn Marino 	if (nldata == NULL)
1046*86d7f5d3SJohn Marino 	{
1047*86d7f5d3SJohn Marino 	    /* There are no more lines in INBUF.  */
1048*86d7f5d3SJohn Marino 	    return;
1049*86d7f5d3SJohn Marino 	}
1050*86d7f5d3SJohn Marino 
1051*86d7f5d3SJohn Marino 	/* Put in the command.  */
1052*86d7f5d3SJohn Marino 	buf_append_char (outbuf, command);
1053*86d7f5d3SJohn Marino 	buf_append_char (outbuf, ' ');
1054*86d7f5d3SJohn Marino 
1055*86d7f5d3SJohn Marino 	if (inbuf->data != nldata)
1056*86d7f5d3SJohn Marino 	{
1057*86d7f5d3SJohn Marino 	    /*
1058*86d7f5d3SJohn Marino 	     * Simply move over all the buffers up to the one containing
1059*86d7f5d3SJohn Marino 	     * the newline.
1060*86d7f5d3SJohn Marino 	     */
1061*86d7f5d3SJohn Marino 	    for (data = inbuf->data; data->next != nldata; data = data->next);
1062*86d7f5d3SJohn Marino 	    data->next = NULL;
1063*86d7f5d3SJohn Marino 	    buf_append_data (outbuf, inbuf->data, data);
1064*86d7f5d3SJohn Marino 	    inbuf->data = nldata;
1065*86d7f5d3SJohn Marino 	}
1066*86d7f5d3SJohn Marino 
1067*86d7f5d3SJohn Marino 	/*
1068*86d7f5d3SJohn Marino 	 * If the newline is at the very end of the buffer, just move
1069*86d7f5d3SJohn Marino 	 * the buffer onto OUTBUF.  Otherwise we must copy the data.
1070*86d7f5d3SJohn Marino 	 */
1071*86d7f5d3SJohn Marino 	len = nl + 1 - nldata->bufp;
1072*86d7f5d3SJohn Marino 	if (len == nldata->size)
1073*86d7f5d3SJohn Marino 	{
1074*86d7f5d3SJohn Marino 	    inbuf->data = nldata->next;
1075*86d7f5d3SJohn Marino 	    if (inbuf->data == NULL)
1076*86d7f5d3SJohn Marino 		inbuf->last = NULL;
1077*86d7f5d3SJohn Marino 
1078*86d7f5d3SJohn Marino 	    nldata->next = NULL;
1079*86d7f5d3SJohn Marino 	    buf_append_data (outbuf, nldata, nldata);
1080*86d7f5d3SJohn Marino 	}
1081*86d7f5d3SJohn Marino 	else
1082*86d7f5d3SJohn Marino 	{
1083*86d7f5d3SJohn Marino 	    buf_output (outbuf, nldata->bufp, len);
1084*86d7f5d3SJohn Marino 	    nldata->bufp += len;
1085*86d7f5d3SJohn Marino 	    nldata->size -= len;
1086*86d7f5d3SJohn Marino 	}
1087*86d7f5d3SJohn Marino     }
1088*86d7f5d3SJohn Marino }
1089*86d7f5d3SJohn Marino 
1090*86d7f5d3SJohn Marino 
1091*86d7f5d3SJohn Marino 
1092*86d7f5d3SJohn Marino /*
1093*86d7f5d3SJohn Marino  * Copy counted data from one buffer to another.  The count is an
1094*86d7f5d3SJohn Marino  * integer, host size, host byte order (it is only used across a
1095*86d7f5d3SJohn Marino  * pipe).  If there is enough data, it should be moved over.  If there
1096*86d7f5d3SJohn Marino  * is not enough data, it should remain on the original buffer.  A
1097*86d7f5d3SJohn Marino  * negative count is a special case.  if one is seen, *SPECIAL is set
1098*86d7f5d3SJohn Marino  * to the (negative) count value and no additional data is gathered
1099*86d7f5d3SJohn Marino  * from the buffer; normally *SPECIAL is set to 0.  This function
1100*86d7f5d3SJohn Marino  * returns the number of bytes it needs to see in order to actually
1101*86d7f5d3SJohn Marino  * copy something over.
1102*86d7f5d3SJohn Marino  */
1103*86d7f5d3SJohn Marino int
buf_copy_counted(struct buffer * outbuf,struct buffer * inbuf,int * special)1104*86d7f5d3SJohn Marino buf_copy_counted (struct buffer *outbuf, struct buffer *inbuf, int *special)
1105*86d7f5d3SJohn Marino {
1106*86d7f5d3SJohn Marino     *special = 0;
1107*86d7f5d3SJohn Marino 
1108*86d7f5d3SJohn Marino     while (1)
1109*86d7f5d3SJohn Marino     {
1110*86d7f5d3SJohn Marino 	struct buffer_data *data;
1111*86d7f5d3SJohn Marino 	int need;
1112*86d7f5d3SJohn Marino 	union
1113*86d7f5d3SJohn Marino 	{
1114*86d7f5d3SJohn Marino 	    char intbuf[sizeof (int)];
1115*86d7f5d3SJohn Marino 	    int i;
1116*86d7f5d3SJohn Marino 	} u;
1117*86d7f5d3SJohn Marino 	char *intp;
1118*86d7f5d3SJohn Marino 	int count;
1119*86d7f5d3SJohn Marino 	struct buffer_data *start;
1120*86d7f5d3SJohn Marino 	int startoff;
1121*86d7f5d3SJohn Marino 	struct buffer_data *stop;
1122*86d7f5d3SJohn Marino 	int stopwant;
1123*86d7f5d3SJohn Marino 
1124*86d7f5d3SJohn Marino 	/* See if we have enough bytes to figure out the count.  */
1125*86d7f5d3SJohn Marino 	need = sizeof (int);
1126*86d7f5d3SJohn Marino 	intp = u.intbuf;
1127*86d7f5d3SJohn Marino 	for (data = inbuf->data; data != NULL; data = data->next)
1128*86d7f5d3SJohn Marino 	{
1129*86d7f5d3SJohn Marino 	    if (data->size >= need)
1130*86d7f5d3SJohn Marino 	    {
1131*86d7f5d3SJohn Marino 		memcpy (intp, data->bufp, need);
1132*86d7f5d3SJohn Marino 		break;
1133*86d7f5d3SJohn Marino 	    }
1134*86d7f5d3SJohn Marino 	    memcpy (intp, data->bufp, data->size);
1135*86d7f5d3SJohn Marino 	    intp += data->size;
1136*86d7f5d3SJohn Marino 	    need -= data->size;
1137*86d7f5d3SJohn Marino 	}
1138*86d7f5d3SJohn Marino 	if (data == NULL)
1139*86d7f5d3SJohn Marino 	{
1140*86d7f5d3SJohn Marino 	    /* We don't have enough bytes to form an integer.  */
1141*86d7f5d3SJohn Marino 	    return need;
1142*86d7f5d3SJohn Marino 	}
1143*86d7f5d3SJohn Marino 
1144*86d7f5d3SJohn Marino 	count = u.i;
1145*86d7f5d3SJohn Marino 	start = data;
1146*86d7f5d3SJohn Marino 	startoff = need;
1147*86d7f5d3SJohn Marino 
1148*86d7f5d3SJohn Marino 	if (count < 0)
1149*86d7f5d3SJohn Marino 	{
1150*86d7f5d3SJohn Marino 	    /* A negative COUNT is a special case meaning that we
1151*86d7f5d3SJohn Marino                don't need any further information.  */
1152*86d7f5d3SJohn Marino 	    stop = start;
1153*86d7f5d3SJohn Marino 	    stopwant = 0;
1154*86d7f5d3SJohn Marino 	}
1155*86d7f5d3SJohn Marino 	else
1156*86d7f5d3SJohn Marino 	{
1157*86d7f5d3SJohn Marino 	    /*
1158*86d7f5d3SJohn Marino 	     * We have an integer in COUNT.  We have gotten all the
1159*86d7f5d3SJohn Marino 	     * data from INBUF in all buffers before START, and we
1160*86d7f5d3SJohn Marino 	     * have gotten STARTOFF bytes from START.  See if we have
1161*86d7f5d3SJohn Marino 	     * enough bytes remaining in INBUF.
1162*86d7f5d3SJohn Marino 	     */
1163*86d7f5d3SJohn Marino 	    need = count - (start->size - startoff);
1164*86d7f5d3SJohn Marino 	    if (need <= 0)
1165*86d7f5d3SJohn Marino 	    {
1166*86d7f5d3SJohn Marino 		stop = start;
1167*86d7f5d3SJohn Marino 		stopwant = count;
1168*86d7f5d3SJohn Marino 	    }
1169*86d7f5d3SJohn Marino 	    else
1170*86d7f5d3SJohn Marino 	    {
1171*86d7f5d3SJohn Marino 		for (data = start->next; data != NULL; data = data->next)
1172*86d7f5d3SJohn Marino 		{
1173*86d7f5d3SJohn Marino 		    if (need <= data->size)
1174*86d7f5d3SJohn Marino 			break;
1175*86d7f5d3SJohn Marino 		    need -= data->size;
1176*86d7f5d3SJohn Marino 		}
1177*86d7f5d3SJohn Marino 		if (data == NULL)
1178*86d7f5d3SJohn Marino 		{
1179*86d7f5d3SJohn Marino 		    /* We don't have enough bytes.  */
1180*86d7f5d3SJohn Marino 		    return need;
1181*86d7f5d3SJohn Marino 		}
1182*86d7f5d3SJohn Marino 		stop = data;
1183*86d7f5d3SJohn Marino 		stopwant = need;
1184*86d7f5d3SJohn Marino 	    }
1185*86d7f5d3SJohn Marino 	}
1186*86d7f5d3SJohn Marino 
1187*86d7f5d3SJohn Marino 	/*
1188*86d7f5d3SJohn Marino 	 * We have enough bytes.  Free any buffers in INBUF before
1189*86d7f5d3SJohn Marino 	 * START, and remove STARTOFF bytes from START, so that we can
1190*86d7f5d3SJohn Marino 	 * forget about STARTOFF.
1191*86d7f5d3SJohn Marino 	 */
1192*86d7f5d3SJohn Marino 	start->bufp += startoff;
1193*86d7f5d3SJohn Marino 	start->size -= startoff;
1194*86d7f5d3SJohn Marino 
1195*86d7f5d3SJohn Marino 	if (start->size == 0)
1196*86d7f5d3SJohn Marino 	    start = start->next;
1197*86d7f5d3SJohn Marino 
1198*86d7f5d3SJohn Marino 	if (stop->size == stopwant)
1199*86d7f5d3SJohn Marino 	{
1200*86d7f5d3SJohn Marino 	    stop = stop->next;
1201*86d7f5d3SJohn Marino 	    stopwant = 0;
1202*86d7f5d3SJohn Marino 	}
1203*86d7f5d3SJohn Marino 
1204*86d7f5d3SJohn Marino 	while (inbuf->data != start)
1205*86d7f5d3SJohn Marino 	{
1206*86d7f5d3SJohn Marino 	    data = inbuf->data;
1207*86d7f5d3SJohn Marino 	    inbuf->data = data->next;
1208*86d7f5d3SJohn Marino 	    buf_free_datas (data, data);
1209*86d7f5d3SJohn Marino 	}
1210*86d7f5d3SJohn Marino 
1211*86d7f5d3SJohn Marino 	/* If COUNT is negative, set *SPECIAL and get out now.  */
1212*86d7f5d3SJohn Marino 	if (count < 0)
1213*86d7f5d3SJohn Marino 	{
1214*86d7f5d3SJohn Marino 	    *special = count;
1215*86d7f5d3SJohn Marino 	    return 0;
1216*86d7f5d3SJohn Marino 	}
1217*86d7f5d3SJohn Marino 
1218*86d7f5d3SJohn Marino 	/*
1219*86d7f5d3SJohn Marino 	 * We want to copy over the bytes from START through STOP.  We
1220*86d7f5d3SJohn Marino 	 * only want STOPWANT bytes from STOP.
1221*86d7f5d3SJohn Marino 	 */
1222*86d7f5d3SJohn Marino 
1223*86d7f5d3SJohn Marino 	if (start != stop)
1224*86d7f5d3SJohn Marino 	{
1225*86d7f5d3SJohn Marino 	    /* Attach the buffers from START through STOP to OUTBUF.  */
1226*86d7f5d3SJohn Marino 	    for (data = start; data->next != stop; data = data->next);
1227*86d7f5d3SJohn Marino 	    inbuf->data = stop;
1228*86d7f5d3SJohn Marino 	    data->next = NULL;
1229*86d7f5d3SJohn Marino 	    buf_append_data (outbuf, start, data);
1230*86d7f5d3SJohn Marino 	}
1231*86d7f5d3SJohn Marino 
1232*86d7f5d3SJohn Marino 	if (stopwant > 0)
1233*86d7f5d3SJohn Marino 	{
1234*86d7f5d3SJohn Marino 	    buf_output (outbuf, stop->bufp, stopwant);
1235*86d7f5d3SJohn Marino 	    stop->bufp += stopwant;
1236*86d7f5d3SJohn Marino 	    stop->size -= stopwant;
1237*86d7f5d3SJohn Marino 	}
1238*86d7f5d3SJohn Marino     }
1239*86d7f5d3SJohn Marino 
1240*86d7f5d3SJohn Marino     /*NOTREACHED*/
1241*86d7f5d3SJohn Marino }
1242*86d7f5d3SJohn Marino 
1243*86d7f5d3SJohn Marino 
1244*86d7f5d3SJohn Marino 
1245*86d7f5d3SJohn Marino int
buf_get_fd(struct buffer * buf)1246*86d7f5d3SJohn Marino buf_get_fd (struct buffer *buf)
1247*86d7f5d3SJohn Marino {
1248*86d7f5d3SJohn Marino     if (buf->get_fd)
1249*86d7f5d3SJohn Marino 	return (*buf->get_fd) (buf->closure);
1250*86d7f5d3SJohn Marino     return -1;
1251*86d7f5d3SJohn Marino }
1252*86d7f5d3SJohn Marino 
1253*86d7f5d3SJohn Marino 
1254*86d7f5d3SJohn Marino 
1255*86d7f5d3SJohn Marino /* Shut down a buffer.  This returns 0 on success, or an errno code.  */
1256*86d7f5d3SJohn Marino int
buf_shutdown(struct buffer * buf)1257*86d7f5d3SJohn Marino buf_shutdown (struct buffer *buf)
1258*86d7f5d3SJohn Marino {
1259*86d7f5d3SJohn Marino     if (buf->shutdown) return (*buf->shutdown) (buf);
1260*86d7f5d3SJohn Marino     return 0;
1261*86d7f5d3SJohn Marino }
1262*86d7f5d3SJohn Marino 
1263*86d7f5d3SJohn Marino 
1264*86d7f5d3SJohn Marino 
1265*86d7f5d3SJohn Marino /* Certain types of communication input and output data in packets,
1266*86d7f5d3SJohn Marino    where each packet is translated in some fashion.  The packetizing
1267*86d7f5d3SJohn Marino    buffer type supports that, given a buffer which handles lower level
1268*86d7f5d3SJohn Marino    I/O and a routine to translate the data in a packet.
1269*86d7f5d3SJohn Marino 
1270*86d7f5d3SJohn Marino    This code uses two bytes for the size of a packet, so packets are
1271*86d7f5d3SJohn Marino    restricted to 65536 bytes in total.
1272*86d7f5d3SJohn Marino 
1273*86d7f5d3SJohn Marino    The translation functions should just translate; they may not
1274*86d7f5d3SJohn Marino    significantly increase or decrease the amount of data.  The actual
1275*86d7f5d3SJohn Marino    size of the initial data is part of the translated data.  The
1276*86d7f5d3SJohn Marino    output translation routine may add up to PACKET_SLOP additional
1277*86d7f5d3SJohn Marino    bytes, and the input translation routine should shrink the data
1278*86d7f5d3SJohn Marino    correspondingly.  */
1279*86d7f5d3SJohn Marino 
1280*86d7f5d3SJohn Marino # define PACKET_SLOP (100)
1281*86d7f5d3SJohn Marino 
1282*86d7f5d3SJohn Marino /* This structure is the closure field of a packetizing buffer.  */
1283*86d7f5d3SJohn Marino 
1284*86d7f5d3SJohn Marino struct packetizing_buffer
1285*86d7f5d3SJohn Marino {
1286*86d7f5d3SJohn Marino     /* The underlying buffer.  */
1287*86d7f5d3SJohn Marino     struct buffer *buf;
1288*86d7f5d3SJohn Marino     /* The input translation function.  Exactly one of inpfn and outfn
1289*86d7f5d3SJohn Marino        will be NULL.  The input translation function should
1290*86d7f5d3SJohn Marino        untranslate the data in INPUT, storing the result in OUTPUT.
1291*86d7f5d3SJohn Marino        SIZE is the amount of data in INPUT, and is also the size of
1292*86d7f5d3SJohn Marino        OUTPUT.  This should return 0 on success, or an errno code.  */
1293*86d7f5d3SJohn Marino     int (*inpfn) (void *fnclosure, const char *input, char *output,
1294*86d7f5d3SJohn Marino 			size_t size);
1295*86d7f5d3SJohn Marino     /* The output translation function.  This should translate the
1296*86d7f5d3SJohn Marino        data in INPUT, storing the result in OUTPUT.  The first two
1297*86d7f5d3SJohn Marino        bytes in INPUT will be the size of the data, and so will SIZE.
1298*86d7f5d3SJohn Marino        This should set *TRANSLATED to the amount of translated data in
1299*86d7f5d3SJohn Marino        OUTPUT.  OUTPUT is large enough to hold SIZE + PACKET_SLOP
1300*86d7f5d3SJohn Marino        bytes.  This should return 0 on success, or an errno code.  */
1301*86d7f5d3SJohn Marino     int (*outfn) (void *fnclosure, const char *input, char *output,
1302*86d7f5d3SJohn Marino 			size_t size, size_t *translated);
1303*86d7f5d3SJohn Marino     /* A closure for the translation function.  */
1304*86d7f5d3SJohn Marino     void *fnclosure;
1305*86d7f5d3SJohn Marino     /* For an input buffer, we may have to buffer up data here.  */
1306*86d7f5d3SJohn Marino     /* This is non-zero if the buffered data has been translated.
1307*86d7f5d3SJohn Marino        Otherwise, the buffered data has not been translated, and starts
1308*86d7f5d3SJohn Marino        with the two byte packet size.  */
1309*86d7f5d3SJohn Marino     bool translated;
1310*86d7f5d3SJohn Marino     /* The amount of buffered data.  */
1311*86d7f5d3SJohn Marino     size_t holdsize;
1312*86d7f5d3SJohn Marino     /* The buffer allocated to hold the data.  */
1313*86d7f5d3SJohn Marino     char *holdbuf;
1314*86d7f5d3SJohn Marino     /* The size of holdbuf.  */
1315*86d7f5d3SJohn Marino     size_t holdbufsize;
1316*86d7f5d3SJohn Marino     /* If translated is set, we need another data pointer to track
1317*86d7f5d3SJohn Marino        where we are in holdbuf.  If translated is clear, then this
1318*86d7f5d3SJohn Marino        pointer is not used.  */
1319*86d7f5d3SJohn Marino     char *holddata;
1320*86d7f5d3SJohn Marino };
1321*86d7f5d3SJohn Marino 
1322*86d7f5d3SJohn Marino 
1323*86d7f5d3SJohn Marino 
1324*86d7f5d3SJohn Marino static int packetizing_buffer_input (void *, char *, size_t, size_t, size_t *);
1325*86d7f5d3SJohn Marino static int packetizing_buffer_output (void *, const char *, size_t, size_t *);
1326*86d7f5d3SJohn Marino static int packetizing_buffer_flush (void *);
1327*86d7f5d3SJohn Marino static int packetizing_buffer_block (void *, bool);
1328*86d7f5d3SJohn Marino static int packetizing_buffer_get_fd (void *);
1329*86d7f5d3SJohn Marino static int packetizing_buffer_shutdown (struct buffer *);
1330*86d7f5d3SJohn Marino 
1331*86d7f5d3SJohn Marino 
1332*86d7f5d3SJohn Marino 
1333*86d7f5d3SJohn Marino /* Create a packetizing buffer.  */
1334*86d7f5d3SJohn Marino struct buffer *
packetizing_buffer_initialize(struct buffer * buf,int (* inpfn)(void *,const char *,char *,size_t),int (* outfn)(void *,const char *,char *,size_t,size_t *),void * fnclosure,void (* memory)(struct buffer *))1335*86d7f5d3SJohn Marino packetizing_buffer_initialize (struct buffer *buf,
1336*86d7f5d3SJohn Marino                                int (*inpfn) (void *, const char *, char *,
1337*86d7f5d3SJohn Marino                                              size_t),
1338*86d7f5d3SJohn Marino                                int (*outfn) (void *, const char *, char *,
1339*86d7f5d3SJohn Marino                                              size_t, size_t *),
1340*86d7f5d3SJohn Marino                                void *fnclosure,
1341*86d7f5d3SJohn Marino                                void (*memory) (struct buffer *))
1342*86d7f5d3SJohn Marino {
1343*86d7f5d3SJohn Marino     struct packetizing_buffer *pb;
1344*86d7f5d3SJohn Marino 
1345*86d7f5d3SJohn Marino     pb = xmalloc (sizeof *pb);
1346*86d7f5d3SJohn Marino     memset (pb, 0, sizeof *pb);
1347*86d7f5d3SJohn Marino 
1348*86d7f5d3SJohn Marino     pb->buf = buf;
1349*86d7f5d3SJohn Marino     pb->inpfn = inpfn;
1350*86d7f5d3SJohn Marino     pb->outfn = outfn;
1351*86d7f5d3SJohn Marino     pb->fnclosure = fnclosure;
1352*86d7f5d3SJohn Marino 
1353*86d7f5d3SJohn Marino     if (inpfn != NULL)
1354*86d7f5d3SJohn Marino     {
1355*86d7f5d3SJohn Marino 	/* Add PACKET_SLOP to handle larger translated packets, and
1356*86d7f5d3SJohn Marino            add 2 for the count.  This buffer is increased if
1357*86d7f5d3SJohn Marino            necessary.  */
1358*86d7f5d3SJohn Marino 	pb->holdbufsize = BUFFER_DATA_SIZE + PACKET_SLOP + 2;
1359*86d7f5d3SJohn Marino 	pb->holdbuf = xmalloc (pb->holdbufsize);
1360*86d7f5d3SJohn Marino     }
1361*86d7f5d3SJohn Marino 
1362*86d7f5d3SJohn Marino     return buf_initialize (inpfn != NULL ? packetizing_buffer_input : NULL,
1363*86d7f5d3SJohn Marino 			   inpfn != NULL ? NULL : packetizing_buffer_output,
1364*86d7f5d3SJohn Marino 			   inpfn != NULL ? NULL : packetizing_buffer_flush,
1365*86d7f5d3SJohn Marino 			   packetizing_buffer_block,
1366*86d7f5d3SJohn Marino 			   packetizing_buffer_get_fd,
1367*86d7f5d3SJohn Marino 			   packetizing_buffer_shutdown,
1368*86d7f5d3SJohn Marino 			   memory,
1369*86d7f5d3SJohn Marino 			   pb);
1370*86d7f5d3SJohn Marino }
1371*86d7f5d3SJohn Marino 
1372*86d7f5d3SJohn Marino 
1373*86d7f5d3SJohn Marino 
1374*86d7f5d3SJohn Marino /* Input data from a packetizing buffer.  */
1375*86d7f5d3SJohn Marino static int
packetizing_buffer_input(void * closure,char * data,size_t need,size_t size,size_t * got)1376*86d7f5d3SJohn Marino packetizing_buffer_input (void *closure, char *data, size_t need, size_t size,
1377*86d7f5d3SJohn Marino                           size_t *got)
1378*86d7f5d3SJohn Marino {
1379*86d7f5d3SJohn Marino     struct packetizing_buffer *pb = closure;
1380*86d7f5d3SJohn Marino 
1381*86d7f5d3SJohn Marino     *got = 0;
1382*86d7f5d3SJohn Marino 
1383*86d7f5d3SJohn Marino     if (pb->holdsize > 0 && pb->translated)
1384*86d7f5d3SJohn Marino     {
1385*86d7f5d3SJohn Marino 	size_t copy;
1386*86d7f5d3SJohn Marino 
1387*86d7f5d3SJohn Marino 	copy = pb->holdsize;
1388*86d7f5d3SJohn Marino 
1389*86d7f5d3SJohn Marino 	if (copy > size)
1390*86d7f5d3SJohn Marino 	{
1391*86d7f5d3SJohn Marino 	    memcpy (data, pb->holddata, size);
1392*86d7f5d3SJohn Marino 	    pb->holdsize -= size;
1393*86d7f5d3SJohn Marino 	    pb->holddata += size;
1394*86d7f5d3SJohn Marino 	    *got = size;
1395*86d7f5d3SJohn Marino 	    return 0;
1396*86d7f5d3SJohn Marino 	}
1397*86d7f5d3SJohn Marino 
1398*86d7f5d3SJohn Marino 	memcpy (data, pb->holddata, copy);
1399*86d7f5d3SJohn Marino 	pb->holdsize = 0;
1400*86d7f5d3SJohn Marino 	pb->translated = false;
1401*86d7f5d3SJohn Marino 
1402*86d7f5d3SJohn Marino 	data += copy;
1403*86d7f5d3SJohn Marino 	need -= copy;
1404*86d7f5d3SJohn Marino 	size -= copy;
1405*86d7f5d3SJohn Marino 	*got = copy;
1406*86d7f5d3SJohn Marino     }
1407*86d7f5d3SJohn Marino 
1408*86d7f5d3SJohn Marino     while (need > 0 || *got == 0)
1409*86d7f5d3SJohn Marino     {
1410*86d7f5d3SJohn Marino 	int status;
1411*86d7f5d3SJohn Marino 	size_t get, nread, count, tcount;
1412*86d7f5d3SJohn Marino 	char *bytes;
1413*86d7f5d3SJohn Marino 	static char *stackoutbuf = NULL;
1414*86d7f5d3SJohn Marino 	char *inbuf, *outbuf;
1415*86d7f5d3SJohn Marino 
1416*86d7f5d3SJohn Marino 	if (!stackoutbuf)
1417*86d7f5d3SJohn Marino 	    stackoutbuf = xmalloc (BUFFER_DATA_SIZE + PACKET_SLOP);
1418*86d7f5d3SJohn Marino 
1419*86d7f5d3SJohn Marino 	/* If we don't already have the two byte count, get it.  */
1420*86d7f5d3SJohn Marino 	if (pb->holdsize < 2)
1421*86d7f5d3SJohn Marino 	{
1422*86d7f5d3SJohn Marino 	    get = 2 - pb->holdsize;
1423*86d7f5d3SJohn Marino 	    status = buf_read_data (pb->buf, get, &bytes, &nread);
1424*86d7f5d3SJohn Marino 	    if (status != 0)
1425*86d7f5d3SJohn Marino 	    {
1426*86d7f5d3SJohn Marino 		/* buf_read_data can return -2, but a buffer input
1427*86d7f5d3SJohn Marino                    function is only supposed to return -1, 0, or an
1428*86d7f5d3SJohn Marino                    error code.  */
1429*86d7f5d3SJohn Marino 		if (status == -2)
1430*86d7f5d3SJohn Marino 		    status = ENOMEM;
1431*86d7f5d3SJohn Marino 		return status;
1432*86d7f5d3SJohn Marino 	    }
1433*86d7f5d3SJohn Marino 
1434*86d7f5d3SJohn Marino 	    if (nread == 0)
1435*86d7f5d3SJohn Marino 	    {
1436*86d7f5d3SJohn Marino 		/* The buffer is in nonblocking mode, and we didn't
1437*86d7f5d3SJohn Marino                    manage to read anything.  */
1438*86d7f5d3SJohn Marino 		return 0;
1439*86d7f5d3SJohn Marino 	    }
1440*86d7f5d3SJohn Marino 
1441*86d7f5d3SJohn Marino 	    if (get == 1)
1442*86d7f5d3SJohn Marino 		pb->holdbuf[1] = bytes[0];
1443*86d7f5d3SJohn Marino 	    else
1444*86d7f5d3SJohn Marino 	    {
1445*86d7f5d3SJohn Marino 		pb->holdbuf[0] = bytes[0];
1446*86d7f5d3SJohn Marino 		if (nread < 2)
1447*86d7f5d3SJohn Marino 		{
1448*86d7f5d3SJohn Marino 		    /* We only got one byte, but we needed two.  Stash
1449*86d7f5d3SJohn Marino                        the byte we got, and try again.  */
1450*86d7f5d3SJohn Marino 		    pb->holdsize = 1;
1451*86d7f5d3SJohn Marino 		    continue;
1452*86d7f5d3SJohn Marino 		}
1453*86d7f5d3SJohn Marino 		pb->holdbuf[1] = bytes[1];
1454*86d7f5d3SJohn Marino 	    }
1455*86d7f5d3SJohn Marino 	    pb->holdsize = 2;
1456*86d7f5d3SJohn Marino 	}
1457*86d7f5d3SJohn Marino 
1458*86d7f5d3SJohn Marino 	/* Read the packet.  */
1459*86d7f5d3SJohn Marino 
1460*86d7f5d3SJohn Marino 	count = (((pb->holdbuf[0] & 0xff) << 8)
1461*86d7f5d3SJohn Marino 		 + (pb->holdbuf[1] & 0xff));
1462*86d7f5d3SJohn Marino 
1463*86d7f5d3SJohn Marino 	if (count + 2 > pb->holdbufsize)
1464*86d7f5d3SJohn Marino 	{
1465*86d7f5d3SJohn Marino 	    char *n;
1466*86d7f5d3SJohn Marino 
1467*86d7f5d3SJohn Marino 	    /* We didn't allocate enough space in the initialize
1468*86d7f5d3SJohn Marino                function.  */
1469*86d7f5d3SJohn Marino 
1470*86d7f5d3SJohn Marino 	    n = xrealloc (pb->holdbuf, count + 2);
1471*86d7f5d3SJohn Marino 	    if (n == NULL)
1472*86d7f5d3SJohn Marino 	    {
1473*86d7f5d3SJohn Marino 		(*pb->buf->memory_error) (pb->buf);
1474*86d7f5d3SJohn Marino 		return ENOMEM;
1475*86d7f5d3SJohn Marino 	    }
1476*86d7f5d3SJohn Marino 	    pb->holdbuf = n;
1477*86d7f5d3SJohn Marino 	    pb->holdbufsize = count + 2;
1478*86d7f5d3SJohn Marino 	}
1479*86d7f5d3SJohn Marino 
1480*86d7f5d3SJohn Marino 	get = count - (pb->holdsize - 2);
1481*86d7f5d3SJohn Marino 
1482*86d7f5d3SJohn Marino 	status = buf_read_data (pb->buf, get, &bytes, &nread);
1483*86d7f5d3SJohn Marino 	if (status != 0)
1484*86d7f5d3SJohn Marino 	{
1485*86d7f5d3SJohn Marino 	    /* buf_read_data can return -2, but a buffer input
1486*86d7f5d3SJohn Marino                function is only supposed to return -1, 0, or an error
1487*86d7f5d3SJohn Marino                code.  */
1488*86d7f5d3SJohn Marino 	    if (status == -2)
1489*86d7f5d3SJohn Marino 		status = ENOMEM;
1490*86d7f5d3SJohn Marino 	    return status;
1491*86d7f5d3SJohn Marino 	}
1492*86d7f5d3SJohn Marino 
1493*86d7f5d3SJohn Marino 	if (nread == 0)
1494*86d7f5d3SJohn Marino 	{
1495*86d7f5d3SJohn Marino 	    /* We did not get any data.  Presumably the buffer is in
1496*86d7f5d3SJohn Marino                nonblocking mode.  */
1497*86d7f5d3SJohn Marino 	    return 0;
1498*86d7f5d3SJohn Marino 	}
1499*86d7f5d3SJohn Marino 
1500*86d7f5d3SJohn Marino 	if (nread < get)
1501*86d7f5d3SJohn Marino 	{
1502*86d7f5d3SJohn Marino 	    /* We did not get all the data we need to fill the packet.
1503*86d7f5d3SJohn Marino                buf_read_data does not promise to return all the bytes
1504*86d7f5d3SJohn Marino                requested, so we must try again.  */
1505*86d7f5d3SJohn Marino 	    memcpy (pb->holdbuf + pb->holdsize, bytes, nread);
1506*86d7f5d3SJohn Marino 	    pb->holdsize += nread;
1507*86d7f5d3SJohn Marino 	    continue;
1508*86d7f5d3SJohn Marino 	}
1509*86d7f5d3SJohn Marino 
1510*86d7f5d3SJohn Marino 	/* We have a complete untranslated packet of COUNT bytes.  */
1511*86d7f5d3SJohn Marino 
1512*86d7f5d3SJohn Marino 	if (pb->holdsize == 2)
1513*86d7f5d3SJohn Marino 	{
1514*86d7f5d3SJohn Marino 	    /* We just read the entire packet (the 2 bytes in
1515*86d7f5d3SJohn Marino                PB->HOLDBUF are the size).  Save a memcpy by
1516*86d7f5d3SJohn Marino                translating directly from BYTES.  */
1517*86d7f5d3SJohn Marino 	    inbuf = bytes;
1518*86d7f5d3SJohn Marino 	}
1519*86d7f5d3SJohn Marino 	else
1520*86d7f5d3SJohn Marino 	{
1521*86d7f5d3SJohn Marino 	    /* We already had a partial packet in PB->HOLDBUF.  We
1522*86d7f5d3SJohn Marino                need to copy the new data over to make the input
1523*86d7f5d3SJohn Marino                contiguous.  */
1524*86d7f5d3SJohn Marino 	    memcpy (pb->holdbuf + pb->holdsize, bytes, nread);
1525*86d7f5d3SJohn Marino 	    inbuf = pb->holdbuf + 2;
1526*86d7f5d3SJohn Marino 	}
1527*86d7f5d3SJohn Marino 
1528*86d7f5d3SJohn Marino 	if (count <= BUFFER_DATA_SIZE + PACKET_SLOP)
1529*86d7f5d3SJohn Marino 	    outbuf = stackoutbuf;
1530*86d7f5d3SJohn Marino 	else
1531*86d7f5d3SJohn Marino 	{
1532*86d7f5d3SJohn Marino 	    outbuf = xmalloc (count);
1533*86d7f5d3SJohn Marino 	    if (outbuf == NULL)
1534*86d7f5d3SJohn Marino 	    {
1535*86d7f5d3SJohn Marino 		(*pb->buf->memory_error) (pb->buf);
1536*86d7f5d3SJohn Marino 		return ENOMEM;
1537*86d7f5d3SJohn Marino 	    }
1538*86d7f5d3SJohn Marino 	}
1539*86d7f5d3SJohn Marino 
1540*86d7f5d3SJohn Marino 	status = (*pb->inpfn) (pb->fnclosure, inbuf, outbuf, count);
1541*86d7f5d3SJohn Marino 	if (status != 0)
1542*86d7f5d3SJohn Marino 	    return status;
1543*86d7f5d3SJohn Marino 
1544*86d7f5d3SJohn Marino 	/* The first two bytes in the translated buffer are the real
1545*86d7f5d3SJohn Marino            length of the translated data.  */
1546*86d7f5d3SJohn Marino 	tcount = ((outbuf[0] & 0xff) << 8) + (outbuf[1] & 0xff);
1547*86d7f5d3SJohn Marino 
1548*86d7f5d3SJohn Marino 	if (tcount > count)
1549*86d7f5d3SJohn Marino 	    error (1, 0, "Input translation failure");
1550*86d7f5d3SJohn Marino 
1551*86d7f5d3SJohn Marino 	if (tcount > size)
1552*86d7f5d3SJohn Marino 	{
1553*86d7f5d3SJohn Marino 	    /* We have more data than the caller has provided space
1554*86d7f5d3SJohn Marino                for.  We need to save some of it for the next call.  */
1555*86d7f5d3SJohn Marino 
1556*86d7f5d3SJohn Marino 	    memcpy (data, outbuf + 2, size);
1557*86d7f5d3SJohn Marino 	    *got += size;
1558*86d7f5d3SJohn Marino 
1559*86d7f5d3SJohn Marino 	    pb->holdsize = tcount - size;
1560*86d7f5d3SJohn Marino 	    memcpy (pb->holdbuf, outbuf + 2 + size, tcount - size);
1561*86d7f5d3SJohn Marino 	    pb->holddata = pb->holdbuf;
1562*86d7f5d3SJohn Marino 	    pb->translated = true;
1563*86d7f5d3SJohn Marino 
1564*86d7f5d3SJohn Marino 	    if (outbuf != stackoutbuf)
1565*86d7f5d3SJohn Marino 		free (outbuf);
1566*86d7f5d3SJohn Marino 
1567*86d7f5d3SJohn Marino 	    return 0;
1568*86d7f5d3SJohn Marino 	}
1569*86d7f5d3SJohn Marino 
1570*86d7f5d3SJohn Marino 	memcpy (data, outbuf + 2, tcount);
1571*86d7f5d3SJohn Marino 
1572*86d7f5d3SJohn Marino 	if (outbuf != stackoutbuf)
1573*86d7f5d3SJohn Marino 	    free (outbuf);
1574*86d7f5d3SJohn Marino 
1575*86d7f5d3SJohn Marino 	pb->holdsize = 0;
1576*86d7f5d3SJohn Marino 
1577*86d7f5d3SJohn Marino 	data += tcount;
1578*86d7f5d3SJohn Marino 	need -= tcount;
1579*86d7f5d3SJohn Marino 	size -= tcount;
1580*86d7f5d3SJohn Marino 	*got += tcount;
1581*86d7f5d3SJohn Marino     }
1582*86d7f5d3SJohn Marino 
1583*86d7f5d3SJohn Marino     return 0;
1584*86d7f5d3SJohn Marino }
1585*86d7f5d3SJohn Marino 
1586*86d7f5d3SJohn Marino 
1587*86d7f5d3SJohn Marino 
1588*86d7f5d3SJohn Marino /* Output data to a packetizing buffer.  */
1589*86d7f5d3SJohn Marino static int
packetizing_buffer_output(void * closure,const char * data,size_t have,size_t * wrote)1590*86d7f5d3SJohn Marino packetizing_buffer_output (void *closure, const char *data, size_t have,
1591*86d7f5d3SJohn Marino                            size_t *wrote)
1592*86d7f5d3SJohn Marino {
1593*86d7f5d3SJohn Marino     struct packetizing_buffer *pb = closure;
1594*86d7f5d3SJohn Marino     static char *inbuf = NULL;  /* These two buffers are static so that they
1595*86d7f5d3SJohn Marino 				 * depend on the size of BUFFER_DATA_SIZE yet
1596*86d7f5d3SJohn Marino 				 * still only be allocated once per run.
1597*86d7f5d3SJohn Marino 				 */
1598*86d7f5d3SJohn Marino     static char *stack_outbuf = NULL;
1599*86d7f5d3SJohn Marino     struct buffer_data *outdata = NULL; /* Initialize to silence -Wall.  Dumb.
1600*86d7f5d3SJohn Marino 					 */
1601*86d7f5d3SJohn Marino     char *outbuf;
1602*86d7f5d3SJohn Marino     size_t size, translated;
1603*86d7f5d3SJohn Marino     int status;
1604*86d7f5d3SJohn Marino 
1605*86d7f5d3SJohn Marino     /* It would be easy to xmalloc a buffer, but I don't think this
1606*86d7f5d3SJohn Marino        case can ever arise.  */
1607*86d7f5d3SJohn Marino     assert (have <= BUFFER_DATA_SIZE);
1608*86d7f5d3SJohn Marino 
1609*86d7f5d3SJohn Marino     if (!inbuf)
1610*86d7f5d3SJohn Marino     {
1611*86d7f5d3SJohn Marino 	inbuf = xmalloc (BUFFER_DATA_SIZE + 2);
1612*86d7f5d3SJohn Marino         stack_outbuf = xmalloc (BUFFER_DATA_SIZE + PACKET_SLOP + 4);
1613*86d7f5d3SJohn Marino     }
1614*86d7f5d3SJohn Marino 
1615*86d7f5d3SJohn Marino     inbuf[0] = (have >> 8) & 0xff;
1616*86d7f5d3SJohn Marino     inbuf[1] = have & 0xff;
1617*86d7f5d3SJohn Marino     memcpy (inbuf + 2, data, have);
1618*86d7f5d3SJohn Marino 
1619*86d7f5d3SJohn Marino     size = have + 2;
1620*86d7f5d3SJohn Marino 
1621*86d7f5d3SJohn Marino     /* The output function is permitted to add up to PACKET_SLOP
1622*86d7f5d3SJohn Marino        bytes, and we need 2 bytes for the size of the translated data.
1623*86d7f5d3SJohn Marino        If we can guarantee that the result will fit in a buffer_data,
1624*86d7f5d3SJohn Marino        we translate directly into one to avoid a memcpy in buf_output.  */
1625*86d7f5d3SJohn Marino     if (size + PACKET_SLOP + 2 > BUFFER_DATA_SIZE)
1626*86d7f5d3SJohn Marino 	outbuf = stack_outbuf;
1627*86d7f5d3SJohn Marino     else
1628*86d7f5d3SJohn Marino     {
1629*86d7f5d3SJohn Marino 	outdata = get_buffer_data ();
1630*86d7f5d3SJohn Marino 	if (outdata == NULL)
1631*86d7f5d3SJohn Marino 	{
1632*86d7f5d3SJohn Marino 	    (*pb->buf->memory_error) (pb->buf);
1633*86d7f5d3SJohn Marino 	    return ENOMEM;
1634*86d7f5d3SJohn Marino 	}
1635*86d7f5d3SJohn Marino 
1636*86d7f5d3SJohn Marino 	outdata->next = NULL;
1637*86d7f5d3SJohn Marino 	outdata->bufp = outdata->text;
1638*86d7f5d3SJohn Marino 
1639*86d7f5d3SJohn Marino 	outbuf = outdata->text;
1640*86d7f5d3SJohn Marino     }
1641*86d7f5d3SJohn Marino 
1642*86d7f5d3SJohn Marino     status = (*pb->outfn) (pb->fnclosure, inbuf, outbuf + 2, size,
1643*86d7f5d3SJohn Marino 			   &translated);
1644*86d7f5d3SJohn Marino     if (status != 0)
1645*86d7f5d3SJohn Marino 	return status;
1646*86d7f5d3SJohn Marino 
1647*86d7f5d3SJohn Marino     /* The output function is permitted to add up to PACKET_SLOP
1648*86d7f5d3SJohn Marino        bytes.  */
1649*86d7f5d3SJohn Marino     assert (translated <= size + PACKET_SLOP);
1650*86d7f5d3SJohn Marino 
1651*86d7f5d3SJohn Marino     outbuf[0] = (translated >> 8) & 0xff;
1652*86d7f5d3SJohn Marino     outbuf[1] = translated & 0xff;
1653*86d7f5d3SJohn Marino 
1654*86d7f5d3SJohn Marino     if (outbuf == stack_outbuf)
1655*86d7f5d3SJohn Marino 	buf_output (pb->buf, outbuf, translated + 2);
1656*86d7f5d3SJohn Marino     else
1657*86d7f5d3SJohn Marino     {
1658*86d7f5d3SJohn Marino 	outdata->size = translated + 2;
1659*86d7f5d3SJohn Marino 	buf_append_data (pb->buf, outdata, outdata);
1660*86d7f5d3SJohn Marino     }
1661*86d7f5d3SJohn Marino 
1662*86d7f5d3SJohn Marino     *wrote = have;
1663*86d7f5d3SJohn Marino 
1664*86d7f5d3SJohn Marino     /* We will only be here because buf_send_output was called on the
1665*86d7f5d3SJohn Marino        packetizing buffer.  That means that we should now call
1666*86d7f5d3SJohn Marino        buf_send_output on the underlying buffer.  */
1667*86d7f5d3SJohn Marino     return buf_send_output (pb->buf);
1668*86d7f5d3SJohn Marino }
1669*86d7f5d3SJohn Marino 
1670*86d7f5d3SJohn Marino 
1671*86d7f5d3SJohn Marino 
1672*86d7f5d3SJohn Marino /* Flush data to a packetizing buffer.  */
1673*86d7f5d3SJohn Marino static int
packetizing_buffer_flush(void * closure)1674*86d7f5d3SJohn Marino packetizing_buffer_flush (void *closure)
1675*86d7f5d3SJohn Marino {
1676*86d7f5d3SJohn Marino     struct packetizing_buffer *pb = closure;
1677*86d7f5d3SJohn Marino 
1678*86d7f5d3SJohn Marino     /* Flush the underlying buffer.  Note that if the original call to
1679*86d7f5d3SJohn Marino        buf_flush passed 1 for the BLOCK argument, then the buffer will
1680*86d7f5d3SJohn Marino        already have been set into blocking mode, so we should always
1681*86d7f5d3SJohn Marino        pass 0 here.  */
1682*86d7f5d3SJohn Marino     return buf_flush (pb->buf, 0);
1683*86d7f5d3SJohn Marino }
1684*86d7f5d3SJohn Marino 
1685*86d7f5d3SJohn Marino 
1686*86d7f5d3SJohn Marino 
1687*86d7f5d3SJohn Marino /* The block routine for a packetizing buffer.  */
1688*86d7f5d3SJohn Marino static int
packetizing_buffer_block(void * closure,bool block)1689*86d7f5d3SJohn Marino packetizing_buffer_block (void *closure, bool block)
1690*86d7f5d3SJohn Marino {
1691*86d7f5d3SJohn Marino     struct packetizing_buffer *pb = closure;
1692*86d7f5d3SJohn Marino 
1693*86d7f5d3SJohn Marino     if (block)
1694*86d7f5d3SJohn Marino 	return set_block (pb->buf);
1695*86d7f5d3SJohn Marino     else
1696*86d7f5d3SJohn Marino 	return set_nonblock (pb->buf);
1697*86d7f5d3SJohn Marino }
1698*86d7f5d3SJohn Marino 
1699*86d7f5d3SJohn Marino 
1700*86d7f5d3SJohn Marino 
1701*86d7f5d3SJohn Marino /* Return the file descriptor underlying any child buffers.  */
1702*86d7f5d3SJohn Marino static int
packetizing_buffer_get_fd(void * closure)1703*86d7f5d3SJohn Marino packetizing_buffer_get_fd (void *closure)
1704*86d7f5d3SJohn Marino {
1705*86d7f5d3SJohn Marino     struct packetizing_buffer *cb = closure;
1706*86d7f5d3SJohn Marino     return buf_get_fd (cb->buf);
1707*86d7f5d3SJohn Marino }
1708*86d7f5d3SJohn Marino 
1709*86d7f5d3SJohn Marino 
1710*86d7f5d3SJohn Marino 
1711*86d7f5d3SJohn Marino /* Shut down a packetizing buffer.  */
1712*86d7f5d3SJohn Marino static int
packetizing_buffer_shutdown(struct buffer * buf)1713*86d7f5d3SJohn Marino packetizing_buffer_shutdown (struct buffer *buf)
1714*86d7f5d3SJohn Marino {
1715*86d7f5d3SJohn Marino     struct packetizing_buffer *pb = buf->closure;
1716*86d7f5d3SJohn Marino 
1717*86d7f5d3SJohn Marino     return buf_shutdown (pb->buf);
1718*86d7f5d3SJohn Marino }
1719*86d7f5d3SJohn Marino 
1720*86d7f5d3SJohn Marino 
1721*86d7f5d3SJohn Marino 
1722*86d7f5d3SJohn Marino /* All server communication goes through buffer structures.  Most of
1723*86d7f5d3SJohn Marino    the buffers are built on top of a file descriptor.  This structure
1724*86d7f5d3SJohn Marino    is used as the closure field in a buffer.  */
1725*86d7f5d3SJohn Marino 
1726*86d7f5d3SJohn Marino struct fd_buffer
1727*86d7f5d3SJohn Marino {
1728*86d7f5d3SJohn Marino     /* The file descriptor.  */
1729*86d7f5d3SJohn Marino     int fd;
1730*86d7f5d3SJohn Marino     /* Nonzero if the file descriptor is in blocking mode.  */
1731*86d7f5d3SJohn Marino     int blocking;
1732*86d7f5d3SJohn Marino     /* The child process id when fd is a pipe.  */
1733*86d7f5d3SJohn Marino     pid_t child_pid;
1734*86d7f5d3SJohn Marino     /* The connection info, when fd is a pipe to a server.  */
1735*86d7f5d3SJohn Marino     cvsroot_t *root;
1736*86d7f5d3SJohn Marino };
1737*86d7f5d3SJohn Marino 
1738*86d7f5d3SJohn Marino static int fd_buffer_input (void *, char *, size_t, size_t, size_t *);
1739*86d7f5d3SJohn Marino static int fd_buffer_output (void *, const char *, size_t, size_t *);
1740*86d7f5d3SJohn Marino static int fd_buffer_flush (void *);
1741*86d7f5d3SJohn Marino static int fd_buffer_block (void *, bool);
1742*86d7f5d3SJohn Marino static int fd_buffer_get_fd (void *);
1743*86d7f5d3SJohn Marino static int fd_buffer_shutdown (struct buffer *);
1744*86d7f5d3SJohn Marino 
1745*86d7f5d3SJohn Marino /* Initialize a buffer built on a file descriptor.  FD is the file
1746*86d7f5d3SJohn Marino    descriptor.  INPUT is nonzero if this is for input, zero if this is
1747*86d7f5d3SJohn Marino    for output.  MEMORY is the function to call when a memory error
1748*86d7f5d3SJohn Marino    occurs.  */
1749*86d7f5d3SJohn Marino 
1750*86d7f5d3SJohn Marino struct buffer *
fd_buffer_initialize(int fd,pid_t child_pid,cvsroot_t * root,bool input,void (* memory)(struct buffer *))1751*86d7f5d3SJohn Marino fd_buffer_initialize (int fd, pid_t child_pid, cvsroot_t *root, bool input,
1752*86d7f5d3SJohn Marino                       void (*memory) (struct buffer *))
1753*86d7f5d3SJohn Marino {
1754*86d7f5d3SJohn Marino     struct fd_buffer *n;
1755*86d7f5d3SJohn Marino 
1756*86d7f5d3SJohn Marino     n = xmalloc (sizeof *n);
1757*86d7f5d3SJohn Marino     n->fd = fd;
1758*86d7f5d3SJohn Marino     n->child_pid = child_pid;
1759*86d7f5d3SJohn Marino     n->root = root;
1760*86d7f5d3SJohn Marino     fd_buffer_block (n, true);
1761*86d7f5d3SJohn Marino     return buf_initialize (input ? fd_buffer_input : NULL,
1762*86d7f5d3SJohn Marino 			   input ? NULL : fd_buffer_output,
1763*86d7f5d3SJohn Marino 			   input ? NULL : fd_buffer_flush,
1764*86d7f5d3SJohn Marino 			   fd_buffer_block, fd_buffer_get_fd,
1765*86d7f5d3SJohn Marino 			   fd_buffer_shutdown,
1766*86d7f5d3SJohn Marino 			   memory,
1767*86d7f5d3SJohn Marino 			   n);
1768*86d7f5d3SJohn Marino }
1769*86d7f5d3SJohn Marino 
1770*86d7f5d3SJohn Marino 
1771*86d7f5d3SJohn Marino 
1772*86d7f5d3SJohn Marino /* The buffer input function for a buffer built on a file descriptor.
1773*86d7f5d3SJohn Marino  *
1774*86d7f5d3SJohn Marino  * In non-blocking mode, this function will read as many bytes as it can in a
1775*86d7f5d3SJohn Marino  * single try, up to SIZE bytes, and return.
1776*86d7f5d3SJohn Marino  *
1777*86d7f5d3SJohn Marino  * In blocking mode with NEED > 0, this function will read as many bytes as it
1778*86d7f5d3SJohn Marino  * can but will not return until it has read at least NEED bytes.
1779*86d7f5d3SJohn Marino  *
1780*86d7f5d3SJohn Marino  * In blocking mode with NEED == 0, this function will block until it can read
1781*86d7f5d3SJohn Marino  * either at least one byte or EOF, then read as many bytes as are available
1782*86d7f5d3SJohn Marino  * and return.  At the very least, compress_buffer_shutdown depends on this
1783*86d7f5d3SJohn Marino  * behavior to read EOF and can loop indefinitely without it.
1784*86d7f5d3SJohn Marino  *
1785*86d7f5d3SJohn Marino  * ASSUMPTIONS
1786*86d7f5d3SJohn Marino  *   NEED <= SIZE.
1787*86d7f5d3SJohn Marino  *
1788*86d7f5d3SJohn Marino  * INPUTS
1789*86d7f5d3SJohn Marino  *   closure	Our FD_BUFFER struct.
1790*86d7f5d3SJohn Marino  *   data	The start of our input buffer.
1791*86d7f5d3SJohn Marino  *   need	How many bytes our caller needs.
1792*86d7f5d3SJohn Marino  *   size	How many bytes are available in DATA.
1793*86d7f5d3SJohn Marino  *   got	Where to store the number of bytes read.
1794*86d7f5d3SJohn Marino  *
1795*86d7f5d3SJohn Marino  * OUTPUTS
1796*86d7f5d3SJohn Marino  *   data	Filled with bytes read.
1797*86d7f5d3SJohn Marino  *   *got	Number of bytes actually read into DATA.
1798*86d7f5d3SJohn Marino  *
1799*86d7f5d3SJohn Marino  * RETURNS
1800*86d7f5d3SJohn Marino  *   errno	On error.
1801*86d7f5d3SJohn Marino  *   -1		On EOF.
1802*86d7f5d3SJohn Marino  *   0		Otherwise.
1803*86d7f5d3SJohn Marino  *
1804*86d7f5d3SJohn Marino  * ERRORS
1805*86d7f5d3SJohn Marino  *   This function can return an error if fd_buffer_block(), or the system
1806*86d7f5d3SJohn Marino  *   read() or select() calls do.
1807*86d7f5d3SJohn Marino  */
1808*86d7f5d3SJohn Marino static int
fd_buffer_input(void * closure,char * data,size_t need,size_t size,size_t * got)1809*86d7f5d3SJohn Marino fd_buffer_input (void *closure, char *data, size_t need, size_t size,
1810*86d7f5d3SJohn Marino 		 size_t *got)
1811*86d7f5d3SJohn Marino {
1812*86d7f5d3SJohn Marino     struct fd_buffer *fb = closure;
1813*86d7f5d3SJohn Marino     int nbytes;
1814*86d7f5d3SJohn Marino 
1815*86d7f5d3SJohn Marino     assert (need <= size);
1816*86d7f5d3SJohn Marino 
1817*86d7f5d3SJohn Marino     *got = 0;
1818*86d7f5d3SJohn Marino 
1819*86d7f5d3SJohn Marino     if (fb->blocking)
1820*86d7f5d3SJohn Marino     {
1821*86d7f5d3SJohn Marino 	int status;
1822*86d7f5d3SJohn Marino 	fd_set readfds;
1823*86d7f5d3SJohn Marino 
1824*86d7f5d3SJohn Marino 	/* Set non-block.  */
1825*86d7f5d3SJohn Marino         status = fd_buffer_block (fb, false);
1826*86d7f5d3SJohn Marino 	if (status != 0) return status;
1827*86d7f5d3SJohn Marino 
1828*86d7f5d3SJohn Marino 	FD_ZERO (&readfds);
1829*86d7f5d3SJohn Marino 	FD_SET (fb->fd, &readfds);
1830*86d7f5d3SJohn Marino 	do
1831*86d7f5d3SJohn Marino 	{
1832*86d7f5d3SJohn Marino 	    int numfds;
1833*86d7f5d3SJohn Marino 
1834*86d7f5d3SJohn Marino 	    do {
1835*86d7f5d3SJohn Marino 		/* This used to select on exceptions too, but as far
1836*86d7f5d3SJohn Marino 		   as I know there was never any reason to do that and
1837*86d7f5d3SJohn Marino 		   SCO doesn't let you select on exceptions on pipes.  */
1838*86d7f5d3SJohn Marino 		numfds = fd_select (fb->fd + 1, &readfds, NULL, NULL, NULL);
1839*86d7f5d3SJohn Marino 		if (numfds < 0 && errno != EINTR)
1840*86d7f5d3SJohn Marino 		{
1841*86d7f5d3SJohn Marino 		    status = errno;
1842*86d7f5d3SJohn Marino 		    goto block_done;
1843*86d7f5d3SJohn Marino 		}
1844*86d7f5d3SJohn Marino 	    } while (numfds < 0);
1845*86d7f5d3SJohn Marino 
1846*86d7f5d3SJohn Marino 	    nbytes = read (fb->fd, data + *got, size - *got);
1847*86d7f5d3SJohn Marino 
1848*86d7f5d3SJohn Marino 	    if (nbytes == 0)
1849*86d7f5d3SJohn Marino 	    {
1850*86d7f5d3SJohn Marino 		/* End of file.  This assumes that we are using POSIX or BSD
1851*86d7f5d3SJohn Marino 		   style nonblocking I/O.  On System V we will get a zero
1852*86d7f5d3SJohn Marino 		   return if there is no data, even when not at EOF.  */
1853*86d7f5d3SJohn Marino 		if (*got)
1854*86d7f5d3SJohn Marino 		{
1855*86d7f5d3SJohn Marino 		    /* We already read some data, so return no error, counting
1856*86d7f5d3SJohn Marino 		     * on the fact that we will read EOF again next time.
1857*86d7f5d3SJohn Marino 		     */
1858*86d7f5d3SJohn Marino 		    status = 0;
1859*86d7f5d3SJohn Marino 		    break;
1860*86d7f5d3SJohn Marino 		}
1861*86d7f5d3SJohn Marino 		else
1862*86d7f5d3SJohn Marino 		{
1863*86d7f5d3SJohn Marino 		    /* Return EOF.  */
1864*86d7f5d3SJohn Marino 		    status = -1;
1865*86d7f5d3SJohn Marino 		    break;
1866*86d7f5d3SJohn Marino 		}
1867*86d7f5d3SJohn Marino 	    }
1868*86d7f5d3SJohn Marino 
1869*86d7f5d3SJohn Marino 	    if (nbytes < 0)
1870*86d7f5d3SJohn Marino 	    {
1871*86d7f5d3SJohn Marino 		/* Some error occurred.  */
1872*86d7f5d3SJohn Marino 		if (!blocking_error (errno))
1873*86d7f5d3SJohn Marino 		{
1874*86d7f5d3SJohn Marino 		    status = errno;
1875*86d7f5d3SJohn Marino 		    break;
1876*86d7f5d3SJohn Marino 		}
1877*86d7f5d3SJohn Marino 		/* else Everything's fine, we just didn't get any data.  */
1878*86d7f5d3SJohn Marino 	    }
1879*86d7f5d3SJohn Marino 
1880*86d7f5d3SJohn Marino 	    *got += nbytes;
1881*86d7f5d3SJohn Marino 	} while (*got < need);
1882*86d7f5d3SJohn Marino 
1883*86d7f5d3SJohn Marino block_done:
1884*86d7f5d3SJohn Marino 	if (status == 0 || status == -1)
1885*86d7f5d3SJohn Marino 	{
1886*86d7f5d3SJohn Marino 	    int newstatus;
1887*86d7f5d3SJohn Marino 
1888*86d7f5d3SJohn Marino 	    /* OK or EOF - Reset block.  */
1889*86d7f5d3SJohn Marino 	    newstatus = fd_buffer_block (fb, true);
1890*86d7f5d3SJohn Marino 	    if (newstatus) status = newstatus;
1891*86d7f5d3SJohn Marino 	}
1892*86d7f5d3SJohn Marino 	return status;
1893*86d7f5d3SJohn Marino     }
1894*86d7f5d3SJohn Marino 
1895*86d7f5d3SJohn Marino     /* The above will always return.  Handle non-blocking read.  */
1896*86d7f5d3SJohn Marino     nbytes = read (fb->fd, data, size);
1897*86d7f5d3SJohn Marino 
1898*86d7f5d3SJohn Marino     if (nbytes > 0)
1899*86d7f5d3SJohn Marino     {
1900*86d7f5d3SJohn Marino 	*got = nbytes;
1901*86d7f5d3SJohn Marino 	return 0;
1902*86d7f5d3SJohn Marino     }
1903*86d7f5d3SJohn Marino 
1904*86d7f5d3SJohn Marino     if (nbytes == 0)
1905*86d7f5d3SJohn Marino 	/* End of file.  This assumes that we are using POSIX or BSD
1906*86d7f5d3SJohn Marino 	   style nonblocking I/O.  On System V we will get a zero
1907*86d7f5d3SJohn Marino 	   return if there is no data, even when not at EOF.  */
1908*86d7f5d3SJohn Marino 	return -1;
1909*86d7f5d3SJohn Marino 
1910*86d7f5d3SJohn Marino     /* Some error occurred.  */
1911*86d7f5d3SJohn Marino     if (blocking_error (errno))
1912*86d7f5d3SJohn Marino 	/* Everything's fine, we just didn't get any data.  */
1913*86d7f5d3SJohn Marino 	return 0;
1914*86d7f5d3SJohn Marino 
1915*86d7f5d3SJohn Marino     return errno;
1916*86d7f5d3SJohn Marino }
1917*86d7f5d3SJohn Marino 
1918*86d7f5d3SJohn Marino 
1919*86d7f5d3SJohn Marino 
1920*86d7f5d3SJohn Marino /* The buffer output function for a buffer built on a file descriptor.  */
1921*86d7f5d3SJohn Marino 
1922*86d7f5d3SJohn Marino static int
fd_buffer_output(void * closure,const char * data,size_t have,size_t * wrote)1923*86d7f5d3SJohn Marino fd_buffer_output (void *closure, const char *data, size_t have, size_t *wrote)
1924*86d7f5d3SJohn Marino {
1925*86d7f5d3SJohn Marino     struct fd_buffer *fd = closure;
1926*86d7f5d3SJohn Marino 
1927*86d7f5d3SJohn Marino     *wrote = 0;
1928*86d7f5d3SJohn Marino 
1929*86d7f5d3SJohn Marino     while (have > 0)
1930*86d7f5d3SJohn Marino     {
1931*86d7f5d3SJohn Marino 	int nbytes;
1932*86d7f5d3SJohn Marino 
1933*86d7f5d3SJohn Marino 	nbytes = write (fd->fd, data, have);
1934*86d7f5d3SJohn Marino 
1935*86d7f5d3SJohn Marino 	if (nbytes <= 0)
1936*86d7f5d3SJohn Marino 	{
1937*86d7f5d3SJohn Marino 	    if (! fd->blocking
1938*86d7f5d3SJohn Marino 		&& (nbytes == 0 || blocking_error (errno)))
1939*86d7f5d3SJohn Marino 	    {
1940*86d7f5d3SJohn Marino 		/* A nonblocking write failed to write any data.  Just
1941*86d7f5d3SJohn Marino 		   return.  */
1942*86d7f5d3SJohn Marino 		return 0;
1943*86d7f5d3SJohn Marino 	    }
1944*86d7f5d3SJohn Marino 
1945*86d7f5d3SJohn Marino 	    /* Some sort of error occurred.  */
1946*86d7f5d3SJohn Marino 
1947*86d7f5d3SJohn Marino 	    if (nbytes == 0)
1948*86d7f5d3SJohn Marino 		return EIO;
1949*86d7f5d3SJohn Marino 
1950*86d7f5d3SJohn Marino 	    return errno;
1951*86d7f5d3SJohn Marino 	}
1952*86d7f5d3SJohn Marino 
1953*86d7f5d3SJohn Marino 	*wrote += nbytes;
1954*86d7f5d3SJohn Marino 	data += nbytes;
1955*86d7f5d3SJohn Marino 	have -= nbytes;
1956*86d7f5d3SJohn Marino     }
1957*86d7f5d3SJohn Marino 
1958*86d7f5d3SJohn Marino     return 0;
1959*86d7f5d3SJohn Marino }
1960*86d7f5d3SJohn Marino 
1961*86d7f5d3SJohn Marino 
1962*86d7f5d3SJohn Marino 
1963*86d7f5d3SJohn Marino /* The buffer flush function for a buffer built on a file descriptor.  */
1964*86d7f5d3SJohn Marino static int
fd_buffer_flush(void * closure)1965*86d7f5d3SJohn Marino fd_buffer_flush (void *closure)
1966*86d7f5d3SJohn Marino {
1967*86d7f5d3SJohn Marino     /* We don't need to do anything here.  Our fd doesn't have its own buffer
1968*86d7f5d3SJohn Marino      * and syncing won't do anything but slow us down.
1969*86d7f5d3SJohn Marino      *
1970*86d7f5d3SJohn Marino      * struct fd_buffer *fb = closure;
1971*86d7f5d3SJohn Marino      *
1972*86d7f5d3SJohn Marino      * if (fsync (fb->fd) < 0 && errno != EROFS && errno != EINVAL)
1973*86d7f5d3SJohn Marino      *     return errno;
1974*86d7f5d3SJohn Marino      */
1975*86d7f5d3SJohn Marino     return 0;
1976*86d7f5d3SJohn Marino }
1977*86d7f5d3SJohn Marino 
1978*86d7f5d3SJohn Marino 
1979*86d7f5d3SJohn Marino 
1980*86d7f5d3SJohn Marino static struct stat devnull;
1981*86d7f5d3SJohn Marino static int devnull_set = -1;
1982*86d7f5d3SJohn Marino 
1983*86d7f5d3SJohn Marino /* The buffer block function for a buffer built on a file descriptor.  */
1984*86d7f5d3SJohn Marino static int
fd_buffer_block(void * closure,bool block)1985*86d7f5d3SJohn Marino fd_buffer_block (void *closure, bool block)
1986*86d7f5d3SJohn Marino {
1987*86d7f5d3SJohn Marino     struct fd_buffer *fb = closure;
1988*86d7f5d3SJohn Marino # if defined (F_GETFL) && defined (O_NONBLOCK) && defined (F_SETFL)
1989*86d7f5d3SJohn Marino     int flags;
1990*86d7f5d3SJohn Marino 
1991*86d7f5d3SJohn Marino     flags = fcntl (fb->fd, F_GETFL, 0);
1992*86d7f5d3SJohn Marino     if (flags < 0)
1993*86d7f5d3SJohn Marino 	return errno;
1994*86d7f5d3SJohn Marino 
1995*86d7f5d3SJohn Marino     if (block)
1996*86d7f5d3SJohn Marino 	flags &= ~O_NONBLOCK;
1997*86d7f5d3SJohn Marino     else
1998*86d7f5d3SJohn Marino 	flags |= O_NONBLOCK;
1999*86d7f5d3SJohn Marino 
2000*86d7f5d3SJohn Marino     if (fcntl (fb->fd, F_SETFL, flags) < 0)
2001*86d7f5d3SJohn Marino     {
2002*86d7f5d3SJohn Marino 	/*
2003*86d7f5d3SJohn Marino 	 * BSD returns ENODEV when we try to set block/nonblock on /dev/null.
2004*86d7f5d3SJohn Marino 	 * BSDI returns ENOTTY when we try to set block/nonblock on /dev/null.
2005*86d7f5d3SJohn Marino 	 */
2006*86d7f5d3SJohn Marino 	struct stat sb;
2007*86d7f5d3SJohn Marino 	int save_errno = errno;
2008*86d7f5d3SJohn Marino 	bool isdevnull = false;
2009*86d7f5d3SJohn Marino 
2010*86d7f5d3SJohn Marino 	if (devnull_set == -1)
2011*86d7f5d3SJohn Marino 	    devnull_set = stat ("/dev/null", &devnull);
2012*86d7f5d3SJohn Marino 
2013*86d7f5d3SJohn Marino 	if (devnull_set >= 0)
2014*86d7f5d3SJohn Marino 	    /* Equivalent to /dev/null ? */
2015*86d7f5d3SJohn Marino 	    isdevnull = (fstat (fb->fd, &sb) >= 0
2016*86d7f5d3SJohn Marino 			 && sb.st_dev == devnull.st_dev
2017*86d7f5d3SJohn Marino 			 && sb.st_ino == devnull.st_ino
2018*86d7f5d3SJohn Marino 			 && sb.st_mode == devnull.st_mode
2019*86d7f5d3SJohn Marino 			 && sb.st_uid == devnull.st_uid
2020*86d7f5d3SJohn Marino 			 && sb.st_gid == devnull.st_gid
2021*86d7f5d3SJohn Marino 			 && sb.st_size == devnull.st_size
2022*86d7f5d3SJohn Marino 			 && sb.st_blocks == devnull.st_blocks
2023*86d7f5d3SJohn Marino 			 && sb.st_blksize == devnull.st_blksize);
2024*86d7f5d3SJohn Marino 	if (isdevnull)
2025*86d7f5d3SJohn Marino 	    errno = 0;
2026*86d7f5d3SJohn Marino 	else
2027*86d7f5d3SJohn Marino 	{
2028*86d7f5d3SJohn Marino 	    errno = save_errno;
2029*86d7f5d3SJohn Marino 	    return errno;
2030*86d7f5d3SJohn Marino 	}
2031*86d7f5d3SJohn Marino     }
2032*86d7f5d3SJohn Marino # endif /* F_GETFL && O_NONBLOCK && F_SETFL */
2033*86d7f5d3SJohn Marino 
2034*86d7f5d3SJohn Marino     fb->blocking = block;
2035*86d7f5d3SJohn Marino 
2036*86d7f5d3SJohn Marino     return 0;
2037*86d7f5d3SJohn Marino }
2038*86d7f5d3SJohn Marino 
2039*86d7f5d3SJohn Marino 
2040*86d7f5d3SJohn Marino 
2041*86d7f5d3SJohn Marino static int
fd_buffer_get_fd(void * closure)2042*86d7f5d3SJohn Marino fd_buffer_get_fd (void *closure)
2043*86d7f5d3SJohn Marino {
2044*86d7f5d3SJohn Marino     struct fd_buffer *fb = closure;
2045*86d7f5d3SJohn Marino     return fb->fd;
2046*86d7f5d3SJohn Marino }
2047*86d7f5d3SJohn Marino 
2048*86d7f5d3SJohn Marino 
2049*86d7f5d3SJohn Marino 
2050*86d7f5d3SJohn Marino /* The buffer shutdown function for a buffer built on a file descriptor.
2051*86d7f5d3SJohn Marino  *
2052*86d7f5d3SJohn Marino  * This function disposes of memory allocated for this buffer.
2053*86d7f5d3SJohn Marino  */
2054*86d7f5d3SJohn Marino static int
fd_buffer_shutdown(struct buffer * buf)2055*86d7f5d3SJohn Marino fd_buffer_shutdown (struct buffer *buf)
2056*86d7f5d3SJohn Marino {
2057*86d7f5d3SJohn Marino     struct fd_buffer *fb = buf->closure;
2058*86d7f5d3SJohn Marino     struct stat s;
2059*86d7f5d3SJohn Marino     bool closefd, statted;
2060*86d7f5d3SJohn Marino 
2061*86d7f5d3SJohn Marino     /* Must be an open pipe, socket, or file.  What could go wrong? */
2062*86d7f5d3SJohn Marino     if (fstat (fb->fd, &s) == -1) statted = false;
2063*86d7f5d3SJohn Marino     else statted = true;
2064*86d7f5d3SJohn Marino     /* Don't bother to try closing the FD if we couldn't stat it.  This
2065*86d7f5d3SJohn Marino      * probably won't work.
2066*86d7f5d3SJohn Marino      *
2067*86d7f5d3SJohn Marino      * (buf_shutdown() on some of the server/child communication pipes is
2068*86d7f5d3SJohn Marino      * getting EBADF on both the fstat and the close.  I'm not sure why -
2069*86d7f5d3SJohn Marino      * perhaps they were alredy closed somehow?
2070*86d7f5d3SJohn Marino      */
2071*86d7f5d3SJohn Marino     closefd = statted;
2072*86d7f5d3SJohn Marino 
2073*86d7f5d3SJohn Marino     /* Flush the buffer if possible.  */
2074*86d7f5d3SJohn Marino     if (buf->flush)
2075*86d7f5d3SJohn Marino     {
2076*86d7f5d3SJohn Marino 	buf_flush (buf, 1);
2077*86d7f5d3SJohn Marino 	buf->flush = NULL;
2078*86d7f5d3SJohn Marino     }
2079*86d7f5d3SJohn Marino 
2080*86d7f5d3SJohn Marino     if (buf->input)
2081*86d7f5d3SJohn Marino     {
2082*86d7f5d3SJohn Marino 	/* There used to be a check here for unread data in the buffer of
2083*86d7f5d3SJohn Marino 	 * the pipe, but it was deemed unnecessary and possibly dangerous.  In
2084*86d7f5d3SJohn Marino 	 * some sense it could be second-guessing the caller who requested it
2085*86d7f5d3SJohn Marino 	 * closed, as well.
2086*86d7f5d3SJohn Marino 	 */
2087*86d7f5d3SJohn Marino 
2088*86d7f5d3SJohn Marino /* FIXME:
2089*86d7f5d3SJohn Marino  *
2090*86d7f5d3SJohn Marino  * This mess of #ifdefs is hard to read.  There must be some relation between
2091*86d7f5d3SJohn Marino  * the macros being checked which at least deserves comments - if
2092*86d7f5d3SJohn Marino  * SHUTDOWN_SERVER, NO_SOCKET_TO_FD, & START_RSH_WITH_POPEN_RW were completely
2093*86d7f5d3SJohn Marino  * independant, then the next few lines could easily refuse to compile.
2094*86d7f5d3SJohn Marino  *
2095*86d7f5d3SJohn Marino  * The note below about START_RSH_WITH_POPEN_RW never being set when
2096*86d7f5d3SJohn Marino  * SHUTDOWN_SERVER is defined means that this code would always break on
2097*86d7f5d3SJohn Marino  * systems with SHUTDOWN_SERVER defined and thus the comment must now be
2098*86d7f5d3SJohn Marino  * incorrect or the code was broken since the comment was written.
2099*86d7f5d3SJohn Marino  */
2100*86d7f5d3SJohn Marino # ifdef SHUTDOWN_SERVER
2101*86d7f5d3SJohn Marino 	if (fb->root && fb->root->method != server_method)
2102*86d7f5d3SJohn Marino # endif
2103*86d7f5d3SJohn Marino # ifndef NO_SOCKET_TO_FD
2104*86d7f5d3SJohn Marino 	{
2105*86d7f5d3SJohn Marino 	    /* shutdown() sockets */
2106*86d7f5d3SJohn Marino 	    if (statted && S_ISSOCK (s.st_mode))
2107*86d7f5d3SJohn Marino 		shutdown (fb->fd, 0);
2108*86d7f5d3SJohn Marino 	}
2109*86d7f5d3SJohn Marino # endif /* NO_SOCKET_TO_FD */
2110*86d7f5d3SJohn Marino # ifdef START_RSH_WITH_POPEN_RW
2111*86d7f5d3SJohn Marino /* Can't be set with SHUTDOWN_SERVER defined */
2112*86d7f5d3SJohn Marino 	/* FIXME: This is now certainly broken since pclose is defined by ANSI
2113*86d7f5d3SJohn Marino 	 * C to accept a FILE * argument.  The switch will need to happen at a
2114*86d7f5d3SJohn Marino 	 * higher abstraction level to switch between initializing stdio & fd
2115*86d7f5d3SJohn Marino 	 * buffers on systems that need this (or maybe an fd buffer that keeps
2116*86d7f5d3SJohn Marino 	 * track of the FILE * could be used - I think flushing the stream
2117*86d7f5d3SJohn Marino 	 * before beginning exclusive access via the FD is OK.
2118*86d7f5d3SJohn Marino 	 */
2119*86d7f5d3SJohn Marino 	else if (fb->root && pclose (fb->fd) == EOF)
2120*86d7f5d3SJohn Marino 	{
2121*86d7f5d3SJohn Marino 	    error (1, errno, "closing connection to %s",
2122*86d7f5d3SJohn Marino 		   fb->root->hostname);
2123*86d7f5d3SJohn Marino 	    closefd = false;
2124*86d7f5d3SJohn Marino 	}
2125*86d7f5d3SJohn Marino # endif /* START_RSH_WITH_POPEN_RW */
2126*86d7f5d3SJohn Marino 
2127*86d7f5d3SJohn Marino 	buf->input = NULL;
2128*86d7f5d3SJohn Marino     }
2129*86d7f5d3SJohn Marino     else if (buf->output)
2130*86d7f5d3SJohn Marino     {
2131*86d7f5d3SJohn Marino # ifdef SHUTDOWN_SERVER
2132*86d7f5d3SJohn Marino 	/* FIXME:  Should have a SHUTDOWN_SERVER_INPUT &
2133*86d7f5d3SJohn Marino 	 * SHUTDOWN_SERVER_OUTPUT
2134*86d7f5d3SJohn Marino 	 */
2135*86d7f5d3SJohn Marino 	if (fb->root && fb->root->method == server_method)
2136*86d7f5d3SJohn Marino 	    SHUTDOWN_SERVER (fb->fd);
2137*86d7f5d3SJohn Marino 	else
2138*86d7f5d3SJohn Marino # endif
2139*86d7f5d3SJohn Marino # ifndef NO_SOCKET_TO_FD
2140*86d7f5d3SJohn Marino 	/* shutdown() sockets */
2141*86d7f5d3SJohn Marino 	if (statted && S_ISSOCK (s.st_mode))
2142*86d7f5d3SJohn Marino 	    shutdown (fb->fd, 1);
2143*86d7f5d3SJohn Marino # else
2144*86d7f5d3SJohn Marino 	{
2145*86d7f5d3SJohn Marino 	/* I'm not sure I like this empty block, but the alternative
2146*86d7f5d3SJohn Marino 	 * is another nested NO_SOCKET_TO_FD switch as above.
2147*86d7f5d3SJohn Marino 	 */
2148*86d7f5d3SJohn Marino 	}
2149*86d7f5d3SJohn Marino # endif /* NO_SOCKET_TO_FD */
2150*86d7f5d3SJohn Marino 
2151*86d7f5d3SJohn Marino 	buf->output = NULL;
2152*86d7f5d3SJohn Marino     }
2153*86d7f5d3SJohn Marino 
2154*86d7f5d3SJohn Marino     if (statted && closefd && close (fb->fd) == -1)
2155*86d7f5d3SJohn Marino     {
2156*86d7f5d3SJohn Marino 	if (server_active)
2157*86d7f5d3SJohn Marino 	{
2158*86d7f5d3SJohn Marino             /* Syslog this? */
2159*86d7f5d3SJohn Marino 	}
2160*86d7f5d3SJohn Marino # ifdef CLIENT_SUPPORT
2161*86d7f5d3SJohn Marino 	else if (fb->root)
2162*86d7f5d3SJohn Marino             error (1, errno, "closing down connection to %s",
2163*86d7f5d3SJohn Marino                    fb->root->hostname);
2164*86d7f5d3SJohn Marino 	    /* EXITS */
2165*86d7f5d3SJohn Marino # endif /* CLIENT_SUPPORT */
2166*86d7f5d3SJohn Marino 
2167*86d7f5d3SJohn Marino 	error (0, errno, "closing down buffer");
2168*86d7f5d3SJohn Marino     }
2169*86d7f5d3SJohn Marino 
2170*86d7f5d3SJohn Marino     /* If we were talking to a process, make sure it exited */
2171*86d7f5d3SJohn Marino     if (fb->child_pid)
2172*86d7f5d3SJohn Marino     {
2173*86d7f5d3SJohn Marino 	int w;
2174*86d7f5d3SJohn Marino 
2175*86d7f5d3SJohn Marino 	do
2176*86d7f5d3SJohn Marino 	    w = waitpid (fb->child_pid, NULL, 0);
2177*86d7f5d3SJohn Marino 	while (w == -1 && errno == EINTR);
2178*86d7f5d3SJohn Marino 	if (w == -1)
2179*86d7f5d3SJohn Marino 	    error (1, errno, "waiting for process %d", fb->child_pid);
2180*86d7f5d3SJohn Marino     }
2181*86d7f5d3SJohn Marino 
2182*86d7f5d3SJohn Marino     free (buf->closure);
2183*86d7f5d3SJohn Marino     buf->closure = NULL;
2184*86d7f5d3SJohn Marino 
2185*86d7f5d3SJohn Marino     return 0;
2186*86d7f5d3SJohn Marino }
2187*86d7f5d3SJohn Marino #endif /* defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT) */
2188