2 * Empire - A multi-player, client/server Internet based war game.
3 * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak,
4 * Ken Stevens, Steve McClure
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
23 * related information and legal notices. It is expected that any future
24 * projects/authors will amend these files as needed.
28 * ioqueue.c: Read and write i/o queues
30 * Known contributors to this file:
35 * Read and write onto io queues. Note that
36 * the io queues don't actually do any writing;
37 * that is left for a higher level.
41 #include <stdlib.h> /* malloc free */
42 #include <sys/types.h>
50 static int ioqtocbuf(struct ioqueue *ioq, s_char *buf, int cc, register int stopc);
52 static int ioqtoiov(struct ioqueue *ioq, struct iovec *iov, register int max);
54 static int ioqtobuf(struct ioqueue *ioq, s_char *buf, int cc);
55 static int appendcc(struct ioqueue *ioq, s_char *buf, int cc);
56 static int removecc(struct ioqueue *ioq, register int cc);
59 static void loc_StripDels(char *pBuf);
67 ioq = (struct ioqueue *) malloc(sizeof(struct ioqueue));
68 emp_initque(&ioq->list.queue);
79 ioq_destroy(struct ioqueue *ioq)
81 #if !defined(aix) && !defined(NeXT)
82 /* ioq_drain doesn't work under aix or NeXT... dunno why --ts */
89 ioq_drain(struct ioqueue *ioq)
94 while ((qp = ioq->list.queue.q_forw) != &ioq->list.queue){
95 io = (struct io *) qp;
96 (void) emp_remque(&io->queue);
97 (void) free((s_char *)io->data);
98 (void) free((s_char *)io);
105 * copy batch of pointers into the passed
106 * iovec, but don't actually dequeue the data.
107 * return # of iovec initialized.
111 ioq_makeiov(struct ioqueue *ioq, struct iovec *iov, int cc)
115 return ioqtoiov(ioq, iov, cc);
120 * Copy the specified number of characters into the buffer
121 * provided, without actually dequeueing the data. Return
122 * number of bytes actually found.
125 ioq_peek(struct ioqueue *ioq, s_char *buf, int cc)
127 return ioqtobuf(ioq, buf, cc);
131 ioq_dequeue(struct ioqueue *ioq, int cc)
133 return removecc(ioq, cc);
137 ioq_append(struct ioqueue *ioq, s_char *buf, int cc)
139 appendcc(ioq, buf, cc);
143 ioq_qsize(struct ioqueue *ioq)
149 * read a line of text up to (but not including)
150 * the newline. return -1 and read nothing if
151 * no input is available
154 ioq_gets(struct ioqueue *ioq, s_char *buf, int cc)
159 nbytes = ioqtocbuf(ioq, buf, cc - 1, '\n');
165 /* remove the newline too */
166 removecc(ioq, nbytes + 1);
175 ioq_puts(struct ioqueue *ioq, s_char *buf)
177 return appendcc(ioq, buf, strlen(buf));
181 * all the rest are local to this module
186 * copy cc bytes from ioq to buf.
187 * this routine doesn't free memory; this is
188 * left for a higher level.
192 ioqtobuf(struct ioqueue *ioq, s_char *buf, int cc)
195 struct emp_qelem *qp;
196 struct emp_qelem *head;
199 register s_char *offset;
203 head = &ioq->list.queue;
204 for (qp = head->q_forw; qp != head && nleft > 0; qp = qp->q_forw) {
205 io = (struct io *) qp;
206 if ((nbytes = io->nbytes - io->offset) < 0) {
207 /* XXX log something here */
213 bcopy(io->data + io->offset, offset, nbytes);
222 * copy at most cc bytes from ioq to buf,
223 * terminating on the stop character.
227 ioqtocbuf(struct ioqueue *ioq, s_char *buf, int cc, register int stopc)
233 struct emp_qelem *qp;
234 struct emp_qelem *head;
238 head = &ioq->list.queue;
241 for (qp = head->q_forw; qp != head; qp = qp->q_forw) {
242 io = (struct io *) qp;
243 if ((nbytes = io->nbytes - io->offset) <= 0)
245 p = io->data + io->offset;
246 for (n=0; n < nbytes && p[n] != stopc; n++)
256 ioqtobuf(ioq, buf, cc < total ? cc : total);
261 * initialize an iovec to point at max bytes worth
262 * of data from the ioqueue.
267 ioqtoiov(struct ioqueue *ioq, struct iovec *iov, register int max)
273 struct emp_qelem *qp;
277 qp = ioq->list.queue.q_forw;
278 while (qp != &ioq->list.queue && cc > 0) {
279 io = (struct io *) qp;
280 len = io->nbytes - io->offset;
283 iov->iov_base = io->data + io->offset;
297 * append a buffer to the end of the ioq.
301 appendcc(struct ioqueue *ioq, s_char *buf, int cc)
308 /* determine if any space is left */
309 io = (struct io *)ioq->list.queue.q_back;
310 avail = io->size - io->nbytes;
312 /* append to existing buffer */
313 len = cc > avail ? avail : cc;
314 bcopy(buf, io->data + io->nbytes, len);
318 appendcc(ioq, buf + len, cc - len);
320 /* create a new buffer, minimum bufsize bytes */
321 len = cc > ioq->bufsize ? cc : ioq->bufsize;
324 io = (struct io *) malloc(sizeof(struct io));
329 emp_insque(&io->queue, ioq->list.queue.q_back);
336 * remove cc bytes from ioqueue ioq
337 * free memory, dequeue io elements
338 * which are no longer used.
342 removecc(struct ioqueue *ioq, register int cc)
345 struct emp_qelem *qp;
352 while ((qp = ioq->list.queue.q_forw) != &ioq->list.queue) {
353 io = (struct io *) qp;
354 there = io->nbytes - io->offset;
357 (void) emp_remque(&io->queue);
358 (void) free((s_char *)io);
361 if (remain >= there) {
362 /* not enough or exact; free entry */
365 (void) emp_remque(&io->queue);
366 (void) free(io->data);
367 (void) free((s_char *)io);
369 /* too much; increment offset */
370 io->offset += remain;
382 * Make an (output) buffer up to the
383 * maximum size of the buffer.
385 * We don't free the bytes...
388 ioq_makebuf(struct ioqueue *ioq, char *pBuf, int nBufLen)
391 struct emp_qelem *qp;
392 struct emp_qelem *head;
401 head = &ioq->list.queue;
403 for (qp = head->q_forw;
404 (qp != head) && (nleft > 0);
406 io = (struct io *) qp;
407 nbytes = io->nbytes - io->offset;
409 /* Paranoid check for bad buffer. */
413 /* too many bytes, wait till next time. */
417 bcopy(io->data + io->offset, offset, nbytes);
428 * Remove backspaces and DELs from the buffer.
430 * Why? Because I got tired of telneting into the
431 * server and having to type perfectly...
434 loc_StripDels(char *pBuf)
440 for (cp = pBuf; *cp;) {
441 /* Remove Backspace and DEL */
442 if (*cp == '\b' || *cp == '\x8F') {