2004-04-27 16:31:57 +04:00
|
|
|
/*
|
|
|
|
* Platform-independent routines shared between all PuTTY programs.
|
|
|
|
*/
|
|
|
|
|
1999-01-08 16:02:13 +03:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2002-10-09 22:09:42 +04:00
|
|
|
#include <stdarg.h>
|
2005-02-20 13:30:05 +03:00
|
|
|
#include <limits.h>
|
2002-11-07 22:49:03 +03:00
|
|
|
#include <ctype.h>
|
2001-08-25 21:09:23 +04:00
|
|
|
#include <assert.h>
|
1999-01-08 16:02:13 +03:00
|
|
|
#include "putty.h"
|
|
|
|
|
2004-12-24 16:39:32 +03:00
|
|
|
/*
|
|
|
|
* Parse a string block size specification. This is approximately a
|
|
|
|
* subset of the block size specs supported by GNU fileutils:
|
|
|
|
* "nk" = n kilobytes
|
|
|
|
* "nM" = n megabytes
|
|
|
|
* "nG" = n gigabytes
|
|
|
|
* All numbers are decimal, and suffixes refer to powers of two.
|
|
|
|
* Case-insensitive.
|
|
|
|
*/
|
|
|
|
unsigned long parse_blocksize(const char *bs)
|
|
|
|
{
|
|
|
|
char *suf;
|
|
|
|
unsigned long r = strtoul(bs, &suf, 10);
|
|
|
|
if (*suf != '\0') {
|
2005-03-21 16:46:16 +03:00
|
|
|
while (*suf && isspace((unsigned char)*suf)) suf++;
|
2004-12-24 16:39:32 +03:00
|
|
|
switch (*suf) {
|
|
|
|
case 'k': case 'K':
|
|
|
|
r *= 1024ul;
|
|
|
|
break;
|
|
|
|
case 'm': case 'M':
|
|
|
|
r *= 1024ul * 1024ul;
|
|
|
|
break;
|
|
|
|
case 'g': case 'G':
|
|
|
|
r *= 1024ul * 1024ul * 1024ul;
|
|
|
|
break;
|
|
|
|
case '\0':
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2005-04-19 22:58:29 +04:00
|
|
|
/*
|
|
|
|
* Parse a ^C style character specification.
|
|
|
|
* Returns NULL in `next' if we didn't recognise it as a control character,
|
|
|
|
* in which case `c' should be ignored.
|
|
|
|
* The precise current parsing is an oddity inherited from the terminal
|
2005-04-19 23:18:14 +04:00
|
|
|
* answerback-string parsing code. All sequences start with ^; all except
|
|
|
|
* ^<123> are two characters. The ones that are worth keeping are probably:
|
2005-04-19 22:58:29 +04:00
|
|
|
* ^? 127
|
|
|
|
* ^@A-Z[\]^_ 0-31
|
|
|
|
* a-z 1-26
|
2005-04-19 23:18:14 +04:00
|
|
|
* <num> specified by number (decimal, 0octal, 0xHEX)
|
2005-04-19 22:58:29 +04:00
|
|
|
* ~ ^ escape
|
|
|
|
*/
|
|
|
|
char ctrlparse(char *s, char **next)
|
|
|
|
{
|
|
|
|
char c = 0;
|
|
|
|
if (*s != '^') {
|
|
|
|
*next = NULL;
|
|
|
|
} else {
|
|
|
|
s++;
|
|
|
|
if (*s == '\0') {
|
|
|
|
*next = NULL;
|
2005-04-19 23:18:14 +04:00
|
|
|
} else if (*s == '<') {
|
|
|
|
s++;
|
|
|
|
c = (char)strtol(s, next, 0);
|
|
|
|
if ((*next == s) || (**next != '>')) {
|
|
|
|
c = 0;
|
|
|
|
*next = NULL;
|
|
|
|
} else
|
|
|
|
(*next)++;
|
2005-04-19 22:58:29 +04:00
|
|
|
} else if (*s >= 'a' && *s <= 'z') {
|
|
|
|
c = (*s - ('a' - 1));
|
2005-04-19 23:18:14 +04:00
|
|
|
*next = s+1;
|
2005-04-19 22:58:29 +04:00
|
|
|
} else if ((*s >= '@' && *s <= '_') || *s == '?' || (*s & 0x80)) {
|
|
|
|
c = ('@' ^ *s);
|
2005-04-19 23:18:14 +04:00
|
|
|
*next = s+1;
|
2005-04-19 22:58:29 +04:00
|
|
|
} else if (*s == '~') {
|
|
|
|
c = '^';
|
2005-04-19 23:18:14 +04:00
|
|
|
*next = s+1;
|
2005-04-19 22:58:29 +04:00
|
|
|
}
|
|
|
|
}
|
2005-04-19 23:18:14 +04:00
|
|
|
return c;
|
2005-04-19 22:58:29 +04:00
|
|
|
}
|
|
|
|
|
2005-10-30 23:24:09 +03:00
|
|
|
prompts_t *new_prompts(void *frontend)
|
|
|
|
{
|
|
|
|
prompts_t *p = snew(prompts_t);
|
|
|
|
p->prompts = NULL;
|
|
|
|
p->n_prompts = 0;
|
|
|
|
p->frontend = frontend;
|
|
|
|
p->data = NULL;
|
|
|
|
p->to_server = TRUE; /* to be on the safe side */
|
|
|
|
p->name = p->instruction = NULL;
|
|
|
|
p->name_reqd = p->instr_reqd = FALSE;
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
void add_prompt(prompts_t *p, char *promptstr, int echo, size_t len)
|
|
|
|
{
|
|
|
|
prompt_t *pr = snew(prompt_t);
|
2006-12-31 02:00:14 +03:00
|
|
|
char *result = snewn(len, char);
|
2005-10-30 23:24:09 +03:00
|
|
|
pr->prompt = promptstr;
|
|
|
|
pr->echo = echo;
|
|
|
|
pr->result = result;
|
|
|
|
pr->result_len = len;
|
|
|
|
p->n_prompts++;
|
|
|
|
p->prompts = sresize(p->prompts, p->n_prompts, prompt_t *);
|
|
|
|
p->prompts[p->n_prompts-1] = pr;
|
|
|
|
}
|
|
|
|
void free_prompts(prompts_t *p)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
for (i=0; i < p->n_prompts; i++) {
|
|
|
|
prompt_t *pr = p->prompts[i];
|
|
|
|
memset(pr->result, 0, pr->result_len); /* burn the evidence */
|
|
|
|
sfree(pr->result);
|
|
|
|
sfree(pr->prompt);
|
|
|
|
sfree(pr);
|
|
|
|
}
|
|
|
|
sfree(p->prompts);
|
|
|
|
sfree(p->name);
|
|
|
|
sfree(p->instruction);
|
|
|
|
sfree(p);
|
|
|
|
}
|
|
|
|
|
2001-08-26 19:31:29 +04:00
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
* String handling routines.
|
|
|
|
*/
|
|
|
|
|
2002-11-07 22:49:03 +03:00
|
|
|
char *dupstr(const char *s)
|
2001-08-26 19:31:29 +04:00
|
|
|
{
|
2003-08-30 02:14:04 +04:00
|
|
|
char *p = NULL;
|
|
|
|
if (s) {
|
|
|
|
int len = strlen(s);
|
|
|
|
p = snewn(len + 1, char);
|
|
|
|
strcpy(p, s);
|
|
|
|
}
|
2001-08-26 19:31:29 +04:00
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Allocate the concatenation of N strings. Terminate arg list with NULL. */
|
2002-11-07 22:49:03 +03:00
|
|
|
char *dupcat(const char *s1, ...)
|
2001-08-26 19:31:29 +04:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
|
2003-03-29 19:14:26 +03:00
|
|
|
p = snewn(len + 1, char);
|
2001-08-26 19:31:29 +04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2002-11-07 22:49:03 +03:00
|
|
|
/*
|
|
|
|
* Do an sprintf(), but into a custom-allocated buffer.
|
|
|
|
*
|
2004-08-16 18:43:29 +04:00
|
|
|
* Currently I'm doing this via vsnprintf. This has worked so far,
|
2006-12-29 19:38:52 +03:00
|
|
|
* but it's not good, because vsnprintf is not available on all
|
|
|
|
* platforms. There's an ifdef to use `_vsnprintf', which seems
|
|
|
|
* to be the local name for it on Windows. Other platforms may
|
|
|
|
* lack it completely, in which case it'll be time to rewrite
|
|
|
|
* this function in a totally different way.
|
2004-08-16 18:43:29 +04:00
|
|
|
*
|
|
|
|
* The only `properly' portable solution I can think of is to
|
|
|
|
* implement my own format string scanner, which figures out an
|
|
|
|
* upper bound for the length of each formatting directive,
|
|
|
|
* allocates the buffer as it goes along, and calls sprintf() to
|
|
|
|
* actually process each directive. If I ever need to actually do
|
|
|
|
* this, some caveats:
|
|
|
|
*
|
|
|
|
* - It's very hard to find a reliable upper bound for
|
|
|
|
* floating-point values. %f, in particular, when supplied with
|
|
|
|
* a number near to the upper or lower limit of representable
|
|
|
|
* numbers, could easily take several hundred characters. It's
|
|
|
|
* probably feasible to predict this statically using the
|
|
|
|
* constants in <float.h>, or even to predict it dynamically by
|
|
|
|
* looking at the exponent of the specific float provided, but
|
|
|
|
* it won't be fun.
|
|
|
|
*
|
|
|
|
* - Don't forget to _check_, after calling sprintf, that it's
|
|
|
|
* used at most the amount of space we had available.
|
|
|
|
*
|
|
|
|
* - Fault any formatting directive we don't fully understand. The
|
|
|
|
* aim here is to _guarantee_ that we never overflow the buffer,
|
|
|
|
* because this is a security-critical function. If we see a
|
|
|
|
* directive we don't know about, we should panic and die rather
|
|
|
|
* than run any risk.
|
2002-11-07 22:49:03 +03:00
|
|
|
*/
|
|
|
|
char *dupprintf(const char *fmt, ...)
|
|
|
|
{
|
|
|
|
char *ret;
|
|
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
|
|
ret = dupvprintf(fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
char *dupvprintf(const char *fmt, va_list ap)
|
|
|
|
{
|
|
|
|
char *buf;
|
|
|
|
int len, size;
|
|
|
|
|
2003-03-29 19:14:26 +03:00
|
|
|
buf = snewn(512, char);
|
2002-11-07 22:49:03 +03:00
|
|
|
size = 512;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
#ifdef _WINDOWS
|
|
|
|
#define vsnprintf _vsnprintf
|
|
|
|
#endif
|
2006-12-29 19:38:52 +03:00
|
|
|
#ifdef va_copy
|
|
|
|
/* Use the `va_copy' macro mandated by C99, if present.
|
|
|
|
* XXX some environments may have this as __va_copy() */
|
|
|
|
va_list aq;
|
|
|
|
va_copy(aq, ap);
|
|
|
|
len = vsnprintf(buf, size, fmt, aq);
|
|
|
|
va_end(aq);
|
|
|
|
#else
|
|
|
|
/* Ugh. No va_copy macro, so do something nasty.
|
|
|
|
* Technically, you can't reuse a va_list like this: it is left
|
|
|
|
* unspecified whether advancing a va_list pointer modifies its
|
|
|
|
* value or something it points to, so on some platforms calling
|
|
|
|
* vsnprintf twice on the same va_list might fail hideously
|
|
|
|
* (indeed, it has been observed to).
|
|
|
|
* XXX the autoconf manual suggests that using memcpy() will give
|
|
|
|
* "maximum portability". */
|
2002-11-07 22:49:03 +03:00
|
|
|
len = vsnprintf(buf, size, fmt, ap);
|
2006-12-29 19:38:52 +03:00
|
|
|
#endif
|
2002-11-07 22:49:03 +03:00
|
|
|
if (len >= 0 && len < size) {
|
|
|
|
/* This is the C99-specified criterion for snprintf to have
|
|
|
|
* been completely successful. */
|
|
|
|
return buf;
|
|
|
|
} else if (len > 0) {
|
|
|
|
/* This is the C99 error condition: the returned length is
|
|
|
|
* the required buffer size not counting the NUL. */
|
|
|
|
size = len + 1;
|
|
|
|
} else {
|
|
|
|
/* This is the pre-C99 glibc error condition: <0 means the
|
|
|
|
* buffer wasn't big enough, so we enlarge it a bit and hope. */
|
|
|
|
size += 512;
|
|
|
|
}
|
2003-03-29 19:14:26 +03:00
|
|
|
buf = sresize(buf, size, char);
|
2002-11-07 22:49:03 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-11-27 16:20:21 +03:00
|
|
|
/*
|
|
|
|
* Read an entire line of text from a file. Return a buffer
|
|
|
|
* malloced to be as big as necessary (caller must free).
|
|
|
|
*/
|
|
|
|
char *fgetline(FILE *fp)
|
|
|
|
{
|
|
|
|
char *ret = snewn(512, char);
|
|
|
|
int size = 512, len = 0;
|
|
|
|
while (fgets(ret + len, size - len, fp)) {
|
|
|
|
len += strlen(ret + len);
|
|
|
|
if (ret[len-1] == '\n')
|
|
|
|
break; /* got a newline, we're done */
|
|
|
|
size = len + 512;
|
|
|
|
ret = sresize(ret, size, char);
|
|
|
|
}
|
|
|
|
if (len == 0) { /* first fgets returned NULL */
|
|
|
|
sfree(ret);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
ret[len] = '\0';
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2002-09-21 18:03:05 +04:00
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
* 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] = '=';
|
|
|
|
}
|
|
|
|
|
2001-08-26 19:31:29 +04:00
|
|
|
/* ----------------------------------------------------------------------
|
2001-08-25 21:09:23 +04:00
|
|
|
* 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
|
2002-09-21 20:52:21 +04:00
|
|
|
* - retrieve a larger amount of initial data from the list
|
2001-08-25 21:09:23 +04:00
|
|
|
* - 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;
|
|
|
|
}
|
|
|
|
|
2003-01-10 21:33:35 +03:00
|
|
|
void bufchain_add(bufchain *ch, const void *data, int len)
|
2001-08-25 21:09:23 +04:00
|
|
|
{
|
2003-01-10 21:33:35 +03:00
|
|
|
const char *buf = (const char *)data;
|
2001-08-25 21:09:23 +04:00
|
|
|
|
2003-10-12 17:16:39 +04:00
|
|
|
if (len == 0) return;
|
|
|
|
|
2001-08-25 21:09:23 +04:00
|
|
|
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;
|
2003-03-29 19:14:26 +03:00
|
|
|
newbuf = snew(struct bufchain_granule);
|
2001-08-25 21:09:23 +04:00
|
|
|
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)
|
|
|
|
{
|
2002-09-21 20:52:21 +04:00
|
|
|
struct bufchain_granule *tmp;
|
|
|
|
|
2001-08-25 21:09:23 +04:00
|
|
|
assert(ch->buffersize >= len);
|
2002-09-21 20:52:21 +04:00
|
|
|
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;
|
2001-08-25 21:09:23 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void bufchain_prefix(bufchain *ch, void **data, int *len)
|
|
|
|
{
|
|
|
|
*len = ch->head->buflen - ch->head->bufpos;
|
|
|
|
*data = ch->head->buf + ch->head->bufpos;
|
|
|
|
}
|
|
|
|
|
2002-09-21 20:52:21 +04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-08-26 19:31:29 +04:00
|
|
|
/* ----------------------------------------------------------------------
|
2000-12-12 13:57:34 +03:00
|
|
|
* 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
|
|
|
|
* pointer, and free to reliably do nothing if passed a NULL
|
|
|
|
* pointer. We can also put trace printouts in, if we need to; and
|
|
|
|
* we can also replace the allocator with an ElectricFence-like
|
|
|
|
* one.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef MINEFIELD
|
2003-03-06 16:24:02 +03:00
|
|
|
void *minefield_c_malloc(size_t size);
|
|
|
|
void minefield_c_free(void *p);
|
|
|
|
void *minefield_c_realloc(void *p, size_t size);
|
|
|
|
#endif
|
1999-01-08 16:02:13 +03:00
|
|
|
|
|
|
|
#ifdef MALLOC_LOG
|
|
|
|
static FILE *fp = NULL;
|
|
|
|
|
2001-12-15 17:09:51 +03:00
|
|
|
static char *mlog_file = NULL;
|
|
|
|
static int mlog_line = 0;
|
|
|
|
|
2001-05-06 18:35:20 +04:00
|
|
|
void mlog(char *file, int line)
|
|
|
|
{
|
2001-12-15 17:09:51 +03:00
|
|
|
mlog_file = file;
|
|
|
|
mlog_line = line;
|
1999-01-15 14:27:36 +03:00
|
|
|
if (!fp) {
|
1999-01-08 16:02:13 +03:00
|
|
|
fp = fopen("putty_mem.log", "w");
|
1999-01-15 14:27:36 +03:00
|
|
|
setvbuf(fp, NULL, _IONBF, BUFSIZ);
|
|
|
|
}
|
1999-01-08 16:02:13 +03:00
|
|
|
if (fp)
|
2001-05-06 18:35:20 +04:00
|
|
|
fprintf(fp, "%s:%d: ", file, line);
|
1999-01-08 16:02:13 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2005-02-20 13:30:05 +03:00
|
|
|
void *safemalloc(size_t n, size_t size)
|
2001-05-06 18:35:20 +04:00
|
|
|
{
|
2000-12-12 13:57:34 +03:00
|
|
|
void *p;
|
2005-02-20 13:30:05 +03:00
|
|
|
|
|
|
|
if (n > INT_MAX / size) {
|
|
|
|
p = NULL;
|
|
|
|
} else {
|
|
|
|
size *= n;
|
2005-09-14 00:17:10 +04:00
|
|
|
if (size == 0) size = 1;
|
2000-12-12 13:57:34 +03:00
|
|
|
#ifdef MINEFIELD
|
2005-02-20 13:30:05 +03:00
|
|
|
p = minefield_c_malloc(size);
|
2000-12-12 13:57:34 +03:00
|
|
|
#else
|
2005-02-20 13:30:05 +03:00
|
|
|
p = malloc(size);
|
2000-12-12 13:57:34 +03:00
|
|
|
#endif
|
2005-02-20 13:30:05 +03:00
|
|
|
}
|
|
|
|
|
1999-01-08 16:02:13 +03:00
|
|
|
if (!p) {
|
2001-12-15 17:09:51 +03:00
|
|
|
char str[200];
|
|
|
|
#ifdef MALLOC_LOG
|
|
|
|
sprintf(str, "Out of memory! (%s:%d, size=%d)",
|
|
|
|
mlog_file, mlog_line, size);
|
2002-02-28 01:20:03 +03:00
|
|
|
fprintf(fp, "*** %s\n", str);
|
|
|
|
fclose(fp);
|
2001-12-15 17:09:51 +03:00
|
|
|
#else
|
|
|
|
strcpy(str, "Out of memory!");
|
|
|
|
#endif
|
2002-10-09 22:09:42 +04:00
|
|
|
modalfatalbox(str);
|
1999-01-08 16:02:13 +03:00
|
|
|
}
|
|
|
|
#ifdef MALLOC_LOG
|
|
|
|
if (fp)
|
|
|
|
fprintf(fp, "malloc(%d) returns %p\n", size, p);
|
|
|
|
#endif
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2005-02-20 13:30:05 +03:00
|
|
|
void *saferealloc(void *ptr, size_t n, size_t size)
|
2001-05-06 18:35:20 +04:00
|
|
|
{
|
1999-01-08 16:02:13 +03:00
|
|
|
void *p;
|
2005-02-20 13:30:05 +03:00
|
|
|
|
|
|
|
if (n > INT_MAX / size) {
|
|
|
|
p = NULL;
|
|
|
|
} else {
|
|
|
|
size *= n;
|
|
|
|
if (!ptr) {
|
2000-12-12 13:57:34 +03:00
|
|
|
#ifdef MINEFIELD
|
2005-02-20 13:30:05 +03:00
|
|
|
p = minefield_c_malloc(size);
|
2000-12-12 13:57:34 +03:00
|
|
|
#else
|
2005-02-20 13:30:05 +03:00
|
|
|
p = malloc(size);
|
2000-12-12 13:57:34 +03:00
|
|
|
#endif
|
2005-02-20 13:30:05 +03:00
|
|
|
} else {
|
2000-12-12 13:57:34 +03:00
|
|
|
#ifdef MINEFIELD
|
2005-02-20 13:30:05 +03:00
|
|
|
p = minefield_c_realloc(ptr, size);
|
2000-12-12 13:57:34 +03:00
|
|
|
#else
|
2005-02-20 13:30:05 +03:00
|
|
|
p = realloc(ptr, size);
|
2000-12-12 13:57:34 +03:00
|
|
|
#endif
|
2005-02-20 13:30:05 +03:00
|
|
|
}
|
2000-12-12 13:57:34 +03:00
|
|
|
}
|
2005-02-20 13:30:05 +03:00
|
|
|
|
1999-01-08 16:02:13 +03:00
|
|
|
if (!p) {
|
2001-12-15 17:09:51 +03:00
|
|
|
char str[200];
|
|
|
|
#ifdef MALLOC_LOG
|
|
|
|
sprintf(str, "Out of memory! (%s:%d, size=%d)",
|
|
|
|
mlog_file, mlog_line, size);
|
2002-02-28 01:20:03 +03:00
|
|
|
fprintf(fp, "*** %s\n", str);
|
|
|
|
fclose(fp);
|
2001-12-15 17:09:51 +03:00
|
|
|
#else
|
|
|
|
strcpy(str, "Out of memory!");
|
|
|
|
#endif
|
2002-10-09 22:09:42 +04:00
|
|
|
modalfatalbox(str);
|
1999-01-08 16:02:13 +03:00
|
|
|
}
|
|
|
|
#ifdef MALLOC_LOG
|
|
|
|
if (fp)
|
|
|
|
fprintf(fp, "realloc(%p,%d) returns %p\n", ptr, size, p);
|
|
|
|
#endif
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2001-05-06 18:35:20 +04:00
|
|
|
void safefree(void *ptr)
|
|
|
|
{
|
1999-01-08 16:02:13 +03:00
|
|
|
if (ptr) {
|
|
|
|
#ifdef MALLOC_LOG
|
|
|
|
if (fp)
|
|
|
|
fprintf(fp, "free(%p)\n", ptr);
|
|
|
|
#endif
|
2000-12-12 13:57:34 +03:00
|
|
|
#ifdef MINEFIELD
|
2001-05-06 18:35:20 +04:00
|
|
|
minefield_c_free(ptr);
|
2000-12-12 13:57:34 +03:00
|
|
|
#else
|
2001-05-06 18:35:20 +04:00
|
|
|
free(ptr);
|
2000-12-12 13:57:34 +03:00
|
|
|
#endif
|
1999-01-08 16:02:13 +03:00
|
|
|
}
|
|
|
|
#ifdef MALLOC_LOG
|
|
|
|
else if (fp)
|
|
|
|
fprintf(fp, "freeing null pointer - no action taken\n");
|
|
|
|
#endif
|
|
|
|
}
|
2000-11-01 22:54:46 +03:00
|
|
|
|
2001-08-26 19:31:29 +04:00
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
* Debugging routines.
|
|
|
|
*/
|
|
|
|
|
2000-11-01 22:54:46 +03:00
|
|
|
#ifdef DEBUG
|
2003-03-06 16:24:02 +03:00
|
|
|
extern void dputs(char *); /* defined in per-platform *misc.c */
|
2001-04-28 13:24:19 +04:00
|
|
|
|
2003-03-06 16:24:02 +03:00
|
|
|
void debug_printf(char *fmt, ...)
|
2001-05-06 18:35:20 +04:00
|
|
|
{
|
2002-11-07 22:49:03 +03:00
|
|
|
char *buf;
|
2001-04-28 13:24:19 +04:00
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
2002-11-07 22:49:03 +03:00
|
|
|
buf = dupvprintf(fmt, ap);
|
2001-05-06 18:35:20 +04:00
|
|
|
dputs(buf);
|
2002-11-07 22:49:03 +03:00
|
|
|
sfree(buf);
|
2000-11-01 22:54:46 +03:00
|
|
|
va_end(ap);
|
|
|
|
}
|
2001-04-28 13:24:19 +04:00
|
|
|
|
|
|
|
|
2001-05-06 18:35:20 +04:00
|
|
|
void debug_memdump(void *buf, int len, int L)
|
|
|
|
{
|
2001-04-28 13:24:19 +04:00
|
|
|
int i;
|
|
|
|
unsigned char *p = buf;
|
2001-04-28 21:35:18 +04:00
|
|
|
char foo[17];
|
2001-04-28 13:24:19 +04:00
|
|
|
if (L) {
|
|
|
|
int delta;
|
2003-03-06 16:24:02 +03:00
|
|
|
debug_printf("\t%d (0x%x) bytes:\n", len, len);
|
2009-01-05 01:24:08 +03:00
|
|
|
delta = 15 & (unsigned long int) p;
|
2001-04-28 13:24:19 +04:00
|
|
|
p -= delta;
|
|
|
|
len += delta;
|
|
|
|
}
|
|
|
|
for (; 0 < len; p += 16, len -= 16) {
|
2001-05-06 18:35:20 +04:00
|
|
|
dputs(" ");
|
|
|
|
if (L)
|
2003-03-06 16:24:02 +03:00
|
|
|
debug_printf("%p: ", p);
|
2001-05-06 18:35:20 +04:00
|
|
|
strcpy(foo, "................"); /* sixteen dots */
|
2001-04-28 13:24:19 +04:00
|
|
|
for (i = 0; i < 16 && i < len; ++i) {
|
|
|
|
if (&p[i] < (unsigned char *) buf) {
|
2001-05-06 18:35:20 +04:00
|
|
|
dputs(" "); /* 3 spaces */
|
2001-04-28 21:35:18 +04:00
|
|
|
foo[i] = ' ';
|
2001-04-28 13:24:19 +04:00
|
|
|
} else {
|
2003-03-06 16:24:02 +03:00
|
|
|
debug_printf("%c%02.2x",
|
2001-05-06 18:35:20 +04:00
|
|
|
&p[i] != (unsigned char *) buf
|
|
|
|
&& i % 4 ? '.' : ' ', p[i]
|
|
|
|
);
|
2001-04-28 21:35:18 +04:00
|
|
|
if (p[i] >= ' ' && p[i] <= '~')
|
2001-05-06 18:35:20 +04:00
|
|
|
foo[i] = (char) p[i];
|
2001-04-28 13:24:19 +04:00
|
|
|
}
|
|
|
|
}
|
2001-04-28 21:35:18 +04:00
|
|
|
foo[i] = '\0';
|
2003-03-06 16:24:02 +03:00
|
|
|
debug_printf("%*s%s\n", (16 - i) * 3 + 2, "", foo);
|
2001-04-28 13:24:19 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-05-06 18:35:20 +04:00
|
|
|
#endif /* def DEBUG */
|
2006-08-28 14:35:12 +04:00
|
|
|
|
|
|
|
/*
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 22:52:21 +04:00
|
|
|
* Determine whether or not a Conf represents a session which can
|
|
|
|
* sensibly be launched right now.
|
2006-08-28 14:35:12 +04:00
|
|
|
*/
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 22:52:21 +04:00
|
|
|
int conf_launchable(Conf *conf)
|
2006-08-28 14:35:12 +04:00
|
|
|
{
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 22:52:21 +04:00
|
|
|
if (conf_get_int(conf, CONF_protocol) == PROT_SERIAL)
|
|
|
|
return conf_get_str(conf, CONF_serline)[0] != 0;
|
2006-08-28 14:35:12 +04:00
|
|
|
else
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 22:52:21 +04:00
|
|
|
return conf_get_str(conf, CONF_host)[0] != 0;
|
2006-08-28 14:35:12 +04:00
|
|
|
}
|
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 22:52:21 +04:00
|
|
|
char const *conf_dest(Conf *conf)
|
2006-08-28 14:35:12 +04:00
|
|
|
{
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 22:52:21 +04:00
|
|
|
if (conf_get_int(conf, CONF_protocol) == PROT_SERIAL)
|
|
|
|
return conf_get_str(conf, CONF_serline);
|
2006-08-28 14:35:12 +04:00
|
|
|
else
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 22:52:21 +04:00
|
|
|
return conf_get_str(conf, CONF_host);
|
2006-08-28 14:35:12 +04:00
|
|
|
}
|