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