X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/5471d09ad63fc6216fb9c2a3b52ca9c93821a054..68a49acbf3f96fbbbc385620655dcb577e62c328:/misc.c diff --git a/misc.c b/misc.c index 4af00d62..2d0a4634 100644 --- a/misc.c +++ b/misc.c @@ -1,10 +1,85 @@ -#include #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; +} + +/* ---------------------------------------------------------------------- + * Base64 encoding routine. This is required in public-key writing + * but also in HTTP proxy handling, so it's centralised here. + */ + +void base64_encode_atom(unsigned char *data, int n, char *out) +{ + static const char base64_chars[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + unsigned word; + + word = data[0] << 16; + if (n > 1) + word |= data[1] << 8; + if (n > 2) + word |= data[2]; + out[0] = base64_chars[(word >> 18) & 0x3F]; + out[1] = base64_chars[(word >> 12) & 0x3F]; + if (n > 1) + out[2] = base64_chars[(word >> 6) & 0x3F]; + else + out[2] = '='; + if (n > 2) + out[3] = base64_chars[word & 0x3F]; + else + out[3] = '='; +} + +/* ---------------------------------------------------------------------- * Generic routines to deal with send buffers: a linked list of * smallish blocks, with the operations * @@ -13,6 +88,7 @@ * - return a (pointer,length) pair giving some initial data in * the list, suitable for passing to a send or write system * call + * - retrieve a larger amount of initial data from the list * - return the current size of the buffer chain in bytes */ @@ -80,16 +156,23 @@ void bufchain_add(bufchain *ch, void *data, int len) void bufchain_consume(bufchain *ch, int len) { + struct bufchain_granule *tmp; + 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; + while (len > 0) { + int remlen = len; + assert(ch->head != NULL); + if (remlen >= ch->head->buflen - ch->head->bufpos) { + remlen = ch->head->buflen - ch->head->bufpos; + tmp = ch->head; + ch->head = tmp->next; + sfree(tmp); + if (!ch->head) + ch->tail = NULL; + } else + ch->head->bufpos += remlen; + ch->buffersize -= remlen; + len -= remlen; } } @@ -99,7 +182,29 @@ void bufchain_prefix(bufchain *ch, void **data, int *len) *data = ch->head->buf + ch->head->bufpos; } -/* +void bufchain_fetch(bufchain *ch, void *data, int len) +{ + struct bufchain_granule *tmp; + char *data_c = (char *)data; + + tmp = ch->head; + + assert(ch->buffersize >= len); + while (len > 0) { + int remlen = len; + + assert(tmp != NULL); + if (remlen >= tmp->buflen - tmp->bufpos) + remlen = tmp->buflen - tmp->bufpos; + memcpy(data_c, tmp->buf + tmp->bufpos, remlen); + + tmp = tmp->next; + len -= remlen; + data_c += remlen; + } +} + +/* ---------------------------------------------------------------------- * 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 @@ -248,7 +353,7 @@ static void *minefield_alloc(int size) /* * Update the admin region. */ - for (i = start + 2; i < start + npages - 1; i++) + for (i = start + 2; i < start + npages + 1; i++) minefield_admin[i] = 0xFFFE; /* used but no region starts here */ minefield_admin[start + 1] = region_start % PAGESIZE; @@ -333,8 +438,13 @@ static void *minefield_c_realloc(void *p, size_t size) #ifdef MALLOC_LOG static FILE *fp = NULL; +static char *mlog_file = NULL; +static int mlog_line = 0; + void mlog(char *file, int line) { + mlog_file = file; + mlog_line = line; if (!fp) { fp = fopen("putty_mem.log", "w"); setvbuf(fp, NULL, _IONBF, BUFSIZ); @@ -353,9 +463,16 @@ void *safemalloc(size_t size) p = malloc(size); #endif if (!p) { - MessageBox(NULL, "Out of memory!", "PuTTY Fatal Error", - MB_SYSTEMMODAL | MB_ICONERROR | MB_OK); - exit(1); + char str[200]; +#ifdef MALLOC_LOG + sprintf(str, "Out of memory! (%s:%d, size=%d)", + mlog_file, mlog_line, size); + fprintf(fp, "*** %s\n", str); + fclose(fp); +#else + strcpy(str, "Out of memory!"); +#endif + modalfatalbox(str); } #ifdef MALLOC_LOG if (fp) @@ -381,9 +498,16 @@ void *saferealloc(void *ptr, size_t size) #endif } if (!p) { - MessageBox(NULL, "Out of memory!", "PuTTY Fatal Error", - MB_SYSTEMMODAL | MB_ICONERROR | MB_OK); - exit(1); + char str[200]; +#ifdef MALLOC_LOG + sprintf(str, "Out of memory! (%s:%d, size=%d)", + mlog_file, mlog_line, size); + fprintf(fp, "*** %s\n", str); + fclose(fp); +#else + strcpy(str, "Out of memory!"); +#endif + modalfatalbox(str); } #ifdef MALLOC_LOG if (fp) @@ -411,6 +535,10 @@ void safefree(void *ptr) #endif } +/* ---------------------------------------------------------------------- + * Debugging routines. + */ + #ifdef DEBUG static FILE *debug_fp = NULL; static int debug_got_console = 0;