X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/putty/blobdiff_plain/32874aeac8dacbca26663777b39a79efc5d8dc4b..e52455b1fd4e5a129cebe653a777b1f421b18b4f:/misc.c diff --git a/misc.c b/misc.c index 2fabbb64..30731152 100644 --- a/misc.c +++ b/misc.c @@ -1,9 +1,151 @@ #include #include #include +#include #include "putty.h" -/* +/* ---------------------------------------------------------------------- + * String handling routines. + */ + +char *dupstr(char *s) +{ + int len = strlen(s); + char *p = smalloc(len + 1); + strcpy(p, s); + return p; +} + +/* Allocate the concatenation of N strings. Terminate arg list with NULL. */ +char *dupcat(char *s1, ...) +{ + int len; + char *p, *q, *sn; + va_list ap; + + len = strlen(s1); + va_start(ap, s1); + while (1) { + sn = va_arg(ap, char *); + if (!sn) + break; + len += strlen(sn); + } + va_end(ap); + + p = smalloc(len + 1); + strcpy(p, s1); + q = p + strlen(p); + + va_start(ap, s1); + while (1) { + sn = va_arg(ap, char *); + if (!sn) + break; + strcpy(q, sn); + q += strlen(q); + } + va_end(ap); + + return p; +} + +/* ---------------------------------------------------------------------- + * Generic routines to deal with send buffers: a linked list of + * smallish blocks, with the operations + * + * - add an arbitrary amount of data to the end of the list + * - remove the first N bytes from the list + * - return a (pointer,length) pair giving some initial data in + * the list, suitable for passing to a send or write system + * call + * - return the current size of the buffer chain in bytes + */ + +#define BUFFER_GRANULE 512 + +struct bufchain_granule { + struct bufchain_granule *next; + int buflen, bufpos; + char buf[BUFFER_GRANULE]; +}; + +void bufchain_init(bufchain *ch) +{ + ch->head = ch->tail = NULL; + ch->buffersize = 0; +} + +void bufchain_clear(bufchain *ch) +{ + struct bufchain_granule *b; + while (ch->head) { + b = ch->head; + ch->head = ch->head->next; + sfree(b); + } + ch->tail = NULL; + ch->buffersize = 0; +} + +int bufchain_size(bufchain *ch) +{ + return ch->buffersize; +} + +void bufchain_add(bufchain *ch, void *data, int len) +{ + char *buf = (char *)data; + + ch->buffersize += len; + + if (ch->tail && ch->tail->buflen < BUFFER_GRANULE) { + int copylen = min(len, BUFFER_GRANULE - ch->tail->buflen); + memcpy(ch->tail->buf + ch->tail->buflen, buf, copylen); + buf += copylen; + len -= copylen; + ch->tail->buflen += copylen; + } + while (len > 0) { + int grainlen = min(len, BUFFER_GRANULE); + struct bufchain_granule *newbuf; + newbuf = smalloc(sizeof(struct bufchain_granule)); + newbuf->bufpos = 0; + newbuf->buflen = grainlen; + memcpy(newbuf->buf, buf, grainlen); + buf += grainlen; + len -= grainlen; + if (ch->tail) + ch->tail->next = newbuf; + else + ch->head = ch->tail = newbuf; + newbuf->next = NULL; + ch->tail = newbuf; + } +} + +void bufchain_consume(bufchain *ch, int len) +{ + assert(ch->buffersize >= len); + assert(ch->head != NULL && ch->head->bufpos + len <= ch->head->buflen); + ch->head->bufpos += len; + ch->buffersize -= len; + if (ch->head->bufpos >= ch->head->buflen) { + struct bufchain_granule *tmp = ch->head; + ch->head = tmp->next; + sfree(tmp); + if (!ch->head) + ch->tail = NULL; + } +} + +void bufchain_prefix(bufchain *ch, void **data, int *len) +{ + *len = ch->head->buflen - ch->head->bufpos; + *data = ch->head->buf + ch->head->bufpos; +} + +/* ---------------------------------------------------------------------- * My own versions of malloc, realloc and free. Because I want * malloc and realloc to bomb out and exit the program if they run * out of memory, realloc to reliably call malloc if passed a NULL @@ -315,6 +457,10 @@ void safefree(void *ptr) #endif } +/* ---------------------------------------------------------------------- + * Debugging routines. + */ + #ifdef DEBUG static FILE *debug_fp = NULL; static int debug_got_console = 0;