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 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 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 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 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 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 * 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