xref: /dflybsd-src/contrib/cvs-1.12/src/ms-buffer.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
1*86d7f5d3SJohn Marino /* CVS client logging buffer.
2*86d7f5d3SJohn Marino 
3*86d7f5d3SJohn Marino    This program is free software; you can redistribute it and/or modify
4*86d7f5d3SJohn Marino    it under the terms of the GNU General Public License as published by
5*86d7f5d3SJohn Marino    the Free Software Foundation; either version 2, or (at your option)
6*86d7f5d3SJohn Marino    any later version.
7*86d7f5d3SJohn Marino 
8*86d7f5d3SJohn Marino    This program is distributed in the hope that it will be useful,
9*86d7f5d3SJohn Marino    but WITHOUT ANY WARRANTY; without even the implied warranty of
10*86d7f5d3SJohn Marino    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11*86d7f5d3SJohn Marino    GNU General Public License for more details.  */
12*86d7f5d3SJohn Marino 
13*86d7f5d3SJohn Marino #include <config.h>
14*86d7f5d3SJohn Marino 
15*86d7f5d3SJohn Marino #include <stdio.h>
16*86d7f5d3SJohn Marino 
17*86d7f5d3SJohn Marino #include "cvs.h"
18*86d7f5d3SJohn Marino #include "buffer.h"
19*86d7f5d3SJohn Marino #include "ms-buffer.h"
20*86d7f5d3SJohn Marino 
21*86d7f5d3SJohn Marino #if defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT)
22*86d7f5d3SJohn Marino #ifdef PROXY_SUPPORT
23*86d7f5d3SJohn Marino 
24*86d7f5d3SJohn Marino /* This structure is the closure field of a multi-source buffer.  */
25*86d7f5d3SJohn Marino struct ms_buffer
26*86d7f5d3SJohn Marino {
27*86d7f5d3SJohn Marino     /* Our buffer struct.  */
28*86d7f5d3SJohn Marino     struct buffer *buf;
29*86d7f5d3SJohn Marino 
30*86d7f5d3SJohn Marino     /* The underlying buffers.  */
31*86d7f5d3SJohn Marino     struct buffer *cur;
32*86d7f5d3SJohn Marino     List *bufs;
33*86d7f5d3SJohn Marino 
34*86d7f5d3SJohn Marino     /* Whether we are in blocking mode or not.  */
35*86d7f5d3SJohn Marino     bool block;
36*86d7f5d3SJohn Marino };
37*86d7f5d3SJohn Marino 
38*86d7f5d3SJohn Marino 
39*86d7f5d3SJohn Marino 
40*86d7f5d3SJohn Marino /* The block function for a multi-source buffer.  */
41*86d7f5d3SJohn Marino static int
ms_buffer_block(void * closure,bool block)42*86d7f5d3SJohn Marino ms_buffer_block (void *closure, bool block)
43*86d7f5d3SJohn Marino {
44*86d7f5d3SJohn Marino     struct ms_buffer *mb = closure;
45*86d7f5d3SJohn Marino 
46*86d7f5d3SJohn Marino     mb->block = block;
47*86d7f5d3SJohn Marino     if (block)
48*86d7f5d3SJohn Marino 	return set_block (mb->cur);
49*86d7f5d3SJohn Marino     else
50*86d7f5d3SJohn Marino 	return set_nonblock (mb->cur);
51*86d7f5d3SJohn Marino }
52*86d7f5d3SJohn Marino 
53*86d7f5d3SJohn Marino 
54*86d7f5d3SJohn Marino 
55*86d7f5d3SJohn Marino /* The input function for a log buffer.  */
56*86d7f5d3SJohn Marino static int
ms_buffer_input(void * closure,char * data,size_t need,size_t size,size_t * got)57*86d7f5d3SJohn Marino ms_buffer_input (void *closure, char *data, size_t need, size_t size,
58*86d7f5d3SJohn Marino 		 size_t *got)
59*86d7f5d3SJohn Marino {
60*86d7f5d3SJohn Marino     struct ms_buffer *mb = closure;
61*86d7f5d3SJohn Marino     int status;
62*86d7f5d3SJohn Marino 
63*86d7f5d3SJohn Marino     assert (mb->cur->input);
64*86d7f5d3SJohn Marino     status = (*mb->cur->input) (mb->cur->closure, data, need, size, got);
65*86d7f5d3SJohn Marino     if (status == -1)
66*86d7f5d3SJohn Marino     {
67*86d7f5d3SJohn Marino 	Node *p;
68*86d7f5d3SJohn Marino 	/* EOF.  Set up the next buffer in line but return success and no
69*86d7f5d3SJohn Marino 	 * data since our caller may have selected on the target to find
70*86d7f5d3SJohn Marino 	 * ready data before calling us.
71*86d7f5d3SJohn Marino 	 *
72*86d7f5d3SJohn Marino 	 * If there are no more buffers, return EOF.
73*86d7f5d3SJohn Marino 	 */
74*86d7f5d3SJohn Marino 	if (list_isempty (mb->bufs)) return -1;
75*86d7f5d3SJohn Marino 	buf_shutdown (mb->cur);
76*86d7f5d3SJohn Marino 	buf_free (mb->cur);
77*86d7f5d3SJohn Marino 	p = mb->bufs->list->next;
78*86d7f5d3SJohn Marino 	mb->cur = p->data;
79*86d7f5d3SJohn Marino 	p->delproc = NULL;
80*86d7f5d3SJohn Marino 	p->data = NULL;
81*86d7f5d3SJohn Marino 	delnode (p);
82*86d7f5d3SJohn Marino 	if (!buf_empty_p (mb->cur)) buf_append_buffer (mb->buf, mb->cur);
83*86d7f5d3SJohn Marino 	ms_buffer_block (closure, mb->block);
84*86d7f5d3SJohn Marino 	*got = 0;
85*86d7f5d3SJohn Marino 	status = 0;
86*86d7f5d3SJohn Marino     }
87*86d7f5d3SJohn Marino 
88*86d7f5d3SJohn Marino     return status;
89*86d7f5d3SJohn Marino }
90*86d7f5d3SJohn Marino 
91*86d7f5d3SJohn Marino 
92*86d7f5d3SJohn Marino 
93*86d7f5d3SJohn Marino /* Return the file descriptor underlying any child buffers.  */
94*86d7f5d3SJohn Marino static int
ms_buffer_get_fd(void * closure)95*86d7f5d3SJohn Marino ms_buffer_get_fd (void *closure)
96*86d7f5d3SJohn Marino {
97*86d7f5d3SJohn Marino     struct ms_buffer *mb = closure;
98*86d7f5d3SJohn Marino     return buf_get_fd (mb->cur);
99*86d7f5d3SJohn Marino }
100*86d7f5d3SJohn Marino 
101*86d7f5d3SJohn Marino 
102*86d7f5d3SJohn Marino 
103*86d7f5d3SJohn Marino /* The shutdown function for a multi-source buffer.  */
104*86d7f5d3SJohn Marino static int
ms_buffer_shutdown(struct buffer * buf)105*86d7f5d3SJohn Marino ms_buffer_shutdown (struct buffer *buf)
106*86d7f5d3SJohn Marino {
107*86d7f5d3SJohn Marino     struct ms_buffer *mb = buf->closure;
108*86d7f5d3SJohn Marino     Node *p;
109*86d7f5d3SJohn Marino     int err = 0;
110*86d7f5d3SJohn Marino 
111*86d7f5d3SJohn Marino     assert (mb->cur);
112*86d7f5d3SJohn Marino     err += buf_shutdown (mb->cur);
113*86d7f5d3SJohn Marino     buf_free (mb->cur);
114*86d7f5d3SJohn Marino     for (p = mb->bufs->list->next; p != mb->bufs->list; p = p->next)
115*86d7f5d3SJohn Marino     {
116*86d7f5d3SJohn Marino 	assert (p);
117*86d7f5d3SJohn Marino 	err += buf_shutdown (p->data);
118*86d7f5d3SJohn Marino     }
119*86d7f5d3SJohn Marino 
120*86d7f5d3SJohn Marino     dellist (&mb->bufs);
121*86d7f5d3SJohn Marino     return err;
122*86d7f5d3SJohn Marino }
123*86d7f5d3SJohn Marino 
124*86d7f5d3SJohn Marino 
125*86d7f5d3SJohn Marino 
126*86d7f5d3SJohn Marino static void
delbuflist(Node * p)127*86d7f5d3SJohn Marino delbuflist (Node *p)
128*86d7f5d3SJohn Marino {
129*86d7f5d3SJohn Marino     if (p->data)
130*86d7f5d3SJohn Marino 	buf_free (p->data);
131*86d7f5d3SJohn Marino }
132*86d7f5d3SJohn Marino 
133*86d7f5d3SJohn Marino 
134*86d7f5d3SJohn Marino 
135*86d7f5d3SJohn Marino /* Create a multi-source buffer.  This could easily be generalized to support
136*86d7f5d3SJohn Marino  * any number of source buffers, but for now only two are necessary.
137*86d7f5d3SJohn Marino  */
138*86d7f5d3SJohn Marino struct buffer *
ms_buffer_initialize(void (* memory)(struct buffer *),struct buffer * buf,struct buffer * buf2)139*86d7f5d3SJohn Marino ms_buffer_initialize (void (*memory) (struct buffer *),
140*86d7f5d3SJohn Marino 		      struct buffer *buf, struct buffer *buf2/*, ...*/)
141*86d7f5d3SJohn Marino {
142*86d7f5d3SJohn Marino     struct ms_buffer *mb = xmalloc (sizeof *mb);
143*86d7f5d3SJohn Marino     struct buffer *retbuf;
144*86d7f5d3SJohn Marino     Node *p;
145*86d7f5d3SJohn Marino 
146*86d7f5d3SJohn Marino     mb->block = false;
147*86d7f5d3SJohn Marino     mb->cur = buf;
148*86d7f5d3SJohn Marino     set_nonblock (buf);
149*86d7f5d3SJohn Marino     mb->bufs = getlist ();
150*86d7f5d3SJohn Marino     p = getnode ();
151*86d7f5d3SJohn Marino     p->data = buf2;
152*86d7f5d3SJohn Marino     p->delproc = delbuflist;
153*86d7f5d3SJohn Marino     addnode (mb->bufs, p);
154*86d7f5d3SJohn Marino     retbuf = buf_initialize (ms_buffer_input, NULL, NULL,
155*86d7f5d3SJohn Marino 			     ms_buffer_block, ms_buffer_get_fd,
156*86d7f5d3SJohn Marino 			     ms_buffer_shutdown, memory, mb);
157*86d7f5d3SJohn Marino     if (!buf_empty_p (buf)) buf_append_buffer (retbuf, buf);
158*86d7f5d3SJohn Marino     mb->buf = retbuf;
159*86d7f5d3SJohn Marino 
160*86d7f5d3SJohn Marino     return retbuf;
161*86d7f5d3SJohn Marino }
162*86d7f5d3SJohn Marino #endif /* PROXY_SUPPORT */
163*86d7f5d3SJohn Marino #endif /* defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT) */
164